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/bits.h"
11 : #include "src/objects-inl.h"
12 :
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_64 {
23 :
24 : // If the target architecture is 64-bit, enable all tests.
25 : #if !V8_TARGET_ARCH_32_BIT || V8_TARGET_ARCH_X64
26 : #define WASM_64 1
27 : #else
28 : #define WASM_64 0
29 : #endif
30 :
31 : // Can't bridge macro land with nested macros.
32 : #if V8_TARGET_ARCH_MIPS
33 : #define MIPS true
34 : #else
35 : #define MIPS false
36 : #endif
37 :
38 : #define FOREACH_I64_OPERATOR(V) \
39 : V(DepthFirst, true) \
40 : V(I64Phi, true) \
41 : V(I64Const, true) \
42 : V(I64Return, true) \
43 : V(I64Param, true) \
44 : V(I64LoadStore, true) \
45 : V(I64Add, true) \
46 : V(I64Sub, true) \
47 : V(I64Mul, !MIPS) \
48 : V(I64DivS, true) \
49 : V(I64DivU, true) \
50 : V(I64RemS, true) \
51 : V(I64RemU, true) \
52 : V(I64And, true) \
53 : V(I64Ior, true) \
54 : V(I64Xor, true) \
55 : V(I64Shl, true) \
56 : V(I64ShrU, true) \
57 : V(I64ShrS, true) \
58 : V(I64Eq, true) \
59 : V(I64Ne, true) \
60 : V(I64LtS, true) \
61 : V(I64LeS, true) \
62 : V(I64LtU, true) \
63 : V(I64LeU, true) \
64 : V(I64GtS, true) \
65 : V(I64GeS, true) \
66 : V(I64GtU, true) \
67 : V(I64GeU, true) \
68 : V(I64Ctz, true) \
69 : V(I64Clz, true) \
70 : V(I64Popcnt, true) \
71 : V(I32ConvertI64, true) \
72 : V(I64SConvertF32, true) \
73 : V(I64SConvertF64, true) \
74 : V(I64UConvertF32, true) \
75 : V(I64UConvertF64, true) \
76 : V(I64SConvertI32, true) \
77 : V(I64UConvertI32, true) \
78 : V(F32SConvertI64, true) \
79 : V(F32UConvertI64, true) \
80 : V(F64SConvertI64, true) \
81 : V(F64UConvertI64, true) \
82 : V(F64ReinterpretI64, true) \
83 : V(I64ReinterpretF64, true) \
84 : V(I64Ror, true) \
85 : V(I64Rol, true)
86 :
87 : #define DECLARE_CONST(name, cond) static const bool kSupported_##name = cond;
88 : FOREACH_I64_OPERATOR(DECLARE_CONST)
89 : #undef DECLARE_CONST
90 :
91 : #undef FOREACH_I64_OPERATOR
92 :
93 : #define REQUIRE(name) \
94 : if (!WASM_64 && !kSupported_##name) return
95 :
96 23742 : WASM_EXEC_TEST(I64Const) {
97 12 : REQUIRE(I64Const);
98 12 : WasmRunner<int64_t> r(execution_mode);
99 : const int64_t kExpectedValue = 0x1122334455667788LL;
100 : // return(kExpectedValue)
101 12 : BUILD(r, WASM_I64V_9(kExpectedValue));
102 12 : CHECK_EQ(kExpectedValue, r.Call());
103 : }
104 :
105 23742 : WASM_EXEC_TEST(I64Const_many) {
106 12 : REQUIRE(I64Const);
107 : int cntr = 0;
108 708 : FOR_INT32_INPUTS(i) {
109 696 : WasmRunner<int64_t> r(execution_mode);
110 696 : const int64_t kExpectedValue = (static_cast<int64_t>(*i) << 32) | cntr;
111 : // return(kExpectedValue)
112 696 : BUILD(r, WASM_I64V(kExpectedValue));
113 696 : CHECK_EQ(kExpectedValue, r.Call());
114 696 : cntr++;
115 : }
116 : }
117 :
118 23742 : WASM_EXEC_TEST(Return_I64) {
119 12 : REQUIRE(I64Return);
120 12 : WasmRunner<int64_t, int64_t> r(execution_mode);
121 :
122 12 : BUILD(r, WASM_RETURN1(WASM_GET_LOCAL(0)));
123 :
124 12 : FOR_INT64_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
125 : }
126 :
127 23742 : WASM_EXEC_TEST(I64Add) {
128 12 : REQUIRE(I64Add);
129 12 : WasmRunner<int64_t, int64_t, int64_t> r(execution_mode);
130 12 : BUILD(r, WASM_I64_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
131 984 : FOR_INT64_INPUTS(i) {
132 78732 : FOR_INT64_INPUTS(j) { CHECK_EQ(*i + *j, r.Call(*i, *j)); }
133 : }
134 : }
135 :
136 : // The i64 add and subtract regression tests need a 64-bit value with a non-zero
137 : // upper half. This upper half was clobbering eax, leading to the function
138 : // returning 1 rather than 0.
139 : const int64_t kHasBit33On = 0x100000000;
140 :
141 23742 : WASM_EXEC_TEST(Regress5800_Add) {
142 12 : REQUIRE(I64Add);
143 12 : WasmRunner<int32_t> r(execution_mode);
144 12 : BUILD(r, WASM_BLOCK(WASM_BR_IF(0, WASM_I64_EQZ(WASM_I64_ADD(
145 : WASM_I64V(0), WASM_I64V(kHasBit33On)))),
146 : WASM_RETURN1(WASM_I32V(0))),
147 : WASM_I32V(0));
148 12 : CHECK_EQ(0, r.Call());
149 : }
150 :
151 23742 : WASM_EXEC_TEST(I64Sub) {
152 12 : REQUIRE(I64Sub);
153 12 : WasmRunner<int64_t, int64_t, int64_t> r(execution_mode);
154 12 : BUILD(r, WASM_I64_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
155 984 : FOR_INT64_INPUTS(i) {
156 78732 : FOR_INT64_INPUTS(j) { CHECK_EQ(*i - *j, r.Call(*i, *j)); }
157 : }
158 : }
159 :
160 23742 : WASM_EXEC_TEST(Regress5800_Sub) {
161 12 : REQUIRE(I64Sub);
162 12 : WasmRunner<int32_t> r(execution_mode);
163 12 : BUILD(r, WASM_BLOCK(WASM_BR_IF(0, WASM_I64_EQZ(WASM_I64_SUB(
164 : WASM_I64V(0), WASM_I64V(kHasBit33On)))),
165 : WASM_RETURN1(WASM_I32V(0))),
166 : WASM_I32V(0));
167 12 : CHECK_EQ(0, r.Call());
168 : }
169 :
170 23742 : WASM_EXEC_TEST(I64AddUseOnlyLowWord) {
171 : REQUIRE(I64Add);
172 : REQUIRE(I32ConvertI64);
173 12 : WasmRunner<int32_t, int64_t, int64_t> r(execution_mode);
174 12 : BUILD(r, WASM_I32_CONVERT_I64(
175 : WASM_I64_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))));
176 984 : FOR_INT64_INPUTS(i) {
177 78732 : FOR_INT64_INPUTS(j) {
178 78732 : CHECK_EQ(static_cast<int32_t>(*i + *j), r.Call(*i, *j));
179 : }
180 : }
181 : }
182 :
183 23742 : WASM_EXEC_TEST(I64SubUseOnlyLowWord) {
184 : REQUIRE(I64Sub);
185 : REQUIRE(I32ConvertI64);
186 12 : WasmRunner<int32_t, int64_t, int64_t> r(execution_mode);
187 12 : BUILD(r, WASM_I32_CONVERT_I64(
188 : WASM_I64_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))));
189 984 : FOR_INT64_INPUTS(i) {
190 78732 : FOR_INT64_INPUTS(j) {
191 78732 : CHECK_EQ(static_cast<int32_t>(*i - *j), r.Call(*i, *j));
192 : }
193 : }
194 : }
195 :
196 23742 : WASM_EXEC_TEST(I64MulUseOnlyLowWord) {
197 : REQUIRE(I64Mul);
198 : REQUIRE(I32ConvertI64);
199 12 : WasmRunner<int32_t, int64_t, int64_t> r(execution_mode);
200 12 : BUILD(r, WASM_I32_CONVERT_I64(
201 : WASM_I64_MUL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))));
202 984 : FOR_INT64_INPUTS(i) {
203 78732 : FOR_INT64_INPUTS(j) {
204 78732 : CHECK_EQ(static_cast<int32_t>(*i * *j), r.Call(*i, *j));
205 : }
206 : }
207 : }
208 :
209 23742 : WASM_EXEC_TEST(I64ShlUseOnlyLowWord) {
210 : REQUIRE(I64Shl);
211 : REQUIRE(I32ConvertI64);
212 12 : WasmRunner<int32_t, int64_t, int64_t> r(execution_mode);
213 12 : BUILD(r, WASM_I32_CONVERT_I64(
214 : WASM_I64_SHL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))));
215 984 : FOR_INT64_INPUTS(i) {
216 78732 : FOR_INT64_INPUTS(j) {
217 78732 : int32_t expected = static_cast<int32_t>((*i) << (*j & 0x3f));
218 78732 : CHECK_EQ(expected, r.Call(*i, *j));
219 : }
220 : }
221 : }
222 :
223 23742 : WASM_EXEC_TEST(I64ShrUseOnlyLowWord) {
224 : REQUIRE(I64ShrU);
225 : REQUIRE(I32ConvertI64);
226 12 : WasmRunner<int32_t, int64_t, int64_t> r(execution_mode);
227 12 : BUILD(r, WASM_I32_CONVERT_I64(
228 : WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))));
229 984 : FOR_UINT64_INPUTS(i) {
230 78732 : FOR_UINT64_INPUTS(j) {
231 78732 : int32_t expected = static_cast<int32_t>((*i) >> (*j & 0x3f));
232 78732 : CHECK_EQ(expected, r.Call(*i, *j));
233 : }
234 : }
235 : }
236 :
237 23742 : WASM_EXEC_TEST(I64SarUseOnlyLowWord) {
238 : REQUIRE(I64ShrS);
239 : REQUIRE(I32ConvertI64);
240 12 : WasmRunner<int32_t, int64_t, int64_t> r(execution_mode);
241 12 : BUILD(r, WASM_I32_CONVERT_I64(
242 : WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))));
243 984 : FOR_INT64_INPUTS(i) {
244 78732 : FOR_INT64_INPUTS(j) {
245 78732 : int32_t expected = static_cast<int32_t>((*i) >> (*j & 0x3f));
246 78732 : CHECK_EQ(expected, r.Call(*i, *j));
247 : }
248 : }
249 : }
250 :
251 23742 : WASM_EXEC_TEST(I64DivS) {
252 12 : REQUIRE(I64DivS);
253 12 : WasmRunner<int64_t, int64_t, int64_t> r(execution_mode);
254 12 : BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
255 984 : FOR_INT64_INPUTS(i) {
256 78732 : FOR_INT64_INPUTS(j) {
257 78732 : if (*j == 0) {
258 3888 : CHECK_TRAP64(r.Call(*i, *j));
259 76788 : } else if (*j == -1 && *i == std::numeric_limits<int64_t>::min()) {
260 0 : CHECK_TRAP64(r.Call(*i, *j));
261 : } else {
262 76788 : CHECK_EQ(*i / *j, r.Call(*i, *j));
263 : }
264 : }
265 : }
266 : }
267 :
268 23742 : WASM_EXEC_TEST(I64DivS_Trap) {
269 12 : REQUIRE(I64DivS);
270 12 : WasmRunner<int64_t, int64_t, int64_t> r(execution_mode);
271 12 : BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
272 12 : CHECK_EQ(0, r.Call(int64_t{0}, int64_t{100}));
273 24 : CHECK_TRAP64(r.Call(int64_t{100}, int64_t{0}));
274 24 : CHECK_TRAP64(r.Call(int64_t{-1001}, int64_t{0}));
275 24 : CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), int64_t{-1}));
276 24 : CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), int64_t{0}));
277 : }
278 :
279 23742 : WASM_EXEC_TEST(I64DivS_Byzero_Const) {
280 12 : REQUIRE(I64DivS);
281 132 : for (int8_t denom = -2; denom < 8; denom++) {
282 120 : WasmRunner<int64_t, int64_t> r(execution_mode);
283 120 : BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_I64V_1(denom)));
284 1920 : for (int64_t val = -7; val < 8; val++) {
285 1800 : if (denom == 0) {
286 360 : CHECK_TRAP64(r.Call(val));
287 : } else {
288 1620 : CHECK_EQ(val / denom, r.Call(val));
289 : }
290 : }
291 : }
292 : }
293 :
294 23742 : WASM_EXEC_TEST(I64DivU) {
295 12 : REQUIRE(I64DivU);
296 12 : WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_mode);
297 12 : BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
298 984 : FOR_UINT64_INPUTS(i) {
299 78732 : FOR_UINT64_INPUTS(j) {
300 78732 : if (*j == 0) {
301 1944 : CHECK_TRAP64(r.Call(*i, *j));
302 : } else {
303 76788 : CHECK_EQ(*i / *j, r.Call(*i, *j));
304 : }
305 : }
306 : }
307 : }
308 :
309 23742 : WASM_EXEC_TEST(I64DivU_Trap) {
310 12 : REQUIRE(I64DivU);
311 12 : WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_mode);
312 12 : BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
313 24 : CHECK_EQ(0, r.Call(uint64_t{0}, uint64_t{100}));
314 12 : CHECK_TRAP64(r.Call(uint64_t{100}, uint64_t{0}));
315 12 : CHECK_TRAP64(r.Call(uint64_t{1001}, uint64_t{0}));
316 12 : CHECK_TRAP64(r.Call(std::numeric_limits<uint64_t>::max(), uint64_t{0}));
317 : }
318 :
319 23730 : WASM_EXEC_TEST(I64DivU_Byzero_Const) {
320 0 : REQUIRE(I64DivU);
321 : for (uint64_t denom = 0xfffffffffffffffe; denom < 8; denom++) {
322 : WasmRunner<uint64_t, uint64_t> r(execution_mode);
323 : BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_I64V_1(denom)));
324 :
325 : for (uint64_t val = 0xfffffffffffffff0; val < 8; val++) {
326 : if (denom == 0) {
327 : CHECK_TRAP64(r.Call(val));
328 : } else {
329 : CHECK_EQ(val / denom, r.Call(val));
330 : }
331 : }
332 : }
333 : }
334 :
335 23742 : WASM_EXEC_TEST(I64RemS) {
336 12 : REQUIRE(I64RemS);
337 12 : WasmRunner<int64_t, int64_t, int64_t> r(execution_mode);
338 12 : BUILD(r, WASM_I64_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
339 984 : FOR_INT64_INPUTS(i) {
340 78732 : FOR_INT64_INPUTS(j) {
341 78732 : if (*j == 0) {
342 3888 : CHECK_TRAP64(r.Call(*i, *j));
343 : } else {
344 76788 : CHECK_EQ(*i % *j, r.Call(*i, *j));
345 : }
346 : }
347 : }
348 : }
349 :
350 23742 : WASM_EXEC_TEST(I64RemS_Trap) {
351 12 : REQUIRE(I64RemS);
352 12 : WasmRunner<int64_t, int64_t, int64_t> r(execution_mode);
353 12 : BUILD(r, WASM_I64_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
354 12 : CHECK_EQ(33, r.Call(int64_t{133}, int64_t{100}));
355 12 : CHECK_EQ(0, r.Call(std::numeric_limits<int64_t>::min(), int64_t{-1}));
356 24 : CHECK_TRAP64(r.Call(int64_t{100}, int64_t{0}));
357 24 : CHECK_TRAP64(r.Call(int64_t{-1001}, int64_t{0}));
358 24 : CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), int64_t{0}));
359 : }
360 :
361 23742 : WASM_EXEC_TEST(I64RemU) {
362 12 : REQUIRE(I64RemU);
363 12 : WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_mode);
364 12 : BUILD(r, WASM_I64_REMU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
365 984 : FOR_UINT64_INPUTS(i) {
366 78732 : FOR_UINT64_INPUTS(j) {
367 78732 : if (*j == 0) {
368 1944 : CHECK_TRAP64(r.Call(*i, *j));
369 : } else {
370 76788 : CHECK_EQ(*i % *j, r.Call(*i, *j));
371 : }
372 : }
373 : }
374 : }
375 :
376 23742 : WASM_EXEC_TEST(I64RemU_Trap) {
377 12 : REQUIRE(I64RemU);
378 12 : WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_mode);
379 12 : BUILD(r, WASM_I64_REMU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
380 24 : CHECK_EQ(17, r.Call(uint64_t{217}, uint64_t{100}));
381 12 : CHECK_TRAP64(r.Call(uint64_t{100}, uint64_t{0}));
382 12 : CHECK_TRAP64(r.Call(uint64_t{1001}, uint64_t{0}));
383 12 : CHECK_TRAP64(r.Call(std::numeric_limits<uint64_t>::max(), uint64_t{0}));
384 : }
385 :
386 23742 : WASM_EXEC_TEST(I64And) {
387 12 : REQUIRE(I64And);
388 12 : WasmRunner<int64_t, int64_t, int64_t> r(execution_mode);
389 12 : BUILD(r, WASM_I64_AND(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
390 984 : FOR_INT64_INPUTS(i) {
391 78732 : FOR_INT64_INPUTS(j) { CHECK_EQ((*i) & (*j), r.Call(*i, *j)); }
392 : }
393 : }
394 :
395 23742 : WASM_EXEC_TEST(I64Ior) {
396 12 : REQUIRE(I64Ior);
397 12 : WasmRunner<int64_t, int64_t, int64_t> r(execution_mode);
398 12 : BUILD(r, WASM_I64_IOR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
399 984 : FOR_INT64_INPUTS(i) {
400 78732 : FOR_INT64_INPUTS(j) { CHECK_EQ((*i) | (*j), r.Call(*i, *j)); }
401 : }
402 : }
403 :
404 23742 : WASM_EXEC_TEST(I64Xor) {
405 12 : REQUIRE(I64Xor);
406 12 : WasmRunner<int64_t, int64_t, int64_t> r(execution_mode);
407 12 : BUILD(r, WASM_I64_XOR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
408 984 : FOR_INT64_INPUTS(i) {
409 78732 : FOR_INT64_INPUTS(j) { CHECK_EQ((*i) ^ (*j), r.Call(*i, *j)); }
410 : }
411 : }
412 :
413 23742 : WASM_EXEC_TEST(I64Shl) {
414 12 : REQUIRE(I64Shl);
415 : {
416 12 : WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_mode);
417 12 : BUILD(r, WASM_I64_SHL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
418 :
419 984 : FOR_UINT64_INPUTS(i) {
420 78732 : FOR_UINT64_INPUTS(j) {
421 78732 : uint64_t expected = (*i) << (*j & 0x3f);
422 78732 : CHECK_EQ(expected, r.Call(*i, *j));
423 : }
424 : }
425 : }
426 : {
427 12 : WasmRunner<uint64_t, int64_t> r(execution_mode);
428 12 : BUILD(r, WASM_I64_SHL(WASM_GET_LOCAL(0), WASM_I64V_1(0)));
429 12 : FOR_UINT64_INPUTS(i) { CHECK_EQ(*i << 0, r.Call(*i)); }
430 : }
431 : {
432 12 : WasmRunner<uint64_t, int64_t> r(execution_mode);
433 12 : BUILD(r, WASM_I64_SHL(WASM_GET_LOCAL(0), WASM_I64V_1(32)));
434 12 : FOR_UINT64_INPUTS(i) { CHECK_EQ(*i << 32, r.Call(*i)); }
435 : }
436 : {
437 12 : WasmRunner<uint64_t, int64_t> r(execution_mode);
438 12 : BUILD(r, WASM_I64_SHL(WASM_GET_LOCAL(0), WASM_I64V_1(20)));
439 12 : FOR_UINT64_INPUTS(i) { CHECK_EQ(*i << 20, r.Call(*i)); }
440 : }
441 : {
442 12 : WasmRunner<uint64_t, int64_t> r(execution_mode);
443 12 : BUILD(r, WASM_I64_SHL(WASM_GET_LOCAL(0), WASM_I64V_1(40)));
444 12 : FOR_UINT64_INPUTS(i) { CHECK_EQ(*i << 40, r.Call(*i)); }
445 : }
446 : }
447 :
448 23742 : WASM_EXEC_TEST(I64ShrU) {
449 12 : REQUIRE(I64ShrU);
450 : {
451 12 : WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_mode);
452 12 : BUILD(r, WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
453 :
454 984 : FOR_UINT64_INPUTS(i) {
455 78732 : FOR_UINT64_INPUTS(j) {
456 78732 : uint64_t expected = (*i) >> (*j & 0x3f);
457 78732 : CHECK_EQ(expected, r.Call(*i, *j));
458 : }
459 : }
460 : }
461 : {
462 12 : WasmRunner<uint64_t, int64_t> r(execution_mode);
463 12 : BUILD(r, WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_I64V_1(0)));
464 12 : FOR_UINT64_INPUTS(i) { CHECK_EQ(*i >> 0, r.Call(*i)); }
465 : }
466 : {
467 12 : WasmRunner<uint64_t, int64_t> r(execution_mode);
468 12 : BUILD(r, WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_I64V_1(32)));
469 12 : FOR_UINT64_INPUTS(i) { CHECK_EQ(*i >> 32, r.Call(*i)); }
470 : }
471 : {
472 12 : WasmRunner<uint64_t, int64_t> r(execution_mode);
473 12 : BUILD(r, WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_I64V_1(20)));
474 12 : FOR_UINT64_INPUTS(i) { CHECK_EQ(*i >> 20, r.Call(*i)); }
475 : }
476 : {
477 12 : WasmRunner<uint64_t, int64_t> r(execution_mode);
478 12 : BUILD(r, WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_I64V_1(40)));
479 12 : FOR_UINT64_INPUTS(i) { CHECK_EQ(*i >> 40, r.Call(*i)); }
480 : }
481 : }
482 :
483 23742 : WASM_EXEC_TEST(I64ShrS) {
484 12 : REQUIRE(I64ShrS);
485 : {
486 12 : WasmRunner<int64_t, int64_t, int64_t> r(execution_mode);
487 12 : BUILD(r, WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
488 :
489 984 : FOR_INT64_INPUTS(i) {
490 78732 : FOR_INT64_INPUTS(j) {
491 78732 : int64_t expected = (*i) >> (*j & 0x3f);
492 78732 : CHECK_EQ(expected, r.Call(*i, *j));
493 : }
494 : }
495 : }
496 : {
497 12 : WasmRunner<int64_t, int64_t> r(execution_mode);
498 12 : BUILD(r, WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_I64V_1(0)));
499 12 : FOR_INT64_INPUTS(i) { CHECK_EQ(*i >> 0, r.Call(*i)); }
500 : }
501 : {
502 12 : WasmRunner<int64_t, int64_t> r(execution_mode);
503 12 : BUILD(r, WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_I64V_1(32)));
504 12 : FOR_INT64_INPUTS(i) { CHECK_EQ(*i >> 32, r.Call(*i)); }
505 : }
506 : {
507 12 : WasmRunner<int64_t, int64_t> r(execution_mode);
508 12 : BUILD(r, WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_I64V_1(20)));
509 12 : FOR_INT64_INPUTS(i) { CHECK_EQ(*i >> 20, r.Call(*i)); }
510 : }
511 : {
512 12 : WasmRunner<int64_t, int64_t> r(execution_mode);
513 12 : BUILD(r, WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_I64V_1(40)));
514 12 : FOR_INT64_INPUTS(i) { CHECK_EQ(*i >> 40, r.Call(*i)); }
515 : }
516 : }
517 :
518 23742 : WASM_EXEC_TEST(I64Eq) {
519 12 : REQUIRE(I64Eq);
520 12 : WasmRunner<int32_t, int64_t, int64_t> r(execution_mode);
521 12 : BUILD(r, WASM_I64_EQ(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
522 984 : FOR_INT64_INPUTS(i) {
523 78732 : FOR_INT64_INPUTS(j) { CHECK_EQ(*i == *j ? 1 : 0, r.Call(*i, *j)); }
524 : }
525 : }
526 :
527 23742 : WASM_EXEC_TEST(I64Ne) {
528 12 : REQUIRE(I64Ne);
529 12 : WasmRunner<int32_t, int64_t, int64_t> r(execution_mode);
530 12 : BUILD(r, WASM_I64_NE(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
531 984 : FOR_INT64_INPUTS(i) {
532 78732 : FOR_INT64_INPUTS(j) { CHECK_EQ(*i != *j ? 1 : 0, r.Call(*i, *j)); }
533 : }
534 : }
535 :
536 23742 : WASM_EXEC_TEST(I64LtS) {
537 12 : REQUIRE(I64LtS);
538 12 : WasmRunner<int32_t, int64_t, int64_t> r(execution_mode);
539 12 : BUILD(r, WASM_I64_LTS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
540 984 : FOR_INT64_INPUTS(i) {
541 78732 : FOR_INT64_INPUTS(j) { CHECK_EQ(*i < *j ? 1 : 0, r.Call(*i, *j)); }
542 : }
543 : }
544 :
545 23742 : WASM_EXEC_TEST(I64LeS) {
546 12 : REQUIRE(I64LeS);
547 12 : WasmRunner<int32_t, int64_t, int64_t> r(execution_mode);
548 12 : BUILD(r, WASM_I64_LES(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
549 984 : FOR_INT64_INPUTS(i) {
550 78732 : FOR_INT64_INPUTS(j) { CHECK_EQ(*i <= *j ? 1 : 0, r.Call(*i, *j)); }
551 : }
552 : }
553 :
554 23742 : WASM_EXEC_TEST(I64LtU) {
555 12 : REQUIRE(I64LtU);
556 12 : WasmRunner<int32_t, int64_t, int64_t> r(execution_mode);
557 12 : BUILD(r, WASM_I64_LTU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
558 984 : FOR_UINT64_INPUTS(i) {
559 78732 : FOR_UINT64_INPUTS(j) { CHECK_EQ(*i < *j ? 1 : 0, r.Call(*i, *j)); }
560 : }
561 : }
562 :
563 23742 : WASM_EXEC_TEST(I64LeU) {
564 12 : REQUIRE(I64LeU);
565 12 : WasmRunner<int32_t, int64_t, int64_t> r(execution_mode);
566 12 : BUILD(r, WASM_I64_LEU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
567 984 : FOR_UINT64_INPUTS(i) {
568 78732 : FOR_UINT64_INPUTS(j) { CHECK_EQ(*i <= *j ? 1 : 0, r.Call(*i, *j)); }
569 : }
570 : }
571 :
572 23742 : WASM_EXEC_TEST(I64GtS) {
573 12 : REQUIRE(I64GtS);
574 12 : WasmRunner<int32_t, int64_t, int64_t> r(execution_mode);
575 12 : BUILD(r, WASM_I64_GTS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
576 984 : FOR_INT64_INPUTS(i) {
577 78732 : FOR_INT64_INPUTS(j) { CHECK_EQ(*i > *j ? 1 : 0, r.Call(*i, *j)); }
578 : }
579 : }
580 :
581 23742 : WASM_EXEC_TEST(I64GeS) {
582 12 : REQUIRE(I64GeS);
583 12 : WasmRunner<int32_t, int64_t, int64_t> r(execution_mode);
584 12 : BUILD(r, WASM_I64_GES(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
585 984 : FOR_INT64_INPUTS(i) {
586 78732 : FOR_INT64_INPUTS(j) { CHECK_EQ(*i >= *j ? 1 : 0, r.Call(*i, *j)); }
587 : }
588 : }
589 :
590 23742 : WASM_EXEC_TEST(I64GtU) {
591 12 : REQUIRE(I64GtU);
592 12 : WasmRunner<int32_t, int64_t, int64_t> r(execution_mode);
593 12 : BUILD(r, WASM_I64_GTU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
594 984 : FOR_UINT64_INPUTS(i) {
595 78732 : FOR_UINT64_INPUTS(j) { CHECK_EQ(*i > *j ? 1 : 0, r.Call(*i, *j)); }
596 : }
597 : }
598 :
599 23742 : WASM_EXEC_TEST(I64GeU) {
600 12 : REQUIRE(I64GeU);
601 12 : WasmRunner<int32_t, int64_t, int64_t> r(execution_mode);
602 12 : BUILD(r, WASM_I64_GEU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
603 984 : FOR_UINT64_INPUTS(i) {
604 78732 : FOR_UINT64_INPUTS(j) { CHECK_EQ(*i >= *j ? 1 : 0, r.Call(*i, *j)); }
605 : }
606 : }
607 :
608 23742 : WASM_EXEC_TEST(I32ConvertI64) {
609 12 : REQUIRE(I32ConvertI64);
610 984 : FOR_INT64_INPUTS(i) {
611 972 : WasmRunner<int32_t> r(execution_mode);
612 972 : BUILD(r, WASM_I32_CONVERT_I64(WASM_I64V(*i)));
613 972 : CHECK_EQ(static_cast<int32_t>(*i), r.Call());
614 : }
615 : }
616 :
617 23742 : WASM_EXEC_TEST(I64SConvertI32) {
618 12 : REQUIRE(I64SConvertI32);
619 12 : WasmRunner<int64_t, int32_t> r(execution_mode);
620 12 : BUILD(r, WASM_I64_SCONVERT_I32(WASM_GET_LOCAL(0)));
621 12 : FOR_INT32_INPUTS(i) { CHECK_EQ(static_cast<int64_t>(*i), r.Call(*i)); }
622 : }
623 :
624 23742 : WASM_EXEC_TEST(I64UConvertI32) {
625 12 : REQUIRE(I64UConvertI32);
626 12 : WasmRunner<int64_t, uint32_t> r(execution_mode);
627 12 : BUILD(r, WASM_I64_UCONVERT_I32(WASM_GET_LOCAL(0)));
628 12 : FOR_UINT32_INPUTS(i) { CHECK_EQ(static_cast<int64_t>(*i), r.Call(*i)); }
629 : }
630 :
631 23742 : WASM_EXEC_TEST(I64Popcnt) {
632 : struct {
633 : int64_t expected;
634 : uint64_t input;
635 : } values[] = {{64, 0xffffffffffffffff},
636 : {0, 0x0000000000000000},
637 : {2, 0x0000080000008000},
638 : {26, 0x1123456782345678},
639 12 : {38, 0xffedcba09edcba09}};
640 :
641 12 : WasmRunner<int64_t, uint64_t> r(execution_mode);
642 12 : BUILD(r, WASM_I64_POPCNT(WASM_GET_LOCAL(0)));
643 72 : for (size_t i = 0; i < arraysize(values); i++) {
644 60 : CHECK_EQ(values[i].expected, r.Call(values[i].input));
645 : }
646 12 : }
647 :
648 23742 : WASM_EXEC_TEST(F32SConvertI64) {
649 12 : REQUIRE(F32SConvertI64);
650 12 : WasmRunner<float, int64_t> r(execution_mode);
651 12 : BUILD(r, WASM_F32_SCONVERT_I64(WASM_GET_LOCAL(0)));
652 12 : FOR_INT64_INPUTS(i) { CHECK_FLOAT_EQ(static_cast<float>(*i), r.Call(*i)); }
653 : }
654 :
655 23742 : WASM_EXEC_TEST(F32UConvertI64) {
656 12 : REQUIRE(F32UConvertI64);
657 : struct {
658 : uint64_t input;
659 : uint32_t expected;
660 : } values[] = {{0x0, 0x0},
661 : {0x1, 0x3f800000},
662 : {0xffffffff, 0x4f800000},
663 : {0x1b09788b, 0x4dd84bc4},
664 : {0x4c5fce8, 0x4c98bf9d},
665 : {0xcc0de5bf, 0x4f4c0de6},
666 : {0x2, 0x40000000},
667 : {0x3, 0x40400000},
668 : {0x4, 0x40800000},
669 : {0x5, 0x40a00000},
670 : {0x8, 0x41000000},
671 : {0x9, 0x41100000},
672 : {0xffffffffffffffff, 0x5f800000},
673 : {0xfffffffffffffffe, 0x5f800000},
674 : {0xfffffffffffffffd, 0x5f800000},
675 : {0x0, 0x0},
676 : {0x100000000, 0x4f800000},
677 : {0xffffffff00000000, 0x5f800000},
678 : {0x1b09788b00000000, 0x5dd84bc4},
679 : {0x4c5fce800000000, 0x5c98bf9d},
680 : {0xcc0de5bf00000000, 0x5f4c0de6},
681 : {0x200000000, 0x50000000},
682 : {0x300000000, 0x50400000},
683 : {0x400000000, 0x50800000},
684 : {0x500000000, 0x50a00000},
685 : {0x800000000, 0x51000000},
686 : {0x900000000, 0x51100000},
687 : {0x273a798e187937a3, 0x5e1ce9e6},
688 : {0xece3af835495a16b, 0x5f6ce3b0},
689 : {0xb668ecc11223344, 0x5d3668ed},
690 : {0x9e, 0x431e0000},
691 : {0x43, 0x42860000},
692 : {0xaf73, 0x472f7300},
693 : {0x116b, 0x458b5800},
694 : {0x658ecc, 0x4acb1d98},
695 : {0x2b3b4c, 0x4a2ced30},
696 : {0x88776655, 0x4f087766},
697 : {0x70000000, 0x4ee00000},
698 : {0x7200000, 0x4ce40000},
699 : {0x7fffffff, 0x4f000000},
700 : {0x56123761, 0x4eac246f},
701 : {0x7fffff00, 0x4efffffe},
702 : {0x761c4761eeeeeeee, 0x5eec388f},
703 : {0x80000000eeeeeeee, 0x5f000000},
704 : {0x88888888dddddddd, 0x5f088889},
705 : {0xa0000000dddddddd, 0x5f200000},
706 : {0xddddddddaaaaaaaa, 0x5f5dddde},
707 : {0xe0000000aaaaaaaa, 0x5f600000},
708 : {0xeeeeeeeeeeeeeeee, 0x5f6eeeef},
709 : {0xfffffffdeeeeeeee, 0x5f800000},
710 : {0xf0000000dddddddd, 0x5f700000},
711 : {0x7fffffdddddddd, 0x5b000000},
712 : {0x3fffffaaaaaaaa, 0x5a7fffff},
713 : {0x1fffffaaaaaaaa, 0x59fffffd},
714 : {0xfffff, 0x497ffff0},
715 : {0x7ffff, 0x48ffffe0},
716 : {0x3ffff, 0x487fffc0},
717 : {0x1ffff, 0x47ffff80},
718 : {0xffff, 0x477fff00},
719 : {0x7fff, 0x46fffe00},
720 : {0x3fff, 0x467ffc00},
721 : {0x1fff, 0x45fff800},
722 : {0xfff, 0x457ff000},
723 : {0x7ff, 0x44ffe000},
724 : {0x3ff, 0x447fc000},
725 : {0x1ff, 0x43ff8000},
726 : {0x3fffffffffff, 0x56800000},
727 : {0x1fffffffffff, 0x56000000},
728 : {0xfffffffffff, 0x55800000},
729 : {0x7ffffffffff, 0x55000000},
730 : {0x3ffffffffff, 0x54800000},
731 : {0x1ffffffffff, 0x54000000},
732 : {0x8000008000000000, 0x5f000000},
733 : {0x8000008000000001, 0x5f000001},
734 : {0x8000000000000400, 0x5f000000},
735 12 : {0x8000000000000401, 0x5f000000}};
736 12 : WasmRunner<float, uint64_t> r(execution_mode);
737 12 : BUILD(r, WASM_F32_UCONVERT_I64(WASM_GET_LOCAL(0)));
738 924 : for (size_t i = 0; i < arraysize(values); i++) {
739 1824 : CHECK_EQ(bit_cast<float>(values[i].expected), r.Call(values[i].input));
740 : }
741 : }
742 :
743 23742 : WASM_EXEC_TEST(F64SConvertI64) {
744 12 : REQUIRE(F64SConvertI64);
745 12 : WasmRunner<double, int64_t> r(execution_mode);
746 12 : BUILD(r, WASM_F64_SCONVERT_I64(WASM_GET_LOCAL(0)));
747 12 : FOR_INT64_INPUTS(i) { CHECK_DOUBLE_EQ(static_cast<double>(*i), r.Call(*i)); }
748 : }
749 :
750 23742 : WASM_EXEC_TEST(F64UConvertI64) {
751 12 : REQUIRE(F64UConvertI64);
752 : struct {
753 : uint64_t input;
754 : uint64_t expected;
755 : } values[] = {{0x0, 0x0},
756 : {0x1, 0x3ff0000000000000},
757 : {0xffffffff, 0x41efffffffe00000},
758 : {0x1b09788b, 0x41bb09788b000000},
759 : {0x4c5fce8, 0x419317f3a0000000},
760 : {0xcc0de5bf, 0x41e981bcb7e00000},
761 : {0x2, 0x4000000000000000},
762 : {0x3, 0x4008000000000000},
763 : {0x4, 0x4010000000000000},
764 : {0x5, 0x4014000000000000},
765 : {0x8, 0x4020000000000000},
766 : {0x9, 0x4022000000000000},
767 : {0xffffffffffffffff, 0x43f0000000000000},
768 : {0xfffffffffffffffe, 0x43f0000000000000},
769 : {0xfffffffffffffffd, 0x43f0000000000000},
770 : {0x100000000, 0x41f0000000000000},
771 : {0xffffffff00000000, 0x43efffffffe00000},
772 : {0x1b09788b00000000, 0x43bb09788b000000},
773 : {0x4c5fce800000000, 0x439317f3a0000000},
774 : {0xcc0de5bf00000000, 0x43e981bcb7e00000},
775 : {0x200000000, 0x4200000000000000},
776 : {0x300000000, 0x4208000000000000},
777 : {0x400000000, 0x4210000000000000},
778 : {0x500000000, 0x4214000000000000},
779 : {0x800000000, 0x4220000000000000},
780 : {0x900000000, 0x4222000000000000},
781 : {0x273a798e187937a3, 0x43c39d3cc70c3c9c},
782 : {0xece3af835495a16b, 0x43ed9c75f06a92b4},
783 : {0xb668ecc11223344, 0x43a6cd1d98224467},
784 : {0x9e, 0x4063c00000000000},
785 : {0x43, 0x4050c00000000000},
786 : {0xaf73, 0x40e5ee6000000000},
787 : {0x116b, 0x40b16b0000000000},
788 : {0x658ecc, 0x415963b300000000},
789 : {0x2b3b4c, 0x41459da600000000},
790 : {0x88776655, 0x41e10eeccaa00000},
791 : {0x70000000, 0x41dc000000000000},
792 : {0x7200000, 0x419c800000000000},
793 : {0x7fffffff, 0x41dfffffffc00000},
794 : {0x56123761, 0x41d5848dd8400000},
795 : {0x7fffff00, 0x41dfffffc0000000},
796 : {0x761c4761eeeeeeee, 0x43dd8711d87bbbbc},
797 : {0x80000000eeeeeeee, 0x43e00000001dddde},
798 : {0x88888888dddddddd, 0x43e11111111bbbbc},
799 : {0xa0000000dddddddd, 0x43e40000001bbbbc},
800 : {0xddddddddaaaaaaaa, 0x43ebbbbbbbb55555},
801 : {0xe0000000aaaaaaaa, 0x43ec000000155555},
802 : {0xeeeeeeeeeeeeeeee, 0x43edddddddddddde},
803 : {0xfffffffdeeeeeeee, 0x43efffffffbdddde},
804 : {0xf0000000dddddddd, 0x43ee0000001bbbbc},
805 : {0x7fffffdddddddd, 0x435ffffff7777777},
806 : {0x3fffffaaaaaaaa, 0x434fffffd5555555},
807 : {0x1fffffaaaaaaaa, 0x433fffffaaaaaaaa},
808 : {0xfffff, 0x412ffffe00000000},
809 : {0x7ffff, 0x411ffffc00000000},
810 : {0x3ffff, 0x410ffff800000000},
811 : {0x1ffff, 0x40fffff000000000},
812 : {0xffff, 0x40efffe000000000},
813 : {0x7fff, 0x40dfffc000000000},
814 : {0x3fff, 0x40cfff8000000000},
815 : {0x1fff, 0x40bfff0000000000},
816 : {0xfff, 0x40affe0000000000},
817 : {0x7ff, 0x409ffc0000000000},
818 : {0x3ff, 0x408ff80000000000},
819 : {0x1ff, 0x407ff00000000000},
820 : {0x3fffffffffff, 0x42cfffffffffff80},
821 : {0x1fffffffffff, 0x42bfffffffffff00},
822 : {0xfffffffffff, 0x42affffffffffe00},
823 : {0x7ffffffffff, 0x429ffffffffffc00},
824 : {0x3ffffffffff, 0x428ffffffffff800},
825 : {0x1ffffffffff, 0x427ffffffffff000},
826 : {0x8000008000000000, 0x43e0000010000000},
827 : {0x8000008000000001, 0x43e0000010000000},
828 : {0x8000000000000400, 0x43e0000000000000},
829 12 : {0x8000000000000401, 0x43e0000000000001}};
830 12 : WasmRunner<double, uint64_t> r(execution_mode);
831 12 : BUILD(r, WASM_F64_UCONVERT_I64(WASM_GET_LOCAL(0)));
832 912 : for (size_t i = 0; i < arraysize(values); i++) {
833 1800 : CHECK_EQ(bit_cast<double>(values[i].expected), r.Call(values[i].input));
834 : }
835 : }
836 :
837 23742 : WASM_EXEC_TEST(I64SConvertF32a) {
838 12 : WasmRunner<int64_t, float> r(execution_mode);
839 12 : BUILD(r, WASM_I64_SCONVERT_F32(WASM_GET_LOCAL(0)));
840 :
841 1392 : FOR_FLOAT32_INPUTS(i) {
842 1380 : if (*i < static_cast<float>(std::numeric_limits<int64_t>::max()) &&
843 : *i >= static_cast<float>(std::numeric_limits<int64_t>::min())) {
844 996 : CHECK_EQ(static_cast<int64_t>(*i), r.Call(*i));
845 : } else {
846 768 : CHECK_TRAP64(r.Call(*i));
847 : }
848 : }
849 12 : }
850 :
851 23742 : WASM_EXEC_TEST(I64SConvertF64a) {
852 12 : WasmRunner<int64_t, double> r(execution_mode);
853 12 : BUILD(r, WASM_I64_SCONVERT_F64(WASM_GET_LOCAL(0)));
854 :
855 600 : FOR_FLOAT64_INPUTS(i) {
856 588 : if (*i < static_cast<double>(std::numeric_limits<int64_t>::max()) &&
857 : *i >= static_cast<double>(std::numeric_limits<int64_t>::min())) {
858 456 : CHECK_EQ(static_cast<int64_t>(*i), r.Call(*i));
859 : } else {
860 264 : CHECK_TRAP64(r.Call(*i));
861 : }
862 : }
863 12 : }
864 :
865 23742 : WASM_EXEC_TEST(I64UConvertF32a) {
866 12 : WasmRunner<uint64_t, float> r(execution_mode);
867 12 : BUILD(r, WASM_I64_UCONVERT_F32(WASM_GET_LOCAL(0)));
868 :
869 1392 : FOR_FLOAT32_INPUTS(i) {
870 1380 : if (*i < static_cast<float>(std::numeric_limits<uint64_t>::max()) &&
871 : *i > -1) {
872 612 : CHECK_EQ(static_cast<uint64_t>(*i), r.Call(*i));
873 : } else {
874 768 : CHECK_TRAP64(r.Call(*i));
875 : }
876 : }
877 12 : }
878 :
879 23742 : WASM_EXEC_TEST(I64UConvertF64a) {
880 12 : WasmRunner<uint64_t, double> r(execution_mode);
881 12 : BUILD(r, WASM_I64_UCONVERT_F64(WASM_GET_LOCAL(0)));
882 :
883 600 : FOR_FLOAT64_INPUTS(i) {
884 588 : if (*i < static_cast<float>(std::numeric_limits<uint64_t>::max()) &&
885 : *i > -1) {
886 348 : CHECK_EQ(static_cast<uint64_t>(*i), r.Call(*i));
887 : } else {
888 240 : CHECK_TRAP64(r.Call(*i));
889 : }
890 : }
891 12 : }
892 :
893 23742 : WASM_EXEC_TEST(CallI64Parameter) {
894 : ValueType param_types[20];
895 12 : for (int i = 0; i < 20; i++) param_types[i] = kWasmI64;
896 12 : param_types[3] = kWasmI32;
897 12 : param_types[4] = kWasmI32;
898 : FunctionSig sig(1, 19, param_types);
899 240 : for (int i = 0; i < 19; i++) {
900 252 : if (i == 2 || i == 3) continue;
901 204 : WasmRunner<int32_t> r(execution_mode);
902 : // Build the target function.
903 408 : WasmFunctionCompiler& t = r.NewFunction(&sig);
904 204 : BUILD(t, WASM_GET_LOCAL(i));
905 :
906 : // Build the calling function.
907 408 : BUILD(
908 : r,
909 : WASM_I32_CONVERT_I64(WASM_CALL_FUNCTION(
910 : t.function_index(), WASM_I64V_9(0xbcd12340000000b),
911 : WASM_I64V_9(0xbcd12340000000c), WASM_I32V_1(0xd),
912 : WASM_I32_CONVERT_I64(WASM_I64V_9(0xbcd12340000000e)),
913 : WASM_I64V_9(0xbcd12340000000f), WASM_I64V_10(0xbcd1234000000010),
914 : WASM_I64V_10(0xbcd1234000000011), WASM_I64V_10(0xbcd1234000000012),
915 : WASM_I64V_10(0xbcd1234000000013), WASM_I64V_10(0xbcd1234000000014),
916 : WASM_I64V_10(0xbcd1234000000015), WASM_I64V_10(0xbcd1234000000016),
917 : WASM_I64V_10(0xbcd1234000000017), WASM_I64V_10(0xbcd1234000000018),
918 : WASM_I64V_10(0xbcd1234000000019), WASM_I64V_10(0xbcd123400000001a),
919 : WASM_I64V_10(0xbcd123400000001b), WASM_I64V_10(0xbcd123400000001c),
920 : WASM_I64V_10(0xbcd123400000001d))));
921 :
922 204 : CHECK_EQ(i + 0xb, r.Call());
923 : }
924 12 : }
925 :
926 228 : void TestI64Binop(WasmExecutionMode execution_mode, WasmOpcode opcode,
927 : int64_t expected, int64_t a, int64_t b) {
928 : {
929 228 : WasmRunner<int64_t> r(execution_mode);
930 : // return K op K
931 228 : BUILD(r, WASM_BINOP(opcode, WASM_I64V(a), WASM_I64V(b)));
932 228 : CHECK_EQ(expected, r.Call());
933 : }
934 : {
935 228 : WasmRunner<int64_t, int64_t, int64_t> r(execution_mode);
936 : // return a op b
937 228 : BUILD(r, WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
938 228 : CHECK_EQ(expected, r.Call(a, b));
939 : }
940 228 : }
941 :
942 120 : void TestI64Cmp(WasmExecutionMode execution_mode, WasmOpcode opcode,
943 : int64_t expected, int64_t a, int64_t b) {
944 : {
945 120 : WasmRunner<int32_t> r(execution_mode);
946 : // return K op K
947 120 : BUILD(r, WASM_BINOP(opcode, WASM_I64V(a), WASM_I64V(b)));
948 240 : CHECK_EQ(expected, r.Call());
949 : }
950 : {
951 120 : WasmRunner<int32_t, int64_t, int64_t> r(execution_mode);
952 : // return a op b
953 120 : BUILD(r, WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
954 240 : CHECK_EQ(expected, r.Call(a, b));
955 : }
956 120 : }
957 :
958 : #define TEST_I64_BINOP(name, expected, a, b) \
959 : do { \
960 : if (WASM_64 || kSupported_##name) \
961 : TestI64Binop(execution_mode, kExpr##name, expected, a, b); \
962 : } while (false)
963 :
964 23742 : WASM_EXEC_TEST(I64Binops) {
965 12 : TEST_I64_BINOP(I64Add, -5586332274295447011, 0x501b72ebabc26847,
966 : 0x625de9793d8f79d6);
967 12 : TEST_I64_BINOP(I64Sub, 9001903251710731490, 0xf24fe6474640002e,
968 : 0x7562b6f711991b4c);
969 12 : TEST_I64_BINOP(I64Mul, -4569547818546064176, 0x231a263c2cbc6451,
970 : 0xead44de6bd3e23d0);
971 12 : TEST_I64_BINOP(I64Mul, -25963122347507043, 0x4da1fa47c9352b73,
972 : 0x91fe82317aa035af);
973 12 : TEST_I64_BINOP(I64Mul, 7640290486138131960, 0x185731abe8eea47c,
974 : 0x714ec59f1380d4c2);
975 12 : TEST_I64_BINOP(I64DivS, -91517, 0x93b1190a34de56a0, 0x00004d8f68863948);
976 12 : TEST_I64_BINOP(I64DivU, 149016, 0xe15b3727e8a2080a, 0x0000631bfa72db8b);
977 12 : TEST_I64_BINOP(I64RemS, -664128064149968, 0x9a78b4e4fe708692,
978 : 0x0003e0b6b3be7609);
979 12 : TEST_I64_BINOP(I64RemU, 1742040017332765, 0x0ce84708c6258c81,
980 : 0x000a6fde82016697);
981 12 : TEST_I64_BINOP(I64And, 2531040582801836054, 0xaf257d1602644a16,
982 : 0x33b290a91a10d997);
983 12 : TEST_I64_BINOP(I64Ior, 8556201506536114940, 0x169d9be7bd3f0a5c,
984 : 0x66bca28d77af40e8);
985 12 : TEST_I64_BINOP(I64Xor, -4605655183785456377, 0xb6ea20a5d48e85b8,
986 : 0x76ff4da6c80688bf);
987 12 : TEST_I64_BINOP(I64Shl, -7240704056088331264, 0xef4dc1ed030e8ffe, 9);
988 12 : TEST_I64_BINOP(I64ShrU, 12500673744059159, 0xb1a52fa7deec5d14, 10);
989 12 : TEST_I64_BINOP(I64ShrS, 1725103446999874, 0x3107c791461a112b, 11);
990 12 : TEST_I64_BINOP(I64Ror, -8960135652432576946, 0x73418d1717e4e83a, 12);
991 12 : TEST_I64_BINOP(I64Ror, 7617662827409989779, 0xebff67cf0c126d36, 13);
992 12 : TEST_I64_BINOP(I64Rol, -2097714064174346012, 0x43938b8db0b0f230, 14);
993 12 : TEST_I64_BINOP(I64Rol, 8728493013947314237, 0xe07af243ac4d219d, 15);
994 12 : }
995 :
996 : #undef TEST_I64_BINOP
997 :
998 : #define TEST_I64_CMP(name, expected, a, b) \
999 : do { \
1000 : if (WASM_64 || kSupported_##name) \
1001 : TestI64Cmp(execution_mode, kExpr##name, expected, a, b); \
1002 : } while (false)
1003 :
1004 23742 : WASM_EXEC_TEST(I64Compare) {
1005 12 : TEST_I64_CMP(I64Eq, 0, 0xB915D8FA494064F0, 0x04D700B2536019A3);
1006 12 : TEST_I64_CMP(I64Ne, 1, 0xC2FAFAAAB0446CDC, 0x52A3328F780C97A3);
1007 12 : TEST_I64_CMP(I64LtS, 0, 0x673636E6306B0578, 0x028EC9ECA78F7227);
1008 12 : TEST_I64_CMP(I64LeS, 1, 0xAE5214114B86A0FA, 0x7C1D21DA3DFD0CCF);
1009 12 : TEST_I64_CMP(I64LtU, 0, 0x7D52166381EC1CE0, 0x59F4A6A9E78CD3D8);
1010 12 : TEST_I64_CMP(I64LeU, 1, 0xE4169A385C7EA0E0, 0xFBDBED2C8781E5BC);
1011 12 : TEST_I64_CMP(I64GtS, 0, 0x9D08FF8FB5F42E81, 0xD4E5C9D7FE09F621);
1012 12 : TEST_I64_CMP(I64GeS, 1, 0x78DA3B2F73264E0F, 0x6FE5E2A67C501CBE);
1013 12 : TEST_I64_CMP(I64GtU, 0, 0x8F691284E44F7DA9, 0xD5EA9BC1EE149192);
1014 12 : TEST_I64_CMP(I64GeU, 0, 0x0886A0C58C7AA224, 0x5DDBE5A81FD7EE47);
1015 12 : }
1016 :
1017 : #undef TEST_I64_CMP
1018 :
1019 23742 : WASM_EXEC_TEST(I64Clz) {
1020 12 : REQUIRE(I64Clz);
1021 : struct {
1022 : int64_t expected;
1023 : uint64_t input;
1024 : } values[] = {{0, 0x8000100000000000}, {1, 0x4000050000000000},
1025 : {2, 0x2000030000000000}, {3, 0x1000000300000000},
1026 : {4, 0x0805000000000000}, {5, 0x0400600000000000},
1027 : {6, 0x0200000000000000}, {7, 0x010000a000000000},
1028 : {8, 0x00800c0000000000}, {9, 0x0040000000000000},
1029 : {10, 0x0020000d00000000}, {11, 0x00100f0000000000},
1030 : {12, 0x0008000000000000}, {13, 0x0004100000000000},
1031 : {14, 0x0002002000000000}, {15, 0x0001030000000000},
1032 : {16, 0x0000804000000000}, {17, 0x0000400500000000},
1033 : {18, 0x0000205000000000}, {19, 0x0000170000000000},
1034 : {20, 0x0000087000000000}, {21, 0x0000040500000000},
1035 : {22, 0x0000020300000000}, {23, 0x0000010100000000},
1036 : {24, 0x0000008900000000}, {25, 0x0000004100000000},
1037 : {26, 0x0000002200000000}, {27, 0x0000001300000000},
1038 : {28, 0x0000000800000000}, {29, 0x0000000400000000},
1039 : {30, 0x0000000200000000}, {31, 0x0000000100000000},
1040 : {32, 0x0000000080001000}, {33, 0x0000000040000500},
1041 : {34, 0x0000000020000300}, {35, 0x0000000010000003},
1042 : {36, 0x0000000008050000}, {37, 0x0000000004006000},
1043 : {38, 0x0000000002000000}, {39, 0x00000000010000a0},
1044 : {40, 0x0000000000800c00}, {41, 0x0000000000400000},
1045 : {42, 0x000000000020000d}, {43, 0x0000000000100f00},
1046 : {44, 0x0000000000080000}, {45, 0x0000000000041000},
1047 : {46, 0x0000000000020020}, {47, 0x0000000000010300},
1048 : {48, 0x0000000000008040}, {49, 0x0000000000004005},
1049 : {50, 0x0000000000002050}, {51, 0x0000000000001700},
1050 : {52, 0x0000000000000870}, {53, 0x0000000000000405},
1051 : {54, 0x0000000000000203}, {55, 0x0000000000000101},
1052 : {56, 0x0000000000000089}, {57, 0x0000000000000041},
1053 : {58, 0x0000000000000022}, {59, 0x0000000000000013},
1054 : {60, 0x0000000000000008}, {61, 0x0000000000000004},
1055 : {62, 0x0000000000000002}, {63, 0x0000000000000001},
1056 12 : {64, 0x0000000000000000}};
1057 :
1058 12 : WasmRunner<int64_t, uint64_t> r(execution_mode);
1059 12 : BUILD(r, WASM_I64_CLZ(WASM_GET_LOCAL(0)));
1060 792 : for (size_t i = 0; i < arraysize(values); i++) {
1061 780 : CHECK_EQ(values[i].expected, r.Call(values[i].input));
1062 : }
1063 : }
1064 :
1065 23742 : WASM_EXEC_TEST(I64Ctz) {
1066 12 : REQUIRE(I64Ctz);
1067 : struct {
1068 : int64_t expected;
1069 : uint64_t input;
1070 : } values[] = {{64, 0x0000000000000000}, {63, 0x8000000000000000},
1071 : {62, 0x4000000000000000}, {61, 0x2000000000000000},
1072 : {60, 0x1000000000000000}, {59, 0xa800000000000000},
1073 : {58, 0xf400000000000000}, {57, 0x6200000000000000},
1074 : {56, 0x9100000000000000}, {55, 0xcd80000000000000},
1075 : {54, 0x0940000000000000}, {53, 0xaf20000000000000},
1076 : {52, 0xac10000000000000}, {51, 0xe0b8000000000000},
1077 : {50, 0x9ce4000000000000}, {49, 0xc792000000000000},
1078 : {48, 0xb8f1000000000000}, {47, 0x3b9f800000000000},
1079 : {46, 0xdb4c400000000000}, {45, 0xe9a3200000000000},
1080 : {44, 0xfca6100000000000}, {43, 0x6c8a780000000000},
1081 : {42, 0x8ce5a40000000000}, {41, 0xcb7d020000000000},
1082 : {40, 0xcb4dc10000000000}, {39, 0xdfbec58000000000},
1083 : {38, 0x27a9db4000000000}, {37, 0xde3bcb2000000000},
1084 : {36, 0xd7e8a61000000000}, {35, 0x9afdbc8800000000},
1085 : {34, 0x9afdbc8400000000}, {33, 0x9afdbc8200000000},
1086 : {32, 0x9afdbc8100000000}, {31, 0x0000000080000000},
1087 : {30, 0x0000000040000000}, {29, 0x0000000020000000},
1088 : {28, 0x0000000010000000}, {27, 0x00000000a8000000},
1089 : {26, 0x00000000f4000000}, {25, 0x0000000062000000},
1090 : {24, 0x0000000091000000}, {23, 0x00000000cd800000},
1091 : {22, 0x0000000009400000}, {21, 0x00000000af200000},
1092 : {20, 0x00000000ac100000}, {19, 0x00000000e0b80000},
1093 : {18, 0x000000009ce40000}, {17, 0x00000000c7920000},
1094 : {16, 0x00000000b8f10000}, {15, 0x000000003b9f8000},
1095 : {14, 0x00000000db4c4000}, {13, 0x00000000e9a32000},
1096 : {12, 0x00000000fca61000}, {11, 0x000000006c8a7800},
1097 : {10, 0x000000008ce5a400}, {9, 0x00000000cb7d0200},
1098 : {8, 0x00000000cb4dc100}, {7, 0x00000000dfbec580},
1099 : {6, 0x0000000027a9db40}, {5, 0x00000000de3bcb20},
1100 : {4, 0x00000000d7e8a610}, {3, 0x000000009afdbc88},
1101 : {2, 0x000000009afdbc84}, {1, 0x000000009afdbc82},
1102 12 : {0, 0x000000009afdbc81}};
1103 :
1104 12 : WasmRunner<int64_t, uint64_t> r(execution_mode);
1105 12 : BUILD(r, WASM_I64_CTZ(WASM_GET_LOCAL(0)));
1106 792 : for (size_t i = 0; i < arraysize(values); i++) {
1107 780 : CHECK_EQ(values[i].expected, r.Call(values[i].input));
1108 : }
1109 : }
1110 :
1111 23742 : WASM_EXEC_TEST(I64Popcnt2) {
1112 12 : REQUIRE(I64Popcnt);
1113 : struct {
1114 : int64_t expected;
1115 : uint64_t input;
1116 : } values[] = {{64, 0xffffffffffffffff},
1117 : {0, 0x0000000000000000},
1118 : {2, 0x0000080000008000},
1119 : {26, 0x1123456782345678},
1120 12 : {38, 0xffedcba09edcba09}};
1121 :
1122 12 : WasmRunner<int64_t, uint64_t> r(execution_mode);
1123 12 : BUILD(r, WASM_I64_POPCNT(WASM_GET_LOCAL(0)));
1124 72 : for (size_t i = 0; i < arraysize(values); i++) {
1125 60 : CHECK_EQ(values[i].expected, r.Call(values[i].input));
1126 : }
1127 : }
1128 :
1129 : // Test the WasmRunner with an Int64 return value and different numbers of
1130 : // Int64 parameters.
1131 23742 : WASM_EXEC_TEST(I64WasmRunner) {
1132 : REQUIRE(I64Param);
1133 : REQUIRE(I64Xor);
1134 984 : {FOR_INT64_INPUTS(i){WasmRunner<int64_t> r(execution_mode);
1135 972 : BUILD(r, WASM_I64V(*i));
1136 972 : CHECK_EQ(*i, r.Call());
1137 : }
1138 : }
1139 : {
1140 12 : WasmRunner<int64_t, int64_t> r(execution_mode);
1141 12 : BUILD(r, WASM_GET_LOCAL(0));
1142 12 : FOR_INT64_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
1143 : }
1144 : {
1145 12 : WasmRunner<int64_t, int64_t, int64_t> r(execution_mode);
1146 12 : BUILD(r, WASM_I64_XOR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
1147 984 : FOR_INT64_INPUTS(i) {
1148 78732 : FOR_INT64_INPUTS(j) { CHECK_EQ(*i ^ *j, r.Call(*i, *j)); }
1149 : }
1150 : }
1151 : {
1152 12 : WasmRunner<int64_t, int64_t, int64_t, int64_t> r(execution_mode);
1153 12 : BUILD(r, WASM_I64_XOR(WASM_GET_LOCAL(0),
1154 : WASM_I64_XOR(WASM_GET_LOCAL(1), WASM_GET_LOCAL(2))));
1155 984 : FOR_INT64_INPUTS(i) {
1156 78732 : FOR_INT64_INPUTS(j) {
1157 78732 : CHECK_EQ(*i ^ *j ^ *j, r.Call(*i, *j, *j));
1158 78732 : CHECK_EQ(*j ^ *i ^ *j, r.Call(*j, *i, *j));
1159 78732 : CHECK_EQ(*j ^ *j ^ *i, r.Call(*j, *j, *i));
1160 : }
1161 : }
1162 : }
1163 : {
1164 12 : WasmRunner<int64_t, int64_t, int64_t, int64_t, int64_t> r(execution_mode);
1165 12 : BUILD(r, WASM_I64_XOR(WASM_GET_LOCAL(0),
1166 : WASM_I64_XOR(WASM_GET_LOCAL(1),
1167 : WASM_I64_XOR(WASM_GET_LOCAL(2),
1168 : WASM_GET_LOCAL(3)))));
1169 984 : FOR_INT64_INPUTS(i) {
1170 78732 : FOR_INT64_INPUTS(j) {
1171 78732 : CHECK_EQ(*i ^ *j ^ *j ^ *j, r.Call(*i, *j, *j, *j));
1172 78732 : CHECK_EQ(*j ^ *i ^ *j ^ *j, r.Call(*j, *i, *j, *j));
1173 78732 : CHECK_EQ(*j ^ *j ^ *i ^ *j, r.Call(*j, *j, *i, *j));
1174 78732 : CHECK_EQ(*j ^ *j ^ *j ^ *i, r.Call(*j, *j, *j, *i));
1175 : }
1176 : }
1177 : }
1178 : }
1179 :
1180 23742 : WASM_EXEC_TEST(Call_Int64Sub) {
1181 12 : REQUIRE(I64Sub);
1182 12 : WasmRunner<int64_t, int64_t, int64_t> r(execution_mode);
1183 : // Build the target function.
1184 12 : TestSignatures sigs;
1185 24 : WasmFunctionCompiler& t = r.NewFunction(sigs.l_ll());
1186 12 : BUILD(t, WASM_I64_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
1187 :
1188 : // Build the caller function.
1189 24 : BUILD(r, WASM_CALL_FUNCTION(t.function_index(), WASM_GET_LOCAL(0),
1190 : WASM_GET_LOCAL(1)));
1191 :
1192 708 : FOR_INT32_INPUTS(i) {
1193 40368 : FOR_INT32_INPUTS(j) {
1194 40368 : int64_t a = static_cast<int64_t>(*i) << 32 |
1195 40368 : (static_cast<int64_t>(*j) | 0xFFFFFFFF);
1196 40368 : int64_t b = static_cast<int64_t>(*j) << 32 |
1197 40368 : (static_cast<int64_t>(*i) | 0xFFFFFFFF);
1198 :
1199 40368 : int64_t expected = static_cast<int64_t>(static_cast<uint64_t>(a) -
1200 40368 : static_cast<uint64_t>(b));
1201 40368 : CHECK_EQ(expected, r.Call(a, b));
1202 : }
1203 : }
1204 : }
1205 :
1206 23742 : WASM_EXEC_TEST(LoadStoreI64_sx) {
1207 : REQUIRE(I64LoadStore);
1208 : REQUIRE(DepthFirst);
1209 : byte loads[] = {kExprI64LoadMem8S, kExprI64LoadMem16S, kExprI64LoadMem32S,
1210 12 : kExprI64LoadMem};
1211 :
1212 60 : for (size_t m = 0; m < arraysize(loads); m++) {
1213 48 : WasmRunner<int64_t> r(execution_mode);
1214 : byte* memory = r.builder().AddMemoryElems<byte>(16);
1215 :
1216 : byte code[] = {
1217 : kExprI32Const, 8, // --
1218 : kExprI32Const, 0, // --
1219 48 : loads[m], // --
1220 : ZERO_ALIGNMENT, // --
1221 : ZERO_OFFSET, // --
1222 : kExprI64StoreMem, // --
1223 : ZERO_ALIGNMENT, // --
1224 : ZERO_OFFSET, // --
1225 : kExprI32Const, 0, // --
1226 : loads[m], // --
1227 : ZERO_ALIGNMENT, // --
1228 : ZERO_OFFSET, // --
1229 96 : };
1230 :
1231 48 : r.Build(code, code + arraysize(code));
1232 :
1233 : // Try a bunch of different negative values.
1234 624 : for (int i = -1; i >= -128; i -= 11) {
1235 576 : int size = 1 << m;
1236 : r.builder().BlankMemory();
1237 576 : memory[size - 1] = static_cast<byte>(i); // set the high order byte.
1238 :
1239 576 : int64_t expected = static_cast<int64_t>(i) << ((size - 1) * 8);
1240 :
1241 576 : CHECK_EQ(expected, r.Call());
1242 576 : CHECK_EQ(static_cast<byte>(i), memory[8 + size - 1]);
1243 2448 : for (int j = size; j < 8; j++) {
1244 4896 : CHECK_EQ(255, memory[8 + j]);
1245 : }
1246 : }
1247 : }
1248 : }
1249 :
1250 23742 : WASM_EXEC_TEST(I64SConvertF32b) {
1251 12 : REQUIRE(I64SConvertF32);
1252 12 : WasmRunner<int64_t, float> r(execution_mode);
1253 12 : BUILD(r, WASM_I64_SCONVERT_F32(WASM_GET_LOCAL(0)));
1254 :
1255 1392 : FOR_FLOAT32_INPUTS(i) {
1256 1380 : if (*i < static_cast<float>(INT64_MAX) &&
1257 : *i >= static_cast<float>(INT64_MIN)) {
1258 996 : CHECK_EQ(static_cast<int64_t>(*i), r.Call(*i));
1259 : } else {
1260 768 : CHECK_TRAP64(r.Call(*i));
1261 : }
1262 : }
1263 : }
1264 :
1265 23742 : WASM_EXEC_TEST(I64SConvertF64b) {
1266 12 : REQUIRE(I64SConvertF64);
1267 12 : WasmRunner<int64_t, double> r(execution_mode);
1268 12 : BUILD(r, WASM_I64_SCONVERT_F64(WASM_GET_LOCAL(0)));
1269 :
1270 600 : FOR_FLOAT64_INPUTS(i) {
1271 588 : if (*i < static_cast<double>(INT64_MAX) &&
1272 : *i >= static_cast<double>(INT64_MIN)) {
1273 456 : CHECK_EQ(static_cast<int64_t>(*i), r.Call(*i));
1274 : } else {
1275 264 : CHECK_TRAP64(r.Call(*i));
1276 : }
1277 : }
1278 : }
1279 :
1280 23742 : WASM_EXEC_TEST(I64UConvertF32b) {
1281 12 : REQUIRE(I64UConvertF32);
1282 12 : WasmRunner<uint64_t, float> r(execution_mode);
1283 12 : BUILD(r, WASM_I64_UCONVERT_F32(WASM_GET_LOCAL(0)));
1284 :
1285 1392 : FOR_FLOAT32_INPUTS(i) {
1286 1380 : if (*i < static_cast<float>(UINT64_MAX) && *i > -1) {
1287 612 : CHECK_EQ(static_cast<uint64_t>(*i), r.Call(*i));
1288 : } else {
1289 768 : CHECK_TRAP64(r.Call(*i));
1290 : }
1291 : }
1292 : }
1293 :
1294 23742 : WASM_EXEC_TEST(I64UConvertF64b) {
1295 12 : REQUIRE(I64UConvertF64);
1296 12 : WasmRunner<uint64_t, double> r(execution_mode);
1297 12 : BUILD(r, WASM_I64_UCONVERT_F64(WASM_GET_LOCAL(0)));
1298 :
1299 600 : FOR_FLOAT64_INPUTS(i) {
1300 588 : if (*i < static_cast<float>(UINT64_MAX) && *i > -1) {
1301 348 : CHECK_EQ(static_cast<uint64_t>(*i), r.Call(*i));
1302 : } else {
1303 240 : CHECK_TRAP64(r.Call(*i));
1304 : }
1305 : }
1306 : }
1307 :
1308 23742 : WASM_EXEC_TEST(I64ReinterpretF64) {
1309 12 : REQUIRE(I64ReinterpretF64);
1310 12 : WasmRunner<int64_t> r(execution_mode);
1311 : int64_t* memory = r.builder().AddMemoryElems<int64_t>(8);
1312 :
1313 12 : BUILD(r, WASM_I64_REINTERPRET_F64(
1314 : WASM_LOAD_MEM(MachineType::Float64(), WASM_ZERO)));
1315 :
1316 708 : FOR_INT32_INPUTS(i) {
1317 696 : int64_t expected = static_cast<int64_t>(*i) * 0x300010001;
1318 : r.builder().WriteMemory(&memory[0], expected);
1319 696 : CHECK_EQ(expected, r.Call());
1320 : }
1321 : }
1322 :
1323 23742 : WASM_EXEC_TEST(SignallingNanSurvivesI64ReinterpretF64) {
1324 12 : REQUIRE(I64ReinterpretF64);
1325 12 : WasmRunner<int64_t> r(execution_mode);
1326 12 : BUILD(r, WASM_I64_REINTERPRET_F64(WASM_SEQ(kExprF64Const, 0x00, 0x00, 0x00,
1327 : 0x00, 0x00, 0x00, 0xf4, 0x7f)));
1328 :
1329 : // This is a signalling nan.
1330 12 : CHECK_EQ(0x7ff4000000000000, r.Call());
1331 : }
1332 :
1333 23742 : WASM_EXEC_TEST(F64ReinterpretI64) {
1334 12 : REQUIRE(F64ReinterpretI64);
1335 12 : WasmRunner<int64_t, int64_t> r(execution_mode);
1336 696 : int64_t* memory = r.builder().AddMemoryElems<int64_t>(8);
1337 :
1338 12 : BUILD(r, WASM_STORE_MEM(MachineType::Float64(), WASM_ZERO,
1339 : WASM_F64_REINTERPRET_I64(WASM_GET_LOCAL(0))),
1340 : WASM_GET_LOCAL(0));
1341 :
1342 708 : FOR_INT32_INPUTS(i) {
1343 696 : int64_t expected = static_cast<int64_t>(*i) * 0x300010001;
1344 696 : CHECK_EQ(expected, r.Call(expected));
1345 696 : CHECK_EQ(expected, r.builder().ReadMemory<int64_t>(&memory[0]));
1346 : }
1347 : }
1348 :
1349 23742 : WASM_EXEC_TEST(LoadMemI64) {
1350 12 : REQUIRE(I64LoadStore);
1351 12 : WasmRunner<int64_t> r(execution_mode);
1352 : int64_t* memory = r.builder().AddMemoryElems<int64_t>(8);
1353 12 : r.builder().RandomizeMemory(1111);
1354 :
1355 12 : BUILD(r, WASM_LOAD_MEM(MachineType::Int64(), WASM_ZERO));
1356 :
1357 : r.builder().WriteMemory<int64_t>(&memory[0], 0x1abbccdd00112233LL);
1358 12 : CHECK_EQ(0x1abbccdd00112233LL, r.Call());
1359 :
1360 : r.builder().WriteMemory<int64_t>(&memory[0], 0x33aabbccdd001122LL);
1361 12 : CHECK_EQ(0x33aabbccdd001122LL, r.Call());
1362 :
1363 : r.builder().WriteMemory<int64_t>(&memory[0], 77777777);
1364 12 : CHECK_EQ(77777777, r.Call());
1365 : }
1366 :
1367 23742 : WASM_EXEC_TEST(LoadMemI64_alignment) {
1368 12 : REQUIRE(I64LoadStore);
1369 60 : for (byte alignment = 0; alignment <= 3; alignment++) {
1370 48 : WasmRunner<int64_t> r(execution_mode);
1371 : int64_t* memory = r.builder().AddMemoryElems<int64_t>(8);
1372 48 : r.builder().RandomizeMemory(1111);
1373 :
1374 48 : BUILD(r,
1375 : WASM_LOAD_MEM_ALIGNMENT(MachineType::Int64(), WASM_ZERO, alignment));
1376 :
1377 : r.builder().WriteMemory<int64_t>(&memory[0], 0x1abbccdd00112233LL);
1378 48 : CHECK_EQ(0x1abbccdd00112233LL, r.Call());
1379 :
1380 : r.builder().WriteMemory<int64_t>(&memory[0], 0x33aabbccdd001122LL);
1381 48 : CHECK_EQ(0x33aabbccdd001122LL, r.Call());
1382 :
1383 : r.builder().WriteMemory<int64_t>(&memory[0], 77777777);
1384 48 : CHECK_EQ(77777777, r.Call());
1385 : }
1386 : }
1387 :
1388 23742 : WASM_EXEC_TEST(MemI64_Sum) {
1389 : REQUIRE(I64LoadStore);
1390 : REQUIRE(I64Add);
1391 : REQUIRE(I64Sub);
1392 : REQUIRE(I64Phi);
1393 : const int kNumElems = 20;
1394 12 : WasmRunner<uint64_t, int32_t> r(execution_mode);
1395 : uint64_t* memory = r.builder().AddMemoryElems<uint64_t>(kNumElems);
1396 : const byte kSum = r.AllocateLocal(kWasmI64);
1397 :
1398 12 : BUILD(r, WASM_WHILE(
1399 : WASM_GET_LOCAL(0),
1400 : WASM_BLOCK(
1401 : WASM_SET_LOCAL(
1402 : kSum, WASM_I64_ADD(WASM_GET_LOCAL(kSum),
1403 : WASM_LOAD_MEM(MachineType::Int64(),
1404 : WASM_GET_LOCAL(0)))),
1405 : WASM_SET_LOCAL(
1406 : 0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I32V_1(8))))),
1407 : WASM_GET_LOCAL(1));
1408 :
1409 : // Run 4 trials.
1410 48 : for (int i = 0; i < 3; i++) {
1411 36 : r.builder().RandomizeMemory(i * 33);
1412 : uint64_t expected = 0;
1413 720 : for (size_t j = kNumElems - 1; j > 0; j--) {
1414 684 : expected += r.builder().ReadMemory(&memory[j]);
1415 : }
1416 36 : uint64_t result = r.Call(8 * (kNumElems - 1));
1417 36 : CHECK_EQ(expected, result);
1418 : }
1419 : }
1420 :
1421 23742 : WASM_EXEC_TEST(StoreMemI64_alignment) {
1422 : const int64_t kWritten = 0x12345678abcd0011ll;
1423 :
1424 60 : for (byte i = 0; i <= 3; i++) {
1425 48 : WasmRunner<int64_t, int64_t> r(execution_mode);
1426 48 : int64_t* memory = r.builder().AddMemoryElems<int64_t>(4);
1427 48 : BUILD(r, WASM_STORE_MEM_ALIGNMENT(MachineType::Int64(), WASM_ZERO, i,
1428 : WASM_GET_LOCAL(0)),
1429 : WASM_GET_LOCAL(0));
1430 48 : r.builder().RandomizeMemory(1111);
1431 : r.builder().WriteMemory<int64_t>(&memory[0], 0);
1432 :
1433 48 : CHECK_EQ(kWritten, r.Call(kWritten));
1434 48 : CHECK_EQ(kWritten, r.builder().ReadMemory(&memory[0]));
1435 : }
1436 12 : }
1437 :
1438 23742 : WASM_EXEC_TEST(I64Global) {
1439 : REQUIRE(I64LoadStore);
1440 : REQUIRE(I64SConvertI32);
1441 : REQUIRE(I64And);
1442 : REQUIRE(DepthFirst);
1443 12 : WasmRunner<int32_t, int32_t> r(execution_mode);
1444 24 : int64_t* global = r.builder().AddGlobal<int64_t>();
1445 : // global = global + p0
1446 12 : BUILD(r, WASM_SET_GLOBAL(
1447 : 0, WASM_I64_AND(WASM_GET_GLOBAL(0),
1448 : WASM_I64_SCONVERT_I32(WASM_GET_LOCAL(0)))),
1449 : WASM_ZERO);
1450 :
1451 : r.builder().WriteMemory<int64_t>(global, 0xFFFFFFFFFFFFFFFFLL);
1452 60 : for (int i = 9; i < 444444; i += 111111) {
1453 48 : int64_t expected = *global & i;
1454 48 : r.Call(i);
1455 48 : CHECK_EQ(expected, *global);
1456 : }
1457 : }
1458 :
1459 23742 : WASM_EXEC_TEST(I64Eqz) {
1460 12 : REQUIRE(I64Eq);
1461 :
1462 12 : WasmRunner<int32_t, int64_t> r(execution_mode);
1463 12 : BUILD(r, WASM_I64_EQZ(WASM_GET_LOCAL(0)));
1464 :
1465 984 : FOR_INT64_INPUTS(i) {
1466 972 : int32_t result = *i == 0 ? 1 : 0;
1467 972 : CHECK_EQ(result, r.Call(*i));
1468 : }
1469 : }
1470 :
1471 23742 : WASM_EXEC_TEST(I64Ror) {
1472 12 : REQUIRE(I64Ror);
1473 12 : WasmRunner<int64_t, int64_t, int64_t> r(execution_mode);
1474 12 : BUILD(r, WASM_I64_ROR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
1475 :
1476 984 : FOR_UINT64_INPUTS(i) {
1477 78732 : FOR_UINT64_INPUTS(j) {
1478 157464 : int64_t expected = base::bits::RotateRight64(*i, *j & 0x3f);
1479 78732 : CHECK_EQ(expected, r.Call(*i, *j));
1480 : }
1481 : }
1482 : }
1483 :
1484 23742 : WASM_EXEC_TEST(I64Rol) {
1485 12 : REQUIRE(I64Rol);
1486 12 : WasmRunner<int64_t, int64_t, int64_t> r(execution_mode);
1487 12 : BUILD(r, WASM_I64_ROL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
1488 :
1489 984 : FOR_UINT64_INPUTS(i) {
1490 78732 : FOR_UINT64_INPUTS(j) {
1491 157464 : int64_t expected = base::bits::RotateLeft64(*i, *j & 0x3f);
1492 78732 : CHECK_EQ(expected, r.Call(*i, *j));
1493 : }
1494 : }
1495 : }
1496 :
1497 23742 : WASM_EXEC_TEST(StoreMem_offset_oob_i64) {
1498 : // TODO(eholk): Fix this test for the trap handler.
1499 24 : if (trap_handler::UseTrapHandler()) return;
1500 : static const MachineType machineTypes[] = {
1501 : MachineType::Int8(), MachineType::Uint8(), MachineType::Int16(),
1502 : MachineType::Uint16(), MachineType::Int32(), MachineType::Uint32(),
1503 : MachineType::Int64(), MachineType::Uint64(), MachineType::Float32(),
1504 : MachineType::Float64()};
1505 :
1506 100 : for (size_t m = 0; m < arraysize(machineTypes); m++) {
1507 100 : WasmRunner<int32_t, uint32_t> r(execution_mode);
1508 : byte* memory = r.builder().AddMemoryElems<byte>(32);
1509 100 : r.builder().RandomizeMemory(1119 + static_cast<int>(m));
1510 :
1511 100 : BUILD(r, WASM_STORE_MEM_OFFSET(machineTypes[m], 8, WASM_GET_LOCAL(0),
1512 : WASM_LOAD_MEM(machineTypes[m], WASM_ZERO)),
1513 : WASM_ZERO);
1514 :
1515 100 : byte memsize = WasmOpcodes::MemSize(machineTypes[m]);
1516 100 : uint32_t boundary = 24 - memsize;
1517 100 : CHECK_EQ(0, r.Call(boundary)); // in bounds.
1518 100 : CHECK_EQ(0, memcmp(&memory[0], &memory[8 + boundary], memsize));
1519 :
1520 1900 : for (uint32_t offset = boundary + 1; offset < boundary + 19; offset++) {
1521 3600 : CHECK_TRAP32(r.Call(offset)); // out of bounds.
1522 : }
1523 : }
1524 : }
1525 :
1526 23742 : WASM_EXEC_TEST(UnalignedInt64Load) {
1527 12 : WasmRunner<uint64_t> r(execution_mode);
1528 : r.builder().AddMemoryElems<int64_t>(8);
1529 12 : BUILD(r, WASM_LOAD_MEM_ALIGNMENT(MachineType::Int64(), WASM_ONE, 3));
1530 12 : r.Call();
1531 12 : }
1532 :
1533 23742 : WASM_EXEC_TEST(UnalignedInt64Store) {
1534 12 : WasmRunner<int32_t> r(execution_mode);
1535 : r.builder().AddMemoryElems<uint64_t>(8);
1536 12 : BUILD(r, WASM_SEQ(WASM_STORE_MEM_ALIGNMENT(MachineType::Int64(), WASM_ONE, 3,
1537 : WASM_I64V_1(1)),
1538 : WASM_I32V_1(12)));
1539 12 : r.Call();
1540 12 : }
1541 :
1542 : #define ADD_CODE(vec, ...) \
1543 : do { \
1544 : byte __buf[] = {__VA_ARGS__}; \
1545 : for (size_t i = 0; i < sizeof(__buf); i++) vec.push_back(__buf[i]); \
1546 : } while (false)
1547 :
1548 6 : static void CompileCallIndirectMany(ValueType param) {
1549 : // Make sure we don't run out of registers when compiling indirect calls
1550 : // with many many parameters.
1551 6 : TestSignatures sigs;
1552 246 : for (byte num_params = 0; num_params < 40; num_params++) {
1553 240 : WasmRunner<void> r(kExecuteCompiled);
1554 240 : FunctionSig* sig = sigs.many(r.zone(), kWasmStmt, param, num_params);
1555 :
1556 240 : r.builder().AddSignature(sig);
1557 240 : r.builder().AddSignature(sig);
1558 240 : r.builder().AddIndirectFunctionTable(nullptr, 0);
1559 :
1560 240 : WasmFunctionCompiler& t = r.NewFunction(sig);
1561 :
1562 : std::vector<byte> code;
1563 4920 : for (byte p = 0; p < num_params; p++) {
1564 4680 : ADD_CODE(code, kExprGetLocal, p);
1565 : }
1566 240 : ADD_CODE(code, kExprI32Const, 0);
1567 240 : ADD_CODE(code, kExprCallIndirect, 1, TABLE_ZERO);
1568 :
1569 480 : t.Build(&code[0], &code[0] + code.size());
1570 : }
1571 6 : }
1572 :
1573 23724 : TEST(Compile_Wasm_CallIndirect_Many_i64) { CompileCallIndirectMany(kWasmI64); }
1574 :
1575 48 : static void Run_WasmMixedCall_N(WasmExecutionMode execution_mode, int start) {
1576 : const int kExpected = 6333;
1577 : const int kElemSize = 8;
1578 48 : TestSignatures sigs;
1579 :
1580 : static MachineType mixed[] = {
1581 : MachineType::Int32(), MachineType::Float32(), MachineType::Int64(),
1582 : MachineType::Float64(), MachineType::Float32(), MachineType::Int64(),
1583 : MachineType::Int32(), MachineType::Float64(), MachineType::Float32(),
1584 : MachineType::Float64(), MachineType::Int32(), MachineType::Int64(),
1585 : MachineType::Int32(), MachineType::Int32()};
1586 :
1587 48 : int num_params = static_cast<int>(arraysize(mixed)) - start;
1588 648 : for (int which = 0; which < num_params; which++) {
1589 600 : v8::internal::AccountingAllocator allocator;
1590 1200 : Zone zone(&allocator, ZONE_NAME);
1591 600 : WasmRunner<int32_t> r(execution_mode);
1592 600 : r.builder().AddMemory(1024);
1593 600 : MachineType* memtypes = &mixed[start];
1594 600 : MachineType result = memtypes[which];
1595 :
1596 : // =========================================================================
1597 : // Build the selector function.
1598 : // =========================================================================
1599 600 : FunctionSig::Builder b(&zone, 1, num_params);
1600 600 : b.AddReturn(WasmOpcodes::ValueTypeFor(result));
1601 8160 : for (int i = 0; i < num_params; i++) {
1602 7560 : b.AddParam(WasmOpcodes::ValueTypeFor(memtypes[i]));
1603 : }
1604 1200 : WasmFunctionCompiler& t = r.NewFunction(b.Build());
1605 600 : BUILD(t, WASM_GET_LOCAL(which));
1606 :
1607 : // =========================================================================
1608 : // Build the calling function.
1609 : // =========================================================================
1610 : std::vector<byte> code;
1611 :
1612 : // Load the arguments.
1613 8760 : for (int i = 0; i < num_params; i++) {
1614 7560 : int offset = (i + 1) * kElemSize;
1615 7560 : ADD_CODE(code, WASM_LOAD_MEM(memtypes[i], WASM_I32V_2(offset)));
1616 : }
1617 :
1618 : // Call the selector function.
1619 1200 : ADD_CODE(code, WASM_CALL_FUNCTION0(t.function_index()));
1620 :
1621 : // Store the result in a local.
1622 600 : byte local_index = r.AllocateLocal(WasmOpcodes::ValueTypeFor(result));
1623 600 : ADD_CODE(code, kExprSetLocal, local_index);
1624 :
1625 : // Store the result in memory.
1626 600 : ADD_CODE(code,
1627 : WASM_STORE_MEM(result, WASM_ZERO, WASM_GET_LOCAL(local_index)));
1628 :
1629 : // Return the expected value.
1630 600 : ADD_CODE(code, WASM_I32V_2(kExpected));
1631 :
1632 1200 : r.Build(&code[0], &code[0] + code.size());
1633 :
1634 : // Run the code.
1635 6600 : for (int t = 0; t < 10; t++) {
1636 6000 : r.builder().RandomizeMemory();
1637 6000 : CHECK_EQ(kExpected, r.Call());
1638 :
1639 6000 : int size = WasmOpcodes::MemSize(result);
1640 41040 : for (int i = 0; i < size; i++) {
1641 35040 : int base = (which + 1) * kElemSize;
1642 35040 : byte expected = r.builder().raw_mem_at<byte>(base + i);
1643 : byte result = r.builder().raw_mem_at<byte>(i);
1644 35040 : CHECK_EQ(expected, result);
1645 : }
1646 : }
1647 600 : }
1648 48 : }
1649 :
1650 23730 : WASM_EXEC_TEST(MixedCall_i64_0) { Run_WasmMixedCall_N(execution_mode, 0); }
1651 23730 : WASM_EXEC_TEST(MixedCall_i64_1) { Run_WasmMixedCall_N(execution_mode, 1); }
1652 23730 : WASM_EXEC_TEST(MixedCall_i64_2) { Run_WasmMixedCall_N(execution_mode, 2); }
1653 23730 : WASM_EXEC_TEST(MixedCall_i64_3) { Run_WasmMixedCall_N(execution_mode, 3); }
1654 :
1655 23742 : WASM_EXEC_TEST(Regress5874) {
1656 : REQUIRE(I32ConvertI64);
1657 : REQUIRE(I64LoadStore);
1658 : REQUIRE(I64Const);
1659 12 : WasmRunner<int32_t> r(execution_mode);
1660 : r.builder().AddMemoryElems<int64_t>(8);
1661 :
1662 12 : BUILD(r, kExprI64Const, 0x00, // --
1663 : kExprI32ConvertI64, // --
1664 : kExprI64Const, 0x00, // --
1665 : kExprI64StoreMem, 0x03, 0x00, // --
1666 : kExprI32Const, 0x00); // --
1667 :
1668 12 : r.Call();
1669 : }
1670 :
1671 23742 : WASM_EXEC_TEST(Regression_6858) {
1672 12 : REQUIRE(I64DivS);
1673 : // WasmRunner with 5 params and returns, which is the maximum.
1674 12 : WasmRunner<int64_t, int64_t, int64_t, int64_t, int64_t> r(execution_mode);
1675 12 : BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
1676 : int64_t dividend = 15;
1677 : int64_t divisor = 0;
1678 : int64_t filler = 34;
1679 24 : CHECK_TRAP64(r.Call(dividend, divisor, filler, filler));
1680 : }
1681 :
1682 : #undef WASM_64
1683 : #undef MIPS
1684 : #undef REQUIRE
1685 : #undef ADD_CODE
1686 :
1687 : // clang-format gets confused about these closing parentheses (wants to change
1688 : // the first comment to "// namespace v8". Disable it.
1689 : // clang-format off
1690 : } // namespace test_run_wasm_64
1691 : } // namespace wasm
1692 : } // namespace internal
1693 71154 : } // namespace v8
1694 : // clang-format on
|