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