1// Copyright 2015 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <stdlib.h>
6#include <string.h>
7
8#include "src/wasm/encoder.h"
9#include "src/wasm/wasm-macro-gen.h"
10#include "src/wasm/wasm-module.h"
11#include "src/wasm/wasm-opcodes.h"
12
13#include "test/cctest/cctest.h"
14
15using namespace v8::base;
16using namespace v8::internal;
17using namespace v8::internal::compiler;
18using namespace v8::internal::wasm;
19
20
21namespace {
22void TestModule(WasmModuleIndex* module, int32_t expected_result) {
23  Isolate* isolate = CcTest::InitIsolateOnce();
24  int32_t result =
25      CompileAndRunWasmModule(isolate, module->Begin(), module->End());
26  CHECK_EQ(expected_result, result);
27}
28}  // namespace
29
30
31// A raw test that skips the WasmModuleBuilder.
32TEST(Run_WasmModule_CallAdd_rev) {
33  static const byte data[] = {
34      // sig#0 ------------------------------------------
35      kDeclSignatures, 2, 0, kLocalI32,    // void -> int
36      2, kLocalI32, kLocalI32, kLocalI32,  // int,int -> int
37      // func#0 (main) ----------------------------------
38      kDeclFunctions, 2, kDeclFunctionExport, 0, 0,  // sig index
39      6, 0,                                          // body size
40      kExprCallFunction, 1,                          // --
41      kExprI8Const, 77,                              // --
42      kExprI8Const, 22,                              // --
43      // func#1 -----------------------------------------
44      0,                 // no name, not exported
45      1, 0,              // sig index
46      5, 0,              // body size
47      kExprI32Add,       // --
48      kExprGetLocal, 0,  // --
49      kExprGetLocal, 1,  // --
50  };
51
52  Isolate* isolate = CcTest::InitIsolateOnce();
53  int32_t result =
54      CompileAndRunWasmModule(isolate, data, data + arraysize(data));
55  CHECK_EQ(99, result);
56}
57
58
59TEST(Run_WasmModule_Return114) {
60  static const int32_t kReturnValue = 114;
61  Zone zone;
62  WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
63  uint16_t f_index = builder->AddFunction();
64  WasmFunctionBuilder* f = builder->FunctionAt(f_index);
65  f->ReturnType(kAstI32);
66  f->Exported(1);
67  byte code[] = {WASM_I8(kReturnValue)};
68  f->EmitCode(code, sizeof(code));
69  WasmModuleWriter* writer = builder->Build(&zone);
70  TestModule(writer->WriteTo(&zone), kReturnValue);
71}
72
73
74TEST(Run_WasmModule_CallAdd) {
75  Zone zone;
76  WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
77  uint16_t f1_index = builder->AddFunction();
78  WasmFunctionBuilder* f = builder->FunctionAt(f1_index);
79  f->ReturnType(kAstI32);
80  uint16_t param1 = f->AddParam(kAstI32);
81  uint16_t param2 = f->AddParam(kAstI32);
82  byte code1[] = {WASM_I32_ADD(WASM_GET_LOCAL(param1), WASM_GET_LOCAL(param2))};
83  uint32_t local_indices1[] = {2, 4};
84  f->EmitCode(code1, sizeof(code1), local_indices1, sizeof(local_indices1) / 4);
85  uint16_t f2_index = builder->AddFunction();
86  f = builder->FunctionAt(f2_index);
87  f->ReturnType(kAstI32);
88  f->Exported(1);
89  byte code2[] = {WASM_CALL_FUNCTION(f1_index, WASM_I8(77), WASM_I8(22))};
90  f->EmitCode(code2, sizeof(code2));
91  WasmModuleWriter* writer = builder->Build(&zone);
92  TestModule(writer->WriteTo(&zone), 99);
93}
94
95
96TEST(Run_WasmModule_ReadLoadedDataSegment) {
97  static const byte kDataSegmentDest0 = 12;
98  Zone zone;
99  WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
100  uint16_t f_index = builder->AddFunction();
101  WasmFunctionBuilder* f = builder->FunctionAt(f_index);
102  f->ReturnType(kAstI32);
103  f->Exported(1);
104  byte code[] = {
105      WASM_LOAD_MEM(MachineType::Int32(), WASM_I8(kDataSegmentDest0))};
106  f->EmitCode(code, sizeof(code));
107  byte data[] = {0xaa, 0xbb, 0xcc, 0xdd};
108  builder->AddDataSegment(new (&zone) WasmDataSegmentEncoder(
109      &zone, data, sizeof(data), kDataSegmentDest0));
110  WasmModuleWriter* writer = builder->Build(&zone);
111  TestModule(writer->WriteTo(&zone), 0xddccbbaa);
112}
113
114
115#if defined(__has_feature)
116#if __has_feature(address_sanitizer)
117#define V8_WITH_ASAN 1
118#endif
119#endif
120
121
122#if !defined(V8_WITH_ASAN)
123// TODO(bradnelson): Figure out why this crashes under asan.
124TEST(Run_WasmModule_CheckMemoryIsZero) {
125  static const int kCheckSize = 16 * 1024;
126  Zone zone;
127  WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
128  uint16_t f_index = builder->AddFunction();
129  WasmFunctionBuilder* f = builder->FunctionAt(f_index);
130  f->ReturnType(kAstI32);
131  uint16_t localIndex = f->AddLocal(kAstI32);
132  f->Exported(1);
133  byte code[] = {WASM_BLOCK(
134      2,
135      WASM_WHILE(
136          WASM_I32_LTS(WASM_GET_LOCAL(localIndex), WASM_I32(kCheckSize)),
137          WASM_IF_ELSE(
138              WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(localIndex)),
139              WASM_BRV(2, WASM_I8(-1)), WASM_INC_LOCAL_BY(localIndex, 4))),
140      WASM_I8(11))};
141  uint32_t local_indices[] = {7, 19, 25, 28};
142  f->EmitCode(code, sizeof(code), local_indices, sizeof(local_indices) / 4);
143  WasmModuleWriter* writer = builder->Build(&zone);
144  TestModule(writer->WriteTo(&zone), 11);
145}
146#endif
147
148
149#if !defined(V8_WITH_ASAN)
150// TODO(bradnelson): Figure out why this crashes under asan.
151TEST(Run_WasmModule_CallMain_recursive) {
152  Zone zone;
153  WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
154  uint16_t f_index = builder->AddFunction();
155  WasmFunctionBuilder* f = builder->FunctionAt(f_index);
156  f->ReturnType(kAstI32);
157  uint16_t localIndex = f->AddLocal(kAstI32);
158  f->Exported(1);
159  byte code[] = {WASM_BLOCK(
160      2, WASM_SET_LOCAL(localIndex,
161                        WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO)),
162      WASM_IF_ELSE(WASM_I32_LTS(WASM_GET_LOCAL(localIndex), WASM_I8(5)),
163                   WASM_BLOCK(2, WASM_STORE_MEM(MachineType::Int32(), WASM_ZERO,
164                                                WASM_INC_LOCAL(localIndex)),
165                              WASM_BRV(1, WASM_CALL_FUNCTION0(0))),
166                   WASM_BRV(0, WASM_I8(55))))};
167  uint32_t local_indices[] = {3, 11, 21, 24};
168  f->EmitCode(code, sizeof(code), local_indices, sizeof(local_indices) / 4);
169  WasmModuleWriter* writer = builder->Build(&zone);
170  TestModule(writer->WriteTo(&zone), 55);
171}
172#endif
173
174
175#if !defined(V8_WITH_ASAN)
176// TODO(bradnelson): Figure out why this crashes under asan.
177TEST(Run_WasmModule_Global) {
178  Zone zone;
179  WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
180  uint32_t global1 = builder->AddGlobal(MachineType::Int32(), 0);
181  uint32_t global2 = builder->AddGlobal(MachineType::Int32(), 0);
182  uint16_t f1_index = builder->AddFunction();
183  WasmFunctionBuilder* f = builder->FunctionAt(f1_index);
184  f->ReturnType(kAstI32);
185  byte code1[] = {
186      WASM_I32_ADD(WASM_LOAD_GLOBAL(global1), WASM_LOAD_GLOBAL(global2))};
187  f->EmitCode(code1, sizeof(code1));
188  uint16_t f2_index = builder->AddFunction();
189  f = builder->FunctionAt(f2_index);
190  f->ReturnType(kAstI32);
191  f->Exported(1);
192  byte code2[] = {WASM_STORE_GLOBAL(global1, WASM_I32(56)),
193                  WASM_STORE_GLOBAL(global2, WASM_I32(41)),
194                  WASM_RETURN(WASM_CALL_FUNCTION0(f1_index))};
195  f->EmitCode(code2, sizeof(code2));
196  WasmModuleWriter* writer = builder->Build(&zone);
197  TestModule(writer->WriteTo(&zone), 97);
198}
199#endif
200