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/base/overflowing-math.h"
12 : #include "src/objects-inl.h"
13 :
14 : #include "test/cctest/cctest.h"
15 : #include "test/cctest/compiler/value-helper.h"
16 : #include "test/cctest/wasm/wasm-run-utils.h"
17 : #include "test/common/wasm/test-signatures.h"
18 : #include "test/common/wasm/wasm-macro-gen.h"
19 :
20 : namespace v8 {
21 : namespace internal {
22 : namespace wasm {
23 : namespace test_run_wasm_64 {
24 :
25 28367 : WASM_EXEC_TEST(I64Const) {
26 15 : WasmRunner<int64_t> r(execution_tier);
27 : const int64_t kExpectedValue = 0x1122334455667788LL;
28 : // return(kExpectedValue)
29 15 : BUILD(r, WASM_I64V_9(kExpectedValue));
30 15 : CHECK_EQ(kExpectedValue, r.Call());
31 15 : }
32 :
33 28367 : WASM_EXEC_TEST(I64Const_many) {
34 : int cntr = 0;
35 885 : FOR_INT32_INPUTS(i) {
36 870 : WasmRunner<int64_t> r(execution_tier);
37 870 : const int64_t kExpectedValue = (static_cast<int64_t>(*i) << 32) | cntr;
38 : // return(kExpectedValue)
39 870 : BUILD(r, WASM_I64V(kExpectedValue));
40 870 : CHECK_EQ(kExpectedValue, r.Call());
41 870 : cntr++;
42 : }
43 15 : }
44 :
45 28367 : WASM_EXEC_TEST(Return_I64) {
46 15 : WasmRunner<int64_t, int64_t> r(execution_tier);
47 :
48 15 : BUILD(r, WASM_RETURN1(WASM_GET_LOCAL(0)));
49 :
50 15 : FOR_INT64_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
51 15 : }
52 :
53 28367 : WASM_EXEC_TEST(I64Add) {
54 15 : WasmRunner<int64_t, int64_t, int64_t> r(execution_tier);
55 15 : BUILD(r, WASM_I64_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
56 1230 : FOR_INT64_INPUTS(i) {
57 98415 : FOR_INT64_INPUTS(j) {
58 196830 : CHECK_EQ(base::AddWithWraparound(*i, *j), r.Call(*i, *j));
59 : }
60 : }
61 15 : }
62 :
63 : // The i64 add and subtract regression tests need a 64-bit value with a non-zero
64 : // upper half. This upper half was clobbering eax, leading to the function
65 : // returning 1 rather than 0.
66 : const int64_t kHasBit33On = 0x100000000;
67 :
68 28367 : WASM_EXEC_TEST(Regress5800_Add) {
69 15 : WasmRunner<int32_t> r(execution_tier);
70 15 : BUILD(r, WASM_BLOCK(WASM_BR_IF(0, WASM_I64_EQZ(WASM_I64_ADD(
71 : WASM_I64V(0), WASM_I64V(kHasBit33On)))),
72 : WASM_RETURN1(WASM_I32V(0))),
73 : WASM_I32V(0));
74 15 : CHECK_EQ(0, r.Call());
75 15 : }
76 :
77 28367 : WASM_EXEC_TEST(I64Sub) {
78 15 : WasmRunner<int64_t, int64_t, int64_t> r(execution_tier);
79 15 : BUILD(r, WASM_I64_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
80 1230 : FOR_INT64_INPUTS(i) {
81 98415 : FOR_INT64_INPUTS(j) {
82 196830 : CHECK_EQ(base::SubWithWraparound(*i, *j), r.Call(*i, *j));
83 : }
84 : }
85 15 : }
86 :
87 28367 : WASM_EXEC_TEST(Regress5800_Sub) {
88 15 : WasmRunner<int32_t> r(execution_tier);
89 15 : BUILD(r, WASM_BLOCK(WASM_BR_IF(0, WASM_I64_EQZ(WASM_I64_SUB(
90 : WASM_I64V(0), WASM_I64V(kHasBit33On)))),
91 : WASM_RETURN1(WASM_I32V(0))),
92 : WASM_I32V(0));
93 15 : CHECK_EQ(0, r.Call());
94 15 : }
95 :
96 28367 : WASM_EXEC_TEST(I64AddUseOnlyLowWord) {
97 15 : WasmRunner<int32_t, int64_t, int64_t> r(execution_tier);
98 15 : BUILD(r, WASM_I32_CONVERT_I64(
99 : WASM_I64_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))));
100 1230 : FOR_INT64_INPUTS(i) {
101 98415 : FOR_INT64_INPUTS(j) {
102 196830 : CHECK_EQ(static_cast<int32_t>(base::AddWithWraparound(*i, *j)),
103 : r.Call(*i, *j));
104 : }
105 : }
106 15 : }
107 :
108 28367 : WASM_EXEC_TEST(I64SubUseOnlyLowWord) {
109 15 : WasmRunner<int32_t, int64_t, int64_t> r(execution_tier);
110 15 : BUILD(r, WASM_I32_CONVERT_I64(
111 : WASM_I64_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))));
112 1230 : FOR_INT64_INPUTS(i) {
113 98415 : FOR_INT64_INPUTS(j) {
114 196830 : CHECK_EQ(static_cast<int32_t>(base::SubWithWraparound(*i, *j)),
115 : r.Call(*i, *j));
116 : }
117 : }
118 15 : }
119 :
120 28367 : WASM_EXEC_TEST(I64MulUseOnlyLowWord) {
121 15 : WasmRunner<int32_t, int64_t, int64_t> r(execution_tier);
122 15 : BUILD(r, WASM_I32_CONVERT_I64(
123 : WASM_I64_MUL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))));
124 1230 : FOR_INT64_INPUTS(i) {
125 98415 : FOR_INT64_INPUTS(j) {
126 196830 : CHECK_EQ(static_cast<int32_t>(base::MulWithWraparound(*i, *j)),
127 : r.Call(*i, *j));
128 : }
129 : }
130 15 : }
131 :
132 28367 : WASM_EXEC_TEST(I64ShlUseOnlyLowWord) {
133 15 : WasmRunner<int32_t, int64_t, int64_t> r(execution_tier);
134 15 : BUILD(r, WASM_I32_CONVERT_I64(
135 : WASM_I64_SHL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))));
136 1230 : FOR_INT64_INPUTS(i) {
137 98415 : FOR_INT64_INPUTS(j) {
138 196830 : int32_t expected = static_cast<int32_t>(base::ShlWithWraparound(*i, *j));
139 98415 : CHECK_EQ(expected, r.Call(*i, *j));
140 : }
141 : }
142 15 : }
143 :
144 28367 : WASM_EXEC_TEST(I64ShrUseOnlyLowWord) {
145 15 : WasmRunner<int32_t, int64_t, int64_t> r(execution_tier);
146 15 : BUILD(r, WASM_I32_CONVERT_I64(
147 : WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))));
148 1230 : FOR_UINT64_INPUTS(i) {
149 98415 : FOR_UINT64_INPUTS(j) {
150 98415 : int32_t expected = static_cast<int32_t>((*i) >> (*j & 0x3F));
151 98415 : CHECK_EQ(expected, r.Call(*i, *j));
152 : }
153 : }
154 15 : }
155 :
156 28367 : WASM_EXEC_TEST(I64SarUseOnlyLowWord) {
157 15 : WasmRunner<int32_t, int64_t, int64_t> r(execution_tier);
158 15 : BUILD(r, WASM_I32_CONVERT_I64(
159 : WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))));
160 1230 : FOR_INT64_INPUTS(i) {
161 98415 : FOR_INT64_INPUTS(j) {
162 98415 : int32_t expected = static_cast<int32_t>((*i) >> (*j & 0x3F));
163 98415 : CHECK_EQ(expected, r.Call(*i, *j));
164 : }
165 : }
166 15 : }
167 :
168 28367 : WASM_EXEC_TEST(I64DivS) {
169 15 : WasmRunner<int64_t, int64_t, int64_t> r(execution_tier);
170 15 : BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
171 1230 : FOR_INT64_INPUTS(i) {
172 98415 : FOR_INT64_INPUTS(j) {
173 98415 : if (*j == 0) {
174 4860 : CHECK_TRAP64(r.Call(*i, *j));
175 95985 : } else if (*j == -1 && *i == std::numeric_limits<int64_t>::min()) {
176 0 : CHECK_TRAP64(r.Call(*i, *j));
177 : } else {
178 95985 : CHECK_EQ(*i / *j, r.Call(*i, *j));
179 : }
180 : }
181 : }
182 15 : }
183 :
184 28367 : WASM_EXEC_TEST(I64DivS_Trap) {
185 15 : WasmRunner<int64_t, int64_t, int64_t> r(execution_tier);
186 15 : BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
187 15 : CHECK_EQ(0, r.Call(int64_t{0}, int64_t{100}));
188 30 : CHECK_TRAP64(r.Call(int64_t{100}, int64_t{0}));
189 30 : CHECK_TRAP64(r.Call(int64_t{-1001}, int64_t{0}));
190 30 : CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), int64_t{-1}));
191 30 : CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), int64_t{0}));
192 15 : }
193 :
194 28367 : WASM_EXEC_TEST(I64DivS_Byzero_Const) {
195 165 : for (int8_t denom = -2; denom < 8; denom++) {
196 150 : WasmRunner<int64_t, int64_t> r(execution_tier);
197 150 : BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_I64V_1(denom)));
198 2400 : for (int64_t val = -7; val < 8; val++) {
199 2250 : if (denom == 0) {
200 450 : CHECK_TRAP64(r.Call(val));
201 : } else {
202 2025 : CHECK_EQ(val / denom, r.Call(val));
203 : }
204 : }
205 : }
206 15 : }
207 :
208 28367 : WASM_EXEC_TEST(I64DivU) {
209 15 : WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_tier);
210 15 : BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
211 1230 : FOR_UINT64_INPUTS(i) {
212 98415 : FOR_UINT64_INPUTS(j) {
213 98415 : if (*j == 0) {
214 2430 : CHECK_TRAP64(r.Call(*i, *j));
215 : } else {
216 95985 : CHECK_EQ(*i / *j, r.Call(*i, *j));
217 : }
218 : }
219 : }
220 15 : }
221 :
222 28367 : WASM_EXEC_TEST(I64DivU_Trap) {
223 15 : WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_tier);
224 15 : BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
225 30 : CHECK_EQ(0, r.Call(uint64_t{0}, uint64_t{100}));
226 15 : CHECK_TRAP64(r.Call(uint64_t{100}, uint64_t{0}));
227 15 : CHECK_TRAP64(r.Call(uint64_t{1001}, uint64_t{0}));
228 15 : CHECK_TRAP64(r.Call(std::numeric_limits<uint64_t>::max(), uint64_t{0}));
229 15 : }
230 :
231 28352 : WASM_EXEC_TEST(I64DivU_Byzero_Const) {
232 : for (uint64_t denom = 0xFFFFFFFFFFFFFFFE; denom < 8; denom++) {
233 : WasmRunner<uint64_t, uint64_t> r(execution_tier);
234 : BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_I64V_1(denom)));
235 :
236 : for (uint64_t val = 0xFFFFFFFFFFFFFFF0; val < 8; val++) {
237 : if (denom == 0) {
238 : CHECK_TRAP64(r.Call(val));
239 : } else {
240 : CHECK_EQ(val / denom, r.Call(val));
241 : }
242 : }
243 : }
244 0 : }
245 :
246 28367 : WASM_EXEC_TEST(I64RemS) {
247 15 : WasmRunner<int64_t, int64_t, int64_t> r(execution_tier);
248 15 : BUILD(r, WASM_I64_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
249 1230 : FOR_INT64_INPUTS(i) {
250 98415 : FOR_INT64_INPUTS(j) {
251 98415 : if (*j == 0) {
252 4860 : CHECK_TRAP64(r.Call(*i, *j));
253 : } else {
254 95985 : CHECK_EQ(*i % *j, r.Call(*i, *j));
255 : }
256 : }
257 : }
258 15 : }
259 :
260 28367 : WASM_EXEC_TEST(I64RemS_Trap) {
261 15 : WasmRunner<int64_t, int64_t, int64_t> r(execution_tier);
262 15 : BUILD(r, WASM_I64_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
263 15 : CHECK_EQ(33, r.Call(int64_t{133}, int64_t{100}));
264 15 : CHECK_EQ(0, r.Call(std::numeric_limits<int64_t>::min(), int64_t{-1}));
265 30 : CHECK_TRAP64(r.Call(int64_t{100}, int64_t{0}));
266 30 : CHECK_TRAP64(r.Call(int64_t{-1001}, int64_t{0}));
267 30 : CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), int64_t{0}));
268 15 : }
269 :
270 28367 : WASM_EXEC_TEST(I64RemU) {
271 15 : WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_tier);
272 15 : BUILD(r, WASM_I64_REMU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
273 1230 : FOR_UINT64_INPUTS(i) {
274 98415 : FOR_UINT64_INPUTS(j) {
275 98415 : if (*j == 0) {
276 2430 : CHECK_TRAP64(r.Call(*i, *j));
277 : } else {
278 95985 : CHECK_EQ(*i % *j, r.Call(*i, *j));
279 : }
280 : }
281 : }
282 15 : }
283 :
284 28367 : WASM_EXEC_TEST(I64RemU_Trap) {
285 15 : WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_tier);
286 15 : BUILD(r, WASM_I64_REMU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
287 30 : CHECK_EQ(17, r.Call(uint64_t{217}, uint64_t{100}));
288 15 : CHECK_TRAP64(r.Call(uint64_t{100}, uint64_t{0}));
289 15 : CHECK_TRAP64(r.Call(uint64_t{1001}, uint64_t{0}));
290 15 : CHECK_TRAP64(r.Call(std::numeric_limits<uint64_t>::max(), uint64_t{0}));
291 15 : }
292 :
293 28367 : WASM_EXEC_TEST(I64And) {
294 15 : WasmRunner<int64_t, int64_t, int64_t> r(execution_tier);
295 15 : BUILD(r, WASM_I64_AND(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
296 1230 : FOR_INT64_INPUTS(i) {
297 98415 : FOR_INT64_INPUTS(j) { CHECK_EQ((*i) & (*j), r.Call(*i, *j)); }
298 : }
299 15 : }
300 :
301 28367 : WASM_EXEC_TEST(I64Ior) {
302 15 : WasmRunner<int64_t, int64_t, int64_t> r(execution_tier);
303 15 : BUILD(r, WASM_I64_IOR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
304 1230 : FOR_INT64_INPUTS(i) {
305 98415 : FOR_INT64_INPUTS(j) { CHECK_EQ((*i) | (*j), r.Call(*i, *j)); }
306 : }
307 15 : }
308 :
309 28367 : WASM_EXEC_TEST(I64Xor) {
310 15 : WasmRunner<int64_t, int64_t, int64_t> r(execution_tier);
311 15 : BUILD(r, WASM_I64_XOR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
312 1230 : FOR_INT64_INPUTS(i) {
313 98415 : FOR_INT64_INPUTS(j) { CHECK_EQ((*i) ^ (*j), r.Call(*i, *j)); }
314 : }
315 15 : }
316 :
317 28367 : WASM_EXEC_TEST(I64Shl) {
318 : {
319 15 : WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_tier);
320 15 : BUILD(r, WASM_I64_SHL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
321 :
322 1230 : FOR_UINT64_INPUTS(i) {
323 98415 : FOR_UINT64_INPUTS(j) {
324 98415 : uint64_t expected = (*i) << (*j & 0x3F);
325 98415 : CHECK_EQ(expected, r.Call(*i, *j));
326 : }
327 : }
328 : }
329 : {
330 15 : WasmRunner<uint64_t, int64_t> r(execution_tier);
331 15 : BUILD(r, WASM_I64_SHL(WASM_GET_LOCAL(0), WASM_I64V_1(0)));
332 15 : FOR_UINT64_INPUTS(i) { CHECK_EQ(*i << 0, r.Call(*i)); }
333 : }
334 : {
335 15 : WasmRunner<uint64_t, int64_t> r(execution_tier);
336 15 : BUILD(r, WASM_I64_SHL(WASM_GET_LOCAL(0), WASM_I64V_1(32)));
337 15 : FOR_UINT64_INPUTS(i) { CHECK_EQ(*i << 32, r.Call(*i)); }
338 : }
339 : {
340 15 : WasmRunner<uint64_t, int64_t> r(execution_tier);
341 15 : BUILD(r, WASM_I64_SHL(WASM_GET_LOCAL(0), WASM_I64V_1(20)));
342 15 : FOR_UINT64_INPUTS(i) { CHECK_EQ(*i << 20, r.Call(*i)); }
343 : }
344 : {
345 15 : WasmRunner<uint64_t, int64_t> r(execution_tier);
346 15 : BUILD(r, WASM_I64_SHL(WASM_GET_LOCAL(0), WASM_I64V_1(40)));
347 15 : FOR_UINT64_INPUTS(i) { CHECK_EQ(*i << 40, r.Call(*i)); }
348 : }
349 15 : }
350 :
351 28367 : WASM_EXEC_TEST(I64ShrU) {
352 : {
353 15 : WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_tier);
354 15 : BUILD(r, WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
355 :
356 1230 : FOR_UINT64_INPUTS(i) {
357 98415 : FOR_UINT64_INPUTS(j) {
358 98415 : uint64_t expected = (*i) >> (*j & 0x3F);
359 98415 : CHECK_EQ(expected, r.Call(*i, *j));
360 : }
361 : }
362 : }
363 : {
364 15 : WasmRunner<uint64_t, int64_t> r(execution_tier);
365 15 : BUILD(r, WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_I64V_1(0)));
366 15 : FOR_UINT64_INPUTS(i) { CHECK_EQ(*i >> 0, r.Call(*i)); }
367 : }
368 : {
369 15 : WasmRunner<uint64_t, int64_t> r(execution_tier);
370 15 : BUILD(r, WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_I64V_1(32)));
371 15 : FOR_UINT64_INPUTS(i) { CHECK_EQ(*i >> 32, r.Call(*i)); }
372 : }
373 : {
374 15 : WasmRunner<uint64_t, int64_t> r(execution_tier);
375 15 : BUILD(r, WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_I64V_1(20)));
376 15 : FOR_UINT64_INPUTS(i) { CHECK_EQ(*i >> 20, r.Call(*i)); }
377 : }
378 : {
379 15 : WasmRunner<uint64_t, int64_t> r(execution_tier);
380 15 : BUILD(r, WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_I64V_1(40)));
381 15 : FOR_UINT64_INPUTS(i) { CHECK_EQ(*i >> 40, r.Call(*i)); }
382 : }
383 15 : }
384 :
385 28367 : WASM_EXEC_TEST(I64ShrS) {
386 : {
387 15 : WasmRunner<int64_t, int64_t, int64_t> r(execution_tier);
388 15 : BUILD(r, WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
389 :
390 1230 : FOR_INT64_INPUTS(i) {
391 98415 : FOR_INT64_INPUTS(j) {
392 98415 : int64_t expected = (*i) >> (*j & 0x3F);
393 98415 : CHECK_EQ(expected, r.Call(*i, *j));
394 : }
395 : }
396 : }
397 : {
398 15 : WasmRunner<int64_t, int64_t> r(execution_tier);
399 15 : BUILD(r, WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_I64V_1(0)));
400 15 : FOR_INT64_INPUTS(i) { CHECK_EQ(*i >> 0, r.Call(*i)); }
401 : }
402 : {
403 15 : WasmRunner<int64_t, int64_t> r(execution_tier);
404 15 : BUILD(r, WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_I64V_1(32)));
405 15 : FOR_INT64_INPUTS(i) { CHECK_EQ(*i >> 32, r.Call(*i)); }
406 : }
407 : {
408 15 : WasmRunner<int64_t, int64_t> r(execution_tier);
409 15 : BUILD(r, WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_I64V_1(20)));
410 15 : FOR_INT64_INPUTS(i) { CHECK_EQ(*i >> 20, r.Call(*i)); }
411 : }
412 : {
413 15 : WasmRunner<int64_t, int64_t> r(execution_tier);
414 15 : BUILD(r, WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_I64V_1(40)));
415 15 : FOR_INT64_INPUTS(i) { CHECK_EQ(*i >> 40, r.Call(*i)); }
416 : }
417 15 : }
418 :
419 28367 : WASM_EXEC_TEST(I64Eq) {
420 15 : WasmRunner<int32_t, int64_t, int64_t> r(execution_tier);
421 15 : BUILD(r, WASM_I64_EQ(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
422 1230 : FOR_INT64_INPUTS(i) {
423 98415 : FOR_INT64_INPUTS(j) { CHECK_EQ(*i == *j ? 1 : 0, r.Call(*i, *j)); }
424 : }
425 15 : }
426 :
427 28367 : WASM_EXEC_TEST(I64Ne) {
428 15 : WasmRunner<int32_t, int64_t, int64_t> r(execution_tier);
429 15 : BUILD(r, WASM_I64_NE(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
430 1230 : FOR_INT64_INPUTS(i) {
431 98415 : FOR_INT64_INPUTS(j) { CHECK_EQ(*i != *j ? 1 : 0, r.Call(*i, *j)); }
432 : }
433 15 : }
434 :
435 28367 : WASM_EXEC_TEST(I64LtS) {
436 15 : WasmRunner<int32_t, int64_t, int64_t> r(execution_tier);
437 15 : BUILD(r, WASM_I64_LTS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
438 1230 : FOR_INT64_INPUTS(i) {
439 98415 : FOR_INT64_INPUTS(j) { CHECK_EQ(*i < *j ? 1 : 0, r.Call(*i, *j)); }
440 : }
441 15 : }
442 :
443 28367 : WASM_EXEC_TEST(I64LeS) {
444 15 : WasmRunner<int32_t, int64_t, int64_t> r(execution_tier);
445 15 : BUILD(r, WASM_I64_LES(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
446 1230 : FOR_INT64_INPUTS(i) {
447 98415 : FOR_INT64_INPUTS(j) { CHECK_EQ(*i <= *j ? 1 : 0, r.Call(*i, *j)); }
448 : }
449 15 : }
450 :
451 28367 : WASM_EXEC_TEST(I64LtU) {
452 15 : WasmRunner<int32_t, int64_t, int64_t> r(execution_tier);
453 15 : BUILD(r, WASM_I64_LTU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
454 1230 : FOR_UINT64_INPUTS(i) {
455 98415 : FOR_UINT64_INPUTS(j) { CHECK_EQ(*i < *j ? 1 : 0, r.Call(*i, *j)); }
456 : }
457 15 : }
458 :
459 28367 : WASM_EXEC_TEST(I64LeU) {
460 15 : WasmRunner<int32_t, int64_t, int64_t> r(execution_tier);
461 15 : BUILD(r, WASM_I64_LEU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
462 1230 : FOR_UINT64_INPUTS(i) {
463 98415 : FOR_UINT64_INPUTS(j) { CHECK_EQ(*i <= *j ? 1 : 0, r.Call(*i, *j)); }
464 : }
465 15 : }
466 :
467 28367 : WASM_EXEC_TEST(I64GtS) {
468 15 : WasmRunner<int32_t, int64_t, int64_t> r(execution_tier);
469 15 : BUILD(r, WASM_I64_GTS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
470 1230 : FOR_INT64_INPUTS(i) {
471 98415 : FOR_INT64_INPUTS(j) { CHECK_EQ(*i > *j ? 1 : 0, r.Call(*i, *j)); }
472 : }
473 15 : }
474 :
475 28367 : WASM_EXEC_TEST(I64GeS) {
476 15 : WasmRunner<int32_t, int64_t, int64_t> r(execution_tier);
477 15 : BUILD(r, WASM_I64_GES(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
478 1230 : FOR_INT64_INPUTS(i) {
479 98415 : FOR_INT64_INPUTS(j) { CHECK_EQ(*i >= *j ? 1 : 0, r.Call(*i, *j)); }
480 : }
481 15 : }
482 :
483 28367 : WASM_EXEC_TEST(I64GtU) {
484 15 : WasmRunner<int32_t, int64_t, int64_t> r(execution_tier);
485 15 : BUILD(r, WASM_I64_GTU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
486 1230 : FOR_UINT64_INPUTS(i) {
487 98415 : FOR_UINT64_INPUTS(j) { CHECK_EQ(*i > *j ? 1 : 0, r.Call(*i, *j)); }
488 : }
489 15 : }
490 :
491 28367 : WASM_EXEC_TEST(I64GeU) {
492 15 : WasmRunner<int32_t, int64_t, int64_t> r(execution_tier);
493 15 : BUILD(r, WASM_I64_GEU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
494 1230 : FOR_UINT64_INPUTS(i) {
495 98415 : FOR_UINT64_INPUTS(j) { CHECK_EQ(*i >= *j ? 1 : 0, r.Call(*i, *j)); }
496 : }
497 15 : }
498 :
499 28367 : WASM_EXEC_TEST(I32ConvertI64) {
500 1230 : FOR_INT64_INPUTS(i) {
501 1215 : WasmRunner<int32_t> r(execution_tier);
502 1215 : BUILD(r, WASM_I32_CONVERT_I64(WASM_I64V(*i)));
503 1215 : CHECK_EQ(static_cast<int32_t>(*i), r.Call());
504 : }
505 15 : }
506 :
507 28367 : WASM_EXEC_TEST(I64SConvertI32) {
508 15 : WasmRunner<int64_t, int32_t> r(execution_tier);
509 15 : BUILD(r, WASM_I64_SCONVERT_I32(WASM_GET_LOCAL(0)));
510 15 : FOR_INT32_INPUTS(i) { CHECK_EQ(static_cast<int64_t>(*i), r.Call(*i)); }
511 15 : }
512 :
513 28367 : WASM_EXEC_TEST(I64UConvertI32) {
514 15 : WasmRunner<int64_t, uint32_t> r(execution_tier);
515 15 : BUILD(r, WASM_I64_UCONVERT_I32(WASM_GET_LOCAL(0)));
516 15 : FOR_UINT32_INPUTS(i) { CHECK_EQ(static_cast<int64_t>(*i), r.Call(*i)); }
517 15 : }
518 :
519 28367 : WASM_EXEC_TEST(I64Popcnt) {
520 : struct {
521 : int64_t expected;
522 : uint64_t input;
523 : } values[] = {{64, 0xFFFFFFFFFFFFFFFF},
524 : {0, 0x0000000000000000},
525 : {2, 0x0000080000008000},
526 : {26, 0x1123456782345678},
527 15 : {38, 0xFFEDCBA09EDCBA09}};
528 :
529 15 : WasmRunner<int64_t, uint64_t> r(execution_tier);
530 15 : BUILD(r, WASM_I64_POPCNT(WASM_GET_LOCAL(0)));
531 90 : for (size_t i = 0; i < arraysize(values); i++) {
532 75 : CHECK_EQ(values[i].expected, r.Call(values[i].input));
533 : }
534 15 : }
535 :
536 28367 : WASM_EXEC_TEST(F32SConvertI64) {
537 15 : WasmRunner<float, int64_t> r(execution_tier);
538 15 : BUILD(r, WASM_F32_SCONVERT_I64(WASM_GET_LOCAL(0)));
539 2445 : FOR_INT64_INPUTS(i) { CHECK_FLOAT_EQ(static_cast<float>(*i), r.Call(*i)); }
540 15 : }
541 :
542 28367 : WASM_EXEC_TEST(F32UConvertI64) {
543 : struct {
544 : uint64_t input;
545 : uint32_t expected;
546 : } values[] = {{0x0, 0x0},
547 : {0x1, 0x3F800000},
548 : {0xFFFFFFFF, 0x4F800000},
549 : {0x1B09788B, 0x4DD84BC4},
550 : {0x4C5FCE8, 0x4C98BF9D},
551 : {0xCC0DE5BF, 0x4F4C0DE6},
552 : {0x2, 0x40000000},
553 : {0x3, 0x40400000},
554 : {0x4, 0x40800000},
555 : {0x5, 0x40A00000},
556 : {0x8, 0x41000000},
557 : {0x9, 0x41100000},
558 : {0xFFFFFFFFFFFFFFFF, 0x5F800000},
559 : {0xFFFFFFFFFFFFFFFE, 0x5F800000},
560 : {0xFFFFFFFFFFFFFFFD, 0x5F800000},
561 : {0x0, 0x0},
562 : {0x100000000, 0x4F800000},
563 : {0xFFFFFFFF00000000, 0x5F800000},
564 : {0x1B09788B00000000, 0x5DD84BC4},
565 : {0x4C5FCE800000000, 0x5C98BF9D},
566 : {0xCC0DE5BF00000000, 0x5F4C0DE6},
567 : {0x200000000, 0x50000000},
568 : {0x300000000, 0x50400000},
569 : {0x400000000, 0x50800000},
570 : {0x500000000, 0x50A00000},
571 : {0x800000000, 0x51000000},
572 : {0x900000000, 0x51100000},
573 : {0x273A798E187937A3, 0x5E1CE9E6},
574 : {0xECE3AF835495A16B, 0x5F6CE3B0},
575 : {0xB668ECC11223344, 0x5D3668ED},
576 : {0x9E, 0x431E0000},
577 : {0x43, 0x42860000},
578 : {0xAF73, 0x472F7300},
579 : {0x116B, 0x458B5800},
580 : {0x658ECC, 0x4ACB1D98},
581 : {0x2B3B4C, 0x4A2CED30},
582 : {0x88776655, 0x4F087766},
583 : {0x70000000, 0x4EE00000},
584 : {0x7200000, 0x4CE40000},
585 : {0x7FFFFFFF, 0x4F000000},
586 : {0x56123761, 0x4EAC246F},
587 : {0x7FFFFF00, 0x4EFFFFFE},
588 : {0x761C4761EEEEEEEE, 0x5EEC388F},
589 : {0x80000000EEEEEEEE, 0x5F000000},
590 : {0x88888888DDDDDDDD, 0x5F088889},
591 : {0xA0000000DDDDDDDD, 0x5F200000},
592 : {0xDDDDDDDDAAAAAAAA, 0x5F5DDDDE},
593 : {0xE0000000AAAAAAAA, 0x5F600000},
594 : {0xEEEEEEEEEEEEEEEE, 0x5F6EEEEF},
595 : {0xFFFFFFFDEEEEEEEE, 0x5F800000},
596 : {0xF0000000DDDDDDDD, 0x5F700000},
597 : {0x7FFFFFDDDDDDDD, 0x5B000000},
598 : {0x3FFFFFAAAAAAAA, 0x5A7FFFFF},
599 : {0x1FFFFFAAAAAAAA, 0x59FFFFFD},
600 : {0xFFFFF, 0x497FFFF0},
601 : {0x7FFFF, 0x48FFFFE0},
602 : {0x3FFFF, 0x487FFFC0},
603 : {0x1FFFF, 0x47FFFF80},
604 : {0xFFFF, 0x477FFF00},
605 : {0x7FFF, 0x46FFFE00},
606 : {0x3FFF, 0x467FFC00},
607 : {0x1FFF, 0x45FFF800},
608 : {0xFFF, 0x457FF000},
609 : {0x7FF, 0x44FFE000},
610 : {0x3FF, 0x447FC000},
611 : {0x1FF, 0x43FF8000},
612 : {0x3FFFFFFFFFFF, 0x56800000},
613 : {0x1FFFFFFFFFFF, 0x56000000},
614 : {0xFFFFFFFFFFF, 0x55800000},
615 : {0x7FFFFFFFFFF, 0x55000000},
616 : {0x3FFFFFFFFFF, 0x54800000},
617 : {0x1FFFFFFFFFF, 0x54000000},
618 : {0x8000008000000000, 0x5F000000},
619 : {0x8000008000000001, 0x5F000001},
620 : {0x8000000000000400, 0x5F000000},
621 15 : {0x8000000000000401, 0x5F000000}};
622 15 : WasmRunner<float, uint64_t> r(execution_tier);
623 15 : BUILD(r, WASM_F32_UCONVERT_I64(WASM_GET_LOCAL(0)));
624 1155 : for (size_t i = 0; i < arraysize(values); i++) {
625 2280 : CHECK_EQ(bit_cast<float>(values[i].expected), r.Call(values[i].input));
626 : }
627 15 : }
628 :
629 28367 : WASM_EXEC_TEST(F64SConvertI64) {
630 15 : WasmRunner<double, int64_t> r(execution_tier);
631 15 : BUILD(r, WASM_F64_SCONVERT_I64(WASM_GET_LOCAL(0)));
632 2445 : FOR_INT64_INPUTS(i) { CHECK_DOUBLE_EQ(static_cast<double>(*i), r.Call(*i)); }
633 15 : }
634 :
635 28367 : WASM_EXEC_TEST(F64UConvertI64) {
636 : struct {
637 : uint64_t input;
638 : uint64_t expected;
639 : } values[] = {{0x0, 0x0},
640 : {0x1, 0x3FF0000000000000},
641 : {0xFFFFFFFF, 0x41EFFFFFFFE00000},
642 : {0x1B09788B, 0x41BB09788B000000},
643 : {0x4C5FCE8, 0x419317F3A0000000},
644 : {0xCC0DE5BF, 0x41E981BCB7E00000},
645 : {0x2, 0x4000000000000000},
646 : {0x3, 0x4008000000000000},
647 : {0x4, 0x4010000000000000},
648 : {0x5, 0x4014000000000000},
649 : {0x8, 0x4020000000000000},
650 : {0x9, 0x4022000000000000},
651 : {0xFFFFFFFFFFFFFFFF, 0x43F0000000000000},
652 : {0xFFFFFFFFFFFFFFFE, 0x43F0000000000000},
653 : {0xFFFFFFFFFFFFFFFD, 0x43F0000000000000},
654 : {0x100000000, 0x41F0000000000000},
655 : {0xFFFFFFFF00000000, 0x43EFFFFFFFE00000},
656 : {0x1B09788B00000000, 0x43BB09788B000000},
657 : {0x4C5FCE800000000, 0x439317F3A0000000},
658 : {0xCC0DE5BF00000000, 0x43E981BCB7E00000},
659 : {0x200000000, 0x4200000000000000},
660 : {0x300000000, 0x4208000000000000},
661 : {0x400000000, 0x4210000000000000},
662 : {0x500000000, 0x4214000000000000},
663 : {0x800000000, 0x4220000000000000},
664 : {0x900000000, 0x4222000000000000},
665 : {0x273A798E187937A3, 0x43C39D3CC70C3C9C},
666 : {0xECE3AF835495A16B, 0x43ED9C75F06A92B4},
667 : {0xB668ECC11223344, 0x43A6CD1D98224467},
668 : {0x9E, 0x4063C00000000000},
669 : {0x43, 0x4050C00000000000},
670 : {0xAF73, 0x40E5EE6000000000},
671 : {0x116B, 0x40B16B0000000000},
672 : {0x658ECC, 0x415963B300000000},
673 : {0x2B3B4C, 0x41459DA600000000},
674 : {0x88776655, 0x41E10EECCAA00000},
675 : {0x70000000, 0x41DC000000000000},
676 : {0x7200000, 0x419C800000000000},
677 : {0x7FFFFFFF, 0x41DFFFFFFFC00000},
678 : {0x56123761, 0x41D5848DD8400000},
679 : {0x7FFFFF00, 0x41DFFFFFC0000000},
680 : {0x761C4761EEEEEEEE, 0x43DD8711D87BBBBC},
681 : {0x80000000EEEEEEEE, 0x43E00000001DDDDE},
682 : {0x88888888DDDDDDDD, 0x43E11111111BBBBC},
683 : {0xA0000000DDDDDDDD, 0x43E40000001BBBBC},
684 : {0xDDDDDDDDAAAAAAAA, 0x43EBBBBBBBB55555},
685 : {0xE0000000AAAAAAAA, 0x43EC000000155555},
686 : {0xEEEEEEEEEEEEEEEE, 0x43EDDDDDDDDDDDDE},
687 : {0xFFFFFFFDEEEEEEEE, 0x43EFFFFFFFBDDDDE},
688 : {0xF0000000DDDDDDDD, 0x43EE0000001BBBBC},
689 : {0x7FFFFFDDDDDDDD, 0x435FFFFFF7777777},
690 : {0x3FFFFFAAAAAAAA, 0x434FFFFFD5555555},
691 : {0x1FFFFFAAAAAAAA, 0x433FFFFFAAAAAAAA},
692 : {0xFFFFF, 0x412FFFFE00000000},
693 : {0x7FFFF, 0x411FFFFC00000000},
694 : {0x3FFFF, 0x410FFFF800000000},
695 : {0x1FFFF, 0x40FFFFF000000000},
696 : {0xFFFF, 0x40EFFFE000000000},
697 : {0x7FFF, 0x40DFFFC000000000},
698 : {0x3FFF, 0x40CFFF8000000000},
699 : {0x1FFF, 0x40BFFF0000000000},
700 : {0xFFF, 0x40AFFE0000000000},
701 : {0x7FF, 0x409FFC0000000000},
702 : {0x3FF, 0x408FF80000000000},
703 : {0x1FF, 0x407FF00000000000},
704 : {0x3FFFFFFFFFFF, 0x42CFFFFFFFFFFF80},
705 : {0x1FFFFFFFFFFF, 0x42BFFFFFFFFFFF00},
706 : {0xFFFFFFFFFFF, 0x42AFFFFFFFFFFE00},
707 : {0x7FFFFFFFFFF, 0x429FFFFFFFFFFC00},
708 : {0x3FFFFFFFFFF, 0x428FFFFFFFFFF800},
709 : {0x1FFFFFFFFFF, 0x427FFFFFFFFFF000},
710 : {0x8000008000000000, 0x43E0000010000000},
711 : {0x8000008000000001, 0x43E0000010000000},
712 : {0x8000000000000400, 0x43E0000000000000},
713 15 : {0x8000000000000401, 0x43E0000000000001}};
714 15 : WasmRunner<double, uint64_t> r(execution_tier);
715 15 : BUILD(r, WASM_F64_UCONVERT_I64(WASM_GET_LOCAL(0)));
716 1140 : for (size_t i = 0; i < arraysize(values); i++) {
717 2250 : CHECK_EQ(bit_cast<double>(values[i].expected), r.Call(values[i].input));
718 : }
719 15 : }
720 :
721 28367 : WASM_EXEC_TEST(I64SConvertF32) {
722 15 : WasmRunner<int64_t, float> r(execution_tier);
723 15 : BUILD(r, WASM_I64_SCONVERT_F32(WASM_GET_LOCAL(0)));
724 :
725 1740 : FOR_FLOAT32_INPUTS(i) {
726 1725 : if (*i < static_cast<float>(std::numeric_limits<int64_t>::max()) &&
727 : *i >= static_cast<float>(std::numeric_limits<int64_t>::min())) {
728 1245 : CHECK_EQ(static_cast<int64_t>(*i), r.Call(*i));
729 : } else {
730 960 : CHECK_TRAP64(r.Call(*i));
731 : }
732 : }
733 15 : }
734 :
735 28367 : WASM_EXEC_TEST(I64SConvertSatF32) {
736 : EXPERIMENTAL_FLAG_SCOPE(sat_f2i_conversions);
737 15 : WasmRunner<int64_t, float> r(execution_tier);
738 15 : BUILD(r, WASM_I64_SCONVERT_SAT_F32(WASM_GET_LOCAL(0)));
739 1740 : FOR_FLOAT32_INPUTS(i) {
740 : int64_t expected;
741 1725 : if (*i < static_cast<float>(std::numeric_limits<int64_t>::max()) &&
742 : *i >= static_cast<float>(std::numeric_limits<int64_t>::min())) {
743 1245 : expected = static_cast<int64_t>(*i);
744 480 : } else if (std::isnan(*i)) {
745 : expected = static_cast<int64_t>(0);
746 450 : } else if (*i < 0.0) {
747 : expected = std::numeric_limits<int64_t>::min();
748 : } else {
749 : expected = std::numeric_limits<int64_t>::max();
750 : }
751 1725 : int64_t found = r.Call(*i);
752 1725 : CHECK_EQ(expected, found);
753 : }
754 15 : }
755 :
756 28367 : WASM_EXEC_TEST(I64SConvertF64) {
757 15 : WasmRunner<int64_t, double> r(execution_tier);
758 15 : BUILD(r, WASM_I64_SCONVERT_F64(WASM_GET_LOCAL(0)));
759 :
760 750 : FOR_FLOAT64_INPUTS(i) {
761 735 : if (*i < static_cast<double>(std::numeric_limits<int64_t>::max()) &&
762 : *i >= static_cast<double>(std::numeric_limits<int64_t>::min())) {
763 570 : CHECK_EQ(static_cast<int64_t>(*i), r.Call(*i));
764 : } else {
765 330 : CHECK_TRAP64(r.Call(*i));
766 : }
767 : }
768 15 : }
769 :
770 28367 : WASM_EXEC_TEST(I64SConvertSatF64) {
771 : EXPERIMENTAL_FLAG_SCOPE(sat_f2i_conversions);
772 15 : WasmRunner<int64_t, double> r(execution_tier);
773 15 : BUILD(r, WASM_I64_SCONVERT_SAT_F64(WASM_GET_LOCAL(0)));
774 750 : FOR_FLOAT64_INPUTS(i) {
775 : int64_t expected;
776 735 : if (*i < static_cast<double>(std::numeric_limits<int64_t>::max()) &&
777 : *i >= static_cast<double>(std::numeric_limits<int64_t>::min())) {
778 570 : expected = static_cast<int64_t>(*i);
779 165 : } else if (std::isnan(*i)) {
780 : expected = static_cast<int64_t>(0);
781 135 : } else if (*i < 0.0) {
782 : expected = std::numeric_limits<int64_t>::min();
783 : } else {
784 : expected = std::numeric_limits<int64_t>::max();
785 : }
786 735 : int64_t found = r.Call(*i);
787 735 : CHECK_EQ(expected, found);
788 : }
789 15 : }
790 :
791 28367 : WASM_EXEC_TEST(I64UConvertF32) {
792 15 : WasmRunner<uint64_t, float> r(execution_tier);
793 15 : BUILD(r, WASM_I64_UCONVERT_F32(WASM_GET_LOCAL(0)));
794 :
795 1740 : FOR_FLOAT32_INPUTS(i) {
796 1725 : if (*i < static_cast<float>(std::numeric_limits<uint64_t>::max()) &&
797 : *i > -1) {
798 765 : CHECK_EQ(static_cast<uint64_t>(*i), r.Call(*i));
799 : } else {
800 960 : CHECK_TRAP64(r.Call(*i));
801 : }
802 : }
803 15 : }
804 :
805 28367 : WASM_EXEC_TEST(I64UConvertSatF32) {
806 : EXPERIMENTAL_FLAG_SCOPE(sat_f2i_conversions);
807 15 : WasmRunner<int64_t, float> r(execution_tier);
808 15 : BUILD(r, WASM_I64_UCONVERT_SAT_F32(WASM_GET_LOCAL(0)));
809 1740 : FOR_FLOAT32_INPUTS(i) {
810 : uint64_t expected;
811 1725 : if (*i < static_cast<float>(std::numeric_limits<uint64_t>::max()) &&
812 : *i > -1) {
813 765 : expected = static_cast<uint64_t>(*i);
814 960 : } else if (std::isnan(*i)) {
815 : expected = static_cast<uint64_t>(0);
816 930 : } else if (*i < 0.0) {
817 : expected = std::numeric_limits<uint64_t>::min();
818 : } else {
819 : expected = std::numeric_limits<uint64_t>::max();
820 : }
821 1725 : uint64_t found = r.Call(*i);
822 1725 : CHECK_EQ(expected, found);
823 : }
824 15 : }
825 :
826 28367 : WASM_EXEC_TEST(I64UConvertF64) {
827 15 : WasmRunner<uint64_t, double> r(execution_tier);
828 15 : BUILD(r, WASM_I64_UCONVERT_F64(WASM_GET_LOCAL(0)));
829 :
830 750 : FOR_FLOAT64_INPUTS(i) {
831 735 : if (*i < static_cast<float>(std::numeric_limits<uint64_t>::max()) &&
832 : *i > -1) {
833 435 : CHECK_EQ(static_cast<uint64_t>(*i), r.Call(*i));
834 : } else {
835 300 : CHECK_TRAP64(r.Call(*i));
836 : }
837 : }
838 15 : }
839 :
840 28367 : WASM_EXEC_TEST(I64UConvertSatF64) {
841 : EXPERIMENTAL_FLAG_SCOPE(sat_f2i_conversions);
842 15 : WasmRunner<int64_t, double> r(execution_tier);
843 15 : BUILD(r, WASM_I64_UCONVERT_SAT_F64(WASM_GET_LOCAL(0)));
844 750 : FOR_FLOAT64_INPUTS(i) {
845 : int64_t expected;
846 735 : if (*i < static_cast<float>(std::numeric_limits<uint64_t>::max()) &&
847 : *i > -1) {
848 435 : expected = static_cast<uint64_t>(*i);
849 300 : } else if (std::isnan(*i)) {
850 : expected = static_cast<uint64_t>(0);
851 270 : } else if (*i < 0.0) {
852 : expected = std::numeric_limits<uint64_t>::min();
853 : } else {
854 : expected = std::numeric_limits<uint64_t>::max();
855 : }
856 735 : int64_t found = r.Call(*i);
857 735 : CHECK_EQ(expected, found);
858 : }
859 15 : }
860 :
861 28367 : WASM_EXEC_TEST(CallI64Parameter) {
862 : ValueType param_types[20];
863 15 : for (int i = 0; i < 20; i++) param_types[i] = kWasmI64;
864 15 : param_types[3] = kWasmI32;
865 15 : param_types[4] = kWasmI32;
866 : FunctionSig sig(1, 19, param_types);
867 300 : for (int i = 0; i < 19; i++) {
868 315 : if (i == 2 || i == 3) continue;
869 255 : WasmRunner<int32_t> r(execution_tier);
870 : // Build the target function.
871 510 : WasmFunctionCompiler& t = r.NewFunction(&sig);
872 255 : BUILD(t, WASM_GET_LOCAL(i));
873 :
874 : // Build the calling function.
875 510 : BUILD(
876 : r,
877 : WASM_I32_CONVERT_I64(WASM_CALL_FUNCTION(
878 : t.function_index(), WASM_I64V_9(0xBCD12340000000B),
879 : WASM_I64V_9(0xBCD12340000000C), WASM_I32V_1(0xD),
880 : WASM_I32_CONVERT_I64(WASM_I64V_9(0xBCD12340000000E)),
881 : WASM_I64V_9(0xBCD12340000000F), WASM_I64V_10(0xBCD1234000000010),
882 : WASM_I64V_10(0xBCD1234000000011), WASM_I64V_10(0xBCD1234000000012),
883 : WASM_I64V_10(0xBCD1234000000013), WASM_I64V_10(0xBCD1234000000014),
884 : WASM_I64V_10(0xBCD1234000000015), WASM_I64V_10(0xBCD1234000000016),
885 : WASM_I64V_10(0xBCD1234000000017), WASM_I64V_10(0xBCD1234000000018),
886 : WASM_I64V_10(0xBCD1234000000019), WASM_I64V_10(0xBCD123400000001A),
887 : WASM_I64V_10(0xBCD123400000001B), WASM_I64V_10(0xBCD123400000001C),
888 : WASM_I64V_10(0xBCD123400000001D))));
889 :
890 255 : CHECK_EQ(i + 0xB, r.Call());
891 : }
892 15 : }
893 :
894 28367 : WASM_EXEC_TEST(CallI64Return) {
895 : ValueType return_types[3]; // TODO(rossberg): support more in the future
896 15 : for (int i = 0; i < 3; i++) return_types[i] = kWasmI64;
897 15 : return_types[1] = kWasmI32;
898 : FunctionSig sig(2, 1, return_types);
899 :
900 15 : WasmRunner<int64_t> r(execution_tier);
901 : // Build the target function.
902 30 : WasmFunctionCompiler& t = r.NewFunction(&sig);
903 15 : BUILD(t, WASM_GET_LOCAL(0), WASM_I32V(7));
904 :
905 : // Build the first calling function.
906 30 : BUILD(r, WASM_CALL_FUNCTION(t.function_index(), WASM_I64V(0xBCD12340000000B)),
907 : WASM_DROP);
908 :
909 15 : CHECK_EQ(0xBCD12340000000B, r.Call());
910 15 : }
911 :
912 285 : void TestI64Binop(ExecutionTier execution_tier, WasmOpcode opcode,
913 : int64_t expected, int64_t a, int64_t b) {
914 : {
915 285 : WasmRunner<int64_t> r(execution_tier);
916 : // return K op K
917 285 : BUILD(r, WASM_BINOP(opcode, WASM_I64V(a), WASM_I64V(b)));
918 285 : CHECK_EQ(expected, r.Call());
919 : }
920 : {
921 285 : WasmRunner<int64_t, int64_t, int64_t> r(execution_tier);
922 : // return a op b
923 285 : BUILD(r, WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
924 285 : CHECK_EQ(expected, r.Call(a, b));
925 : }
926 285 : }
927 :
928 150 : void TestI64Cmp(ExecutionTier execution_tier, WasmOpcode opcode,
929 : int64_t expected, int64_t a, int64_t b) {
930 : {
931 150 : WasmRunner<int32_t> r(execution_tier);
932 : // return K op K
933 150 : BUILD(r, WASM_BINOP(opcode, WASM_I64V(a), WASM_I64V(b)));
934 300 : CHECK_EQ(expected, r.Call());
935 : }
936 : {
937 150 : WasmRunner<int32_t, int64_t, int64_t> r(execution_tier);
938 : // return a op b
939 150 : BUILD(r, WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
940 300 : CHECK_EQ(expected, r.Call(a, b));
941 : }
942 150 : }
943 :
944 28367 : WASM_EXEC_TEST(I64Binops) {
945 : TestI64Binop(execution_tier, kExprI64Add, -5586332274295447011,
946 15 : 0x501B72EBABC26847, 0x625DE9793D8F79D6);
947 : TestI64Binop(execution_tier, kExprI64Sub, 9001903251710731490,
948 15 : 0xF24FE6474640002E, 0x7562B6F711991B4C);
949 : TestI64Binop(execution_tier, kExprI64Mul, -4569547818546064176,
950 15 : 0x231A263C2CBC6451, 0xEAD44DE6BD3E23D0);
951 : TestI64Binop(execution_tier, kExprI64Mul, -25963122347507043,
952 15 : 0x4DA1FA47C9352B73, 0x91FE82317AA035AF);
953 : TestI64Binop(execution_tier, kExprI64Mul, 7640290486138131960,
954 15 : 0x185731ABE8EEA47C, 0x714EC59F1380D4C2);
955 : TestI64Binop(execution_tier, kExprI64DivS, -91517, 0x93B1190A34DE56A0,
956 15 : 0x00004D8F68863948);
957 : TestI64Binop(execution_tier, kExprI64DivU, 149016, 0xE15B3727E8A2080A,
958 15 : 0x0000631BFA72DB8B);
959 : TestI64Binop(execution_tier, kExprI64RemS, -664128064149968,
960 15 : 0x9A78B4E4FE708692, 0x0003E0B6B3BE7609);
961 : TestI64Binop(execution_tier, kExprI64RemU, 1742040017332765,
962 15 : 0x0CE84708C6258C81, 0x000A6FDE82016697);
963 : TestI64Binop(execution_tier, kExprI64And, 2531040582801836054,
964 15 : 0xAF257D1602644A16, 0x33B290A91A10D997);
965 : TestI64Binop(execution_tier, kExprI64Ior, 8556201506536114940,
966 15 : 0x169D9BE7BD3F0A5C, 0x66BCA28D77AF40E8);
967 : TestI64Binop(execution_tier, kExprI64Xor, -4605655183785456377,
968 15 : 0xB6EA20A5D48E85B8, 0x76FF4DA6C80688BF);
969 : TestI64Binop(execution_tier, kExprI64Shl, -7240704056088331264,
970 15 : 0xEF4DC1ED030E8FFE, 9);
971 : TestI64Binop(execution_tier, kExprI64ShrU, 12500673744059159,
972 15 : 0xB1A52FA7DEEC5D14, 10);
973 : TestI64Binop(execution_tier, kExprI64ShrS, 1725103446999874,
974 15 : 0x3107C791461A112B, 11);
975 : TestI64Binop(execution_tier, kExprI64Ror, -8960135652432576946,
976 15 : 0x73418D1717E4E83A, 12);
977 : TestI64Binop(execution_tier, kExprI64Ror, 7617662827409989779,
978 15 : 0xEBFF67CF0C126D36, 13);
979 : TestI64Binop(execution_tier, kExprI64Rol, -2097714064174346012,
980 15 : 0x43938B8DB0B0F230, 14);
981 : TestI64Binop(execution_tier, kExprI64Rol, 8728493013947314237,
982 15 : 0xE07AF243AC4D219D, 15);
983 15 : }
984 :
985 28367 : WASM_EXEC_TEST(I64Compare) {
986 : TestI64Cmp(execution_tier, kExprI64Eq, 0, 0xB915D8FA494064F0,
987 15 : 0x04D700B2536019A3);
988 : TestI64Cmp(execution_tier, kExprI64Ne, 1, 0xC2FAFAAAB0446CDC,
989 15 : 0x52A3328F780C97A3);
990 : TestI64Cmp(execution_tier, kExprI64LtS, 0, 0x673636E6306B0578,
991 15 : 0x028EC9ECA78F7227);
992 : TestI64Cmp(execution_tier, kExprI64LeS, 1, 0xAE5214114B86A0FA,
993 15 : 0x7C1D21DA3DFD0CCF);
994 : TestI64Cmp(execution_tier, kExprI64LtU, 0, 0x7D52166381EC1CE0,
995 15 : 0x59F4A6A9E78CD3D8);
996 : TestI64Cmp(execution_tier, kExprI64LeU, 1, 0xE4169A385C7EA0E0,
997 15 : 0xFBDBED2C8781E5BC);
998 : TestI64Cmp(execution_tier, kExprI64GtS, 0, 0x9D08FF8FB5F42E81,
999 15 : 0xD4E5C9D7FE09F621);
1000 : TestI64Cmp(execution_tier, kExprI64GeS, 1, 0x78DA3B2F73264E0F,
1001 15 : 0x6FE5E2A67C501CBE);
1002 : TestI64Cmp(execution_tier, kExprI64GtU, 0, 0x8F691284E44F7DA9,
1003 15 : 0xD5EA9BC1EE149192);
1004 : TestI64Cmp(execution_tier, kExprI64GeU, 0, 0x0886A0C58C7AA224,
1005 15 : 0x5DDBE5A81FD7EE47);
1006 15 : }
1007 :
1008 28367 : WASM_EXEC_TEST(I64Clz) {
1009 : struct {
1010 : int64_t expected;
1011 : uint64_t input;
1012 : } values[] = {{0, 0x8000100000000000}, {1, 0x4000050000000000},
1013 : {2, 0x2000030000000000}, {3, 0x1000000300000000},
1014 : {4, 0x0805000000000000}, {5, 0x0400600000000000},
1015 : {6, 0x0200000000000000}, {7, 0x010000A000000000},
1016 : {8, 0x00800C0000000000}, {9, 0x0040000000000000},
1017 : {10, 0x0020000D00000000}, {11, 0x00100F0000000000},
1018 : {12, 0x0008000000000000}, {13, 0x0004100000000000},
1019 : {14, 0x0002002000000000}, {15, 0x0001030000000000},
1020 : {16, 0x0000804000000000}, {17, 0x0000400500000000},
1021 : {18, 0x0000205000000000}, {19, 0x0000170000000000},
1022 : {20, 0x0000087000000000}, {21, 0x0000040500000000},
1023 : {22, 0x0000020300000000}, {23, 0x0000010100000000},
1024 : {24, 0x0000008900000000}, {25, 0x0000004100000000},
1025 : {26, 0x0000002200000000}, {27, 0x0000001300000000},
1026 : {28, 0x0000000800000000}, {29, 0x0000000400000000},
1027 : {30, 0x0000000200000000}, {31, 0x0000000100000000},
1028 : {32, 0x0000000080001000}, {33, 0x0000000040000500},
1029 : {34, 0x0000000020000300}, {35, 0x0000000010000003},
1030 : {36, 0x0000000008050000}, {37, 0x0000000004006000},
1031 : {38, 0x0000000002000000}, {39, 0x00000000010000A0},
1032 : {40, 0x0000000000800C00}, {41, 0x0000000000400000},
1033 : {42, 0x000000000020000D}, {43, 0x0000000000100F00},
1034 : {44, 0x0000000000080000}, {45, 0x0000000000041000},
1035 : {46, 0x0000000000020020}, {47, 0x0000000000010300},
1036 : {48, 0x0000000000008040}, {49, 0x0000000000004005},
1037 : {50, 0x0000000000002050}, {51, 0x0000000000001700},
1038 : {52, 0x0000000000000870}, {53, 0x0000000000000405},
1039 : {54, 0x0000000000000203}, {55, 0x0000000000000101},
1040 : {56, 0x0000000000000089}, {57, 0x0000000000000041},
1041 : {58, 0x0000000000000022}, {59, 0x0000000000000013},
1042 : {60, 0x0000000000000008}, {61, 0x0000000000000004},
1043 : {62, 0x0000000000000002}, {63, 0x0000000000000001},
1044 15 : {64, 0x0000000000000000}};
1045 :
1046 15 : WasmRunner<int64_t, uint64_t> r(execution_tier);
1047 15 : BUILD(r, WASM_I64_CLZ(WASM_GET_LOCAL(0)));
1048 990 : for (size_t i = 0; i < arraysize(values); i++) {
1049 975 : CHECK_EQ(values[i].expected, r.Call(values[i].input));
1050 : }
1051 15 : }
1052 :
1053 28367 : WASM_EXEC_TEST(I64Ctz) {
1054 : struct {
1055 : int64_t expected;
1056 : uint64_t input;
1057 : } values[] = {{64, 0x0000000000000000}, {63, 0x8000000000000000},
1058 : {62, 0x4000000000000000}, {61, 0x2000000000000000},
1059 : {60, 0x1000000000000000}, {59, 0xA800000000000000},
1060 : {58, 0xF400000000000000}, {57, 0x6200000000000000},
1061 : {56, 0x9100000000000000}, {55, 0xCD80000000000000},
1062 : {54, 0x0940000000000000}, {53, 0xAF20000000000000},
1063 : {52, 0xAC10000000000000}, {51, 0xE0B8000000000000},
1064 : {50, 0x9CE4000000000000}, {49, 0xC792000000000000},
1065 : {48, 0xB8F1000000000000}, {47, 0x3B9F800000000000},
1066 : {46, 0xDB4C400000000000}, {45, 0xE9A3200000000000},
1067 : {44, 0xFCA6100000000000}, {43, 0x6C8A780000000000},
1068 : {42, 0x8CE5A40000000000}, {41, 0xCB7D020000000000},
1069 : {40, 0xCB4DC10000000000}, {39, 0xDFBEC58000000000},
1070 : {38, 0x27A9DB4000000000}, {37, 0xDE3BCB2000000000},
1071 : {36, 0xD7E8A61000000000}, {35, 0x9AFDBC8800000000},
1072 : {34, 0x9AFDBC8400000000}, {33, 0x9AFDBC8200000000},
1073 : {32, 0x9AFDBC8100000000}, {31, 0x0000000080000000},
1074 : {30, 0x0000000040000000}, {29, 0x0000000020000000},
1075 : {28, 0x0000000010000000}, {27, 0x00000000A8000000},
1076 : {26, 0x00000000F4000000}, {25, 0x0000000062000000},
1077 : {24, 0x0000000091000000}, {23, 0x00000000CD800000},
1078 : {22, 0x0000000009400000}, {21, 0x00000000AF200000},
1079 : {20, 0x00000000AC100000}, {19, 0x00000000E0B80000},
1080 : {18, 0x000000009CE40000}, {17, 0x00000000C7920000},
1081 : {16, 0x00000000B8F10000}, {15, 0x000000003B9F8000},
1082 : {14, 0x00000000DB4C4000}, {13, 0x00000000E9A32000},
1083 : {12, 0x00000000FCA61000}, {11, 0x000000006C8A7800},
1084 : {10, 0x000000008CE5A400}, {9, 0x00000000CB7D0200},
1085 : {8, 0x00000000CB4DC100}, {7, 0x00000000DFBEC580},
1086 : {6, 0x0000000027A9DB40}, {5, 0x00000000DE3BCB20},
1087 : {4, 0x00000000D7E8A610}, {3, 0x000000009AFDBC88},
1088 : {2, 0x000000009AFDBC84}, {1, 0x000000009AFDBC82},
1089 15 : {0, 0x000000009AFDBC81}};
1090 :
1091 15 : WasmRunner<int64_t, uint64_t> r(execution_tier);
1092 15 : BUILD(r, WASM_I64_CTZ(WASM_GET_LOCAL(0)));
1093 990 : for (size_t i = 0; i < arraysize(values); i++) {
1094 975 : CHECK_EQ(values[i].expected, r.Call(values[i].input));
1095 : }
1096 15 : }
1097 :
1098 28367 : WASM_EXEC_TEST(I64Popcnt2) {
1099 : struct {
1100 : int64_t expected;
1101 : uint64_t input;
1102 : } values[] = {{64, 0xFFFFFFFFFFFFFFFF},
1103 : {0, 0x0000000000000000},
1104 : {2, 0x0000080000008000},
1105 : {26, 0x1123456782345678},
1106 15 : {38, 0xFFEDCBA09EDCBA09}};
1107 :
1108 15 : WasmRunner<int64_t, uint64_t> r(execution_tier);
1109 15 : BUILD(r, WASM_I64_POPCNT(WASM_GET_LOCAL(0)));
1110 90 : for (size_t i = 0; i < arraysize(values); i++) {
1111 75 : CHECK_EQ(values[i].expected, r.Call(values[i].input));
1112 : }
1113 15 : }
1114 :
1115 : // Test the WasmRunner with an Int64 return value and different numbers of
1116 : // Int64 parameters.
1117 28367 : WASM_EXEC_TEST(I64WasmRunner) {
1118 1230 : {FOR_INT64_INPUTS(i){WasmRunner<int64_t> r(execution_tier);
1119 1215 : BUILD(r, WASM_I64V(*i));
1120 1215 : CHECK_EQ(*i, r.Call());
1121 : }
1122 : }
1123 : {
1124 15 : WasmRunner<int64_t, int64_t> r(execution_tier);
1125 15 : BUILD(r, WASM_GET_LOCAL(0));
1126 15 : FOR_INT64_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
1127 : }
1128 : {
1129 15 : WasmRunner<int64_t, int64_t, int64_t> r(execution_tier);
1130 15 : BUILD(r, WASM_I64_XOR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
1131 1230 : FOR_INT64_INPUTS(i) {
1132 98415 : FOR_INT64_INPUTS(j) { CHECK_EQ(*i ^ *j, r.Call(*i, *j)); }
1133 : }
1134 : }
1135 : {
1136 15 : WasmRunner<int64_t, int64_t, int64_t, int64_t> r(execution_tier);
1137 15 : BUILD(r, WASM_I64_XOR(WASM_GET_LOCAL(0),
1138 : WASM_I64_XOR(WASM_GET_LOCAL(1), WASM_GET_LOCAL(2))));
1139 1230 : FOR_INT64_INPUTS(i) {
1140 98415 : FOR_INT64_INPUTS(j) {
1141 98415 : CHECK_EQ(*i ^ *j ^ *j, r.Call(*i, *j, *j));
1142 98415 : CHECK_EQ(*j ^ *i ^ *j, r.Call(*j, *i, *j));
1143 98415 : CHECK_EQ(*j ^ *j ^ *i, r.Call(*j, *j, *i));
1144 : }
1145 : }
1146 : }
1147 : {
1148 15 : WasmRunner<int64_t, int64_t, int64_t, int64_t, int64_t> r(execution_tier);
1149 15 : BUILD(r, WASM_I64_XOR(WASM_GET_LOCAL(0),
1150 : WASM_I64_XOR(WASM_GET_LOCAL(1),
1151 : WASM_I64_XOR(WASM_GET_LOCAL(2),
1152 : WASM_GET_LOCAL(3)))));
1153 1230 : FOR_INT64_INPUTS(i) {
1154 98415 : FOR_INT64_INPUTS(j) {
1155 98415 : CHECK_EQ(*i ^ *j ^ *j ^ *j, r.Call(*i, *j, *j, *j));
1156 98415 : CHECK_EQ(*j ^ *i ^ *j ^ *j, r.Call(*j, *i, *j, *j));
1157 98415 : CHECK_EQ(*j ^ *j ^ *i ^ *j, r.Call(*j, *j, *i, *j));
1158 98415 : CHECK_EQ(*j ^ *j ^ *j ^ *i, r.Call(*j, *j, *j, *i));
1159 : }
1160 : }
1161 : }
1162 15 : }
1163 :
1164 28367 : WASM_EXEC_TEST(Call_Int64Sub) {
1165 15 : WasmRunner<int64_t, int64_t, int64_t> r(execution_tier);
1166 : // Build the target function.
1167 15 : TestSignatures sigs;
1168 30 : WasmFunctionCompiler& t = r.NewFunction(sigs.l_ll());
1169 15 : BUILD(t, WASM_I64_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
1170 :
1171 : // Build the caller function.
1172 30 : BUILD(r, WASM_CALL_FUNCTION(t.function_index(), WASM_GET_LOCAL(0),
1173 : WASM_GET_LOCAL(1)));
1174 :
1175 885 : FOR_INT32_INPUTS(i) {
1176 50460 : FOR_INT32_INPUTS(j) {
1177 50460 : int64_t a = static_cast<int64_t>(*i) << 32 |
1178 50460 : (static_cast<int64_t>(*j) | 0xFFFFFFFF);
1179 50460 : int64_t b = static_cast<int64_t>(*j) << 32 |
1180 50460 : (static_cast<int64_t>(*i) | 0xFFFFFFFF);
1181 :
1182 50460 : int64_t expected = static_cast<int64_t>(static_cast<uint64_t>(a) -
1183 50460 : static_cast<uint64_t>(b));
1184 50460 : CHECK_EQ(expected, r.Call(a, b));
1185 : }
1186 : }
1187 15 : }
1188 :
1189 28367 : WASM_EXEC_TEST(LoadStoreI64_sx) {
1190 : byte loads[] = {kExprI64LoadMem8S, kExprI64LoadMem16S, kExprI64LoadMem32S,
1191 15 : kExprI64LoadMem};
1192 :
1193 75 : for (size_t m = 0; m < arraysize(loads); m++) {
1194 60 : WasmRunner<int64_t> r(execution_tier);
1195 : byte* memory = r.builder().AddMemoryElems<byte>(kWasmPageSize);
1196 :
1197 : byte code[] = {
1198 : kExprI32Const, 8, // --
1199 : kExprI32Const, 0, // --
1200 60 : loads[m], // --
1201 : ZERO_ALIGNMENT, // --
1202 : ZERO_OFFSET, // --
1203 : kExprI64StoreMem, // --
1204 : ZERO_ALIGNMENT, // --
1205 : ZERO_OFFSET, // --
1206 : kExprI32Const, 0, // --
1207 : loads[m], // --
1208 : ZERO_ALIGNMENT, // --
1209 : ZERO_OFFSET, // --
1210 120 : };
1211 :
1212 60 : r.Build(code, code + arraysize(code));
1213 :
1214 : // Try a bunch of different negative values.
1215 780 : for (int i = -1; i >= -128; i -= 11) {
1216 720 : int size = 1 << m;
1217 : r.builder().BlankMemory();
1218 720 : memory[size - 1] = static_cast<byte>(i); // set the high order byte.
1219 :
1220 720 : int64_t expected = static_cast<int64_t>(i) << ((size - 1) * 8);
1221 :
1222 720 : CHECK_EQ(expected, r.Call());
1223 720 : CHECK_EQ(static_cast<byte>(i), memory[8 + size - 1]);
1224 3060 : for (int j = size; j < 8; j++) {
1225 6120 : CHECK_EQ(255, memory[8 + j]);
1226 : }
1227 : }
1228 : }
1229 15 : }
1230 :
1231 :
1232 28367 : WASM_EXEC_TEST(I64ReinterpretF64) {
1233 15 : WasmRunner<int64_t> r(execution_tier);
1234 : int64_t* memory =
1235 : r.builder().AddMemoryElems<int64_t>(kWasmPageSize / sizeof(int64_t));
1236 :
1237 15 : BUILD(r, WASM_I64_REINTERPRET_F64(
1238 : WASM_LOAD_MEM(MachineType::Float64(), WASM_ZERO)));
1239 :
1240 885 : FOR_INT32_INPUTS(i) {
1241 : int64_t expected = base::MulWithWraparound(static_cast<int64_t>(*i),
1242 870 : int64_t{0x300010001L});
1243 : r.builder().WriteMemory(&memory[0], expected);
1244 870 : CHECK_EQ(expected, r.Call());
1245 : }
1246 15 : }
1247 :
1248 28367 : WASM_EXEC_TEST(SignallingNanSurvivesI64ReinterpretF64) {
1249 15 : WasmRunner<int64_t> r(execution_tier);
1250 15 : BUILD(r, WASM_I64_REINTERPRET_F64(WASM_SEQ(kExprF64Const, 0x00, 0x00, 0x00,
1251 : 0x00, 0x00, 0x00, 0xF4, 0x7F)));
1252 :
1253 : // This is a signalling nan.
1254 15 : CHECK_EQ(0x7FF4000000000000, r.Call());
1255 15 : }
1256 :
1257 28367 : WASM_EXEC_TEST(F64ReinterpretI64) {
1258 15 : WasmRunner<int64_t, int64_t> r(execution_tier);
1259 870 : int64_t* memory =
1260 : r.builder().AddMemoryElems<int64_t>(kWasmPageSize / sizeof(int64_t));
1261 :
1262 15 : BUILD(r, WASM_STORE_MEM(MachineType::Float64(), WASM_ZERO,
1263 : WASM_F64_REINTERPRET_I64(WASM_GET_LOCAL(0))),
1264 : WASM_GET_LOCAL(0));
1265 :
1266 885 : FOR_INT32_INPUTS(i) {
1267 : int64_t expected = base::MulWithWraparound(static_cast<int64_t>(*i),
1268 870 : int64_t{0x300010001L});
1269 870 : CHECK_EQ(expected, r.Call(expected));
1270 870 : CHECK_EQ(expected, r.builder().ReadMemory<int64_t>(&memory[0]));
1271 : }
1272 15 : }
1273 :
1274 28367 : WASM_EXEC_TEST(LoadMemI64) {
1275 15 : WasmRunner<int64_t> r(execution_tier);
1276 : int64_t* memory =
1277 : r.builder().AddMemoryElems<int64_t>(kWasmPageSize / sizeof(int64_t));
1278 15 : r.builder().RandomizeMemory(1111);
1279 :
1280 15 : BUILD(r, WASM_LOAD_MEM(MachineType::Int64(), WASM_ZERO));
1281 :
1282 : r.builder().WriteMemory<int64_t>(&memory[0], 0x1ABBCCDD00112233LL);
1283 15 : CHECK_EQ(0x1ABBCCDD00112233LL, r.Call());
1284 :
1285 : r.builder().WriteMemory<int64_t>(&memory[0], 0x33AABBCCDD001122LL);
1286 15 : CHECK_EQ(0x33AABBCCDD001122LL, r.Call());
1287 :
1288 : r.builder().WriteMemory<int64_t>(&memory[0], 77777777);
1289 15 : CHECK_EQ(77777777, r.Call());
1290 15 : }
1291 :
1292 28367 : WASM_EXEC_TEST(LoadMemI64_alignment) {
1293 75 : for (byte alignment = 0; alignment <= 3; alignment++) {
1294 60 : WasmRunner<int64_t> r(execution_tier);
1295 : int64_t* memory =
1296 : r.builder().AddMemoryElems<int64_t>(kWasmPageSize / sizeof(int64_t));
1297 60 : r.builder().RandomizeMemory(1111);
1298 :
1299 60 : BUILD(r,
1300 : WASM_LOAD_MEM_ALIGNMENT(MachineType::Int64(), WASM_ZERO, alignment));
1301 :
1302 : r.builder().WriteMemory<int64_t>(&memory[0], 0x1ABBCCDD00112233LL);
1303 60 : CHECK_EQ(0x1ABBCCDD00112233LL, r.Call());
1304 :
1305 : r.builder().WriteMemory<int64_t>(&memory[0], 0x33AABBCCDD001122LL);
1306 60 : CHECK_EQ(0x33AABBCCDD001122LL, r.Call());
1307 :
1308 : r.builder().WriteMemory<int64_t>(&memory[0], 77777777);
1309 60 : CHECK_EQ(77777777, r.Call());
1310 : }
1311 15 : }
1312 :
1313 28367 : WASM_EXEC_TEST(MemI64_Sum) {
1314 : const int kNumElems = 20;
1315 15 : WasmRunner<uint64_t, int32_t> r(execution_tier);
1316 : uint64_t* memory =
1317 : r.builder().AddMemoryElems<uint64_t>(kWasmPageSize / sizeof(uint64_t));
1318 : const byte kSum = r.AllocateLocal(kWasmI64);
1319 :
1320 15 : BUILD(r, WASM_WHILE(
1321 : WASM_GET_LOCAL(0),
1322 : WASM_BLOCK(
1323 : WASM_SET_LOCAL(
1324 : kSum, WASM_I64_ADD(WASM_GET_LOCAL(kSum),
1325 : WASM_LOAD_MEM(MachineType::Int64(),
1326 : WASM_GET_LOCAL(0)))),
1327 : WASM_SET_LOCAL(
1328 : 0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I32V_1(8))))),
1329 : WASM_GET_LOCAL(1));
1330 :
1331 : // Run 4 trials.
1332 60 : for (int i = 0; i < 3; i++) {
1333 45 : r.builder().RandomizeMemory(i * 33);
1334 : uint64_t expected = 0;
1335 900 : for (size_t j = kNumElems - 1; j > 0; j--) {
1336 855 : expected += r.builder().ReadMemory(&memory[j]);
1337 : }
1338 45 : uint64_t result = r.Call(8 * (kNumElems - 1));
1339 45 : CHECK_EQ(expected, result);
1340 : }
1341 15 : }
1342 :
1343 28367 : WASM_EXEC_TEST(StoreMemI64_alignment) {
1344 : const int64_t kWritten = 0x12345678ABCD0011ll;
1345 :
1346 75 : for (byte i = 0; i <= 3; i++) {
1347 60 : WasmRunner<int64_t, int64_t> r(execution_tier);
1348 60 : int64_t* memory =
1349 : r.builder().AddMemoryElems<int64_t>(kWasmPageSize / sizeof(int64_t));
1350 60 : BUILD(r, WASM_STORE_MEM_ALIGNMENT(MachineType::Int64(), WASM_ZERO, i,
1351 : WASM_GET_LOCAL(0)),
1352 : WASM_GET_LOCAL(0));
1353 60 : r.builder().RandomizeMemory(1111);
1354 : r.builder().WriteMemory<int64_t>(&memory[0], 0);
1355 :
1356 60 : CHECK_EQ(kWritten, r.Call(kWritten));
1357 60 : CHECK_EQ(kWritten, r.builder().ReadMemory(&memory[0]));
1358 : }
1359 15 : }
1360 :
1361 28367 : WASM_EXEC_TEST(I64Global) {
1362 15 : WasmRunner<int32_t, int32_t> r(execution_tier);
1363 135 : int64_t* global = r.builder().AddGlobal<int64_t>();
1364 : // global = global + p0
1365 15 : BUILD(r, WASM_SET_GLOBAL(
1366 : 0, WASM_I64_AND(WASM_GET_GLOBAL(0),
1367 : WASM_I64_SCONVERT_I32(WASM_GET_LOCAL(0)))),
1368 : WASM_ZERO);
1369 :
1370 : r.builder().WriteMemory<int64_t>(global, 0xFFFFFFFFFFFFFFFFLL);
1371 75 : for (int i = 9; i < 444444; i += 111111) {
1372 60 : int64_t expected = ReadLittleEndianValue<int64_t>(global) & i;
1373 60 : r.Call(i);
1374 60 : CHECK_EQ(expected, ReadLittleEndianValue<int64_t>(global));
1375 : }
1376 15 : }
1377 :
1378 28367 : WASM_EXEC_TEST(I64Eqz) {
1379 15 : WasmRunner<int32_t, int64_t> r(execution_tier);
1380 15 : BUILD(r, WASM_I64_EQZ(WASM_GET_LOCAL(0)));
1381 :
1382 1230 : FOR_INT64_INPUTS(i) {
1383 1215 : int32_t result = *i == 0 ? 1 : 0;
1384 1215 : CHECK_EQ(result, r.Call(*i));
1385 : }
1386 15 : }
1387 :
1388 28367 : WASM_EXEC_TEST(I64Ror) {
1389 15 : WasmRunner<int64_t, int64_t, int64_t> r(execution_tier);
1390 15 : BUILD(r, WASM_I64_ROR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
1391 :
1392 1230 : FOR_UINT64_INPUTS(i) {
1393 98415 : FOR_UINT64_INPUTS(j) {
1394 196830 : int64_t expected = base::bits::RotateRight64(*i, *j & 0x3F);
1395 98415 : CHECK_EQ(expected, r.Call(*i, *j));
1396 : }
1397 : }
1398 15 : }
1399 :
1400 28367 : WASM_EXEC_TEST(I64Rol) {
1401 15 : WasmRunner<int64_t, int64_t, int64_t> r(execution_tier);
1402 15 : BUILD(r, WASM_I64_ROL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
1403 :
1404 1230 : FOR_UINT64_INPUTS(i) {
1405 98415 : FOR_UINT64_INPUTS(j) {
1406 196830 : int64_t expected = base::bits::RotateLeft64(*i, *j & 0x3F);
1407 98415 : CHECK_EQ(expected, r.Call(*i, *j));
1408 : }
1409 : }
1410 15 : }
1411 :
1412 28367 : WASM_EXEC_TEST(StoreMem_offset_oob_i64) {
1413 : static const MachineType machineTypes[] = {
1414 : MachineType::Int8(), MachineType::Uint8(), MachineType::Int16(),
1415 : MachineType::Uint16(), MachineType::Int32(), MachineType::Uint32(),
1416 : MachineType::Int64(), MachineType::Uint64(), MachineType::Float32(),
1417 : MachineType::Float64()};
1418 :
1419 : constexpr size_t num_bytes = kWasmPageSize;
1420 :
1421 165 : for (size_t m = 0; m < arraysize(machineTypes); m++) {
1422 150 : WasmRunner<int32_t, uint32_t> r(execution_tier);
1423 : byte* memory = r.builder().AddMemoryElems<byte>(num_bytes);
1424 150 : r.builder().RandomizeMemory(1119 + static_cast<int>(m));
1425 :
1426 150 : BUILD(r, WASM_STORE_MEM_OFFSET(machineTypes[m], 8, WASM_GET_LOCAL(0),
1427 : WASM_LOAD_MEM(machineTypes[m], WASM_ZERO)),
1428 : WASM_ZERO);
1429 :
1430 150 : byte memsize = ValueTypes::MemSize(machineTypes[m]);
1431 150 : uint32_t boundary = num_bytes - 8 - memsize;
1432 150 : CHECK_EQ(0, r.Call(boundary)); // in bounds.
1433 150 : CHECK_EQ(0, memcmp(&memory[0], &memory[8 + boundary], memsize));
1434 :
1435 2850 : for (uint32_t offset = boundary + 1; offset < boundary + 19; offset++) {
1436 5400 : CHECK_TRAP32(r.Call(offset)); // out of bounds.
1437 : }
1438 : }
1439 15 : }
1440 :
1441 28367 : WASM_EXEC_TEST(Store_i64_narrowed) {
1442 : constexpr byte kOpcodes[] = {kExprI64StoreMem8, kExprI64StoreMem16,
1443 15 : kExprI64StoreMem32, kExprI64StoreMem};
1444 : int stored_size_in_bytes = 0;
1445 75 : for (auto opcode : kOpcodes) {
1446 120 : stored_size_in_bytes = std::max(1, stored_size_in_bytes * 2);
1447 : constexpr int kBytes = 24;
1448 60 : uint8_t expected_memory[kBytes] = {0};
1449 60 : WasmRunner<int32_t, int32_t, int64_t> r(execution_tier);
1450 : uint8_t* memory = r.builder().AddMemoryElems<uint8_t>(kWasmPageSize);
1451 : constexpr uint64_t kPattern = 0x0123456789abcdef;
1452 :
1453 60 : BUILD(r, WASM_GET_LOCAL(0), // index
1454 : WASM_GET_LOCAL(1), // value
1455 : opcode, ZERO_ALIGNMENT, ZERO_OFFSET, // store
1456 : WASM_ZERO); // return value
1457 :
1458 1335 : for (int i = 0; i <= kBytes - stored_size_in_bytes; ++i) {
1459 1275 : uint64_t pattern = base::bits::RotateLeft64(kPattern, i % 64);
1460 1275 : r.Call(i, pattern);
1461 5625 : for (int b = 0; b < stored_size_in_bytes; ++b) {
1462 4350 : expected_memory[i + b] = static_cast<uint8_t>(pattern >> (b * 8));
1463 : }
1464 30600 : for (int w = 0; w < kBytes; ++w) {
1465 30600 : CHECK_EQ(expected_memory[w], memory[w]);
1466 : }
1467 : }
1468 : }
1469 15 : }
1470 :
1471 28367 : WASM_EXEC_TEST(UnalignedInt64Load) {
1472 15 : WasmRunner<uint64_t> r(execution_tier);
1473 : r.builder().AddMemoryElems<int64_t>(kWasmPageSize / sizeof(int64_t));
1474 15 : BUILD(r, WASM_LOAD_MEM_ALIGNMENT(MachineType::Int64(), WASM_ONE, 3));
1475 15 : r.Call();
1476 15 : }
1477 :
1478 28367 : WASM_EXEC_TEST(UnalignedInt64Store) {
1479 15 : WasmRunner<int32_t> r(execution_tier);
1480 : r.builder().AddMemoryElems<uint64_t>(kWasmPageSize / sizeof(int64_t));
1481 15 : BUILD(r, WASM_SEQ(WASM_STORE_MEM_ALIGNMENT(MachineType::Int64(), WASM_ONE, 3,
1482 : WASM_I64V_1(1)),
1483 : WASM_I32V_1(12)));
1484 15 : r.Call();
1485 15 : }
1486 :
1487 : #define ADD_CODE(vec, ...) \
1488 : do { \
1489 : byte __buf[] = {__VA_ARGS__}; \
1490 : for (size_t i = 0; i < sizeof(__buf); i++) vec.push_back(__buf[i]); \
1491 : } while (false)
1492 :
1493 15 : static void CompileCallIndirectMany(ExecutionTier tier, ValueType param) {
1494 : // Make sure we don't run out of registers when compiling indirect calls
1495 : // with many many parameters.
1496 15 : TestSignatures sigs;
1497 615 : for (byte num_params = 0; num_params < 40; num_params++) {
1498 600 : WasmRunner<void> r(tier);
1499 600 : FunctionSig* sig = sigs.many(r.zone(), kWasmStmt, param, num_params);
1500 :
1501 600 : r.builder().AddSignature(sig);
1502 600 : r.builder().AddSignature(sig);
1503 600 : r.builder().AddIndirectFunctionTable(nullptr, 0);
1504 :
1505 600 : WasmFunctionCompiler& t = r.NewFunction(sig);
1506 :
1507 : std::vector<byte> code;
1508 12300 : for (byte p = 0; p < num_params; p++) {
1509 11700 : ADD_CODE(code, kExprGetLocal, p);
1510 : }
1511 600 : ADD_CODE(code, kExprI32Const, 0);
1512 600 : ADD_CODE(code, kExprCallIndirect, 1, TABLE_ZERO);
1513 :
1514 1200 : t.Build(&code[0], &code[0] + code.size());
1515 : }
1516 15 : }
1517 :
1518 28367 : WASM_EXEC_TEST(Compile_Wasm_CallIndirect_Many_i64) {
1519 15 : CompileCallIndirectMany(execution_tier, kWasmI64);
1520 0 : }
1521 :
1522 60 : static void Run_WasmMixedCall_N(ExecutionTier execution_tier, int start) {
1523 : const int kExpected = 6333;
1524 : const int kElemSize = 8;
1525 60 : TestSignatures sigs;
1526 :
1527 : static MachineType mixed[] = {
1528 : MachineType::Int32(), MachineType::Float32(), MachineType::Int64(),
1529 : MachineType::Float64(), MachineType::Float32(), MachineType::Int64(),
1530 : MachineType::Int32(), MachineType::Float64(), MachineType::Float32(),
1531 : MachineType::Float64(), MachineType::Int32(), MachineType::Int64(),
1532 : MachineType::Int32(), MachineType::Int32()};
1533 :
1534 60 : int num_params = static_cast<int>(arraysize(mixed)) - start;
1535 810 : for (int which = 0; which < num_params; which++) {
1536 750 : v8::internal::AccountingAllocator allocator;
1537 1500 : Zone zone(&allocator, ZONE_NAME);
1538 750 : WasmRunner<int32_t> r(execution_tier);
1539 750 : r.builder().AddMemory(kWasmPageSize);
1540 750 : MachineType* memtypes = &mixed[start];
1541 750 : MachineType result = memtypes[which];
1542 :
1543 : // =========================================================================
1544 : // Build the selector function.
1545 : // =========================================================================
1546 750 : FunctionSig::Builder b(&zone, 1, num_params);
1547 750 : b.AddReturn(ValueTypes::ValueTypeFor(result));
1548 10200 : for (int i = 0; i < num_params; i++) {
1549 9450 : b.AddParam(ValueTypes::ValueTypeFor(memtypes[i]));
1550 : }
1551 1500 : WasmFunctionCompiler& t = r.NewFunction(b.Build());
1552 750 : BUILD(t, WASM_GET_LOCAL(which));
1553 :
1554 : // =========================================================================
1555 : // Build the calling function.
1556 : // =========================================================================
1557 : std::vector<byte> code;
1558 :
1559 : // Load the arguments.
1560 10950 : for (int i = 0; i < num_params; i++) {
1561 9450 : int offset = (i + 1) * kElemSize;
1562 9450 : ADD_CODE(code, WASM_LOAD_MEM(memtypes[i], WASM_I32V_2(offset)));
1563 : }
1564 :
1565 : // Call the selector function.
1566 1500 : ADD_CODE(code, WASM_CALL_FUNCTION0(t.function_index()));
1567 :
1568 : // Store the result in a local.
1569 750 : byte local_index = r.AllocateLocal(ValueTypes::ValueTypeFor(result));
1570 750 : ADD_CODE(code, kExprSetLocal, local_index);
1571 :
1572 : // Store the result in memory.
1573 750 : ADD_CODE(code,
1574 : WASM_STORE_MEM(result, WASM_ZERO, WASM_GET_LOCAL(local_index)));
1575 :
1576 : // Return the expected value.
1577 750 : ADD_CODE(code, WASM_I32V_2(kExpected));
1578 :
1579 1500 : r.Build(&code[0], &code[0] + code.size());
1580 :
1581 : // Run the code.
1582 8250 : for (int t = 0; t < 10; t++) {
1583 7500 : r.builder().RandomizeMemory();
1584 7500 : CHECK_EQ(kExpected, r.Call());
1585 :
1586 7500 : int size = ValueTypes::MemSize(result);
1587 51300 : for (int i = 0; i < size; i++) {
1588 43800 : int base = (which + 1) * kElemSize;
1589 43800 : byte expected = r.builder().raw_mem_at<byte>(base + i);
1590 : byte result = r.builder().raw_mem_at<byte>(i);
1591 43800 : CHECK_EQ(expected, result);
1592 : }
1593 : }
1594 750 : }
1595 60 : }
1596 :
1597 28352 : WASM_EXEC_TEST(MixedCall_i64_0) { Run_WasmMixedCall_N(execution_tier, 0); }
1598 28352 : WASM_EXEC_TEST(MixedCall_i64_1) { Run_WasmMixedCall_N(execution_tier, 1); }
1599 28352 : WASM_EXEC_TEST(MixedCall_i64_2) { Run_WasmMixedCall_N(execution_tier, 2); }
1600 28352 : WASM_EXEC_TEST(MixedCall_i64_3) { Run_WasmMixedCall_N(execution_tier, 3); }
1601 :
1602 28367 : WASM_EXEC_TEST(Regress5874) {
1603 15 : WasmRunner<int32_t> r(execution_tier);
1604 : r.builder().AddMemoryElems<int64_t>(kWasmPageSize / sizeof(int64_t));
1605 :
1606 15 : BUILD(r, kExprI64Const, 0x00, // --
1607 : kExprI32ConvertI64, // --
1608 : kExprI64Const, 0x00, // --
1609 : kExprI64StoreMem, 0x03, 0x00, // --
1610 : kExprI32Const, 0x00); // --
1611 :
1612 15 : r.Call();
1613 15 : }
1614 :
1615 28367 : WASM_EXEC_TEST(Regression_6858) {
1616 : // WasmRunner with 5 params and returns, which is the maximum.
1617 15 : WasmRunner<int64_t, int64_t, int64_t, int64_t, int64_t> r(execution_tier);
1618 15 : BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
1619 : int64_t dividend = 15;
1620 : int64_t divisor = 0;
1621 : int64_t filler = 34;
1622 30 : CHECK_TRAP64(r.Call(dividend, divisor, filler, filler));
1623 15 : }
1624 :
1625 : #undef ADD_CODE
1626 :
1627 : // clang-format gets confused about these closing parentheses (wants to change
1628 : // the first comment to "// namespace v8". Disable it.
1629 : // clang-format off
1630 : } // namespace test_run_wasm_64
1631 : } // namespace wasm
1632 : } // namespace internal
1633 85011 : } // namespace v8
1634 : // clang-format on
|