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