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