WasmConstants.h (31758B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * 4 * Copyright 2015 Mozilla Foundation 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 #ifndef wasm_constants_h 20 #define wasm_constants_h 21 22 #include <stdint.h> 23 24 #include "wasm/WasmBuiltinModuleGenerated.h" 25 #include "wasm/WasmSerialize.h" 26 27 namespace js { 28 namespace wasm { 29 30 static const uint32_t MagicNumber = 0x6d736100; // "\0asm" 31 static const uint32_t EncodingVersion = 0x01; 32 33 enum class SectionId { 34 Custom = 0, 35 Type = 1, 36 Import = 2, 37 Function = 3, 38 Table = 4, 39 Memory = 5, 40 Global = 6, 41 Export = 7, 42 Start = 8, 43 Elem = 9, 44 Code = 10, 45 Data = 11, 46 DataCount = 12, 47 Tag = 13, 48 }; 49 50 // WebAssembly type encodings are all single-byte negative SLEB128s, hence: 51 // forall tc:TypeCode. ((tc & SLEB128SignMask) == SLEB128SignBit 52 static const uint8_t SLEB128SignMask = 0xc0; 53 static const uint8_t SLEB128SignBit = 0x40; 54 55 enum class TypeCode { 56 57 // If more "simple primitive" (non-reference, non-constructor, 58 // non-special-purpose) types are added here then you MUST update 59 // LowestPrimitiveTypeCode, below. 60 61 I32 = 0x7f, // SLEB128(-0x01) 62 I64 = 0x7e, // SLEB128(-0x02) 63 F32 = 0x7d, // SLEB128(-0x03) 64 F64 = 0x7c, // SLEB128(-0x04) 65 V128 = 0x7b, // SLEB128(-0x05) 66 67 I8 = 0x78, // SLEB128(-0x08) 68 I16 = 0x77, // SLEB128(-0x09) 69 70 // A function pointer with any signature 71 FuncRef = 0x70, // SLEB128(-0x10) 72 73 // A reference to any host value. 74 ExternRef = 0x6f, // SLEB128(-0x11) 75 76 // A reference to any wasm gc value. 77 AnyRef = 0x6e, // SLEB128(-0x12) 78 79 // A reference to a struct/array value. 80 EqRef = 0x6d, // SLEB128(-0x13) 81 82 // Type constructor for nullable reference types. 83 NullableRef = 0x63, // SLEB128(-0x1D) 84 85 // Type constructor for non-nullable reference types. 86 Ref = 0x64, // SLEB128(-0x1C) 87 88 // A reference to an unboxed 31-bit integer. 89 I31Ref = 0x6c, // SLEB128(-0x14) 90 91 // A null reference in the extern hierarchy. 92 NullExternRef = 0x72, // SLEB128(-0x0E) 93 94 // A null reference in the func hierarchy. 95 NullFuncRef = 0x73, // SLEB128(-0x0D) 96 97 // A null reference in the exn hierarchy. 98 NullExnRef = 0x74, // SLEB128(-0x0C) 99 100 // A reference to any struct value. 101 StructRef = 0x6b, // SLEB128(-0x15) 102 103 // A reference to any array value. 104 ArrayRef = 0x6a, // SLEB128(-0x16) 105 106 // A reference to an exception value. 107 ExnRef = 0x69, // SLEB128(-0x17) 108 109 // A null reference in the any hierarchy. 110 NullAnyRef = 0x71, // SLEB128(-0x0F) 111 112 // Type constructor for function types 113 Func = 0x60, // SLEB128(-0x20) 114 115 // Type constructor for structure types - gc proposal 116 Struct = 0x5f, // SLEB128(-0x21) 117 118 // Type constructor for array types - gc proposal 119 Array = 0x5e, // SLEB128(-0x22) 120 121 // Value for non-nullable type present. 122 TableHasInitExpr = 0x40, 123 124 // The 'empty' case of blocktype. 125 BlockVoid = 0x40, // SLEB128(-0x40) 126 127 // Type constructor for recursion groups - gc proposal 128 RecGroup = 0x4e, // SLEB128(-0x31) 129 130 // Type prefix for parent types - gc proposal 131 SubNoFinalType = 0x50, // SLEB128(-0x30) 132 133 // Type prefix for final types - gc proposal 134 SubFinalType = 0x4f, // SLEB128(-0x32) 135 136 Limit = 0x80 137 }; 138 139 // This is the lowest-valued TypeCode that is a primitive type, used in 140 // UnpackTypeCodeTypeAbstracted(). If primitive typecodes are added below any 141 // reference typecode then the logic in that function MUST change. 142 143 static constexpr TypeCode LowestPrimitiveTypeCode = TypeCode::I16; 144 145 // An arbitrary reference type used as the result of 146 // UnpackTypeCodeTypeAbstracted() when a value type is a reference. 147 148 static constexpr TypeCode AbstractReferenceTypeCode = TypeCode::ExternRef; 149 150 // A type code used to represent (ref null? T) whether or not the type 151 // is encoded with 'Ref' or 'NullableRef'. 152 153 static constexpr TypeCode AbstractTypeRefCode = TypeCode::Ref; 154 155 // wasm traps are machine instructions that can fail to execute for reasons 156 // that have to do with some condition in the wasm that they were compiled 157 // from. The failure manifests as a (machine-level) exception of some sort, 158 // which leads execution to a signal handler, and is eventually reported as a 159 // WebAssembly.RuntimeError. Generated code may also jump to a Trap 160 // symbolically, passing the bytecode offset to report as the trap offset. 161 // The generated jump will be bound to a tiny stub which fills the offset and 162 // then jumps to a per-Trap shared stub at the end of the module. 163 // 164 // Traps are described by a value from Trap and, in debug builds only, a value 165 // from TrapInsn. 166 // 167 // * A Trap indicates why the trap has happened and is used to construct the 168 // WebAssembly.Runtime message. 169 // 170 // * A TrapMachineInsn (not defined in this file) describes roughly what kind 171 // of machine instruction has caused the trap. This is used only for 172 // validation of trap placement in debug builds, in 173 // ModuleGenerator::finishMetadataTier, and is not necessary for execution 174 // of wasm code. 175 176 enum class Trap { 177 // The Unreachable opcode has been executed. 178 Unreachable, 179 // An integer arithmetic operation led to an overflow. 180 IntegerOverflow, 181 // Trying to coerce NaN to an integer. 182 InvalidConversionToInteger, 183 // Integer division by zero. 184 IntegerDivideByZero, 185 // Out of bounds on wasm memory accesses. 186 OutOfBounds, 187 // Unaligned on wasm atomic accesses; also used for non-standard ARM 188 // unaligned access faults. 189 UnalignedAccess, 190 // call_indirect to null. 191 IndirectCallToNull, 192 // call_indirect signature mismatch. 193 IndirectCallBadSig, 194 // Dereference null pointer in operation on (Ref T) 195 NullPointerDereference, 196 // Failed to cast a (Ref T) in a ref.cast instruction 197 BadCast, 198 199 // The internal stack space was exhausted. For compatibility, this throws 200 // the same over-recursed error as JS. 201 StackOverflow, 202 203 // The wasm execution has potentially run too long and the engine must call 204 // CheckForInterrupt(). This trap is resumable. 205 CheckInterrupt, 206 207 // Signal an error that was reported in C++ code. 208 ThrowReported, 209 210 Limit 211 }; 212 213 enum class DefinitionKind { 214 Function = 0x00, 215 Table = 0x01, 216 Memory = 0x02, 217 Global = 0x03, 218 Tag = 0x04, 219 }; 220 221 enum class GlobalTypeImmediate { IsMutable = 0x1, AllowedMask = 0x1 }; 222 223 enum class LimitsFlags { 224 Default = 0x0, 225 HasMaximum = 0x1, 226 IsShared = 0x2, 227 IsI64 = 0x4, 228 #ifdef ENABLE_WASM_CUSTOM_PAGE_SIZES 229 HasCustomPageSize = 0x8, 230 #endif 231 }; 232 233 enum class LimitsMask { 234 Table = uint8_t(LimitsFlags::HasMaximum) | uint8_t(LimitsFlags::IsI64), 235 #ifdef ENABLE_WASM_CUSTOM_PAGE_SIZES 236 Memory = uint8_t(LimitsFlags::HasMaximum) | uint8_t(LimitsFlags::IsShared) | 237 uint8_t(LimitsFlags::IsI64) | 238 uint8_t(LimitsFlags::HasCustomPageSize), 239 #else 240 Memory = uint8_t(LimitsFlags::HasMaximum) | uint8_t(LimitsFlags::IsShared) | 241 uint8_t(LimitsFlags::IsI64), 242 #endif 243 }; 244 245 enum class DataSegmentKind { 246 Active = 0x00, 247 Passive = 0x01, 248 ActiveWithMemoryIndex = 0x02 249 }; 250 251 enum class ElemSegmentKind : uint32_t { 252 Active = 0x0, 253 Passive = 0x1, 254 ActiveWithTableIndex = 0x2, 255 Declared = 0x3, 256 }; 257 258 enum class ElemSegmentPayload : uint32_t { 259 Indices = 0x0, 260 Expressions = 0x4, 261 }; 262 263 enum class TagKind { 264 Exception = 0x0, 265 }; 266 267 enum class Op { 268 // Control flow operators 269 Unreachable = 0x00, 270 Nop = 0x01, 271 Block = 0x02, 272 Loop = 0x03, 273 If = 0x04, 274 Else = 0x05, 275 Try = 0x06, 276 Catch = 0x07, 277 Throw = 0x08, 278 Rethrow = 0x09, 279 ThrowRef = 0x0a, 280 End = 0x0b, 281 Br = 0x0c, 282 BrIf = 0x0d, 283 BrTable = 0x0e, 284 Return = 0x0f, 285 286 // Call operators 287 Call = 0x10, 288 CallIndirect = 0x11, 289 ReturnCall = 0x12, 290 ReturnCallIndirect = 0x13, 291 CallRef = 0x14, 292 ReturnCallRef = 0x15, 293 294 // Additional exception operators 295 Delegate = 0x18, 296 CatchAll = 0x19, 297 298 // Parametric operators 299 Drop = 0x1a, 300 SelectNumeric = 0x1b, 301 SelectTyped = 0x1c, 302 303 // Additional exception operators 304 TryTable = 0x1f, 305 306 // Variable access 307 LocalGet = 0x20, 308 LocalSet = 0x21, 309 LocalTee = 0x22, 310 GlobalGet = 0x23, 311 GlobalSet = 0x24, 312 TableGet = 0x25, // Reftypes, 313 TableSet = 0x26, // per proposal as of February 2019 314 315 // Memory-related operators 316 I32Load = 0x28, 317 I64Load = 0x29, 318 F32Load = 0x2a, 319 F64Load = 0x2b, 320 I32Load8S = 0x2c, 321 I32Load8U = 0x2d, 322 I32Load16S = 0x2e, 323 I32Load16U = 0x2f, 324 I64Load8S = 0x30, 325 I64Load8U = 0x31, 326 I64Load16S = 0x32, 327 I64Load16U = 0x33, 328 I64Load32S = 0x34, 329 I64Load32U = 0x35, 330 I32Store = 0x36, 331 I64Store = 0x37, 332 F32Store = 0x38, 333 F64Store = 0x39, 334 I32Store8 = 0x3a, 335 I32Store16 = 0x3b, 336 I64Store8 = 0x3c, 337 I64Store16 = 0x3d, 338 I64Store32 = 0x3e, 339 MemorySize = 0x3f, 340 MemoryGrow = 0x40, 341 342 // Constants 343 I32Const = 0x41, 344 I64Const = 0x42, 345 F32Const = 0x43, 346 F64Const = 0x44, 347 348 // Comparison operators 349 I32Eqz = 0x45, 350 I32Eq = 0x46, 351 I32Ne = 0x47, 352 I32LtS = 0x48, 353 I32LtU = 0x49, 354 I32GtS = 0x4a, 355 I32GtU = 0x4b, 356 I32LeS = 0x4c, 357 I32LeU = 0x4d, 358 I32GeS = 0x4e, 359 I32GeU = 0x4f, 360 I64Eqz = 0x50, 361 I64Eq = 0x51, 362 I64Ne = 0x52, 363 I64LtS = 0x53, 364 I64LtU = 0x54, 365 I64GtS = 0x55, 366 I64GtU = 0x56, 367 I64LeS = 0x57, 368 I64LeU = 0x58, 369 I64GeS = 0x59, 370 I64GeU = 0x5a, 371 F32Eq = 0x5b, 372 F32Ne = 0x5c, 373 F32Lt = 0x5d, 374 F32Gt = 0x5e, 375 F32Le = 0x5f, 376 F32Ge = 0x60, 377 F64Eq = 0x61, 378 F64Ne = 0x62, 379 F64Lt = 0x63, 380 F64Gt = 0x64, 381 F64Le = 0x65, 382 F64Ge = 0x66, 383 384 // Numeric operators 385 I32Clz = 0x67, 386 I32Ctz = 0x68, 387 I32Popcnt = 0x69, 388 I32Add = 0x6a, 389 I32Sub = 0x6b, 390 I32Mul = 0x6c, 391 I32DivS = 0x6d, 392 I32DivU = 0x6e, 393 I32RemS = 0x6f, 394 I32RemU = 0x70, 395 I32And = 0x71, 396 I32Or = 0x72, 397 I32Xor = 0x73, 398 I32Shl = 0x74, 399 I32ShrS = 0x75, 400 I32ShrU = 0x76, 401 I32Rotl = 0x77, 402 I32Rotr = 0x78, 403 I64Clz = 0x79, 404 I64Ctz = 0x7a, 405 I64Popcnt = 0x7b, 406 I64Add = 0x7c, 407 I64Sub = 0x7d, 408 I64Mul = 0x7e, 409 I64DivS = 0x7f, 410 I64DivU = 0x80, 411 I64RemS = 0x81, 412 I64RemU = 0x82, 413 I64And = 0x83, 414 I64Or = 0x84, 415 I64Xor = 0x85, 416 I64Shl = 0x86, 417 I64ShrS = 0x87, 418 I64ShrU = 0x88, 419 I64Rotl = 0x89, 420 I64Rotr = 0x8a, 421 F32Abs = 0x8b, 422 F32Neg = 0x8c, 423 F32Ceil = 0x8d, 424 F32Floor = 0x8e, 425 F32Trunc = 0x8f, 426 F32Nearest = 0x90, 427 F32Sqrt = 0x91, 428 F32Add = 0x92, 429 F32Sub = 0x93, 430 F32Mul = 0x94, 431 F32Div = 0x95, 432 F32Min = 0x96, 433 F32Max = 0x97, 434 F32CopySign = 0x98, 435 F64Abs = 0x99, 436 F64Neg = 0x9a, 437 F64Ceil = 0x9b, 438 F64Floor = 0x9c, 439 F64Trunc = 0x9d, 440 F64Nearest = 0x9e, 441 F64Sqrt = 0x9f, 442 F64Add = 0xa0, 443 F64Sub = 0xa1, 444 F64Mul = 0xa2, 445 F64Div = 0xa3, 446 F64Min = 0xa4, 447 F64Max = 0xa5, 448 F64CopySign = 0xa6, 449 450 // Conversions 451 I32WrapI64 = 0xa7, 452 I32TruncF32S = 0xa8, 453 I32TruncF32U = 0xa9, 454 I32TruncF64S = 0xaa, 455 I32TruncF64U = 0xab, 456 I64ExtendI32S = 0xac, 457 I64ExtendI32U = 0xad, 458 I64TruncF32S = 0xae, 459 I64TruncF32U = 0xaf, 460 I64TruncF64S = 0xb0, 461 I64TruncF64U = 0xb1, 462 F32ConvertI32S = 0xb2, 463 F32ConvertI32U = 0xb3, 464 F32ConvertI64S = 0xb4, 465 F32ConvertI64U = 0xb5, 466 F32DemoteF64 = 0xb6, 467 F64ConvertI32S = 0xb7, 468 F64ConvertI32U = 0xb8, 469 F64ConvertI64S = 0xb9, 470 F64ConvertI64U = 0xba, 471 F64PromoteF32 = 0xbb, 472 473 // Reinterpretations 474 I32ReinterpretF32 = 0xbc, 475 I64ReinterpretF64 = 0xbd, 476 F32ReinterpretI32 = 0xbe, 477 F64ReinterpretI64 = 0xbf, 478 479 // Sign extension 480 I32Extend8S = 0xc0, 481 I32Extend16S = 0xc1, 482 I64Extend8S = 0xc2, 483 I64Extend16S = 0xc3, 484 I64Extend32S = 0xc4, 485 486 // Reference types 487 RefNull = 0xd0, 488 RefIsNull = 0xd1, 489 RefFunc = 0xd2, 490 491 // Function references 492 RefAsNonNull = 0xd4, 493 BrOnNull = 0xd5, 494 495 // GC (experimental) 496 RefEq = 0xd3, 497 498 // Function references 499 BrOnNonNull = 0xd6, 500 501 FirstPrefix = 0xfa, 502 GcPrefix = 0xfb, 503 MiscPrefix = 0xfc, 504 SimdPrefix = 0xfd, 505 ThreadPrefix = 0xfe, 506 MozPrefix = 0xff, 507 508 Limit = 0x100 509 }; 510 511 inline bool IsPrefixByte(uint8_t b) { return b >= uint8_t(Op::FirstPrefix); } 512 513 // Opcodes in the GC opcode space. 514 enum class GcOp { 515 // Structure operations 516 StructNew = 0x0, 517 StructNewDefault = 0x1, 518 StructGet = 0x02, 519 StructGetS = 0x03, 520 StructGetU = 0x04, 521 StructSet = 0x05, 522 523 // Array operations 524 ArrayNew = 0x6, 525 ArrayNewDefault = 0x7, 526 ArrayNewFixed = 0x8, 527 ArrayNewData = 0x9, 528 ArrayNewElem = 0xa, 529 ArrayGet = 0xb, 530 ArrayGetS = 0xc, 531 ArrayGetU = 0xd, 532 ArraySet = 0xe, 533 ArrayLen = 0xf, 534 ArrayFill = 0x10, 535 ArrayCopy = 0x11, 536 ArrayInitData = 0x12, 537 ArrayInitElem = 0x13, 538 539 // Ref operations 540 RefTest = 0x14, 541 RefTestNull = 0x15, 542 RefCast = 0x16, 543 RefCastNull = 0x17, 544 BrOnCast = 0x18, 545 BrOnCastFail = 0x19, 546 547 // Extern/any coercion operations 548 AnyConvertExtern = 0x1a, 549 ExternConvertAny = 0x1b, 550 551 // I31 operations 552 RefI31 = 0x1c, 553 I31GetS = 0x1d, 554 I31GetU = 0x1e, 555 556 Limit 557 }; 558 559 // Opcode list from the SIMD proposal post-renumbering in May, 2020. 560 561 // Opcodes with suffix 'Experimental' are proposed but not standardized, and are 562 // compatible with those same opcodes in V8. No opcode labeled 'Experimental' 563 // will ship in a Release build where SIMD is enabled by default. 564 565 enum class SimdOp { 566 V128Load = 0x00, 567 V128Load8x8S = 0x01, 568 V128Load8x8U = 0x02, 569 V128Load16x4S = 0x03, 570 V128Load16x4U = 0x04, 571 V128Load32x2S = 0x05, 572 V128Load32x2U = 0x06, 573 V128Load8Splat = 0x07, 574 V128Load16Splat = 0x08, 575 V128Load32Splat = 0x09, 576 V128Load64Splat = 0x0a, 577 V128Store = 0x0b, 578 V128Const = 0x0c, 579 I8x16Shuffle = 0x0d, 580 I8x16Swizzle = 0x0e, 581 I8x16Splat = 0x0f, 582 I16x8Splat = 0x10, 583 I32x4Splat = 0x11, 584 I64x2Splat = 0x12, 585 F32x4Splat = 0x13, 586 F64x2Splat = 0x14, 587 I8x16ExtractLaneS = 0x15, 588 I8x16ExtractLaneU = 0x16, 589 I8x16ReplaceLane = 0x17, 590 I16x8ExtractLaneS = 0x18, 591 I16x8ExtractLaneU = 0x19, 592 I16x8ReplaceLane = 0x1a, 593 I32x4ExtractLane = 0x1b, 594 I32x4ReplaceLane = 0x1c, 595 I64x2ExtractLane = 0x1d, 596 I64x2ReplaceLane = 0x1e, 597 F32x4ExtractLane = 0x1f, 598 F32x4ReplaceLane = 0x20, 599 F64x2ExtractLane = 0x21, 600 F64x2ReplaceLane = 0x22, 601 I8x16Eq = 0x23, 602 I8x16Ne = 0x24, 603 I8x16LtS = 0x25, 604 I8x16LtU = 0x26, 605 I8x16GtS = 0x27, 606 I8x16GtU = 0x28, 607 I8x16LeS = 0x29, 608 I8x16LeU = 0x2a, 609 I8x16GeS = 0x2b, 610 I8x16GeU = 0x2c, 611 I16x8Eq = 0x2d, 612 I16x8Ne = 0x2e, 613 I16x8LtS = 0x2f, 614 I16x8LtU = 0x30, 615 I16x8GtS = 0x31, 616 I16x8GtU = 0x32, 617 I16x8LeS = 0x33, 618 I16x8LeU = 0x34, 619 I16x8GeS = 0x35, 620 I16x8GeU = 0x36, 621 I32x4Eq = 0x37, 622 I32x4Ne = 0x38, 623 I32x4LtS = 0x39, 624 I32x4LtU = 0x3a, 625 I32x4GtS = 0x3b, 626 I32x4GtU = 0x3c, 627 I32x4LeS = 0x3d, 628 I32x4LeU = 0x3e, 629 I32x4GeS = 0x3f, 630 I32x4GeU = 0x40, 631 F32x4Eq = 0x41, 632 F32x4Ne = 0x42, 633 F32x4Lt = 0x43, 634 F32x4Gt = 0x44, 635 F32x4Le = 0x45, 636 F32x4Ge = 0x46, 637 F64x2Eq = 0x47, 638 F64x2Ne = 0x48, 639 F64x2Lt = 0x49, 640 F64x2Gt = 0x4a, 641 F64x2Le = 0x4b, 642 F64x2Ge = 0x4c, 643 V128Not = 0x4d, 644 V128And = 0x4e, 645 V128AndNot = 0x4f, 646 V128Or = 0x50, 647 V128Xor = 0x51, 648 V128Bitselect = 0x52, 649 V128AnyTrue = 0x53, 650 V128Load8Lane = 0x54, 651 V128Load16Lane = 0x55, 652 V128Load32Lane = 0x56, 653 V128Load64Lane = 0x57, 654 V128Store8Lane = 0x58, 655 V128Store16Lane = 0x59, 656 V128Store32Lane = 0x5a, 657 V128Store64Lane = 0x5b, 658 V128Load32Zero = 0x5c, 659 V128Load64Zero = 0x5d, 660 F32x4DemoteF64x2Zero = 0x5e, 661 F64x2PromoteLowF32x4 = 0x5f, 662 I8x16Abs = 0x60, 663 I8x16Neg = 0x61, 664 I8x16Popcnt = 0x62, 665 I8x16AllTrue = 0x63, 666 I8x16Bitmask = 0x64, 667 I8x16NarrowI16x8S = 0x65, 668 I8x16NarrowI16x8U = 0x66, 669 F32x4Ceil = 0x67, 670 F32x4Floor = 0x68, 671 F32x4Trunc = 0x69, 672 F32x4Nearest = 0x6a, 673 I8x16Shl = 0x6b, 674 I8x16ShrS = 0x6c, 675 I8x16ShrU = 0x6d, 676 I8x16Add = 0x6e, 677 I8x16AddSatS = 0x6f, 678 I8x16AddSatU = 0x70, 679 I8x16Sub = 0x71, 680 I8x16SubSatS = 0x72, 681 I8x16SubSatU = 0x73, 682 F64x2Ceil = 0x74, 683 F64x2Floor = 0x75, 684 I8x16MinS = 0x76, 685 I8x16MinU = 0x77, 686 I8x16MaxS = 0x78, 687 I8x16MaxU = 0x79, 688 F64x2Trunc = 0x7a, 689 I8x16AvgrU = 0x7b, 690 I16x8ExtaddPairwiseI8x16S = 0x7c, 691 I16x8ExtaddPairwiseI8x16U = 0x7d, 692 I32x4ExtaddPairwiseI16x8S = 0x7e, 693 I32x4ExtaddPairwiseI16x8U = 0x7f, 694 I16x8Abs = 0x80, 695 I16x8Neg = 0x81, 696 I16x8Q15MulrSatS = 0x82, 697 I16x8AllTrue = 0x83, 698 I16x8Bitmask = 0x84, 699 I16x8NarrowI32x4S = 0x85, 700 I16x8NarrowI32x4U = 0x86, 701 I16x8ExtendLowI8x16S = 0x87, 702 I16x8ExtendHighI8x16S = 0x88, 703 I16x8ExtendLowI8x16U = 0x89, 704 I16x8ExtendHighI8x16U = 0x8a, 705 I16x8Shl = 0x8b, 706 I16x8ShrS = 0x8c, 707 I16x8ShrU = 0x8d, 708 I16x8Add = 0x8e, 709 I16x8AddSatS = 0x8f, 710 I16x8AddSatU = 0x90, 711 I16x8Sub = 0x91, 712 I16x8SubSatS = 0x92, 713 I16x8SubSatU = 0x93, 714 F64x2Nearest = 0x94, 715 I16x8Mul = 0x95, 716 I16x8MinS = 0x96, 717 I16x8MinU = 0x97, 718 I16x8MaxS = 0x98, 719 I16x8MaxU = 0x99, 720 // Unused = 0x9a 721 I16x8AvgrU = 0x9b, 722 I16x8ExtmulLowI8x16S = 0x9c, 723 I16x8ExtmulHighI8x16S = 0x9d, 724 I16x8ExtmulLowI8x16U = 0x9e, 725 I16x8ExtmulHighI8x16U = 0x9f, 726 I32x4Abs = 0xa0, 727 I32x4Neg = 0xa1, 728 // Unused = 0xa2 729 I32x4AllTrue = 0xa3, 730 I32x4Bitmask = 0xa4, 731 // Unused = 0xa5 732 // Unused = 0xa6 733 I32x4ExtendLowI16x8S = 0xa7, 734 I32x4ExtendHighI16x8S = 0xa8, 735 I32x4ExtendLowI16x8U = 0xa9, 736 I32x4ExtendHighI16x8U = 0xaa, 737 I32x4Shl = 0xab, 738 I32x4ShrS = 0xac, 739 I32x4ShrU = 0xad, 740 I32x4Add = 0xae, 741 // Unused = 0xaf 742 // Unused = 0xb0 743 I32x4Sub = 0xb1, 744 // Unused = 0xb2 745 // Unused = 0xb3 746 // Unused = 0xb4 747 I32x4Mul = 0xb5, 748 I32x4MinS = 0xb6, 749 I32x4MinU = 0xb7, 750 I32x4MaxS = 0xb8, 751 I32x4MaxU = 0xb9, 752 I32x4DotI16x8S = 0xba, 753 // Unused = 0xbb 754 I32x4ExtmulLowI16x8S = 0xbc, 755 I32x4ExtmulHighI16x8S = 0xbd, 756 I32x4ExtmulLowI16x8U = 0xbe, 757 I32x4ExtmulHighI16x8U = 0xbf, 758 I64x2Abs = 0xc0, 759 I64x2Neg = 0xc1, 760 // AnyTrue = 0xc2 761 I64x2AllTrue = 0xc3, 762 I64x2Bitmask = 0xc4, 763 // Unused = 0xc5 764 // Unused = 0xc6 765 I64x2ExtendLowI32x4S = 0xc7, 766 I64x2ExtendHighI32x4S = 0xc8, 767 I64x2ExtendLowI32x4U = 0xc9, 768 I64x2ExtendHighI32x4U = 0xca, 769 I64x2Shl = 0xcb, 770 I64x2ShrS = 0xcc, 771 I64x2ShrU = 0xcd, 772 I64x2Add = 0xce, 773 // Unused = 0xcf 774 // Unused = 0xd0 775 I64x2Sub = 0xd1, 776 // Unused = 0xd2 777 // Unused = 0xd3 778 // Unused = 0xd4 779 I64x2Mul = 0xd5, 780 I64x2Eq = 0xd6, 781 I64x2Ne = 0xd7, 782 I64x2LtS = 0xd8, 783 I64x2GtS = 0xd9, 784 I64x2LeS = 0xda, 785 I64x2GeS = 0xdb, 786 I64x2ExtmulLowI32x4S = 0xdc, 787 I64x2ExtmulHighI32x4S = 0xdd, 788 I64x2ExtmulLowI32x4U = 0xde, 789 I64x2ExtmulHighI32x4U = 0xdf, 790 F32x4Abs = 0xe0, 791 F32x4Neg = 0xe1, 792 // Unused = 0xe2 793 F32x4Sqrt = 0xe3, 794 F32x4Add = 0xe4, 795 F32x4Sub = 0xe5, 796 F32x4Mul = 0xe6, 797 F32x4Div = 0xe7, 798 F32x4Min = 0xe8, 799 F32x4Max = 0xe9, 800 F32x4PMin = 0xea, 801 F32x4PMax = 0xeb, 802 F64x2Abs = 0xec, 803 F64x2Neg = 0xed, 804 // Unused = 0xee 805 F64x2Sqrt = 0xef, 806 F64x2Add = 0xf0, 807 F64x2Sub = 0xf1, 808 F64x2Mul = 0xf2, 809 F64x2Div = 0xf3, 810 F64x2Min = 0xf4, 811 F64x2Max = 0xf5, 812 F64x2PMin = 0xf6, 813 F64x2PMax = 0xf7, 814 I32x4TruncSatF32x4S = 0xf8, 815 I32x4TruncSatF32x4U = 0xf9, 816 F32x4ConvertI32x4S = 0xfa, 817 F32x4ConvertI32x4U = 0xfb, 818 I32x4TruncSatF64x2SZero = 0xfc, 819 I32x4TruncSatF64x2UZero = 0xfd, 820 F64x2ConvertLowI32x4S = 0xfe, 821 F64x2ConvertLowI32x4U = 0xff, 822 I8x16RelaxedSwizzle = 0x100, 823 I32x4RelaxedTruncF32x4S = 0x101, 824 I32x4RelaxedTruncF32x4U = 0x102, 825 I32x4RelaxedTruncF64x2SZero = 0x103, 826 I32x4RelaxedTruncF64x2UZero = 0x104, 827 F32x4RelaxedMadd = 0x105, 828 F32x4RelaxedNmadd = 0x106, 829 F64x2RelaxedMadd = 0x107, 830 F64x2RelaxedNmadd = 0x108, 831 I8x16RelaxedLaneSelect = 0x109, 832 I16x8RelaxedLaneSelect = 0x10a, 833 I32x4RelaxedLaneSelect = 0x10b, 834 I64x2RelaxedLaneSelect = 0x10c, 835 F32x4RelaxedMin = 0x10d, 836 F32x4RelaxedMax = 0x10e, 837 F64x2RelaxedMin = 0x10f, 838 F64x2RelaxedMax = 0x110, 839 I16x8RelaxedQ15MulrS = 0x111, 840 I16x8RelaxedDotI8x16I7x16S = 0x112, 841 I32x4RelaxedDotI8x16I7x16AddS = 0x113, 842 843 // Reserved for Relaxed SIMD = 0x114-0x12f 844 845 // Unused = 0x130 and up 846 847 // Mozilla extensions 848 MozPMADDUBSW = 0x201, 849 850 Limit 851 }; 852 853 // Opcodes in the "miscellaneous" opcode space. 854 enum class MiscOp { 855 // Saturating float-to-int conversions 856 I32TruncSatF32S = 0x00, 857 I32TruncSatF32U = 0x01, 858 I32TruncSatF64S = 0x02, 859 I32TruncSatF64U = 0x03, 860 I64TruncSatF32S = 0x04, 861 I64TruncSatF32U = 0x05, 862 I64TruncSatF64S = 0x06, 863 I64TruncSatF64U = 0x07, 864 865 // Bulk memory operations, per proposal as of February 2019. 866 MemoryInit = 0x08, 867 DataDrop = 0x09, 868 MemoryCopy = 0x0a, 869 MemoryFill = 0x0b, 870 TableInit = 0x0c, 871 ElemDrop = 0x0d, 872 TableCopy = 0x0e, 873 874 // Reftypes, per proposal as of February 2019. 875 TableGrow = 0x0f, 876 TableSize = 0x10, 877 TableFill = 0x11, 878 879 MemoryDiscard = 0x12, 880 881 Limit 882 }; 883 884 // Opcodes from threads proposal as of June 30, 2017 885 enum class ThreadOp { 886 // Wait and notify 887 Notify = 0x00, 888 I32Wait = 0x01, 889 I64Wait = 0x02, 890 Fence = 0x03, 891 892 // Load and store 893 I32AtomicLoad = 0x10, 894 I64AtomicLoad = 0x11, 895 I32AtomicLoad8U = 0x12, 896 I32AtomicLoad16U = 0x13, 897 I64AtomicLoad8U = 0x14, 898 I64AtomicLoad16U = 0x15, 899 I64AtomicLoad32U = 0x16, 900 I32AtomicStore = 0x17, 901 I64AtomicStore = 0x18, 902 I32AtomicStore8U = 0x19, 903 I32AtomicStore16U = 0x1a, 904 I64AtomicStore8U = 0x1b, 905 I64AtomicStore16U = 0x1c, 906 I64AtomicStore32U = 0x1d, 907 908 // Read-modify-write operations 909 I32AtomicAdd = 0x1e, 910 I64AtomicAdd = 0x1f, 911 I32AtomicAdd8U = 0x20, 912 I32AtomicAdd16U = 0x21, 913 I64AtomicAdd8U = 0x22, 914 I64AtomicAdd16U = 0x23, 915 I64AtomicAdd32U = 0x24, 916 917 I32AtomicSub = 0x25, 918 I64AtomicSub = 0x26, 919 I32AtomicSub8U = 0x27, 920 I32AtomicSub16U = 0x28, 921 I64AtomicSub8U = 0x29, 922 I64AtomicSub16U = 0x2a, 923 I64AtomicSub32U = 0x2b, 924 925 I32AtomicAnd = 0x2c, 926 I64AtomicAnd = 0x2d, 927 I32AtomicAnd8U = 0x2e, 928 I32AtomicAnd16U = 0x2f, 929 I64AtomicAnd8U = 0x30, 930 I64AtomicAnd16U = 0x31, 931 I64AtomicAnd32U = 0x32, 932 933 I32AtomicOr = 0x33, 934 I64AtomicOr = 0x34, 935 I32AtomicOr8U = 0x35, 936 I32AtomicOr16U = 0x36, 937 I64AtomicOr8U = 0x37, 938 I64AtomicOr16U = 0x38, 939 I64AtomicOr32U = 0x39, 940 941 I32AtomicXor = 0x3a, 942 I64AtomicXor = 0x3b, 943 I32AtomicXor8U = 0x3c, 944 I32AtomicXor16U = 0x3d, 945 I64AtomicXor8U = 0x3e, 946 I64AtomicXor16U = 0x3f, 947 I64AtomicXor32U = 0x40, 948 949 I32AtomicXchg = 0x41, 950 I64AtomicXchg = 0x42, 951 I32AtomicXchg8U = 0x43, 952 I32AtomicXchg16U = 0x44, 953 I64AtomicXchg8U = 0x45, 954 I64AtomicXchg16U = 0x46, 955 I64AtomicXchg32U = 0x47, 956 957 // CompareExchange 958 I32AtomicCmpXchg = 0x48, 959 I64AtomicCmpXchg = 0x49, 960 I32AtomicCmpXchg8U = 0x4a, 961 I32AtomicCmpXchg16U = 0x4b, 962 I64AtomicCmpXchg8U = 0x4c, 963 I64AtomicCmpXchg16U = 0x4d, 964 I64AtomicCmpXchg32U = 0x4e, 965 966 Limit 967 }; 968 969 enum class BuiltinModuleFuncId { 970 None = 0, 971 972 // ------------------------------------------------------------------------ 973 // These are part/suffix of the MozOp::CallBuiltinModuleFunc operators that are 974 // emitted internally when compiling intrinsic modules and are rejected by wasm 975 // validation. 976 // See wasm/WasmBuiltinModule.yaml for the list. 977 #define VISIT_BUILTIN_FUNC(op, export, sa_name, abitype, needs_thunk, entry, \ 978 uses_memory, inline_op, idx) \ 979 op = idx + 1, // NOLINT 980 FOR_EACH_BUILTIN_MODULE_FUNC(VISIT_BUILTIN_FUNC) 981 #undef VISIT_BUILTIN_FUNC 982 983 // Op limit. 984 Limit 985 }; 986 987 enum class BuiltinInlineOp { 988 None = 0, 989 990 StringCast, 991 StringTest, 992 StringLength, 993 994 // Op limit. 995 Limit 996 }; 997 998 enum class BuiltinModuleId { 999 SelfTest = 0, 1000 IntGemm, 1001 JSString, 1002 1003 // Not technically a builtin module, but it uses most of the same machinery. 1004 JSStringConstants, 1005 }; 1006 1007 enum class StackSwitchKind { 1008 SwitchToSuspendable, 1009 SwitchToMain, 1010 ContinueOnSuspendable, 1011 }; 1012 1013 enum class UpdateSuspenderStateAction { 1014 Enter, 1015 Suspend, 1016 Resume, 1017 Leave, 1018 }; 1019 1020 enum class MozOp { 1021 // ------------------------------------------------------------------------ 1022 // These operators are emitted internally when compiling asm.js and are 1023 // rejected by wasm validation. They are prefixed by MozPrefix. 1024 1025 // asm.js-specific operators. They start at 1 so as to check for 1026 // uninitialized (zeroed) storage. 1027 TeeGlobal = 0x01, 1028 I32Min, 1029 I32Max, 1030 I32Neg, 1031 I32BitNot, 1032 I32Abs, 1033 F32TeeStoreF64, 1034 F64TeeStoreF32, 1035 I32TeeStore8, 1036 I32TeeStore16, 1037 I64TeeStore8, 1038 I64TeeStore16, 1039 I64TeeStore32, 1040 I32TeeStore, 1041 I64TeeStore, 1042 F32TeeStore, 1043 F64TeeStore, 1044 F64Mod, 1045 F64SinNative, 1046 F64SinFdlibm, 1047 F64CosNative, 1048 F64CosFdlibm, 1049 F64TanNative, 1050 F64TanFdlibm, 1051 F64Asin, 1052 F64Acos, 1053 F64Atan, 1054 F64Exp, 1055 F64Log, 1056 F64Pow, 1057 F64Atan2, 1058 1059 // asm.js-style call_indirect with the callee evaluated first. 1060 OldCallDirect, 1061 OldCallIndirect, 1062 1063 // Call a builtin module funcs. The operator has argument leb u32 to specify 1064 // particular operation id. See BuiltinModuleFuncId above. 1065 CallBuiltinModuleFunc, 1066 1067 StackSwitch, 1068 1069 Limit 1070 }; 1071 1072 struct OpBytes { 1073 // b0 is a byte value but has a 16-bit representation to allow for a full 1074 // 256-value range plus a sentinel Limit value. 1075 uint16_t b0; 1076 // b1 is a LEB128 value but 32 bits is enough for now. 1077 uint32_t b1; 1078 1079 explicit OpBytes(Op x) { 1080 b0 = uint16_t(x); 1081 b1 = 0; 1082 } 1083 OpBytes(uint16_t b0, uint16_t b1) : b0(b0), b1(b1) {} 1084 OpBytes() = default; 1085 1086 uint32_t toPacked() const { 1087 // In practice all of our secondary bytecodes are actually 16-bit right now. 1088 MOZ_RELEASE_ASSERT(b1 <= UINT16_MAX); 1089 return b0 | (b1 << 16); 1090 } 1091 1092 static OpBytes fromPacked(uint32_t packed) { 1093 return OpBytes(packed & 0xFFFF, packed >> 16); 1094 } 1095 1096 // Whether this opcode should have a breakpoint site inserted directly before 1097 // the opcode in baseline when debugging. We use this as a heuristic to 1098 // reduce the number of breakpoint sites. 1099 bool shouldHaveBreakpoint() const { 1100 switch (Op(b0)) { 1101 // Block-like instructions don't get their own breakpoint site, a 1102 // breakpoint can be used on instructions in the block. 1103 case Op::Block: 1104 case Op::Loop: 1105 case Op::If: 1106 case Op::Else: 1107 case Op::Try: 1108 case Op::Delegate: 1109 case Op::Catch: 1110 case Op::CatchAll: 1111 case Op::End: 1112 // Effect-less instructions without inputs are leaf nodes in expressions, 1113 // a breakpoint can be used on instructions that consume these values. 1114 case Op::LocalGet: 1115 case Op::GlobalGet: 1116 case Op::I32Const: 1117 case Op::I64Const: 1118 case Op::F32Const: 1119 case Op::F64Const: 1120 case Op::RefNull: 1121 case Op::Drop: 1122 return false; 1123 default: 1124 return true; 1125 } 1126 } 1127 1128 // Defined in WasmOpIter.cpp 1129 const char* toString() const; 1130 }; 1131 1132 static const char NameSectionName[] = "name"; 1133 static const char SourceMappingURLSectionName[] = "sourceMappingURL"; 1134 static const char BranchHintingSectionName[] = "metadata.code.branch_hint"; 1135 1136 enum class NameType { Module = 0, Function = 1, Local = 2 }; 1137 1138 enum class FieldFlags { Mutable = 0x01, AllowedMask = 0x01 }; 1139 1140 enum class FieldWideningOp { None, Signed, Unsigned }; 1141 1142 // The WebAssembly custom page sizes proposal allows for a virtual page size of 1143 // either 64KiB, or 1 byte. We call these Standard and Tiny, respectively. 1144 enum class PageSize { 1145 #ifdef ENABLE_WASM_CUSTOM_PAGE_SIZES 1146 Tiny = 0, 1147 #endif 1148 Standard = 16 1149 }; 1150 1151 // These limits are agreed upon with other engines for consistency. 1152 1153 static const unsigned MaxRecGroups = 1000000; 1154 static const unsigned MaxTypes = 1000000; 1155 static const unsigned MaxSubTypingDepth = 63; 1156 static const unsigned MaxTags = 1000000; 1157 static const unsigned MaxFuncs = 1000000; 1158 static const unsigned MaxTables = 100000; 1159 static const unsigned MaxMemories = 100; 1160 static const unsigned MaxImports = 1000000; 1161 static const unsigned MaxExports = 1000000; 1162 static const unsigned MaxGlobals = 1000000; 1163 static const unsigned MaxDataSegments = 100000; 1164 static const unsigned MaxDataSegmentLengthPages = 16384; 1165 static const unsigned MaxElemSegments = 10000000; 1166 static const unsigned MaxElemSegmentLength = 10000000; 1167 static const uint64_t MaxTable32ElemsValidation = UINT32_MAX; 1168 static const uint64_t MaxTable64ElemsValidation = UINT64_MAX; 1169 static const unsigned MaxTableElemsRuntime = 10000000; 1170 static const unsigned MaxLocals = 50000; 1171 static const unsigned MaxParams = 1000; 1172 static const unsigned MaxResults = 1000; 1173 static const unsigned MaxStructFields = 10000; 1174 #ifdef ENABLE_WASM_CUSTOM_PAGE_SIZES 1175 static const uint64_t MaxMemory32TinyPagesValidation = UINT32_MAX; 1176 static const uint64_t MaxMemory64TinyPagesValidation = (uint64_t(1) << 53) - 1; 1177 #endif 1178 static const uint64_t MaxMemory32StandardPagesValidation = uint64_t(1) << 16; 1179 static const uint64_t MaxMemory64StandardPagesValidation = 1180 (uint64_t(1) << 37) - 1; 1181 static const unsigned MaxModuleBytes = 1024 * 1024 * 1024; 1182 static const unsigned MaxFunctionBytes = 7654321; 1183 static const unsigned MaxArrayNewFixedElements = 10000; 1184 1185 // Maximum payload size, in bytes, of a gc-proposal Array. Puts it fairly 1186 // close to 2^31 without exposing us to potential danger at the signed-i32 1187 // wraparound boundary. Note that gc-proposal Struct sizes are limited by 1188 // MaxStructFields above. Some code assumes that the payload size will fit in 1189 // a uint32_t, hence the static assert. 1190 static const unsigned MaxArrayPayloadBytes = 1987654321; 1191 static_assert(uint64_t(MaxArrayPayloadBytes) < 1192 (uint64_t(1) << (8 * sizeof(uint32_t)))); 1193 1194 // These limits pertain to our WebAssembly implementation only. 1195 1196 static const unsigned MaxTryTableCatches = 10000; 1197 static const unsigned MaxBrTableElems = 65520; 1198 static const unsigned MaxCodeSectionBytes = MaxModuleBytes; 1199 static const unsigned MaxBranchHintValue = 2; 1200 1201 // 512KiB should be enough, considering how Rabaldr uses the stack and 1202 // what the standard limits are: 1203 // 1204 // - 1,000 parameters 1205 // - 50,000 locals 1206 // - 10,000 values on the eval stack (not an official limit) 1207 // 1208 // At sizeof(int64) bytes per slot this works out to about 480KiB. 1209 1210 static const unsigned MaxFrameSize = 512 * 1024; 1211 1212 // Limit for the amount of stacks present in the runtime. 1213 static const size_t SuspendableStacksMaxCount = 100; 1214 1215 // Max size of an allocated stack. 1216 static const size_t SuspendableStackSize = 0x100000; 1217 1218 // Size of additional space at the top of a suspendable stack. 1219 // The space is allocated to C++ handlers such as error/trap handlers, 1220 // or stack snapshots utilities. 1221 static const size_t SuspendableRedZoneSize = 0x6000; 1222 1223 // Total size of a suspendable stack to be reserved. 1224 static constexpr size_t SuspendableStackPlusRedZoneSize = 1225 SuspendableStackSize + SuspendableRedZoneSize; 1226 1227 // Asserted by Decoder::readVarU32. 1228 1229 static const unsigned MaxVarU32DecodedBytes = 5; 1230 1231 // The CompileMode controls how compilation of a module is performed. 1232 enum class CompileMode { 1233 // Compile the module just once using a given tier. 1234 Once, 1235 // Compile the module first with baseline, then eagerly launch an ion 1236 // background compile to compile the module again. 1237 EagerTiering, 1238 // Compile the module first with baseline, then lazily compile functions with 1239 // ion when they trigger a hotness threshold. 1240 LazyTiering, 1241 }; 1242 1243 // CompileState tracks where in the compilation process we are for a module. 1244 enum class CompileState { 1245 // We're compiling the module using the 'once' mode. 1246 Once, 1247 // We're compiling the module using the eager tiering mode. We're 1248 // currently compiling the first tier. The second tier task will be launched 1249 // once we're done compiling the first tier. 1250 EagerTier1, 1251 // We're compiling the module using the eager tiering mode. We're now 1252 // compiling the second tier. 1253 EagerTier2, 1254 // We're compiling the module eagerly using the lazy tiering mode. We're 1255 // compiling the first tier. 1256 LazyTier1, 1257 // We're compiling the module eagerly using the lazy tiering strategy. We're 1258 // compiling the second tier. 1259 LazyTier2, 1260 }; 1261 1262 // Typed enum for whether debugging is enabled. 1263 1264 enum class DebugEnabled { False, True }; 1265 1266 } // namespace wasm 1267 } // namespace js 1268 1269 #endif // wasm_constants_h