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