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 <stdint.h>
6 #include <stdlib.h>
7 #include <string.h>
8
9 #include "src/base/platform/elapsed-timer.h"
10
11 #include "src/wasm/wasm-macro-gen.h"
12
13 #include "test/cctest/cctest.h"
14 #include "test/cctest/compiler/value-helper.h"
15 #include "test/cctest/wasm/test-signatures.h"
16 #include "test/cctest/wasm/wasm-run-utils.h"
17
18 using namespace v8::base;
19 using namespace v8::internal;
20 using namespace v8::internal::compiler;
21 using namespace v8::internal::wasm;
22
23 // for even shorter tests.
24 #define B2(a, b) kExprBlock, a, b, kExprEnd
25 #define B1(a) kExprBlock, a, kExprEnd
26 #define RET(x) x, kExprReturn, 1
27 #define RET_I8(x) kExprI8Const, x, kExprReturn, 1
28
WASM_EXEC_TEST(Int8Const)29 WASM_EXEC_TEST(Int8Const) {
30 WasmRunner<int32_t> r(execution_mode);
31 const byte kExpectedValue = 121;
32 // return(kExpectedValue)
33 BUILD(r, WASM_I8(kExpectedValue));
34 CHECK_EQ(kExpectedValue, r.Call());
35 }
36
WASM_EXEC_TEST(Int8Const_fallthru1)37 WASM_EXEC_TEST(Int8Const_fallthru1) {
38 WasmRunner<int32_t> r(execution_mode);
39 const byte kExpectedValue = 122;
40 // kExpectedValue
41 BUILD(r, WASM_I8(kExpectedValue));
42 CHECK_EQ(kExpectedValue, r.Call());
43 }
44
WASM_EXEC_TEST(Int8Const_fallthru2)45 WASM_EXEC_TEST(Int8Const_fallthru2) {
46 WasmRunner<int32_t> r(execution_mode);
47 const byte kExpectedValue = 123;
48 // -99 kExpectedValue
49 BUILD(r, WASM_I8(-99), WASM_I8(kExpectedValue));
50 CHECK_EQ(kExpectedValue, r.Call());
51 }
52
WASM_EXEC_TEST(Int8Const_all)53 WASM_EXEC_TEST(Int8Const_all) {
54 for (int value = -128; value <= 127; ++value) {
55 WasmRunner<int32_t> r(execution_mode);
56 // return(value)
57 BUILD(r, WASM_I8(value));
58 int32_t result = r.Call();
59 CHECK_EQ(value, result);
60 }
61 }
62
WASM_EXEC_TEST(Int32Const)63 WASM_EXEC_TEST(Int32Const) {
64 WasmRunner<int32_t> r(execution_mode);
65 const int32_t kExpectedValue = 0x11223344;
66 // return(kExpectedValue)
67 BUILD(r, WASM_I32V_5(kExpectedValue));
68 CHECK_EQ(kExpectedValue, r.Call());
69 }
70
WASM_EXEC_TEST(Int32Const_many)71 WASM_EXEC_TEST(Int32Const_many) {
72 FOR_INT32_INPUTS(i) {
73 WasmRunner<int32_t> r(execution_mode);
74 const int32_t kExpectedValue = *i;
75 // return(kExpectedValue)
76 BUILD(r, WASM_I32V(kExpectedValue));
77 CHECK_EQ(kExpectedValue, r.Call());
78 }
79 }
80
WASM_EXEC_TEST(MemorySize)81 WASM_EXEC_TEST(MemorySize) {
82 TestingModule module(execution_mode);
83 WasmRunner<int32_t> r(&module);
84 module.AddMemory(1024);
85 BUILD(r, kExprMemorySize);
86 CHECK_EQ(1024, r.Call());
87 }
88
WASM_EXEC_TEST(Int32Param0)89 WASM_EXEC_TEST(Int32Param0) {
90 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
91 // return(local[0])
92 BUILD(r, WASM_GET_LOCAL(0));
93 FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
94 }
95
WASM_EXEC_TEST(Int32Param0_fallthru)96 WASM_EXEC_TEST(Int32Param0_fallthru) {
97 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
98 // local[0]
99 BUILD(r, WASM_GET_LOCAL(0));
100 FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
101 }
102
WASM_EXEC_TEST(Int32Param1)103 WASM_EXEC_TEST(Int32Param1) {
104 WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
105 MachineType::Int32());
106 // local[1]
107 BUILD(r, WASM_GET_LOCAL(1));
108 FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(-111, *i)); }
109 }
110
WASM_EXEC_TEST(Int32Add)111 WASM_EXEC_TEST(Int32Add) {
112 WasmRunner<int32_t> r(execution_mode);
113 // 11 + 44
114 BUILD(r, WASM_I32_ADD(WASM_I8(11), WASM_I8(44)));
115 CHECK_EQ(55, r.Call());
116 }
117
WASM_EXEC_TEST(Int32Add_P)118 WASM_EXEC_TEST(Int32Add_P) {
119 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
120 // p0 + 13
121 BUILD(r, WASM_I32_ADD(WASM_I8(13), WASM_GET_LOCAL(0)));
122 FOR_INT32_INPUTS(i) { CHECK_EQ(*i + 13, r.Call(*i)); }
123 }
124
WASM_EXEC_TEST(Int32Add_P_fallthru)125 WASM_EXEC_TEST(Int32Add_P_fallthru) {
126 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
127 // p0 + 13
128 BUILD(r, WASM_I32_ADD(WASM_I8(13), WASM_GET_LOCAL(0)));
129 FOR_INT32_INPUTS(i) { CHECK_EQ(*i + 13, r.Call(*i)); }
130 }
131
WASM_EXEC_TEST(Int32Add_P2)132 WASM_EXEC_TEST(Int32Add_P2) {
133 WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
134 MachineType::Int32());
135 // p0 + p1
136 BUILD(r, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
137 FOR_INT32_INPUTS(i) {
138 FOR_INT32_INPUTS(j) {
139 int32_t expected = static_cast<int32_t>(static_cast<uint32_t>(*i) +
140 static_cast<uint32_t>(*j));
141 CHECK_EQ(expected, r.Call(*i, *j));
142 }
143 }
144 }
145
WASM_EXEC_TEST(Float32Add)146 WASM_EXEC_TEST(Float32Add) {
147 WasmRunner<int32_t> r(execution_mode);
148 // int(11.5f + 44.5f)
149 BUILD(r,
150 WASM_I32_SCONVERT_F32(WASM_F32_ADD(WASM_F32(11.5f), WASM_F32(44.5f))));
151 CHECK_EQ(56, r.Call());
152 }
153
WASM_EXEC_TEST(Float64Add)154 WASM_EXEC_TEST(Float64Add) {
155 WasmRunner<int32_t> r(execution_mode);
156 // return int(13.5d + 43.5d)
157 BUILD(r, WASM_I32_SCONVERT_F64(WASM_F64_ADD(WASM_F64(13.5), WASM_F64(43.5))));
158 CHECK_EQ(57, r.Call());
159 }
160
TestInt32Binop(WasmExecutionMode execution_mode,WasmOpcode opcode,int32_t expected,int32_t a,int32_t b)161 void TestInt32Binop(WasmExecutionMode execution_mode, WasmOpcode opcode,
162 int32_t expected, int32_t a, int32_t b) {
163 {
164 WasmRunner<int32_t> r(execution_mode);
165 // K op K
166 BUILD(r, WASM_BINOP(opcode, WASM_I32V(a), WASM_I32V(b)));
167 CHECK_EQ(expected, r.Call());
168 }
169 {
170 WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
171 MachineType::Int32());
172 // a op b
173 BUILD(r, WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
174 CHECK_EQ(expected, r.Call(a, b));
175 }
176 }
177
WASM_EXEC_TEST(Int32Binops)178 WASM_EXEC_TEST(Int32Binops) {
179 TestInt32Binop(execution_mode, kExprI32Add, 88888888, 33333333, 55555555);
180 TestInt32Binop(execution_mode, kExprI32Sub, -1111111, 7777777, 8888888);
181 TestInt32Binop(execution_mode, kExprI32Mul, 65130756, 88734, 734);
182 TestInt32Binop(execution_mode, kExprI32DivS, -66, -4777344, 72384);
183 TestInt32Binop(execution_mode, kExprI32DivU, 805306368, 0xF0000000, 5);
184 TestInt32Binop(execution_mode, kExprI32RemS, -3, -3003, 1000);
185 TestInt32Binop(execution_mode, kExprI32RemU, 4, 4004, 1000);
186 TestInt32Binop(execution_mode, kExprI32And, 0xEE, 0xFFEE, 0xFF0000FF);
187 TestInt32Binop(execution_mode, kExprI32Ior, 0xF0FF00FF, 0xF0F000EE,
188 0x000F0011);
189 TestInt32Binop(execution_mode, kExprI32Xor, 0xABCDEF01, 0xABCDEFFF, 0xFE);
190 TestInt32Binop(execution_mode, kExprI32Shl, 0xA0000000, 0xA, 28);
191 TestInt32Binop(execution_mode, kExprI32ShrU, 0x07000010, 0x70000100, 4);
192 TestInt32Binop(execution_mode, kExprI32ShrS, 0xFF000000, 0x80000000, 7);
193 TestInt32Binop(execution_mode, kExprI32Ror, 0x01000000, 0x80000000, 7);
194 TestInt32Binop(execution_mode, kExprI32Ror, 0x01000000, 0x80000000, 39);
195 TestInt32Binop(execution_mode, kExprI32Rol, 0x00000040, 0x80000000, 7);
196 TestInt32Binop(execution_mode, kExprI32Rol, 0x00000040, 0x80000000, 39);
197 TestInt32Binop(execution_mode, kExprI32Eq, 1, -99, -99);
198 TestInt32Binop(execution_mode, kExprI32Ne, 0, -97, -97);
199
200 TestInt32Binop(execution_mode, kExprI32LtS, 1, -4, 4);
201 TestInt32Binop(execution_mode, kExprI32LeS, 0, -2, -3);
202 TestInt32Binop(execution_mode, kExprI32LtU, 1, 0, -6);
203 TestInt32Binop(execution_mode, kExprI32LeU, 1, 98978, 0xF0000000);
204
205 TestInt32Binop(execution_mode, kExprI32GtS, 1, 4, -4);
206 TestInt32Binop(execution_mode, kExprI32GeS, 0, -3, -2);
207 TestInt32Binop(execution_mode, kExprI32GtU, 1, -6, 0);
208 TestInt32Binop(execution_mode, kExprI32GeU, 1, 0xF0000000, 98978);
209 }
210
TestInt32Unop(WasmExecutionMode execution_mode,WasmOpcode opcode,int32_t expected,int32_t a)211 void TestInt32Unop(WasmExecutionMode execution_mode, WasmOpcode opcode,
212 int32_t expected, int32_t a) {
213 {
214 WasmRunner<int32_t> r(execution_mode);
215 // return op K
216 BUILD(r, WASM_UNOP(opcode, WASM_I32V(a)));
217 CHECK_EQ(expected, r.Call());
218 }
219 {
220 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
221 // return op a
222 BUILD(r, WASM_UNOP(opcode, WASM_GET_LOCAL(0)));
223 CHECK_EQ(expected, r.Call(a));
224 }
225 }
226
WASM_EXEC_TEST(Int32Clz)227 WASM_EXEC_TEST(Int32Clz) {
228 TestInt32Unop(execution_mode, kExprI32Clz, 0, 0x80001000);
229 TestInt32Unop(execution_mode, kExprI32Clz, 1, 0x40000500);
230 TestInt32Unop(execution_mode, kExprI32Clz, 2, 0x20000300);
231 TestInt32Unop(execution_mode, kExprI32Clz, 3, 0x10000003);
232 TestInt32Unop(execution_mode, kExprI32Clz, 4, 0x08050000);
233 TestInt32Unop(execution_mode, kExprI32Clz, 5, 0x04006000);
234 TestInt32Unop(execution_mode, kExprI32Clz, 6, 0x02000000);
235 TestInt32Unop(execution_mode, kExprI32Clz, 7, 0x010000a0);
236 TestInt32Unop(execution_mode, kExprI32Clz, 8, 0x00800c00);
237 TestInt32Unop(execution_mode, kExprI32Clz, 9, 0x00400000);
238 TestInt32Unop(execution_mode, kExprI32Clz, 10, 0x0020000d);
239 TestInt32Unop(execution_mode, kExprI32Clz, 11, 0x00100f00);
240 TestInt32Unop(execution_mode, kExprI32Clz, 12, 0x00080000);
241 TestInt32Unop(execution_mode, kExprI32Clz, 13, 0x00041000);
242 TestInt32Unop(execution_mode, kExprI32Clz, 14, 0x00020020);
243 TestInt32Unop(execution_mode, kExprI32Clz, 15, 0x00010300);
244 TestInt32Unop(execution_mode, kExprI32Clz, 16, 0x00008040);
245 TestInt32Unop(execution_mode, kExprI32Clz, 17, 0x00004005);
246 TestInt32Unop(execution_mode, kExprI32Clz, 18, 0x00002050);
247 TestInt32Unop(execution_mode, kExprI32Clz, 19, 0x00001700);
248 TestInt32Unop(execution_mode, kExprI32Clz, 20, 0x00000870);
249 TestInt32Unop(execution_mode, kExprI32Clz, 21, 0x00000405);
250 TestInt32Unop(execution_mode, kExprI32Clz, 22, 0x00000203);
251 TestInt32Unop(execution_mode, kExprI32Clz, 23, 0x00000101);
252 TestInt32Unop(execution_mode, kExprI32Clz, 24, 0x00000089);
253 TestInt32Unop(execution_mode, kExprI32Clz, 25, 0x00000041);
254 TestInt32Unop(execution_mode, kExprI32Clz, 26, 0x00000022);
255 TestInt32Unop(execution_mode, kExprI32Clz, 27, 0x00000013);
256 TestInt32Unop(execution_mode, kExprI32Clz, 28, 0x00000008);
257 TestInt32Unop(execution_mode, kExprI32Clz, 29, 0x00000004);
258 TestInt32Unop(execution_mode, kExprI32Clz, 30, 0x00000002);
259 TestInt32Unop(execution_mode, kExprI32Clz, 31, 0x00000001);
260 TestInt32Unop(execution_mode, kExprI32Clz, 32, 0x00000000);
261 }
262
WASM_EXEC_TEST(Int32Ctz)263 WASM_EXEC_TEST(Int32Ctz) {
264 TestInt32Unop(execution_mode, kExprI32Ctz, 32, 0x00000000);
265 TestInt32Unop(execution_mode, kExprI32Ctz, 31, 0x80000000);
266 TestInt32Unop(execution_mode, kExprI32Ctz, 30, 0x40000000);
267 TestInt32Unop(execution_mode, kExprI32Ctz, 29, 0x20000000);
268 TestInt32Unop(execution_mode, kExprI32Ctz, 28, 0x10000000);
269 TestInt32Unop(execution_mode, kExprI32Ctz, 27, 0xa8000000);
270 TestInt32Unop(execution_mode, kExprI32Ctz, 26, 0xf4000000);
271 TestInt32Unop(execution_mode, kExprI32Ctz, 25, 0x62000000);
272 TestInt32Unop(execution_mode, kExprI32Ctz, 24, 0x91000000);
273 TestInt32Unop(execution_mode, kExprI32Ctz, 23, 0xcd800000);
274 TestInt32Unop(execution_mode, kExprI32Ctz, 22, 0x09400000);
275 TestInt32Unop(execution_mode, kExprI32Ctz, 21, 0xaf200000);
276 TestInt32Unop(execution_mode, kExprI32Ctz, 20, 0xac100000);
277 TestInt32Unop(execution_mode, kExprI32Ctz, 19, 0xe0b80000);
278 TestInt32Unop(execution_mode, kExprI32Ctz, 18, 0x9ce40000);
279 TestInt32Unop(execution_mode, kExprI32Ctz, 17, 0xc7920000);
280 TestInt32Unop(execution_mode, kExprI32Ctz, 16, 0xb8f10000);
281 TestInt32Unop(execution_mode, kExprI32Ctz, 15, 0x3b9f8000);
282 TestInt32Unop(execution_mode, kExprI32Ctz, 14, 0xdb4c4000);
283 TestInt32Unop(execution_mode, kExprI32Ctz, 13, 0xe9a32000);
284 TestInt32Unop(execution_mode, kExprI32Ctz, 12, 0xfca61000);
285 TestInt32Unop(execution_mode, kExprI32Ctz, 11, 0x6c8a7800);
286 TestInt32Unop(execution_mode, kExprI32Ctz, 10, 0x8ce5a400);
287 TestInt32Unop(execution_mode, kExprI32Ctz, 9, 0xcb7d0200);
288 TestInt32Unop(execution_mode, kExprI32Ctz, 8, 0xcb4dc100);
289 TestInt32Unop(execution_mode, kExprI32Ctz, 7, 0xdfbec580);
290 TestInt32Unop(execution_mode, kExprI32Ctz, 6, 0x27a9db40);
291 TestInt32Unop(execution_mode, kExprI32Ctz, 5, 0xde3bcb20);
292 TestInt32Unop(execution_mode, kExprI32Ctz, 4, 0xd7e8a610);
293 TestInt32Unop(execution_mode, kExprI32Ctz, 3, 0x9afdbc88);
294 TestInt32Unop(execution_mode, kExprI32Ctz, 2, 0x9afdbc84);
295 TestInt32Unop(execution_mode, kExprI32Ctz, 1, 0x9afdbc82);
296 TestInt32Unop(execution_mode, kExprI32Ctz, 0, 0x9afdbc81);
297 }
298
WASM_EXEC_TEST(Int32Popcnt)299 WASM_EXEC_TEST(Int32Popcnt) {
300 TestInt32Unop(execution_mode, kExprI32Popcnt, 32, 0xffffffff);
301 TestInt32Unop(execution_mode, kExprI32Popcnt, 0, 0x00000000);
302 TestInt32Unop(execution_mode, kExprI32Popcnt, 1, 0x00008000);
303 TestInt32Unop(execution_mode, kExprI32Popcnt, 13, 0x12345678);
304 TestInt32Unop(execution_mode, kExprI32Popcnt, 19, 0xfedcba09);
305 }
306
WASM_EXEC_TEST(I32Eqz)307 WASM_EXEC_TEST(I32Eqz) {
308 TestInt32Unop(execution_mode, kExprI32Eqz, 0, 1);
309 TestInt32Unop(execution_mode, kExprI32Eqz, 0, -1);
310 TestInt32Unop(execution_mode, kExprI32Eqz, 0, -827343);
311 TestInt32Unop(execution_mode, kExprI32Eqz, 0, 8888888);
312 TestInt32Unop(execution_mode, kExprI32Eqz, 1, 0);
313 }
314
WASM_EXEC_TEST(I32Shl)315 WASM_EXEC_TEST(I32Shl) {
316 WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32(),
317 MachineType::Uint32());
318 BUILD(r, WASM_I32_SHL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
319
320 FOR_UINT32_INPUTS(i) {
321 FOR_UINT32_INPUTS(j) {
322 uint32_t expected = (*i) << (*j & 0x1f);
323 CHECK_EQ(expected, r.Call(*i, *j));
324 }
325 }
326 }
327
WASM_EXEC_TEST(I32Shr)328 WASM_EXEC_TEST(I32Shr) {
329 WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32(),
330 MachineType::Uint32());
331 BUILD(r, WASM_I32_SHR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
332
333 FOR_UINT32_INPUTS(i) {
334 FOR_UINT32_INPUTS(j) {
335 uint32_t expected = (*i) >> (*j & 0x1f);
336 CHECK_EQ(expected, r.Call(*i, *j));
337 }
338 }
339 }
340
WASM_EXEC_TEST(I32Sar)341 WASM_EXEC_TEST(I32Sar) {
342 WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
343 MachineType::Int32());
344 BUILD(r, WASM_I32_SAR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
345
346 FOR_INT32_INPUTS(i) {
347 FOR_INT32_INPUTS(j) {
348 int32_t expected = (*i) >> (*j & 0x1f);
349 CHECK_EQ(expected, r.Call(*i, *j));
350 }
351 }
352 }
353
WASM_EXEC_TEST(Int32DivS_trap)354 WASM_EXEC_TEST(Int32DivS_trap) {
355 WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
356 MachineType::Int32());
357 BUILD(r, WASM_I32_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
358 const int32_t kMin = std::numeric_limits<int32_t>::min();
359 CHECK_EQ(0, r.Call(0, 100));
360 CHECK_TRAP(r.Call(100, 0));
361 CHECK_TRAP(r.Call(-1001, 0));
362 CHECK_TRAP(r.Call(kMin, -1));
363 CHECK_TRAP(r.Call(kMin, 0));
364 }
365
WASM_EXEC_TEST(Int32RemS_trap)366 WASM_EXEC_TEST(Int32RemS_trap) {
367 WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
368 MachineType::Int32());
369 BUILD(r, WASM_I32_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
370 const int32_t kMin = std::numeric_limits<int32_t>::min();
371 CHECK_EQ(33, r.Call(133, 100));
372 CHECK_EQ(0, r.Call(kMin, -1));
373 CHECK_TRAP(r.Call(100, 0));
374 CHECK_TRAP(r.Call(-1001, 0));
375 CHECK_TRAP(r.Call(kMin, 0));
376 }
377
WASM_EXEC_TEST(Int32DivU_trap)378 WASM_EXEC_TEST(Int32DivU_trap) {
379 WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
380 MachineType::Int32());
381 BUILD(r, WASM_I32_DIVU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
382 const int32_t kMin = std::numeric_limits<int32_t>::min();
383 CHECK_EQ(0, r.Call(0, 100));
384 CHECK_EQ(0, r.Call(kMin, -1));
385 CHECK_TRAP(r.Call(100, 0));
386 CHECK_TRAP(r.Call(-1001, 0));
387 CHECK_TRAP(r.Call(kMin, 0));
388 }
389
WASM_EXEC_TEST(Int32RemU_trap)390 WASM_EXEC_TEST(Int32RemU_trap) {
391 WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
392 MachineType::Int32());
393 BUILD(r, WASM_I32_REMU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
394 CHECK_EQ(17, r.Call(217, 100));
395 const int32_t kMin = std::numeric_limits<int32_t>::min();
396 CHECK_TRAP(r.Call(100, 0));
397 CHECK_TRAP(r.Call(-1001, 0));
398 CHECK_TRAP(r.Call(kMin, 0));
399 CHECK_EQ(kMin, r.Call(kMin, -1));
400 }
401
WASM_EXEC_TEST(Int32DivS_byzero_const)402 WASM_EXEC_TEST(Int32DivS_byzero_const) {
403 for (int8_t denom = -2; denom < 8; ++denom) {
404 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
405 BUILD(r, WASM_I32_DIVS(WASM_GET_LOCAL(0), WASM_I8(denom)));
406 for (int32_t val = -7; val < 8; ++val) {
407 if (denom == 0) {
408 CHECK_TRAP(r.Call(val));
409 } else {
410 CHECK_EQ(val / denom, r.Call(val));
411 }
412 }
413 }
414 }
415
WASM_EXEC_TEST(Int32DivU_byzero_const)416 WASM_EXEC_TEST(Int32DivU_byzero_const) {
417 for (uint32_t denom = 0xfffffffe; denom < 8; ++denom) {
418 WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32());
419 BUILD(r, WASM_I32_DIVU(WASM_GET_LOCAL(0), WASM_I32V_1(denom)));
420
421 for (uint32_t val = 0xfffffff0; val < 8; ++val) {
422 if (denom == 0) {
423 CHECK_TRAP(r.Call(val));
424 } else {
425 CHECK_EQ(val / denom, r.Call(val));
426 }
427 }
428 }
429 }
430
WASM_EXEC_TEST(Int32DivS_trap_effect)431 WASM_EXEC_TEST(Int32DivS_trap_effect) {
432 TestingModule module(execution_mode);
433 module.AddMemoryElems<int32_t>(8);
434 WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32());
435
436 BUILD(r,
437 WASM_IF_ELSE(WASM_GET_LOCAL(0),
438 WASM_I32_DIVS(WASM_STORE_MEM(MachineType::Int8(),
439 WASM_ZERO, WASM_GET_LOCAL(0)),
440 WASM_GET_LOCAL(1)),
441 WASM_I32_DIVS(WASM_STORE_MEM(MachineType::Int8(),
442 WASM_ZERO, WASM_GET_LOCAL(0)),
443 WASM_GET_LOCAL(1))));
444 CHECK_EQ(0, r.Call(0, 100));
445 CHECK_TRAP(r.Call(8, 0));
446 CHECK_TRAP(r.Call(4, 0));
447 CHECK_TRAP(r.Call(0, 0));
448 }
449
TestFloat32Binop(WasmExecutionMode execution_mode,WasmOpcode opcode,int32_t expected,float a,float b)450 void TestFloat32Binop(WasmExecutionMode execution_mode, WasmOpcode opcode,
451 int32_t expected, float a, float b) {
452 {
453 WasmRunner<int32_t> r(execution_mode);
454 // return K op K
455 BUILD(r, WASM_BINOP(opcode, WASM_F32(a), WASM_F32(b)));
456 CHECK_EQ(expected, r.Call());
457 }
458 {
459 WasmRunner<int32_t> r(execution_mode, MachineType::Float32(),
460 MachineType::Float32());
461 // return a op b
462 BUILD(r, WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
463 CHECK_EQ(expected, r.Call(a, b));
464 }
465 }
466
TestFloat32BinopWithConvert(WasmExecutionMode execution_mode,WasmOpcode opcode,int32_t expected,float a,float b)467 void TestFloat32BinopWithConvert(WasmExecutionMode execution_mode,
468 WasmOpcode opcode, int32_t expected, float a,
469 float b) {
470 {
471 WasmRunner<int32_t> r(execution_mode);
472 // return int(K op K)
473 BUILD(r,
474 WASM_I32_SCONVERT_F32(WASM_BINOP(opcode, WASM_F32(a), WASM_F32(b))));
475 CHECK_EQ(expected, r.Call());
476 }
477 {
478 WasmRunner<int32_t> r(execution_mode, MachineType::Float32(),
479 MachineType::Float32());
480 // return int(a op b)
481 BUILD(r, WASM_I32_SCONVERT_F32(
482 WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))));
483 CHECK_EQ(expected, r.Call(a, b));
484 }
485 }
486
TestFloat32UnopWithConvert(WasmExecutionMode execution_mode,WasmOpcode opcode,int32_t expected,float a)487 void TestFloat32UnopWithConvert(WasmExecutionMode execution_mode,
488 WasmOpcode opcode, int32_t expected, float a) {
489 {
490 WasmRunner<int32_t> r(execution_mode);
491 // return int(op(K))
492 BUILD(r, WASM_I32_SCONVERT_F32(WASM_UNOP(opcode, WASM_F32(a))));
493 CHECK_EQ(expected, r.Call());
494 }
495 {
496 WasmRunner<int32_t> r(execution_mode, MachineType::Float32());
497 // return int(op(a))
498 BUILD(r, WASM_I32_SCONVERT_F32(WASM_UNOP(opcode, WASM_GET_LOCAL(0))));
499 CHECK_EQ(expected, r.Call(a));
500 }
501 }
502
TestFloat64Binop(WasmExecutionMode execution_mode,WasmOpcode opcode,int32_t expected,double a,double b)503 void TestFloat64Binop(WasmExecutionMode execution_mode, WasmOpcode opcode,
504 int32_t expected, double a, double b) {
505 {
506 WasmRunner<int32_t> r(execution_mode);
507 // return K op K
508 BUILD(r, WASM_BINOP(opcode, WASM_F64(a), WASM_F64(b)));
509 CHECK_EQ(expected, r.Call());
510 }
511 {
512 WasmRunner<int32_t> r(execution_mode, MachineType::Float64(),
513 MachineType::Float64());
514 // return a op b
515 BUILD(r, WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
516 CHECK_EQ(expected, r.Call(a, b));
517 }
518 }
519
TestFloat64BinopWithConvert(WasmExecutionMode execution_mode,WasmOpcode opcode,int32_t expected,double a,double b)520 void TestFloat64BinopWithConvert(WasmExecutionMode execution_mode,
521 WasmOpcode opcode, int32_t expected, double a,
522 double b) {
523 {
524 WasmRunner<int32_t> r(execution_mode);
525 // return int(K op K)
526 BUILD(r,
527 WASM_I32_SCONVERT_F64(WASM_BINOP(opcode, WASM_F64(a), WASM_F64(b))));
528 CHECK_EQ(expected, r.Call());
529 }
530 {
531 WasmRunner<int32_t> r(execution_mode, MachineType::Float64(),
532 MachineType::Float64());
533 BUILD(r, WASM_I32_SCONVERT_F64(
534 WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))));
535 CHECK_EQ(expected, r.Call(a, b));
536 }
537 }
538
TestFloat64UnopWithConvert(WasmExecutionMode execution_mode,WasmOpcode opcode,int32_t expected,double a)539 void TestFloat64UnopWithConvert(WasmExecutionMode execution_mode,
540 WasmOpcode opcode, int32_t expected, double a) {
541 {
542 WasmRunner<int32_t> r(execution_mode);
543 // return int(op(K))
544 BUILD(r, WASM_I32_SCONVERT_F64(WASM_UNOP(opcode, WASM_F64(a))));
545 CHECK_EQ(expected, r.Call());
546 }
547 {
548 WasmRunner<int32_t> r(execution_mode, MachineType::Float64());
549 // return int(op(a))
550 BUILD(r, WASM_I32_SCONVERT_F64(WASM_UNOP(opcode, WASM_GET_LOCAL(0))));
551 CHECK_EQ(expected, r.Call(a));
552 }
553 }
554
WASM_EXEC_TEST(Float32Binops)555 WASM_EXEC_TEST(Float32Binops) {
556 TestFloat32Binop(execution_mode, kExprF32Eq, 1, 8.125f, 8.125f);
557 TestFloat32Binop(execution_mode, kExprF32Ne, 1, 8.125f, 8.127f);
558 TestFloat32Binop(execution_mode, kExprF32Lt, 1, -9.5f, -9.0f);
559 TestFloat32Binop(execution_mode, kExprF32Le, 1, -1111.0f, -1111.0f);
560 TestFloat32Binop(execution_mode, kExprF32Gt, 1, -9.0f, -9.5f);
561 TestFloat32Binop(execution_mode, kExprF32Ge, 1, -1111.0f, -1111.0f);
562
563 TestFloat32BinopWithConvert(execution_mode, kExprF32Add, 10, 3.5f, 6.5f);
564 TestFloat32BinopWithConvert(execution_mode, kExprF32Sub, 2, 44.5f, 42.5f);
565 TestFloat32BinopWithConvert(execution_mode, kExprF32Mul, -66, -132.1f, 0.5f);
566 TestFloat32BinopWithConvert(execution_mode, kExprF32Div, 11, 22.1f, 2.0f);
567 }
568
WASM_EXEC_TEST(Float32Unops)569 WASM_EXEC_TEST(Float32Unops) {
570 TestFloat32UnopWithConvert(execution_mode, kExprF32Abs, 8, 8.125f);
571 TestFloat32UnopWithConvert(execution_mode, kExprF32Abs, 9, -9.125f);
572 TestFloat32UnopWithConvert(execution_mode, kExprF32Neg, -213, 213.125f);
573 TestFloat32UnopWithConvert(execution_mode, kExprF32Sqrt, 12, 144.4f);
574 }
575
WASM_EXEC_TEST(Float64Binops)576 WASM_EXEC_TEST(Float64Binops) {
577 TestFloat64Binop(execution_mode, kExprF64Eq, 1, 16.25, 16.25);
578 TestFloat64Binop(execution_mode, kExprF64Ne, 1, 16.25, 16.15);
579 TestFloat64Binop(execution_mode, kExprF64Lt, 1, -32.4, 11.7);
580 TestFloat64Binop(execution_mode, kExprF64Le, 1, -88.9, -88.9);
581 TestFloat64Binop(execution_mode, kExprF64Gt, 1, 11.7, -32.4);
582 TestFloat64Binop(execution_mode, kExprF64Ge, 1, -88.9, -88.9);
583
584 TestFloat64BinopWithConvert(execution_mode, kExprF64Add, 100, 43.5, 56.5);
585 TestFloat64BinopWithConvert(execution_mode, kExprF64Sub, 200, 12200.1,
586 12000.1);
587 TestFloat64BinopWithConvert(execution_mode, kExprF64Mul, -33, 134, -0.25);
588 TestFloat64BinopWithConvert(execution_mode, kExprF64Div, -1111, -2222.3, 2);
589 }
590
WASM_EXEC_TEST(Float64Unops)591 WASM_EXEC_TEST(Float64Unops) {
592 TestFloat64UnopWithConvert(execution_mode, kExprF64Abs, 108, 108.125);
593 TestFloat64UnopWithConvert(execution_mode, kExprF64Abs, 209, -209.125);
594 TestFloat64UnopWithConvert(execution_mode, kExprF64Neg, -209, 209.125);
595 TestFloat64UnopWithConvert(execution_mode, kExprF64Sqrt, 13, 169.4);
596 }
597
WASM_EXEC_TEST(Float32Neg)598 WASM_EXEC_TEST(Float32Neg) {
599 WasmRunner<float> r(execution_mode, MachineType::Float32());
600 BUILD(r, WASM_F32_NEG(WASM_GET_LOCAL(0)));
601
602 FOR_FLOAT32_INPUTS(i) {
603 CHECK_EQ(0x80000000,
604 bit_cast<uint32_t>(*i) ^ bit_cast<uint32_t>(r.Call(*i)));
605 }
606 }
607
WASM_EXEC_TEST(Float32SubMinusZero)608 WASM_EXEC_TEST(Float32SubMinusZero) {
609 WasmRunner<float> r(execution_mode, MachineType::Float32());
610 BUILD(r, WASM_F32_SUB(WASM_F32(-0.0), WASM_GET_LOCAL(0)));
611
612 uint32_t sNanValue =
613 bit_cast<uint32_t>(std::numeric_limits<float>::signaling_NaN());
614 uint32_t qNanValue =
615 bit_cast<uint32_t>(std::numeric_limits<float>::quiet_NaN());
616 uint32_t payload = 0x00200000;
617
618 uint32_t expected = (qNanValue & 0xffc00000) | payload;
619 uint32_t operand = (sNanValue & 0xffc00000) | payload;
620 CHECK_EQ(expected, bit_cast<uint32_t>(r.Call(bit_cast<float>(operand))));
621
622 // Change the sign of the NaN.
623 expected |= 0x80000000;
624 operand |= 0x80000000;
625 CHECK_EQ(expected, bit_cast<uint32_t>(r.Call(bit_cast<float>(operand))));
626 }
627
WASM_EXEC_TEST(Float64SubMinusZero)628 WASM_EXEC_TEST(Float64SubMinusZero) {
629 WasmRunner<double> r(execution_mode, MachineType::Float64());
630 BUILD(r, WASM_F64_SUB(WASM_F64(-0.0), WASM_GET_LOCAL(0)));
631
632 uint64_t sNanValue =
633 bit_cast<uint64_t>(std::numeric_limits<double>::signaling_NaN());
634 uint64_t qNanValue =
635 bit_cast<uint64_t>(std::numeric_limits<double>::quiet_NaN());
636 uint64_t payload = 0x0000123456789abc;
637
638 uint64_t expected = (qNanValue & 0xfff8000000000000) | payload;
639 uint64_t operand = (sNanValue & 0xfff8000000000000) | payload;
640 CHECK_EQ(expected, bit_cast<uint64_t>(r.Call(bit_cast<double>(operand))));
641
642 // Change the sign of the NaN.
643 expected |= 0x8000000000000000;
644 operand |= 0x8000000000000000;
645 CHECK_EQ(expected, bit_cast<uint64_t>(r.Call(bit_cast<double>(operand))));
646 }
647
WASM_EXEC_TEST(Float64Neg)648 WASM_EXEC_TEST(Float64Neg) {
649 WasmRunner<double> r(execution_mode, MachineType::Float64());
650 BUILD(r, WASM_F64_NEG(WASM_GET_LOCAL(0)));
651
652 FOR_FLOAT64_INPUTS(i) {
653 CHECK_EQ(0x8000000000000000,
654 bit_cast<uint64_t>(*i) ^ bit_cast<uint64_t>(r.Call(*i)));
655 }
656 }
657
WASM_EXEC_TEST(IfElse_P)658 WASM_EXEC_TEST(IfElse_P) {
659 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
660 // if (p0) return 11; else return 22;
661 BUILD(r, WASM_IF_ELSE(WASM_GET_LOCAL(0), // --
662 WASM_I8(11), // --
663 WASM_I8(22))); // --
664 FOR_INT32_INPUTS(i) {
665 int32_t expected = *i ? 11 : 22;
666 CHECK_EQ(expected, r.Call(*i));
667 }
668 }
669
WASM_EXEC_TEST(If_empty1)670 WASM_EXEC_TEST(If_empty1) {
671 WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32(),
672 MachineType::Uint32());
673 BUILD(r, WASM_GET_LOCAL(0), kExprIf, kExprEnd, WASM_GET_LOCAL(1));
674 FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i - 9, *i)); }
675 }
676
WASM_EXEC_TEST(IfElse_empty1)677 WASM_EXEC_TEST(IfElse_empty1) {
678 WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32(),
679 MachineType::Uint32());
680 BUILD(r, WASM_GET_LOCAL(0), kExprIf, kExprElse, kExprEnd, WASM_GET_LOCAL(1));
681 FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i - 8, *i)); }
682 }
683
WASM_EXEC_TEST(IfElse_empty2)684 WASM_EXEC_TEST(IfElse_empty2) {
685 WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32(),
686 MachineType::Uint32());
687 BUILD(r, WASM_GET_LOCAL(0), kExprIf, WASM_ZERO, kExprElse, kExprEnd,
688 WASM_GET_LOCAL(1));
689 FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i - 7, *i)); }
690 }
691
WASM_EXEC_TEST(IfElse_empty3)692 WASM_EXEC_TEST(IfElse_empty3) {
693 WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32(),
694 MachineType::Uint32());
695 BUILD(r, WASM_GET_LOCAL(0), kExprIf, kExprElse, WASM_ZERO, kExprEnd,
696 WASM_GET_LOCAL(1));
697 FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i - 6, *i)); }
698 }
699
WASM_EXEC_TEST(If_chain)700 WASM_EXEC_TEST(If_chain) {
701 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
702 // if (p0) 13; if (p0) 14; 15
703 BUILD(r, WASM_IF(WASM_GET_LOCAL(0), WASM_I8(13)),
704 WASM_IF(WASM_GET_LOCAL(0), WASM_I8(14)), WASM_I8(15));
705 FOR_INT32_INPUTS(i) { CHECK_EQ(15, r.Call(*i)); }
706 }
707
WASM_EXEC_TEST(If_chain_set)708 WASM_EXEC_TEST(If_chain_set) {
709 WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
710 MachineType::Int32());
711 // if (p0) p1 = 73; if (p0) p1 = 74; p1
712 BUILD(r, WASM_IF(WASM_GET_LOCAL(0), WASM_SET_LOCAL(1, WASM_I8(73))),
713 WASM_IF(WASM_GET_LOCAL(0), WASM_SET_LOCAL(1, WASM_I8(74))),
714 WASM_GET_LOCAL(1));
715 FOR_INT32_INPUTS(i) {
716 int32_t expected = *i ? 74 : *i;
717 CHECK_EQ(expected, r.Call(*i, *i));
718 }
719 }
720
WASM_EXEC_TEST(IfElse_Unreachable1)721 WASM_EXEC_TEST(IfElse_Unreachable1) {
722 WasmRunner<int32_t> r(execution_mode);
723 // if (0) unreachable; else return 22;
724 BUILD(r, WASM_IF_ELSE(WASM_ZERO, // --
725 WASM_UNREACHABLE, // --
726 WASM_I8(27))); // --
727 CHECK_EQ(27, r.Call());
728 }
729
WASM_EXEC_TEST(Return12)730 WASM_EXEC_TEST(Return12) {
731 WasmRunner<int32_t> r(execution_mode);
732
733 BUILD(r, RET_I8(12));
734 CHECK_EQ(12, r.Call());
735 }
736
WASM_EXEC_TEST(Return17)737 WASM_EXEC_TEST(Return17) {
738 WasmRunner<int32_t> r(execution_mode);
739
740 BUILD(r, B1(RET_I8(17)));
741 CHECK_EQ(17, r.Call());
742 }
743
WASM_EXEC_TEST(Return_I32)744 WASM_EXEC_TEST(Return_I32) {
745 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
746
747 BUILD(r, RET(WASM_GET_LOCAL(0)));
748
749 FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
750 }
751
WASM_EXEC_TEST(Return_F32)752 WASM_EXEC_TEST(Return_F32) {
753 WasmRunner<float> r(execution_mode, MachineType::Float32());
754
755 BUILD(r, RET(WASM_GET_LOCAL(0)));
756
757 FOR_FLOAT32_INPUTS(i) {
758 float expect = *i;
759 float result = r.Call(expect);
760 if (std::isnan(expect)) {
761 CHECK(std::isnan(result));
762 } else {
763 CHECK_EQ(expect, result);
764 }
765 }
766 }
767
WASM_EXEC_TEST(Return_F64)768 WASM_EXEC_TEST(Return_F64) {
769 WasmRunner<double> r(execution_mode, MachineType::Float64());
770
771 BUILD(r, RET(WASM_GET_LOCAL(0)));
772
773 FOR_FLOAT64_INPUTS(i) {
774 double expect = *i;
775 double result = r.Call(expect);
776 if (std::isnan(expect)) {
777 CHECK(std::isnan(result));
778 } else {
779 CHECK_EQ(expect, result);
780 }
781 }
782 }
783
WASM_EXEC_TEST(Select)784 WASM_EXEC_TEST(Select) {
785 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
786 // return select(11, 22, a);
787 BUILD(r, WASM_SELECT(WASM_I8(11), WASM_I8(22), WASM_GET_LOCAL(0)));
788 FOR_INT32_INPUTS(i) {
789 int32_t expected = *i ? 11 : 22;
790 CHECK_EQ(expected, r.Call(*i));
791 }
792 }
793
WASM_EXEC_TEST(Select_strict1)794 WASM_EXEC_TEST(Select_strict1) {
795 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
796 // select(a=0, a=1, a=2); return a
797 BUILD(r, B2(WASM_SELECT(WASM_SET_LOCAL(0, WASM_I8(0)),
798 WASM_SET_LOCAL(0, WASM_I8(1)),
799 WASM_SET_LOCAL(0, WASM_I8(2))),
800 WASM_GET_LOCAL(0)));
801 FOR_INT32_INPUTS(i) { CHECK_EQ(2, r.Call(*i)); }
802 }
803
WASM_EXEC_TEST(Select_strict2)804 WASM_EXEC_TEST(Select_strict2) {
805 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
806 r.AllocateLocal(kAstI32);
807 r.AllocateLocal(kAstI32);
808 // select(b=5, c=6, a)
809 BUILD(r, WASM_SELECT(WASM_SET_LOCAL(1, WASM_I8(5)),
810 WASM_SET_LOCAL(2, WASM_I8(6)), WASM_GET_LOCAL(0)));
811 FOR_INT32_INPUTS(i) {
812 int32_t expected = *i ? 5 : 6;
813 CHECK_EQ(expected, r.Call(*i));
814 }
815 }
816
WASM_EXEC_TEST(Select_strict3)817 WASM_EXEC_TEST(Select_strict3) {
818 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
819 r.AllocateLocal(kAstI32);
820 r.AllocateLocal(kAstI32);
821 // select(b=5, c=6, a=b)
822 BUILD(r, WASM_SELECT(WASM_SET_LOCAL(1, WASM_I8(5)),
823 WASM_SET_LOCAL(2, WASM_I8(6)),
824 WASM_SET_LOCAL(0, WASM_GET_LOCAL(1))));
825 FOR_INT32_INPUTS(i) {
826 int32_t expected = 5;
827 CHECK_EQ(expected, r.Call(*i));
828 }
829 }
830
WASM_EXEC_TEST(BrIf_strict)831 WASM_EXEC_TEST(BrIf_strict) {
832 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
833 BUILD(
834 r,
835 B2(B1(WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_SET_LOCAL(0, WASM_I8(99)))),
836 WASM_GET_LOCAL(0)));
837
838 FOR_INT32_INPUTS(i) { CHECK_EQ(99, r.Call(*i)); }
839 }
840
WASM_EXEC_TEST(BrTable0a)841 WASM_EXEC_TEST(BrTable0a) {
842 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
843 BUILD(r,
844 B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 0, BR_TARGET(0))), WASM_I8(91)));
845 FOR_INT32_INPUTS(i) { CHECK_EQ(91, r.Call(*i)); }
846 }
847
WASM_EXEC_TEST(BrTable0b)848 WASM_EXEC_TEST(BrTable0b) {
849 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
850 BUILD(r,
851 B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 1, BR_TARGET(0), BR_TARGET(0))),
852 WASM_I8(92)));
853 FOR_INT32_INPUTS(i) { CHECK_EQ(92, r.Call(*i)); }
854 }
855
WASM_EXEC_TEST(BrTable0c)856 WASM_EXEC_TEST(BrTable0c) {
857 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
858 BUILD(
859 r,
860 B2(B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 1, BR_TARGET(0), BR_TARGET(1))),
861 RET_I8(76)),
862 WASM_I8(77)));
863 FOR_INT32_INPUTS(i) {
864 int32_t expected = *i == 0 ? 76 : 77;
865 CHECK_EQ(expected, r.Call(*i));
866 }
867 }
868
WASM_EXEC_TEST(BrTable1)869 WASM_EXEC_TEST(BrTable1) {
870 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
871 BUILD(r, B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 0, BR_TARGET(0))), RET_I8(93));
872 FOR_INT32_INPUTS(i) { CHECK_EQ(93, r.Call(*i)); }
873 }
874
WASM_EXEC_TEST(BrTable_loop)875 WASM_EXEC_TEST(BrTable_loop) {
876 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
877 BUILD(r,
878 B2(WASM_LOOP(1, WASM_BR_TABLE(WASM_INC_LOCAL_BY(0, 1), 2, BR_TARGET(2),
879 BR_TARGET(1), BR_TARGET(0))),
880 RET_I8(99)),
881 WASM_I8(98));
882 CHECK_EQ(99, r.Call(0));
883 CHECK_EQ(98, r.Call(-1));
884 CHECK_EQ(98, r.Call(-2));
885 CHECK_EQ(98, r.Call(-3));
886 CHECK_EQ(98, r.Call(-100));
887 }
888
WASM_EXEC_TEST(BrTable_br)889 WASM_EXEC_TEST(BrTable_br) {
890 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
891 BUILD(r,
892 B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 1, BR_TARGET(1), BR_TARGET(0))),
893 RET_I8(91)),
894 WASM_I8(99));
895 CHECK_EQ(99, r.Call(0));
896 CHECK_EQ(91, r.Call(1));
897 CHECK_EQ(91, r.Call(2));
898 CHECK_EQ(91, r.Call(3));
899 }
900
WASM_EXEC_TEST(BrTable_br2)901 WASM_EXEC_TEST(BrTable_br2) {
902 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
903
904 BUILD(r, B2(B2(B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 3, BR_TARGET(1),
905 BR_TARGET(2), BR_TARGET(3), BR_TARGET(0))),
906 RET_I8(85)),
907 RET_I8(86)),
908 RET_I8(87)),
909 WASM_I8(88));
910 CHECK_EQ(86, r.Call(0));
911 CHECK_EQ(87, r.Call(1));
912 CHECK_EQ(88, r.Call(2));
913 CHECK_EQ(85, r.Call(3));
914 CHECK_EQ(85, r.Call(4));
915 CHECK_EQ(85, r.Call(5));
916 }
917
WASM_EXEC_TEST(BrTable4)918 WASM_EXEC_TEST(BrTable4) {
919 for (int i = 0; i < 4; ++i) {
920 for (int t = 0; t < 4; ++t) {
921 uint32_t cases[] = {0, 1, 2, 3};
922 cases[i] = t;
923 byte code[] = {B2(B2(B2(B2(B1(WASM_BR_TABLE(
924 WASM_GET_LOCAL(0), 3, BR_TARGET(cases[0]),
925 BR_TARGET(cases[1]), BR_TARGET(cases[2]),
926 BR_TARGET(cases[3]))),
927 RET_I8(70)),
928 RET_I8(71)),
929 RET_I8(72)),
930 RET_I8(73)),
931 WASM_I8(75)};
932
933 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
934 r.Build(code, code + arraysize(code));
935
936 for (int x = -3; x < 50; ++x) {
937 int index = (x > 3 || x < 0) ? 3 : x;
938 int32_t expected = 70 + cases[index];
939 CHECK_EQ(expected, r.Call(x));
940 }
941 }
942 }
943 }
944
WASM_EXEC_TEST(BrTable4x4)945 WASM_EXEC_TEST(BrTable4x4) {
946 for (byte a = 0; a < 4; ++a) {
947 for (byte b = 0; b < 4; ++b) {
948 for (byte c = 0; c < 4; ++c) {
949 for (byte d = 0; d < 4; ++d) {
950 for (int i = 0; i < 4; ++i) {
951 uint32_t cases[] = {a, b, c, d};
952 byte code[] = {
953 B2(B2(B2(B2(B1(WASM_BR_TABLE(
954 WASM_GET_LOCAL(0), 3, BR_TARGET(cases[0]),
955 BR_TARGET(cases[1]), BR_TARGET(cases[2]),
956 BR_TARGET(cases[3]))),
957 RET_I8(50)),
958 RET_I8(51)),
959 RET_I8(52)),
960 RET_I8(53)),
961 WASM_I8(55)};
962
963 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
964 r.Build(code, code + arraysize(code));
965
966 for (int x = -6; x < 47; ++x) {
967 int index = (x > 3 || x < 0) ? 3 : x;
968 int32_t expected = 50 + cases[index];
969 CHECK_EQ(expected, r.Call(x));
970 }
971 }
972 }
973 }
974 }
975 }
976 }
977
WASM_EXEC_TEST(BrTable4_fallthru)978 WASM_EXEC_TEST(BrTable4_fallthru) {
979 byte code[] = {
980 B2(B2(B2(B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 3, BR_TARGET(0),
981 BR_TARGET(1), BR_TARGET(2), BR_TARGET(3))),
982 WASM_INC_LOCAL_BY(1, 1)),
983 WASM_INC_LOCAL_BY(1, 2)),
984 WASM_INC_LOCAL_BY(1, 4)),
985 WASM_INC_LOCAL_BY(1, 8)),
986 WASM_GET_LOCAL(1)};
987
988 WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
989 MachineType::Int32());
990 r.Build(code, code + arraysize(code));
991
992 CHECK_EQ(15, r.Call(0, 0));
993 CHECK_EQ(14, r.Call(1, 0));
994 CHECK_EQ(12, r.Call(2, 0));
995 CHECK_EQ(8, r.Call(3, 0));
996 CHECK_EQ(8, r.Call(4, 0));
997
998 CHECK_EQ(115, r.Call(0, 100));
999 CHECK_EQ(114, r.Call(1, 100));
1000 CHECK_EQ(112, r.Call(2, 100));
1001 CHECK_EQ(108, r.Call(3, 100));
1002 CHECK_EQ(108, r.Call(4, 100));
1003 }
1004
WASM_EXEC_TEST(F32ReinterpretI32)1005 WASM_EXEC_TEST(F32ReinterpretI32) {
1006 TestingModule module(execution_mode);
1007 int32_t* memory = module.AddMemoryElems<int32_t>(8);
1008 WasmRunner<int32_t> r(&module);
1009
1010 BUILD(r, WASM_I32_REINTERPRET_F32(
1011 WASM_LOAD_MEM(MachineType::Float32(), WASM_ZERO)));
1012
1013 FOR_INT32_INPUTS(i) {
1014 int32_t expected = *i;
1015 memory[0] = expected;
1016 CHECK_EQ(expected, r.Call());
1017 }
1018 }
1019
WASM_EXEC_TEST(I32ReinterpretF32)1020 WASM_EXEC_TEST(I32ReinterpretF32) {
1021 TestingModule module(execution_mode);
1022 int32_t* memory = module.AddMemoryElems<int32_t>(8);
1023 WasmRunner<int32_t> r(&module, MachineType::Int32());
1024
1025 BUILD(r, WASM_BLOCK(
1026 2, WASM_STORE_MEM(MachineType::Float32(), WASM_ZERO,
1027 WASM_F32_REINTERPRET_I32(WASM_GET_LOCAL(0))),
1028 WASM_I8(107)));
1029
1030 FOR_INT32_INPUTS(i) {
1031 int32_t expected = *i;
1032 CHECK_EQ(107, r.Call(expected));
1033 CHECK_EQ(expected, memory[0]);
1034 }
1035 }
1036
WASM_EXEC_TEST(ReturnStore)1037 WASM_EXEC_TEST(ReturnStore) {
1038 TestingModule module(execution_mode);
1039 int32_t* memory = module.AddMemoryElems<int32_t>(8);
1040 WasmRunner<int32_t> r(&module);
1041
1042 BUILD(r, WASM_STORE_MEM(MachineType::Int32(), WASM_ZERO,
1043 WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO)));
1044
1045 FOR_INT32_INPUTS(i) {
1046 int32_t expected = *i;
1047 memory[0] = expected;
1048 CHECK_EQ(expected, r.Call());
1049 }
1050 }
1051
WASM_EXEC_TEST(VoidReturn1)1052 WASM_EXEC_TEST(VoidReturn1) {
1053 // We use a wrapper function because WasmRunner<void> does not exist.
1054
1055 // Build the test function.
1056 TestSignatures sigs;
1057 TestingModule module(execution_mode);
1058 WasmFunctionCompiler t(sigs.v_v(), &module);
1059 BUILD(t, kExprNop);
1060 uint32_t index = t.CompileAndAdd();
1061
1062 const int32_t kExpected = -414444;
1063 // Build the calling function.
1064 WasmRunner<int32_t> r(&module);
1065 BUILD(r, B2(WASM_CALL_FUNCTION0(index), WASM_I32V_3(kExpected)));
1066
1067 int32_t result = r.Call();
1068 CHECK_EQ(kExpected, result);
1069 }
1070
WASM_EXEC_TEST(VoidReturn2)1071 WASM_EXEC_TEST(VoidReturn2) {
1072 // We use a wrapper function because WasmRunner<void> does not exist.
1073 // Build the test function.
1074 TestSignatures sigs;
1075 TestingModule module(execution_mode);
1076 WasmFunctionCompiler t(sigs.v_v(), &module);
1077 BUILD(t, WASM_RETURN0);
1078 uint32_t index = t.CompileAndAdd();
1079
1080 const int32_t kExpected = -414444;
1081 // Build the calling function.
1082 WasmRunner<int32_t> r(&module);
1083 BUILD(r, B2(WASM_CALL_FUNCTION0(index), WASM_I32V_3(kExpected)));
1084
1085 int32_t result = r.Call();
1086 CHECK_EQ(kExpected, result);
1087 }
1088
WASM_EXEC_TEST(Block_empty)1089 WASM_EXEC_TEST(Block_empty) {
1090 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1091 BUILD(r, kExprBlock, kExprEnd, WASM_GET_LOCAL(0));
1092 FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
1093 }
1094
WASM_EXEC_TEST(Block_empty_br1)1095 WASM_EXEC_TEST(Block_empty_br1) {
1096 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1097 BUILD(r, B1(WASM_BR(0)), WASM_GET_LOCAL(0));
1098 FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
1099 }
1100
WASM_EXEC_TEST(Block_empty_brif1)1101 WASM_EXEC_TEST(Block_empty_brif1) {
1102 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1103 BUILD(r, B1(WASM_BR_IF(0, WASM_ZERO)), WASM_GET_LOCAL(0));
1104 FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
1105 }
1106
WASM_EXEC_TEST(Block_empty_brif2)1107 WASM_EXEC_TEST(Block_empty_brif2) {
1108 WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32(),
1109 MachineType::Uint32());
1110 BUILD(r, B1(WASM_BR_IF(0, WASM_GET_LOCAL(1))), WASM_GET_LOCAL(0));
1111 FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i, *i + 1)); }
1112 }
1113
WASM_EXEC_TEST(Block_br2)1114 WASM_EXEC_TEST(Block_br2) {
1115 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1116 BUILD(r, B1(WASM_BRV(0, WASM_GET_LOCAL(0))));
1117 FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
1118 }
1119
WASM_EXEC_TEST(Block_If_P)1120 WASM_EXEC_TEST(Block_If_P) {
1121 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1122 // { if (p0) return 51; return 52; }
1123 BUILD(r, B2( // --
1124 WASM_IF(WASM_GET_LOCAL(0), // --
1125 WASM_BRV(1, WASM_I8(51))), // --
1126 WASM_I8(52))); // --
1127 FOR_INT32_INPUTS(i) {
1128 int32_t expected = *i ? 51 : 52;
1129 CHECK_EQ(expected, r.Call(*i));
1130 }
1131 }
1132
WASM_EXEC_TEST(Loop_empty)1133 WASM_EXEC_TEST(Loop_empty) {
1134 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1135 BUILD(r, kExprLoop, kExprEnd, WASM_GET_LOCAL(0));
1136 FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
1137 }
1138
WASM_EXEC_TEST(Loop_empty_br1)1139 WASM_EXEC_TEST(Loop_empty_br1) {
1140 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1141 BUILD(r, WASM_LOOP(1, WASM_BR(1)), WASM_GET_LOCAL(0));
1142 FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
1143 }
1144
WASM_EXEC_TEST(Loop_empty_brif1)1145 WASM_EXEC_TEST(Loop_empty_brif1) {
1146 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1147 BUILD(r, WASM_LOOP(1, WASM_BR_IF(1, WASM_ZERO)), WASM_GET_LOCAL(0));
1148 FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
1149 }
1150
WASM_EXEC_TEST(Loop_empty_brif2)1151 WASM_EXEC_TEST(Loop_empty_brif2) {
1152 WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32(),
1153 MachineType::Uint32());
1154 BUILD(r, WASM_LOOP(1, WASM_BR_IF(1, WASM_GET_LOCAL(1))), WASM_GET_LOCAL(0));
1155 FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i, *i + 1)); }
1156 }
1157
WASM_EXEC_TEST(Block_BrIf_P)1158 WASM_EXEC_TEST(Block_BrIf_P) {
1159 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1160 BUILD(r, B2(WASM_BRV_IF(0, WASM_I8(51), WASM_GET_LOCAL(0)), WASM_I8(52)));
1161 FOR_INT32_INPUTS(i) {
1162 int32_t expected = *i ? 51 : 52;
1163 CHECK_EQ(expected, r.Call(*i));
1164 }
1165 }
1166
WASM_EXEC_TEST(Block_IfElse_P_assign)1167 WASM_EXEC_TEST(Block_IfElse_P_assign) {
1168 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1169 // { if (p0) p0 = 71; else p0 = 72; return p0; }
1170 BUILD(r, B2( // --
1171 WASM_IF_ELSE(WASM_GET_LOCAL(0), // --
1172 WASM_SET_LOCAL(0, WASM_I8(71)), // --
1173 WASM_SET_LOCAL(0, WASM_I8(72))), // --
1174 WASM_GET_LOCAL(0)));
1175 FOR_INT32_INPUTS(i) {
1176 int32_t expected = *i ? 71 : 72;
1177 CHECK_EQ(expected, r.Call(*i));
1178 }
1179 }
1180
WASM_EXEC_TEST(Block_IfElse_P_return)1181 WASM_EXEC_TEST(Block_IfElse_P_return) {
1182 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1183 // if (p0) return 81; else return 82;
1184 BUILD(r, // --
1185 WASM_IF_ELSE(WASM_GET_LOCAL(0), // --
1186 RET_I8(81), // --
1187 RET_I8(82))); // --
1188 FOR_INT32_INPUTS(i) {
1189 int32_t expected = *i ? 81 : 82;
1190 CHECK_EQ(expected, r.Call(*i));
1191 }
1192 }
1193
WASM_EXEC_TEST(Block_If_P_assign)1194 WASM_EXEC_TEST(Block_If_P_assign) {
1195 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1196 // { if (p0) p0 = 61; p0; }
1197 BUILD(r, WASM_BLOCK(
1198 2, WASM_IF(WASM_GET_LOCAL(0), WASM_SET_LOCAL(0, WASM_I8(61))),
1199 WASM_GET_LOCAL(0)));
1200 FOR_INT32_INPUTS(i) {
1201 int32_t expected = *i ? 61 : *i;
1202 CHECK_EQ(expected, r.Call(*i));
1203 }
1204 }
1205
WASM_EXEC_TEST(DanglingAssign)1206 WASM_EXEC_TEST(DanglingAssign) {
1207 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1208 // { return 0; p0 = 0; }
1209 BUILD(r, B2(RET_I8(99), WASM_SET_LOCAL(0, WASM_ZERO)));
1210 CHECK_EQ(99, r.Call(1));
1211 }
1212
WASM_EXEC_TEST(ExprIf_P)1213 WASM_EXEC_TEST(ExprIf_P) {
1214 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1215 // p0 ? 11 : 22;
1216 BUILD(r, WASM_IF_ELSE(WASM_GET_LOCAL(0), // --
1217 WASM_I8(11), // --
1218 WASM_I8(22))); // --
1219 FOR_INT32_INPUTS(i) {
1220 int32_t expected = *i ? 11 : 22;
1221 CHECK_EQ(expected, r.Call(*i));
1222 }
1223 }
1224
WASM_EXEC_TEST(ExprIf_P_fallthru)1225 WASM_EXEC_TEST(ExprIf_P_fallthru) {
1226 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1227 // p0 ? 11 : 22;
1228 BUILD(r, WASM_IF_ELSE(WASM_GET_LOCAL(0), // --
1229 WASM_I8(11), // --
1230 WASM_I8(22))); // --
1231 FOR_INT32_INPUTS(i) {
1232 int32_t expected = *i ? 11 : 22;
1233 CHECK_EQ(expected, r.Call(*i));
1234 }
1235 }
1236
WASM_EXEC_TEST(CountDown)1237 WASM_EXEC_TEST(CountDown) {
1238 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1239 BUILD(r,
1240 WASM_BLOCK(
1241 2, WASM_LOOP(
1242 1, WASM_IF(WASM_GET_LOCAL(0),
1243 WASM_BRV(1, WASM_SET_LOCAL(
1244 0, WASM_I32_SUB(WASM_GET_LOCAL(0),
1245 WASM_I8(1)))))),
1246 WASM_GET_LOCAL(0)));
1247 CHECK_EQ(0, r.Call(1));
1248 CHECK_EQ(0, r.Call(10));
1249 CHECK_EQ(0, r.Call(100));
1250 }
1251
WASM_EXEC_TEST(CountDown_fallthru)1252 WASM_EXEC_TEST(CountDown_fallthru) {
1253 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1254 BUILD(r,
1255 WASM_BLOCK(
1256 2, WASM_LOOP(3, WASM_IF(WASM_NOT(WASM_GET_LOCAL(0)), WASM_BREAK(1)),
1257 WASM_SET_LOCAL(
1258 0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(1))),
1259 WASM_CONTINUE(0)),
1260 WASM_GET_LOCAL(0)));
1261 CHECK_EQ(0, r.Call(1));
1262 CHECK_EQ(0, r.Call(10));
1263 CHECK_EQ(0, r.Call(100));
1264 }
1265
WASM_EXEC_TEST(WhileCountDown)1266 WASM_EXEC_TEST(WhileCountDown) {
1267 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1268 BUILD(r, WASM_BLOCK(
1269 2, WASM_WHILE(WASM_GET_LOCAL(0),
1270 WASM_SET_LOCAL(0, WASM_I32_SUB(WASM_GET_LOCAL(0),
1271 WASM_I8(1)))),
1272 WASM_GET_LOCAL(0)));
1273 CHECK_EQ(0, r.Call(1));
1274 CHECK_EQ(0, r.Call(10));
1275 CHECK_EQ(0, r.Call(100));
1276 }
1277
WASM_EXEC_TEST(Loop_if_break1)1278 WASM_EXEC_TEST(Loop_if_break1) {
1279 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1280 BUILD(r, B2(WASM_LOOP(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BREAK(1)),
1281 WASM_SET_LOCAL(0, WASM_I8(99))),
1282 WASM_GET_LOCAL(0)));
1283 CHECK_EQ(99, r.Call(0));
1284 CHECK_EQ(3, r.Call(3));
1285 CHECK_EQ(10000, r.Call(10000));
1286 CHECK_EQ(-29, r.Call(-29));
1287 }
1288
WASM_EXEC_TEST(Loop_if_break2)1289 WASM_EXEC_TEST(Loop_if_break2) {
1290 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1291 BUILD(r, B2(WASM_LOOP(2, WASM_BR_IF(1, WASM_GET_LOCAL(0)),
1292 WASM_SET_LOCAL(0, WASM_I8(99))),
1293 WASM_GET_LOCAL(0)));
1294 CHECK_EQ(99, r.Call(0));
1295 CHECK_EQ(3, r.Call(3));
1296 CHECK_EQ(10000, r.Call(10000));
1297 CHECK_EQ(-29, r.Call(-29));
1298 }
1299
WASM_EXEC_TEST(Loop_if_break_fallthru)1300 WASM_EXEC_TEST(Loop_if_break_fallthru) {
1301 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1302 BUILD(r, B1(WASM_LOOP(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BREAK(1)),
1303 WASM_SET_LOCAL(0, WASM_I8(93)))),
1304 WASM_GET_LOCAL(0));
1305 CHECK_EQ(93, r.Call(0));
1306 CHECK_EQ(3, r.Call(3));
1307 CHECK_EQ(10001, r.Call(10001));
1308 CHECK_EQ(-22, r.Call(-22));
1309 }
1310
WASM_EXEC_TEST(IfBreak1)1311 WASM_EXEC_TEST(IfBreak1) {
1312 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1313 BUILD(r, WASM_IF(WASM_GET_LOCAL(0), WASM_SEQ(WASM_BR(0), WASM_UNREACHABLE)),
1314 WASM_I8(91));
1315 CHECK_EQ(91, r.Call(0));
1316 CHECK_EQ(91, r.Call(1));
1317 CHECK_EQ(91, r.Call(-8734));
1318 }
1319
WASM_EXEC_TEST(IfBreak2)1320 WASM_EXEC_TEST(IfBreak2) {
1321 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1322 BUILD(r, WASM_IF(WASM_GET_LOCAL(0), WASM_SEQ(WASM_BR(0), RET_I8(77))),
1323 WASM_I8(81));
1324 CHECK_EQ(81, r.Call(0));
1325 CHECK_EQ(81, r.Call(1));
1326 CHECK_EQ(81, r.Call(-8734));
1327 }
1328
WASM_EXEC_TEST(LoadMemI32)1329 WASM_EXEC_TEST(LoadMemI32) {
1330 TestingModule module(execution_mode);
1331 int32_t* memory = module.AddMemoryElems<int32_t>(8);
1332 WasmRunner<int32_t> r(&module, MachineType::Int32());
1333 module.RandomizeMemory(1111);
1334
1335 BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_I8(0)));
1336
1337 memory[0] = 99999999;
1338 CHECK_EQ(99999999, r.Call(0));
1339
1340 memory[0] = 88888888;
1341 CHECK_EQ(88888888, r.Call(0));
1342
1343 memory[0] = 77777777;
1344 CHECK_EQ(77777777, r.Call(0));
1345 }
1346
WASM_EXEC_TEST(LoadMemI32_alignment)1347 WASM_EXEC_TEST(LoadMemI32_alignment) {
1348 TestingModule module(execution_mode);
1349 int32_t* memory = module.AddMemoryElems<int32_t>(8);
1350 for (byte alignment = 0; alignment <= 2; ++alignment) {
1351 WasmRunner<int32_t> r(&module, MachineType::Int32());
1352 module.RandomizeMemory(1111);
1353
1354 BUILD(r,
1355 WASM_LOAD_MEM_ALIGNMENT(MachineType::Int32(), WASM_I8(0), alignment));
1356
1357 memory[0] = 0x1a2b3c4d;
1358 CHECK_EQ(0x1a2b3c4d, r.Call(0));
1359
1360 memory[0] = 0x5e6f7a8b;
1361 CHECK_EQ(0x5e6f7a8b, r.Call(0));
1362
1363 memory[0] = 0x9ca0b1c2;
1364 CHECK_EQ(0x9ca0b1c2, r.Call(0));
1365 }
1366 }
1367
WASM_EXEC_TEST(LoadMemI32_oob)1368 WASM_EXEC_TEST(LoadMemI32_oob) {
1369 TestingModule module(execution_mode);
1370 int32_t* memory = module.AddMemoryElems<int32_t>(8);
1371 WasmRunner<int32_t> r(&module, MachineType::Uint32());
1372 module.RandomizeMemory(1111);
1373
1374 BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(0)));
1375
1376 memory[0] = 88888888;
1377 CHECK_EQ(88888888, r.Call(0u));
1378 for (uint32_t offset = 29; offset < 40; ++offset) {
1379 CHECK_TRAP(r.Call(offset));
1380 }
1381
1382 for (uint32_t offset = 0x80000000; offset < 0x80000010; ++offset) {
1383 CHECK_TRAP(r.Call(offset));
1384 }
1385 }
1386
WASM_EXEC_TEST(LoadMem_offset_oob)1387 WASM_EXEC_TEST(LoadMem_offset_oob) {
1388 TestingModule module(execution_mode);
1389 module.AddMemoryElems<int32_t>(8);
1390
1391 static const MachineType machineTypes[] = {
1392 MachineType::Int8(), MachineType::Uint8(), MachineType::Int16(),
1393 MachineType::Uint16(), MachineType::Int32(), MachineType::Uint32(),
1394 MachineType::Int64(), MachineType::Uint64(), MachineType::Float32(),
1395 MachineType::Float64()};
1396
1397 for (size_t m = 0; m < arraysize(machineTypes); ++m) {
1398 module.RandomizeMemory(1116 + static_cast<int>(m));
1399 WasmRunner<int32_t> r(&module, MachineType::Uint32());
1400 uint32_t boundary = 24 - WasmOpcodes::MemSize(machineTypes[m]);
1401
1402 BUILD(r, WASM_LOAD_MEM_OFFSET(machineTypes[m], 8, WASM_GET_LOCAL(0)),
1403 WASM_ZERO);
1404
1405 CHECK_EQ(0, r.Call(boundary)); // in bounds.
1406
1407 for (uint32_t offset = boundary + 1; offset < boundary + 19; ++offset) {
1408 CHECK_TRAP(r.Call(offset)); // out of bounds.
1409 }
1410 }
1411 }
1412
WASM_EXEC_TEST(LoadMemI32_offset)1413 WASM_EXEC_TEST(LoadMemI32_offset) {
1414 TestingModule module(execution_mode);
1415 int32_t* memory = module.AddMemoryElems<int32_t>(4);
1416 WasmRunner<int32_t> r(&module, MachineType::Int32());
1417 module.RandomizeMemory(1111);
1418
1419 BUILD(r, WASM_LOAD_MEM_OFFSET(MachineType::Int32(), 4, WASM_GET_LOCAL(0)));
1420
1421 memory[0] = 66666666;
1422 memory[1] = 77777777;
1423 memory[2] = 88888888;
1424 memory[3] = 99999999;
1425 CHECK_EQ(77777777, r.Call(0));
1426 CHECK_EQ(88888888, r.Call(4));
1427 CHECK_EQ(99999999, r.Call(8));
1428
1429 memory[0] = 11111111;
1430 memory[1] = 22222222;
1431 memory[2] = 33333333;
1432 memory[3] = 44444444;
1433 CHECK_EQ(22222222, r.Call(0));
1434 CHECK_EQ(33333333, r.Call(4));
1435 CHECK_EQ(44444444, r.Call(8));
1436 }
1437
WASM_EXEC_TEST(LoadMemI32_const_oob_misaligned)1438 WASM_EXEC_TEST(LoadMemI32_const_oob_misaligned) {
1439 const int kMemSize = 12;
1440 // TODO(titzer): Fix misaligned accesses on MIPS and re-enable.
1441 for (int offset = 0; offset < kMemSize + 5; ++offset) {
1442 for (int index = 0; index < kMemSize + 5; ++index) {
1443 TestingModule module(execution_mode);
1444 module.AddMemoryElems<byte>(kMemSize);
1445
1446 WasmRunner<int32_t> r(&module);
1447 module.RandomizeMemory();
1448
1449 BUILD(r,
1450 WASM_LOAD_MEM_OFFSET(MachineType::Int32(), offset, WASM_I8(index)));
1451
1452 if ((offset + index) <= (kMemSize - sizeof(int32_t))) {
1453 CHECK_EQ(module.raw_val_at<int32_t>(offset + index), r.Call());
1454 } else {
1455 CHECK_TRAP(r.Call());
1456 }
1457 }
1458 }
1459 }
1460
WASM_EXEC_TEST(LoadMemI32_const_oob)1461 WASM_EXEC_TEST(LoadMemI32_const_oob) {
1462 const int kMemSize = 24;
1463 for (int offset = 0; offset < kMemSize + 5; offset += 4) {
1464 for (int index = 0; index < kMemSize + 5; index += 4) {
1465 TestingModule module(execution_mode);
1466 module.AddMemoryElems<byte>(kMemSize);
1467
1468 WasmRunner<int32_t> r(&module);
1469 module.RandomizeMemory();
1470
1471 BUILD(r,
1472 WASM_LOAD_MEM_OFFSET(MachineType::Int32(), offset, WASM_I8(index)));
1473
1474 if ((offset + index) <= (kMemSize - sizeof(int32_t))) {
1475 CHECK_EQ(module.raw_val_at<int32_t>(offset + index), r.Call());
1476 } else {
1477 CHECK_TRAP(r.Call());
1478 }
1479 }
1480 }
1481 }
1482
WASM_EXEC_TEST(StoreMemI32_alignment)1483 WASM_EXEC_TEST(StoreMemI32_alignment) {
1484 TestingModule module(execution_mode);
1485 int32_t* memory = module.AddMemoryElems<int32_t>(4);
1486 const int32_t kWritten = 0x12345678;
1487
1488 for (byte i = 0; i <= 2; ++i) {
1489 WasmRunner<int32_t> r(&module, MachineType::Int32());
1490 BUILD(r, WASM_STORE_MEM_ALIGNMENT(MachineType::Int32(), WASM_ZERO, i,
1491 WASM_GET_LOCAL(0)));
1492 module.RandomizeMemory(1111);
1493 memory[0] = 0;
1494
1495 CHECK_EQ(kWritten, r.Call(kWritten));
1496 CHECK_EQ(kWritten, memory[0]);
1497 }
1498 }
1499
WASM_EXEC_TEST(StoreMemI32_offset)1500 WASM_EXEC_TEST(StoreMemI32_offset) {
1501 TestingModule module(execution_mode);
1502 int32_t* memory = module.AddMemoryElems<int32_t>(4);
1503 WasmRunner<int32_t> r(&module, MachineType::Int32());
1504 const int32_t kWritten = 0xaabbccdd;
1505
1506 BUILD(r, WASM_STORE_MEM_OFFSET(MachineType::Int32(), 4, WASM_GET_LOCAL(0),
1507 WASM_I32V_5(kWritten)));
1508
1509 for (int i = 0; i < 2; ++i) {
1510 module.RandomizeMemory(1111);
1511 memory[0] = 66666666;
1512 memory[1] = 77777777;
1513 memory[2] = 88888888;
1514 memory[3] = 99999999;
1515 CHECK_EQ(kWritten, r.Call(i * 4));
1516 CHECK_EQ(66666666, memory[0]);
1517 CHECK_EQ(i == 0 ? kWritten : 77777777, memory[1]);
1518 CHECK_EQ(i == 1 ? kWritten : 88888888, memory[2]);
1519 CHECK_EQ(i == 2 ? kWritten : 99999999, memory[3]);
1520 }
1521 }
1522
WASM_EXEC_TEST(StoreMem_offset_oob)1523 WASM_EXEC_TEST(StoreMem_offset_oob) {
1524 TestingModule module(execution_mode);
1525 byte* memory = module.AddMemoryElems<byte>(32);
1526
1527 // 64-bit cases are handled in test-run-wasm-64.cc
1528 static const MachineType machineTypes[] = {
1529 MachineType::Int8(), MachineType::Uint8(), MachineType::Int16(),
1530 MachineType::Uint16(), MachineType::Int32(), MachineType::Uint32(),
1531 MachineType::Float32(), MachineType::Float64()};
1532
1533 for (size_t m = 0; m < arraysize(machineTypes); ++m) {
1534 module.RandomizeMemory(1119 + static_cast<int>(m));
1535 WasmRunner<int32_t> r(&module, MachineType::Uint32());
1536
1537 BUILD(r, WASM_STORE_MEM_OFFSET(machineTypes[m], 8, WASM_GET_LOCAL(0),
1538 WASM_LOAD_MEM(machineTypes[m], WASM_ZERO)),
1539 WASM_ZERO);
1540
1541 byte memsize = WasmOpcodes::MemSize(machineTypes[m]);
1542 uint32_t boundary = 24 - memsize;
1543 CHECK_EQ(0, r.Call(boundary)); // in bounds.
1544 CHECK_EQ(0, memcmp(&memory[0], &memory[8 + boundary], memsize));
1545
1546 for (uint32_t offset = boundary + 1; offset < boundary + 19; ++offset) {
1547 CHECK_TRAP(r.Call(offset)); // out of bounds.
1548 }
1549 }
1550 }
1551
WASM_EXEC_TEST(LoadMemI32_P)1552 WASM_EXEC_TEST(LoadMemI32_P) {
1553 const int kNumElems = 8;
1554 TestingModule module(execution_mode);
1555 int32_t* memory = module.AddMemoryElems<int32_t>(kNumElems);
1556 WasmRunner<int32_t> r(&module, MachineType::Int32());
1557 module.RandomizeMemory(2222);
1558
1559 BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(0)));
1560
1561 for (int i = 0; i < kNumElems; ++i) {
1562 CHECK_EQ(memory[i], r.Call(i * 4));
1563 }
1564 }
1565
WASM_EXEC_TEST(MemI32_Sum)1566 WASM_EXEC_TEST(MemI32_Sum) {
1567 const int kNumElems = 20;
1568 TestingModule module(execution_mode);
1569 uint32_t* memory = module.AddMemoryElems<uint32_t>(kNumElems);
1570 WasmRunner<uint32_t> r(&module, MachineType::Int32());
1571 const byte kSum = r.AllocateLocal(kAstI32);
1572
1573 BUILD(r, WASM_BLOCK(
1574 2, WASM_WHILE(
1575 WASM_GET_LOCAL(0),
1576 WASM_BLOCK(
1577 2, WASM_SET_LOCAL(
1578 kSum, WASM_I32_ADD(
1579 WASM_GET_LOCAL(kSum),
1580 WASM_LOAD_MEM(MachineType::Int32(),
1581 WASM_GET_LOCAL(0)))),
1582 WASM_SET_LOCAL(
1583 0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(4))))),
1584 WASM_GET_LOCAL(1)));
1585
1586 // Run 4 trials.
1587 for (int i = 0; i < 3; ++i) {
1588 module.RandomizeMemory(i * 33);
1589 uint32_t expected = 0;
1590 for (size_t j = kNumElems - 1; j > 0; --j) {
1591 expected += memory[j];
1592 }
1593 uint32_t result = r.Call(4 * (kNumElems - 1));
1594 CHECK_EQ(expected, result);
1595 }
1596 }
1597
WASM_EXEC_TEST(CheckMachIntsZero)1598 WASM_EXEC_TEST(CheckMachIntsZero) {
1599 const int kNumElems = 55;
1600 TestingModule module(execution_mode);
1601 module.AddMemoryElems<uint32_t>(kNumElems);
1602 WasmRunner<uint32_t> r(&module, MachineType::Int32());
1603
1604 BUILD(r, kExprLoop, kExprGetLocal, 0, kExprIf, kExprGetLocal, 0,
1605 kExprI32LoadMem, 0, 0, kExprIf, kExprI8Const, 255, kExprReturn, ARITY_1,
1606 kExprEnd, kExprGetLocal, 0, kExprI8Const, 4, kExprI32Sub, kExprSetLocal,
1607 0, kExprBr, ARITY_1, DEPTH_0, kExprEnd, kExprEnd, kExprI8Const, 0);
1608
1609 module.BlankMemory();
1610 CHECK_EQ(0, r.Call((kNumElems - 1) * 4));
1611 }
1612
WASM_EXEC_TEST(MemF32_Sum)1613 WASM_EXEC_TEST(MemF32_Sum) {
1614 const int kSize = 5;
1615 TestingModule module(execution_mode);
1616 module.AddMemoryElems<float>(kSize);
1617 float* buffer = module.raw_mem_start<float>();
1618 buffer[0] = -99.25;
1619 buffer[1] = -888.25;
1620 buffer[2] = -77.25;
1621 buffer[3] = 66666.25;
1622 buffer[4] = 5555.25;
1623 WasmRunner<int32_t> r(&module, MachineType::Int32());
1624 const byte kSum = r.AllocateLocal(kAstF32);
1625
1626 BUILD(r, WASM_BLOCK(
1627 3, WASM_WHILE(
1628 WASM_GET_LOCAL(0),
1629 WASM_BLOCK(
1630 2, WASM_SET_LOCAL(
1631 kSum, WASM_F32_ADD(
1632 WASM_GET_LOCAL(kSum),
1633 WASM_LOAD_MEM(MachineType::Float32(),
1634 WASM_GET_LOCAL(0)))),
1635 WASM_SET_LOCAL(
1636 0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(4))))),
1637 WASM_STORE_MEM(MachineType::Float32(), WASM_ZERO,
1638 WASM_GET_LOCAL(kSum)),
1639 WASM_GET_LOCAL(0)));
1640
1641 CHECK_EQ(0, r.Call(4 * (kSize - 1)));
1642 CHECK_NE(-99.25, buffer[0]);
1643 CHECK_EQ(71256.0f, buffer[0]);
1644 }
1645
1646 template <typename T>
GenerateAndRunFold(WasmExecutionMode execution_mode,WasmOpcode binop,T * buffer,uint32_t size,LocalType astType,MachineType memType)1647 T GenerateAndRunFold(WasmExecutionMode execution_mode, WasmOpcode binop,
1648 T* buffer, uint32_t size, LocalType astType,
1649 MachineType memType) {
1650 TestingModule module(execution_mode);
1651 module.AddMemoryElems<T>(size);
1652 for (uint32_t i = 0; i < size; ++i) {
1653 module.raw_mem_start<T>()[i] = buffer[i];
1654 }
1655 WasmRunner<int32_t> r(&module, MachineType::Int32());
1656 const byte kAccum = r.AllocateLocal(astType);
1657
1658 BUILD(
1659 r,
1660 WASM_BLOCK(
1661 4, WASM_SET_LOCAL(kAccum, WASM_LOAD_MEM(memType, WASM_ZERO)),
1662 WASM_WHILE(
1663 WASM_GET_LOCAL(0),
1664 WASM_BLOCK(
1665 2, WASM_SET_LOCAL(
1666 kAccum,
1667 WASM_BINOP(binop, WASM_GET_LOCAL(kAccum),
1668 WASM_LOAD_MEM(memType, WASM_GET_LOCAL(0)))),
1669 WASM_SET_LOCAL(
1670 0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(sizeof(T)))))),
1671 WASM_STORE_MEM(memType, WASM_ZERO, WASM_GET_LOCAL(kAccum)),
1672 WASM_GET_LOCAL(0)));
1673 r.Call(static_cast<int>(sizeof(T) * (size - 1)));
1674 return module.raw_mem_at<double>(0);
1675 }
1676
WASM_EXEC_TEST(MemF64_Mul)1677 WASM_EXEC_TEST(MemF64_Mul) {
1678 const size_t kSize = 6;
1679 double buffer[kSize] = {1, 2, 2, 2, 2, 2};
1680 double result =
1681 GenerateAndRunFold<double>(execution_mode, kExprF64Mul, buffer, kSize,
1682 kAstF64, MachineType::Float64());
1683 CHECK_EQ(32, result);
1684 }
1685
WASM_EXEC_TEST(Build_Wasm_Infinite_Loop)1686 WASM_EXEC_TEST(Build_Wasm_Infinite_Loop) {
1687 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1688 // Only build the graph and compile, don't run.
1689 BUILD(r, WASM_INFINITE_LOOP);
1690 }
1691
WASM_EXEC_TEST(Build_Wasm_Infinite_Loop_effect)1692 WASM_EXEC_TEST(Build_Wasm_Infinite_Loop_effect) {
1693 TestingModule module(execution_mode);
1694 module.AddMemoryElems<int8_t>(16);
1695 WasmRunner<int32_t> r(&module, MachineType::Int32());
1696
1697 // Only build the graph and compile, don't run.
1698 BUILD(r, WASM_LOOP(1, WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO)));
1699 }
1700
WASM_EXEC_TEST(Unreachable0a)1701 WASM_EXEC_TEST(Unreachable0a) {
1702 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1703 BUILD(r, B2(WASM_BRV(0, WASM_I8(9)), RET(WASM_GET_LOCAL(0))));
1704 CHECK_EQ(9, r.Call(0));
1705 CHECK_EQ(9, r.Call(1));
1706 }
1707
WASM_EXEC_TEST(Unreachable0b)1708 WASM_EXEC_TEST(Unreachable0b) {
1709 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1710 BUILD(r, B2(WASM_BRV(0, WASM_I8(7)), WASM_UNREACHABLE));
1711 CHECK_EQ(7, r.Call(0));
1712 CHECK_EQ(7, r.Call(1));
1713 }
1714
TEST(Build_Wasm_Unreachable1)1715 TEST(Build_Wasm_Unreachable1) {
1716 WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32());
1717 BUILD(r, WASM_UNREACHABLE);
1718 }
1719
TEST(Build_Wasm_Unreachable2)1720 TEST(Build_Wasm_Unreachable2) {
1721 WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32());
1722 BUILD(r, WASM_UNREACHABLE, WASM_UNREACHABLE);
1723 }
1724
TEST(Build_Wasm_Unreachable3)1725 TEST(Build_Wasm_Unreachable3) {
1726 WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32());
1727 BUILD(r, WASM_UNREACHABLE, WASM_UNREACHABLE, WASM_UNREACHABLE);
1728 }
1729
TEST(Build_Wasm_UnreachableIf1)1730 TEST(Build_Wasm_UnreachableIf1) {
1731 WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32());
1732 BUILD(r, WASM_UNREACHABLE, WASM_IF(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)));
1733 }
1734
TEST(Build_Wasm_UnreachableIf2)1735 TEST(Build_Wasm_UnreachableIf2) {
1736 WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32());
1737 BUILD(r, WASM_UNREACHABLE,
1738 WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0), WASM_UNREACHABLE));
1739 }
1740
WASM_EXEC_TEST(Unreachable_Load)1741 WASM_EXEC_TEST(Unreachable_Load) {
1742 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1743 BUILD(r, B2(WASM_BRV(0, WASM_GET_LOCAL(0)),
1744 WASM_LOAD_MEM(MachineType::Int8(), WASM_GET_LOCAL(0))));
1745 CHECK_EQ(11, r.Call(11));
1746 CHECK_EQ(21, r.Call(21));
1747 }
1748
WASM_EXEC_TEST(Infinite_Loop_not_taken1)1749 WASM_EXEC_TEST(Infinite_Loop_not_taken1) {
1750 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1751 BUILD(r, B2(WASM_IF(WASM_GET_LOCAL(0), WASM_INFINITE_LOOP), WASM_I8(45)));
1752 // Run the code, but don't go into the infinite loop.
1753 CHECK_EQ(45, r.Call(0));
1754 }
1755
WASM_EXEC_TEST(Infinite_Loop_not_taken2)1756 WASM_EXEC_TEST(Infinite_Loop_not_taken2) {
1757 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1758 BUILD(r, B1(WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_BRV(1, WASM_I8(45)),
1759 WASM_INFINITE_LOOP)));
1760 // Run the code, but don't go into the infinite loop.
1761 CHECK_EQ(45, r.Call(1));
1762 }
1763
WASM_EXEC_TEST(Infinite_Loop_not_taken2_brif)1764 WASM_EXEC_TEST(Infinite_Loop_not_taken2_brif) {
1765 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
1766 BUILD(r,
1767 B2(WASM_BRV_IF(0, WASM_I8(45), WASM_GET_LOCAL(0)), WASM_INFINITE_LOOP));
1768 // Run the code, but don't go into the infinite loop.
1769 CHECK_EQ(45, r.Call(1));
1770 }
1771
TestBuildGraphForSimpleExpression(WasmOpcode opcode)1772 static void TestBuildGraphForSimpleExpression(WasmOpcode opcode) {
1773 Isolate* isolate = CcTest::InitIsolateOnce();
1774 Zone zone(isolate->allocator());
1775 HandleScope scope(isolate);
1776 // Enable all optional operators.
1777 CommonOperatorBuilder common(&zone);
1778 MachineOperatorBuilder machine(&zone, MachineType::PointerRepresentation(),
1779 MachineOperatorBuilder::kAllOptionalOps);
1780 Graph graph(&zone);
1781 JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine);
1782 FunctionSig* sig = WasmOpcodes::Signature(opcode);
1783
1784 if (sig->parameter_count() == 1) {
1785 byte code[] = {WASM_NO_LOCALS, kExprGetLocal, 0, static_cast<byte>(opcode)};
1786 TestBuildingGraph(&zone, &jsgraph, nullptr, sig, nullptr, code,
1787 code + arraysize(code));
1788 } else {
1789 CHECK_EQ(2, sig->parameter_count());
1790 byte code[] = {WASM_NO_LOCALS, kExprGetLocal, 0, kExprGetLocal, 1,
1791 static_cast<byte>(opcode)};
1792 TestBuildingGraph(&zone, &jsgraph, nullptr, sig, nullptr, code,
1793 code + arraysize(code));
1794 }
1795 }
1796
TEST(Build_Wasm_SimpleExprs)1797 TEST(Build_Wasm_SimpleExprs) {
1798 // Test that the decoder can build a graph for all supported simple expressions.
1799 #define GRAPH_BUILD_TEST(name, opcode, sig) \
1800 TestBuildGraphForSimpleExpression(kExpr##name);
1801
1802 FOREACH_SIMPLE_OPCODE(GRAPH_BUILD_TEST);
1803
1804 #undef GRAPH_BUILD_TEST
1805 }
1806
WASM_EXEC_TEST(Int32LoadInt8_signext)1807 WASM_EXEC_TEST(Int32LoadInt8_signext) {
1808 TestingModule module(execution_mode);
1809 const int kNumElems = 16;
1810 int8_t* memory = module.AddMemoryElems<int8_t>(kNumElems);
1811 module.RandomizeMemory();
1812 memory[0] = -1;
1813 WasmRunner<int32_t> r(&module, MachineType::Int32());
1814 BUILD(r, WASM_LOAD_MEM(MachineType::Int8(), WASM_GET_LOCAL(0)));
1815
1816 for (int i = 0; i < kNumElems; ++i) {
1817 CHECK_EQ(memory[i], r.Call(i));
1818 }
1819 }
1820
WASM_EXEC_TEST(Int32LoadInt8_zeroext)1821 WASM_EXEC_TEST(Int32LoadInt8_zeroext) {
1822 TestingModule module(execution_mode);
1823 const int kNumElems = 16;
1824 byte* memory = module.AddMemory(kNumElems);
1825 module.RandomizeMemory(77);
1826 memory[0] = 255;
1827 WasmRunner<int32_t> r(&module, MachineType::Int32());
1828 BUILD(r, WASM_LOAD_MEM(MachineType::Uint8(), WASM_GET_LOCAL(0)));
1829
1830 for (int i = 0; i < kNumElems; ++i) {
1831 CHECK_EQ(memory[i], r.Call(i));
1832 }
1833 }
1834
WASM_EXEC_TEST(Int32LoadInt16_signext)1835 WASM_EXEC_TEST(Int32LoadInt16_signext) {
1836 TestingModule module(execution_mode);
1837 const int kNumBytes = 16;
1838 byte* memory = module.AddMemory(kNumBytes);
1839 module.RandomizeMemory(888);
1840 memory[1] = 200;
1841 WasmRunner<int32_t> r(&module, MachineType::Int32());
1842 BUILD(r, WASM_LOAD_MEM(MachineType::Int16(), WASM_GET_LOCAL(0)));
1843
1844 for (int i = 0; i < kNumBytes; i += 2) {
1845 int32_t expected = memory[i] | (static_cast<int8_t>(memory[i + 1]) << 8);
1846 CHECK_EQ(expected, r.Call(i));
1847 }
1848 }
1849
WASM_EXEC_TEST(Int32LoadInt16_zeroext)1850 WASM_EXEC_TEST(Int32LoadInt16_zeroext) {
1851 TestingModule module(execution_mode);
1852 const int kNumBytes = 16;
1853 byte* memory = module.AddMemory(kNumBytes);
1854 module.RandomizeMemory(9999);
1855 memory[1] = 204;
1856 WasmRunner<int32_t> r(&module, MachineType::Int32());
1857 BUILD(r, WASM_LOAD_MEM(MachineType::Uint16(), WASM_GET_LOCAL(0)));
1858
1859 for (int i = 0; i < kNumBytes; i += 2) {
1860 int32_t expected = memory[i] | (memory[i + 1] << 8);
1861 CHECK_EQ(expected, r.Call(i));
1862 }
1863 }
1864
WASM_EXEC_TEST(Int32Global)1865 WASM_EXEC_TEST(Int32Global) {
1866 TestingModule module(execution_mode);
1867 int32_t* global = module.AddGlobal<int32_t>(MachineType::Int32());
1868 WasmRunner<int32_t> r(&module, MachineType::Int32());
1869 // global = global + p0
1870 BUILD(r, WASM_STORE_GLOBAL(
1871 0, WASM_I32_ADD(WASM_LOAD_GLOBAL(0), WASM_GET_LOCAL(0))));
1872
1873 *global = 116;
1874 for (int i = 9; i < 444444; i += 111111) {
1875 int32_t expected = *global + i;
1876 r.Call(i);
1877 CHECK_EQ(expected, *global);
1878 }
1879 }
1880
WASM_EXEC_TEST(Int32Globals_DontAlias)1881 WASM_EXEC_TEST(Int32Globals_DontAlias) {
1882 const int kNumGlobals = 3;
1883 TestingModule module(execution_mode);
1884 int32_t* globals[] = {module.AddGlobal<int32_t>(MachineType::Int32()),
1885 module.AddGlobal<int32_t>(MachineType::Int32()),
1886 module.AddGlobal<int32_t>(MachineType::Int32())};
1887
1888 for (int g = 0; g < kNumGlobals; ++g) {
1889 // global = global + p0
1890 WasmRunner<int32_t> r(&module, MachineType::Int32());
1891 BUILD(r, WASM_STORE_GLOBAL(
1892 g, WASM_I32_ADD(WASM_LOAD_GLOBAL(g), WASM_GET_LOCAL(0))));
1893
1894 // Check that reading/writing global number {g} doesn't alter the others.
1895 *globals[g] = 116 * g;
1896 int32_t before[kNumGlobals];
1897 for (int i = 9; i < 444444; i += 111113) {
1898 int32_t sum = *globals[g] + i;
1899 for (int j = 0; j < kNumGlobals; ++j) before[j] = *globals[j];
1900 r.Call(i);
1901 for (int j = 0; j < kNumGlobals; ++j) {
1902 int32_t expected = j == g ? sum : before[j];
1903 CHECK_EQ(expected, *globals[j]);
1904 }
1905 }
1906 }
1907 }
1908
WASM_EXEC_TEST(Float32Global)1909 WASM_EXEC_TEST(Float32Global) {
1910 TestingModule module(execution_mode);
1911 float* global = module.AddGlobal<float>(MachineType::Float32());
1912 WasmRunner<int32_t> r(&module, MachineType::Int32());
1913 // global = global + p0
1914 BUILD(r, B2(WASM_STORE_GLOBAL(
1915 0, WASM_F32_ADD(WASM_LOAD_GLOBAL(0),
1916 WASM_F32_SCONVERT_I32(WASM_GET_LOCAL(0)))),
1917 WASM_ZERO));
1918
1919 *global = 1.25;
1920 for (int i = 9; i < 4444; i += 1111) {
1921 volatile float expected = *global + i;
1922 r.Call(i);
1923 CHECK_EQ(expected, *global);
1924 }
1925 }
1926
WASM_EXEC_TEST(Float64Global)1927 WASM_EXEC_TEST(Float64Global) {
1928 TestingModule module(execution_mode);
1929 double* global = module.AddGlobal<double>(MachineType::Float64());
1930 WasmRunner<int32_t> r(&module, MachineType::Int32());
1931 // global = global + p0
1932 BUILD(r, B2(WASM_STORE_GLOBAL(
1933 0, WASM_F64_ADD(WASM_LOAD_GLOBAL(0),
1934 WASM_F64_SCONVERT_I32(WASM_GET_LOCAL(0)))),
1935 WASM_ZERO));
1936
1937 *global = 1.25;
1938 for (int i = 9; i < 4444; i += 1111) {
1939 volatile double expected = *global + i;
1940 r.Call(i);
1941 CHECK_EQ(expected, *global);
1942 }
1943 }
1944
WASM_EXEC_TEST(MixedGlobals)1945 WASM_EXEC_TEST(MixedGlobals) {
1946 TestingModule module(execution_mode);
1947 int32_t* unused = module.AddGlobal<int32_t>(MachineType::Int32());
1948 byte* memory = module.AddMemory(32);
1949
1950 int8_t* var_int8 = module.AddGlobal<int8_t>(MachineType::Int8());
1951 uint8_t* var_uint8 = module.AddGlobal<uint8_t>(MachineType::Uint8());
1952 int16_t* var_int16 = module.AddGlobal<int16_t>(MachineType::Int16());
1953 uint16_t* var_uint16 = module.AddGlobal<uint16_t>(MachineType::Uint16());
1954 int32_t* var_int32 = module.AddGlobal<int32_t>(MachineType::Int32());
1955 uint32_t* var_uint32 = module.AddGlobal<uint32_t>(MachineType::Uint32());
1956 float* var_float = module.AddGlobal<float>(MachineType::Float32());
1957 double* var_double = module.AddGlobal<double>(MachineType::Float64());
1958
1959 WasmRunner<int32_t> r(&module, MachineType::Int32());
1960
1961 BUILD(
1962 r,
1963 WASM_BLOCK(
1964 9,
1965 WASM_STORE_GLOBAL(1, WASM_LOAD_MEM(MachineType::Int8(), WASM_ZERO)),
1966 WASM_STORE_GLOBAL(2, WASM_LOAD_MEM(MachineType::Uint8(), WASM_ZERO)),
1967 WASM_STORE_GLOBAL(3, WASM_LOAD_MEM(MachineType::Int16(), WASM_ZERO)),
1968 WASM_STORE_GLOBAL(4, WASM_LOAD_MEM(MachineType::Uint16(), WASM_ZERO)),
1969 WASM_STORE_GLOBAL(5, WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO)),
1970 WASM_STORE_GLOBAL(6, WASM_LOAD_MEM(MachineType::Uint32(), WASM_ZERO)),
1971 WASM_STORE_GLOBAL(7,
1972 WASM_LOAD_MEM(MachineType::Float32(), WASM_ZERO)),
1973 WASM_STORE_GLOBAL(8,
1974 WASM_LOAD_MEM(MachineType::Float64(), WASM_ZERO)),
1975 WASM_ZERO));
1976
1977 memory[0] = 0xaa;
1978 memory[1] = 0xcc;
1979 memory[2] = 0x55;
1980 memory[3] = 0xee;
1981 memory[4] = 0x33;
1982 memory[5] = 0x22;
1983 memory[6] = 0x11;
1984 memory[7] = 0x99;
1985 r.Call(1);
1986
1987 CHECK(static_cast<int8_t>(0xaa) == *var_int8);
1988 CHECK(static_cast<uint8_t>(0xaa) == *var_uint8);
1989 CHECK(static_cast<int16_t>(0xccaa) == *var_int16);
1990 CHECK(static_cast<uint16_t>(0xccaa) == *var_uint16);
1991 CHECK(static_cast<int32_t>(0xee55ccaa) == *var_int32);
1992 CHECK(static_cast<uint32_t>(0xee55ccaa) == *var_uint32);
1993 CHECK(bit_cast<float>(0xee55ccaa) == *var_float);
1994 CHECK(bit_cast<double>(0x99112233ee55ccaaULL) == *var_double);
1995
1996 USE(unused);
1997 }
1998
WASM_EXEC_TEST(CallEmpty)1999 WASM_EXEC_TEST(CallEmpty) {
2000 const int32_t kExpected = -414444;
2001 // Build the target function.
2002 TestSignatures sigs;
2003 TestingModule module(execution_mode);
2004 WasmFunctionCompiler t(sigs.i_v(), &module);
2005 BUILD(t, WASM_I32V_3(kExpected));
2006 uint32_t index = t.CompileAndAdd();
2007
2008 // Build the calling function.
2009 WasmRunner<int32_t> r(&module);
2010 BUILD(r, WASM_CALL_FUNCTION0(index));
2011
2012 int32_t result = r.Call();
2013 CHECK_EQ(kExpected, result);
2014 }
2015
WASM_EXEC_TEST(CallF32StackParameter)2016 WASM_EXEC_TEST(CallF32StackParameter) {
2017 // Build the target function.
2018 LocalType param_types[20];
2019 for (int i = 0; i < 20; ++i) param_types[i] = kAstF32;
2020 FunctionSig sig(1, 19, param_types);
2021 TestingModule module(execution_mode);
2022 WasmFunctionCompiler t(&sig, &module);
2023 BUILD(t, WASM_GET_LOCAL(17));
2024 uint32_t index = t.CompileAndAdd();
2025
2026 // Build the calling function.
2027 WasmRunner<float> r(&module);
2028 BUILD(r, WASM_CALL_FUNCTIONN(
2029 19, index, WASM_F32(1.0f), WASM_F32(2.0f), WASM_F32(4.0f),
2030 WASM_F32(8.0f), WASM_F32(16.0f), WASM_F32(32.0f),
2031 WASM_F32(64.0f), WASM_F32(128.0f), WASM_F32(256.0f),
2032 WASM_F32(1.5f), WASM_F32(2.5f), WASM_F32(4.5f), WASM_F32(8.5f),
2033 WASM_F32(16.5f), WASM_F32(32.5f), WASM_F32(64.5f),
2034 WASM_F32(128.5f), WASM_F32(256.5f), WASM_F32(512.5f)));
2035
2036 float result = r.Call();
2037 CHECK_EQ(256.5f, result);
2038 }
2039
WASM_EXEC_TEST(CallF64StackParameter)2040 WASM_EXEC_TEST(CallF64StackParameter) {
2041 // Build the target function.
2042 LocalType param_types[20];
2043 for (int i = 0; i < 20; ++i) param_types[i] = kAstF64;
2044 FunctionSig sig(1, 19, param_types);
2045 TestingModule module(execution_mode);
2046 WasmFunctionCompiler t(&sig, &module);
2047 BUILD(t, WASM_GET_LOCAL(17));
2048 uint32_t index = t.CompileAndAdd();
2049
2050 // Build the calling function.
2051 WasmRunner<double> r(&module);
2052 BUILD(r, WASM_CALL_FUNCTIONN(19, index, WASM_F64(1.0), WASM_F64(2.0),
2053 WASM_F64(4.0), WASM_F64(8.0), WASM_F64(16.0),
2054 WASM_F64(32.0), WASM_F64(64.0), WASM_F64(128.0),
2055 WASM_F64(256.0), WASM_F64(1.5), WASM_F64(2.5),
2056 WASM_F64(4.5), WASM_F64(8.5), WASM_F64(16.5),
2057 WASM_F64(32.5), WASM_F64(64.5), WASM_F64(128.5),
2058 WASM_F64(256.5), WASM_F64(512.5)));
2059
2060 float result = r.Call();
2061 CHECK_EQ(256.5, result);
2062 }
2063
WASM_EXEC_TEST(CallVoid)2064 WASM_EXEC_TEST(CallVoid) {
2065 const byte kMemOffset = 8;
2066 const int32_t kElemNum = kMemOffset / sizeof(int32_t);
2067 const int32_t kExpected = -414444;
2068 // Build the target function.
2069 TestSignatures sigs;
2070 TestingModule module(execution_mode);
2071 module.AddMemory(16);
2072 module.RandomizeMemory();
2073 WasmFunctionCompiler t(sigs.v_v(), &module);
2074 BUILD(t, WASM_STORE_MEM(MachineType::Int32(), WASM_I8(kMemOffset),
2075 WASM_I32V_3(kExpected)));
2076 uint32_t index = t.CompileAndAdd();
2077
2078 // Build the calling function.
2079 WasmRunner<int32_t> r(&module);
2080 BUILD(r, WASM_CALL_FUNCTION0(index),
2081 WASM_LOAD_MEM(MachineType::Int32(), WASM_I8(kMemOffset)));
2082
2083 int32_t result = r.Call();
2084 CHECK_EQ(kExpected, result);
2085 CHECK_EQ(kExpected, module.raw_mem_start<int32_t>()[kElemNum]);
2086 }
2087
WASM_EXEC_TEST(Call_Int32Add)2088 WASM_EXEC_TEST(Call_Int32Add) {
2089 // Build the target function.
2090 TestSignatures sigs;
2091 TestingModule module(execution_mode);
2092 WasmFunctionCompiler t(sigs.i_ii(), &module);
2093 BUILD(t, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
2094 uint32_t index = t.CompileAndAdd();
2095
2096 // Build the caller function.
2097 WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32());
2098 BUILD(r, WASM_CALL_FUNCTION2(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
2099
2100 FOR_INT32_INPUTS(i) {
2101 FOR_INT32_INPUTS(j) {
2102 int32_t expected = static_cast<int32_t>(static_cast<uint32_t>(*i) +
2103 static_cast<uint32_t>(*j));
2104 CHECK_EQ(expected, r.Call(*i, *j));
2105 }
2106 }
2107 }
2108
WASM_EXEC_TEST(Call_Float32Sub)2109 WASM_EXEC_TEST(Call_Float32Sub) {
2110 TestSignatures sigs;
2111 TestingModule module(execution_mode);
2112 WasmFunctionCompiler t(sigs.f_ff(), &module);
2113
2114 // Build the target function.
2115 BUILD(t, WASM_F32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
2116 uint32_t index = t.CompileAndAdd();
2117
2118 // Builder the caller function.
2119 WasmRunner<float> r(&module, MachineType::Float32(), MachineType::Float32());
2120 BUILD(r, WASM_CALL_FUNCTION2(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
2121
2122 FOR_FLOAT32_INPUTS(i) {
2123 FOR_FLOAT32_INPUTS(j) { CHECK_FLOAT_EQ(*i - *j, r.Call(*i, *j)); }
2124 }
2125 }
2126
WASM_EXEC_TEST(Call_Float64Sub)2127 WASM_EXEC_TEST(Call_Float64Sub) {
2128 TestingModule module(execution_mode);
2129 double* memory = module.AddMemoryElems<double>(16);
2130 WasmRunner<int32_t> r(&module);
2131
2132 BUILD(r, WASM_BLOCK(
2133 2, WASM_STORE_MEM(
2134 MachineType::Float64(), WASM_ZERO,
2135 WASM_F64_SUB(
2136 WASM_LOAD_MEM(MachineType::Float64(), WASM_ZERO),
2137 WASM_LOAD_MEM(MachineType::Float64(), WASM_I8(8)))),
2138 WASM_I8(107)));
2139
2140 FOR_FLOAT64_INPUTS(i) {
2141 FOR_FLOAT64_INPUTS(j) {
2142 memory[0] = *i;
2143 memory[1] = *j;
2144 double expected = *i - *j;
2145 CHECK_EQ(107, r.Call());
2146 if (expected != expected) {
2147 CHECK(memory[0] != memory[0]);
2148 } else {
2149 CHECK_EQ(expected, memory[0]);
2150 }
2151 }
2152 }
2153 }
2154
2155 #define ADD_CODE(vec, ...) \
2156 do { \
2157 byte __buf[] = {__VA_ARGS__}; \
2158 for (size_t i = 0; i < sizeof(__buf); ++i) vec.push_back(__buf[i]); \
2159 } while (false)
2160
Run_WasmMixedCall_N(WasmExecutionMode execution_mode,int start)2161 static void Run_WasmMixedCall_N(WasmExecutionMode execution_mode, int start) {
2162 const int kExpected = 6333;
2163 const int kElemSize = 8;
2164 TestSignatures sigs;
2165
2166 // 64-bit cases handled in test-run-wasm-64.cc.
2167 static MachineType mixed[] = {
2168 MachineType::Int32(), MachineType::Float32(), MachineType::Float64(),
2169 MachineType::Float32(), MachineType::Int32(), MachineType::Float64(),
2170 MachineType::Float32(), MachineType::Float64(), MachineType::Int32(),
2171 MachineType::Int32(), MachineType::Int32()};
2172
2173 int num_params = static_cast<int>(arraysize(mixed)) - start;
2174 for (int which = 0; which < num_params; ++which) {
2175 v8::base::AccountingAllocator allocator;
2176 Zone zone(&allocator);
2177 TestingModule module(execution_mode);
2178 module.AddMemory(1024);
2179 MachineType* memtypes = &mixed[start];
2180 MachineType result = memtypes[which];
2181
2182 // =========================================================================
2183 // Build the selector function.
2184 // =========================================================================
2185 uint32_t index;
2186 FunctionSig::Builder b(&zone, 1, num_params);
2187 b.AddReturn(WasmOpcodes::LocalTypeFor(result));
2188 for (int i = 0; i < num_params; ++i) {
2189 b.AddParam(WasmOpcodes::LocalTypeFor(memtypes[i]));
2190 }
2191 WasmFunctionCompiler t(b.Build(), &module);
2192 BUILD(t, WASM_GET_LOCAL(which));
2193 index = t.CompileAndAdd();
2194
2195 // =========================================================================
2196 // Build the calling function.
2197 // =========================================================================
2198 WasmRunner<int32_t> r(&module);
2199 std::vector<byte> code;
2200
2201 // Load the offset for the store.
2202 ADD_CODE(code, WASM_ZERO);
2203
2204 // Load the arguments.
2205 for (int i = 0; i < num_params; ++i) {
2206 int offset = (i + 1) * kElemSize;
2207 ADD_CODE(code, WASM_LOAD_MEM(memtypes[i], WASM_I8(offset)));
2208 }
2209
2210 // Call the selector function.
2211 ADD_CODE(code, kExprCallFunction, static_cast<byte>(num_params),
2212 static_cast<byte>(index));
2213
2214 // Store the result in memory.
2215 ADD_CODE(code,
2216 static_cast<byte>(WasmOpcodes::LoadStoreOpcodeOf(result, true)),
2217 ZERO_ALIGNMENT, ZERO_OFFSET);
2218
2219 // Return the expected value.
2220 ADD_CODE(code, WASM_I32V_2(kExpected));
2221
2222 r.Build(&code[0], &code[0] + code.size());
2223
2224 // Run the code.
2225 for (int t = 0; t < 10; ++t) {
2226 module.RandomizeMemory();
2227 CHECK_EQ(kExpected, r.Call());
2228
2229 int size = WasmOpcodes::MemSize(result);
2230 for (int i = 0; i < size; ++i) {
2231 int base = (which + 1) * kElemSize;
2232 byte expected = module.raw_mem_at<byte>(base + i);
2233 byte result = module.raw_mem_at<byte>(i);
2234 CHECK_EQ(expected, result);
2235 }
2236 }
2237 }
2238 }
2239
WASM_EXEC_TEST(MixedCall_0)2240 WASM_EXEC_TEST(MixedCall_0) { Run_WasmMixedCall_N(execution_mode, 0); }
WASM_EXEC_TEST(MixedCall_1)2241 WASM_EXEC_TEST(MixedCall_1) { Run_WasmMixedCall_N(execution_mode, 1); }
WASM_EXEC_TEST(MixedCall_2)2242 WASM_EXEC_TEST(MixedCall_2) { Run_WasmMixedCall_N(execution_mode, 2); }
WASM_EXEC_TEST(MixedCall_3)2243 WASM_EXEC_TEST(MixedCall_3) { Run_WasmMixedCall_N(execution_mode, 3); }
2244
WASM_EXEC_TEST(AddCall)2245 WASM_EXEC_TEST(AddCall) {
2246 TestSignatures sigs;
2247 TestingModule module(execution_mode);
2248 WasmFunctionCompiler t1(sigs.i_ii(), &module);
2249 BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
2250 t1.CompileAndAdd();
2251
2252 WasmRunner<int32_t> r(&module, MachineType::Int32());
2253 byte local = r.AllocateLocal(kAstI32);
2254 BUILD(r, B2(WASM_SET_LOCAL(local, WASM_I8(99)),
2255 WASM_I32_ADD(
2256 WASM_CALL_FUNCTION2(t1.function_index(), WASM_GET_LOCAL(0),
2257 WASM_GET_LOCAL(0)),
2258 WASM_CALL_FUNCTION2(t1.function_index(), WASM_GET_LOCAL(1),
2259 WASM_GET_LOCAL(local)))));
2260
2261 CHECK_EQ(198, r.Call(0));
2262 CHECK_EQ(200, r.Call(1));
2263 CHECK_EQ(100, r.Call(-49));
2264 }
2265
WASM_EXEC_TEST(CountDown_expr)2266 WASM_EXEC_TEST(CountDown_expr) {
2267 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
2268 BUILD(r, WASM_LOOP(
2269 3, WASM_IF(WASM_NOT(WASM_GET_LOCAL(0)),
2270 WASM_BREAKV(1, WASM_GET_LOCAL(0))),
2271 WASM_SET_LOCAL(0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(1))),
2272 WASM_CONTINUE(0)));
2273 CHECK_EQ(0, r.Call(1));
2274 CHECK_EQ(0, r.Call(10));
2275 CHECK_EQ(0, r.Call(100));
2276 }
2277
WASM_EXEC_TEST(ExprBlock2a)2278 WASM_EXEC_TEST(ExprBlock2a) {
2279 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
2280 BUILD(r, B2(WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(1, WASM_I8(1))), WASM_I8(1)));
2281 CHECK_EQ(1, r.Call(0));
2282 CHECK_EQ(1, r.Call(1));
2283 }
2284
WASM_EXEC_TEST(ExprBlock2b)2285 WASM_EXEC_TEST(ExprBlock2b) {
2286 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
2287 BUILD(r, B2(WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(1, WASM_I8(1))), WASM_I8(2)));
2288 CHECK_EQ(2, r.Call(0));
2289 CHECK_EQ(1, r.Call(1));
2290 }
2291
WASM_EXEC_TEST(ExprBlock2c)2292 WASM_EXEC_TEST(ExprBlock2c) {
2293 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
2294 BUILD(r, B2(WASM_BRV_IF(0, WASM_I8(1), WASM_GET_LOCAL(0)), WASM_I8(1)));
2295 CHECK_EQ(1, r.Call(0));
2296 CHECK_EQ(1, r.Call(1));
2297 }
2298
WASM_EXEC_TEST(ExprBlock2d)2299 WASM_EXEC_TEST(ExprBlock2d) {
2300 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
2301 BUILD(r, B2(WASM_BRV_IF(0, WASM_I8(1), WASM_GET_LOCAL(0)), WASM_I8(2)));
2302 CHECK_EQ(2, r.Call(0));
2303 CHECK_EQ(1, r.Call(1));
2304 }
2305
WASM_EXEC_TEST(ExprBlock_ManualSwitch)2306 WASM_EXEC_TEST(ExprBlock_ManualSwitch) {
2307 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
2308 BUILD(r, WASM_BLOCK(6, WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(1)),
2309 WASM_BRV(1, WASM_I8(11))),
2310 WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(2)),
2311 WASM_BRV(1, WASM_I8(12))),
2312 WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(3)),
2313 WASM_BRV(1, WASM_I8(13))),
2314 WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(4)),
2315 WASM_BRV(1, WASM_I8(14))),
2316 WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(5)),
2317 WASM_BRV(1, WASM_I8(15))),
2318 WASM_I8(99)));
2319 CHECK_EQ(99, r.Call(0));
2320 CHECK_EQ(11, r.Call(1));
2321 CHECK_EQ(12, r.Call(2));
2322 CHECK_EQ(13, r.Call(3));
2323 CHECK_EQ(14, r.Call(4));
2324 CHECK_EQ(15, r.Call(5));
2325 CHECK_EQ(99, r.Call(6));
2326 }
2327
WASM_EXEC_TEST(ExprBlock_ManualSwitch_brif)2328 WASM_EXEC_TEST(ExprBlock_ManualSwitch_brif) {
2329 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
2330 BUILD(r,
2331 WASM_BLOCK(6, WASM_BRV_IF(0, WASM_I8(11),
2332 WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(1))),
2333 WASM_BRV_IF(0, WASM_I8(12),
2334 WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(2))),
2335 WASM_BRV_IF(0, WASM_I8(13),
2336 WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(3))),
2337 WASM_BRV_IF(0, WASM_I8(14),
2338 WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(4))),
2339 WASM_BRV_IF(0, WASM_I8(15),
2340 WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(5))),
2341 WASM_I8(99)));
2342 CHECK_EQ(99, r.Call(0));
2343 CHECK_EQ(11, r.Call(1));
2344 CHECK_EQ(12, r.Call(2));
2345 CHECK_EQ(13, r.Call(3));
2346 CHECK_EQ(14, r.Call(4));
2347 CHECK_EQ(15, r.Call(5));
2348 CHECK_EQ(99, r.Call(6));
2349 }
2350
WASM_EXEC_TEST(nested_ifs)2351 WASM_EXEC_TEST(nested_ifs) {
2352 WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
2353 MachineType::Int32());
2354
2355 BUILD(r, WASM_IF_ELSE(
2356 WASM_GET_LOCAL(0),
2357 WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_I8(11), WASM_I8(12)),
2358 WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_I8(13), WASM_I8(14))));
2359
2360 CHECK_EQ(11, r.Call(1, 1));
2361 CHECK_EQ(12, r.Call(1, 0));
2362 CHECK_EQ(13, r.Call(0, 1));
2363 CHECK_EQ(14, r.Call(0, 0));
2364 }
2365
WASM_EXEC_TEST(ExprBlock_if)2366 WASM_EXEC_TEST(ExprBlock_if) {
2367 WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
2368
2369 BUILD(r, B1(WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(11)),
2370 WASM_BRV(1, WASM_I8(14)))));
2371
2372 CHECK_EQ(11, r.Call(1));
2373 CHECK_EQ(14, r.Call(0));
2374 }
2375
WASM_EXEC_TEST(ExprBlock_nested_ifs)2376 WASM_EXEC_TEST(ExprBlock_nested_ifs) {
2377 WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
2378 MachineType::Int32());
2379
2380 BUILD(r, WASM_BLOCK(
2381 1, WASM_IF_ELSE(
2382 WASM_GET_LOCAL(0),
2383 WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_BRV(0, WASM_I8(11)),
2384 WASM_BRV(1, WASM_I8(12))),
2385 WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_BRV(0, WASM_I8(13)),
2386 WASM_BRV(1, WASM_I8(14))))));
2387
2388 CHECK_EQ(11, r.Call(1, 1));
2389 CHECK_EQ(12, r.Call(1, 0));
2390 CHECK_EQ(13, r.Call(0, 1));
2391 CHECK_EQ(14, r.Call(0, 0));
2392 }
2393
WASM_EXEC_TEST(ExprLoop_nested_ifs)2394 WASM_EXEC_TEST(ExprLoop_nested_ifs) {
2395 WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
2396 MachineType::Int32());
2397
2398 BUILD(r, WASM_LOOP(
2399 1, WASM_IF_ELSE(
2400 WASM_GET_LOCAL(0),
2401 WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_BRV(1, WASM_I8(11)),
2402 WASM_BRV(3, WASM_I8(12))),
2403 WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_BRV(1, WASM_I8(13)),
2404 WASM_BRV(3, WASM_I8(14))))));
2405
2406 CHECK_EQ(11, r.Call(1, 1));
2407 CHECK_EQ(12, r.Call(1, 0));
2408 CHECK_EQ(13, r.Call(0, 1));
2409 CHECK_EQ(14, r.Call(0, 0));
2410 }
2411
WASM_EXEC_TEST(SimpleCallIndirect)2412 WASM_EXEC_TEST(SimpleCallIndirect) {
2413 TestSignatures sigs;
2414 TestingModule module(execution_mode);
2415
2416 WasmFunctionCompiler t1(sigs.i_ii(), &module);
2417 BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
2418 t1.CompileAndAdd(/*sig_index*/ 1);
2419
2420 WasmFunctionCompiler t2(sigs.i_ii(), &module);
2421 BUILD(t2, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
2422 t2.CompileAndAdd(/*sig_index*/ 1);
2423
2424 // Signature table.
2425 module.AddSignature(sigs.f_ff());
2426 module.AddSignature(sigs.i_ii());
2427 module.AddSignature(sigs.d_dd());
2428
2429 // Function table.
2430 int table[] = {0, 1};
2431 module.AddIndirectFunctionTable(table, 2);
2432 module.PopulateIndirectFunctionTable();
2433
2434 // Builder the caller function.
2435 WasmRunner<int32_t> r(&module, MachineType::Int32());
2436 BUILD(r, WASM_CALL_INDIRECT2(1, WASM_GET_LOCAL(0), WASM_I8(66), WASM_I8(22)));
2437
2438 CHECK_EQ(88, r.Call(0));
2439 CHECK_EQ(44, r.Call(1));
2440 CHECK_TRAP(r.Call(2));
2441 }
2442
WASM_EXEC_TEST(MultipleCallIndirect)2443 WASM_EXEC_TEST(MultipleCallIndirect) {
2444 TestSignatures sigs;
2445 TestingModule module(execution_mode);
2446
2447 WasmFunctionCompiler t1(sigs.i_ii(), &module);
2448 BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
2449 t1.CompileAndAdd(/*sig_index*/ 1);
2450
2451 WasmFunctionCompiler t2(sigs.i_ii(), &module);
2452 BUILD(t2, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
2453 t2.CompileAndAdd(/*sig_index*/ 1);
2454
2455 // Signature table.
2456 module.AddSignature(sigs.f_ff());
2457 module.AddSignature(sigs.i_ii());
2458 module.AddSignature(sigs.d_dd());
2459
2460 // Function table.
2461 int table[] = {0, 1};
2462 module.AddIndirectFunctionTable(table, 2);
2463 module.PopulateIndirectFunctionTable();
2464
2465 // Builder the caller function.
2466 WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32(),
2467 MachineType::Int32());
2468 BUILD(r, WASM_I32_ADD(
2469 WASM_CALL_INDIRECT2(1, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1),
2470 WASM_GET_LOCAL(2)),
2471 WASM_CALL_INDIRECT2(1, WASM_GET_LOCAL(1), WASM_GET_LOCAL(2),
2472 WASM_GET_LOCAL(0))));
2473
2474 CHECK_EQ(5, r.Call(0, 1, 2));
2475 CHECK_EQ(19, r.Call(0, 1, 9));
2476 CHECK_EQ(1, r.Call(1, 0, 2));
2477 CHECK_EQ(1, r.Call(1, 0, 9));
2478
2479 CHECK_TRAP(r.Call(0, 2, 1));
2480 CHECK_TRAP(r.Call(1, 2, 0));
2481 CHECK_TRAP(r.Call(2, 0, 1));
2482 CHECK_TRAP(r.Call(2, 1, 0));
2483 }
2484
WASM_EXEC_TEST(CallIndirect_NoTable)2485 WASM_EXEC_TEST(CallIndirect_NoTable) {
2486 TestSignatures sigs;
2487 TestingModule module(execution_mode);
2488
2489 // One function.
2490 WasmFunctionCompiler t1(sigs.i_ii(), &module);
2491 BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
2492 t1.CompileAndAdd(/*sig_index*/ 1);
2493
2494 // Signature table.
2495 module.AddSignature(sigs.f_ff());
2496 module.AddSignature(sigs.i_ii());
2497
2498 // Builder the caller function.
2499 WasmRunner<int32_t> r(&module, MachineType::Int32());
2500 BUILD(r, WASM_CALL_INDIRECT2(1, WASM_GET_LOCAL(0), WASM_I8(66), WASM_I8(22)));
2501
2502 CHECK_TRAP(r.Call(0));
2503 CHECK_TRAP(r.Call(1));
2504 CHECK_TRAP(r.Call(2));
2505 }
2506
WASM_EXEC_TEST(F32Floor)2507 WASM_EXEC_TEST(F32Floor) {
2508 WasmRunner<float> r(execution_mode, MachineType::Float32());
2509 BUILD(r, WASM_F32_FLOOR(WASM_GET_LOCAL(0)));
2510
2511 FOR_FLOAT32_INPUTS(i) { CHECK_FLOAT_EQ(floorf(*i), r.Call(*i)); }
2512 }
2513
WASM_EXEC_TEST(F32Ceil)2514 WASM_EXEC_TEST(F32Ceil) {
2515 WasmRunner<float> r(execution_mode, MachineType::Float32());
2516 BUILD(r, WASM_F32_CEIL(WASM_GET_LOCAL(0)));
2517
2518 FOR_FLOAT32_INPUTS(i) { CHECK_FLOAT_EQ(ceilf(*i), r.Call(*i)); }
2519 }
2520
WASM_EXEC_TEST(F32Trunc)2521 WASM_EXEC_TEST(F32Trunc) {
2522 WasmRunner<float> r(execution_mode, MachineType::Float32());
2523 BUILD(r, WASM_F32_TRUNC(WASM_GET_LOCAL(0)));
2524
2525 FOR_FLOAT32_INPUTS(i) { CHECK_FLOAT_EQ(truncf(*i), r.Call(*i)); }
2526 }
2527
WASM_EXEC_TEST(F32NearestInt)2528 WASM_EXEC_TEST(F32NearestInt) {
2529 WasmRunner<float> r(execution_mode, MachineType::Float32());
2530 BUILD(r, WASM_F32_NEARESTINT(WASM_GET_LOCAL(0)));
2531
2532 FOR_FLOAT32_INPUTS(i) { CHECK_FLOAT_EQ(nearbyintf(*i), r.Call(*i)); }
2533 }
2534
WASM_EXEC_TEST(F64Floor)2535 WASM_EXEC_TEST(F64Floor) {
2536 WasmRunner<double> r(execution_mode, MachineType::Float64());
2537 BUILD(r, WASM_F64_FLOOR(WASM_GET_LOCAL(0)));
2538
2539 FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(floor(*i), r.Call(*i)); }
2540 }
2541
WASM_EXEC_TEST(F64Ceil)2542 WASM_EXEC_TEST(F64Ceil) {
2543 WasmRunner<double> r(execution_mode, MachineType::Float64());
2544 BUILD(r, WASM_F64_CEIL(WASM_GET_LOCAL(0)));
2545
2546 FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ceil(*i), r.Call(*i)); }
2547 }
2548
WASM_EXEC_TEST(F64Trunc)2549 WASM_EXEC_TEST(F64Trunc) {
2550 WasmRunner<double> r(execution_mode, MachineType::Float64());
2551 BUILD(r, WASM_F64_TRUNC(WASM_GET_LOCAL(0)));
2552
2553 FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(trunc(*i), r.Call(*i)); }
2554 }
2555
WASM_EXEC_TEST(F64NearestInt)2556 WASM_EXEC_TEST(F64NearestInt) {
2557 WasmRunner<double> r(execution_mode, MachineType::Float64());
2558 BUILD(r, WASM_F64_NEARESTINT(WASM_GET_LOCAL(0)));
2559
2560 FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(nearbyint(*i), r.Call(*i)); }
2561 }
2562
WASM_EXEC_TEST(F32Min)2563 WASM_EXEC_TEST(F32Min) {
2564 WasmRunner<float> r(execution_mode, MachineType::Float32(),
2565 MachineType::Float32());
2566 BUILD(r, WASM_F32_MIN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
2567
2568 FOR_FLOAT32_INPUTS(i) {
2569 FOR_FLOAT32_INPUTS(j) {
2570 float expected;
2571 if (*i < *j) {
2572 expected = *i;
2573 } else if (*j < *i) {
2574 expected = *j;
2575 } else if (*i != *i) {
2576 // If *i or *j is NaN, then the result is NaN.
2577 expected = *i;
2578 } else {
2579 expected = *j;
2580 }
2581
2582 CHECK_FLOAT_EQ(expected, r.Call(*i, *j));
2583 }
2584 }
2585 }
2586
WASM_EXEC_TEST(F64Min)2587 WASM_EXEC_TEST(F64Min) {
2588 WasmRunner<double> r(execution_mode, MachineType::Float64(),
2589 MachineType::Float64());
2590 BUILD(r, WASM_F64_MIN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
2591
2592 FOR_FLOAT64_INPUTS(i) {
2593 FOR_FLOAT64_INPUTS(j) {
2594 double expected;
2595 if (*i < *j) {
2596 expected = *i;
2597 } else if (*j < *i) {
2598 expected = *j;
2599 } else if (*i != *i) {
2600 // If *i or *j is NaN, then the result is NaN.
2601 expected = *i;
2602 } else {
2603 expected = *j;
2604 }
2605
2606 CHECK_DOUBLE_EQ(expected, r.Call(*i, *j));
2607 }
2608 }
2609 }
2610
WASM_EXEC_TEST(F32Max)2611 WASM_EXEC_TEST(F32Max) {
2612 WasmRunner<float> r(execution_mode, MachineType::Float32(),
2613 MachineType::Float32());
2614 BUILD(r, WASM_F32_MAX(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
2615
2616 FOR_FLOAT32_INPUTS(i) {
2617 FOR_FLOAT32_INPUTS(j) {
2618 float expected;
2619 if (*i > *j) {
2620 expected = *i;
2621 } else if (*j > *i) {
2622 expected = *j;
2623 } else if (*i != *i) {
2624 // If *i or *j is NaN, then the result is NaN.
2625 expected = *i;
2626 } else {
2627 expected = *j;
2628 }
2629
2630 CHECK_FLOAT_EQ(expected, r.Call(*i, *j));
2631 }
2632 }
2633 }
2634
WASM_EXEC_TEST(F64Max)2635 WASM_EXEC_TEST(F64Max) {
2636 WasmRunner<double> r(execution_mode, MachineType::Float64(),
2637 MachineType::Float64());
2638 BUILD(r, WASM_F64_MAX(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
2639
2640 FOR_FLOAT64_INPUTS(i) {
2641 FOR_FLOAT64_INPUTS(j) {
2642 double expected;
2643 if (*i > *j) {
2644 expected = *i;
2645 } else if (*j > *i) {
2646 expected = *j;
2647 } else if (*i != *i) {
2648 // If *i or *j is NaN, then the result is NaN.
2649 expected = *i;
2650 } else {
2651 expected = *j;
2652 }
2653
2654 CHECK_DOUBLE_EQ(expected, r.Call(*i, *j));
2655 }
2656 }
2657 }
2658
2659 // TODO(ahaas): Fix on mips and reenable.
2660 #if !V8_TARGET_ARCH_MIPS && !V8_TARGET_ARCH_MIPS64
2661
WASM_EXEC_TEST(F32Min_Snan)2662 WASM_EXEC_TEST(F32Min_Snan) {
2663 // Test that the instruction does not return a signalling NaN.
2664 {
2665 WasmRunner<float> r(execution_mode);
2666 BUILD(r,
2667 WASM_F32_MIN(WASM_F32(bit_cast<float>(0xff80f1e2)), WASM_F32(57.67)));
2668 CHECK_EQ(0xffc0f1e2, bit_cast<uint32_t>(r.Call()));
2669 }
2670 {
2671 WasmRunner<float> r(execution_mode);
2672 BUILD(r,
2673 WASM_F32_MIN(WASM_F32(45.73), WASM_F32(bit_cast<float>(0x7f80f1e2))));
2674 CHECK_EQ(0x7fc0f1e2, bit_cast<uint32_t>(r.Call()));
2675 }
2676 }
2677
WASM_EXEC_TEST(F32Max_Snan)2678 WASM_EXEC_TEST(F32Max_Snan) {
2679 // Test that the instruction does not return a signalling NaN.
2680 {
2681 WasmRunner<float> r(execution_mode);
2682 BUILD(r,
2683 WASM_F32_MAX(WASM_F32(bit_cast<float>(0xff80f1e2)), WASM_F32(57.67)));
2684 CHECK_EQ(0xffc0f1e2, bit_cast<uint32_t>(r.Call()));
2685 }
2686 {
2687 WasmRunner<float> r(execution_mode);
2688 BUILD(r,
2689 WASM_F32_MAX(WASM_F32(45.73), WASM_F32(bit_cast<float>(0x7f80f1e2))));
2690 CHECK_EQ(0x7fc0f1e2, bit_cast<uint32_t>(r.Call()));
2691 }
2692 }
2693
WASM_EXEC_TEST(F64Min_Snan)2694 WASM_EXEC_TEST(F64Min_Snan) {
2695 // Test that the instruction does not return a signalling NaN.
2696 {
2697 WasmRunner<double> r(execution_mode);
2698 BUILD(r, WASM_F64_MIN(WASM_F64(bit_cast<double>(0xfff000000000f1e2)),
2699 WASM_F64(57.67)));
2700 CHECK_EQ(0xfff800000000f1e2, bit_cast<uint64_t>(r.Call()));
2701 }
2702 {
2703 WasmRunner<double> r(execution_mode);
2704 BUILD(r, WASM_F64_MIN(WASM_F64(45.73),
2705 WASM_F64(bit_cast<double>(0x7ff000000000f1e2))));
2706 CHECK_EQ(0x7ff800000000f1e2, bit_cast<uint64_t>(r.Call()));
2707 }
2708 }
2709
WASM_EXEC_TEST(F64Max_Snan)2710 WASM_EXEC_TEST(F64Max_Snan) {
2711 // Test that the instruction does not return a signalling NaN.
2712 {
2713 WasmRunner<double> r(execution_mode);
2714 BUILD(r, WASM_F64_MAX(WASM_F64(bit_cast<double>(0xfff000000000f1e2)),
2715 WASM_F64(57.67)));
2716 CHECK_EQ(0xfff800000000f1e2, bit_cast<uint64_t>(r.Call()));
2717 }
2718 {
2719 WasmRunner<double> r(execution_mode);
2720 BUILD(r, WASM_F64_MAX(WASM_F64(45.73),
2721 WASM_F64(bit_cast<double>(0x7ff000000000f1e2))));
2722 CHECK_EQ(0x7ff800000000f1e2, bit_cast<uint64_t>(r.Call()));
2723 }
2724 }
2725
2726 #endif
2727
WASM_EXEC_TEST(I32SConvertF32)2728 WASM_EXEC_TEST(I32SConvertF32) {
2729 WasmRunner<int32_t> r(execution_mode, MachineType::Float32());
2730 BUILD(r, WASM_I32_SCONVERT_F32(WASM_GET_LOCAL(0)));
2731
2732 FOR_FLOAT32_INPUTS(i) {
2733 if (*i < static_cast<float>(INT32_MAX) &&
2734 *i >= static_cast<float>(INT32_MIN)) {
2735 CHECK_EQ(static_cast<int32_t>(*i), r.Call(*i));
2736 } else {
2737 CHECK_TRAP32(r.Call(*i));
2738 }
2739 }
2740 }
2741
WASM_EXEC_TEST(I32SConvertF64)2742 WASM_EXEC_TEST(I32SConvertF64) {
2743 WasmRunner<int32_t> r(execution_mode, MachineType::Float64());
2744 BUILD(r, WASM_I32_SCONVERT_F64(WASM_GET_LOCAL(0)));
2745
2746 FOR_FLOAT64_INPUTS(i) {
2747 if (*i < (static_cast<double>(INT32_MAX) + 1.0) &&
2748 *i > (static_cast<double>(INT32_MIN) - 1.0)) {
2749 CHECK_EQ(static_cast<int64_t>(*i), r.Call(*i));
2750 } else {
2751 CHECK_TRAP32(r.Call(*i));
2752 }
2753 }
2754 }
2755
WASM_EXEC_TEST(I32UConvertF32)2756 WASM_EXEC_TEST(I32UConvertF32) {
2757 WasmRunner<uint32_t> r(execution_mode, MachineType::Float32());
2758 BUILD(r, WASM_I32_UCONVERT_F32(WASM_GET_LOCAL(0)));
2759
2760 FOR_FLOAT32_INPUTS(i) {
2761 if (*i < (static_cast<float>(UINT32_MAX) + 1.0) && *i > -1) {
2762 CHECK_EQ(static_cast<uint32_t>(*i), r.Call(*i));
2763 } else {
2764 CHECK_TRAP32(r.Call(*i));
2765 }
2766 }
2767 }
2768
WASM_EXEC_TEST(I32UConvertF64)2769 WASM_EXEC_TEST(I32UConvertF64) {
2770 WasmRunner<uint32_t> r(execution_mode, MachineType::Float64());
2771 BUILD(r, WASM_I32_UCONVERT_F64(WASM_GET_LOCAL(0)));
2772
2773 FOR_FLOAT64_INPUTS(i) {
2774 if (*i < (static_cast<float>(UINT32_MAX) + 1.0) && *i > -1) {
2775 CHECK_EQ(static_cast<uint32_t>(*i), r.Call(*i));
2776 } else {
2777 CHECK_TRAP32(r.Call(*i));
2778 }
2779 }
2780 }
2781
WASM_EXEC_TEST(F64CopySign)2782 WASM_EXEC_TEST(F64CopySign) {
2783 WasmRunner<double> r(execution_mode, MachineType::Float64(),
2784 MachineType::Float64());
2785 BUILD(r, WASM_F64_COPYSIGN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
2786
2787 FOR_FLOAT64_INPUTS(i) {
2788 FOR_FLOAT64_INPUTS(j) { CHECK_DOUBLE_EQ(copysign(*i, *j), r.Call(*i, *j)); }
2789 }
2790 }
2791
WASM_EXEC_TEST(F32CopySign)2792 WASM_EXEC_TEST(F32CopySign) {
2793 WasmRunner<float> r(execution_mode, MachineType::Float32(),
2794 MachineType::Float32());
2795 BUILD(r, WASM_F32_COPYSIGN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
2796
2797 FOR_FLOAT32_INPUTS(i) {
2798 FOR_FLOAT32_INPUTS(j) { CHECK_FLOAT_EQ(copysignf(*i, *j), r.Call(*i, *j)); }
2799 }
2800 }
2801
CompileCallIndirectMany(LocalType param)2802 static void CompileCallIndirectMany(LocalType param) {
2803 // Make sure we don't run out of registers when compiling indirect calls
2804 // with many many parameters.
2805 TestSignatures sigs;
2806 for (byte num_params = 0; num_params < 40; ++num_params) {
2807 v8::base::AccountingAllocator allocator;
2808 Zone zone(&allocator);
2809 HandleScope scope(CcTest::InitIsolateOnce());
2810 TestingModule module(kExecuteCompiled);
2811 FunctionSig* sig = sigs.many(&zone, kAstStmt, param, num_params);
2812
2813 module.AddSignature(sig);
2814 module.AddSignature(sig);
2815 module.AddIndirectFunctionTable(nullptr, 0);
2816
2817 WasmFunctionCompiler t(sig, &module);
2818
2819 std::vector<byte> code;
2820 ADD_CODE(code, kExprI8Const, 0);
2821 for (byte p = 0; p < num_params; ++p) {
2822 ADD_CODE(code, kExprGetLocal, p);
2823 }
2824 ADD_CODE(code, kExprCallIndirect, static_cast<byte>(num_params), 1);
2825
2826 t.Build(&code[0], &code[0] + code.size());
2827 t.Compile();
2828 }
2829 }
2830
TEST(Compile_Wasm_CallIndirect_Many_i32)2831 TEST(Compile_Wasm_CallIndirect_Many_i32) { CompileCallIndirectMany(kAstI32); }
2832
TEST(Compile_Wasm_CallIndirect_Many_f32)2833 TEST(Compile_Wasm_CallIndirect_Many_f32) { CompileCallIndirectMany(kAstF32); }
2834
TEST(Compile_Wasm_CallIndirect_Many_f64)2835 TEST(Compile_Wasm_CallIndirect_Many_f64) { CompileCallIndirectMany(kAstF64); }
2836
WASM_EXEC_TEST(Int32RemS_dead)2837 WASM_EXEC_TEST(Int32RemS_dead) {
2838 WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
2839 MachineType::Int32());
2840 BUILD(r, WASM_I32_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)), WASM_ZERO);
2841 const int32_t kMin = std::numeric_limits<int32_t>::min();
2842 CHECK_EQ(0, r.Call(133, 100));
2843 CHECK_EQ(0, r.Call(kMin, -1));
2844 CHECK_EQ(0, r.Call(0, 1));
2845 CHECK_TRAP(r.Call(100, 0));
2846 CHECK_TRAP(r.Call(-1001, 0));
2847 CHECK_TRAP(r.Call(kMin, 0));
2848 }
2849