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