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/WasmIntrinsicGenerated.h"
25 
26 namespace js {
27 namespace wasm {
28 
29 static const uint32_t MagicNumber = 0x6d736100;  // "\0asm"
30 static const uint32_t EncodingVersion = 0x01;
31 
32 enum class SectionId {
33   Custom = 0,
34   Type = 1,
35   Import = 2,
36   Function = 3,
37   Table = 4,
38   Memory = 5,
39   Global = 6,
40   Export = 7,
41   Start = 8,
42   Elem = 9,
43   Code = 10,
44   Data = 11,
45   DataCount = 12,
46 #ifdef ENABLE_WASM_EXCEPTIONS
47   Tag = 13,
48 #endif
49 };
50 
51 // WebAssembly type encodings are all single-byte negative SLEB128s, hence:
52 //  forall tc:TypeCode. ((tc & SLEB128SignMask) == SLEB128SignBit
53 static const uint8_t SLEB128SignMask = 0xc0;
54 static const uint8_t SLEB128SignBit = 0x40;
55 
56 enum class TypeCode {
57 
58   // If more "simple primitive" (non-reference, non-constructor,
59   // non-special-purpose) types are added here then you MUST update
60   // LowestPrimitiveTypeCode, below.
61 
62   I32 = 0x7f,   // SLEB128(-0x01)
63   I64 = 0x7e,   // SLEB128(-0x02)
64   F32 = 0x7d,   // SLEB128(-0x03)
65   F64 = 0x7c,   // SLEB128(-0x04)
66   V128 = 0x7b,  // SLEB128(-0x05)
67 
68   I8 = 0x7a,   // SLEB128(-0x06)
69   I16 = 0x79,  // SLEB128(-0x07)
70 
71   // A function pointer with any signature
72   FuncRef = 0x70,  // SLEB128(-0x10)
73 
74   // A reference to any host value.
75   ExternRef = 0x6f,  // SLEB128(-0x11)
76 
77   // A reference to a struct/array value.
78   EqRef = 0x6d,  // SLEB128(-0x12)
79 
80   // Type constructor for nullable reference types.
81   NullableRef = 0x6c,  // SLEB128(-0x14)
82 
83   // Type constructor for non-nullable reference types.
84   Ref = 0x6b,  // SLEB128(-0x15)
85 
86   // Type constructors for rtt types.
87   RttWithDepth = 0x69,  // SLEB128(-0x17)
88   Rtt = 0x68,           // SLEB128(-0x18)
89 
90   // Type constructor for function types
91   Func = 0x60,  // SLEB128(-0x20)
92 
93   // Type constructor for structure types - gc proposal
94   Struct = 0x5f,  // SLEB128(-0x21)
95 
96   // Type constructor for array types - gc proposal
97   Array = 0x5e,  // SLEB128(-0x22)
98 
99   // The 'empty' case of blocktype.
100   BlockVoid = 0x40,  // SLEB128(-0x40)
101 
102   Limit = 0x80
103 };
104 
105 // This is the lowest-valued TypeCode that is a primitive type, used in
106 // UnpackTypeCodeTypeAbstracted().  If primitive typecodes are added below any
107 // reference typecode then the logic in that function MUST change.
108 
109 static constexpr TypeCode LowestPrimitiveTypeCode = TypeCode::I16;
110 
111 // An arbitrary reference type used as the result of
112 // UnpackTypeCodeTypeAbstracted() when a value type is a reference.
113 
114 static constexpr TypeCode AbstractReferenceTypeCode = TypeCode::ExternRef;
115 
116 // A type code used to represent (ref null? typeindex) whether or not the type
117 // is encoded with 'Ref' or 'NullableRef'.
118 
119 static constexpr TypeCode AbstractReferenceTypeIndexCode = TypeCode::Ref;
120 
121 // A type code used to represent (rtt depth? typeindex) whether or not the type
122 // is encoded with 'Rtt' or 'RttWithDepth'.
123 
124 static constexpr TypeCode AbstractRttCode = TypeCode::Rtt;
125 
126 enum class TypeIdDescKind { None, Immediate, Global };
127 
128 // A wasm::Trap represents a wasm-defined trap that can occur during execution
129 // which triggers a WebAssembly.RuntimeError. Generated code may jump to a Trap
130 // symbolically, passing the bytecode offset to report as the trap offset. The
131 // generated jump will be bound to a tiny stub which fills the offset and
132 // then jumps to a per-Trap shared stub at the end of the module.
133 
134 enum class Trap {
135   // The Unreachable opcode has been executed.
136   Unreachable,
137   // An integer arithmetic operation led to an overflow.
138   IntegerOverflow,
139   // Trying to coerce NaN to an integer.
140   InvalidConversionToInteger,
141   // Integer division by zero.
142   IntegerDivideByZero,
143   // Out of bounds on wasm memory accesses.
144   OutOfBounds,
145   // Unaligned on wasm atomic accesses; also used for non-standard ARM
146   // unaligned access faults.
147   UnalignedAccess,
148   // call_indirect to null.
149   IndirectCallToNull,
150   // call_indirect signature mismatch.
151   IndirectCallBadSig,
152   // Dereference null pointer in operation on (Ref T)
153   NullPointerDereference,
154   // Failed to cast a (Ref T) in a ref.cast instruction
155   BadCast,
156 
157   // The internal stack space was exhausted. For compatibility, this throws
158   // the same over-recursed error as JS.
159   StackOverflow,
160 
161   // The wasm execution has potentially run too long and the engine must call
162   // CheckForInterrupt(). This trap is resumable.
163   CheckInterrupt,
164 
165   // Signal an error that was reported in C++ code.
166   ThrowReported,
167 
168   Limit
169 };
170 
171 // The representation of a null reference value throughout the compiler.
172 
173 static const intptr_t NULLREF_VALUE = intptr_t((void*)nullptr);
174 
175 enum class DefinitionKind {
176   Function = 0x00,
177   Table = 0x01,
178   Memory = 0x02,
179   Global = 0x03,
180 #ifdef ENABLE_WASM_EXCEPTIONS
181   Tag = 0x04,
182 #endif
183 };
184 
185 enum class GlobalTypeImmediate { IsMutable = 0x1, AllowedMask = 0x1 };
186 
187 enum class LimitsFlags {
188   Default = 0x0,
189   HasMaximum = 0x1,
190   IsShared = 0x2,
191   IsI64 = 0x4,
192 };
193 
194 enum class LimitsMask {
195   Table = uint8_t(LimitsFlags::HasMaximum),
196 #ifdef ENABLE_WASM_MEMORY64
197   Memory = uint8_t(LimitsFlags::HasMaximum) | uint8_t(LimitsFlags::IsShared) |
198            uint8_t(LimitsFlags::IsI64),
199 #else
200   Memory = uint8_t(LimitsFlags::HasMaximum) | uint8_t(LimitsFlags::IsShared),
201 #endif
202 };
203 
204 enum class DataSegmentKind {
205   Active = 0x00,
206   Passive = 0x01,
207   ActiveWithMemoryIndex = 0x02
208 };
209 
210 enum class ElemSegmentKind : uint32_t {
211   Active = 0x0,
212   Passive = 0x1,
213   ActiveWithTableIndex = 0x2,
214   Declared = 0x3,
215 };
216 
217 enum class ElemSegmentPayload : uint32_t {
218   ExternIndex = 0x0,
219   ElemExpression = 0x4,
220 };
221 
222 #ifdef ENABLE_WASM_EXCEPTIONS
223 enum class TagKind {
224   Exception = 0x0,
225 };
226 #endif
227 
228 enum class Op {
229   // Control flow operators
230   Unreachable = 0x00,
231   Nop = 0x01,
232   Block = 0x02,
233   Loop = 0x03,
234   If = 0x04,
235   Else = 0x05,
236 #ifdef ENABLE_WASM_EXCEPTIONS
237   Try = 0x06,
238   Catch = 0x07,
239   Throw = 0x08,
240   Rethrow = 0x09,
241 #endif
242   End = 0x0b,
243   Br = 0x0c,
244   BrIf = 0x0d,
245   BrTable = 0x0e,
246   Return = 0x0f,
247 
248   // Call operators
249   Call = 0x10,
250   CallIndirect = 0x11,
251 
252 // Additional exception operators
253 #ifdef ENABLE_WASM_EXCEPTIONS
254   Delegate = 0x18,
255   CatchAll = 0x19,
256 #endif
257 
258   // Parametric operators
259   Drop = 0x1a,
260   SelectNumeric = 0x1b,
261   SelectTyped = 0x1c,
262 
263   // Variable access
264   LocalGet = 0x20,
265   LocalSet = 0x21,
266   LocalTee = 0x22,
267   GlobalGet = 0x23,
268   GlobalSet = 0x24,
269   TableGet = 0x25,  // Reftypes,
270   TableSet = 0x26,  //   per proposal as of February 2019
271 
272   // Memory-related operators
273   I32Load = 0x28,
274   I64Load = 0x29,
275   F32Load = 0x2a,
276   F64Load = 0x2b,
277   I32Load8S = 0x2c,
278   I32Load8U = 0x2d,
279   I32Load16S = 0x2e,
280   I32Load16U = 0x2f,
281   I64Load8S = 0x30,
282   I64Load8U = 0x31,
283   I64Load16S = 0x32,
284   I64Load16U = 0x33,
285   I64Load32S = 0x34,
286   I64Load32U = 0x35,
287   I32Store = 0x36,
288   I64Store = 0x37,
289   F32Store = 0x38,
290   F64Store = 0x39,
291   I32Store8 = 0x3a,
292   I32Store16 = 0x3b,
293   I64Store8 = 0x3c,
294   I64Store16 = 0x3d,
295   I64Store32 = 0x3e,
296   MemorySize = 0x3f,
297   MemoryGrow = 0x40,
298 
299   // Constants
300   I32Const = 0x41,
301   I64Const = 0x42,
302   F32Const = 0x43,
303   F64Const = 0x44,
304 
305   // Comparison operators
306   I32Eqz = 0x45,
307   I32Eq = 0x46,
308   I32Ne = 0x47,
309   I32LtS = 0x48,
310   I32LtU = 0x49,
311   I32GtS = 0x4a,
312   I32GtU = 0x4b,
313   I32LeS = 0x4c,
314   I32LeU = 0x4d,
315   I32GeS = 0x4e,
316   I32GeU = 0x4f,
317   I64Eqz = 0x50,
318   I64Eq = 0x51,
319   I64Ne = 0x52,
320   I64LtS = 0x53,
321   I64LtU = 0x54,
322   I64GtS = 0x55,
323   I64GtU = 0x56,
324   I64LeS = 0x57,
325   I64LeU = 0x58,
326   I64GeS = 0x59,
327   I64GeU = 0x5a,
328   F32Eq = 0x5b,
329   F32Ne = 0x5c,
330   F32Lt = 0x5d,
331   F32Gt = 0x5e,
332   F32Le = 0x5f,
333   F32Ge = 0x60,
334   F64Eq = 0x61,
335   F64Ne = 0x62,
336   F64Lt = 0x63,
337   F64Gt = 0x64,
338   F64Le = 0x65,
339   F64Ge = 0x66,
340 
341   // Numeric operators
342   I32Clz = 0x67,
343   I32Ctz = 0x68,
344   I32Popcnt = 0x69,
345   I32Add = 0x6a,
346   I32Sub = 0x6b,
347   I32Mul = 0x6c,
348   I32DivS = 0x6d,
349   I32DivU = 0x6e,
350   I32RemS = 0x6f,
351   I32RemU = 0x70,
352   I32And = 0x71,
353   I32Or = 0x72,
354   I32Xor = 0x73,
355   I32Shl = 0x74,
356   I32ShrS = 0x75,
357   I32ShrU = 0x76,
358   I32Rotl = 0x77,
359   I32Rotr = 0x78,
360   I64Clz = 0x79,
361   I64Ctz = 0x7a,
362   I64Popcnt = 0x7b,
363   I64Add = 0x7c,
364   I64Sub = 0x7d,
365   I64Mul = 0x7e,
366   I64DivS = 0x7f,
367   I64DivU = 0x80,
368   I64RemS = 0x81,
369   I64RemU = 0x82,
370   I64And = 0x83,
371   I64Or = 0x84,
372   I64Xor = 0x85,
373   I64Shl = 0x86,
374   I64ShrS = 0x87,
375   I64ShrU = 0x88,
376   I64Rotl = 0x89,
377   I64Rotr = 0x8a,
378   F32Abs = 0x8b,
379   F32Neg = 0x8c,
380   F32Ceil = 0x8d,
381   F32Floor = 0x8e,
382   F32Trunc = 0x8f,
383   F32Nearest = 0x90,
384   F32Sqrt = 0x91,
385   F32Add = 0x92,
386   F32Sub = 0x93,
387   F32Mul = 0x94,
388   F32Div = 0x95,
389   F32Min = 0x96,
390   F32Max = 0x97,
391   F32CopySign = 0x98,
392   F64Abs = 0x99,
393   F64Neg = 0x9a,
394   F64Ceil = 0x9b,
395   F64Floor = 0x9c,
396   F64Trunc = 0x9d,
397   F64Nearest = 0x9e,
398   F64Sqrt = 0x9f,
399   F64Add = 0xa0,
400   F64Sub = 0xa1,
401   F64Mul = 0xa2,
402   F64Div = 0xa3,
403   F64Min = 0xa4,
404   F64Max = 0xa5,
405   F64CopySign = 0xa6,
406 
407   // Conversions
408   I32WrapI64 = 0xa7,
409   I32TruncF32S = 0xa8,
410   I32TruncF32U = 0xa9,
411   I32TruncF64S = 0xaa,
412   I32TruncF64U = 0xab,
413   I64ExtendI32S = 0xac,
414   I64ExtendI32U = 0xad,
415   I64TruncF32S = 0xae,
416   I64TruncF32U = 0xaf,
417   I64TruncF64S = 0xb0,
418   I64TruncF64U = 0xb1,
419   F32ConvertI32S = 0xb2,
420   F32ConvertI32U = 0xb3,
421   F32ConvertI64S = 0xb4,
422   F32ConvertI64U = 0xb5,
423   F32DemoteF64 = 0xb6,
424   F64ConvertI32S = 0xb7,
425   F64ConvertI32U = 0xb8,
426   F64ConvertI64S = 0xb9,
427   F64ConvertI64U = 0xba,
428   F64PromoteF32 = 0xbb,
429 
430   // Reinterpretations
431   I32ReinterpretF32 = 0xbc,
432   I64ReinterpretF64 = 0xbd,
433   F32ReinterpretI32 = 0xbe,
434   F64ReinterpretI64 = 0xbf,
435 
436   // Sign extension
437   I32Extend8S = 0xc0,
438   I32Extend16S = 0xc1,
439   I64Extend8S = 0xc2,
440   I64Extend16S = 0xc3,
441   I64Extend32S = 0xc4,
442 
443   // Reference types
444   RefNull = 0xd0,
445   RefIsNull = 0xd1,
446   RefFunc = 0xd2,
447 
448   // Function references
449   RefAsNonNull = 0xd3,
450   BrOnNull = 0xd4,
451 
452   // GC (experimental)
453   RefEq = 0xd5,
454 
455   FirstPrefix = 0xfa,
456   GcPrefix = 0xfb,
457   MiscPrefix = 0xfc,
458   SimdPrefix = 0xfd,
459   ThreadPrefix = 0xfe,
460   MozPrefix = 0xff,
461 
462   Limit = 0x100
463 };
464 
IsPrefixByte(uint8_t b)465 inline bool IsPrefixByte(uint8_t b) { return b >= uint8_t(Op::FirstPrefix); }
466 
467 // Opcodes in the GC opcode space.
468 enum class GcOp {
469   // Structure operations
470   StructNewWithRtt = 0x1,
471   StructNewDefaultWithRtt = 0x2,
472   StructGet = 0x03,
473   StructGetS = 0x04,
474   StructGetU = 0x05,
475   StructSet = 0x06,
476 
477   // Array operations
478   ArrayNewWithRtt = 0x11,
479   ArrayNewDefaultWithRtt = 0x12,
480   ArrayGet = 0x13,
481   ArrayGetS = 0x14,
482   ArrayGetU = 0x15,
483   ArraySet = 0x16,
484   ArrayLen = 0x17,
485 
486   // Rtt operations
487   RttCanon = 0x30,
488   RttSub = 0x31,
489 
490   // Ref operations
491   RefTest = 0x40,
492   RefCast = 0x41,
493   BrOnCast = 0x42,
494 
495   Limit
496 };
497 
498 // Opcode list from the SIMD proposal post-renumbering in May, 2020.
499 
500 // Opcodes with suffix 'Experimental' are proposed but not standardized, and are
501 // compatible with those same opcodes in V8.  No opcode labeled 'Experimental'
502 // will ship in a Release build where SIMD is enabled by default.
503 
504 enum class SimdOp {
505   V128Load = 0x00,
506   V128Load8x8S = 0x01,
507   V128Load8x8U = 0x02,
508   V128Load16x4S = 0x03,
509   V128Load16x4U = 0x04,
510   V128Load32x2S = 0x05,
511   V128Load32x2U = 0x06,
512   V128Load8Splat = 0x07,
513   V128Load16Splat = 0x08,
514   V128Load32Splat = 0x09,
515   V128Load64Splat = 0x0a,
516   V128Store = 0x0b,
517   V128Const = 0x0c,
518   I8x16Shuffle = 0x0d,
519   I8x16Swizzle = 0x0e,
520   I8x16Splat = 0x0f,
521   I16x8Splat = 0x10,
522   I32x4Splat = 0x11,
523   I64x2Splat = 0x12,
524   F32x4Splat = 0x13,
525   F64x2Splat = 0x14,
526   I8x16ExtractLaneS = 0x15,
527   I8x16ExtractLaneU = 0x16,
528   I8x16ReplaceLane = 0x17,
529   I16x8ExtractLaneS = 0x18,
530   I16x8ExtractLaneU = 0x19,
531   I16x8ReplaceLane = 0x1a,
532   I32x4ExtractLane = 0x1b,
533   I32x4ReplaceLane = 0x1c,
534   I64x2ExtractLane = 0x1d,
535   I64x2ReplaceLane = 0x1e,
536   F32x4ExtractLane = 0x1f,
537   F32x4ReplaceLane = 0x20,
538   F64x2ExtractLane = 0x21,
539   F64x2ReplaceLane = 0x22,
540   I8x16Eq = 0x23,
541   I8x16Ne = 0x24,
542   I8x16LtS = 0x25,
543   I8x16LtU = 0x26,
544   I8x16GtS = 0x27,
545   I8x16GtU = 0x28,
546   I8x16LeS = 0x29,
547   I8x16LeU = 0x2a,
548   I8x16GeS = 0x2b,
549   I8x16GeU = 0x2c,
550   I16x8Eq = 0x2d,
551   I16x8Ne = 0x2e,
552   I16x8LtS = 0x2f,
553   I16x8LtU = 0x30,
554   I16x8GtS = 0x31,
555   I16x8GtU = 0x32,
556   I16x8LeS = 0x33,
557   I16x8LeU = 0x34,
558   I16x8GeS = 0x35,
559   I16x8GeU = 0x36,
560   I32x4Eq = 0x37,
561   I32x4Ne = 0x38,
562   I32x4LtS = 0x39,
563   I32x4LtU = 0x3a,
564   I32x4GtS = 0x3b,
565   I32x4GtU = 0x3c,
566   I32x4LeS = 0x3d,
567   I32x4LeU = 0x3e,
568   I32x4GeS = 0x3f,
569   I32x4GeU = 0x40,
570   F32x4Eq = 0x41,
571   F32x4Ne = 0x42,
572   F32x4Lt = 0x43,
573   F32x4Gt = 0x44,
574   F32x4Le = 0x45,
575   F32x4Ge = 0x46,
576   F64x2Eq = 0x47,
577   F64x2Ne = 0x48,
578   F64x2Lt = 0x49,
579   F64x2Gt = 0x4a,
580   F64x2Le = 0x4b,
581   F64x2Ge = 0x4c,
582   V128Not = 0x4d,
583   V128And = 0x4e,
584   V128AndNot = 0x4f,
585   V128Or = 0x50,
586   V128Xor = 0x51,
587   V128Bitselect = 0x52,
588   V128AnyTrue = 0x53,
589   V128Load8Lane = 0x54,
590   V128Load16Lane = 0x55,
591   V128Load32Lane = 0x56,
592   V128Load64Lane = 0x57,
593   V128Store8Lane = 0x58,
594   V128Store16Lane = 0x59,
595   V128Store32Lane = 0x5a,
596   V128Store64Lane = 0x5b,
597   V128Load32Zero = 0x5c,
598   V128Load64Zero = 0x5d,
599   F32x4DemoteF64x2Zero = 0x5e,
600   F64x2PromoteLowF32x4 = 0x5f,
601   I8x16Abs = 0x60,
602   I8x16Neg = 0x61,
603   I8x16Popcnt = 0x62,
604   I8x16AllTrue = 0x63,
605   I8x16Bitmask = 0x64,
606   I8x16NarrowI16x8S = 0x65,
607   I8x16NarrowI16x8U = 0x66,
608   F32x4Ceil = 0x67,
609   F32x4Floor = 0x68,
610   F32x4Trunc = 0x69,
611   F32x4Nearest = 0x6a,
612   I8x16Shl = 0x6b,
613   I8x16ShrS = 0x6c,
614   I8x16ShrU = 0x6d,
615   I8x16Add = 0x6e,
616   I8x16AddSatS = 0x6f,
617   I8x16AddSatU = 0x70,
618   I8x16Sub = 0x71,
619   I8x16SubSatS = 0x72,
620   I8x16SubSatU = 0x73,
621   F64x2Ceil = 0x74,
622   F64x2Floor = 0x75,
623   I8x16MinS = 0x76,
624   I8x16MinU = 0x77,
625   I8x16MaxS = 0x78,
626   I8x16MaxU = 0x79,
627   F64x2Trunc = 0x7a,
628   I8x16AvgrU = 0x7b,
629   I16x8ExtaddPairwiseI8x16S = 0x7c,
630   I16x8ExtaddPairwiseI8x16U = 0x7d,
631   I32x4ExtaddPairwiseI16x8S = 0x7e,
632   I32x4ExtaddPairwiseI16x8U = 0x7f,
633   I16x8Abs = 0x80,
634   I16x8Neg = 0x81,
635   I16x8Q15MulrSatS = 0x82,
636   I16x8AllTrue = 0x83,
637   I16x8Bitmask = 0x84,
638   I16x8NarrowI32x4S = 0x85,
639   I16x8NarrowI32x4U = 0x86,
640   I16x8ExtendLowI8x16S = 0x87,
641   I16x8ExtendHighI8x16S = 0x88,
642   I16x8ExtendLowI8x16U = 0x89,
643   I16x8ExtendHighI8x16U = 0x8a,
644   I16x8Shl = 0x8b,
645   I16x8ShrS = 0x8c,
646   I16x8ShrU = 0x8d,
647   I16x8Add = 0x8e,
648   I16x8AddSatS = 0x8f,
649   I16x8AddSatU = 0x90,
650   I16x8Sub = 0x91,
651   I16x8SubSatS = 0x92,
652   I16x8SubSatU = 0x93,
653   F64x2Nearest = 0x94,
654   I16x8Mul = 0x95,
655   I16x8MinS = 0x96,
656   I16x8MinU = 0x97,
657   I16x8MaxS = 0x98,
658   I16x8MaxU = 0x99,
659   // Unused = 0x9a
660   I16x8AvgrU = 0x9b,
661   I16x8ExtmulLowI8x16S = 0x9c,
662   I16x8ExtmulHighI8x16S = 0x9d,
663   I16x8ExtmulLowI8x16U = 0x9e,
664   I16x8ExtmulHighI8x16U = 0x9f,
665   I32x4Abs = 0xa0,
666   I32x4Neg = 0xa1,
667   V8x16RelaxedSwizzle = 0xa2,
668   I32x4AllTrue = 0xa3,
669   I32x4Bitmask = 0xa4,
670   I32x4RelaxedTruncSSatF32x4 = 0xa5,
671   I32x4RelaxedTruncUSatF32x4 = 0xa6,
672   I32x4ExtendLowI16x8S = 0xa7,
673   I32x4ExtendHighI16x8S = 0xa8,
674   I32x4ExtendLowI16x8U = 0xa9,
675   I32x4ExtendHighI16x8U = 0xaa,
676   I32x4Shl = 0xab,
677   I32x4ShrS = 0xac,
678   I32x4ShrU = 0xad,
679   I32x4Add = 0xae,
680   F32x4RelaxedFma = 0xaf,
681   F32x4RelaxedFms = 0xb0,
682   I32x4Sub = 0xb1,
683   I8x16LaneSelect = 0xb2,
684   I16x8LaneSelect = 0xb3,
685   F32x4RelaxedMin = 0xb4,
686   I32x4Mul = 0xb5,
687   I32x4MinS = 0xb6,
688   I32x4MinU = 0xb7,
689   I32x4MaxS = 0xb8,
690   I32x4MaxU = 0xb9,
691   I32x4DotI16x8S = 0xba,
692   // Unused = 0xbb
693   I32x4ExtmulLowI16x8S = 0xbc,
694   I32x4ExtmulHighI16x8S = 0xbd,
695   I32x4ExtmulLowI16x8U = 0xbe,
696   I32x4ExtmulHighI16x8U = 0xbf,
697   I64x2Abs = 0xc0,
698   I64x2Neg = 0xc1,
699   // AnyTrue = 0xc2
700   I64x2AllTrue = 0xc3,
701   I64x2Bitmask = 0xc4,
702   I32x4RelaxedTruncSatF64x2SZero = 0xc5,
703   I32x4RelaxedTruncSatF64x2UZero = 0xc6,
704   I64x2ExtendLowI32x4S = 0xc7,
705   I64x2ExtendHighI32x4S = 0xc8,
706   I64x2ExtendLowI32x4U = 0xc9,
707   I64x2ExtendHighI32x4U = 0xca,
708   I64x2Shl = 0xcb,
709   I64x2ShrS = 0xcc,
710   I64x2ShrU = 0xcd,
711   I64x2Add = 0xce,
712   F64x2RelaxedFma = 0xcf,
713   F64x2RelaxedFms = 0xd0,
714   I64x2Sub = 0xd1,
715   I32x4LaneSelect = 0xd2,
716   I64x2LaneSelect = 0xd3,
717   F64x2RelaxedMin = 0xd4,
718   I64x2Mul = 0xd5,
719   I64x2Eq = 0xd6,
720   I64x2Ne = 0xd7,
721   I64x2LtS = 0xd8,
722   I64x2GtS = 0xd9,
723   I64x2LeS = 0xda,
724   I64x2GeS = 0xdb,
725   I64x2ExtmulLowI32x4S = 0xdc,
726   I64x2ExtmulHighI32x4S = 0xdd,
727   I64x2ExtmulLowI32x4U = 0xde,
728   I64x2ExtmulHighI32x4U = 0xdf,
729   F32x4Abs = 0xe0,
730   F32x4Neg = 0xe1,
731   F32x4RelaxedMax = 0xe2,
732   F32x4Sqrt = 0xe3,
733   F32x4Add = 0xe4,
734   F32x4Sub = 0xe5,
735   F32x4Mul = 0xe6,
736   F32x4Div = 0xe7,
737   F32x4Min = 0xe8,
738   F32x4Max = 0xe9,
739   F32x4PMin = 0xea,
740   F32x4PMax = 0xeb,
741   F64x2Abs = 0xec,
742   F64x2Neg = 0xed,
743   F64x2RelaxedMax = 0xee,
744   F64x2Sqrt = 0xef,
745   F64x2Add = 0xf0,
746   F64x2Sub = 0xf1,
747   F64x2Mul = 0xf2,
748   F64x2Div = 0xf3,
749   F64x2Min = 0xf4,
750   F64x2Max = 0xf5,
751   F64x2PMin = 0xf6,
752   F64x2PMax = 0xf7,
753   I32x4TruncSatF32x4S = 0xf8,
754   I32x4TruncSatF32x4U = 0xf9,
755   F32x4ConvertI32x4S = 0xfa,
756   F32x4ConvertI32x4U = 0xfb,
757   I32x4TruncSatF64x2SZero = 0xfc,
758   I32x4TruncSatF64x2UZero = 0xfd,
759   F64x2ConvertLowI32x4S = 0xfe,
760   F64x2ConvertLowI32x4U = 0xff,
761 // Unused = 0x100 and up
762 
763 // Mozilla extensions, highly experimental and platform-specific
764 #ifdef ENABLE_WASM_SIMD_WORMHOLE
765   // The wormhole is a mechanism for injecting experimental, possibly
766   // platform-dependent, opcodes into the generated code.  A wormhole op is
767   // expressed as a two-operation SIMD shuffle op with the pattern <31, 0, 30,
768   // 2, 29, 4, 28, 6, 27, 8, 26, 10, 25, 12, 24, X> where X is the opcode,
769   // 0..31, from the set below.  If an operation uses no operands, the operands
770   // to the shuffle opcode should be v128.const 0.  If an operation uses one
771   // operand, the operands to the shuffle opcode should both be that operand.
772   //
773   // The wormhole must be enabled by a flag (see below) and is only supported on
774   // x64 and x86 (though with both compilers).
775   //
776   // The benefit of this mechanism is that it allows experimental opcodes to be
777   // used without updating other tools (compilers, linkers, optimizers).
778   //
779   // Controlling the wormhole:
780   //
781   // - Under the correct circumstances, an options bag that is passed as an
782   //   additional and nonstandard argument to any function that validates or
783   //   compiles wasm will be inspected for carrying additional compilation
784   //   options. The options bag always follows any fixed and optional arguments
785   //   already in the signature.  The functions are: WA.validate, WA.compile,
786   //   WA.instantiate when called on a BufferSource, WA.compileStreaming,
787   //   WA.instantiateStreaming, and WA.Module.constructor.  If compiled code can
788   //   be cached, the presence of the options bag forces recompilation.
789   //
790   // - If the bag is inspected and contains the property `simdWormhole` and that
791   //   property has the boolean value `true` (and not just any truthy value),
792   //   then wasm SIMD will be enabled and the wormhole functionality will also
793   //   be enabled for the affected compilation only.
794   //
795   // - The options bag is parsed under these circumstances:
796   //
797   //   - In the shell, if the switch `--wasm-simd-wormhole` is set.
798   //
799   //   - In Nightly and early Beta browsers, if the flag
800   //     `j.o.wasm_simd_wormhole` is set.
801   //
802   //   - In all browsers, if the content passing the options bag is privileged
803   //     (in a way that is TBD).
804   //
805   // - As per normal, wasm SIMD can be enabled by setting `j.o.wasm_simd` to
806   //   true, but in that case the wormhole functionality will not be enabled.
807   //   Note that `j.o.wasm_simd_wormhole` does not enable the wormhole
808   //   functionality directly; it must be enabled by passing an options bag as
809   //   described above.
810 
811   // These opcodes can be rearranged but the X values associated with them must
812   // remain fixed.
813 
814   // X=0, selftest opcode.  No operands.  The result is an 8x16 hex value:
815   // DEADD00DCAFEBABE.
816   MozWHSELFTEST = 0x200,
817 
818   // X=1, Intel SSE3 PMADDUBSW instruction. Two operands.
819   MozWHPMADDUBSW = 0x201,
820 
821   // X=2, Intel SSE2 PMADDWD instruction. Two operands.
822   MozWHPMADDWD = 0x202,
823 #endif
824 
825   Limit
826 };
827 
828 // Opcodes in the "miscellaneous" opcode space.
829 enum class MiscOp {
830   // Saturating float-to-int conversions
831   I32TruncSatF32S = 0x00,
832   I32TruncSatF32U = 0x01,
833   I32TruncSatF64S = 0x02,
834   I32TruncSatF64U = 0x03,
835   I64TruncSatF32S = 0x04,
836   I64TruncSatF32U = 0x05,
837   I64TruncSatF64S = 0x06,
838   I64TruncSatF64U = 0x07,
839 
840   // Bulk memory operations, per proposal as of February 2019.
841   MemoryInit = 0x08,
842   DataDrop = 0x09,
843   MemoryCopy = 0x0a,
844   MemoryFill = 0x0b,
845   TableInit = 0x0c,
846   ElemDrop = 0x0d,
847   TableCopy = 0x0e,
848 
849   // Reftypes, per proposal as of February 2019.
850   TableGrow = 0x0f,
851   TableSize = 0x10,
852   TableFill = 0x11,
853 
854   Limit
855 };
856 
857 // Opcodes from threads proposal as of June 30, 2017
858 enum class ThreadOp {
859   // Wait and wake
860   Wake = 0x00,
861   I32Wait = 0x01,
862   I64Wait = 0x02,
863   Fence = 0x03,
864 
865   // Load and store
866   I32AtomicLoad = 0x10,
867   I64AtomicLoad = 0x11,
868   I32AtomicLoad8U = 0x12,
869   I32AtomicLoad16U = 0x13,
870   I64AtomicLoad8U = 0x14,
871   I64AtomicLoad16U = 0x15,
872   I64AtomicLoad32U = 0x16,
873   I32AtomicStore = 0x17,
874   I64AtomicStore = 0x18,
875   I32AtomicStore8U = 0x19,
876   I32AtomicStore16U = 0x1a,
877   I64AtomicStore8U = 0x1b,
878   I64AtomicStore16U = 0x1c,
879   I64AtomicStore32U = 0x1d,
880 
881   // Read-modify-write operations
882   I32AtomicAdd = 0x1e,
883   I64AtomicAdd = 0x1f,
884   I32AtomicAdd8U = 0x20,
885   I32AtomicAdd16U = 0x21,
886   I64AtomicAdd8U = 0x22,
887   I64AtomicAdd16U = 0x23,
888   I64AtomicAdd32U = 0x24,
889 
890   I32AtomicSub = 0x25,
891   I64AtomicSub = 0x26,
892   I32AtomicSub8U = 0x27,
893   I32AtomicSub16U = 0x28,
894   I64AtomicSub8U = 0x29,
895   I64AtomicSub16U = 0x2a,
896   I64AtomicSub32U = 0x2b,
897 
898   I32AtomicAnd = 0x2c,
899   I64AtomicAnd = 0x2d,
900   I32AtomicAnd8U = 0x2e,
901   I32AtomicAnd16U = 0x2f,
902   I64AtomicAnd8U = 0x30,
903   I64AtomicAnd16U = 0x31,
904   I64AtomicAnd32U = 0x32,
905 
906   I32AtomicOr = 0x33,
907   I64AtomicOr = 0x34,
908   I32AtomicOr8U = 0x35,
909   I32AtomicOr16U = 0x36,
910   I64AtomicOr8U = 0x37,
911   I64AtomicOr16U = 0x38,
912   I64AtomicOr32U = 0x39,
913 
914   I32AtomicXor = 0x3a,
915   I64AtomicXor = 0x3b,
916   I32AtomicXor8U = 0x3c,
917   I32AtomicXor16U = 0x3d,
918   I64AtomicXor8U = 0x3e,
919   I64AtomicXor16U = 0x3f,
920   I64AtomicXor32U = 0x40,
921 
922   I32AtomicXchg = 0x41,
923   I64AtomicXchg = 0x42,
924   I32AtomicXchg8U = 0x43,
925   I32AtomicXchg16U = 0x44,
926   I64AtomicXchg8U = 0x45,
927   I64AtomicXchg16U = 0x46,
928   I64AtomicXchg32U = 0x47,
929 
930   // CompareExchange
931   I32AtomicCmpXchg = 0x48,
932   I64AtomicCmpXchg = 0x49,
933   I32AtomicCmpXchg8U = 0x4a,
934   I32AtomicCmpXchg16U = 0x4b,
935   I64AtomicCmpXchg8U = 0x4c,
936   I64AtomicCmpXchg16U = 0x4d,
937   I64AtomicCmpXchg32U = 0x4e,
938 
939   Limit
940 };
941 
942 enum class IntrinsicId {
943 // ------------------------------------------------------------------------
944 // These are part/suffix of the MozOp::Intrinsic operators that are emitted
945 // internally when compiling intrinsic modules and are rejected by wasm
946 // validation.
947 // See wasm/WasmIntrinsic.yaml for the list.
948 #define DECL_INTRINSIC_OP(op, export, sa_name, abitype, entry, idx) \
949   op = idx,  // NOLINT
950   FOR_EACH_INTRINSIC(DECL_INTRINSIC_OP)
951 #undef DECL_INTRINSIC_OP
952 
953   // Op limit.
954   Limit
955 };
956 
957 enum class MozOp {
958   // ------------------------------------------------------------------------
959   // These operators are emitted internally when compiling asm.js and are
960   // rejected by wasm validation.  They are prefixed by MozPrefix.
961 
962   // asm.js-specific operators.  They start at 1 so as to check for
963   // uninitialized (zeroed) storage.
964   TeeGlobal = 0x01,
965   I32Min,
966   I32Max,
967   I32Neg,
968   I32BitNot,
969   I32Abs,
970   F32TeeStoreF64,
971   F64TeeStoreF32,
972   I32TeeStore8,
973   I32TeeStore16,
974   I64TeeStore8,
975   I64TeeStore16,
976   I64TeeStore32,
977   I32TeeStore,
978   I64TeeStore,
979   F32TeeStore,
980   F64TeeStore,
981   F64Mod,
982   F64Sin,
983   F64Cos,
984   F64Tan,
985   F64Asin,
986   F64Acos,
987   F64Atan,
988   F64Exp,
989   F64Log,
990   F64Pow,
991   F64Atan2,
992 
993   // asm.js-style call_indirect with the callee evaluated first.
994   OldCallDirect,
995   OldCallIndirect,
996 
997   // Intrinsic modules operations. The operator has argument leb u32 to specify
998   // particular operation id. See IntrinsicId above.
999   Intrinsic,
1000 
1001   Limit
1002 };
1003 
1004 struct OpBytes {
1005   // b0 is a byte value but has a 16-bit representation to allow for a full
1006   // 256-value range plus a sentinel Limit value.
1007   uint16_t b0;
1008   // b1 is a LEB128 value but 32 bits is enough for now.
1009   uint32_t b1;
1010 
OpBytesOpBytes1011   explicit OpBytes(Op x) {
1012     b0 = uint16_t(x);
1013     b1 = 0;
1014   }
1015   OpBytes() = default;
1016 };
1017 
1018 static const char NameSectionName[] = "name";
1019 static const char SourceMappingURLSectionName[] = "sourceMappingURL";
1020 
1021 enum class NameType { Module = 0, Function = 1, Local = 2 };
1022 
1023 enum class FieldFlags { Mutable = 0x01, AllowedMask = 0x01 };
1024 
1025 enum class FieldExtension { None, Signed, Unsigned };
1026 
1027 // The WebAssembly spec hard-codes the virtual page size to be 64KiB and
1028 // requires the size of linear memory to always be a multiple of 64KiB.
1029 
1030 static const unsigned PageSize = 64 * 1024;
1031 static const unsigned PageBits = 16;
1032 static_assert(PageSize == (1u << PageBits));
1033 
1034 static const unsigned PageMask = ((1u << PageBits) - 1);
1035 
1036 // These limits are agreed upon with other engines for consistency.
1037 
1038 static const unsigned MaxTypes = 1000000;
1039 static const unsigned MaxFuncs = 1000000;
1040 static const unsigned MaxTables = 100000;
1041 static const unsigned MaxImports = 100000;
1042 static const unsigned MaxExports = 100000;
1043 static const unsigned MaxGlobals = 1000000;
1044 static const unsigned MaxDataSegments = 100000;
1045 static const unsigned MaxDataSegmentLengthPages = 16384;
1046 static const unsigned MaxElemSegments = 10000000;
1047 static const unsigned MaxElemSegmentLength = 10000000;
1048 static const unsigned MaxTableLimitField = UINT32_MAX;
1049 static const unsigned MaxTableLength = 10000000;
1050 static const unsigned MaxLocals = 50000;
1051 static const unsigned MaxParams = 1000;
1052 static const unsigned MaxResults = 1000;
1053 static const unsigned MaxStructFields = 1000;
1054 static const uint64_t MaxMemory32LimitField = uint64_t(1) << 16;
1055 static const uint64_t MaxMemory64LimitField = uint64_t(1) << 48;
1056 static const unsigned MaxStringBytes = 100000;
1057 static const unsigned MaxModuleBytes = 1024 * 1024 * 1024;
1058 static const unsigned MaxFunctionBytes = 7654321;
1059 
1060 // These limits pertain to our WebAssembly implementation only, but may make
1061 // sense to get into the shared limits spec eventually.
1062 
1063 // See PackedTypeCode for exact bits available for these fields depending on
1064 // platform
1065 #ifdef JS_64BIT
1066 static const unsigned MaxTypeIndex = 1000000;
1067 static const unsigned MaxRttDepth = 1000;
1068 #else
1069 static const unsigned MaxTypeIndex = 15000;
1070 static const unsigned MaxRttDepth = 100;
1071 #endif
1072 
1073 static const unsigned MaxTags = 1000000;
1074 
1075 // These limits pertain to our WebAssembly implementation only.
1076 
1077 static const unsigned MaxBrTableElems = 1000000;
1078 static const unsigned MaxCodeSectionBytes = MaxModuleBytes;
1079 
1080 // 512KiB should be enough, considering how Rabaldr uses the stack and
1081 // what the standard limits are:
1082 //
1083 // - 1,000 parameters
1084 // - 50,000 locals
1085 // - 10,000 values on the eval stack (not an official limit)
1086 //
1087 // At sizeof(int64) bytes per slot this works out to about 480KiB.
1088 
1089 static const unsigned MaxFrameSize = 512 * 1024;
1090 
1091 // A magic value of rtt depth to signify that it was not specified.
1092 
1093 static const uint32_t RttDepthNone = MaxRttDepth + 1;
1094 
1095 // Asserted by Decoder::readVarU32.
1096 
1097 static const unsigned MaxVarU32DecodedBytes = 5;
1098 
1099 // Which backend to use in the case of the optimized tier.
1100 
1101 enum class OptimizedBackend {
1102   Ion,
1103   Cranelift,
1104 };
1105 
1106 // The CompileMode controls how compilation of a module is performed (notably,
1107 // how many times we compile it).
1108 
1109 enum class CompileMode { Once, Tier1, Tier2 };
1110 
1111 // Typed enum for whether debugging is enabled.
1112 
1113 enum class DebugEnabled { False, True };
1114 
1115 }  // namespace wasm
1116 }  // namespace js
1117 
1118 #endif  // wasm_constants_h
1119