Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
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_binary_h
20 : #define wasm_binary_h
21 :
22 : #include "builtin/SIMD.h"
23 :
24 : namespace js {
25 : namespace wasm {
26 :
27 : static const uint32_t MagicNumber = 0x6d736100; // "\0asm"
28 : static const uint32_t EncodingVersion = 0x01;
29 :
30 : enum class SectionId
31 : {
32 : Custom = 0,
33 : Type = 1,
34 : Import = 2,
35 : Function = 3,
36 : Table = 4,
37 : Memory = 5,
38 : Global = 6,
39 : Export = 7,
40 : Start = 8,
41 : Elem = 9,
42 : Code = 10,
43 : Data = 11
44 : };
45 :
46 : enum class TypeCode
47 : {
48 : I32 = 0x7f, // SLEB128(-0x01)
49 : I64 = 0x7e, // SLEB128(-0x02)
50 : F32 = 0x7d, // SLEB128(-0x03)
51 : F64 = 0x7c, // SLEB128(-0x04)
52 :
53 : // Only emitted internally for asm.js, likely to get collapsed into I128
54 : I8x16 = 0x7b,
55 : I16x8 = 0x7a,
56 : I32x4 = 0x79,
57 : F32x4 = 0x78,
58 : B8x16 = 0x77,
59 : B16x8 = 0x76,
60 : B32x4 = 0x75,
61 :
62 : // A function pointer with any signature
63 : AnyFunc = 0x70, // SLEB128(-0x10)
64 :
65 : // Type constructor for function types
66 : Func = 0x60, // SLEB128(-0x20)
67 :
68 : // Special code representing the block signature ()->()
69 : BlockVoid = 0x40, // SLEB128(-0x40)
70 :
71 : Limit = 0x80
72 : };
73 :
74 : enum class ValType
75 : {
76 : I32 = uint8_t(TypeCode::I32),
77 : I64 = uint8_t(TypeCode::I64),
78 : F32 = uint8_t(TypeCode::F32),
79 : F64 = uint8_t(TypeCode::F64),
80 :
81 : // ------------------------------------------------------------------------
82 : // The rest of these types are currently only emitted internally when
83 : // compiling asm.js and are rejected by wasm validation.
84 :
85 : I8x16 = uint8_t(TypeCode::I8x16),
86 : I16x8 = uint8_t(TypeCode::I16x8),
87 : I32x4 = uint8_t(TypeCode::I32x4),
88 : F32x4 = uint8_t(TypeCode::F32x4),
89 : B8x16 = uint8_t(TypeCode::B8x16),
90 : B16x8 = uint8_t(TypeCode::B16x8),
91 : B32x4 = uint8_t(TypeCode::B32x4)
92 : };
93 :
94 : typedef Vector<ValType, 8, SystemAllocPolicy> ValTypeVector;
95 :
96 : enum class DefinitionKind
97 : {
98 : Function = 0x00,
99 : Table = 0x01,
100 : Memory = 0x02,
101 : Global = 0x03
102 : };
103 :
104 : enum class GlobalTypeImmediate
105 : {
106 : IsMutable = 0x1,
107 : AllowedMask = 0x1
108 : };
109 :
110 : enum class MemoryTableFlags
111 : {
112 : Default = 0x0
113 : };
114 :
115 : enum class Op
116 : {
117 : // Control flow operators
118 : Unreachable = 0x00,
119 : Nop = 0x01,
120 : Block = 0x02,
121 : Loop = 0x03,
122 : If = 0x04,
123 : Else = 0x05,
124 : End = 0x0b,
125 : Br = 0x0c,
126 : BrIf = 0x0d,
127 : BrTable = 0x0e,
128 : Return = 0x0f,
129 :
130 : // Call operators
131 : Call = 0x10,
132 : CallIndirect = 0x11,
133 :
134 : // Parametric operators
135 : Drop = 0x1a,
136 : Select = 0x1b,
137 :
138 : // Variable access
139 : GetLocal = 0x20,
140 : SetLocal = 0x21,
141 : TeeLocal = 0x22,
142 : GetGlobal = 0x23,
143 : SetGlobal = 0x24,
144 :
145 : // Memory-related operators
146 : I32Load = 0x28,
147 : I64Load = 0x29,
148 : F32Load = 0x2a,
149 : F64Load = 0x2b,
150 : I32Load8S = 0x2c,
151 : I32Load8U = 0x2d,
152 : I32Load16S = 0x2e,
153 : I32Load16U = 0x2f,
154 : I64Load8S = 0x30,
155 : I64Load8U = 0x31,
156 : I64Load16S = 0x32,
157 : I64Load16U = 0x33,
158 : I64Load32S = 0x34,
159 : I64Load32U = 0x35,
160 : I32Store = 0x36,
161 : I64Store = 0x37,
162 : F32Store = 0x38,
163 : F64Store = 0x39,
164 : I32Store8 = 0x3a,
165 : I32Store16 = 0x3b,
166 : I64Store8 = 0x3c,
167 : I64Store16 = 0x3d,
168 : I64Store32 = 0x3e,
169 : CurrentMemory = 0x3f,
170 : GrowMemory = 0x40,
171 :
172 : // Constants
173 : I32Const = 0x41,
174 : I64Const = 0x42,
175 : F32Const = 0x43,
176 : F64Const = 0x44,
177 :
178 : // Comparison operators
179 : I32Eqz = 0x45,
180 : I32Eq = 0x46,
181 : I32Ne = 0x47,
182 : I32LtS = 0x48,
183 : I32LtU = 0x49,
184 : I32GtS = 0x4a,
185 : I32GtU = 0x4b,
186 : I32LeS = 0x4c,
187 : I32LeU = 0x4d,
188 : I32GeS = 0x4e,
189 : I32GeU = 0x4f,
190 : I64Eqz = 0x50,
191 : I64Eq = 0x51,
192 : I64Ne = 0x52,
193 : I64LtS = 0x53,
194 : I64LtU = 0x54,
195 : I64GtS = 0x55,
196 : I64GtU = 0x56,
197 : I64LeS = 0x57,
198 : I64LeU = 0x58,
199 : I64GeS = 0x59,
200 : I64GeU = 0x5a,
201 : F32Eq = 0x5b,
202 : F32Ne = 0x5c,
203 : F32Lt = 0x5d,
204 : F32Gt = 0x5e,
205 : F32Le = 0x5f,
206 : F32Ge = 0x60,
207 : F64Eq = 0x61,
208 : F64Ne = 0x62,
209 : F64Lt = 0x63,
210 : F64Gt = 0x64,
211 : F64Le = 0x65,
212 : F64Ge = 0x66,
213 :
214 : // Numeric operators
215 : I32Clz = 0x67,
216 : I32Ctz = 0x68,
217 : I32Popcnt = 0x69,
218 : I32Add = 0x6a,
219 : I32Sub = 0x6b,
220 : I32Mul = 0x6c,
221 : I32DivS = 0x6d,
222 : I32DivU = 0x6e,
223 : I32RemS = 0x6f,
224 : I32RemU = 0x70,
225 : I32And = 0x71,
226 : I32Or = 0x72,
227 : I32Xor = 0x73,
228 : I32Shl = 0x74,
229 : I32ShrS = 0x75,
230 : I32ShrU = 0x76,
231 : I32Rotl = 0x77,
232 : I32Rotr = 0x78,
233 : I64Clz = 0x79,
234 : I64Ctz = 0x7a,
235 : I64Popcnt = 0x7b,
236 : I64Add = 0x7c,
237 : I64Sub = 0x7d,
238 : I64Mul = 0x7e,
239 : I64DivS = 0x7f,
240 : I64DivU = 0x80,
241 : I64RemS = 0x81,
242 : I64RemU = 0x82,
243 : I64And = 0x83,
244 : I64Or = 0x84,
245 : I64Xor = 0x85,
246 : I64Shl = 0x86,
247 : I64ShrS = 0x87,
248 : I64ShrU = 0x88,
249 : I64Rotl = 0x89,
250 : I64Rotr = 0x8a,
251 : F32Abs = 0x8b,
252 : F32Neg = 0x8c,
253 : F32Ceil = 0x8d,
254 : F32Floor = 0x8e,
255 : F32Trunc = 0x8f,
256 : F32Nearest = 0x90,
257 : F32Sqrt = 0x91,
258 : F32Add = 0x92,
259 : F32Sub = 0x93,
260 : F32Mul = 0x94,
261 : F32Div = 0x95,
262 : F32Min = 0x96,
263 : F32Max = 0x97,
264 : F32CopySign = 0x98,
265 : F64Abs = 0x99,
266 : F64Neg = 0x9a,
267 : F64Ceil = 0x9b,
268 : F64Floor = 0x9c,
269 : F64Trunc = 0x9d,
270 : F64Nearest = 0x9e,
271 : F64Sqrt = 0x9f,
272 : F64Add = 0xa0,
273 : F64Sub = 0xa1,
274 : F64Mul = 0xa2,
275 : F64Div = 0xa3,
276 : F64Min = 0xa4,
277 : F64Max = 0xa5,
278 : F64CopySign = 0xa6,
279 :
280 : // Conversions
281 : I32WrapI64 = 0xa7,
282 : I32TruncSF32 = 0xa8,
283 : I32TruncUF32 = 0xa9,
284 : I32TruncSF64 = 0xaa,
285 : I32TruncUF64 = 0xab,
286 : I64ExtendSI32 = 0xac,
287 : I64ExtendUI32 = 0xad,
288 : I64TruncSF32 = 0xae,
289 : I64TruncUF32 = 0xaf,
290 : I64TruncSF64 = 0xb0,
291 : I64TruncUF64 = 0xb1,
292 : F32ConvertSI32 = 0xb2,
293 : F32ConvertUI32 = 0xb3,
294 : F32ConvertSI64 = 0xb4,
295 : F32ConvertUI64 = 0xb5,
296 : F32DemoteF64 = 0xb6,
297 : F64ConvertSI32 = 0xb7,
298 : F64ConvertUI32 = 0xb8,
299 : F64ConvertSI64 = 0xb9,
300 : F64ConvertUI64 = 0xba,
301 : F64PromoteF32 = 0xbb,
302 :
303 : // Reinterpretations
304 : I32ReinterpretF32 = 0xbc,
305 : I64ReinterpretF64 = 0xbd,
306 : F32ReinterpretI32 = 0xbe,
307 : F64ReinterpretI64 = 0xbf,
308 :
309 : AtomicPrefix = 0xfe,
310 : MozPrefix = 0xff,
311 :
312 : Limit = 0x100
313 : };
314 :
315 : inline bool
316 0 : IsPrefixByte(uint8_t b) {
317 0 : return b >= uint8_t(Op::AtomicPrefix);
318 : }
319 :
320 : enum class MozOp
321 : {
322 : // ------------------------------------------------------------------------
323 : // These operators are emitted internally when compiling asm.js and are
324 : // rejected by wasm validation. They are prefixed by MozPrefix.
325 :
326 : // asm.js-specific operators. They start at 1 so as to check for
327 : // uninitialized (zeroed) storage.
328 : TeeGlobal = 0x01,
329 : I32Min,
330 : I32Max,
331 : I32Neg,
332 : I32BitNot,
333 : I32Abs,
334 : F32TeeStoreF64,
335 : F64TeeStoreF32,
336 : I32TeeStore8,
337 : I32TeeStore16,
338 : I64TeeStore8,
339 : I64TeeStore16,
340 : I64TeeStore32,
341 : I32TeeStore,
342 : I64TeeStore,
343 : F32TeeStore,
344 : F64TeeStore,
345 : F64Mod,
346 : F64Sin,
347 : F64Cos,
348 : F64Tan,
349 : F64Asin,
350 : F64Acos,
351 : F64Atan,
352 : F64Exp,
353 : F64Log,
354 : F64Pow,
355 : F64Atan2,
356 :
357 : // asm.js-style call_indirect with the callee evaluated first.
358 : OldCallIndirect,
359 :
360 : // Atomics
361 : I32AtomicsCompareExchange,
362 : I32AtomicsExchange,
363 : I32AtomicsLoad,
364 : I32AtomicsStore,
365 : I32AtomicsBinOp,
366 :
367 : // SIMD
368 : #define SIMD_OPCODE(TYPE, OP) TYPE##OP,
369 : #define _(OP) SIMD_OPCODE(I8x16, OP)
370 : FORALL_INT8X16_ASMJS_OP(_)
371 : I8x16Constructor,
372 : I8x16Const,
373 : #undef _
374 : // Unsigned I8x16 operations. These are the SIMD.Uint8x16 operations that
375 : // behave differently from their SIMD.Int8x16 counterparts.
376 : I8x16extractLaneU,
377 : I8x16addSaturateU,
378 : I8x16subSaturateU,
379 : I8x16shiftRightByScalarU,
380 : I8x16lessThanU,
381 : I8x16lessThanOrEqualU,
382 : I8x16greaterThanU,
383 : I8x16greaterThanOrEqualU,
384 :
385 : #define SIMD_OPCODE(TYPE, OP) TYPE##OP,
386 : #define _(OP) SIMD_OPCODE(I16x8, OP)
387 : FORALL_INT16X8_ASMJS_OP(_)
388 : I16x8Constructor,
389 : I16x8Const,
390 : #undef _
391 : // Unsigned I16x8 operations. These are the SIMD.Uint16x8 operations that
392 : // behave differently from their SIMD.Int16x8 counterparts.
393 : I16x8extractLaneU,
394 : I16x8addSaturateU,
395 : I16x8subSaturateU,
396 : I16x8shiftRightByScalarU,
397 : I16x8lessThanU,
398 : I16x8lessThanOrEqualU,
399 : I16x8greaterThanU,
400 : I16x8greaterThanOrEqualU,
401 :
402 : #define SIMD_OPCODE(TYPE, OP) TYPE##OP,
403 : #define _(OP) SIMD_OPCODE(I32x4, OP)
404 : FORALL_INT32X4_ASMJS_OP(_)
405 : I32x4Constructor,
406 : I32x4Const,
407 : #undef _
408 : // Unsigned I32x4 operations. These are the SIMD.Uint32x4 operations that
409 : // behave differently from their SIMD.Int32x4 counterparts.
410 : I32x4shiftRightByScalarU,
411 : I32x4lessThanU,
412 : I32x4lessThanOrEqualU,
413 : I32x4greaterThanU,
414 : I32x4greaterThanOrEqualU,
415 : I32x4fromFloat32x4U,
416 : #define _(OP) SIMD_OPCODE(F32x4, OP)
417 : FORALL_FLOAT32X4_ASMJS_OP(_)
418 : F32x4Constructor,
419 : F32x4Const,
420 : #undef _
421 :
422 : #define _(OP) SIMD_OPCODE(B8x16, OP)
423 : FORALL_BOOL_SIMD_OP(_)
424 : B8x16Constructor,
425 : B8x16Const,
426 : #undef _
427 : #undef OPCODE
428 :
429 : #define _(OP) SIMD_OPCODE(B16x8, OP)
430 : FORALL_BOOL_SIMD_OP(_)
431 : B16x8Constructor,
432 : B16x8Const,
433 : #undef _
434 : #undef OPCODE
435 :
436 : #define _(OP) SIMD_OPCODE(B32x4, OP)
437 : FORALL_BOOL_SIMD_OP(_)
438 : B32x4Constructor,
439 : B32x4Const,
440 : #undef _
441 : #undef OPCODE
442 :
443 : Limit
444 : };
445 :
446 : struct OpBytes
447 : {
448 : // The bytes of the opcode have 16-bit representations to allow for a full
449 : // 256-value range plus a sentinel Limit value.
450 : uint16_t b0;
451 : uint16_t b1;
452 :
453 0 : explicit OpBytes(Op x) {
454 0 : b0 = uint16_t(x);
455 0 : b1 = 0;
456 0 : }
457 0 : OpBytes() = default;
458 : };
459 :
460 : static const char NameSectionName[] = "name";
461 : static const char SourceMappingURLSectionName[] = "sourceMappingURL";
462 :
463 : enum class NameType
464 : {
465 : Module = 0,
466 : Function = 1,
467 : Local = 2
468 : };
469 :
470 : // Telemetry sample values for the JS_AOT_USAGE key, indicating whether asm.js
471 : // or WebAssembly is used.
472 :
473 : enum class Telemetry
474 : {
475 : ASMJS = 0,
476 : WASM = 1
477 : };
478 :
479 : // These limits are agreed upon with other engines for consistency.
480 :
481 : static const unsigned MaxTypes = 1000000;
482 : static const unsigned MaxFuncs = 1000000;
483 : static const unsigned MaxImports = 100000;
484 : static const unsigned MaxExports = 100000;
485 : static const unsigned MaxGlobals = 1000000;
486 : static const unsigned MaxDataSegments = 100000;
487 : static const unsigned MaxElemSegments = 10000000;
488 : static const unsigned MaxTableInitialLength = 10000000;
489 : static const unsigned MaxStringBytes = 100000;
490 : static const unsigned MaxLocals = 50000;
491 : static const unsigned MaxParams = 1000;
492 : static const unsigned MaxBrTableElems = 1000000;
493 : static const unsigned MaxMemoryInitialPages = 16384;
494 : static const unsigned MaxMemoryMaximumPages = 65536;
495 : static const unsigned MaxModuleBytes = 1024 * 1024 * 1024;
496 : static const unsigned MaxFunctionBytes = 128 * 1024;
497 :
498 : // To be able to assign function indices during compilation while the number of
499 : // imports is still unknown, asm.js sets a maximum number of imports so it can
500 : // immediately start handing out function indices starting at the maximum + 1.
501 : // this means that there is a "hole" between the last import and the first
502 : // definition, but that's fine.
503 :
504 : static const unsigned AsmJSMaxTypes = 4 * 1024;
505 : static const unsigned AsmJSMaxFuncs = 512 * 1024;
506 : static const unsigned AsmJSMaxImports = 4 * 1024;
507 : static const unsigned AsmJSMaxTables = 4 * 1024;
508 : static const unsigned AsmJSFirstDefFuncIndex = AsmJSMaxImports + 1;
509 :
510 : static_assert(AsmJSMaxTypes <= MaxTypes, "conservative");
511 : static_assert(AsmJSMaxImports <= MaxImports, "conservative");
512 : static_assert(AsmJSFirstDefFuncIndex < MaxFuncs, "conservative");
513 :
514 : } // namespace wasm
515 : } // namespace js
516 :
517 : #endif // wasm_binary_h
|