summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/lib/wasm-binary.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit-test/lib/wasm-binary.js')
-rw-r--r--js/src/jit-test/lib/wasm-binary.js555
1 files changed, 555 insertions, 0 deletions
diff --git a/js/src/jit-test/lib/wasm-binary.js b/js/src/jit-test/lib/wasm-binary.js
new file mode 100644
index 0000000000..93ddc0571d
--- /dev/null
+++ b/js/src/jit-test/lib/wasm-binary.js
@@ -0,0 +1,555 @@
+// MagicNumber = 0x6d736100;
+const magic0 = 0x00; // '\0'
+const magic1 = 0x61; // 'a'
+const magic2 = 0x73; // 's'
+const magic3 = 0x6d; // 'm'
+
+// EncodingVersion
+const encodingVersion = 0x1;
+const ver0 = (encodingVersion >>> 0) & 0xff;
+const ver1 = (encodingVersion >>> 8) & 0xff;
+const ver2 = (encodingVersion >>> 16) & 0xff;
+const ver3 = (encodingVersion >>> 24) & 0xff;
+
+// Section opcodes
+const userDefinedId = 0;
+const typeId = 1;
+const importId = 2;
+const functionId = 3;
+const tableId = 4;
+const memoryId = 5;
+const globalId = 6;
+const exportId = 7;
+const startId = 8;
+const elemId = 9;
+const codeId = 10;
+const dataId = 11;
+const dataCountId = 12;
+const tagId = 13;
+
+// User-defined section names
+const nameName = "name";
+
+// Name section name types
+const nameTypeModule = 0;
+const nameTypeFunction = 1;
+const nameTypeLocal = 2;
+const nameTypeTag = 3;
+
+// Type codes
+const I32Code = 0x7f;
+const I64Code = 0x7e;
+const F32Code = 0x7d;
+const F64Code = 0x7c;
+const V128Code = 0x7b;
+const AnyFuncCode = 0x70;
+const ExternRefCode = 0x6f;
+const EqRefCode = 0x6d;
+const OptRefCode = 0x6c;
+const FuncCode = 0x60;
+const VoidCode = 0x40;
+
+// Opcodes
+const UnreachableCode = 0x00
+const BlockCode = 0x02;
+const TryCode = 0x06;
+const CatchCode = 0x07;
+const ThrowCode = 0x08;
+const RethrowCode = 0x09;
+const EndCode = 0x0b;
+const ReturnCode = 0x0f;
+const CallCode = 0x10;
+const CallIndirectCode = 0x11;
+const DelegateCode = 0x18;
+const DropCode = 0x1a;
+const SelectCode = 0x1b;
+const LocalGetCode = 0x20;
+const I32Load = 0x28;
+const I64Load = 0x29;
+const F32Load = 0x2a;
+const F64Load = 0x2b;
+const I32Load8S = 0x2c;
+const I32Load8U = 0x2d;
+const I32Load16S = 0x2e;
+const I32Load16U = 0x2f;
+const I64Load8S = 0x30;
+const I64Load8U = 0x31;
+const I64Load16S = 0x32;
+const I64Load16U = 0x33;
+const I64Load32S = 0x34;
+const I64Load32U = 0x35;
+const I32Store = 0x36;
+const I64Store = 0x37;
+const F32Store = 0x38;
+const F64Store = 0x39;
+const I32Store8 = 0x3a;
+const I32Store16 = 0x3b;
+const I64Store8 = 0x3c;
+const I64Store16 = 0x3d;
+const I64Store32 = 0x3e;
+const GrowMemoryCode = 0x40;
+const I32ConstCode = 0x41;
+const I64ConstCode = 0x42;
+const F32ConstCode = 0x43;
+const F64ConstCode = 0x44;
+const I32AddCode = 0x6a;
+const I32DivSCode = 0x6d;
+const I32DivUCode = 0x6e;
+const I32RemSCode = 0x6f;
+const I32RemUCode = 0x70;
+const I32TruncSF32Code = 0xa8;
+const I32TruncUF32Code = 0xa9;
+const I32TruncSF64Code = 0xaa;
+const I32TruncUF64Code = 0xab;
+const I64TruncSF32Code = 0xae;
+const I64TruncUF32Code = 0xaf;
+const I64TruncSF64Code = 0xb0;
+const I64TruncUF64Code = 0xb1;
+const I64DivSCode = 0x7f;
+const I64DivUCode = 0x80;
+const I64RemSCode = 0x81;
+const I64RemUCode = 0x82;
+const RefNullCode = 0xd0;
+const RefIsNullCode = 0xd1;
+const RefFuncCode = 0xd2;
+
+// SIMD opcodes
+const V128LoadCode = 0x00;
+const V128StoreCode = 0x0b;
+const I32x4DotSI16x8Code = 0xba;
+const F32x4CeilCode = 0xd8;
+const F32x4FloorCode = 0xd9;
+const F32x4TruncCode = 0xda;
+const F32x4NearestCode = 0xdb;
+const F64x2CeilCode = 0xdc;
+const F64x2FloorCode = 0xdd;
+const F64x2TruncCode = 0xde;
+const F64x2NearestCode = 0xdf;
+const F32x4PMinCode = 0xea;
+const F32x4PMaxCode = 0xeb;
+const F64x2PMinCode = 0xf6;
+const F64x2PMaxCode = 0xf7;
+const V128Load32ZeroCode = 0xfc;
+const V128Load64ZeroCode = 0xfd;
+
+// Relaxed SIMD opcodes.
+const I8x16RelaxedSwizzleCode = 0x100;
+const I32x4RelaxedTruncSSatF32x4Code = 0x101;
+const I32x4RelaxedTruncUSatF32x4Code = 0x102;
+const I32x4RelaxedTruncSatF64x2SZeroCode = 0x103;
+const I32x4RelaxedTruncSatF64x2UZeroCode = 0x104;
+const F32x4RelaxedFmaCode = 0x105;
+const F32x4RelaxedFnmaCode = 0x106;
+const F64x2RelaxedFmaCode = 0x107;
+const F64x2RelaxedFnmaCode = 0x108;
+const I8x16RelaxedLaneSelectCode = 0x109;
+const I16x8RelaxedLaneSelectCode = 0x10a;
+const I32x4RelaxedLaneSelectCode = 0x10b;
+const I64x2RelaxedLaneSelectCode = 0x10c;
+const F32x4RelaxedMinCode = 0x10d;
+const F32x4RelaxedMaxCode = 0x10e;
+const F64x2RelaxedMinCode = 0x10f;
+const F64x2RelaxedMaxCode = 0x110;
+const I16x8RelaxedQ15MulrS = 0x111;
+const I16x8DotI8x16I7x16S = 0x112;
+const I32x4DotI8x16I7x16AddS = 0x113;
+
+const FirstInvalidOpcode = 0xc5;
+const LastInvalidOpcode = 0xfa;
+const GcPrefix = 0xfb;
+const MiscPrefix = 0xfc;
+const SimdPrefix = 0xfd;
+const ThreadPrefix = 0xfe;
+const MozPrefix = 0xff;
+
+// See WasmConstants.h for documentation.
+// Limit this to a group of 8 per line.
+
+const definedOpcodes =
+ [0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ ...(wasmExceptionsEnabled() ? [0x06, 0x07, 0x08, 0x09] : []),
+ 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11,
+ ...(wasmFunctionReferencesEnabled() ? [0x14] : []),
+ ...(wasmExceptionsEnabled() ? [0x18, 0x19] : []),
+ 0x1a, 0x1b, 0x1c,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
+ 0xf0,
+ 0xfb, 0xfc, 0xfd, 0xfe, 0xff ];
+
+const undefinedOpcodes = (function () {
+ let a = [];
+ let j = 0;
+ let i = 0;
+ while (i < 256) {
+ while (definedOpcodes[j] > i)
+ a.push(i++);
+ assertEq(definedOpcodes[j], i);
+ i++;
+ j++;
+ }
+ assertEq(definedOpcodes.length + a.length, 256);
+ return a;
+})();
+
+// Secondary opcode bytes for misc prefix
+const MemoryInitCode = 0x08; // Pending
+const DataDropCode = 0x09; // Pending
+const MemoryCopyCode = 0x0a; // Pending
+const MemoryFillCode = 0x0b; // Pending
+const TableInitCode = 0x0c; // Pending
+const ElemDropCode = 0x0d; // Pending
+const TableCopyCode = 0x0e; // Pending
+
+const StructNew = 0x00; // UNOFFICIAL
+const StructGet = 0x03; // UNOFFICIAL
+const StructSet = 0x06; // UNOFFICIAL
+
+// DefinitionKind
+const FunctionCode = 0x00;
+const TableCode = 0x01;
+const MemoryCode = 0x02;
+const GlobalCode = 0x03;
+const TagCode = 0x04;
+
+// ResizableFlags
+const HasMaximumFlag = 0x1;
+
+function toU8(array) {
+ for (let b of array)
+ assertEq(b < 256, true);
+ return Uint8Array.from(array);
+}
+
+function varU32(u32) {
+ assertEq(u32 >= 0, true);
+ assertEq(u32 < Math.pow(2,32), true);
+ var bytes = [];
+ do {
+ var byte = u32 & 0x7f;
+ u32 >>>= 7;
+ if (u32 != 0)
+ byte |= 0x80;
+ bytes.push(byte);
+ } while (u32 != 0);
+ return bytes;
+}
+
+function varS32(s32) {
+ assertEq(s32 >= -Math.pow(2,31), true);
+ assertEq(s32 < Math.pow(2,31), true);
+ var bytes = [];
+ do {
+ var byte = s32 & 0x7f;
+ s32 >>= 7;
+ if (s32 != 0 && s32 != -1)
+ byte |= 0x80;
+ bytes.push(byte);
+ } while (s32 != 0 && s32 != -1);
+ return bytes;
+}
+
+function moduleHeaderThen(...rest) {
+ return [magic0, magic1, magic2, magic3, ver0, ver1, ver2, ver3, ...rest];
+}
+
+function string(name) {
+ var nameBytes = name.split('').map(c => {
+ var code = c.charCodeAt(0);
+ assertEq(code < 128, true); // TODO
+ return code
+ });
+ return varU32(nameBytes.length).concat(nameBytes);
+}
+
+function encodedString(name, len) {
+ var name = unescape(encodeURIComponent(name)); // break into string of utf8 code points
+ var nameBytes = name.split('').map(c => c.charCodeAt(0)); // map to array of numbers
+ return varU32(len === undefined ? nameBytes.length : len).concat(nameBytes);
+}
+
+function moduleWithSections(sectionArray) {
+ var bytes = moduleHeaderThen();
+ for (let section of sectionArray) {
+ bytes.push(section.name);
+ bytes.push(...varU32(section.body.length));
+ bytes.push(...section.body);
+ }
+ return toU8(bytes);
+}
+
+function sigSection(sigs) {
+ var body = [];
+ body.push(...varU32(sigs.length));
+ for (let sig of sigs) {
+ body.push(...varU32(FuncCode));
+ body.push(...varU32(sig.args.length));
+ for (let arg of sig.args)
+ body.push(...varU32(arg));
+ if (sig.ret == VoidCode) {
+ body.push(...varU32(0));
+ } else if (typeof sig.ret == "number") {
+ body.push(...varU32(1));
+ body.push(...varU32(sig.ret));
+ } else {
+ body.push(...varU32(sig.ret.length));
+ for (let r of sig.ret)
+ body.push(...varU32(r));
+ }
+ }
+ return { name: typeId, body };
+}
+
+function declSection(decls) {
+ var body = [];
+ body.push(...varU32(decls.length));
+ for (let decl of decls)
+ body.push(...varU32(decl));
+ return { name: functionId, body };
+}
+
+function funcBody(func, withEndCode=true) {
+ var body = varU32(func.locals.length);
+ for (let local of func.locals)
+ body.push(...varU32(local));
+ body = body.concat(...func.body);
+ if (withEndCode)
+ body.push(EndCode);
+ body.splice(0, 0, ...varU32(body.length));
+ return body;
+}
+
+function bodySection(bodies) {
+ var body = varU32(bodies.length).concat(...bodies);
+ return { name: codeId, body };
+}
+
+function importSection(imports) {
+ var body = [];
+ body.push(...varU32(imports.length));
+ for (let imp of imports) {
+ body.push(...string(imp.module));
+ body.push(...string(imp.func));
+ body.push(...varU32(FunctionCode));
+ body.push(...varU32(imp.sigIndex));
+ }
+ return { name: importId, body };
+}
+
+function exportSection(exports) {
+ var body = [];
+ body.push(...varU32(exports.length));
+ for (let exp of exports) {
+ body.push(...string(exp.name));
+ if (exp.hasOwnProperty("funcIndex")) {
+ body.push(...varU32(FunctionCode));
+ body.push(...varU32(exp.funcIndex));
+ } else if (exp.hasOwnProperty("memIndex")) {
+ body.push(...varU32(MemoryCode));
+ body.push(...varU32(exp.memIndex));
+ } else if (exp.hasOwnProperty("tagIndex")) {
+ body.push(...varU32(TagCode));
+ body.push(...varU32(exp.tagIndex));
+ } else {
+ throw "Bad export " + exp;
+ }
+ }
+ return { name: exportId, body };
+}
+
+function tableSection(initialSize) {
+ var body = [];
+ body.push(...varU32(1)); // number of tables
+ body.push(...varU32(AnyFuncCode));
+ body.push(...varU32(0x0)); // for now, no maximum
+ body.push(...varU32(initialSize));
+ return { name: tableId, body };
+}
+
+function memorySection(initialSize) {
+ var body = [];
+ body.push(...varU32(1)); // number of memories
+ body.push(...varU32(0x0)); // for now, no maximum
+ body.push(...varU32(initialSize));
+ return { name: memoryId, body };
+}
+
+function tagSection(tags) {
+ var body = [];
+ body.push(...varU32(tags.length));
+ for (let tag of tags) {
+ body.push(...varU32(0)); // exception attribute
+ body.push(...varU32(tag.type));
+ }
+ return { name: tagId, body };
+}
+
+function dataSection(segmentArrays) {
+ var body = [];
+ body.push(...varU32(segmentArrays.length));
+ for (let array of segmentArrays) {
+ body.push(...varU32(0)); // table index
+ body.push(...varU32(I32ConstCode));
+ body.push(...varS32(array.offset));
+ body.push(...varU32(EndCode));
+ body.push(...varU32(array.elems.length));
+ for (let elem of array.elems)
+ body.push(...varU32(elem));
+ }
+ return { name: dataId, body };
+}
+
+function dataCountSection(count) {
+ var body = [];
+ body.push(...varU32(count));
+ return { name: dataCountId, body };
+}
+
+function globalSection(globalArray) {
+ var body = [];
+ body.push(...varU32(globalArray.length));
+ for (let globalObj of globalArray) {
+ // Value type
+ body.push(...varU32(globalObj.valType));
+ // Flags
+ body.push(globalObj.flags & 255);
+ // Initializer expression
+ body.push(...globalObj.initExpr);
+ }
+ return { name: globalId, body };
+}
+
+function elemSection(elemArrays) {
+ var body = [];
+ body.push(...varU32(elemArrays.length));
+ for (let array of elemArrays) {
+ body.push(...varU32(0)); // table index
+ body.push(...varU32(I32ConstCode));
+ body.push(...varS32(array.offset));
+ body.push(...varU32(EndCode));
+ body.push(...varU32(array.elems.length));
+ for (let elem of array.elems)
+ body.push(...varU32(elem));
+ }
+ return { name: elemId, body };
+}
+
+// For now, the encoding spec is here:
+// https://github.com/WebAssembly/bulk-memory-operations/issues/98#issuecomment-507330729
+
+const LegacyActiveExternVal = 0;
+const PassiveExternVal = 1;
+const ActiveExternVal = 2;
+const DeclaredExternVal = 3;
+const LegacyActiveElemExpr = 4;
+const PassiveElemExpr = 5;
+const ActiveElemExpr = 6;
+const DeclaredElemExpr = 7;
+
+function generalElemSection(elemObjs) {
+ let body = [];
+ body.push(...varU32(elemObjs.length));
+ for (let elemObj of elemObjs) {
+ body.push(elemObj.flag);
+ if ((elemObj.flag & 3) == 2)
+ body.push(...varU32(elemObj.table));
+ // TODO: This is not very flexible
+ if ((elemObj.flag & 1) == 0) {
+ body.push(...varU32(I32ConstCode));
+ body.push(...varS32(elemObj.offset));
+ body.push(...varU32(EndCode));
+ }
+ if (elemObj.flag & 4) {
+ if (elemObj.flag & 3)
+ body.push(elemObj.typeCode & 255);
+ // Each element is an array of bytes
+ body.push(...varU32(elemObj.elems.length));
+ for (let elemBytes of elemObj.elems)
+ body.push(...elemBytes);
+ } else {
+ if (elemObj.flag & 3)
+ body.push(elemObj.externKind & 255);
+ // Each element is a putative function index
+ body.push(...varU32(elemObj.elems.length));
+ for (let elem of elemObj.elems)
+ body.push(...varU32(elem));
+ }
+ }
+ return { name: elemId, body };
+}
+
+function moduleNameSubsection(moduleName) {
+ var body = [];
+ body.push(...varU32(nameTypeModule));
+
+ var subsection = encodedString(moduleName);
+ body.push(...varU32(subsection.length));
+ body.push(...subsection);
+
+ return body;
+}
+
+function funcNameSubsection(funcNames) {
+ var body = [];
+ body.push(...varU32(nameTypeFunction));
+
+ var subsection = varU32(funcNames.length);
+
+ var funcIndex = 0;
+ for (let f of funcNames) {
+ subsection.push(...varU32(f.index ? f.index : funcIndex));
+ subsection.push(...encodedString(f.name, f.nameLen));
+ funcIndex++;
+ }
+
+ body.push(...varU32(subsection.length));
+ body.push(...subsection);
+ return body;
+}
+
+function nameSection(subsections) {
+ var body = [];
+ body.push(...string(nameName));
+
+ for (let ss of subsections)
+ body.push(...ss);
+
+ return { name: userDefinedId, body };
+}
+
+function customSection(name, ...body) {
+ return { name: userDefinedId, body: [...string(name), ...body] };
+}
+
+function tableSection0() {
+ var body = [];
+ body.push(...varU32(0)); // number of tables
+ return { name: tableId, body };
+}
+
+function memorySection0() {
+ var body = [];
+ body.push(...varU32(0)); // number of memories
+ return { name: memoryId, body };
+}