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/wasm/wasm-macro-gen.h" 10 11 #include "test/cctest/cctest.h" 12 #include "test/cctest/compiler/value-helper.h" 13 #include "test/cctest/wasm/test-signatures.h" 14 #include "test/cctest/wasm/wasm-run-utils.h" 15 16 using namespace v8::base; 17 using namespace v8::internal; 18 using namespace v8::internal::compiler; 19 using namespace v8::internal::wasm; 20 21 #define BUILD(r, ...) \ 22 do { \ 23 byte code[] = {__VA_ARGS__}; \ 24 r.Build(code, code + arraysize(code)); \ 25 } while (false) 26 27 28 TEST(Run_WasmInt8Const) { 29 WasmRunner<int8_t> r; 30 const byte kExpectedValue = 121; 31 // return(kExpectedValue) 32 BUILD(r, WASM_I8(kExpectedValue)); 33 CHECK_EQ(kExpectedValue, r.Call()); 34 } 35 36 37 TEST(Run_WasmInt8Const_fallthru1) { 38 WasmRunner<int8_t> r; 39 const byte kExpectedValue = 122; 40 // kExpectedValue 41 BUILD(r, WASM_I8(kExpectedValue)); 42 CHECK_EQ(kExpectedValue, r.Call()); 43 } 44 45 46 TEST(Run_WasmInt8Const_fallthru2) { 47 WasmRunner<int8_t> r; 48 const byte kExpectedValue = 123; 49 // -99 kExpectedValue 50 BUILD(r, WASM_I8(-99), WASM_I8(kExpectedValue)); 51 CHECK_EQ(kExpectedValue, r.Call()); 52 } 53 54 55 TEST(Run_WasmInt8Const_all) { 56 for (int value = -128; value <= 127; value++) { 57 WasmRunner<int8_t> r; 58 // return(value) 59 BUILD(r, WASM_I8(value)); 60 int8_t result = r.Call(); 61 CHECK_EQ(value, result); 62 } 63 } 64 65 66 TEST(Run_WasmInt32Const) { 67 WasmRunner<int32_t> r; 68 const int32_t kExpectedValue = 0x11223344; 69 // return(kExpectedValue) 70 BUILD(r, WASM_I32(kExpectedValue)); 71 CHECK_EQ(kExpectedValue, r.Call()); 72 } 73 74 75 TEST(Run_WasmInt32Const_many) { 76 FOR_INT32_INPUTS(i) { 77 WasmRunner<int32_t> r; 78 const int32_t kExpectedValue = *i; 79 // return(kExpectedValue) 80 BUILD(r, WASM_I32(kExpectedValue)); 81 CHECK_EQ(kExpectedValue, r.Call()); 82 } 83 } 84 85 86 TEST(Run_WasmMemorySize) { 87 WasmRunner<int32_t> r; 88 TestingModule module; 89 module.AddMemory(1024); 90 r.env()->module = &module; 91 BUILD(r, kExprMemorySize); 92 CHECK_EQ(1024, r.Call()); 93 } 94 95 96 #if WASM_64 97 TEST(Run_WasmInt64Const) { 98 WasmRunner<int64_t> r; 99 const int64_t kExpectedValue = 0x1122334455667788LL; 100 // return(kExpectedValue) 101 BUILD(r, WASM_I64(kExpectedValue)); 102 CHECK_EQ(kExpectedValue, r.Call()); 103 } 104 105 106 TEST(Run_WasmInt64Const_many) { 107 int cntr = 0; 108 FOR_INT32_INPUTS(i) { 109 WasmRunner<int64_t> r; 110 const int64_t kExpectedValue = (static_cast<int64_t>(*i) << 32) | cntr; 111 // return(kExpectedValue) 112 BUILD(r, WASM_I64(kExpectedValue)); 113 CHECK_EQ(kExpectedValue, r.Call()); 114 cntr++; 115 } 116 } 117 #endif 118 119 120 TEST(Run_WasmInt32Param0) { 121 WasmRunner<int32_t> r(MachineType::Int32()); 122 // return(local[0]) 123 BUILD(r, WASM_GET_LOCAL(0)); 124 FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); } 125 } 126 127 128 TEST(Run_WasmInt32Param0_fallthru) { 129 WasmRunner<int32_t> r(MachineType::Int32()); 130 // local[0] 131 BUILD(r, WASM_GET_LOCAL(0)); 132 FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); } 133 } 134 135 136 TEST(Run_WasmInt32Param1) { 137 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32()); 138 // local[1] 139 BUILD(r, WASM_GET_LOCAL(1)); 140 FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(-111, *i)); } 141 } 142 143 144 TEST(Run_WasmInt32Add) { 145 WasmRunner<int32_t> r; 146 // 11 + 44 147 BUILD(r, WASM_I32_ADD(WASM_I8(11), WASM_I8(44))); 148 CHECK_EQ(55, r.Call()); 149 } 150 151 152 TEST(Run_WasmInt32Add_P) { 153 WasmRunner<int32_t> r(MachineType::Int32()); 154 // p0 + 13 155 BUILD(r, WASM_I32_ADD(WASM_I8(13), WASM_GET_LOCAL(0))); 156 FOR_INT32_INPUTS(i) { CHECK_EQ(*i + 13, r.Call(*i)); } 157 } 158 159 160 TEST(Run_WasmInt32Add_P_fallthru) { 161 WasmRunner<int32_t> r(MachineType::Int32()); 162 // p0 + 13 163 BUILD(r, WASM_I32_ADD(WASM_I8(13), WASM_GET_LOCAL(0))); 164 FOR_INT32_INPUTS(i) { CHECK_EQ(*i + 13, r.Call(*i)); } 165 } 166 167 168 TEST(Run_WasmInt32Add_P2) { 169 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32()); 170 // p0 + p1 171 BUILD(r, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 172 FOR_INT32_INPUTS(i) { 173 FOR_INT32_INPUTS(j) { 174 int32_t expected = static_cast<int32_t>(static_cast<uint32_t>(*i) + 175 static_cast<uint32_t>(*j)); 176 CHECK_EQ(expected, r.Call(*i, *j)); 177 } 178 } 179 } 180 181 182 // TODO(titzer): Fix for nosee4 and re-enable. 183 #if 0 184 185 TEST(Run_WasmFloat32Add) { 186 WasmRunner<int32_t> r; 187 // int(11.5f + 44.5f) 188 BUILD(r, 189 WASM_I32_SCONVERT_F32(WASM_F32_ADD(WASM_F32(11.5f), WASM_F32(44.5f)))); 190 CHECK_EQ(56, r.Call()); 191 } 192 193 194 TEST(Run_WasmFloat64Add) { 195 WasmRunner<int32_t> r; 196 // return int(13.5d + 43.5d) 197 BUILD(r, WASM_I32_SCONVERT_F64(WASM_F64_ADD(WASM_F64(13.5), WASM_F64(43.5)))); 198 CHECK_EQ(57, r.Call()); 199 } 200 201 #endif 202 203 204 void TestInt32Binop(WasmOpcode opcode, int32_t expected, int32_t a, int32_t b) { 205 { 206 WasmRunner<int32_t> r; 207 // K op K 208 BUILD(r, WASM_BINOP(opcode, WASM_I32(a), WASM_I32(b))); 209 CHECK_EQ(expected, r.Call()); 210 } 211 { 212 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32()); 213 // a op b 214 BUILD(r, WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 215 CHECK_EQ(expected, r.Call(a, b)); 216 } 217 } 218 219 220 TEST(Run_WasmInt32Binops) { 221 TestInt32Binop(kExprI32Add, 88888888, 33333333, 55555555); 222 TestInt32Binop(kExprI32Sub, -1111111, 7777777, 8888888); 223 TestInt32Binop(kExprI32Mul, 65130756, 88734, 734); 224 TestInt32Binop(kExprI32DivS, -66, -4777344, 72384); 225 TestInt32Binop(kExprI32DivU, 805306368, 0xF0000000, 5); 226 TestInt32Binop(kExprI32RemS, -3, -3003, 1000); 227 TestInt32Binop(kExprI32RemU, 4, 4004, 1000); 228 TestInt32Binop(kExprI32And, 0xEE, 0xFFEE, 0xFF0000FF); 229 TestInt32Binop(kExprI32Ior, 0xF0FF00FF, 0xF0F000EE, 0x000F0011); 230 TestInt32Binop(kExprI32Xor, 0xABCDEF01, 0xABCDEFFF, 0xFE); 231 TestInt32Binop(kExprI32Shl, 0xA0000000, 0xA, 28); 232 TestInt32Binop(kExprI32ShrU, 0x07000010, 0x70000100, 4); 233 TestInt32Binop(kExprI32ShrS, 0xFF000000, 0x80000000, 7); 234 TestInt32Binop(kExprI32Eq, 1, -99, -99); 235 TestInt32Binop(kExprI32Ne, 0, -97, -97); 236 237 TestInt32Binop(kExprI32LtS, 1, -4, 4); 238 TestInt32Binop(kExprI32LeS, 0, -2, -3); 239 TestInt32Binop(kExprI32LtU, 1, 0, -6); 240 TestInt32Binop(kExprI32LeU, 1, 98978, 0xF0000000); 241 242 TestInt32Binop(kExprI32GtS, 1, 4, -4); 243 TestInt32Binop(kExprI32GeS, 0, -3, -2); 244 TestInt32Binop(kExprI32GtU, 1, -6, 0); 245 TestInt32Binop(kExprI32GeU, 1, 0xF0000000, 98978); 246 } 247 248 249 void TestInt32Unop(WasmOpcode opcode, int32_t expected, int32_t a) { 250 { 251 WasmRunner<int32_t> r; 252 // return op K 253 BUILD(r, WASM_UNOP(opcode, WASM_I32(a))); 254 CHECK_EQ(expected, r.Call()); 255 } 256 { 257 WasmRunner<int32_t> r(MachineType::Int32()); 258 // return op a 259 BUILD(r, WASM_UNOP(opcode, WASM_GET_LOCAL(0))); 260 CHECK_EQ(expected, r.Call(a)); 261 } 262 } 263 264 265 TEST(Run_WasmInt32Clz) { 266 TestInt32Unop(kExprI32Clz, 0, 0x80001000); 267 TestInt32Unop(kExprI32Clz, 1, 0x40000500); 268 TestInt32Unop(kExprI32Clz, 2, 0x20000300); 269 TestInt32Unop(kExprI32Clz, 3, 0x10000003); 270 TestInt32Unop(kExprI32Clz, 4, 0x08050000); 271 TestInt32Unop(kExprI32Clz, 5, 0x04006000); 272 TestInt32Unop(kExprI32Clz, 6, 0x02000000); 273 TestInt32Unop(kExprI32Clz, 7, 0x010000a0); 274 TestInt32Unop(kExprI32Clz, 8, 0x00800c00); 275 TestInt32Unop(kExprI32Clz, 9, 0x00400000); 276 TestInt32Unop(kExprI32Clz, 10, 0x0020000d); 277 TestInt32Unop(kExprI32Clz, 11, 0x00100f00); 278 TestInt32Unop(kExprI32Clz, 12, 0x00080000); 279 TestInt32Unop(kExprI32Clz, 13, 0x00041000); 280 TestInt32Unop(kExprI32Clz, 14, 0x00020020); 281 TestInt32Unop(kExprI32Clz, 15, 0x00010300); 282 TestInt32Unop(kExprI32Clz, 16, 0x00008040); 283 TestInt32Unop(kExprI32Clz, 17, 0x00004005); 284 TestInt32Unop(kExprI32Clz, 18, 0x00002050); 285 TestInt32Unop(kExprI32Clz, 19, 0x00001700); 286 TestInt32Unop(kExprI32Clz, 20, 0x00000870); 287 TestInt32Unop(kExprI32Clz, 21, 0x00000405); 288 TestInt32Unop(kExprI32Clz, 22, 0x00000203); 289 TestInt32Unop(kExprI32Clz, 23, 0x00000101); 290 TestInt32Unop(kExprI32Clz, 24, 0x00000089); 291 TestInt32Unop(kExprI32Clz, 25, 0x00000041); 292 TestInt32Unop(kExprI32Clz, 26, 0x00000022); 293 TestInt32Unop(kExprI32Clz, 27, 0x00000013); 294 TestInt32Unop(kExprI32Clz, 28, 0x00000008); 295 TestInt32Unop(kExprI32Clz, 29, 0x00000004); 296 TestInt32Unop(kExprI32Clz, 30, 0x00000002); 297 TestInt32Unop(kExprI32Clz, 31, 0x00000001); 298 TestInt32Unop(kExprI32Clz, 32, 0x00000000); 299 } 300 301 302 TEST(Run_WasmInt32Ctz) { 303 TestInt32Unop(kExprI32Ctz, 32, 0x00000000); 304 TestInt32Unop(kExprI32Ctz, 31, 0x80000000); 305 TestInt32Unop(kExprI32Ctz, 30, 0x40000000); 306 TestInt32Unop(kExprI32Ctz, 29, 0x20000000); 307 TestInt32Unop(kExprI32Ctz, 28, 0x10000000); 308 TestInt32Unop(kExprI32Ctz, 27, 0xa8000000); 309 TestInt32Unop(kExprI32Ctz, 26, 0xf4000000); 310 TestInt32Unop(kExprI32Ctz, 25, 0x62000000); 311 TestInt32Unop(kExprI32Ctz, 24, 0x91000000); 312 TestInt32Unop(kExprI32Ctz, 23, 0xcd800000); 313 TestInt32Unop(kExprI32Ctz, 22, 0x09400000); 314 TestInt32Unop(kExprI32Ctz, 21, 0xaf200000); 315 TestInt32Unop(kExprI32Ctz, 20, 0xac100000); 316 TestInt32Unop(kExprI32Ctz, 19, 0xe0b80000); 317 TestInt32Unop(kExprI32Ctz, 18, 0x9ce40000); 318 TestInt32Unop(kExprI32Ctz, 17, 0xc7920000); 319 TestInt32Unop(kExprI32Ctz, 16, 0xb8f10000); 320 TestInt32Unop(kExprI32Ctz, 15, 0x3b9f8000); 321 TestInt32Unop(kExprI32Ctz, 14, 0xdb4c4000); 322 TestInt32Unop(kExprI32Ctz, 13, 0xe9a32000); 323 TestInt32Unop(kExprI32Ctz, 12, 0xfca61000); 324 TestInt32Unop(kExprI32Ctz, 11, 0x6c8a7800); 325 TestInt32Unop(kExprI32Ctz, 10, 0x8ce5a400); 326 TestInt32Unop(kExprI32Ctz, 9, 0xcb7d0200); 327 TestInt32Unop(kExprI32Ctz, 8, 0xcb4dc100); 328 TestInt32Unop(kExprI32Ctz, 7, 0xdfbec580); 329 TestInt32Unop(kExprI32Ctz, 6, 0x27a9db40); 330 TestInt32Unop(kExprI32Ctz, 5, 0xde3bcb20); 331 TestInt32Unop(kExprI32Ctz, 4, 0xd7e8a610); 332 TestInt32Unop(kExprI32Ctz, 3, 0x9afdbc88); 333 TestInt32Unop(kExprI32Ctz, 2, 0x9afdbc84); 334 TestInt32Unop(kExprI32Ctz, 1, 0x9afdbc82); 335 TestInt32Unop(kExprI32Ctz, 0, 0x9afdbc81); 336 } 337 338 339 TEST(Run_WasmInt32Popcnt) { 340 TestInt32Unop(kExprI32Popcnt, 32, 0xffffffff); 341 TestInt32Unop(kExprI32Popcnt, 0, 0x00000000); 342 TestInt32Unop(kExprI32Popcnt, 1, 0x00008000); 343 TestInt32Unop(kExprI32Popcnt, 13, 0x12345678); 344 TestInt32Unop(kExprI32Popcnt, 19, 0xfedcba09); 345 } 346 347 348 #if WASM_64 349 void TestInt64Binop(WasmOpcode opcode, int64_t expected, int64_t a, int64_t b) { 350 if (!WasmOpcodes::IsSupported(opcode)) return; 351 { 352 WasmRunner<int64_t> r; 353 // return K op K 354 BUILD(r, WASM_BINOP(opcode, WASM_I64(a), WASM_I64(b))); 355 CHECK_EQ(expected, r.Call()); 356 } 357 { 358 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); 359 // return a op b 360 BUILD(r, WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 361 CHECK_EQ(expected, r.Call(a, b)); 362 } 363 } 364 365 366 void TestInt64Cmp(WasmOpcode opcode, int64_t expected, int64_t a, int64_t b) { 367 if (!WasmOpcodes::IsSupported(opcode)) return; 368 { 369 WasmRunner<int32_t> r; 370 // return K op K 371 BUILD(r, WASM_BINOP(opcode, WASM_I64(a), WASM_I64(b))); 372 CHECK_EQ(expected, r.Call()); 373 } 374 { 375 WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64()); 376 // return a op b 377 BUILD(r, WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 378 CHECK_EQ(expected, r.Call(a, b)); 379 } 380 } 381 382 383 TEST(Run_WasmInt64Binops) { 384 // TODO(titzer): real 64-bit numbers 385 TestInt64Binop(kExprI64Add, 8888888888888LL, 3333333333333LL, 386 5555555555555LL); 387 TestInt64Binop(kExprI64Sub, -111111111111LL, 777777777777LL, 888888888888LL); 388 TestInt64Binop(kExprI64Mul, 65130756, 88734, 734); 389 TestInt64Binop(kExprI64DivS, -66, -4777344, 72384); 390 TestInt64Binop(kExprI64DivU, 805306368, 0xF0000000, 5); 391 TestInt64Binop(kExprI64RemS, -3, -3003, 1000); 392 TestInt64Binop(kExprI64RemU, 4, 4004, 1000); 393 TestInt64Binop(kExprI64And, 0xEE, 0xFFEE, 0xFF0000FF); 394 TestInt64Binop(kExprI64Ior, 0xF0FF00FF, 0xF0F000EE, 0x000F0011); 395 TestInt64Binop(kExprI64Xor, 0xABCDEF01, 0xABCDEFFF, 0xFE); 396 TestInt64Binop(kExprI64Shl, 0xA0000000, 0xA, 28); 397 TestInt64Binop(kExprI64ShrU, 0x0700001000123456LL, 0x7000010001234567LL, 4); 398 TestInt64Binop(kExprI64ShrS, 0xFF00000000000000LL, 0x8000000000000000LL, 7); 399 TestInt64Cmp(kExprI64Eq, 1, -9999, -9999); 400 TestInt64Cmp(kExprI64Ne, 1, -9199, -9999); 401 TestInt64Cmp(kExprI64LtS, 1, -4, 4); 402 TestInt64Cmp(kExprI64LeS, 0, -2, -3); 403 TestInt64Cmp(kExprI64LtU, 1, 0, -6); 404 TestInt64Cmp(kExprI64LeU, 1, 98978, 0xF0000000); 405 } 406 407 408 TEST(Run_WasmInt64Clz) { 409 struct { 410 int64_t expected; 411 uint64_t input; 412 } values[] = {{0, 0x8000100000000000}, {1, 0x4000050000000000}, 413 {2, 0x2000030000000000}, {3, 0x1000000300000000}, 414 {4, 0x0805000000000000}, {5, 0x0400600000000000}, 415 {6, 0x0200000000000000}, {7, 0x010000a000000000}, 416 {8, 0x00800c0000000000}, {9, 0x0040000000000000}, 417 {10, 0x0020000d00000000}, {11, 0x00100f0000000000}, 418 {12, 0x0008000000000000}, {13, 0x0004100000000000}, 419 {14, 0x0002002000000000}, {15, 0x0001030000000000}, 420 {16, 0x0000804000000000}, {17, 0x0000400500000000}, 421 {18, 0x0000205000000000}, {19, 0x0000170000000000}, 422 {20, 0x0000087000000000}, {21, 0x0000040500000000}, 423 {22, 0x0000020300000000}, {23, 0x0000010100000000}, 424 {24, 0x0000008900000000}, {25, 0x0000004100000000}, 425 {26, 0x0000002200000000}, {27, 0x0000001300000000}, 426 {28, 0x0000000800000000}, {29, 0x0000000400000000}, 427 {30, 0x0000000200000000}, {31, 0x0000000100000000}, 428 {32, 0x0000000080001000}, {33, 0x0000000040000500}, 429 {34, 0x0000000020000300}, {35, 0x0000000010000003}, 430 {36, 0x0000000008050000}, {37, 0x0000000004006000}, 431 {38, 0x0000000002000000}, {39, 0x00000000010000a0}, 432 {40, 0x0000000000800c00}, {41, 0x0000000000400000}, 433 {42, 0x000000000020000d}, {43, 0x0000000000100f00}, 434 {44, 0x0000000000080000}, {45, 0x0000000000041000}, 435 {46, 0x0000000000020020}, {47, 0x0000000000010300}, 436 {48, 0x0000000000008040}, {49, 0x0000000000004005}, 437 {50, 0x0000000000002050}, {51, 0x0000000000001700}, 438 {52, 0x0000000000000870}, {53, 0x0000000000000405}, 439 {54, 0x0000000000000203}, {55, 0x0000000000000101}, 440 {56, 0x0000000000000089}, {57, 0x0000000000000041}, 441 {58, 0x0000000000000022}, {59, 0x0000000000000013}, 442 {60, 0x0000000000000008}, {61, 0x0000000000000004}, 443 {62, 0x0000000000000002}, {63, 0x0000000000000001}, 444 {64, 0x0000000000000000}}; 445 446 WasmRunner<int64_t> r(MachineType::Uint64()); 447 BUILD(r, WASM_I64_CLZ(WASM_GET_LOCAL(0))); 448 for (size_t i = 0; i < arraysize(values); i++) { 449 CHECK_EQ(values[i].expected, r.Call(values[i].input)); 450 } 451 } 452 453 454 TEST(Run_WasmInt64Ctz) { 455 struct { 456 int64_t expected; 457 uint64_t input; 458 } values[] = {{64, 0x0000000000000000}, {63, 0x8000000000000000}, 459 {62, 0x4000000000000000}, {61, 0x2000000000000000}, 460 {60, 0x1000000000000000}, {59, 0xa800000000000000}, 461 {58, 0xf400000000000000}, {57, 0x6200000000000000}, 462 {56, 0x9100000000000000}, {55, 0xcd80000000000000}, 463 {54, 0x0940000000000000}, {53, 0xaf20000000000000}, 464 {52, 0xac10000000000000}, {51, 0xe0b8000000000000}, 465 {50, 0x9ce4000000000000}, {49, 0xc792000000000000}, 466 {48, 0xb8f1000000000000}, {47, 0x3b9f800000000000}, 467 {46, 0xdb4c400000000000}, {45, 0xe9a3200000000000}, 468 {44, 0xfca6100000000000}, {43, 0x6c8a780000000000}, 469 {42, 0x8ce5a40000000000}, {41, 0xcb7d020000000000}, 470 {40, 0xcb4dc10000000000}, {39, 0xdfbec58000000000}, 471 {38, 0x27a9db4000000000}, {37, 0xde3bcb2000000000}, 472 {36, 0xd7e8a61000000000}, {35, 0x9afdbc8800000000}, 473 {34, 0x9afdbc8400000000}, {33, 0x9afdbc8200000000}, 474 {32, 0x9afdbc8100000000}, {31, 0x0000000080000000}, 475 {30, 0x0000000040000000}, {29, 0x0000000020000000}, 476 {28, 0x0000000010000000}, {27, 0x00000000a8000000}, 477 {26, 0x00000000f4000000}, {25, 0x0000000062000000}, 478 {24, 0x0000000091000000}, {23, 0x00000000cd800000}, 479 {22, 0x0000000009400000}, {21, 0x00000000af200000}, 480 {20, 0x00000000ac100000}, {19, 0x00000000e0b80000}, 481 {18, 0x000000009ce40000}, {17, 0x00000000c7920000}, 482 {16, 0x00000000b8f10000}, {15, 0x000000003b9f8000}, 483 {14, 0x00000000db4c4000}, {13, 0x00000000e9a32000}, 484 {12, 0x00000000fca61000}, {11, 0x000000006c8a7800}, 485 {10, 0x000000008ce5a400}, {9, 0x00000000cb7d0200}, 486 {8, 0x00000000cb4dc100}, {7, 0x00000000dfbec580}, 487 {6, 0x0000000027a9db40}, {5, 0x00000000de3bcb20}, 488 {4, 0x00000000d7e8a610}, {3, 0x000000009afdbc88}, 489 {2, 0x000000009afdbc84}, {1, 0x000000009afdbc82}, 490 {0, 0x000000009afdbc81}}; 491 492 WasmRunner<int64_t> r(MachineType::Uint64()); 493 BUILD(r, WASM_I64_CTZ(WASM_GET_LOCAL(0))); 494 for (size_t i = 0; i < arraysize(values); i++) { 495 CHECK_EQ(values[i].expected, r.Call(values[i].input)); 496 } 497 } 498 499 500 TEST(Run_WasmInt64Popcnt) { 501 struct { 502 int64_t expected; 503 uint64_t input; 504 } values[] = {{64, 0xffffffffffffffff}, 505 {0, 0x0000000000000000}, 506 {2, 0x0000080000008000}, 507 {26, 0x1123456782345678}, 508 {38, 0xffedcba09edcba09}}; 509 510 WasmRunner<int64_t> r(MachineType::Uint64()); 511 BUILD(r, WASM_I64_POPCNT(WASM_GET_LOCAL(0))); 512 for (size_t i = 0; i < arraysize(values); i++) { 513 CHECK_EQ(values[i].expected, r.Call(values[i].input)); 514 } 515 } 516 517 518 #endif 519 520 TEST(Run_WASM_Int32DivS_trap) { 521 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32()); 522 BUILD(r, WASM_I32_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 523 CHECK_EQ(0, r.Call(0, 100)); 524 CHECK_TRAP(r.Call(100, 0)); 525 CHECK_TRAP(r.Call(-1001, 0)); 526 CHECK_TRAP(r.Call(std::numeric_limits<int32_t>::min(), -1)); 527 CHECK_TRAP(r.Call(std::numeric_limits<int32_t>::min(), 0)); 528 } 529 530 531 TEST(Run_WASM_Int32RemS_trap) { 532 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32()); 533 BUILD(r, WASM_I32_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 534 CHECK_EQ(33, r.Call(133, 100)); 535 CHECK_EQ(0, r.Call(std::numeric_limits<int32_t>::min(), -1)); 536 CHECK_TRAP(r.Call(100, 0)); 537 CHECK_TRAP(r.Call(-1001, 0)); 538 CHECK_TRAP(r.Call(std::numeric_limits<int32_t>::min(), 0)); 539 } 540 541 542 TEST(Run_WASM_Int32DivU_trap) { 543 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32()); 544 BUILD(r, WASM_I32_DIVU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 545 CHECK_EQ(0, r.Call(0, 100)); 546 CHECK_EQ(0, r.Call(std::numeric_limits<int32_t>::min(), -1)); 547 CHECK_TRAP(r.Call(100, 0)); 548 CHECK_TRAP(r.Call(-1001, 0)); 549 CHECK_TRAP(r.Call(std::numeric_limits<int32_t>::min(), 0)); 550 } 551 552 553 TEST(Run_WASM_Int32RemU_trap) { 554 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32()); 555 BUILD(r, WASM_I32_REMU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 556 CHECK_EQ(17, r.Call(217, 100)); 557 CHECK_TRAP(r.Call(100, 0)); 558 CHECK_TRAP(r.Call(-1001, 0)); 559 CHECK_TRAP(r.Call(std::numeric_limits<int32_t>::min(), 0)); 560 CHECK_EQ(std::numeric_limits<int32_t>::min(), 561 r.Call(std::numeric_limits<int32_t>::min(), -1)); 562 } 563 564 565 TEST(Run_WASM_Int32DivS_byzero_const) { 566 for (int8_t denom = -2; denom < 8; denom++) { 567 WasmRunner<int32_t> r(MachineType::Int32()); 568 BUILD(r, WASM_I32_DIVS(WASM_GET_LOCAL(0), WASM_I8(denom))); 569 for (int32_t val = -7; val < 8; val++) { 570 if (denom == 0) { 571 CHECK_TRAP(r.Call(val)); 572 } else { 573 CHECK_EQ(val / denom, r.Call(val)); 574 } 575 } 576 } 577 } 578 579 580 TEST(Run_WASM_Int32DivU_byzero_const) { 581 for (uint32_t denom = 0xfffffffe; denom < 8; denom++) { 582 WasmRunner<uint32_t> r(MachineType::Uint32()); 583 BUILD(r, WASM_I32_DIVU(WASM_GET_LOCAL(0), WASM_I32(denom))); 584 585 for (uint32_t val = 0xfffffff0; val < 8; val++) { 586 if (denom == 0) { 587 CHECK_TRAP(r.Call(val)); 588 } else { 589 CHECK_EQ(val / denom, r.Call(val)); 590 } 591 } 592 } 593 } 594 595 596 TEST(Run_WASM_Int32DivS_trap_effect) { 597 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32()); 598 TestingModule module; 599 module.AddMemoryElems<int32_t>(8); 600 r.env()->module = &module; 601 602 BUILD(r, 603 WASM_IF_ELSE(WASM_GET_LOCAL(0), 604 WASM_I32_DIVS(WASM_STORE_MEM(MachineType::Int8(), 605 WASM_ZERO, WASM_GET_LOCAL(0)), 606 WASM_GET_LOCAL(1)), 607 WASM_I32_DIVS(WASM_STORE_MEM(MachineType::Int8(), 608 WASM_ZERO, WASM_GET_LOCAL(0)), 609 WASM_GET_LOCAL(1)))); 610 CHECK_EQ(0, r.Call(0, 100)); 611 CHECK_TRAP(r.Call(8, 0)); 612 CHECK_TRAP(r.Call(4, 0)); 613 CHECK_TRAP(r.Call(0, 0)); 614 } 615 616 617 #if WASM_64 618 #define as64(x) static_cast<int64_t>(x) 619 TEST(Run_WASM_Int64DivS_trap) { 620 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); 621 BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 622 CHECK_EQ(0, r.Call(as64(0), as64(100))); 623 CHECK_TRAP64(r.Call(as64(100), as64(0))); 624 CHECK_TRAP64(r.Call(as64(-1001), as64(0))); 625 CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), as64(-1))); 626 CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), as64(0))); 627 } 628 629 630 TEST(Run_WASM_Int64RemS_trap) { 631 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); 632 BUILD(r, WASM_I64_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 633 CHECK_EQ(33, r.Call(as64(133), as64(100))); 634 CHECK_EQ(0, r.Call(std::numeric_limits<int64_t>::min(), as64(-1))); 635 CHECK_TRAP64(r.Call(as64(100), as64(0))); 636 CHECK_TRAP64(r.Call(as64(-1001), as64(0))); 637 CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), as64(0))); 638 } 639 640 641 TEST(Run_WASM_Int64DivU_trap) { 642 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); 643 BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 644 CHECK_EQ(0, r.Call(as64(0), as64(100))); 645 CHECK_EQ(0, r.Call(std::numeric_limits<int64_t>::min(), as64(-1))); 646 CHECK_TRAP64(r.Call(as64(100), as64(0))); 647 CHECK_TRAP64(r.Call(as64(-1001), as64(0))); 648 CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), as64(0))); 649 } 650 651 652 TEST(Run_WASM_Int64RemU_trap) { 653 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); 654 BUILD(r, WASM_I64_REMU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 655 CHECK_EQ(17, r.Call(as64(217), as64(100))); 656 CHECK_TRAP64(r.Call(as64(100), as64(0))); 657 CHECK_TRAP64(r.Call(as64(-1001), as64(0))); 658 CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), as64(0))); 659 CHECK_EQ(std::numeric_limits<int64_t>::min(), 660 r.Call(std::numeric_limits<int64_t>::min(), as64(-1))); 661 } 662 663 664 TEST(Run_WASM_Int64DivS_byzero_const) { 665 for (int8_t denom = -2; denom < 8; denom++) { 666 WasmRunner<int64_t> r(MachineType::Int64()); 667 BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_I64(denom))); 668 for (int64_t val = -7; val < 8; val++) { 669 if (denom == 0) { 670 CHECK_TRAP64(r.Call(val)); 671 } else { 672 CHECK_EQ(val / denom, r.Call(val)); 673 } 674 } 675 } 676 } 677 678 679 TEST(Run_WASM_Int64DivU_byzero_const) { 680 for (uint64_t denom = 0xfffffffffffffffe; denom < 8; denom++) { 681 WasmRunner<uint64_t> r(MachineType::Uint64()); 682 BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_I64(denom))); 683 684 for (uint64_t val = 0xfffffffffffffff0; val < 8; val++) { 685 if (denom == 0) { 686 CHECK_TRAP64(r.Call(val)); 687 } else { 688 CHECK_EQ(val / denom, r.Call(val)); 689 } 690 } 691 } 692 } 693 #endif 694 695 696 void TestFloat32Binop(WasmOpcode opcode, int32_t expected, float a, float b) { 697 { 698 WasmRunner<int32_t> r; 699 // return K op K 700 BUILD(r, WASM_BINOP(opcode, WASM_F32(a), WASM_F32(b))); 701 CHECK_EQ(expected, r.Call()); 702 } 703 { 704 WasmRunner<int32_t> r(MachineType::Float32(), MachineType::Float32()); 705 // return a op b 706 BUILD(r, WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 707 CHECK_EQ(expected, r.Call(a, b)); 708 } 709 } 710 711 712 void TestFloat32BinopWithConvert(WasmOpcode opcode, int32_t expected, float a, 713 float b) { 714 { 715 WasmRunner<int32_t> r; 716 // return int(K op K) 717 BUILD(r, 718 WASM_I32_SCONVERT_F32(WASM_BINOP(opcode, WASM_F32(a), WASM_F32(b)))); 719 CHECK_EQ(expected, r.Call()); 720 } 721 { 722 WasmRunner<int32_t> r(MachineType::Float32(), MachineType::Float32()); 723 // return int(a op b) 724 BUILD(r, WASM_I32_SCONVERT_F32( 725 WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)))); 726 CHECK_EQ(expected, r.Call(a, b)); 727 } 728 } 729 730 731 void TestFloat32UnopWithConvert(WasmOpcode opcode, int32_t expected, float a) { 732 { 733 WasmRunner<int32_t> r; 734 // return int(op(K)) 735 BUILD(r, WASM_I32_SCONVERT_F32(WASM_UNOP(opcode, WASM_F32(a)))); 736 CHECK_EQ(expected, r.Call()); 737 } 738 { 739 WasmRunner<int32_t> r(MachineType::Float32()); 740 // return int(op(a)) 741 BUILD(r, WASM_I32_SCONVERT_F32(WASM_UNOP(opcode, WASM_GET_LOCAL(0)))); 742 CHECK_EQ(expected, r.Call(a)); 743 } 744 } 745 746 747 void TestFloat64Binop(WasmOpcode opcode, int32_t expected, double a, double b) { 748 { 749 WasmRunner<int32_t> r; 750 // return K op K 751 BUILD(r, WASM_BINOP(opcode, WASM_F64(a), WASM_F64(b))); 752 CHECK_EQ(expected, r.Call()); 753 } 754 { 755 WasmRunner<int32_t> r(MachineType::Float64(), MachineType::Float64()); 756 // return a op b 757 BUILD(r, WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 758 CHECK_EQ(expected, r.Call(a, b)); 759 } 760 } 761 762 763 void TestFloat64BinopWithConvert(WasmOpcode opcode, int32_t expected, double a, 764 double b) { 765 { 766 WasmRunner<int32_t> r; 767 // return int(K op K) 768 BUILD(r, 769 WASM_I32_SCONVERT_F64(WASM_BINOP(opcode, WASM_F64(a), WASM_F64(b)))); 770 CHECK_EQ(expected, r.Call()); 771 } 772 { 773 WasmRunner<int32_t> r(MachineType::Float64(), MachineType::Float64()); 774 BUILD(r, WASM_I32_SCONVERT_F64( 775 WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)))); 776 CHECK_EQ(expected, r.Call(a, b)); 777 } 778 } 779 780 781 void TestFloat64UnopWithConvert(WasmOpcode opcode, int32_t expected, double a) { 782 { 783 WasmRunner<int32_t> r; 784 // return int(op(K)) 785 BUILD(r, WASM_I32_SCONVERT_F64(WASM_UNOP(opcode, WASM_F64(a)))); 786 CHECK_EQ(expected, r.Call()); 787 } 788 { 789 WasmRunner<int32_t> r(MachineType::Float64()); 790 // return int(op(a)) 791 BUILD(r, WASM_I32_SCONVERT_F64(WASM_UNOP(opcode, WASM_GET_LOCAL(0)))); 792 CHECK_EQ(expected, r.Call(a)); 793 } 794 } 795 796 797 // TODO(titzer): Fix for nosee4 and re-enable. 798 #if 0 799 800 TEST(Run_WasmFloat32Binops) { 801 TestFloat32Binop(kExprF32Eq, 1, 8.125f, 8.125f); 802 TestFloat32Binop(kExprF32Ne, 1, 8.125f, 8.127f); 803 TestFloat32Binop(kExprF32Lt, 1, -9.5f, -9.0f); 804 TestFloat32Binop(kExprF32Le, 1, -1111.0f, -1111.0f); 805 TestFloat32Binop(kExprF32Gt, 1, -9.0f, -9.5f); 806 TestFloat32Binop(kExprF32Ge, 1, -1111.0f, -1111.0f); 807 808 TestFloat32BinopWithConvert(kExprF32Add, 10, 3.5f, 6.5f); 809 TestFloat32BinopWithConvert(kExprF32Sub, 2, 44.5f, 42.5f); 810 TestFloat32BinopWithConvert(kExprF32Mul, -66, -132.1f, 0.5f); 811 TestFloat32BinopWithConvert(kExprF32Div, 11, 22.1f, 2.0f); 812 } 813 814 815 TEST(Run_WasmFloat32Unops) { 816 TestFloat32UnopWithConvert(kExprF32Abs, 8, 8.125f); 817 TestFloat32UnopWithConvert(kExprF32Abs, 9, -9.125f); 818 TestFloat32UnopWithConvert(kExprF32Neg, -213, 213.125f); 819 TestFloat32UnopWithConvert(kExprF32Sqrt, 12, 144.4f); 820 } 821 822 823 TEST(Run_WasmFloat64Binops) { 824 TestFloat64Binop(kExprF64Eq, 1, 16.25, 16.25); 825 TestFloat64Binop(kExprF64Ne, 1, 16.25, 16.15); 826 TestFloat64Binop(kExprF64Lt, 1, -32.4, 11.7); 827 TestFloat64Binop(kExprF64Le, 1, -88.9, -88.9); 828 TestFloat64Binop(kExprF64Gt, 1, 11.7, -32.4); 829 TestFloat64Binop(kExprF64Ge, 1, -88.9, -88.9); 830 831 TestFloat64BinopWithConvert(kExprF64Add, 100, 43.5, 56.5); 832 TestFloat64BinopWithConvert(kExprF64Sub, 200, 12200.1, 12000.1); 833 TestFloat64BinopWithConvert(kExprF64Mul, -33, 134, -0.25); 834 TestFloat64BinopWithConvert(kExprF64Div, -1111, -2222.3, 2); 835 } 836 837 838 TEST(Run_WasmFloat64Unops) { 839 TestFloat64UnopWithConvert(kExprF64Abs, 108, 108.125); 840 TestFloat64UnopWithConvert(kExprF64Abs, 209, -209.125); 841 TestFloat64UnopWithConvert(kExprF64Neg, -209, 209.125); 842 TestFloat64UnopWithConvert(kExprF64Sqrt, 13, 169.4); 843 } 844 845 #endif 846 847 848 TEST(Run_WasmFloat32Neg) { 849 WasmRunner<float> r(MachineType::Float32()); 850 BUILD(r, WASM_F32_NEG(WASM_GET_LOCAL(0))); 851 852 FOR_FLOAT32_INPUTS(i) { 853 CHECK_EQ(0x80000000, 854 bit_cast<uint32_t>(*i) ^ bit_cast<uint32_t>(r.Call(*i))); 855 } 856 } 857 858 859 TEST(Run_WasmFloat64Neg) { 860 WasmRunner<double> r(MachineType::Float64()); 861 BUILD(r, WASM_F64_NEG(WASM_GET_LOCAL(0))); 862 863 FOR_FLOAT64_INPUTS(i) { 864 CHECK_EQ(0x8000000000000000, 865 bit_cast<uint64_t>(*i) ^ bit_cast<uint64_t>(r.Call(*i))); 866 } 867 } 868 869 870 TEST(Run_Wasm_IfElse_P) { 871 WasmRunner<int32_t> r(MachineType::Int32()); 872 // if (p0) return 11; else return 22; 873 BUILD(r, WASM_IF_ELSE(WASM_GET_LOCAL(0), // -- 874 WASM_I8(11), // -- 875 WASM_I8(22))); // -- 876 FOR_INT32_INPUTS(i) { 877 int32_t expected = *i ? 11 : 22; 878 CHECK_EQ(expected, r.Call(*i)); 879 } 880 } 881 882 883 TEST(Run_Wasm_IfElse_Unreachable1) { 884 WasmRunner<int32_t> r; 885 // if (0) unreachable; else return 22; 886 BUILD(r, WASM_IF_ELSE(WASM_ZERO, // -- 887 WASM_UNREACHABLE, // -- 888 WASM_I8(27))); // -- 889 CHECK_EQ(27, r.Call()); 890 } 891 892 893 TEST(Run_Wasm_Return12) { 894 WasmRunner<int32_t> r; 895 896 BUILD(r, WASM_RETURN(WASM_I8(12))); 897 CHECK_EQ(12, r.Call()); 898 } 899 900 901 TEST(Run_Wasm_Return17) { 902 WasmRunner<int32_t> r; 903 904 BUILD(r, WASM_BLOCK(1, WASM_RETURN(WASM_I8(17)))); 905 CHECK_EQ(17, r.Call()); 906 } 907 908 909 TEST(Run_Wasm_Return_I32) { 910 WasmRunner<int32_t> r(MachineType::Int32()); 911 912 BUILD(r, WASM_RETURN(WASM_GET_LOCAL(0))); 913 914 FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); } 915 } 916 917 918 #if WASM_64 919 TEST(Run_Wasm_Return_I64) { 920 WasmRunner<int64_t> r(MachineType::Int64()); 921 922 BUILD(r, WASM_RETURN(WASM_GET_LOCAL(0))); 923 924 FOR_INT64_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); } 925 } 926 #endif 927 928 929 TEST(Run_Wasm_Return_F32) { 930 WasmRunner<float> r(MachineType::Float32()); 931 932 BUILD(r, WASM_RETURN(WASM_GET_LOCAL(0))); 933 934 FOR_FLOAT32_INPUTS(i) { 935 float expect = *i; 936 float result = r.Call(expect); 937 if (std::isnan(expect)) { 938 CHECK(std::isnan(result)); 939 } else { 940 CHECK_EQ(expect, result); 941 } 942 } 943 } 944 945 946 TEST(Run_Wasm_Return_F64) { 947 WasmRunner<double> r(MachineType::Float64()); 948 949 BUILD(r, WASM_RETURN(WASM_GET_LOCAL(0))); 950 951 FOR_FLOAT64_INPUTS(i) { 952 double expect = *i; 953 double result = r.Call(expect); 954 if (std::isnan(expect)) { 955 CHECK(std::isnan(result)); 956 } else { 957 CHECK_EQ(expect, result); 958 } 959 } 960 } 961 962 963 TEST(Run_Wasm_Select) { 964 WasmRunner<int32_t> r(MachineType::Int32()); 965 // return select(a, 11, 22); 966 BUILD(r, WASM_SELECT(WASM_GET_LOCAL(0), WASM_I8(11), WASM_I8(22))); 967 FOR_INT32_INPUTS(i) { 968 int32_t expected = *i ? 11 : 22; 969 CHECK_EQ(expected, r.Call(*i)); 970 } 971 } 972 973 974 TEST(Run_Wasm_Select_strict1) { 975 WasmRunner<int32_t> r(MachineType::Int32()); 976 // select(a, a = 11, 22); return a 977 BUILD(r, 978 WASM_BLOCK(2, WASM_SELECT(WASM_GET_LOCAL(0), 979 WASM_SET_LOCAL(0, WASM_I8(11)), WASM_I8(22)), 980 WASM_GET_LOCAL(0))); 981 FOR_INT32_INPUTS(i) { CHECK_EQ(11, r.Call(*i)); } 982 } 983 984 985 TEST(Run_Wasm_Select_strict2) { 986 WasmRunner<int32_t> r(MachineType::Int32()); 987 // select(a, 11, a = 22); return a; 988 BUILD(r, WASM_BLOCK(2, WASM_SELECT(WASM_GET_LOCAL(0), WASM_I8(11), 989 WASM_SET_LOCAL(0, WASM_I8(22))), 990 WASM_GET_LOCAL(0))); 991 FOR_INT32_INPUTS(i) { CHECK_EQ(22, r.Call(*i)); } 992 } 993 994 995 TEST(Run_Wasm_BrIf_strict) { 996 WasmRunner<int32_t> r(MachineType::Int32()); 997 BUILD(r, WASM_BLOCK( 998 2, WASM_BLOCK(1, WASM_BRV_IF(0, WASM_GET_LOCAL(0), 999 WASM_SET_LOCAL(0, WASM_I8(99)))), 1000 WASM_GET_LOCAL(0))); 1001 1002 FOR_INT32_INPUTS(i) { CHECK_EQ(99, r.Call(*i)); } 1003 } 1004 1005 1006 TEST(Run_Wasm_TableSwitch1) { 1007 WasmRunner<int32_t> r(MachineType::Int32()); 1008 BUILD(r, WASM_TABLESWITCH_OP(1, 1, WASM_CASE(0)), 1009 WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_RETURN(WASM_I8(93)))); 1010 FOR_INT32_INPUTS(i) { CHECK_EQ(93, r.Call(*i)); } 1011 } 1012 1013 1014 TEST(Run_Wasm_TableSwitch_br) { 1015 WasmRunner<int32_t> r(MachineType::Int32()); 1016 BUILD(r, WASM_TABLESWITCH_OP(1, 2, WASM_CASE_BR(0), WASM_CASE(0)), 1017 WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_RETURN(WASM_I8(91))), 1018 WASM_I8(99)); 1019 CHECK_EQ(99, r.Call(0)); 1020 CHECK_EQ(91, r.Call(1)); 1021 CHECK_EQ(91, r.Call(2)); 1022 CHECK_EQ(91, r.Call(3)); 1023 } 1024 1025 1026 TEST(Run_Wasm_TableSwitch_br2) { 1027 WasmRunner<int32_t> r(MachineType::Int32()); 1028 BUILD(r, WASM_BLOCK( 1029 2, WASM_BLOCK(2, WASM_TABLESWITCH_OP( 1030 1, 4, WASM_CASE_BR(0), WASM_CASE_BR(1), 1031 WASM_CASE_BR(2), WASM_CASE(0)), 1032 WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), 1033 WASM_RETURN(WASM_I8(85))), 1034 WASM_RETURN(WASM_I8(86))), 1035 WASM_RETURN(WASM_I8(87))), 1036 WASM_I8(88)); 1037 CHECK_EQ(86, r.Call(0)); 1038 CHECK_EQ(87, r.Call(1)); 1039 CHECK_EQ(88, r.Call(2)); 1040 CHECK_EQ(85, r.Call(3)); 1041 CHECK_EQ(85, r.Call(4)); 1042 CHECK_EQ(85, r.Call(5)); 1043 } 1044 1045 1046 TEST(Run_Wasm_TableSwitch2) { 1047 WasmRunner<int32_t> r(MachineType::Int32()); 1048 BUILD(r, WASM_TABLESWITCH_OP(2, 2, WASM_CASE(0), WASM_CASE(1)), 1049 WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_RETURN(WASM_I8(91)), 1050 WASM_RETURN(WASM_I8(92)))); 1051 FOR_INT32_INPUTS(i) { 1052 int32_t expected = *i == 0 ? 91 : 92; 1053 CHECK_EQ(expected, r.Call(*i)); 1054 } 1055 } 1056 1057 1058 TEST(Run_Wasm_TableSwitch2b) { 1059 WasmRunner<int32_t> r(MachineType::Int32()); 1060 BUILD(r, WASM_TABLESWITCH_OP(2, 2, WASM_CASE(1), WASM_CASE(0)), 1061 WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_RETURN(WASM_I8(81)), 1062 WASM_RETURN(WASM_I8(82)))); 1063 FOR_INT32_INPUTS(i) { 1064 int32_t expected = *i == 0 ? 82 : 81; 1065 CHECK_EQ(expected, r.Call(*i)); 1066 } 1067 } 1068 1069 1070 TEST(Run_Wasm_TableSwitch4) { 1071 for (int i = 0; i < 4; i++) { 1072 const uint16_t br = 0x8000u; 1073 uint16_t c = 0; 1074 uint16_t cases[] = {i == 0 ? br : c++, i == 1 ? br : c++, i == 2 ? br : c++, 1075 i == 3 ? br : c++}; 1076 byte code[] = { 1077 WASM_BLOCK(1, WASM_TABLESWITCH_OP( 1078 3, 4, WASM_CASE(cases[0]), WASM_CASE(cases[1]), 1079 WASM_CASE(cases[2]), WASM_CASE(cases[3])), 1080 WASM_TABLESWITCH_BODY( 1081 WASM_GET_LOCAL(0), WASM_RETURN(WASM_I8(71)), 1082 WASM_RETURN(WASM_I8(72)), WASM_RETURN(WASM_I8(73)))), 1083 WASM_RETURN(WASM_I8(74))}; 1084 1085 WasmRunner<int32_t> r(MachineType::Int32()); 1086 r.Build(code, code + arraysize(code)); 1087 1088 FOR_INT32_INPUTS(i) { 1089 int index = (*i < 0 || *i > 3) ? 3 : *i; 1090 int32_t expected = 71 + cases[index]; 1091 if (expected >= 0x8000) expected = 74; 1092 CHECK_EQ(expected, r.Call(*i)); 1093 } 1094 } 1095 } 1096 1097 1098 TEST(Run_Wasm_TableSwitch4b) { 1099 for (int a = 0; a < 2; a++) { 1100 for (int b = 0; b < 2; b++) { 1101 for (int c = 0; c < 2; c++) { 1102 for (int d = 0; d < 2; d++) { 1103 if (a + b + c + d == 0) continue; 1104 if (a + b + c + d == 4) continue; 1105 1106 byte code[] = { 1107 WASM_TABLESWITCH_OP(2, 4, WASM_CASE(a), WASM_CASE(b), 1108 WASM_CASE(c), WASM_CASE(d)), 1109 WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_RETURN(WASM_I8(61)), 1110 WASM_RETURN(WASM_I8(62)))}; 1111 1112 WasmRunner<int32_t> r(MachineType::Int32()); 1113 r.Build(code, code + arraysize(code)); 1114 1115 CHECK_EQ(61 + a, r.Call(0)); 1116 CHECK_EQ(61 + b, r.Call(1)); 1117 CHECK_EQ(61 + c, r.Call(2)); 1118 CHECK_EQ(61 + d, r.Call(3)); 1119 CHECK_EQ(61 + d, r.Call(4)); 1120 } 1121 } 1122 } 1123 } 1124 } 1125 1126 1127 TEST(Run_Wasm_TableSwitch4_fallthru) { 1128 byte code[] = { 1129 WASM_TABLESWITCH_OP(4, 4, WASM_CASE(0), WASM_CASE(1), WASM_CASE(2), 1130 WASM_CASE(3)), 1131 WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_INC_LOCAL_BY(1, 1), 1132 WASM_INC_LOCAL_BY(1, 2), WASM_INC_LOCAL_BY(1, 4), 1133 WASM_INC_LOCAL_BY(1, 8)), 1134 WASM_GET_LOCAL(1)}; 1135 1136 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32()); 1137 r.Build(code, code + arraysize(code)); 1138 1139 CHECK_EQ(15, r.Call(0, 0)); 1140 CHECK_EQ(14, r.Call(1, 0)); 1141 CHECK_EQ(12, r.Call(2, 0)); 1142 CHECK_EQ(8, r.Call(3, 0)); 1143 CHECK_EQ(8, r.Call(4, 0)); 1144 1145 CHECK_EQ(115, r.Call(0, 100)); 1146 CHECK_EQ(114, r.Call(1, 100)); 1147 CHECK_EQ(112, r.Call(2, 100)); 1148 CHECK_EQ(108, r.Call(3, 100)); 1149 CHECK_EQ(108, r.Call(4, 100)); 1150 } 1151 1152 1153 TEST(Run_Wasm_TableSwitch4_fallthru_br) { 1154 byte code[] = { 1155 WASM_TABLESWITCH_OP(4, 4, WASM_CASE(0), WASM_CASE(1), WASM_CASE(2), 1156 WASM_CASE(3)), 1157 WASM_TABLESWITCH_BODY(WASM_GET_LOCAL(0), WASM_INC_LOCAL_BY(1, 1), 1158 WASM_BRV(0, WASM_INC_LOCAL_BY(1, 2)), 1159 WASM_INC_LOCAL_BY(1, 4), 1160 WASM_BRV(0, WASM_INC_LOCAL_BY(1, 8))), 1161 WASM_GET_LOCAL(1)}; 1162 1163 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32()); 1164 r.Build(code, code + arraysize(code)); 1165 1166 CHECK_EQ(3, r.Call(0, 0)); 1167 CHECK_EQ(2, r.Call(1, 0)); 1168 CHECK_EQ(12, r.Call(2, 0)); 1169 CHECK_EQ(8, r.Call(3, 0)); 1170 CHECK_EQ(8, r.Call(4, 0)); 1171 1172 CHECK_EQ(203, r.Call(0, 200)); 1173 CHECK_EQ(202, r.Call(1, 200)); 1174 CHECK_EQ(212, r.Call(2, 200)); 1175 CHECK_EQ(208, r.Call(3, 200)); 1176 CHECK_EQ(208, r.Call(4, 200)); 1177 } 1178 1179 1180 TEST(Run_Wasm_F32ReinterpretI32) { 1181 WasmRunner<int32_t> r; 1182 TestingModule module; 1183 int32_t* memory = module.AddMemoryElems<int32_t>(8); 1184 r.env()->module = &module; 1185 1186 BUILD(r, WASM_I32_REINTERPRET_F32( 1187 WASM_LOAD_MEM(MachineType::Float32(), WASM_ZERO))); 1188 1189 FOR_INT32_INPUTS(i) { 1190 int32_t expected = *i; 1191 memory[0] = expected; 1192 CHECK_EQ(expected, r.Call()); 1193 } 1194 } 1195 1196 1197 TEST(Run_Wasm_I32ReinterpretF32) { 1198 WasmRunner<int32_t> r(MachineType::Int32()); 1199 TestingModule module; 1200 int32_t* memory = module.AddMemoryElems<int32_t>(8); 1201 r.env()->module = &module; 1202 1203 BUILD(r, WASM_BLOCK( 1204 2, WASM_STORE_MEM(MachineType::Float32(), WASM_ZERO, 1205 WASM_F32_REINTERPRET_I32(WASM_GET_LOCAL(0))), 1206 WASM_I8(107))); 1207 1208 FOR_INT32_INPUTS(i) { 1209 int32_t expected = *i; 1210 CHECK_EQ(107, r.Call(expected)); 1211 CHECK_EQ(expected, memory[0]); 1212 } 1213 } 1214 1215 1216 TEST(Run_Wasm_ReturnStore) { 1217 WasmRunner<int32_t> r; 1218 TestingModule module; 1219 int32_t* memory = module.AddMemoryElems<int32_t>(8); 1220 r.env()->module = &module; 1221 1222 BUILD(r, WASM_STORE_MEM(MachineType::Int32(), WASM_ZERO, 1223 WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO))); 1224 1225 FOR_INT32_INPUTS(i) { 1226 int32_t expected = *i; 1227 memory[0] = expected; 1228 CHECK_EQ(expected, r.Call()); 1229 } 1230 } 1231 1232 1233 TEST(Run_Wasm_VoidReturn1) { 1234 WasmRunner<void> r; 1235 BUILD(r, kExprNop); 1236 r.Call(); 1237 } 1238 1239 1240 TEST(Run_Wasm_VoidReturn2) { 1241 WasmRunner<void> r; 1242 BUILD(r, WASM_RETURN0); 1243 r.Call(); 1244 } 1245 1246 1247 TEST(Run_Wasm_Block_If_P) { 1248 WasmRunner<int32_t> r(MachineType::Int32()); 1249 // { if (p0) return 51; return 52; } 1250 BUILD(r, WASM_BLOCK(2, // -- 1251 WASM_IF(WASM_GET_LOCAL(0), // -- 1252 WASM_BRV(0, WASM_I8(51))), // -- 1253 WASM_I8(52))); // -- 1254 FOR_INT32_INPUTS(i) { 1255 int32_t expected = *i ? 51 : 52; 1256 CHECK_EQ(expected, r.Call(*i)); 1257 } 1258 } 1259 1260 1261 TEST(Run_Wasm_Block_BrIf_P) { 1262 WasmRunner<int32_t> r(MachineType::Int32()); 1263 BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_I8(51)), 1264 WASM_I8(52))); 1265 FOR_INT32_INPUTS(i) { 1266 int32_t expected = *i ? 51 : 52; 1267 CHECK_EQ(expected, r.Call(*i)); 1268 } 1269 } 1270 1271 1272 TEST(Run_Wasm_Block_IfElse_P_assign) { 1273 WasmRunner<int32_t> r(MachineType::Int32()); 1274 // { if (p0) p0 = 71; else p0 = 72; return p0; } 1275 BUILD(r, WASM_BLOCK(2, // -- 1276 WASM_IF_ELSE(WASM_GET_LOCAL(0), // -- 1277 WASM_SET_LOCAL(0, WASM_I8(71)), // -- 1278 WASM_SET_LOCAL(0, WASM_I8(72))), // -- 1279 WASM_GET_LOCAL(0))); 1280 FOR_INT32_INPUTS(i) { 1281 int32_t expected = *i ? 71 : 72; 1282 CHECK_EQ(expected, r.Call(*i)); 1283 } 1284 } 1285 1286 1287 TEST(Run_Wasm_Block_IfElse_P_return) { 1288 WasmRunner<int32_t> r(MachineType::Int32()); 1289 // if (p0) return 81; else return 82; 1290 BUILD(r, // -- 1291 WASM_IF_ELSE(WASM_GET_LOCAL(0), // -- 1292 WASM_RETURN(WASM_I8(81)), // -- 1293 WASM_RETURN(WASM_I8(82)))); // -- 1294 FOR_INT32_INPUTS(i) { 1295 int32_t expected = *i ? 81 : 82; 1296 CHECK_EQ(expected, r.Call(*i)); 1297 } 1298 } 1299 1300 1301 TEST(Run_Wasm_Block_If_P_assign) { 1302 WasmRunner<int32_t> r(MachineType::Int32()); 1303 // { if (p0) p0 = 61; p0; } 1304 BUILD(r, WASM_BLOCK( 1305 2, WASM_IF(WASM_GET_LOCAL(0), WASM_SET_LOCAL(0, WASM_I8(61))), 1306 WASM_GET_LOCAL(0))); 1307 FOR_INT32_INPUTS(i) { 1308 int32_t expected = *i ? 61 : *i; 1309 CHECK_EQ(expected, r.Call(*i)); 1310 } 1311 } 1312 1313 1314 TEST(Run_Wasm_DanglingAssign) { 1315 WasmRunner<int32_t> r(MachineType::Int32()); 1316 // { return 0; p0 = 0; } 1317 BUILD(r, 1318 WASM_BLOCK(2, WASM_RETURN(WASM_I8(99)), WASM_SET_LOCAL(0, WASM_ZERO))); 1319 CHECK_EQ(99, r.Call(1)); 1320 } 1321 1322 1323 TEST(Run_Wasm_ExprIf_P) { 1324 WasmRunner<int32_t> r(MachineType::Int32()); 1325 // p0 ? 11 : 22; 1326 BUILD(r, WASM_IF_ELSE(WASM_GET_LOCAL(0), // -- 1327 WASM_I8(11), // -- 1328 WASM_I8(22))); // -- 1329 FOR_INT32_INPUTS(i) { 1330 int32_t expected = *i ? 11 : 22; 1331 CHECK_EQ(expected, r.Call(*i)); 1332 } 1333 } 1334 1335 1336 TEST(Run_Wasm_ExprIf_P_fallthru) { 1337 WasmRunner<int32_t> r(MachineType::Int32()); 1338 // p0 ? 11 : 22; 1339 BUILD(r, WASM_IF_ELSE(WASM_GET_LOCAL(0), // -- 1340 WASM_I8(11), // -- 1341 WASM_I8(22))); // -- 1342 FOR_INT32_INPUTS(i) { 1343 int32_t expected = *i ? 11 : 22; 1344 CHECK_EQ(expected, r.Call(*i)); 1345 } 1346 } 1347 1348 1349 TEST(Run_Wasm_CountDown) { 1350 WasmRunner<int32_t> r(MachineType::Int32()); 1351 BUILD(r, 1352 WASM_BLOCK( 1353 2, WASM_LOOP( 1354 1, WASM_IF(WASM_GET_LOCAL(0), 1355 WASM_BRV(0, WASM_SET_LOCAL( 1356 0, WASM_I32_SUB(WASM_GET_LOCAL(0), 1357 WASM_I8(1)))))), 1358 WASM_GET_LOCAL(0))); 1359 CHECK_EQ(0, r.Call(1)); 1360 CHECK_EQ(0, r.Call(10)); 1361 CHECK_EQ(0, r.Call(100)); 1362 } 1363 1364 1365 TEST(Run_Wasm_CountDown_fallthru) { 1366 WasmRunner<int32_t> r(MachineType::Int32()); 1367 BUILD(r, 1368 WASM_BLOCK( 1369 2, WASM_LOOP(3, WASM_IF(WASM_NOT(WASM_GET_LOCAL(0)), WASM_BREAK(0)), 1370 WASM_SET_LOCAL( 1371 0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(1))), 1372 WASM_CONTINUE(0)), 1373 WASM_GET_LOCAL(0))); 1374 CHECK_EQ(0, r.Call(1)); 1375 CHECK_EQ(0, r.Call(10)); 1376 CHECK_EQ(0, r.Call(100)); 1377 } 1378 1379 1380 TEST(Run_Wasm_WhileCountDown) { 1381 WasmRunner<int32_t> r(MachineType::Int32()); 1382 BUILD(r, WASM_BLOCK( 1383 2, WASM_WHILE(WASM_GET_LOCAL(0), 1384 WASM_SET_LOCAL(0, WASM_I32_SUB(WASM_GET_LOCAL(0), 1385 WASM_I8(1)))), 1386 WASM_GET_LOCAL(0))); 1387 CHECK_EQ(0, r.Call(1)); 1388 CHECK_EQ(0, r.Call(10)); 1389 CHECK_EQ(0, r.Call(100)); 1390 } 1391 1392 1393 TEST(Run_Wasm_Loop_if_break1) { 1394 WasmRunner<int32_t> r(MachineType::Int32()); 1395 BUILD(r, WASM_BLOCK(2, WASM_LOOP(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BREAK(0)), 1396 WASM_SET_LOCAL(0, WASM_I8(99))), 1397 WASM_GET_LOCAL(0))); 1398 CHECK_EQ(99, r.Call(0)); 1399 CHECK_EQ(3, r.Call(3)); 1400 CHECK_EQ(10000, r.Call(10000)); 1401 CHECK_EQ(-29, r.Call(-29)); 1402 } 1403 1404 1405 TEST(Run_Wasm_Loop_if_break2) { 1406 WasmRunner<int32_t> r(MachineType::Int32()); 1407 BUILD(r, WASM_BLOCK(2, WASM_LOOP(2, WASM_BR_IF(1, WASM_GET_LOCAL(0)), 1408 WASM_SET_LOCAL(0, WASM_I8(99))), 1409 WASM_GET_LOCAL(0))); 1410 CHECK_EQ(99, r.Call(0)); 1411 CHECK_EQ(3, r.Call(3)); 1412 CHECK_EQ(10000, r.Call(10000)); 1413 CHECK_EQ(-29, r.Call(-29)); 1414 } 1415 1416 1417 TEST(Run_Wasm_Loop_if_break_fallthru) { 1418 WasmRunner<int32_t> r(MachineType::Int32()); 1419 BUILD(r, WASM_BLOCK(1, WASM_LOOP(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BREAK(1)), 1420 WASM_SET_LOCAL(0, WASM_I8(93)))), 1421 WASM_GET_LOCAL(0)); 1422 CHECK_EQ(93, r.Call(0)); 1423 CHECK_EQ(3, r.Call(3)); 1424 CHECK_EQ(10001, r.Call(10001)); 1425 CHECK_EQ(-22, r.Call(-22)); 1426 } 1427 1428 1429 TEST(Run_Wasm_LoadMemI32) { 1430 WasmRunner<int32_t> r(MachineType::Int32()); 1431 TestingModule module; 1432 int32_t* memory = module.AddMemoryElems<int32_t>(8); 1433 module.RandomizeMemory(1111); 1434 r.env()->module = &module; 1435 1436 BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_I8(0))); 1437 1438 memory[0] = 99999999; 1439 CHECK_EQ(99999999, r.Call(0)); 1440 1441 memory[0] = 88888888; 1442 CHECK_EQ(88888888, r.Call(0)); 1443 1444 memory[0] = 77777777; 1445 CHECK_EQ(77777777, r.Call(0)); 1446 } 1447 1448 1449 TEST(Run_Wasm_LoadMemI32_oob) { 1450 WasmRunner<int32_t> r(MachineType::Uint32()); 1451 TestingModule module; 1452 int32_t* memory = module.AddMemoryElems<int32_t>(8); 1453 module.RandomizeMemory(1111); 1454 r.env()->module = &module; 1455 1456 BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(0))); 1457 1458 memory[0] = 88888888; 1459 CHECK_EQ(88888888, r.Call(0u)); 1460 for (uint32_t offset = 29; offset < 40; offset++) { 1461 CHECK_TRAP(r.Call(offset)); 1462 } 1463 1464 for (uint32_t offset = 0x80000000; offset < 0x80000010; offset++) { 1465 CHECK_TRAP(r.Call(offset)); 1466 } 1467 } 1468 1469 1470 TEST(Run_Wasm_LoadMemI32_oob_asm) { 1471 WasmRunner<int32_t> r(MachineType::Uint32()); 1472 TestingModule module; 1473 module.asm_js = true; 1474 int32_t* memory = module.AddMemoryElems<int32_t>(8); 1475 module.RandomizeMemory(1112); 1476 r.env()->module = &module; 1477 1478 BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(0))); 1479 1480 memory[0] = 999999; 1481 CHECK_EQ(999999, r.Call(0u)); 1482 // TODO(titzer): offset 29-31 should also be OOB. 1483 for (uint32_t offset = 32; offset < 40; offset++) { 1484 CHECK_EQ(0, r.Call(offset)); 1485 } 1486 1487 for (uint32_t offset = 0x80000000; offset < 0x80000010; offset++) { 1488 CHECK_EQ(0, r.Call(offset)); 1489 } 1490 } 1491 1492 1493 TEST(Run_Wasm_LoadMem_offset_oob) { 1494 TestingModule module; 1495 module.AddMemoryElems<int32_t>(8); 1496 1497 static const MachineType machineTypes[] = { 1498 MachineType::Int8(), MachineType::Uint8(), MachineType::Int16(), 1499 MachineType::Uint16(), MachineType::Int32(), MachineType::Uint32(), 1500 MachineType::Int64(), MachineType::Uint64(), MachineType::Float32(), 1501 MachineType::Float64()}; 1502 1503 for (size_t m = 0; m < arraysize(machineTypes); m++) { 1504 module.RandomizeMemory(1116 + static_cast<int>(m)); 1505 WasmRunner<int32_t> r(MachineType::Uint32()); 1506 r.env()->module = &module; 1507 uint32_t boundary = 24 - WasmOpcodes::MemSize(machineTypes[m]); 1508 1509 BUILD(r, WASM_LOAD_MEM_OFFSET(machineTypes[m], 8, WASM_GET_LOCAL(0)), 1510 WASM_ZERO); 1511 1512 CHECK_EQ(0, r.Call(boundary)); // in bounds. 1513 1514 for (uint32_t offset = boundary + 1; offset < boundary + 19; offset++) { 1515 CHECK_TRAP(r.Call(offset)); // out of bounds. 1516 } 1517 } 1518 } 1519 1520 1521 TEST(Run_Wasm_LoadMemI32_offset) { 1522 WasmRunner<int32_t> r(MachineType::Int32()); 1523 TestingModule module; 1524 int32_t* memory = module.AddMemoryElems<int32_t>(4); 1525 module.RandomizeMemory(1111); 1526 r.env()->module = &module; 1527 1528 BUILD(r, WASM_LOAD_MEM_OFFSET(MachineType::Int32(), 4, WASM_GET_LOCAL(0))); 1529 1530 memory[0] = 66666666; 1531 memory[1] = 77777777; 1532 memory[2] = 88888888; 1533 memory[3] = 99999999; 1534 CHECK_EQ(77777777, r.Call(0)); 1535 CHECK_EQ(88888888, r.Call(4)); 1536 CHECK_EQ(99999999, r.Call(8)); 1537 1538 memory[0] = 11111111; 1539 memory[1] = 22222222; 1540 memory[2] = 33333333; 1541 memory[3] = 44444444; 1542 CHECK_EQ(22222222, r.Call(0)); 1543 CHECK_EQ(33333333, r.Call(4)); 1544 CHECK_EQ(44444444, r.Call(8)); 1545 } 1546 1547 1548 // TODO(titzer): Fix for mips and re-enable. 1549 #if !V8_TARGET_ARCH_MIPS && !V8_TARGET_ARCH_MIPS64 1550 1551 TEST(Run_Wasm_LoadMemI32_const_oob) { 1552 TestingModule module; 1553 const int kMemSize = 12; 1554 module.AddMemoryElems<byte>(kMemSize); 1555 1556 for (int offset = 0; offset < kMemSize + 5; offset++) { 1557 for (int index = 0; index < kMemSize + 5; index++) { 1558 WasmRunner<int32_t> r; 1559 r.env()->module = &module; 1560 module.RandomizeMemory(); 1561 1562 BUILD(r, 1563 WASM_LOAD_MEM_OFFSET(MachineType::Int32(), offset, WASM_I8(index))); 1564 1565 if ((offset + index) <= (kMemSize - sizeof(int32_t))) { 1566 CHECK_EQ(module.raw_val_at<int32_t>(offset + index), r.Call()); 1567 } else { 1568 CHECK_TRAP(r.Call()); 1569 } 1570 } 1571 } 1572 } 1573 1574 #endif 1575 1576 1577 TEST(Run_Wasm_StoreMemI32_offset) { 1578 WasmRunner<int32_t> r(MachineType::Int32()); 1579 const int32_t kWritten = 0xaabbccdd; 1580 TestingModule module; 1581 int32_t* memory = module.AddMemoryElems<int32_t>(4); 1582 r.env()->module = &module; 1583 1584 BUILD(r, WASM_STORE_MEM_OFFSET(MachineType::Int32(), 4, WASM_GET_LOCAL(0), 1585 WASM_I32(kWritten))); 1586 1587 for (int i = 0; i < 2; i++) { 1588 module.RandomizeMemory(1111); 1589 memory[0] = 66666666; 1590 memory[1] = 77777777; 1591 memory[2] = 88888888; 1592 memory[3] = 99999999; 1593 CHECK_EQ(kWritten, r.Call(i * 4)); 1594 CHECK_EQ(66666666, memory[0]); 1595 CHECK_EQ(i == 0 ? kWritten : 77777777, memory[1]); 1596 CHECK_EQ(i == 1 ? kWritten : 88888888, memory[2]); 1597 CHECK_EQ(i == 2 ? kWritten : 99999999, memory[3]); 1598 } 1599 } 1600 1601 1602 TEST(Run_Wasm_StoreMem_offset_oob) { 1603 TestingModule module; 1604 byte* memory = module.AddMemoryElems<byte>(32); 1605 1606 #if WASM_64 1607 static const MachineType machineTypes[] = { 1608 MachineType::Int8(), MachineType::Uint8(), MachineType::Int16(), 1609 MachineType::Uint16(), MachineType::Int32(), MachineType::Uint32(), 1610 MachineType::Int64(), MachineType::Uint64(), MachineType::Float32(), 1611 MachineType::Float64()}; 1612 #else 1613 static const MachineType machineTypes[] = { 1614 MachineType::Int8(), MachineType::Uint8(), MachineType::Int16(), 1615 MachineType::Uint16(), MachineType::Int32(), MachineType::Uint32(), 1616 MachineType::Float32(), MachineType::Float64()}; 1617 #endif 1618 1619 for (size_t m = 0; m < arraysize(machineTypes); m++) { 1620 module.RandomizeMemory(1119 + static_cast<int>(m)); 1621 WasmRunner<int32_t> r(MachineType::Uint32()); 1622 r.env()->module = &module; 1623 1624 BUILD(r, WASM_STORE_MEM_OFFSET(machineTypes[m], 8, WASM_GET_LOCAL(0), 1625 WASM_LOAD_MEM(machineTypes[m], WASM_ZERO)), 1626 WASM_ZERO); 1627 1628 byte memsize = WasmOpcodes::MemSize(machineTypes[m]); 1629 uint32_t boundary = 24 - memsize; 1630 CHECK_EQ(0, r.Call(boundary)); // in bounds. 1631 CHECK_EQ(0, memcmp(&memory[0], &memory[8 + boundary], memsize)); 1632 1633 for (uint32_t offset = boundary + 1; offset < boundary + 19; offset++) { 1634 CHECK_TRAP(r.Call(offset)); // out of bounds. 1635 } 1636 } 1637 } 1638 1639 1640 #if WASM_64 1641 TEST(Run_Wasm_F64ReinterpretI64) { 1642 WasmRunner<int64_t> r; 1643 TestingModule module; 1644 int64_t* memory = module.AddMemoryElems<int64_t>(8); 1645 r.env()->module = &module; 1646 1647 BUILD(r, WASM_I64_REINTERPRET_F64( 1648 WASM_LOAD_MEM(MachineType::Float64(), WASM_ZERO))); 1649 1650 FOR_INT32_INPUTS(i) { 1651 int64_t expected = static_cast<int64_t>(*i) * 0x300010001; 1652 memory[0] = expected; 1653 CHECK_EQ(expected, r.Call()); 1654 } 1655 } 1656 1657 1658 TEST(Run_Wasm_I64ReinterpretF64) { 1659 WasmRunner<int64_t> r(MachineType::Int64()); 1660 TestingModule module; 1661 int64_t* memory = module.AddMemoryElems<int64_t>(8); 1662 r.env()->module = &module; 1663 1664 BUILD(r, WASM_BLOCK( 1665 2, WASM_STORE_MEM(MachineType::Float64(), WASM_ZERO, 1666 WASM_F64_REINTERPRET_I64(WASM_GET_LOCAL(0))), 1667 WASM_GET_LOCAL(0))); 1668 1669 FOR_INT32_INPUTS(i) { 1670 int64_t expected = static_cast<int64_t>(*i) * 0x300010001; 1671 CHECK_EQ(expected, r.Call(expected)); 1672 CHECK_EQ(expected, memory[0]); 1673 } 1674 } 1675 1676 1677 TEST(Run_Wasm_LoadMemI64) { 1678 WasmRunner<int64_t> r; 1679 TestingModule module; 1680 int64_t* memory = module.AddMemoryElems<int64_t>(8); 1681 module.RandomizeMemory(1111); 1682 r.env()->module = &module; 1683 1684 BUILD(r, WASM_LOAD_MEM(MachineType::Int64(), WASM_I8(0))); 1685 1686 memory[0] = 0xaabbccdd00112233LL; 1687 CHECK_EQ(0xaabbccdd00112233LL, r.Call()); 1688 1689 memory[0] = 0x33aabbccdd001122LL; 1690 CHECK_EQ(0x33aabbccdd001122LL, r.Call()); 1691 1692 memory[0] = 77777777; 1693 CHECK_EQ(77777777, r.Call()); 1694 } 1695 #endif 1696 1697 1698 TEST(Run_Wasm_LoadMemI32_P) { 1699 const int kNumElems = 8; 1700 WasmRunner<int32_t> r(MachineType::Int32()); 1701 TestingModule module; 1702 int32_t* memory = module.AddMemoryElems<int32_t>(kNumElems); 1703 module.RandomizeMemory(2222); 1704 r.env()->module = &module; 1705 1706 BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(0))); 1707 1708 for (int i = 0; i < kNumElems; i++) { 1709 CHECK_EQ(memory[i], r.Call(i * 4)); 1710 } 1711 } 1712 1713 1714 TEST(Run_Wasm_MemI32_Sum) { 1715 WasmRunner<uint32_t> r(MachineType::Int32()); 1716 const int kNumElems = 20; 1717 const byte kSum = r.AllocateLocal(kAstI32); 1718 TestingModule module; 1719 uint32_t* memory = module.AddMemoryElems<uint32_t>(kNumElems); 1720 r.env()->module = &module; 1721 1722 BUILD(r, WASM_BLOCK( 1723 2, WASM_WHILE( 1724 WASM_GET_LOCAL(0), 1725 WASM_BLOCK( 1726 2, WASM_SET_LOCAL( 1727 kSum, WASM_I32_ADD( 1728 WASM_GET_LOCAL(kSum), 1729 WASM_LOAD_MEM(MachineType::Int32(), 1730 WASM_GET_LOCAL(0)))), 1731 WASM_SET_LOCAL( 1732 0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(4))))), 1733 WASM_GET_LOCAL(1))); 1734 1735 // Run 4 trials. 1736 for (int i = 0; i < 3; i++) { 1737 module.RandomizeMemory(i * 33); 1738 uint32_t expected = 0; 1739 for (size_t j = kNumElems - 1; j > 0; j--) { 1740 expected += memory[j]; 1741 } 1742 uint32_t result = r.Call(static_cast<int>(4 * (kNumElems - 1))); 1743 CHECK_EQ(expected, result); 1744 } 1745 } 1746 1747 1748 TEST(Run_Wasm_CheckMachIntsZero) { 1749 WasmRunner<uint32_t> r(MachineType::Int32()); 1750 const int kNumElems = 55; 1751 TestingModule module; 1752 module.AddMemoryElems<uint32_t>(kNumElems); 1753 r.env()->module = &module; 1754 1755 BUILD(r, kExprBlock, 2, kExprLoop, 1, kExprIf, kExprGetLocal, 0, kExprBr, 0, 1756 kExprIfElse, kExprI32LoadMem, 0, kExprGetLocal, 0, kExprBr, 2, 1757 kExprI8Const, 255, kExprSetLocal, 0, kExprI32Sub, kExprGetLocal, 0, 1758 kExprI8Const, 4, kExprI8Const, 0); 1759 1760 module.BlankMemory(); 1761 CHECK_EQ(0, r.Call((kNumElems - 1) * 4)); 1762 } 1763 1764 1765 TEST(Run_Wasm_MemF32_Sum) { 1766 WasmRunner<int32_t> r(MachineType::Int32()); 1767 const byte kSum = r.AllocateLocal(kAstF32); 1768 const int kSize = 5; 1769 TestingModule module; 1770 module.AddMemoryElems<float>(kSize); 1771 float* buffer = module.raw_mem_start<float>(); 1772 buffer[0] = -99.25; 1773 buffer[1] = -888.25; 1774 buffer[2] = -77.25; 1775 buffer[3] = 66666.25; 1776 buffer[4] = 5555.25; 1777 r.env()->module = &module; 1778 1779 BUILD(r, WASM_BLOCK( 1780 3, WASM_WHILE( 1781 WASM_GET_LOCAL(0), 1782 WASM_BLOCK( 1783 2, WASM_SET_LOCAL( 1784 kSum, WASM_F32_ADD( 1785 WASM_GET_LOCAL(kSum), 1786 WASM_LOAD_MEM(MachineType::Float32(), 1787 WASM_GET_LOCAL(0)))), 1788 WASM_SET_LOCAL( 1789 0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(4))))), 1790 WASM_STORE_MEM(MachineType::Float32(), WASM_ZERO, 1791 WASM_GET_LOCAL(kSum)), 1792 WASM_GET_LOCAL(0))); 1793 1794 CHECK_EQ(0, r.Call(4 * (kSize - 1))); 1795 CHECK_NE(-99.25, buffer[0]); 1796 CHECK_EQ(71256.0f, buffer[0]); 1797 } 1798 1799 1800 #if WASM_64 1801 TEST(Run_Wasm_MemI64_Sum) { 1802 WasmRunner<uint64_t> r(MachineType::Int32()); 1803 const int kNumElems = 20; 1804 const byte kSum = r.AllocateLocal(kAstI64); 1805 TestingModule module; 1806 uint64_t* memory = module.AddMemoryElems<uint64_t>(kNumElems); 1807 r.env()->module = &module; 1808 1809 BUILD(r, WASM_BLOCK( 1810 2, WASM_WHILE( 1811 WASM_GET_LOCAL(0), 1812 WASM_BLOCK( 1813 2, WASM_SET_LOCAL( 1814 kSum, WASM_I64_ADD( 1815 WASM_GET_LOCAL(kSum), 1816 WASM_LOAD_MEM(MachineType::Int64(), 1817 WASM_GET_LOCAL(0)))), 1818 WASM_SET_LOCAL( 1819 0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(8))))), 1820 WASM_GET_LOCAL(1))); 1821 1822 // Run 4 trials. 1823 for (int i = 0; i < 3; i++) { 1824 module.RandomizeMemory(i * 33); 1825 uint64_t expected = 0; 1826 for (size_t j = kNumElems - 1; j > 0; j--) { 1827 expected += memory[j]; 1828 } 1829 uint64_t result = r.Call(8 * (kNumElems - 1)); 1830 CHECK_EQ(expected, result); 1831 } 1832 } 1833 #endif 1834 1835 1836 template <typename T> 1837 T GenerateAndRunFold(WasmOpcode binop, T* buffer, size_t size, 1838 LocalType astType, MachineType memType) { 1839 WasmRunner<int32_t> r(MachineType::Int32()); 1840 const byte kAccum = r.AllocateLocal(astType); 1841 TestingModule module; 1842 module.AddMemoryElems<T>(size); 1843 for (size_t i = 0; i < size; i++) { 1844 module.raw_mem_start<T>()[i] = buffer[i]; 1845 } 1846 r.env()->module = &module; 1847 1848 BUILD( 1849 r, 1850 WASM_BLOCK( 1851 4, WASM_SET_LOCAL(kAccum, WASM_LOAD_MEM(memType, WASM_ZERO)), 1852 WASM_WHILE( 1853 WASM_GET_LOCAL(0), 1854 WASM_BLOCK( 1855 2, WASM_SET_LOCAL( 1856 kAccum, 1857 WASM_BINOP(binop, WASM_GET_LOCAL(kAccum), 1858 WASM_LOAD_MEM(memType, WASM_GET_LOCAL(0)))), 1859 WASM_SET_LOCAL( 1860 0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(sizeof(T)))))), 1861 WASM_STORE_MEM(memType, WASM_ZERO, WASM_GET_LOCAL(kAccum)), 1862 WASM_GET_LOCAL(0))); 1863 r.Call(static_cast<int>(sizeof(T) * (size - 1))); 1864 return module.raw_mem_at<double>(0); 1865 } 1866 1867 1868 TEST(Run_Wasm_MemF64_Mul) { 1869 const size_t kSize = 6; 1870 double buffer[kSize] = {1, 2, 2, 2, 2, 2}; 1871 double result = GenerateAndRunFold<double>(kExprF64Mul, buffer, kSize, 1872 kAstF64, MachineType::Float64()); 1873 CHECK_EQ(32, result); 1874 } 1875 1876 1877 TEST(Build_Wasm_Infinite_Loop) { 1878 WasmRunner<int32_t> r(MachineType::Int32()); 1879 // Only build the graph and compile, don't run. 1880 BUILD(r, WASM_INFINITE_LOOP); 1881 } 1882 1883 1884 TEST(Build_Wasm_Infinite_Loop_effect) { 1885 WasmRunner<int32_t> r(MachineType::Int32()); 1886 TestingModule module; 1887 module.AddMemoryElems<int8_t>(16); 1888 r.env()->module = &module; 1889 1890 // Only build the graph and compile, don't run. 1891 BUILD(r, WASM_LOOP(1, WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO))); 1892 } 1893 1894 1895 TEST(Run_Wasm_Unreachable0a) { 1896 WasmRunner<int32_t> r(MachineType::Int32()); 1897 BUILD(r, 1898 WASM_BLOCK(2, WASM_BRV(0, WASM_I8(9)), WASM_RETURN(WASM_GET_LOCAL(0)))); 1899 CHECK_EQ(9, r.Call(0)); 1900 CHECK_EQ(9, r.Call(1)); 1901 } 1902 1903 1904 TEST(Run_Wasm_Unreachable0b) { 1905 WasmRunner<int32_t> r(MachineType::Int32()); 1906 BUILD(r, WASM_BLOCK(2, WASM_BRV(0, WASM_I8(7)), WASM_UNREACHABLE)); 1907 CHECK_EQ(7, r.Call(0)); 1908 CHECK_EQ(7, r.Call(1)); 1909 } 1910 1911 1912 TEST(Build_Wasm_Unreachable1) { 1913 WasmRunner<int32_t> r(MachineType::Int32()); 1914 BUILD(r, WASM_UNREACHABLE); 1915 } 1916 1917 1918 TEST(Build_Wasm_Unreachable2) { 1919 WasmRunner<int32_t> r(MachineType::Int32()); 1920 BUILD(r, WASM_UNREACHABLE, WASM_UNREACHABLE); 1921 } 1922 1923 1924 TEST(Build_Wasm_Unreachable3) { 1925 WasmRunner<int32_t> r(MachineType::Int32()); 1926 BUILD(r, WASM_UNREACHABLE, WASM_UNREACHABLE, WASM_UNREACHABLE); 1927 } 1928 1929 1930 TEST(Build_Wasm_UnreachableIf1) { 1931 WasmRunner<int32_t> r(MachineType::Int32()); 1932 BUILD(r, WASM_UNREACHABLE, WASM_IF(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0))); 1933 } 1934 1935 1936 TEST(Build_Wasm_UnreachableIf2) { 1937 WasmRunner<int32_t> r(MachineType::Int32()); 1938 BUILD(r, WASM_UNREACHABLE, 1939 WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0), WASM_UNREACHABLE)); 1940 } 1941 1942 1943 TEST(Run_Wasm_Unreachable_Load) { 1944 WasmRunner<int32_t> r(MachineType::Int32()); 1945 BUILD(r, WASM_BLOCK(2, WASM_BRV(0, WASM_GET_LOCAL(0)), 1946 WASM_LOAD_MEM(MachineType::Int8(), WASM_GET_LOCAL(0)))); 1947 CHECK_EQ(11, r.Call(11)); 1948 CHECK_EQ(21, r.Call(21)); 1949 } 1950 1951 1952 TEST(Run_Wasm_Infinite_Loop_not_taken1) { 1953 WasmRunner<int32_t> r(MachineType::Int32()); 1954 BUILD(r, WASM_BLOCK(2, WASM_IF(WASM_GET_LOCAL(0), WASM_INFINITE_LOOP), 1955 WASM_I8(45))); 1956 // Run the code, but don't go into the infinite loop. 1957 CHECK_EQ(45, r.Call(0)); 1958 } 1959 1960 1961 TEST(Run_Wasm_Infinite_Loop_not_taken2) { 1962 WasmRunner<int32_t> r(MachineType::Int32()); 1963 BUILD(r, 1964 WASM_BLOCK(1, WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(45)), 1965 WASM_INFINITE_LOOP))); 1966 // Run the code, but don't go into the infinite loop. 1967 CHECK_EQ(45, r.Call(1)); 1968 } 1969 1970 1971 TEST(Run_Wasm_Infinite_Loop_not_taken2_brif) { 1972 WasmRunner<int32_t> r(MachineType::Int32()); 1973 BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_I8(45)), 1974 WASM_INFINITE_LOOP)); 1975 // Run the code, but don't go into the infinite loop. 1976 CHECK_EQ(45, r.Call(1)); 1977 } 1978 1979 1980 static void TestBuildGraphForSimpleExpression(WasmOpcode opcode) { 1981 if (!WasmOpcodes::IsSupported(opcode)) return; 1982 1983 Zone zone; 1984 Isolate* isolate = CcTest::InitIsolateOnce(); 1985 HandleScope scope(isolate); 1986 // Enable all optional operators. 1987 CommonOperatorBuilder common(&zone); 1988 MachineOperatorBuilder machine(&zone, MachineType::PointerRepresentation(), 1989 MachineOperatorBuilder::kAllOptionalOps); 1990 Graph graph(&zone); 1991 JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine); 1992 FunctionEnv env; 1993 FunctionSig* sig = WasmOpcodes::Signature(opcode); 1994 init_env(&env, sig); 1995 1996 if (sig->parameter_count() == 1) { 1997 byte code[] = {static_cast<byte>(opcode), kExprGetLocal, 0}; 1998 TestBuildingGraph(&zone, &jsgraph, &env, code, code + arraysize(code)); 1999 } else { 2000 CHECK_EQ(2, sig->parameter_count()); 2001 byte code[] = {static_cast<byte>(opcode), kExprGetLocal, 0, kExprGetLocal, 2002 1}; 2003 TestBuildingGraph(&zone, &jsgraph, &env, code, code + arraysize(code)); 2004 } 2005 } 2006 2007 2008 TEST(Build_Wasm_SimpleExprs) { 2009 // Test that the decoder can build a graph for all supported simple expressions. 2010 #define GRAPH_BUILD_TEST(name, opcode, sig) \ 2011 TestBuildGraphForSimpleExpression(kExpr##name); 2012 2013 FOREACH_SIMPLE_OPCODE(GRAPH_BUILD_TEST); 2014 2015 #undef GRAPH_BUILD_TEST 2016 } 2017 2018 2019 TEST(Run_Wasm_Int32LoadInt8_signext) { 2020 TestingModule module; 2021 const int kNumElems = 16; 2022 int8_t* memory = module.AddMemoryElems<int8_t>(kNumElems); 2023 module.RandomizeMemory(); 2024 memory[0] = -1; 2025 WasmRunner<int32_t> r(MachineType::Int32()); 2026 r.env()->module = &module; 2027 BUILD(r, WASM_LOAD_MEM(MachineType::Int8(), WASM_GET_LOCAL(0))); 2028 2029 for (size_t i = 0; i < kNumElems; i++) { 2030 CHECK_EQ(memory[i], r.Call(static_cast<int>(i))); 2031 } 2032 } 2033 2034 2035 TEST(Run_Wasm_Int32LoadInt8_zeroext) { 2036 TestingModule module; 2037 const int kNumElems = 16; 2038 byte* memory = module.AddMemory(kNumElems); 2039 module.RandomizeMemory(77); 2040 memory[0] = 255; 2041 WasmRunner<int32_t> r(MachineType::Int32()); 2042 r.env()->module = &module; 2043 BUILD(r, WASM_LOAD_MEM(MachineType::Uint8(), WASM_GET_LOCAL(0))); 2044 2045 for (size_t i = 0; i < kNumElems; i++) { 2046 CHECK_EQ(memory[i], r.Call(static_cast<int>(i))); 2047 } 2048 } 2049 2050 2051 TEST(Run_Wasm_Int32LoadInt16_signext) { 2052 TestingModule module; 2053 const int kNumBytes = 16; 2054 byte* memory = module.AddMemory(kNumBytes); 2055 module.RandomizeMemory(888); 2056 memory[1] = 200; 2057 WasmRunner<int32_t> r(MachineType::Int32()); 2058 r.env()->module = &module; 2059 BUILD(r, WASM_LOAD_MEM(MachineType::Int16(), WASM_GET_LOCAL(0))); 2060 2061 for (size_t i = 0; i < kNumBytes; i += 2) { 2062 int32_t expected = memory[i] | (static_cast<int8_t>(memory[i + 1]) << 8); 2063 CHECK_EQ(expected, r.Call(static_cast<int>(i))); 2064 } 2065 } 2066 2067 2068 TEST(Run_Wasm_Int32LoadInt16_zeroext) { 2069 TestingModule module; 2070 const int kNumBytes = 16; 2071 byte* memory = module.AddMemory(kNumBytes); 2072 module.RandomizeMemory(9999); 2073 memory[1] = 204; 2074 WasmRunner<int32_t> r(MachineType::Int32()); 2075 r.env()->module = &module; 2076 BUILD(r, WASM_LOAD_MEM(MachineType::Uint16(), WASM_GET_LOCAL(0))); 2077 2078 for (size_t i = 0; i < kNumBytes; i += 2) { 2079 int32_t expected = memory[i] | (memory[i + 1] << 8); 2080 CHECK_EQ(expected, r.Call(static_cast<int>(i))); 2081 } 2082 } 2083 2084 2085 TEST(Run_WasmInt32Global) { 2086 TestingModule module; 2087 int32_t* global = module.AddGlobal<int32_t>(MachineType::Int32()); 2088 WasmRunner<int32_t> r(MachineType::Int32()); 2089 r.env()->module = &module; 2090 // global = global + p0 2091 BUILD(r, WASM_STORE_GLOBAL( 2092 0, WASM_I32_ADD(WASM_LOAD_GLOBAL(0), WASM_GET_LOCAL(0)))); 2093 2094 *global = 116; 2095 for (int i = 9; i < 444444; i += 111111) { 2096 int32_t expected = *global + i; 2097 r.Call(i); 2098 CHECK_EQ(expected, *global); 2099 } 2100 } 2101 2102 2103 TEST(Run_WasmInt32Globals_DontAlias) { 2104 const int kNumGlobals = 3; 2105 TestingModule module; 2106 int32_t* globals[] = {module.AddGlobal<int32_t>(MachineType::Int32()), 2107 module.AddGlobal<int32_t>(MachineType::Int32()), 2108 module.AddGlobal<int32_t>(MachineType::Int32())}; 2109 2110 for (int g = 0; g < kNumGlobals; g++) { 2111 // global = global + p0 2112 WasmRunner<int32_t> r(MachineType::Int32()); 2113 r.env()->module = &module; 2114 BUILD(r, WASM_STORE_GLOBAL( 2115 g, WASM_I32_ADD(WASM_LOAD_GLOBAL(g), WASM_GET_LOCAL(0)))); 2116 2117 // Check that reading/writing global number {g} doesn't alter the others. 2118 *globals[g] = 116 * g; 2119 int32_t before[kNumGlobals]; 2120 for (int i = 9; i < 444444; i += 111113) { 2121 int32_t sum = *globals[g] + i; 2122 for (int j = 0; j < kNumGlobals; j++) before[j] = *globals[j]; 2123 r.Call(i); 2124 for (int j = 0; j < kNumGlobals; j++) { 2125 int32_t expected = j == g ? sum : before[j]; 2126 CHECK_EQ(expected, *globals[j]); 2127 } 2128 } 2129 } 2130 } 2131 2132 2133 #if WASM_64 2134 TEST(Run_WasmInt64Global) { 2135 TestingModule module; 2136 int64_t* global = module.AddGlobal<int64_t>(MachineType::Int64()); 2137 WasmRunner<int32_t> r(MachineType::Int32()); 2138 r.env()->module = &module; 2139 // global = global + p0 2140 BUILD(r, WASM_BLOCK(2, WASM_STORE_GLOBAL( 2141 0, WASM_I64_ADD( 2142 WASM_LOAD_GLOBAL(0), 2143 WASM_I64_SCONVERT_I32(WASM_GET_LOCAL(0)))), 2144 WASM_ZERO)); 2145 2146 *global = 0xFFFFFFFFFFFFFFFFLL; 2147 for (int i = 9; i < 444444; i += 111111) { 2148 int64_t expected = *global + i; 2149 r.Call(i); 2150 CHECK_EQ(expected, *global); 2151 } 2152 } 2153 #endif 2154 2155 2156 TEST(Run_WasmFloat32Global) { 2157 TestingModule module; 2158 float* global = module.AddGlobal<float>(MachineType::Float32()); 2159 WasmRunner<int32_t> r(MachineType::Int32()); 2160 r.env()->module = &module; 2161 // global = global + p0 2162 BUILD(r, WASM_BLOCK(2, WASM_STORE_GLOBAL( 2163 0, WASM_F32_ADD( 2164 WASM_LOAD_GLOBAL(0), 2165 WASM_F32_SCONVERT_I32(WASM_GET_LOCAL(0)))), 2166 WASM_ZERO)); 2167 2168 *global = 1.25; 2169 for (int i = 9; i < 4444; i += 1111) { 2170 volatile float expected = *global + i; 2171 r.Call(i); 2172 CHECK_EQ(expected, *global); 2173 } 2174 } 2175 2176 2177 TEST(Run_WasmFloat64Global) { 2178 TestingModule module; 2179 double* global = module.AddGlobal<double>(MachineType::Float64()); 2180 WasmRunner<int32_t> r(MachineType::Int32()); 2181 r.env()->module = &module; 2182 // global = global + p0 2183 BUILD(r, WASM_BLOCK(2, WASM_STORE_GLOBAL( 2184 0, WASM_F64_ADD( 2185 WASM_LOAD_GLOBAL(0), 2186 WASM_F64_SCONVERT_I32(WASM_GET_LOCAL(0)))), 2187 WASM_ZERO)); 2188 2189 *global = 1.25; 2190 for (int i = 9; i < 4444; i += 1111) { 2191 volatile double expected = *global + i; 2192 r.Call(i); 2193 CHECK_EQ(expected, *global); 2194 } 2195 } 2196 2197 2198 TEST(Run_WasmMixedGlobals) { 2199 TestingModule module; 2200 int32_t* unused = module.AddGlobal<int32_t>(MachineType::Int32()); 2201 byte* memory = module.AddMemory(32); 2202 2203 int8_t* var_int8 = module.AddGlobal<int8_t>(MachineType::Int8()); 2204 uint8_t* var_uint8 = module.AddGlobal<uint8_t>(MachineType::Uint8()); 2205 int16_t* var_int16 = module.AddGlobal<int16_t>(MachineType::Int16()); 2206 uint16_t* var_uint16 = module.AddGlobal<uint16_t>(MachineType::Uint16()); 2207 int32_t* var_int32 = module.AddGlobal<int32_t>(MachineType::Int32()); 2208 uint32_t* var_uint32 = module.AddGlobal<uint32_t>(MachineType::Uint32()); 2209 float* var_float = module.AddGlobal<float>(MachineType::Float32()); 2210 double* var_double = module.AddGlobal<double>(MachineType::Float64()); 2211 2212 WasmRunner<int32_t> r(MachineType::Int32()); 2213 r.env()->module = &module; 2214 2215 BUILD( 2216 r, 2217 WASM_BLOCK( 2218 9, 2219 WASM_STORE_GLOBAL(1, WASM_LOAD_MEM(MachineType::Int8(), WASM_ZERO)), 2220 WASM_STORE_GLOBAL(2, WASM_LOAD_MEM(MachineType::Uint8(), WASM_ZERO)), 2221 WASM_STORE_GLOBAL(3, WASM_LOAD_MEM(MachineType::Int16(), WASM_ZERO)), 2222 WASM_STORE_GLOBAL(4, WASM_LOAD_MEM(MachineType::Uint16(), WASM_ZERO)), 2223 WASM_STORE_GLOBAL(5, WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO)), 2224 WASM_STORE_GLOBAL(6, WASM_LOAD_MEM(MachineType::Uint32(), WASM_ZERO)), 2225 WASM_STORE_GLOBAL(7, 2226 WASM_LOAD_MEM(MachineType::Float32(), WASM_ZERO)), 2227 WASM_STORE_GLOBAL(8, 2228 WASM_LOAD_MEM(MachineType::Float64(), WASM_ZERO)), 2229 WASM_ZERO)); 2230 2231 memory[0] = 0xaa; 2232 memory[1] = 0xcc; 2233 memory[2] = 0x55; 2234 memory[3] = 0xee; 2235 memory[4] = 0x33; 2236 memory[5] = 0x22; 2237 memory[6] = 0x11; 2238 memory[7] = 0x99; 2239 r.Call(1); 2240 2241 CHECK(static_cast<int8_t>(0xaa) == *var_int8); 2242 CHECK(static_cast<uint8_t>(0xaa) == *var_uint8); 2243 CHECK(static_cast<int16_t>(0xccaa) == *var_int16); 2244 CHECK(static_cast<uint16_t>(0xccaa) == *var_uint16); 2245 CHECK(static_cast<int32_t>(0xee55ccaa) == *var_int32); 2246 CHECK(static_cast<uint32_t>(0xee55ccaa) == *var_uint32); 2247 CHECK(bit_cast<float>(0xee55ccaa) == *var_float); 2248 CHECK(bit_cast<double>(0x99112233ee55ccaaULL) == *var_double); 2249 2250 USE(unused); 2251 } 2252 2253 2254 #if WASM_64 2255 // Test the WasmRunner with an Int64 return value and different numbers of 2256 // Int64 parameters. 2257 TEST(Run_TestI64WasmRunner) { 2258 { 2259 FOR_INT64_INPUTS(i) { 2260 WasmRunner<int64_t> r; 2261 BUILD(r, WASM_I64(*i)); 2262 CHECK_EQ(*i, r.Call()); 2263 } 2264 } 2265 { 2266 WasmRunner<int64_t> r(MachineType::Int64()); 2267 BUILD(r, WASM_GET_LOCAL(0)); 2268 FOR_INT64_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); } 2269 } 2270 { 2271 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); 2272 BUILD(r, WASM_I64_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 2273 FOR_INT64_INPUTS(i) { 2274 FOR_INT64_INPUTS(j) { CHECK_EQ(*i + *j, r.Call(*i, *j)); } 2275 } 2276 } 2277 { 2278 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64(), 2279 MachineType::Int64()); 2280 BUILD(r, WASM_I64_ADD(WASM_GET_LOCAL(0), 2281 WASM_I64_ADD(WASM_GET_LOCAL(1), WASM_GET_LOCAL(2)))); 2282 FOR_INT64_INPUTS(i) { 2283 FOR_INT64_INPUTS(j) { 2284 CHECK_EQ(*i + *j + *j, r.Call(*i, *j, *j)); 2285 CHECK_EQ(*j + *i + *j, r.Call(*j, *i, *j)); 2286 CHECK_EQ(*j + *j + *i, r.Call(*j, *j, *i)); 2287 } 2288 } 2289 } 2290 { 2291 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64(), 2292 MachineType::Int64(), MachineType::Int64()); 2293 BUILD(r, WASM_I64_ADD(WASM_GET_LOCAL(0), 2294 WASM_I64_ADD(WASM_GET_LOCAL(1), 2295 WASM_I64_ADD(WASM_GET_LOCAL(2), 2296 WASM_GET_LOCAL(3))))); 2297 FOR_INT64_INPUTS(i) { 2298 FOR_INT64_INPUTS(j) { 2299 CHECK_EQ(*i + *j + *j + *j, r.Call(*i, *j, *j, *j)); 2300 CHECK_EQ(*j + *i + *j + *j, r.Call(*j, *i, *j, *j)); 2301 CHECK_EQ(*j + *j + *i + *j, r.Call(*j, *j, *i, *j)); 2302 CHECK_EQ(*j + *j + *j + *i, r.Call(*j, *j, *j, *i)); 2303 } 2304 } 2305 } 2306 } 2307 #endif 2308 2309 2310 TEST(Run_WasmCallEmpty) { 2311 const int32_t kExpected = -414444; 2312 // Build the target function. 2313 TestSignatures sigs; 2314 TestingModule module; 2315 WasmFunctionCompiler t(sigs.i_v()); 2316 BUILD(t, WASM_I32(kExpected)); 2317 uint32_t index = t.CompileAndAdd(&module); 2318 2319 // Build the calling function. 2320 WasmRunner<int32_t> r; 2321 r.env()->module = &module; 2322 BUILD(r, WASM_CALL_FUNCTION0(index)); 2323 2324 int32_t result = r.Call(); 2325 CHECK_EQ(kExpected, result); 2326 } 2327 2328 2329 // TODO(tizer): Fix on arm and reenable. 2330 #if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64 2331 2332 TEST(Run_WasmCallF32StackParameter) { 2333 // Build the target function. 2334 LocalType param_types[20]; 2335 for (int i = 0; i < 20; i++) param_types[i] = kAstF32; 2336 FunctionSig sig(1, 19, param_types); 2337 TestingModule module; 2338 WasmFunctionCompiler t(&sig); 2339 BUILD(t, WASM_GET_LOCAL(17)); 2340 uint32_t index = t.CompileAndAdd(&module); 2341 2342 // Build the calling function. 2343 WasmRunner<float> r; 2344 r.env()->module = &module; 2345 BUILD(r, WASM_CALL_FUNCTION( 2346 index, WASM_F32(1.0f), WASM_F32(2.0f), WASM_F32(4.0f), 2347 WASM_F32(8.0f), WASM_F32(16.0f), WASM_F32(32.0f), 2348 WASM_F32(64.0f), WASM_F32(128.0f), WASM_F32(256.0f), 2349 WASM_F32(1.5f), WASM_F32(2.5f), WASM_F32(4.5f), WASM_F32(8.5f), 2350 WASM_F32(16.5f), WASM_F32(32.5f), WASM_F32(64.5f), 2351 WASM_F32(128.5f), WASM_F32(256.5f), WASM_F32(512.5f))); 2352 2353 float result = r.Call(); 2354 CHECK_EQ(256.5f, result); 2355 } 2356 2357 2358 TEST(Run_WasmCallF64StackParameter) { 2359 // Build the target function. 2360 LocalType param_types[20]; 2361 for (int i = 0; i < 20; i++) param_types[i] = kAstF64; 2362 FunctionSig sig(1, 19, param_types); 2363 TestingModule module; 2364 WasmFunctionCompiler t(&sig); 2365 BUILD(t, WASM_GET_LOCAL(17)); 2366 uint32_t index = t.CompileAndAdd(&module); 2367 2368 // Build the calling function. 2369 WasmRunner<double> r; 2370 r.env()->module = &module; 2371 BUILD(r, WASM_CALL_FUNCTION(index, WASM_F64(1.0), WASM_F64(2.0), 2372 WASM_F64(4.0), WASM_F64(8.0), WASM_F64(16.0), 2373 WASM_F64(32.0), WASM_F64(64.0), WASM_F64(128.0), 2374 WASM_F64(256.0), WASM_F64(1.5), WASM_F64(2.5), 2375 WASM_F64(4.5), WASM_F64(8.5), WASM_F64(16.5), 2376 WASM_F64(32.5), WASM_F64(64.5), WASM_F64(128.5), 2377 WASM_F64(256.5), WASM_F64(512.5))); 2378 2379 float result = r.Call(); 2380 CHECK_EQ(256.5, result); 2381 } 2382 2383 #endif 2384 2385 2386 TEST(Run_WasmCallVoid) { 2387 const byte kMemOffset = 8; 2388 const int32_t kElemNum = kMemOffset / sizeof(int32_t); 2389 const int32_t kExpected = -414444; 2390 // Build the target function. 2391 TestSignatures sigs; 2392 TestingModule module; 2393 module.AddMemory(16); 2394 module.RandomizeMemory(); 2395 WasmFunctionCompiler t(sigs.v_v()); 2396 t.env.module = &module; 2397 BUILD(t, WASM_STORE_MEM(MachineType::Int32(), WASM_I8(kMemOffset), 2398 WASM_I32(kExpected))); 2399 uint32_t index = t.CompileAndAdd(&module); 2400 2401 // Build the calling function. 2402 WasmRunner<int32_t> r; 2403 r.env()->module = &module; 2404 BUILD(r, WASM_CALL_FUNCTION0(index), 2405 WASM_LOAD_MEM(MachineType::Int32(), WASM_I8(kMemOffset))); 2406 2407 int32_t result = r.Call(); 2408 CHECK_EQ(kExpected, result); 2409 CHECK_EQ(kExpected, module.raw_mem_start<int32_t>()[kElemNum]); 2410 } 2411 2412 2413 TEST(Run_WasmCall_Int32Add) { 2414 // Build the target function. 2415 TestSignatures sigs; 2416 TestingModule module; 2417 WasmFunctionCompiler t(sigs.i_ii()); 2418 BUILD(t, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 2419 uint32_t index = t.CompileAndAdd(&module); 2420 2421 // Build the caller function. 2422 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32()); 2423 r.env()->module = &module; 2424 BUILD(r, WASM_CALL_FUNCTION(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 2425 2426 FOR_INT32_INPUTS(i) { 2427 FOR_INT32_INPUTS(j) { 2428 int32_t expected = static_cast<int32_t>(static_cast<uint32_t>(*i) + 2429 static_cast<uint32_t>(*j)); 2430 CHECK_EQ(expected, r.Call(*i, *j)); 2431 } 2432 } 2433 } 2434 2435 2436 #if WASM_64 2437 TEST(Run_WasmCall_Int64Sub) { 2438 // Build the target function. 2439 TestSignatures sigs; 2440 TestingModule module; 2441 WasmFunctionCompiler t(sigs.l_ll()); 2442 BUILD(t, WASM_I64_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 2443 uint32_t index = t.CompileAndAdd(&module); 2444 2445 // Build the caller function. 2446 WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64()); 2447 r.env()->module = &module; 2448 BUILD(r, WASM_CALL_FUNCTION(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 2449 2450 FOR_INT32_INPUTS(i) { 2451 FOR_INT32_INPUTS(j) { 2452 int64_t a = static_cast<int64_t>(*i) << 32 | 2453 (static_cast<int64_t>(*j) | 0xFFFFFFFF); 2454 int64_t b = static_cast<int64_t>(*j) << 32 | 2455 (static_cast<int64_t>(*i) | 0xFFFFFFFF); 2456 2457 int64_t expected = static_cast<int64_t>(static_cast<uint64_t>(a) - 2458 static_cast<uint64_t>(b)); 2459 CHECK_EQ(expected, r.Call(a, b)); 2460 } 2461 } 2462 } 2463 #endif 2464 2465 2466 TEST(Run_WasmCall_Float32Sub) { 2467 TestSignatures sigs; 2468 WasmFunctionCompiler t(sigs.f_ff()); 2469 2470 // Build the target function. 2471 TestingModule module; 2472 BUILD(t, WASM_F32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 2473 uint32_t index = t.CompileAndAdd(&module); 2474 2475 // Builder the caller function. 2476 WasmRunner<float> r(MachineType::Float32(), MachineType::Float32()); 2477 r.env()->module = &module; 2478 BUILD(r, WASM_CALL_FUNCTION(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 2479 2480 FOR_FLOAT32_INPUTS(i) { 2481 FOR_FLOAT32_INPUTS(j) { 2482 volatile float expected = *i - *j; 2483 CheckFloatEq(expected, r.Call(*i, *j)); 2484 } 2485 } 2486 } 2487 2488 2489 TEST(Run_WasmCall_Float64Sub) { 2490 WasmRunner<int32_t> r; 2491 TestingModule module; 2492 double* memory = module.AddMemoryElems<double>(16); 2493 r.env()->module = &module; 2494 2495 // TODO(titzer): convert to a binop test. 2496 BUILD(r, WASM_BLOCK( 2497 2, WASM_STORE_MEM( 2498 MachineType::Float64(), WASM_ZERO, 2499 WASM_F64_SUB( 2500 WASM_LOAD_MEM(MachineType::Float64(), WASM_ZERO), 2501 WASM_LOAD_MEM(MachineType::Float64(), WASM_I8(8)))), 2502 WASM_I8(107))); 2503 2504 FOR_FLOAT64_INPUTS(i) { 2505 FOR_FLOAT64_INPUTS(j) { 2506 memory[0] = *i; 2507 memory[1] = *j; 2508 double expected = *i - *j; 2509 CHECK_EQ(107, r.Call()); 2510 if (expected != expected) { 2511 CHECK(memory[0] != memory[0]); 2512 } else { 2513 CHECK_EQ(expected, memory[0]); 2514 } 2515 } 2516 } 2517 } 2518 2519 #define ADD_CODE(vec, ...) \ 2520 do { \ 2521 byte __buf[] = {__VA_ARGS__}; \ 2522 for (size_t i = 0; i < sizeof(__buf); i++) vec.push_back(__buf[i]); \ 2523 } while (false) 2524 2525 2526 static void Run_WasmMixedCall_N(int start) { 2527 const int kExpected = 6333; 2528 const int kElemSize = 8; 2529 TestSignatures sigs; 2530 2531 #if WASM_64 2532 static MachineType mixed[] = { 2533 MachineType::Int32(), MachineType::Float32(), MachineType::Int64(), 2534 MachineType::Float64(), MachineType::Float32(), MachineType::Int64(), 2535 MachineType::Int32(), MachineType::Float64(), MachineType::Float32(), 2536 MachineType::Float64(), MachineType::Int32(), MachineType::Int64(), 2537 MachineType::Int32(), MachineType::Int32()}; 2538 #else 2539 static MachineType mixed[] = { 2540 MachineType::Int32(), MachineType::Float32(), MachineType::Float64(), 2541 MachineType::Float32(), MachineType::Int32(), MachineType::Float64(), 2542 MachineType::Float32(), MachineType::Float64(), MachineType::Int32(), 2543 MachineType::Int32(), MachineType::Int32()}; 2544 #endif 2545 2546 int num_params = static_cast<int>(arraysize(mixed)) - start; 2547 for (int which = 0; which < num_params; which++) { 2548 Zone zone; 2549 TestingModule module; 2550 module.AddMemory(1024); 2551 MachineType* memtypes = &mixed[start]; 2552 MachineType result = memtypes[which]; 2553 2554 // ========================================================================= 2555 // Build the selector function. 2556 // ========================================================================= 2557 uint32_t index; 2558 FunctionSig::Builder b(&zone, 1, num_params); 2559 b.AddReturn(WasmOpcodes::LocalTypeFor(result)); 2560 for (int i = 0; i < num_params; i++) { 2561 b.AddParam(WasmOpcodes::LocalTypeFor(memtypes[i])); 2562 } 2563 WasmFunctionCompiler t(b.Build()); 2564 t.env.module = &module; 2565 BUILD(t, WASM_GET_LOCAL(which)); 2566 index = t.CompileAndAdd(&module); 2567 2568 // ========================================================================= 2569 // Build the calling function. 2570 // ========================================================================= 2571 WasmRunner<int32_t> r; 2572 r.env()->module = &module; 2573 2574 { 2575 std::vector<byte> code; 2576 ADD_CODE(code, 2577 static_cast<byte>(WasmOpcodes::LoadStoreOpcodeOf(result, true)), 2578 WasmOpcodes::LoadStoreAccessOf(false)); 2579 ADD_CODE(code, WASM_ZERO); 2580 ADD_CODE(code, kExprCallFunction, static_cast<byte>(index)); 2581 2582 for (int i = 0; i < num_params; i++) { 2583 int offset = (i + 1) * kElemSize; 2584 ADD_CODE(code, WASM_LOAD_MEM(memtypes[i], WASM_I8(offset))); 2585 } 2586 2587 ADD_CODE(code, WASM_I32(kExpected)); 2588 size_t end = code.size(); 2589 code.push_back(0); 2590 r.Build(&code[0], &code[end]); 2591 } 2592 2593 // Run the code. 2594 for (int t = 0; t < 10; t++) { 2595 module.RandomizeMemory(); 2596 CHECK_EQ(kExpected, r.Call()); 2597 2598 int size = WasmOpcodes::MemSize(result); 2599 for (int i = 0; i < size; i++) { 2600 int base = (which + 1) * kElemSize; 2601 byte expected = module.raw_mem_at<byte>(base + i); 2602 byte result = module.raw_mem_at<byte>(i); 2603 CHECK_EQ(expected, result); 2604 } 2605 } 2606 } 2607 } 2608 2609 2610 TEST(Run_WasmMixedCall_0) { Run_WasmMixedCall_N(0); } 2611 TEST(Run_WasmMixedCall_1) { Run_WasmMixedCall_N(1); } 2612 TEST(Run_WasmMixedCall_2) { Run_WasmMixedCall_N(2); } 2613 TEST(Run_WasmMixedCall_3) { Run_WasmMixedCall_N(3); } 2614 2615 2616 TEST(Run_Wasm_CountDown_expr) { 2617 WasmRunner<int32_t> r(MachineType::Int32()); 2618 BUILD(r, WASM_LOOP( 2619 3, WASM_IF(WASM_NOT(WASM_GET_LOCAL(0)), 2620 WASM_BREAKV(0, WASM_GET_LOCAL(0))), 2621 WASM_SET_LOCAL(0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(1))), 2622 WASM_CONTINUE(0))); 2623 CHECK_EQ(0, r.Call(1)); 2624 CHECK_EQ(0, r.Call(10)); 2625 CHECK_EQ(0, r.Call(100)); 2626 } 2627 2628 2629 TEST(Run_Wasm_ExprBlock2a) { 2630 WasmRunner<int32_t> r(MachineType::Int32()); 2631 BUILD(r, WASM_BLOCK(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(1))), 2632 WASM_I8(1))); 2633 CHECK_EQ(1, r.Call(0)); 2634 CHECK_EQ(1, r.Call(1)); 2635 } 2636 2637 2638 TEST(Run_Wasm_ExprBlock2b) { 2639 WasmRunner<int32_t> r(MachineType::Int32()); 2640 BUILD(r, WASM_BLOCK(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(1))), 2641 WASM_I8(2))); 2642 CHECK_EQ(2, r.Call(0)); 2643 CHECK_EQ(1, r.Call(1)); 2644 } 2645 2646 2647 TEST(Run_Wasm_ExprBlock2c) { 2648 WasmRunner<int32_t> r(MachineType::Int32()); 2649 BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_I8(1)), 2650 WASM_I8(1))); 2651 CHECK_EQ(1, r.Call(0)); 2652 CHECK_EQ(1, r.Call(1)); 2653 } 2654 2655 2656 TEST(Run_Wasm_ExprBlock2d) { 2657 WasmRunner<int32_t> r(MachineType::Int32()); 2658 BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_I8(1)), 2659 WASM_I8(2))); 2660 CHECK_EQ(2, r.Call(0)); 2661 CHECK_EQ(1, r.Call(1)); 2662 } 2663 2664 2665 TEST(Run_Wasm_ExprBlock_ManualSwitch) { 2666 WasmRunner<int32_t> r(MachineType::Int32()); 2667 BUILD(r, WASM_BLOCK(6, WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(1)), 2668 WASM_BRV(0, WASM_I8(11))), 2669 WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(2)), 2670 WASM_BRV(0, WASM_I8(12))), 2671 WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(3)), 2672 WASM_BRV(0, WASM_I8(13))), 2673 WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(4)), 2674 WASM_BRV(0, WASM_I8(14))), 2675 WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(5)), 2676 WASM_BRV(0, WASM_I8(15))), 2677 WASM_I8(99))); 2678 CHECK_EQ(99, r.Call(0)); 2679 CHECK_EQ(11, r.Call(1)); 2680 CHECK_EQ(12, r.Call(2)); 2681 CHECK_EQ(13, r.Call(3)); 2682 CHECK_EQ(14, r.Call(4)); 2683 CHECK_EQ(15, r.Call(5)); 2684 CHECK_EQ(99, r.Call(6)); 2685 } 2686 2687 2688 TEST(Run_Wasm_ExprBlock_ManualSwitch_brif) { 2689 WasmRunner<int32_t> r(MachineType::Int32()); 2690 BUILD(r, 2691 WASM_BLOCK(6, WASM_BRV_IF(0, WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(1)), 2692 WASM_I8(11)), 2693 WASM_BRV_IF(0, WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(2)), 2694 WASM_I8(12)), 2695 WASM_BRV_IF(0, WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(3)), 2696 WASM_I8(13)), 2697 WASM_BRV_IF(0, WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(4)), 2698 WASM_I8(14)), 2699 WASM_BRV_IF(0, WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(5)), 2700 WASM_I8(15)), 2701 WASM_I8(99))); 2702 CHECK_EQ(99, r.Call(0)); 2703 CHECK_EQ(11, r.Call(1)); 2704 CHECK_EQ(12, r.Call(2)); 2705 CHECK_EQ(13, r.Call(3)); 2706 CHECK_EQ(14, r.Call(4)); 2707 CHECK_EQ(15, r.Call(5)); 2708 CHECK_EQ(99, r.Call(6)); 2709 } 2710 2711 2712 TEST(Run_Wasm_nested_ifs) { 2713 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32()); 2714 2715 BUILD(r, WASM_IF_ELSE( 2716 WASM_GET_LOCAL(0), 2717 WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_I8(11), WASM_I8(12)), 2718 WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_I8(13), WASM_I8(14)))); 2719 2720 2721 CHECK_EQ(11, r.Call(1, 1)); 2722 CHECK_EQ(12, r.Call(1, 0)); 2723 CHECK_EQ(13, r.Call(0, 1)); 2724 CHECK_EQ(14, r.Call(0, 0)); 2725 } 2726 2727 2728 TEST(Run_Wasm_ExprBlock_if) { 2729 WasmRunner<int32_t> r(MachineType::Int32()); 2730 2731 BUILD(r, 2732 WASM_BLOCK(1, WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(11)), 2733 WASM_BRV(0, WASM_I8(14))))); 2734 2735 CHECK_EQ(11, r.Call(1)); 2736 CHECK_EQ(14, r.Call(0)); 2737 } 2738 2739 2740 TEST(Run_Wasm_ExprBlock_nested_ifs) { 2741 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32()); 2742 2743 BUILD(r, WASM_BLOCK( 2744 1, WASM_IF_ELSE( 2745 WASM_GET_LOCAL(0), 2746 WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_BRV(0, WASM_I8(11)), 2747 WASM_BRV(0, WASM_I8(12))), 2748 WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_BRV(0, WASM_I8(13)), 2749 WASM_BRV(0, WASM_I8(14)))))); 2750 2751 2752 CHECK_EQ(11, r.Call(1, 1)); 2753 CHECK_EQ(12, r.Call(1, 0)); 2754 CHECK_EQ(13, r.Call(0, 1)); 2755 CHECK_EQ(14, r.Call(0, 0)); 2756 } 2757 2758 2759 TEST(Run_Wasm_ExprLoop_nested_ifs) { 2760 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32()); 2761 2762 BUILD(r, WASM_LOOP( 2763 1, WASM_IF_ELSE( 2764 WASM_GET_LOCAL(0), 2765 WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_BRV(1, WASM_I8(11)), 2766 WASM_BRV(1, WASM_I8(12))), 2767 WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_BRV(1, WASM_I8(13)), 2768 WASM_BRV(1, WASM_I8(14)))))); 2769 2770 2771 CHECK_EQ(11, r.Call(1, 1)); 2772 CHECK_EQ(12, r.Call(1, 0)); 2773 CHECK_EQ(13, r.Call(0, 1)); 2774 CHECK_EQ(14, r.Call(0, 0)); 2775 } 2776 2777 2778 #if WASM_64 2779 TEST(Run_Wasm_LoadStoreI64_sx) { 2780 byte loads[] = {kExprI64LoadMem8S, kExprI64LoadMem16S, kExprI64LoadMem32S, 2781 kExprI64LoadMem}; 2782 2783 for (size_t m = 0; m < arraysize(loads); m++) { 2784 WasmRunner<int64_t> r; 2785 TestingModule module; 2786 byte* memory = module.AddMemoryElems<byte>(16); 2787 r.env()->module = &module; 2788 2789 byte code[] = {kExprI64StoreMem, 0, kExprI8Const, 8, 2790 loads[m], 0, kExprI8Const, 0}; 2791 2792 r.Build(code, code + arraysize(code)); 2793 2794 // Try a bunch of different negative values. 2795 for (int i = -1; i >= -128; i -= 11) { 2796 int size = 1 << m; 2797 module.BlankMemory(); 2798 memory[size - 1] = static_cast<byte>(i); // set the high order byte. 2799 2800 int64_t expected = static_cast<int64_t>(i) << ((size - 1) * 8); 2801 2802 CHECK_EQ(expected, r.Call()); 2803 CHECK_EQ(static_cast<byte>(i), memory[8 + size - 1]); 2804 for (int j = size; j < 8; j++) { 2805 CHECK_EQ(255, memory[8 + j]); 2806 } 2807 } 2808 } 2809 } 2810 2811 2812 #endif 2813 2814 2815 TEST(Run_Wasm_SimpleCallIndirect) { 2816 Isolate* isolate = CcTest::InitIsolateOnce(); 2817 2818 WasmRunner<int32_t> r(MachineType::Int32()); 2819 TestSignatures sigs; 2820 TestingModule module; 2821 r.env()->module = &module; 2822 WasmFunctionCompiler t1(sigs.i_ii()); 2823 BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 2824 t1.CompileAndAdd(&module); 2825 2826 WasmFunctionCompiler t2(sigs.i_ii()); 2827 BUILD(t2, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 2828 t2.CompileAndAdd(&module); 2829 2830 // Signature table. 2831 module.AddSignature(sigs.f_ff()); 2832 module.AddSignature(sigs.i_ii()); 2833 module.AddSignature(sigs.d_dd()); 2834 2835 // Function table. 2836 int table_size = 2; 2837 module.module->function_table = new std::vector<uint16_t>; 2838 module.module->function_table->push_back(0); 2839 module.module->function_table->push_back(1); 2840 2841 // Function table. 2842 Handle<FixedArray> fixed = isolate->factory()->NewFixedArray(2 * table_size); 2843 fixed->set(0, Smi::FromInt(1)); 2844 fixed->set(1, Smi::FromInt(1)); 2845 fixed->set(2, *module.function_code->at(0)); 2846 fixed->set(3, *module.function_code->at(1)); 2847 module.function_table = fixed; 2848 2849 // Builder the caller function. 2850 BUILD(r, WASM_CALL_INDIRECT(1, WASM_GET_LOCAL(0), WASM_I8(66), WASM_I8(22))); 2851 2852 CHECK_EQ(88, r.Call(0)); 2853 CHECK_EQ(44, r.Call(1)); 2854 CHECK_TRAP(r.Call(2)); 2855 } 2856 2857 2858 TEST(Run_Wasm_MultipleCallIndirect) { 2859 Isolate* isolate = CcTest::InitIsolateOnce(); 2860 2861 WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32(), 2862 MachineType::Int32()); 2863 TestSignatures sigs; 2864 TestingModule module; 2865 r.env()->module = &module; 2866 WasmFunctionCompiler t1(sigs.i_ii()); 2867 BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 2868 t1.CompileAndAdd(&module); 2869 2870 WasmFunctionCompiler t2(sigs.i_ii()); 2871 BUILD(t2, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 2872 t2.CompileAndAdd(&module); 2873 2874 // Signature table. 2875 module.AddSignature(sigs.f_ff()); 2876 module.AddSignature(sigs.i_ii()); 2877 module.AddSignature(sigs.d_dd()); 2878 2879 // Function table. 2880 int table_size = 2; 2881 module.module->function_table = new std::vector<uint16_t>; 2882 module.module->function_table->push_back(0); 2883 module.module->function_table->push_back(1); 2884 2885 // Function table. 2886 Handle<FixedArray> fixed = isolate->factory()->NewFixedArray(2 * table_size); 2887 fixed->set(0, Smi::FromInt(1)); 2888 fixed->set(1, Smi::FromInt(1)); 2889 fixed->set(2, *module.function_code->at(0)); 2890 fixed->set(3, *module.function_code->at(1)); 2891 module.function_table = fixed; 2892 2893 // Builder the caller function. 2894 BUILD(r, 2895 WASM_I32_ADD(WASM_CALL_INDIRECT(1, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1), 2896 WASM_GET_LOCAL(2)), 2897 WASM_CALL_INDIRECT(1, WASM_GET_LOCAL(1), WASM_GET_LOCAL(2), 2898 WASM_GET_LOCAL(0)))); 2899 2900 CHECK_EQ(5, r.Call(0, 1, 2)); 2901 CHECK_EQ(19, r.Call(0, 1, 9)); 2902 CHECK_EQ(1, r.Call(1, 0, 2)); 2903 CHECK_EQ(1, r.Call(1, 0, 9)); 2904 2905 CHECK_TRAP(r.Call(0, 2, 1)); 2906 CHECK_TRAP(r.Call(1, 2, 0)); 2907 CHECK_TRAP(r.Call(2, 0, 1)); 2908 CHECK_TRAP(r.Call(2, 1, 0)); 2909 } 2910 2911 2912 // TODO(titzer): Fix for nosee4 and re-enable. 2913 #if 0 2914 2915 TEST(Run_Wasm_F32Floor) { 2916 WasmRunner<float> r(MachineType::Float32()); 2917 BUILD(r, WASM_F32_FLOOR(WASM_GET_LOCAL(0))); 2918 2919 FOR_FLOAT32_INPUTS(i) { CheckFloatEq(floor(*i), r.Call(*i)); } 2920 } 2921 2922 2923 TEST(Run_Wasm_F32Ceil) { 2924 WasmRunner<float> r(MachineType::Float32()); 2925 BUILD(r, WASM_F32_CEIL(WASM_GET_LOCAL(0))); 2926 2927 FOR_FLOAT32_INPUTS(i) { CheckFloatEq(ceil(*i), r.Call(*i)); } 2928 } 2929 2930 2931 TEST(Run_Wasm_F32Trunc) { 2932 WasmRunner<float> r(MachineType::Float32()); 2933 BUILD(r, WASM_F32_TRUNC(WASM_GET_LOCAL(0))); 2934 2935 FOR_FLOAT32_INPUTS(i) { CheckFloatEq(trunc(*i), r.Call(*i)); } 2936 } 2937 2938 2939 TEST(Run_Wasm_F32NearestInt) { 2940 WasmRunner<float> r(MachineType::Float32()); 2941 BUILD(r, WASM_F32_NEARESTINT(WASM_GET_LOCAL(0))); 2942 2943 FOR_FLOAT32_INPUTS(i) { CheckFloatEq(nearbyint(*i), r.Call(*i)); } 2944 } 2945 2946 2947 TEST(Run_Wasm_F64Floor) { 2948 WasmRunner<double> r(MachineType::Float64()); 2949 BUILD(r, WASM_F64_FLOOR(WASM_GET_LOCAL(0))); 2950 2951 FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(floor(*i), r.Call(*i)); } 2952 } 2953 2954 2955 TEST(Run_Wasm_F64Ceil) { 2956 WasmRunner<double> r(MachineType::Float64()); 2957 BUILD(r, WASM_F64_CEIL(WASM_GET_LOCAL(0))); 2958 2959 FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(ceil(*i), r.Call(*i)); } 2960 } 2961 2962 2963 TEST(Run_Wasm_F64Trunc) { 2964 WasmRunner<double> r(MachineType::Float64()); 2965 BUILD(r, WASM_F64_TRUNC(WASM_GET_LOCAL(0))); 2966 2967 FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(trunc(*i), r.Call(*i)); } 2968 } 2969 2970 2971 TEST(Run_Wasm_F64NearestInt) { 2972 WasmRunner<double> r(MachineType::Float64()); 2973 BUILD(r, WASM_F64_NEARESTINT(WASM_GET_LOCAL(0))); 2974 2975 FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(nearbyint(*i), r.Call(*i)); } 2976 } 2977 2978 #endif 2979 2980 2981 TEST(Run_Wasm_F32Min) { 2982 WasmRunner<float> r(MachineType::Float32(), MachineType::Float32()); 2983 BUILD(r, WASM_F32_MIN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 2984 2985 FOR_FLOAT32_INPUTS(i) { 2986 FOR_FLOAT32_INPUTS(j) { 2987 float expected; 2988 if (*i < *j) { 2989 expected = *i; 2990 } else if (*j < *i) { 2991 expected = *j; 2992 } else if (*i != *i) { 2993 // If *i or *j is NaN, then the result is NaN. 2994 expected = *i; 2995 } else { 2996 expected = *j; 2997 } 2998 2999 CheckFloatEq(expected, r.Call(*i, *j)); 3000 } 3001 } 3002 } 3003 3004 3005 TEST(Run_Wasm_F64Min) { 3006 WasmRunner<double> r(MachineType::Float64(), MachineType::Float64()); 3007 BUILD(r, WASM_F64_MIN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 3008 3009 FOR_FLOAT64_INPUTS(i) { 3010 FOR_FLOAT64_INPUTS(j) { 3011 double expected; 3012 if (*i < *j) { 3013 expected = *i; 3014 } else if (*j < *i) { 3015 expected = *j; 3016 } else if (*i != *i) { 3017 // If *i or *j is NaN, then the result is NaN. 3018 expected = *i; 3019 } else { 3020 expected = *j; 3021 } 3022 3023 CheckDoubleEq(expected, r.Call(*i, *j)); 3024 } 3025 } 3026 } 3027 3028 3029 TEST(Run_Wasm_F32Max) { 3030 WasmRunner<float> r(MachineType::Float32(), MachineType::Float32()); 3031 BUILD(r, WASM_F32_MAX(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 3032 3033 FOR_FLOAT32_INPUTS(i) { 3034 FOR_FLOAT32_INPUTS(j) { 3035 float expected; 3036 if (*i > *j) { 3037 expected = *i; 3038 } else if (*j > *i) { 3039 expected = *j; 3040 } else if (*i != *i) { 3041 // If *i or *j is NaN, then the result is NaN. 3042 expected = *i; 3043 } else { 3044 expected = *j; 3045 } 3046 3047 CheckFloatEq(expected, r.Call(*i, *j)); 3048 } 3049 } 3050 } 3051 3052 3053 TEST(Run_Wasm_F64Max) { 3054 WasmRunner<double> r(MachineType::Float64(), MachineType::Float64()); 3055 BUILD(r, WASM_F64_MAX(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 3056 3057 FOR_FLOAT64_INPUTS(i) { 3058 FOR_FLOAT64_INPUTS(j) { 3059 double expected; 3060 if (*i > *j) { 3061 expected = *i; 3062 } else if (*j > *i) { 3063 expected = *j; 3064 } else if (*i != *i) { 3065 // If *i or *j is NaN, then the result is NaN. 3066 expected = *i; 3067 } else { 3068 expected = *j; 3069 } 3070 3071 CheckDoubleEq(expected, r.Call(*i, *j)); 3072 } 3073 } 3074 } 3075 3076 3077 #if WASM_64 3078 TEST(Run_Wasm_F32SConvertI64) { 3079 WasmRunner<float> r(MachineType::Int64()); 3080 BUILD(r, WASM_F32_SCONVERT_I64(WASM_GET_LOCAL(0))); 3081 FOR_INT64_INPUTS(i) { CHECK_EQ(static_cast<float>(*i), r.Call(*i)); } 3082 } 3083 3084 3085 #if !defined(_WIN64) 3086 // TODO(ahaas): Fix this failure. 3087 TEST(Run_Wasm_F32UConvertI64) { 3088 WasmRunner<float> r(MachineType::Uint64()); 3089 BUILD(r, WASM_F32_UCONVERT_I64(WASM_GET_LOCAL(0))); 3090 FOR_UINT64_INPUTS(i) { CHECK_EQ(static_cast<float>(*i), r.Call(*i)); } 3091 } 3092 #endif 3093 3094 3095 TEST(Run_Wasm_F64SConvertI64) { 3096 WasmRunner<double> r(MachineType::Int64()); 3097 BUILD(r, WASM_F64_SCONVERT_I64(WASM_GET_LOCAL(0))); 3098 FOR_INT64_INPUTS(i) { CHECK_EQ(static_cast<double>(*i), r.Call(*i)); } 3099 } 3100 3101 3102 #if !defined(_WIN64) 3103 // TODO(ahaas): Fix this failure. 3104 TEST(Run_Wasm_F64UConvertI64) { 3105 WasmRunner<double> r(MachineType::Uint64()); 3106 BUILD(r, WASM_F64_UCONVERT_I64(WASM_GET_LOCAL(0))); 3107 FOR_UINT64_INPUTS(i) { CHECK_EQ(static_cast<double>(*i), r.Call(*i)); } 3108 } 3109 #endif 3110 3111 3112 TEST(Run_Wasm_I64SConvertF32) { 3113 WasmRunner<int64_t> r(MachineType::Float32()); 3114 BUILD(r, WASM_I64_SCONVERT_F32(WASM_GET_LOCAL(0))); 3115 3116 FOR_FLOAT32_INPUTS(i) { 3117 if (*i < static_cast<float>(INT64_MAX) && 3118 *i >= static_cast<float>(INT64_MIN)) { 3119 CHECK_EQ(static_cast<int64_t>(*i), r.Call(*i)); 3120 } else { 3121 CHECK_TRAP64(r.Call(*i)); 3122 } 3123 } 3124 } 3125 3126 3127 TEST(Run_Wasm_I64SConvertF64) { 3128 WasmRunner<int64_t> r(MachineType::Float64()); 3129 BUILD(r, WASM_I64_SCONVERT_F64(WASM_GET_LOCAL(0))); 3130 3131 FOR_FLOAT64_INPUTS(i) { 3132 if (*i < static_cast<double>(INT64_MAX) && 3133 *i >= static_cast<double>(INT64_MIN)) { 3134 CHECK_EQ(static_cast<int64_t>(*i), r.Call(*i)); 3135 } else { 3136 CHECK_TRAP64(r.Call(*i)); 3137 } 3138 } 3139 } 3140 3141 3142 TEST(Run_Wasm_I64UConvertF32) { 3143 WasmRunner<uint64_t> r(MachineType::Float32()); 3144 BUILD(r, WASM_I64_UCONVERT_F32(WASM_GET_LOCAL(0))); 3145 3146 FOR_FLOAT32_INPUTS(i) { 3147 if (*i < static_cast<float>(UINT64_MAX) && *i > -1) { 3148 CHECK_EQ(static_cast<uint64_t>(*i), r.Call(*i)); 3149 } else { 3150 CHECK_TRAP64(r.Call(*i)); 3151 } 3152 } 3153 } 3154 3155 3156 TEST(Run_Wasm_I64UConvertF64) { 3157 WasmRunner<uint64_t> r(MachineType::Float64()); 3158 BUILD(r, WASM_I64_UCONVERT_F64(WASM_GET_LOCAL(0))); 3159 3160 FOR_FLOAT64_INPUTS(i) { 3161 if (*i < static_cast<float>(UINT64_MAX) && *i > -1) { 3162 CHECK_EQ(static_cast<uint64_t>(*i), r.Call(*i)); 3163 } else { 3164 CHECK_TRAP64(r.Call(*i)); 3165 } 3166 } 3167 } 3168 #endif 3169 3170 3171 // TODO(titzer): Fix and re-enable. 3172 #if 0 3173 TEST(Run_Wasm_I32SConvertF32) { 3174 WasmRunner<int32_t> r(MachineType::Float32()); 3175 BUILD(r, WASM_I32_SCONVERT_F32(WASM_GET_LOCAL(0))); 3176 3177 FOR_FLOAT32_INPUTS(i) { 3178 if (*i < static_cast<float>(INT32_MAX) && 3179 *i >= static_cast<float>(INT32_MIN)) { 3180 CHECK_EQ(static_cast<int32_t>(*i), r.Call(*i)); 3181 } else { 3182 CHECK_TRAP32(r.Call(*i)); 3183 } 3184 } 3185 } 3186 3187 3188 TEST(Run_Wasm_I32SConvertF64) { 3189 WasmRunner<int32_t> r(MachineType::Float64()); 3190 BUILD(r, WASM_I32_SCONVERT_F64(WASM_GET_LOCAL(0))); 3191 3192 FOR_FLOAT64_INPUTS(i) { 3193 if (*i < static_cast<double>(INT32_MAX) && 3194 *i >= static_cast<double>(INT32_MIN)) { 3195 CHECK_EQ(static_cast<int64_t>(*i), r.Call(*i)); 3196 } else { 3197 CHECK_TRAP32(r.Call(*i)); 3198 } 3199 } 3200 } 3201 3202 3203 TEST(Run_Wasm_I32UConvertF32) { 3204 WasmRunner<uint32_t> r(MachineType::Float32()); 3205 BUILD(r, WASM_I32_UCONVERT_F32(WASM_GET_LOCAL(0))); 3206 3207 FOR_FLOAT32_INPUTS(i) { 3208 if (*i < static_cast<float>(UINT32_MAX) && *i > -1) { 3209 CHECK_EQ(static_cast<uint32_t>(*i), r.Call(*i)); 3210 } else { 3211 CHECK_TRAP32(r.Call(*i)); 3212 } 3213 } 3214 } 3215 3216 3217 TEST(Run_Wasm_I32UConvertF64) { 3218 WasmRunner<uint32_t> r(MachineType::Float64()); 3219 BUILD(r, WASM_I32_UCONVERT_F64(WASM_GET_LOCAL(0))); 3220 3221 FOR_FLOAT64_INPUTS(i) { 3222 if (*i < static_cast<float>(UINT32_MAX) && *i > -1) { 3223 CHECK_EQ(static_cast<uint32_t>(*i), r.Call(*i)); 3224 } else { 3225 CHECK_TRAP32(r.Call(*i)); 3226 } 3227 } 3228 } 3229 #endif 3230 3231 3232 TEST(Run_Wasm_F64CopySign) { 3233 WasmRunner<double> r(MachineType::Float64(), MachineType::Float64()); 3234 BUILD(r, WASM_F64_COPYSIGN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 3235 3236 FOR_FLOAT64_INPUTS(i) { 3237 FOR_FLOAT64_INPUTS(j) { CheckDoubleEq(copysign(*i, *j), r.Call(*i, *j)); } 3238 } 3239 } 3240 3241 3242 // TODO(tizer): Fix on arm and reenable. 3243 #if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64 3244 3245 TEST(Run_Wasm_F32CopySign) { 3246 WasmRunner<float> r(MachineType::Float32(), MachineType::Float32()); 3247 BUILD(r, WASM_F32_COPYSIGN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 3248 3249 FOR_FLOAT32_INPUTS(i) { 3250 FOR_FLOAT32_INPUTS(j) { CheckFloatEq(copysign(*i, *j), r.Call(*i, *j)); } 3251 } 3252 } 3253 3254 #endif 3255