| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_WASM_OPCODES_H_ | 5 #ifndef V8_WASM_OPCODES_H_ |
| 6 #define V8_WASM_OPCODES_H_ | 6 #define V8_WASM_OPCODES_H_ |
| 7 | 7 |
| 8 #include "src/machine-type.h" | 8 #include "src/machine-type.h" |
| 9 #include "src/signature.h" | 9 #include "src/signature.h" |
| 10 | 10 |
| 11 namespace v8 { | 11 namespace v8 { |
| 12 namespace internal { | 12 namespace internal { |
| 13 namespace wasm { | 13 namespace wasm { |
| 14 | 14 |
| 15 // Binary encoding of local types. | 15 // Binary encoding of local types. |
| 16 enum LocalTypeCode { | 16 enum LocalTypeCode { |
| 17 kLocalVoid = 0, | 17 kLocalVoid = 0, |
| 18 kLocalI32 = 1, | 18 kLocalI32 = 1, |
| 19 kLocalI64 = 2, | 19 kLocalI64 = 2, |
| 20 kLocalF32 = 3, | 20 kLocalF32 = 3, |
| 21 kLocalF64 = 4 | 21 kLocalF64 = 4, |
| 22 kLocalS128 = 5 |
| 22 }; | 23 }; |
| 23 | 24 |
| 24 // Binary encoding of memory types. | 25 // Binary encoding of memory types. |
| 25 enum MemTypeCode { | 26 enum MemTypeCode { |
| 26 kMemI8 = 0, | 27 kMemI8 = 0, |
| 27 kMemU8 = 1, | 28 kMemU8 = 1, |
| 28 kMemI16 = 2, | 29 kMemI16 = 2, |
| 29 kMemU16 = 3, | 30 kMemU16 = 3, |
| 30 kMemI32 = 4, | 31 kMemI32 = 4, |
| 31 kMemU32 = 5, | 32 kMemU32 = 5, |
| 32 kMemI64 = 6, | 33 kMemI64 = 6, |
| 33 kMemU64 = 7, | 34 kMemU64 = 7, |
| 34 kMemF32 = 8, | 35 kMemF32 = 8, |
| 35 kMemF64 = 9 | 36 kMemF64 = 9, |
| 37 kMemS128 = 10 |
| 36 }; | 38 }; |
| 37 | 39 |
| 38 // We reuse the internal machine type to represent WebAssembly AST types. | 40 // We reuse the internal machine type to represent WebAssembly AST types. |
| 39 // A typedef improves readability without adding a whole new type system. | 41 // A typedef improves readability without adding a whole new type system. |
| 40 typedef MachineRepresentation LocalType; | 42 typedef MachineRepresentation LocalType; |
| 41 const LocalType kAstStmt = MachineRepresentation::kNone; | 43 const LocalType kAstStmt = MachineRepresentation::kNone; |
| 42 const LocalType kAstI32 = MachineRepresentation::kWord32; | 44 const LocalType kAstI32 = MachineRepresentation::kWord32; |
| 43 const LocalType kAstI64 = MachineRepresentation::kWord64; | 45 const LocalType kAstI64 = MachineRepresentation::kWord64; |
| 44 const LocalType kAstF32 = MachineRepresentation::kFloat32; | 46 const LocalType kAstF32 = MachineRepresentation::kFloat32; |
| 45 const LocalType kAstF64 = MachineRepresentation::kFloat64; | 47 const LocalType kAstF64 = MachineRepresentation::kFloat64; |
| 48 const LocalType kAstS128 = MachineRepresentation::kSimd128; |
| 46 // We use kTagged here because kNone is already used by kAstStmt. | 49 // We use kTagged here because kNone is already used by kAstStmt. |
| 47 const LocalType kAstEnd = MachineRepresentation::kTagged; | 50 const LocalType kAstEnd = MachineRepresentation::kTagged; |
| 48 | 51 |
| 49 typedef Signature<LocalType> FunctionSig; | 52 typedef Signature<LocalType> FunctionSig; |
| 50 std::ostream& operator<<(std::ostream& os, const FunctionSig& function); | 53 std::ostream& operator<<(std::ostream& os, const FunctionSig& function); |
| 51 | 54 |
| 52 typedef Vector<const char> WasmName; | 55 typedef Vector<const char> WasmName; |
| 53 | 56 |
| 54 typedef int WasmCodePosition; | 57 typedef int WasmCodePosition; |
| 55 const WasmCodePosition kNoCodePosition = -1; | 58 const WasmCodePosition kNoCodePosition = -1; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 V(F32StoreMem, 0x35, f_if) \ | 116 V(F32StoreMem, 0x35, f_if) \ |
| 114 V(F64StoreMem, 0x36, d_id) | 117 V(F64StoreMem, 0x36, d_id) |
| 115 | 118 |
| 116 // Load memory expressions. | 119 // Load memory expressions. |
| 117 #define FOREACH_MISC_MEM_OPCODE(V) \ | 120 #define FOREACH_MISC_MEM_OPCODE(V) \ |
| 118 V(MemorySize, 0x3b, i_v) \ | 121 V(MemorySize, 0x3b, i_v) \ |
| 119 V(GrowMemory, 0x39, i_i) | 122 V(GrowMemory, 0x39, i_i) |
| 120 | 123 |
| 121 // Expressions with signatures. | 124 // Expressions with signatures. |
| 122 #define FOREACH_SIMPLE_OPCODE(V) \ | 125 #define FOREACH_SIMPLE_OPCODE(V) \ |
| 126 FOREACH_SIMD_OPCODE(V) \ |
| 123 V(I32Add, 0x40, i_ii) \ | 127 V(I32Add, 0x40, i_ii) \ |
| 124 V(I32Sub, 0x41, i_ii) \ | 128 V(I32Sub, 0x41, i_ii) \ |
| 125 V(I32Mul, 0x42, i_ii) \ | 129 V(I32Mul, 0x42, i_ii) \ |
| 126 V(I32DivS, 0x43, i_ii) \ | 130 V(I32DivS, 0x43, i_ii) \ |
| 127 V(I32DivU, 0x44, i_ii) \ | 131 V(I32DivU, 0x44, i_ii) \ |
| 128 V(I32RemS, 0x45, i_ii) \ | 132 V(I32RemS, 0x45, i_ii) \ |
| 129 V(I32RemU, 0x46, i_ii) \ | 133 V(I32RemU, 0x46, i_ii) \ |
| 130 V(I32And, 0x47, i_ii) \ | 134 V(I32And, 0x47, i_ii) \ |
| 131 V(I32Ior, 0x48, i_ii) \ | 135 V(I32Ior, 0x48, i_ii) \ |
| 132 V(I32Xor, 0x49, i_ii) \ | 136 V(I32Xor, 0x49, i_ii) \ |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 271 V(I32AsmjsStoreMem8, 0xdb, i_ii) \ | 275 V(I32AsmjsStoreMem8, 0xdb, i_ii) \ |
| 272 V(I32AsmjsStoreMem16, 0xdc, i_ii) \ | 276 V(I32AsmjsStoreMem16, 0xdc, i_ii) \ |
| 273 V(I32AsmjsStoreMem, 0xdd, i_ii) \ | 277 V(I32AsmjsStoreMem, 0xdd, i_ii) \ |
| 274 V(F32AsmjsStoreMem, 0xde, f_if) \ | 278 V(F32AsmjsStoreMem, 0xde, f_if) \ |
| 275 V(F64AsmjsStoreMem, 0xdf, d_id) \ | 279 V(F64AsmjsStoreMem, 0xdf, d_id) \ |
| 276 V(I32AsmjsSConvertF32, 0xe0, i_f) \ | 280 V(I32AsmjsSConvertF32, 0xe0, i_f) \ |
| 277 V(I32AsmjsUConvertF32, 0xe1, i_f) \ | 281 V(I32AsmjsUConvertF32, 0xe1, i_f) \ |
| 278 V(I32AsmjsSConvertF64, 0xe2, i_d) \ | 282 V(I32AsmjsSConvertF64, 0xe2, i_d) \ |
| 279 V(I32AsmjsUConvertF64, 0xe3, i_d) | 283 V(I32AsmjsUConvertF64, 0xe3, i_d) |
| 280 | 284 |
| 285 // Simd opcodes |
| 286 #define FOREACH_SIMD_OPCODE(V) \ |
| 287 V(Int32x4Splat, 0xe4, s_i) \ |
| 288 V(Int32x4ExtractLane, 0xe5, i_si) |
| 289 |
| 281 // All opcodes. | 290 // All opcodes. |
| 282 #define FOREACH_OPCODE(V) \ | 291 #define FOREACH_OPCODE(V) \ |
| 283 FOREACH_CONTROL_OPCODE(V) \ | 292 FOREACH_CONTROL_OPCODE(V) \ |
| 284 FOREACH_MISC_OPCODE(V) \ | 293 FOREACH_MISC_OPCODE(V) \ |
| 285 FOREACH_SIMPLE_OPCODE(V) \ | 294 FOREACH_SIMPLE_OPCODE(V) \ |
| 286 FOREACH_STORE_MEM_OPCODE(V) \ | 295 FOREACH_STORE_MEM_OPCODE(V) \ |
| 287 FOREACH_LOAD_MEM_OPCODE(V) \ | 296 FOREACH_LOAD_MEM_OPCODE(V) \ |
| 288 FOREACH_MISC_MEM_OPCODE(V) \ | 297 FOREACH_MISC_MEM_OPCODE(V) \ |
| 289 FOREACH_ASMJS_COMPAT_OPCODE(V) | 298 FOREACH_ASMJS_COMPAT_OPCODE(V) |
| 290 | 299 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 309 V(f_d, kAstF32, kAstF64) \ | 318 V(f_d, kAstF32, kAstF64) \ |
| 310 V(f_i, kAstF32, kAstI32) \ | 319 V(f_i, kAstF32, kAstI32) \ |
| 311 V(f_l, kAstF32, kAstI64) \ | 320 V(f_l, kAstF32, kAstI64) \ |
| 312 V(d_dd, kAstF64, kAstF64, kAstF64) \ | 321 V(d_dd, kAstF64, kAstF64, kAstF64) \ |
| 313 V(d_d, kAstF64, kAstF64) \ | 322 V(d_d, kAstF64, kAstF64) \ |
| 314 V(d_f, kAstF64, kAstF32) \ | 323 V(d_f, kAstF64, kAstF32) \ |
| 315 V(d_i, kAstF64, kAstI32) \ | 324 V(d_i, kAstF64, kAstI32) \ |
| 316 V(d_l, kAstF64, kAstI64) \ | 325 V(d_l, kAstF64, kAstI64) \ |
| 317 V(d_id, kAstF64, kAstI32, kAstF64) \ | 326 V(d_id, kAstF64, kAstI32, kAstF64) \ |
| 318 V(f_if, kAstF32, kAstI32, kAstF32) \ | 327 V(f_if, kAstF32, kAstI32, kAstF32) \ |
| 319 V(l_il, kAstI64, kAstI32, kAstI64) | 328 V(l_il, kAstI64, kAstI32, kAstI64) \ |
| 329 V(s_i, kAstS128, kAstI32) \ |
| 330 V(i_si, kAstI32, kAstS128, kAstI32) |
| 320 | 331 |
| 321 enum WasmOpcode { | 332 enum WasmOpcode { |
| 322 // Declare expression opcodes. | 333 // Declare expression opcodes. |
| 323 #define DECLARE_NAMED_ENUM(name, opcode, sig) kExpr##name = opcode, | 334 #define DECLARE_NAMED_ENUM(name, opcode, sig) kExpr##name = opcode, |
| 324 FOREACH_OPCODE(DECLARE_NAMED_ENUM) | 335 FOREACH_OPCODE(DECLARE_NAMED_ENUM) |
| 325 #undef DECLARE_NAMED_ENUM | 336 #undef DECLARE_NAMED_ENUM |
| 326 }; | 337 }; |
| 327 | 338 |
| 328 // The reason for a trap. | 339 // The reason for a trap. |
| 329 #define FOREACH_WASM_TRAPREASON(V) \ | 340 #define FOREACH_WASM_TRAPREASON(V) \ |
| (...skipping 12 matching lines...) Expand all Loading... |
| 342 kTrapCount | 353 kTrapCount |
| 343 #undef DECLARE_ENUM | 354 #undef DECLARE_ENUM |
| 344 }; | 355 }; |
| 345 | 356 |
| 346 // A collection of opcode-related static methods. | 357 // A collection of opcode-related static methods. |
| 347 class WasmOpcodes { | 358 class WasmOpcodes { |
| 348 public: | 359 public: |
| 349 static const char* OpcodeName(WasmOpcode opcode); | 360 static const char* OpcodeName(WasmOpcode opcode); |
| 350 static const char* ShortOpcodeName(WasmOpcode opcode); | 361 static const char* ShortOpcodeName(WasmOpcode opcode); |
| 351 static FunctionSig* Signature(WasmOpcode opcode); | 362 static FunctionSig* Signature(WasmOpcode opcode); |
| 363 static bool IsSimd(WasmOpcode opcode); |
| 352 | 364 |
| 353 static int TrapReasonToMessageId(TrapReason reason); | 365 static int TrapReasonToMessageId(TrapReason reason); |
| 354 static const char* TrapReasonMessage(TrapReason reason); | 366 static const char* TrapReasonMessage(TrapReason reason); |
| 355 | 367 |
| 356 static byte MemSize(MachineType type) { | 368 static byte MemSize(MachineType type) { |
| 357 return 1 << ElementSizeLog2Of(type.representation()); | 369 return 1 << ElementSizeLog2Of(type.representation()); |
| 358 } | 370 } |
| 359 | 371 |
| 360 static LocalTypeCode LocalTypeCodeFor(LocalType type) { | 372 static LocalTypeCode LocalTypeCodeFor(LocalType type) { |
| 361 switch (type) { | 373 switch (type) { |
| 362 case kAstI32: | 374 case kAstI32: |
| 363 return kLocalI32; | 375 return kLocalI32; |
| 364 case kAstI64: | 376 case kAstI64: |
| 365 return kLocalI64; | 377 return kLocalI64; |
| 366 case kAstF32: | 378 case kAstF32: |
| 367 return kLocalF32; | 379 return kLocalF32; |
| 368 case kAstF64: | 380 case kAstF64: |
| 369 return kLocalF64; | 381 return kLocalF64; |
| 370 case kAstStmt: | 382 case kAstStmt: |
| 371 return kLocalVoid; | 383 return kLocalVoid; |
| 384 case kAstS128: |
| 385 return kLocalS128; |
| 372 default: | 386 default: |
| 373 UNREACHABLE(); | 387 UNREACHABLE(); |
| 374 return kLocalVoid; | 388 return kLocalVoid; |
| 375 } | 389 } |
| 376 } | 390 } |
| 377 | 391 |
| 378 static MemTypeCode MemTypeCodeFor(MachineType type) { | 392 static MemTypeCode MemTypeCodeFor(MachineType type) { |
| 379 if (type == MachineType::Int8()) { | 393 if (type == MachineType::Int8()) { |
| 380 return kMemI8; | 394 return kMemI8; |
| 381 } else if (type == MachineType::Uint8()) { | 395 } else if (type == MachineType::Uint8()) { |
| 382 return kMemU8; | 396 return kMemU8; |
| 383 } else if (type == MachineType::Int16()) { | 397 } else if (type == MachineType::Int16()) { |
| 384 return kMemI16; | 398 return kMemI16; |
| 385 } else if (type == MachineType::Uint16()) { | 399 } else if (type == MachineType::Uint16()) { |
| 386 return kMemU16; | 400 return kMemU16; |
| 387 } else if (type == MachineType::Int32()) { | 401 } else if (type == MachineType::Int32()) { |
| 388 return kMemI32; | 402 return kMemI32; |
| 389 } else if (type == MachineType::Uint32()) { | 403 } else if (type == MachineType::Uint32()) { |
| 390 return kMemU32; | 404 return kMemU32; |
| 391 } else if (type == MachineType::Int64()) { | 405 } else if (type == MachineType::Int64()) { |
| 392 return kMemI64; | 406 return kMemI64; |
| 393 } else if (type == MachineType::Uint64()) { | 407 } else if (type == MachineType::Uint64()) { |
| 394 return kMemU64; | 408 return kMemU64; |
| 395 } else if (type == MachineType::Float32()) { | 409 } else if (type == MachineType::Float32()) { |
| 396 return kMemF32; | 410 return kMemF32; |
| 397 } else if (type == MachineType::Float64()) { | 411 } else if (type == MachineType::Float64()) { |
| 398 return kMemF64; | 412 return kMemF64; |
| 413 } else if (type == MachineType::Simd128()) { |
| 414 return kMemS128; |
| 399 } else { | 415 } else { |
| 400 UNREACHABLE(); | 416 UNREACHABLE(); |
| 401 return kMemI32; | 417 return kMemI32; |
| 402 } | 418 } |
| 403 } | 419 } |
| 404 | 420 |
| 405 static MachineType MachineTypeFor(LocalType type) { | 421 static MachineType MachineTypeFor(LocalType type) { |
| 406 switch (type) { | 422 switch (type) { |
| 407 case kAstI32: | 423 case kAstI32: |
| 408 return MachineType::Int32(); | 424 return MachineType::Int32(); |
| 409 case kAstI64: | 425 case kAstI64: |
| 410 return MachineType::Int64(); | 426 return MachineType::Int64(); |
| 411 case kAstF32: | 427 case kAstF32: |
| 412 return MachineType::Float32(); | 428 return MachineType::Float32(); |
| 413 case kAstF64: | 429 case kAstF64: |
| 414 return MachineType::Float64(); | 430 return MachineType::Float64(); |
| 431 case kAstS128: |
| 432 return MachineType::Simd128(); |
| 415 case kAstStmt: | 433 case kAstStmt: |
| 416 return MachineType::None(); | 434 return MachineType::None(); |
| 417 default: | 435 default: |
| 418 UNREACHABLE(); | 436 UNREACHABLE(); |
| 419 return MachineType::None(); | 437 return MachineType::None(); |
| 420 } | 438 } |
| 421 } | 439 } |
| 422 | 440 |
| 423 static LocalType LocalTypeFor(MachineType type) { | 441 static LocalType LocalTypeFor(MachineType type) { |
| 424 if (type == MachineType::Int8()) { | 442 if (type == MachineType::Int8()) { |
| 425 return kAstI32; | 443 return kAstI32; |
| 426 } else if (type == MachineType::Uint8()) { | 444 } else if (type == MachineType::Uint8()) { |
| 427 return kAstI32; | 445 return kAstI32; |
| 428 } else if (type == MachineType::Int16()) { | 446 } else if (type == MachineType::Int16()) { |
| 429 return kAstI32; | 447 return kAstI32; |
| 430 } else if (type == MachineType::Uint16()) { | 448 } else if (type == MachineType::Uint16()) { |
| 431 return kAstI32; | 449 return kAstI32; |
| 432 } else if (type == MachineType::Int32()) { | 450 } else if (type == MachineType::Int32()) { |
| 433 return kAstI32; | 451 return kAstI32; |
| 434 } else if (type == MachineType::Uint32()) { | 452 } else if (type == MachineType::Uint32()) { |
| 435 return kAstI32; | 453 return kAstI32; |
| 436 } else if (type == MachineType::Int64()) { | 454 } else if (type == MachineType::Int64()) { |
| 437 return kAstI64; | 455 return kAstI64; |
| 438 } else if (type == MachineType::Uint64()) { | 456 } else if (type == MachineType::Uint64()) { |
| 439 return kAstI64; | 457 return kAstI64; |
| 440 } else if (type == MachineType::Float32()) { | 458 } else if (type == MachineType::Float32()) { |
| 441 return kAstF32; | 459 return kAstF32; |
| 442 } else if (type == MachineType::Float64()) { | 460 } else if (type == MachineType::Float64()) { |
| 443 return kAstF64; | 461 return kAstF64; |
| 462 } else if (type == MachineType::Simd128()) { |
| 463 return kAstS128; |
| 444 } else { | 464 } else { |
| 445 UNREACHABLE(); | 465 UNREACHABLE(); |
| 446 return kAstI32; | 466 return kAstI32; |
| 447 } | 467 } |
| 448 } | 468 } |
| 449 | 469 |
| 450 static WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) { | 470 static WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) { |
| 451 if (type == MachineType::Int8()) { | 471 if (type == MachineType::Int8()) { |
| 452 return store ? kExprI32StoreMem8 : kExprI32LoadMem8S; | 472 return store ? kExprI32StoreMem8 : kExprI32LoadMem8S; |
| 453 } else if (type == MachineType::Uint8()) { | 473 } else if (type == MachineType::Uint8()) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 477 static char ShortNameOf(LocalType type) { | 497 static char ShortNameOf(LocalType type) { |
| 478 switch (type) { | 498 switch (type) { |
| 479 case kAstI32: | 499 case kAstI32: |
| 480 return 'i'; | 500 return 'i'; |
| 481 case kAstI64: | 501 case kAstI64: |
| 482 return 'l'; | 502 return 'l'; |
| 483 case kAstF32: | 503 case kAstF32: |
| 484 return 'f'; | 504 return 'f'; |
| 485 case kAstF64: | 505 case kAstF64: |
| 486 return 'd'; | 506 return 'd'; |
| 507 case kAstS128: |
| 508 return 's'; |
| 487 case kAstStmt: | 509 case kAstStmt: |
| 488 return 'v'; | 510 return 'v'; |
| 489 case kAstEnd: | 511 case kAstEnd: |
| 490 return 'x'; | 512 return 'x'; |
| 491 default: | 513 default: |
| 492 UNREACHABLE(); | 514 UNREACHABLE(); |
| 493 return '?'; | 515 return '?'; |
| 494 } | 516 } |
| 495 } | 517 } |
| 496 | 518 |
| 497 static const char* TypeName(LocalType type) { | 519 static const char* TypeName(LocalType type) { |
| 498 switch (type) { | 520 switch (type) { |
| 499 case kAstI32: | 521 case kAstI32: |
| 500 return "i32"; | 522 return "i32"; |
| 501 case kAstI64: | 523 case kAstI64: |
| 502 return "i64"; | 524 return "i64"; |
| 503 case kAstF32: | 525 case kAstF32: |
| 504 return "f32"; | 526 return "f32"; |
| 505 case kAstF64: | 527 case kAstF64: |
| 506 return "f64"; | 528 return "f64"; |
| 529 case kAstS128: |
| 530 return "s128"; |
| 507 case kAstStmt: | 531 case kAstStmt: |
| 508 return "<stmt>"; | 532 return "<stmt>"; |
| 509 case kAstEnd: | 533 case kAstEnd: |
| 510 return "<end>"; | 534 return "<end>"; |
| 511 default: | 535 default: |
| 512 return "<unknown>"; | 536 return "<unknown>"; |
| 513 } | 537 } |
| 514 } | 538 } |
| 515 }; | 539 }; |
| 516 } // namespace wasm | 540 } // namespace wasm |
| 517 } // namespace internal | 541 } // namespace internal |
| 518 } // namespace v8 | 542 } // namespace v8 |
| 519 | 543 |
| 520 #endif // V8_WASM_OPCODES_H_ | 544 #endif // V8_WASM_OPCODES_H_ |
| OLD | NEW |