WebAssembly: update binary format to 0xD version
authorjfbastien@apple.com <jfbastien@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 1 Dec 2016 07:04:18 +0000 (07:04 +0000)
committerjfbastien@apple.com <jfbastien@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 1 Dec 2016 07:04:18 +0000 (07:04 +0000)
https://bugs.webkit.org/show_bug.cgi?id=164724

Reviewed by Saam Barati.

As described in the following PR: https://github.com/WebAssembly/design/pull/836

JSTests:

* wasm/Builder.js:
(const._normalizeFunctionSignature):
* wasm/Builder_WebAssemblyBinary.js:
(const.emitters.Type):
(const.emitters.Code):
* wasm/LowLevelBinary.js:
(export.default.LowLevelBinary.prototype.block_type):
(export.default.LowLevelBinary.prototype.inline_signature_type): Deleted.
* wasm/WASM.js:
* wasm/js-api/test_basic_api.js:
* wasm/self-test/test_BuilderWebAssembly.js:
(EmptyModule):
(CustomSection):
* wasm/self-test/test_WASM.js:
* wasm/wasm.json:

Source/JavaScriptCore:

* wasm/WasmB3IRGenerator.cpp:
(JSC::Wasm::B3IRGenerator::B3IRGenerator):
(JSC::Wasm::B3IRGenerator::zeroForType):
(JSC::Wasm::B3IRGenerator::addConstant):
(JSC::Wasm::createJSWrapper):
* wasm/WasmCallingConvention.h:
(JSC::Wasm::CallingConvention::marshallArgument):
* wasm/WasmFormat.cpp:
(JSC::Wasm::toString): Deleted.
* wasm/WasmFormat.h:
(JSC::Wasm::isValueType):
(JSC::Wasm::toB3Type): Deleted.
* wasm/WasmFunctionParser.h:
(JSC::Wasm::FunctionParser<Context>::parseExpression):
* wasm/WasmModuleParser.cpp:
(JSC::Wasm::ModuleParser::parse):
(JSC::Wasm::ModuleParser::parseType):
* wasm/WasmModuleParser.h:
* wasm/WasmParser.h:
(JSC::Wasm::Parser::parseResultType):
* wasm/generateWasm.py:
(Wasm.__init__):
* wasm/generateWasmOpsHeader.py:
(cppMacro):
(typeMacroizer):
(opcodeMacroizer):
* wasm/wasm.json:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@209175 268f45cc-cd09-0410-ab3c-d52691b4dbfc

22 files changed:
JSTests/ChangeLog
JSTests/wasm/Builder.js
JSTests/wasm/Builder_WebAssemblyBinary.js
JSTests/wasm/LowLevelBinary.js
JSTests/wasm/WASM.js
JSTests/wasm/js-api/test_basic_api.js
JSTests/wasm/self-test/test_BuilderWebAssembly.js
JSTests/wasm/self-test/test_WASM.js
JSTests/wasm/wasm.json
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp
Source/JavaScriptCore/wasm/WasmCallingConvention.h
Source/JavaScriptCore/wasm/WasmFormat.cpp
Source/JavaScriptCore/wasm/WasmFormat.h
Source/JavaScriptCore/wasm/WasmFunctionParser.h
Source/JavaScriptCore/wasm/WasmModuleParser.cpp
Source/JavaScriptCore/wasm/WasmModuleParser.h
Source/JavaScriptCore/wasm/WasmParser.h
Source/JavaScriptCore/wasm/generateWasm.py
Source/JavaScriptCore/wasm/generateWasmOpsHeader.py
Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp
Source/JavaScriptCore/wasm/wasm.json

index 1e536ec..83bf61c 100644 (file)
@@ -1,5 +1,30 @@
 2016-11-30  JF Bastien  <jfbastien@apple.com>
 
+        WebAssembly: update binary format to 0xD version
+        https://bugs.webkit.org/show_bug.cgi?id=164724
+
+        Reviewed by Saam Barati.
+
+        As described in the following PR: https://github.com/WebAssembly/design/pull/836
+
+        * wasm/Builder.js:
+        (const._normalizeFunctionSignature):
+        * wasm/Builder_WebAssemblyBinary.js:
+        (const.emitters.Type):
+        (const.emitters.Code):
+        * wasm/LowLevelBinary.js:
+        (export.default.LowLevelBinary.prototype.block_type):
+        (export.default.LowLevelBinary.prototype.inline_signature_type): Deleted.
+        * wasm/WASM.js:
+        * wasm/js-api/test_basic_api.js:
+        * wasm/self-test/test_BuilderWebAssembly.js:
+        (EmptyModule):
+        (CustomSection):
+        * wasm/self-test/test_WASM.js:
+        * wasm/wasm.json:
+
+2016-11-30  JF Bastien  <jfbastien@apple.com>
+
         WebAssembly builder: don't throw when checker not implemented
         https://bugs.webkit.org/show_bug.cgi?id=165219
 
index 754c9e1..cecb2c7 100644 (file)
@@ -51,7 +51,7 @@ const _normalizeFunctionSignature = (params, ret) => {
     if (typeof(ret) === "undefined")
         ret = "void";
     assert.isNotArray(ret, `Multiple return values not supported by WebAssembly yet`);
-    assert.falsy(ret !== "void" && !WASM.isValidValueType(ret), `Type return ${ret} must be valid value type`);
+    assert.truthy(WASM.isValidBlockType(ret), `Type return ${ret} must be valid block type`);
     return [params, ret];
 };
 
@@ -156,7 +156,7 @@ const _exportFunctionContinuation = (builder, section, nextBuilder) => {
 
 const _checkStackArgs = (op, param) => {
     for (let expect of param) {
-        if (WASM.isValidValueType(expect)) {
+        if (WASM.isValidType(expect)) {
             // FIXME implement stack checks for arguments. https://bugs.webkit.org/show_bug.cgi?id=163421
         } else {
             // Handle our own meta-types.
@@ -177,7 +177,7 @@ const _checkStackArgs = (op, param) => {
 
 const _checkStackReturn = (op, ret) => {
     for (let expect of ret) {
-        if (WASM.isValidValueType(expect)) {
+        if (WASM.isValidType(expect)) {
             // FIXME implement stack checks for return. https://bugs.webkit.org/show_bug.cgi?id=163421
         } else {
             // Handle our own meta-types.
@@ -221,8 +221,7 @@ const _checkImms = (op, imms, expectedImms, ret) => {
         case "default_target": break; // improve checking https://bugs.webkit.org/show_bug.cgi?id=163421
         case "relative_depth": break; // improve checking https://bugs.webkit.org/show_bug.cgi?id=163421
         case "sig":
-            // FIXME this should be isValidBlockType https://bugs.webkit.org/show_bug.cgi?id=164724
-            assert.truthy(imms[idx] === "void" || WASM.isValidValueType(imms[idx]), `Invalid block type on ${op}: "${imms[idx]}"`);
+            assert.truthy(WASM.isValidBlockType(imms[idx]), `Invalid block type on ${op}: "${imms[idx]}"`);
             break;
         case "target_count": break; // improve checking https://bugs.webkit.org/show_bug.cgi?id=163421
         case "target_table": break; // improve checking https://bugs.webkit.org/show_bug.cgi?id=163421
index 2103ed3..494641a 100644 (file)
@@ -33,16 +33,15 @@ const emitters = {
     Type: (section, bin) => {
         put(bin, "varuint32", section.data.length);
         for (const entry of section.data) {
-            const funcTypeConstructor = -0x20; // FIXME Move this to wasm.json.
-            put(bin, "varint7", funcTypeConstructor);
+            put(bin, "varint7", WASM.typeValue["func"]);
             put(bin, "varuint32", entry.params.length);
             for (const param of entry.params)
-                put(bin, "uint8", WASM.valueTypeValue[param]);
+                put(bin, "varint7", WASM.typeValue[param]);
             if (entry.ret === "void")
                 put(bin, "varuint1", 0);
             else {
                 put(bin, "varuint1", 1);
-                put(bin, "uint8", WASM.valueTypeValue[entry.ret]);
+                put(bin, "varint7", WASM.typeValue[entry.ret]);
             }
         }
     },
@@ -107,7 +106,7 @@ const emitters = {
             put(funcBin, "varuint32", localCount);
             for (let i = func.parameterCount; i < func.locals.length; ++i) {
                 put(funcBin, "varuint32", 1);
-                put(funcBin, "uint8", WASM.valueTypeValue[func.locals[i]]);
+                put(funcBin, "varint7", WASM.typeValue[func.locals[i]]);
             }
 
             for (const op of func.code) {
index 0bd4237..814cb91 100644 (file)
@@ -159,8 +159,10 @@ export default class LowLevelBinary {
             throw new RangeError(`Invalid varuint7 ${v} range is [${varuint32Min}, ${varuint7Max}]`);
         this.varuint32(v);
     }
-    inline_signature_type(v) {
-        this.varint7(WASM.valueTypeValue[v]);
+    block_type(v) {
+        if (!WASM.isValidBlockType(v))
+            throw new Error(`Invalid block type ${v}`);
+        this.varint7(WASM.typeValue[v]);
     }
     string(str) {
         let patch = this.newPatchable("varuint32");
index d8eaef6..1bb79b8 100644 (file)
@@ -33,10 +33,14 @@ const _mapValues = from => {
 };
 
 export const description = utilities.json("wasm.json");
-export const valueType = Object.keys(description.value_type);
-const _valueTypeSet = new Set(valueType);
+export const type = Object.keys(description.type);
+const _typeSet = new Set(type);
+export const isValidType = v => _typeSet.has(v);
+export const typeValue = _mapValues(description.type);
+const _valueTypeSet = new Set(description.value_type);
 export const isValidValueType = v => _valueTypeSet.has(v);
-export const valueTypeValue = _mapValues(description.value_type);
+const _blockTypeSet = new Set(description.block_type);
+export const isValidBlockType = v => _blockTypeSet.has(v);
 export const externalKindValue = _mapValues(description.external_kind);
 export const sections = Object.keys(description.section);
 export const sectionEncodingType = description.section[sections[0]].type;
index 73c5a83..3f7d0bd 100644 (file)
@@ -1,7 +1,7 @@
 import * as assert from '../assert.js';
 import * as utilities from '../utilities.js';
 
-const version = 0xC;
+const version = 0x0D;
 const emptyModuleArray = Uint8Array.of(0x0, 0x61, 0x73, 0x6d, version, 0x00, 0x00, 0x00);
 const invalidConstructorInputs = [undefined, null, "", 1, {}, []];
 const invalidInstanceImports = [null, "", 1];
index 8d8112d..57ef43d 100644 (file)
@@ -6,7 +6,7 @@ import Builder from '../Builder.js';
     const bin = builder.WebAssembly();
     // Note: this will change as we update version number.
     assert.eq(bin.hexdump().trim(),
-              "00000000 00 61 73 6d 0c 00 00 00                          |·asm····        |");
+              "00000000 00 61 73 6d 0d 00 00 00                          |·asm····        |");
 })();
 
 (function EmptyModule() {
@@ -27,6 +27,6 @@ import Builder from '../Builder.js';
         .End()
         .WebAssembly();
     assert.eq(bin.hexdump().trim(),
-              ["00000000 00 61 73 6d 0c 00 00 00 00 0a 05 4f 48 48 41 49  |·asm·······OHHAI|",
+              ["00000000 00 61 73 6d 0d 00 00 00 00 0a 05 4f 48 48 41 49  |·asm·······OHHAI|",
                "00000010 de ad c0 fe                                      |····            |"].join("\n"));
 })();
index 997797f..11aa069 100644 (file)
@@ -2,17 +2,16 @@ import * as assert from '../assert.js';
 import * as WASM from '../WASM.js';
 
 assert.isNotUndef(WASM.description);
-assert.isNotUndef(WASM.valueType);
-assert.ge(WASM.valueType.length, 4);
+assert.isNotUndef(WASM.type);
+assert.ge(WASM.type.length, 7);
 
-for (const v of WASM.valueType)
-    if (!WASM.isValidValueType(v))
-        throw new Error(`Expected value ${v} to be a valid value type`);
+for (const v of WASM.type)
+    if (!WASM.isValidType(v))
+        throw new Error(`Expected value ${v} to be a valid type`);
 
 const expectedFields = [
     "preamble",
-    "value_type",
-    "inline_signature_type",
+    "type",
     "external_kind",
     "section",
     "opcode",
index d8f7c91..34878ea 100644 (file)
@@ -1,25 +1,23 @@
 {
     "comments": ["This file describes the WebAssembly ISA.",
-                 "Scripts in this folder auto-generate C++ code for JavaScriptCore as well as the testing DSL which WebKit's WebAssembly tests use.",
-                 "When you update this file you need to re-generate the C++ code: jsc ./JSTests/stress/wasm/generate-wasmops-header.js > ./Source/JavaScriptCore/wasm/WASMOps.h"
+                 "Scripts in this folder auto-generate C++ code for JavaScriptCore as well as the testing DSL which WebKit's WebAssembly tests use."
                 ],
     "preamble": [
         { "name": "magic number", "type": "uint32", "value": 1836278016, "description": "NULL character followed by 'asm'" },
-        { "name": "version",      "type": "uint32", "value":         12, "description": "Version number, will be reset to 1 for MVP" }
+        { "name": "version",      "type": "uint32", "value":         13, "description": "Version number, will be reset to 1 for MVP" }
     ],
-    "value_type" : {
-        "i32": { "type": "uint8", "value": 1 },
-        "i64": { "type": "uint8", "value": 2 },
-        "f32": { "type": "uint8", "value": 3 },
-        "f64": { "type": "uint8", "value": 4 }
-    },
-    "inline_signature_type" : {
-        "void": { "type": "uint8", "value": 0 },
-        "i32":  { "type": "uint8", "value": 1 },
-        "i64":  { "type": "uint8", "value": 2 },
-        "f32":  { "type": "uint8", "value": 3 },
-        "f64":  { "type": "uint8", "value": 4 }
+    "type" : {
+        "i32":     { "type": "varint7", "value":  -1, "b3type": "B3::Int32" },
+        "i64":     { "type": "varint7", "value":  -2, "b3type": "B3::Int64" },
+        "f32":     { "type": "varint7", "value":  -3, "b3type": "B3::Float" },
+        "f64":     { "type": "varint7", "value":  -4, "b3type": "B3::Double" },
+        "anyfunc": { "type": "varint7", "value": -16, "b3type": "B3::Void" },
+        "func":    { "type": "varint7", "value": -32, "b3type": "B3::Void" },
+        "void":    { "type": "varint7", "value": -64, "b3type": "B3::Void" }
     },
+    "value_type": ["i32", "i64", "f32", "f64"],
+    "block_type": ["i32", "i64", "f32", "f64", "void"],
+    "elem_type": ["anyfunc"],
     "external_kind": {
         "Function": { "type": "uint8", "value": 0 },
         "Table":    { "type": "uint8", "value": 1 },
     },
     "opcode": {
         "unreachable":         { "category": "control",    "value":   0, "return": [],           "parameter": [],                      "immediate": [],                                                                                         "description": "trap immediately" },
-        "block":               { "category": "control",    "value":   1, "return": ["control"],  "parameter": [],                      "immediate": [{"name": "sig", "type": "inline_signature_type"}],                                         "description": "begin a sequence of expressions, yielding 0 or 1 values" },
-        "loop":                { "category": "control",    "value":   2, "return": ["control"],  "parameter": [],                      "immediate": [{"name": "sig", "type": "inline_signature_type"}],                                         "description": "begin a block which can also form control flow loops" },
-        "if":                  { "category": "control",    "value":   3, "return": ["control"],  "parameter": ["bool"],                "immediate": [{"name": "sig", "type": "inline_signature_type"}],                                         "description": "begin if expression" },
-        "else":                { "category": "control",    "value":   4, "return": ["control"],  "parameter": [],                      "immediate": [],                                                                                         "description": "begin else expression of if" },
-        "select":              { "category": "control",    "value":   5, "return": ["prev"],     "parameter": ["any", "prev", "bool"], "immediate": [],                                                                                         "description": "select one of two values based on condition" },
-        "br":                  { "category": "control",    "value":   6, "return": [],           "parameter": [],                      "immediate": [{"name": "relative_depth", "type": "varuint32"}],                                          "description": "break that targets an outer nested block" },
-        "br_if":               { "category": "control",    "value":   7, "return": [],           "parameter": [],                      "immediate": [{"name": "relative_depth", "type": "varuint32"}],                                          "description": "conditional break that targets an outer nested block" },
-        "br_table":            { "category": "control",    "value":   8, "return": [],           "parameter": [],                      "immediate": [{"name": "target_count",   "type": "varuint32",                                            "description": "number of entries in the target_table"},
+        "block":               { "category": "control",    "value":   2, "return": ["control"],  "parameter": [],                      "immediate": [{"name": "sig", "type": "block_type"}],                                                    "description": "begin a sequence of expressions, yielding 0 or 1 values" },
+        "loop":                { "category": "control",    "value":   3, "return": ["control"],  "parameter": [],                      "immediate": [{"name": "sig", "type": "block_type"}],                                                    "description": "begin a block which can also form control flow loops" },
+        "if":                  { "category": "control",    "value":   4, "return": ["control"],  "parameter": ["bool"],                "immediate": [{"name": "sig", "type": "block_type"}],                                                    "description": "begin if expression" },
+        "else":                { "category": "control",    "value":   5, "return": ["control"],  "parameter": [],                      "immediate": [],                                                                                         "description": "begin else expression of if" },
+        "select":              { "category": "control",    "value":  27, "return": ["prev"],     "parameter": ["any", "prev", "bool"], "immediate": [],                                                                                         "description": "select one of two values based on condition" },
+        "br":                  { "category": "control",    "value":  12, "return": [],           "parameter": [],                      "immediate": [{"name": "relative_depth", "type": "varuint32"}],                                          "description": "break that targets an outer nested block" },
+        "br_if":               { "category": "control",    "value":  13, "return": [],           "parameter": [],                      "immediate": [{"name": "relative_depth", "type": "varuint32"}],                                          "description": "conditional break that targets an outer nested block" },
+        "br_table":            { "category": "control",    "value":  14, "return": [],           "parameter": [],                      "immediate": [{"name": "target_count",   "type": "varuint32",                                            "description": "number of entries in the target_table"},
                                                                                                                                                      {"name": "target_table",   "type": "varuint32*",                                           "description": "target entries that indicate an outer block or loop to which to break"},
                                                                                                                                                      {"name": "default_target", "type": "varuint32",                                            "description": "an outer block or loop to which to break in the default case"}],
                                                                                                                                                                                                                                                 "description": "branch table control flow construct" },
-        "return":              { "category": "control",    "value":   9, "return": [],           "parameter": [],                       "immediate": [],                                                                                         "description": "return zero or one value from this function" },
-        "drop":                { "category": "control",    "value":  11, "return": [],           "parameter": ["any"],                  "immediate": [],                                                                                         "description": "ignore value" },
-        "nop":                 { "category": "control",    "value":  10, "return": [],           "parameter": [],                       "immediate": [],                                                                                         "description": "no operation" },
-        "end":                 { "category": "control",    "value":  15, "return": [],           "parameter": [],                       "immediate": [],                                                                                         "description": "end a block, loop, or if" },
-        "i32.const":           { "category": "special",    "value":  16, "return": ["i32"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "varint32"}],                                           "description": "a constant value interpreted as i32" },
-        "i64.const":           { "category": "special",    "value":  17, "return": ["i64"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "varint64"}],                                           "description": "a constant value interpreted as i64" },
-        "f64.const":           { "category": "special",    "value":  18, "return": ["f64"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "uint64"}],                                             "description": "a constant value interpreted as f64" },
-        "f32.const":           { "category": "special",    "value":  19, "return": ["f32"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "uint32"}],                                             "description": "a constant value interpreted as f32" },
-        "get_local":           { "category": "special",    "value":  20, "return": ["local"],    "parameter": [],                       "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "read a local variable or parameter" },
-        "set_local":           { "category": "special",    "value":  21, "return": [],           "parameter": ["local"],                "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "write a local variable or parameter" },
-        "tee_local":           { "category": "special",    "value":  25, "return": ["prev"],     "parameter": ["any"],                  "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "write a local variable or parameter and return the same value" },
-        "get_global":          { "category": "special",    "value": 187, "return": ["global"],   "parameter": [],                       "immediate": [{"name": "global_index",   "type": "varuint32"}],                                          "description": "read a global variable" },
-        "set_global":          { "category": "special",    "value": 188, "return": [""],         "parameter": ["global"],               "immediate": [{"name": "global_index",   "type": "varuint32"}],                                          "description": "write a global variable" },
-        "call":                { "category": "call",       "value":  22, "return": ["call"],     "parameter": ["call"],                 "immediate": [{"name": "function_index", "type": "varuint32"}],                                          "description": "call a function by its index" },
-        "call_indirect":       { "category": "call",       "value":  23, "return": ["call"],     "parameter": ["call"],                 "immediate": [{"name": "type_index",     "type": "varuint32"}],                                          "description": "call a function indirect with an expected signature" },
-        "i32.load8_s":         { "category": "memory",     "value":  32, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "i32.load8_u":         { "category": "memory",     "value":  33, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "i32.load16_s":        { "category": "memory",     "value":  34, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "i32.load16_u":        { "category": "memory",     "value":  35, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "i64.load8_s":         { "category": "memory",     "value":  36, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "i64.load8_u":         { "category": "memory",     "value":  37, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "i64.load16_s":        { "category": "memory",     "value":  38, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "i64.load16_u":        { "category": "memory",     "value":  39, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "i64.load32_s":        { "category": "memory",     "value":  40, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "i64.load32_u":        { "category": "memory",     "value":  41, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "i32.load":            { "category": "memory",     "value":  42, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "i64.load":            { "category": "memory",     "value":  43, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "f32.load":            { "category": "memory",     "value":  44, "return": ["f32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "f64.load":            { "category": "memory",     "value":  45, "return": ["f64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "i32.store8":          { "category": "memory",     "value":  46, "return": [],           "parameter": ["addr", "i32"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
-        "i32.store16":         { "category": "memory",     "value":  47, "return": [],           "parameter": ["addr", "i32"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
-        "i64.store8":          { "category": "memory",     "value":  48, "return": [],           "parameter": ["addr", "i64"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
-        "i64.store16":         { "category": "memory",     "value":  49, "return": [],           "parameter": ["addr", "i64"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
-        "i64.store32":         { "category": "memory",     "value":  50, "return": [],           "parameter": ["addr", "i64"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
-        "i32.store":           { "category": "memory",     "value":  51, "return": [],           "parameter": ["addr", "i32"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
-        "i64.store":           { "category": "memory",     "value":  52, "return": [],           "parameter": ["addr", "i64"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
-        "f32.store":           { "category": "memory",     "value":  53, "return": [],           "parameter": ["addr", "f32"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
-        "f64.store":           { "category": "memory",     "value":  54, "return": [],           "parameter": ["addr", "f64"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
-        "current_memory":      { "category": "operation",  "value":  59, "return": ["size"],     "parameter": [],                       "immediate": [],                                                                                         "description": "query the size of memory" },
-        "grow_memory":         { "category": "operation",  "value":  57, "return": ["size"],     "parameter": ["size"],                 "immediate": [],                                                                                         "description": "grow the size of memory" },
-        "i32.add":             { "category": "arithmetic", "value":  64, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Add"          },
-        "i32.sub":             { "category": "arithmetic", "value":  65, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Sub"          },
-        "i32.mul":             { "category": "arithmetic", "value":  66, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Mul"          },
-        "i32.div_s":           { "category": "arithmetic", "value":  67, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Div"          },
-        "i32.div_u":           { "category": "arithmetic", "value":  68, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "UDiv"         },
-        "i32.rem_s":           { "category": "arithmetic", "value":  69, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Mod"          },
-        "i32.rem_u":           { "category": "arithmetic", "value":  70, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "UMod"         },
-        "i32.and":             { "category": "arithmetic", "value":  71, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "BitAnd"       },
-        "i32.or":              { "category": "arithmetic", "value":  72, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "BitOr"        },
-        "i32.xor":             { "category": "arithmetic", "value":  73, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "BitXor"       },
-        "i32.shl":             { "category": "arithmetic", "value":  74, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Shl"          },
-        "i32.shr_u":           { "category": "arithmetic", "value":  75, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "SShr"         },
-        "i32.shr_s":           { "category": "arithmetic", "value":  76, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "ZShr"         },
-        "i32.rotr":            { "category": "arithmetic", "value": 182, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "RotR"         },
-        "i32.rotl":            { "category": "arithmetic", "value": 183, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "RotL"         },
-        "i32.eq":              { "category": "comparison", "value":  77, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Equal"        },
-        "i32.ne":              { "category": "comparison", "value":  78, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "NotEqual"     },
-        "i32.lt_s":            { "category": "comparison", "value":  79, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "LessThan"     },
-        "i32.le_s":            { "category": "comparison", "value":  80, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "LessEqual"    },
-        "i32.lt_u":            { "category": "comparison", "value":  81, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Below"        },
-        "i32.le_u":            { "category": "comparison", "value":  82, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "BelowEqual"   },
-        "i32.gt_s":            { "category": "comparison", "value":  83, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "GreaterThan"  },
-        "i32.ge_s":            { "category": "comparison", "value":  84, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "GreaterEqual" },
-        "i32.gt_u":            { "category": "comparison", "value":  85, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Above"        },
-        "i32.ge_u":            { "category": "comparison", "value":  86, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "AboveEqual"   },
-        "i32.clz":             { "category": "arithmetic", "value":  87, "return": ["i32"],      "parameter": ["i32"],                  "immediate": [], "b3op": "Clz"          },
-        "i32.ctz":             { "category": "arithmetic", "value":  88, "return": ["i32"],      "parameter": ["i32"],                  "immediate": []                         },
-        "i32.popcnt":          { "category": "arithmetic", "value":  89, "return": ["i32"],      "parameter": ["i32"],                  "immediate": []                         },
-        "i32.eqz":             { "category": "comparison", "value":  90, "return": ["bool"],     "parameter": ["i32"],                  "immediate": [], "b3op": "Equal(i32(0), @0)" },
-        "i64.add":             { "category": "arithmetic", "value":  91, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Add"          },
-        "i64.sub":             { "category": "arithmetic", "value":  92, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Sub"          },
-        "i64.mul":             { "category": "arithmetic", "value":  93, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Mul"          },
-        "i64.div_s":           { "category": "arithmetic", "value":  94, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Div"          },
-        "i64.div_u":           { "category": "arithmetic", "value":  95, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "UDiv"         },
-        "i64.rem_s":           { "category": "arithmetic", "value":  96, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Mod"          },
-        "i64.rem_u":           { "category": "arithmetic", "value":  97, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "UDiv"         },
-        "i64.and":             { "category": "arithmetic", "value":  98, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "BitAnd"       },
-        "i64.or":              { "category": "arithmetic", "value":  99, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "BitOr"        },
-        "i64.xor":             { "category": "arithmetic", "value": 100, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "BitXor"       },
-        "i64.shl":             { "category": "arithmetic", "value": 101, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Shl"          },
-        "i64.shr_u":           { "category": "arithmetic", "value": 102, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "SShr"         },
-        "i64.shr_s":           { "category": "arithmetic", "value": 103, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "ZShr"         },
-        "i64.rotr":            { "category": "arithmetic", "value": 184, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "RotR"         },
-        "i64.rotl":            { "category": "arithmetic", "value": 185, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "RotL"         },
-        "i64.eq":              { "category": "comparison", "value": 104, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Equal"        },
-        "i64.ne":              { "category": "comparison", "value": 105, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "NotEqual"     },
-        "i64.lt_s":            { "category": "comparison", "value": 106, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "LessThan"     },
-        "i64.le_s":            { "category": "comparison", "value": 107, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "LessEqual"    },
-        "i64.lt_u":            { "category": "comparison", "value": 108, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Below"        },
-        "i64.le_u":            { "category": "comparison", "value": 109, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "BelowEqual"   },
-        "i64.gt_s":            { "category": "comparison", "value": 110, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "GreaterThan"  },
-        "i64.ge_s":            { "category": "comparison", "value": 111, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "GreaterEqual" },
-        "i64.gt_u":            { "category": "comparison", "value": 112, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Above"        },
-        "i64.ge_u":            { "category": "comparison", "value": 113, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "AboveEqual"   },
-        "i64.clz":             { "category": "arithmetic", "value": 114, "return": ["i64"],      "parameter": ["i64"],                  "immediate": [], "b3op": "Clz"          },
-        "i64.ctz":             { "category": "arithmetic", "value": 115, "return": ["i64"],      "parameter": ["i64"],                  "immediate": []                         },
-        "i64.popcnt":          { "category": "arithmetic", "value": 116, "return": ["i64"],      "parameter": ["i64"],                  "immediate": []                         },
-        "i64.eqz":             { "category": "comparison", "value": 186, "return": ["bool"],     "parameter": ["i64"],                  "immediate": [], "b3op": "Equal(i32(0), @0)" },
-        "f32.add":             { "category": "arithmetic", "value": 117, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Add"          },
-        "f32.sub":             { "category": "arithmetic", "value": 118, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Sub"          },
-        "f32.mul":             { "category": "arithmetic", "value": 119, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Mul"          },
-        "f32.div":             { "category": "arithmetic", "value": 120, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Div"          },
-        "f32.min":             { "category": "arithmetic", "value": 121, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Select(LessThan(@0, @1), @0, @1)" },
-        "f32.max":             { "category": "arithmetic", "value": 122, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Select(LessThan(@0, @1), @1, @0)" },
-        "f32.abs":             { "category": "arithmetic", "value": 123, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Abs"          },
-        "f32.neg":             { "category": "arithmetic", "value": 124, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Neg"          },
-        "f32.copysign":        { "category": "arithmetic", "value": 125, "return": ["f32"],      "parameter": ["f32"],                  "immediate": []                         },
-        "f32.ceil":            { "category": "arithmetic", "value": 126, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Ceil"         },
-        "f32.floor":           { "category": "arithmetic", "value": 127, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Floor"        },
-        "f32.trunc":           { "category": "arithmetic", "value": 128, "return": ["f32"],      "parameter": ["f32"],                  "immediate": []                         },
-        "f32.nearest":         { "category": "arithmetic", "value": 129, "return": ["f32"],      "parameter": ["f32"],                  "immediate": []                         },
-        "f32.sqrt":            { "category": "arithmetic", "value": 130, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Sqrt"         },
-        "f32.eq":              { "category": "comparison", "value": 131, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Equal"        },
-        "f32.ne":              { "category": "comparison", "value": 132, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "NotEqual"     },
-        "f32.lt":              { "category": "comparison", "value": 133, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "LessThan"     },
-        "f32.le":              { "category": "comparison", "value": 134, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "LessEqual"    },
-        "f32.gt":              { "category": "comparison", "value": 135, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "GreaterThan"  },
-        "f32.ge":              { "category": "comparison", "value": 136, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "GreaterEqual" },
-        "f64.add":             { "category": "arithmetic", "value": 137, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Add"          },
-        "f64.sub":             { "category": "arithmetic", "value": 138, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Sub"          },
-        "f64.mul":             { "category": "arithmetic", "value": 139, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Mul"          },
-        "f64.div":             { "category": "arithmetic", "value": 140, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Div"          },
-        "f64.min":             { "category": "arithmetic", "value": 141, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Select(LessThan(@0, @1), @0, @1)" },
-        "f64.max":             { "category": "arithmetic", "value": 142, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Select(LessThan(@0, @1), @1, @0)" },
-        "f64.abs":             { "category": "arithmetic", "value": 143, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Abs"          },
-        "f64.neg":             { "category": "arithmetic", "value": 144, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Neg"          },
-        "f64.copysign":        { "category": "arithmetic", "value": 145, "return": ["f64"],      "parameter": ["f64"],                  "immediate": []                         },
-        "f64.ceil":            { "category": "arithmetic", "value": 146, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Ceil"         },
-        "f64.floor":           { "category": "arithmetic", "value": 147, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Floor"        },
-        "f64.trunc":           { "category": "arithmetic", "value": 148, "return": ["f64"],      "parameter": ["f64"],                  "immediate": []                         },
-        "f64.nearest":         { "category": "arithmetic", "value": 149, "return": ["f64"],      "parameter": ["f64"],                  "immediate": []                         },
-        "f64.sqrt":            { "category": "arithmetic", "value": 150, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Sqrt"         },
-        "f64.eq":              { "category": "comparison", "value": 151, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Equal"        },
-        "f64.ne":              { "category": "comparison", "value": 152, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "NotEqual"     },
-        "f64.lt":              { "category": "comparison", "value": 153, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "LessThan"     },
-        "f64.le":              { "category": "comparison", "value": 154, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "LessEqual"    },
-        "f64.gt":              { "category": "comparison", "value": 155, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "GreaterThan"  },
-        "f64.ge":              { "category": "comparison", "value": 156, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "GreaterEqual" },
-        "i32.trunc_s/f32":     { "category": "conversion", "value": 157, "return": ["i32"],      "parameter": ["f32"],                  "immediate": []                         },
-        "i32.trunc_s/f64":     { "category": "conversion", "value": 158, "return": ["i32"],      "parameter": ["f64"],                  "immediate": []                         },
-        "i32.trunc_u/f32":     { "category": "conversion", "value": 159, "return": ["i32"],      "parameter": ["f32"],                  "immediate": []                         },
-        "i32.trunc_u/f64":     { "category": "conversion", "value": 160, "return": ["i32"],      "parameter": ["f64"],                  "immediate": []                         },
-        "i32.wrap/i64":        { "category": "conversion", "value": 161, "return": ["i32"],      "parameter": ["i64"],                  "immediate": []                         },
-        "i64.trunc_s/f32":     { "category": "conversion", "value": 162, "return": ["i64"],      "parameter": ["f32"],                  "immediate": []                         },
-        "i64.trunc_s/f64":     { "category": "conversion", "value": 163, "return": ["i64"],      "parameter": ["f64"],                  "immediate": []                         },
-        "i64.trunc_u/f32":     { "category": "conversion", "value": 164, "return": ["i64"],      "parameter": ["f32"],                  "immediate": []                         },
-        "i64.trunc_u/f64":     { "category": "conversion", "value": 165, "return": ["i64"],      "parameter": ["f64"],                  "immediate": []                         },
-        "i64.extend_s/i32":    { "category": "conversion", "value": 166, "return": ["i64"],      "parameter": ["i32"],                  "immediate": [], "b3op": "SExt32"       },
-        "i64.extend_u/i32":    { "category": "conversion", "value": 167, "return": ["i64"],      "parameter": ["i32"],                  "immediate": [], "b3op": "ZExt32"       },
-        "f32.convert_s/i32":   { "category": "conversion", "value": 168, "return": ["f32"],      "parameter": ["i32"],                  "immediate": []                         },
-        "f32.convert_u/i32":   { "category": "conversion", "value": 169, "return": ["f32"],      "parameter": ["i32"],                  "immediate": []                         },
-        "f32.convert_s/i64":   { "category": "conversion", "value": 170, "return": ["f32"],      "parameter": ["i64"],                  "immediate": []                         },
-        "f32.convert_u/i64":   { "category": "conversion", "value": 171, "return": ["f32"],      "parameter": ["i64"],                  "immediate": []                         },
-        "f32.demote/f64":      { "category": "conversion", "value": 172, "return": ["f32"],      "parameter": ["f64"],                  "immediate": [], "b3op": "DoubleToFloat"},
-        "f32.reinterpret/i32": { "category": "conversion", "value": 173, "return": ["f32"],      "parameter": ["i32"],                  "immediate": [], "b3op": "BitwiseCast"  },
-        "f64.convert_s/i32":   { "category": "conversion", "value": 174, "return": ["f64"],      "parameter": ["i32"],                  "immediate": []                         },
-        "f64.convert_u/i32":   { "category": "conversion", "value": 175, "return": ["f64"],      "parameter": ["i32"],                  "immediate": []                         },
-        "f64.convert_s/i64":   { "category": "conversion", "value": 176, "return": ["f64"],      "parameter": ["i64"],                  "immediate": []                         },
-        "f64.convert_u/i64":   { "category": "conversion", "value": 177, "return": ["f64"],      "parameter": ["i64"],                  "immediate": []                         },
-        "f64.promote/f32":     { "category": "conversion", "value": 178, "return": ["f64"],      "parameter": ["f32"],                  "immediate": [], "b3op": "FloatToDouble"},
-        "f64.reinterpret/i64": { "category": "conversion", "value": 179, "return": ["f64"],      "parameter": ["i64"],                  "immediate": [], "b3op": "BitwiseCast"  },
-        "i32.reinterpret/f32": { "category": "conversion", "value": 180, "return": ["i32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "BitwiseCast"  },
-        "i64.reinterpret/f64": { "category": "conversion", "value": 181, "return": ["i64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "BitwiseCast"  }
+        "return":              { "category": "control",    "value":  15, "return": [],           "parameter": [],                       "immediate": [],                                                                                         "description": "return zero or one value from this function" },
+        "drop":                { "category": "control",    "value":  26, "return": [],           "parameter": ["any"],                  "immediate": [],                                                                                         "description": "ignore value" },
+        "nop":                 { "category": "control",    "value":   1, "return": [],           "parameter": [],                       "immediate": [],                                                                                         "description": "no operation" },
+        "end":                 { "category": "control",    "value":  11, "return": [],           "parameter": [],                       "immediate": [],                                                                                         "description": "end a block, loop, or if" },
+        "i32.const":           { "category": "special",    "value":  65, "return": ["i32"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "varint32"}],                                           "description": "a constant value interpreted as i32" },
+        "i64.const":           { "category": "special",    "value":  66, "return": ["i64"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "varint64"}],                                           "description": "a constant value interpreted as i64" },
+        "f64.const":           { "category": "special",    "value":  68, "return": ["f64"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "uint64"}],                                             "description": "a constant value interpreted as f64" },
+        "f32.const":           { "category": "special",    "value":  67, "return": ["f32"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "uint32"}],                                             "description": "a constant value interpreted as f32" },
+        "get_local":           { "category": "special",    "value":  32, "return": ["local"],    "parameter": [],                       "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "read a local variable or parameter" },
+        "set_local":           { "category": "special",    "value":  33, "return": [],           "parameter": ["local"],                "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "write a local variable or parameter" },
+        "tee_local":           { "category": "special",    "value":  34, "return": ["prev"],     "parameter": ["any"],                  "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "write a local variable or parameter and return the same value" },
+        "get_global":          { "category": "special",    "value":  35, "return": ["global"],   "parameter": [],                       "immediate": [{"name": "global_index",   "type": "varuint32"}],                                          "description": "read a global variable" },
+        "set_global":          { "category": "special",    "value":  36, "return": [""],         "parameter": ["global"],               "immediate": [{"name": "global_index",   "type": "varuint32"}],                                          "description": "write a global variable" },
+        "call":                { "category": "call",       "value":  16, "return": ["call"],     "parameter": ["call"],                 "immediate": [{"name": "function_index", "type": "varuint32"}],                                          "description": "call a function by its index" },
+        "call_indirect":       { "category": "call",       "value":  17, "return": ["call"],     "parameter": ["call"],                 "immediate": [{"name": "type_index",     "type": "varuint32"}],                                          "description": "call a function indirect with an expected signature" },
+        "i32.load8_s":         { "category": "memory",     "value":  44, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i32.load8_u":         { "category": "memory",     "value":  45, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i32.load16_s":        { "category": "memory",     "value":  46, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i32.load16_u":        { "category": "memory",     "value":  47, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i64.load8_s":         { "category": "memory",     "value":  48, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i64.load8_u":         { "category": "memory",     "value":  49, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i64.load16_s":        { "category": "memory",     "value":  50, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i64.load16_u":        { "category": "memory",     "value":  51, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i64.load32_s":        { "category": "memory",     "value":  52, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i64.load32_u":        { "category": "memory",     "value":  53, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i32.load":            { "category": "memory",     "value":  40, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i64.load":            { "category": "memory",     "value":  41, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "f32.load":            { "category": "memory",     "value":  42, "return": ["f32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "f64.load":            { "category": "memory",     "value":  43, "return": ["f64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i32.store8":          { "category": "memory",     "value":  58, "return": [],           "parameter": ["addr", "i32"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "i32.store16":         { "category": "memory",     "value":  59, "return": [],           "parameter": ["addr", "i32"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "i64.store8":          { "category": "memory",     "value":  60, "return": [],           "parameter": ["addr", "i64"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "i64.store16":         { "category": "memory",     "value":  61, "return": [],           "parameter": ["addr", "i64"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "i64.store32":         { "category": "memory",     "value":  62, "return": [],           "parameter": ["addr", "i64"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "i32.store":           { "category": "memory",     "value":  54, "return": [],           "parameter": ["addr", "i32"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "i64.store":           { "category": "memory",     "value":  55, "return": [],           "parameter": ["addr", "i64"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "f32.store":           { "category": "memory",     "value":  56, "return": [],           "parameter": ["addr", "f32"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "f64.store":           { "category": "memory",     "value":  57, "return": [],           "parameter": ["addr", "f64"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "current_memory":      { "category": "operation",  "value":  63, "return": ["size"],     "parameter": [],                       "immediate": [],                                                                                         "description": "query the size of memory" },
+        "grow_memory":         { "category": "operation",  "value":  64, "return": ["size"],     "parameter": ["size"],                 "immediate": [],                                                                                         "description": "grow the size of memory" },
+        "i32.add":             { "category": "arithmetic", "value": 106, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Add"          },
+        "i32.sub":             { "category": "arithmetic", "value": 107, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Sub"          },
+        "i32.mul":             { "category": "arithmetic", "value": 108, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Mul"          },
+        "i32.div_s":           { "category": "arithmetic", "value": 109, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Div"          },
+        "i32.div_u":           { "category": "arithmetic", "value": 110, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "UDiv"         },
+        "i32.rem_s":           { "category": "arithmetic", "value": 111, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Mod"          },
+        "i32.rem_u":           { "category": "arithmetic", "value": 112, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "UMod"         },
+        "i32.and":             { "category": "arithmetic", "value": 113, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "BitAnd"       },
+        "i32.or":              { "category": "arithmetic", "value": 114, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "BitOr"        },
+        "i32.xor":             { "category": "arithmetic", "value": 115, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "BitXor"       },
+        "i32.shl":             { "category": "arithmetic", "value": 116, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Shl"          },
+        "i32.shr_u":           { "category": "arithmetic", "value": 118, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "SShr"         },
+        "i32.shr_s":           { "category": "arithmetic", "value": 117, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "ZShr"         },
+        "i32.rotr":            { "category": "arithmetic", "value": 120, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "RotR"         },
+        "i32.rotl":            { "category": "arithmetic", "value": 119, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "RotL"         },
+        "i32.eq":              { "category": "comparison", "value":  70, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Equal"        },
+        "i32.ne":              { "category": "comparison", "value":  71, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "NotEqual"     },
+        "i32.lt_s":            { "category": "comparison", "value":  72, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "LessThan"     },
+        "i32.le_s":            { "category": "comparison", "value":  76, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "LessEqual"    },
+        "i32.lt_u":            { "category": "comparison", "value":  73, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Below"        },
+        "i32.le_u":            { "category": "comparison", "value":  77, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "BelowEqual"   },
+        "i32.gt_s":            { "category": "comparison", "value":  74, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "GreaterThan"  },
+        "i32.ge_s":            { "category": "comparison", "value":  78, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "GreaterEqual" },
+        "i32.gt_u":            { "category": "comparison", "value":  75, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Above"        },
+        "i32.ge_u":            { "category": "comparison", "value":  79, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "AboveEqual"   },
+        "i32.clz":             { "category": "arithmetic", "value": 103, "return": ["i32"],      "parameter": ["i32"],                  "immediate": [], "b3op": "Clz"          },
+        "i32.ctz":             { "category": "arithmetic", "value": 104, "return": ["i32"],      "parameter": ["i32"],                  "immediate": []                         },
+        "i32.popcnt":          { "category": "arithmetic", "value": 105, "return": ["i32"],      "parameter": ["i32"],                  "immediate": []                         },
+        "i32.eqz":             { "category": "comparison", "value":  69, "return": ["bool"],     "parameter": ["i32"],                  "immediate": [], "b3op": "Equal(i32(0), @0)" },
+        "i64.add":             { "category": "arithmetic", "value": 124, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Add"          },
+        "i64.sub":             { "category": "arithmetic", "value": 125, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Sub"          },
+        "i64.mul":             { "category": "arithmetic", "value": 126, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Mul"          },
+        "i64.div_s":           { "category": "arithmetic", "value": 127, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Div"          },
+        "i64.div_u":           { "category": "arithmetic", "value": 128, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "UDiv"         },
+        "i64.rem_s":           { "category": "arithmetic", "value": 129, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Mod"          },
+        "i64.rem_u":           { "category": "arithmetic", "value": 130, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "UDiv"         },
+        "i64.and":             { "category": "arithmetic", "value": 131, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "BitAnd"       },
+        "i64.or":              { "category": "arithmetic", "value": 132, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "BitOr"        },
+        "i64.xor":             { "category": "arithmetic", "value": 133, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "BitXor"       },
+        "i64.shl":             { "category": "arithmetic", "value": 134, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Shl"          },
+        "i64.shr_u":           { "category": "arithmetic", "value": 136, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "SShr"         },
+        "i64.shr_s":           { "category": "arithmetic", "value": 135, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "ZShr"         },
+        "i64.rotr":            { "category": "arithmetic", "value": 138, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "RotR"         },
+        "i64.rotl":            { "category": "arithmetic", "value": 137, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "RotL"         },
+        "i64.eq":              { "category": "comparison", "value":  81, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Equal"        },
+        "i64.ne":              { "category": "comparison", "value":  82, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "NotEqual"     },
+        "i64.lt_s":            { "category": "comparison", "value":  83, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "LessThan"     },
+        "i64.le_s":            { "category": "comparison", "value":  87, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "LessEqual"    },
+        "i64.lt_u":            { "category": "comparison", "value":  84, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Below"        },
+        "i64.le_u":            { "category": "comparison", "value":  88, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "BelowEqual"   },
+        "i64.gt_s":            { "category": "comparison", "value":  85, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "GreaterThan"  },
+        "i64.ge_s":            { "category": "comparison", "value":  89, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "GreaterEqual" },
+        "i64.gt_u":            { "category": "comparison", "value":  86, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Above"        },
+        "i64.ge_u":            { "category": "comparison", "value":  90, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "AboveEqual"   },
+        "i64.clz":             { "category": "arithmetic", "value": 121, "return": ["i64"],      "parameter": ["i64"],                  "immediate": [], "b3op": "Clz"          },
+        "i64.ctz":             { "category": "arithmetic", "value": 122, "return": ["i64"],      "parameter": ["i64"],                  "immediate": []                         },
+        "i64.popcnt":          { "category": "arithmetic", "value": 123, "return": ["i64"],      "parameter": ["i64"],                  "immediate": []                         },
+        "i64.eqz":             { "category": "comparison", "value":  80, "return": ["bool"],     "parameter": ["i64"],                  "immediate": [], "b3op": "Equal(i32(0), @0)" },
+        "f32.add":             { "category": "arithmetic", "value": 146, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Add"          },
+        "f32.sub":             { "category": "arithmetic", "value": 147, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Sub"          },
+        "f32.mul":             { "category": "arithmetic", "value": 148, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Mul"          },
+        "f32.div":             { "category": "arithmetic", "value": 149, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Div"          },
+        "f32.min":             { "category": "arithmetic", "value": 150, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Select(LessThan(@0, @1), @0, @1)" },
+        "f32.max":             { "category": "arithmetic", "value": 151, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Select(LessThan(@0, @1), @1, @0)" },
+        "f32.abs":             { "category": "arithmetic", "value": 139, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Abs"          },
+        "f32.neg":             { "category": "arithmetic", "value": 140, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Neg"          },
+        "f32.copysign":        { "category": "arithmetic", "value": 152, "return": ["f32"],      "parameter": ["f32"],                  "immediate": []                         },
+        "f32.ceil":            { "category": "arithmetic", "value": 141, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Ceil"         },
+        "f32.floor":           { "category": "arithmetic", "value": 142, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Floor"        },
+        "f32.trunc":           { "category": "arithmetic", "value": 143, "return": ["f32"],      "parameter": ["f32"],                  "immediate": []                         },
+        "f32.nearest":         { "category": "arithmetic", "value": 144, "return": ["f32"],      "parameter": ["f32"],                  "immediate": []                         },
+        "f32.sqrt":            { "category": "arithmetic", "value": 145, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Sqrt"         },
+        "f32.eq":              { "category": "comparison", "value":  91, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Equal"        },
+        "f32.ne":              { "category": "comparison", "value":  92, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "NotEqual"     },
+        "f32.lt":              { "category": "comparison", "value":  93, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "LessThan"     },
+        "f32.le":              { "category": "comparison", "value":  95, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "LessEqual"    },
+        "f32.gt":              { "category": "comparison", "value":  94, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "GreaterThan"  },
+        "f32.ge":              { "category": "comparison", "value":  96, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "GreaterEqual" },
+        "f64.add":             { "category": "arithmetic", "value": 160, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Add"          },
+        "f64.sub":             { "category": "arithmetic", "value": 161, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Sub"          },
+        "f64.mul":             { "category": "arithmetic", "value": 162, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Mul"          },
+        "f64.div":             { "category": "arithmetic", "value": 163, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Div"          },
+        "f64.min":             { "category": "arithmetic", "value": 164, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Select(LessThan(@0, @1), @0, @1)" },
+        "f64.max":             { "category": "arithmetic", "value": 165, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Select(LessThan(@0, @1), @1, @0)" },
+        "f64.abs":             { "category": "arithmetic", "value": 153, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Abs"          },
+        "f64.neg":             { "category": "arithmetic", "value": 154, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Neg"          },
+        "f64.copysign":        { "category": "arithmetic", "value": 166, "return": ["f64"],      "parameter": ["f64"],                  "immediate": []                         },
+        "f64.ceil":            { "category": "arithmetic", "value": 155, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Ceil"         },
+        "f64.floor":           { "category": "arithmetic", "value": 156, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Floor"        },
+        "f64.trunc":           { "category": "arithmetic", "value": 157, "return": ["f64"],      "parameter": ["f64"],                  "immediate": []                         },
+        "f64.nearest":         { "category": "arithmetic", "value": 158, "return": ["f64"],      "parameter": ["f64"],                  "immediate": []                         },
+        "f64.sqrt":            { "category": "arithmetic", "value": 159, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Sqrt"         },
+        "f64.eq":              { "category": "comparison", "value":  97, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Equal"        },
+        "f64.ne":              { "category": "comparison", "value":  98, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "NotEqual"     },
+        "f64.lt":              { "category": "comparison", "value":  99, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "LessThan"     },
+        "f64.le":              { "category": "comparison", "value": 101, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "LessEqual"    },
+        "f64.gt":              { "category": "comparison", "value": 100, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "GreaterThan"  },
+        "f64.ge":              { "category": "comparison", "value": 102, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "GreaterEqual" },
+        "i32.trunc_s/f32":     { "category": "conversion", "value": 168, "return": ["i32"],      "parameter": ["f32"],                  "immediate": []                         },
+        "i32.trunc_s/f64":     { "category": "conversion", "value": 170, "return": ["i32"],      "parameter": ["f64"],                  "immediate": []                         },
+        "i32.trunc_u/f32":     { "category": "conversion", "value": 169, "return": ["i32"],      "parameter": ["f32"],                  "immediate": []                         },
+        "i32.trunc_u/f64":     { "category": "conversion", "value": 171, "return": ["i32"],      "parameter": ["f64"],                  "immediate": []                         },
+        "i32.wrap/i64":        { "category": "conversion", "value": 167, "return": ["i32"],      "parameter": ["i64"],                  "immediate": []                         },
+        "i64.trunc_s/f32":     { "category": "conversion", "value": 174, "return": ["i64"],      "parameter": ["f32"],                  "immediate": []                         },
+        "i64.trunc_s/f64":     { "category": "conversion", "value": 176, "return": ["i64"],      "parameter": ["f64"],                  "immediate": []                         },
+        "i64.trunc_u/f32":     { "category": "conversion", "value": 175, "return": ["i64"],      "parameter": ["f32"],                  "immediate": []                         },
+        "i64.trunc_u/f64":     { "category": "conversion", "value": 177, "return": ["i64"],      "parameter": ["f64"],                  "immediate": []                         },
+        "i64.extend_s/i32":    { "category": "conversion", "value": 172, "return": ["i64"],      "parameter": ["i32"],                  "immediate": [], "b3op": "SExt32"       },
+        "i64.extend_u/i32":    { "category": "conversion", "value": 173, "return": ["i64"],      "parameter": ["i32"],                  "immediate": [], "b3op": "ZExt32"       },
+        "f32.convert_s/i32":   { "category": "conversion", "value": 178, "return": ["f32"],      "parameter": ["i32"],                  "immediate": []                         },
+        "f32.convert_u/i32":   { "category": "conversion", "value": 179, "return": ["f32"],      "parameter": ["i32"],                  "immediate": []                         },
+        "f32.convert_s/i64":   { "category": "conversion", "value": 180, "return": ["f32"],      "parameter": ["i64"],                  "immediate": []                         },
+        "f32.convert_u/i64":   { "category": "conversion", "value": 181, "return": ["f32"],      "parameter": ["i64"],                  "immediate": []                         },
+        "f32.demote/f64":      { "category": "conversion", "value": 182, "return": ["f32"],      "parameter": ["f64"],                  "immediate": [], "b3op": "DoubleToFloat"},
+        "f32.reinterpret/i32": { "category": "conversion", "value": 190, "return": ["f32"],      "parameter": ["i32"],                  "immediate": [], "b3op": "BitwiseCast"  },
+        "f64.convert_s/i32":   { "category": "conversion", "value": 183, "return": ["f64"],      "parameter": ["i32"],                  "immediate": []                         },
+        "f64.convert_u/i32":   { "category": "conversion", "value": 184, "return": ["f64"],      "parameter": ["i32"],                  "immediate": []                         },
+        "f64.convert_s/i64":   { "category": "conversion", "value": 185, "return": ["f64"],      "parameter": ["i64"],                  "immediate": []                         },
+        "f64.convert_u/i64":   { "category": "conversion", "value": 186, "return": ["f64"],      "parameter": ["i64"],                  "immediate": []                         },
+        "f64.promote/f32":     { "category": "conversion", "value": 187, "return": ["f64"],      "parameter": ["f32"],                  "immediate": [], "b3op": "FloatToDouble"},
+        "f64.reinterpret/i64": { "category": "conversion", "value": 191, "return": ["f64"],      "parameter": ["i64"],                  "immediate": [], "b3op": "BitwiseCast"  },
+        "i32.reinterpret/f32": { "category": "conversion", "value": 188, "return": ["i32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "BitwiseCast"  },
+        "i64.reinterpret/f64": { "category": "conversion", "value": 189, "return": ["i64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "BitwiseCast"  }
     }
 }
index 9f6e789..f0b6c75 100644 (file)
@@ -1,3 +1,40 @@
+2016-11-30  JF Bastien  <jfbastien@apple.com>
+
+        WebAssembly: update binary format to 0xD version
+        https://bugs.webkit.org/show_bug.cgi?id=164724
+
+        Reviewed by Saam Barati.
+
+        As described in the following PR: https://github.com/WebAssembly/design/pull/836
+
+        * wasm/WasmB3IRGenerator.cpp:
+        (JSC::Wasm::B3IRGenerator::B3IRGenerator):
+        (JSC::Wasm::B3IRGenerator::zeroForType):
+        (JSC::Wasm::B3IRGenerator::addConstant):
+        (JSC::Wasm::createJSWrapper):
+        * wasm/WasmCallingConvention.h:
+        (JSC::Wasm::CallingConvention::marshallArgument):
+        * wasm/WasmFormat.cpp:
+        (JSC::Wasm::toString): Deleted.
+        * wasm/WasmFormat.h:
+        (JSC::Wasm::isValueType):
+        (JSC::Wasm::toB3Type): Deleted.
+        * wasm/WasmFunctionParser.h:
+        (JSC::Wasm::FunctionParser<Context>::parseExpression):
+        * wasm/WasmModuleParser.cpp:
+        (JSC::Wasm::ModuleParser::parse):
+        (JSC::Wasm::ModuleParser::parseType):
+        * wasm/WasmModuleParser.h:
+        * wasm/WasmParser.h:
+        (JSC::Wasm::Parser::parseResultType):
+        * wasm/generateWasm.py:
+        (Wasm.__init__):
+        * wasm/generateWasmOpsHeader.py:
+        (cppMacro):
+        (typeMacroizer):
+        (opcodeMacroizer):
+        * wasm/wasm.json:
+
 2016-11-30  Darin Adler  <darin@apple.com>
 
         Roll out StringBuilder changes from the previous patch.
index a515e4c..fd07c45 100644 (file)
@@ -186,7 +186,7 @@ private:
     Vector<UnlinkedCall>& m_unlinkedCalls;
     GPRReg m_memoryBaseGPR;
     GPRReg m_memorySizeGPR;
-    Value* m_zeroValues[Type::LastValueType];
+    Value* m_zeroValues[numTypes];
 };
 
 B3IRGenerator::B3IRGenerator(Memory* memory, Procedure& procedure, Vector<UnlinkedCall>& unlinkedCalls)
@@ -196,8 +196,19 @@ B3IRGenerator::B3IRGenerator(Memory* memory, Procedure& procedure, Vector<Unlink
 {
     m_currentBlock = m_proc.addBlock();
 
-    for (unsigned i = 0; i < Type::LastValueType; ++i)
-        m_zeroValues[i] = m_currentBlock->appendIntConstant(m_proc, Origin(), toB3Type(static_cast<Type>(i + 1)), 0);
+    for (unsigned i = 0; i < numTypes; ++i) {
+        switch (B3::Type b3Type = toB3Type(linearizedToType(i))) {
+        case B3::Int32:
+        case B3::Int64:
+        case B3::Float:
+        case B3::Double:
+            m_zeroValues[i] = m_currentBlock->appendIntConstant(m_proc, Origin(), b3Type, 0);
+            break;
+        case B3::Void:
+            m_zeroValues[i] = nullptr;
+            break;
+        }
+    }
 
     if (m_memory) {
         m_memoryBaseGPR = m_memory->pinnedRegisters().baseMemoryPointer;
@@ -218,7 +229,9 @@ B3IRGenerator::B3IRGenerator(Memory* memory, Procedure& procedure, Vector<Unlink
 Value* B3IRGenerator::zeroForType(Type type)
 {
     ASSERT(type != Void);
-    return m_zeroValues[type - 1];
+    Value* zeroValue = m_zeroValues[linearizeType(type)];
+    ASSERT(zeroValue);
+    return zeroValue;
 }
 
 bool B3IRGenerator::addLocal(Type type, uint32_t count)
@@ -441,18 +454,21 @@ bool B3IRGenerator::addSelect(ExpressionType condition, ExpressionType nonZero,
 B3IRGenerator::ExpressionType B3IRGenerator::addConstant(Type type, uint64_t value)
 {
     switch (type) {
-    case Int32:
+    case Wasm::I32:
         return m_currentBlock->appendNew<Const32Value>(m_proc, Origin(), static_cast<int32_t>(value));
-    case Int64:
+    case Wasm::I64:
         return m_currentBlock->appendNew<Const64Value>(m_proc, Origin(), value);
-    case Float:
+    case Wasm::F32:
         return m_currentBlock->appendNew<ConstFloatValue>(m_proc, Origin(), bitwise_cast<float>(static_cast<int32_t>(value)));
-    case Double:
+    case Wasm::F64:
         return m_currentBlock->appendNew<ConstDoubleValue>(m_proc, Origin(), bitwise_cast<double>(value));
-    default:
-        RELEASE_ASSERT_NOT_REACHED();
-        return nullptr;
+    case Wasm::Void:
+    case Wasm::Func:
+    case Wasm::Anyfunc:
+        break;
     }
+    RELEASE_ASSERT_NOT_REACHED();
+    return nullptr;
 }
 
 B3IRGenerator::ControlData B3IRGenerator::addBlock(Type signature)
@@ -701,17 +717,20 @@ static std::unique_ptr<Compilation> createJSWrapper(VM& vm, const Signature* sig
 
     // Return the result, if needed.
     switch (signature->returnType) {
-    case Void:
+    case Wasm::Void:
         block->appendNewControlValue(proc, B3::Return, Origin());
         break;
-    case F32:
-    case F64:
+    case Wasm::F32:
+    case Wasm::F64:
         result = block->appendNew<Value>(proc, BitwiseCast, Origin(), result);
         FALLTHROUGH;
-    case I32:
-    case I64:
+    case Wasm::I32:
+    case Wasm::I64:
         block->appendNewControlValue(proc, B3::Return, Origin(), result);
         break;
+    case Wasm::Func:
+    case Wasm::Anyfunc:
+        RELEASE_ASSERT_NOT_REACHED();
     }
 
     return std::make_unique<Compilation>(vm, proc);
index 5589363..950e31a 100644 (file)
@@ -76,7 +76,7 @@ private:
         case B3::Float:
         case B3::Double:
             return marshallArgumentImpl(m_fprArgs, type, fpArgumentCount, stackOffset);
-        case Void:
+        case B3::Void:
             break;
         }
         RELEASE_ASSERT_NOT_REACHED();
index 20c9e3d..267c54b 100644 (file)
 
 #include "WasmMemory.h"
 
-#if COMPILER(GCC) && ASSERT_DISABLED
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wreturn-type"
-#endif // COMPILER(GCC) && ASSERT_DISABLED
-
 namespace JSC { namespace Wasm {
 
-const char* toString(Type type)
-{
-    switch (type) {
-    case Void:
-        return "void";
-    case I32:
-        return "i32";
-    case I64:
-        return "i64";
-    case F32:
-        return "f32";
-    case F64:
-        return "f64";
-    }
-}
-
 ModuleInformation::~ModuleInformation() { }
 
 } } // namespace JSC::Wasm
 
-#if COMPILER(GCC) && ASSERT_DISABLED
-#pragma GCC diagnostic pop
-#endif // COMPILER(GCC) && ASSERT_DISABLED
-
 #endif // ENABLE(WEBASSEMBLY)
index 29f0603..274fe7d 100644 (file)
@@ -31,6 +31,7 @@
 #include "B3Type.h"
 #include "CodeLocation.h"
 #include "Identifier.h"
+#include "WasmOps.h"
 #include <wtf/Vector.h>
 
 namespace JSC {
@@ -39,33 +40,6 @@ class JSFunction;
 
 namespace Wasm {
 
-enum Type : uint8_t {
-    Void,
-    I32,
-    I64,
-    F32,
-    F64,
-    LastValueType = F64,
-};
-
-static_assert(I32 == 1, "Wasm needs I32 to have the value 1");
-static_assert(I64 == 2, "Wasm needs I64 to have the value 2");
-static_assert(F32 == 3, "Wasm needs F32 to have the value 3");
-static_assert(F64 == 4, "Wasm needs F64 to have the value 4");
-
-inline B3::Type toB3Type(Type type)
-{
-    switch (type) {
-    case I32: return B3::Int32;
-    case I64: return B3::Int64;
-    case F32: return B3::Float;
-    case F64: return B3::Double;
-    case Void: return B3::Void;
-    default: break;
-    }
-    RELEASE_ASSERT_NOT_REACHED();
-}
-
 inline bool isValueType(Type type)
 {
     switch (type) {
@@ -79,11 +53,10 @@ inline bool isValueType(Type type)
     }
     return false;
 }
-
-const char* toString(Type);
     
 struct External {
     enum Kind : uint8_t {
+        // FIXME auto-generate this. https://bugs.webkit.org/show_bug.cgi?id=165231
         Function = 0,
         Table = 1,
         Memory = 2,
index 2ffb113..4ee1b5f 100644 (file)
@@ -207,11 +207,11 @@ template<typename Context>
 bool FunctionParser<Context>::parseExpression(OpType op)
 {
     switch (op) {
-#define CREATE_CASE(name, id, b3op) case OpType::name: return binaryCase<OpType::name>();
+#define CREATE_CASE(name, id, b3op, inc) case OpType::name: return binaryCase<OpType::name>();
     FOR_EACH_WASM_SIMPLE_BINARY_OP(CREATE_CASE)
 #undef CREATE_CASE
 
-#define CREATE_CASE(name, id, b3op) case OpType::name: return unaryCase<OpType::name>();
+#define CREATE_CASE(name, id, b3op, inc) case OpType::name: return unaryCase<OpType::name>();
     FOR_EACH_WASM_SIMPLE_UNARY_OP(CREATE_CASE)
 #undef CREATE_CASE
 
@@ -236,7 +236,7 @@ bool FunctionParser<Context>::parseExpression(OpType op)
         return true;
     }
 
-#define CREATE_CASE(name, id, b3op) case OpType::name:
+#define CREATE_CASE(name, id, b3op, inc) case OpType::name:
     FOR_EACH_WASM_MEMORY_LOAD_OP(CREATE_CASE) {
         uint32_t alignment;
         if (!parseVarUInt32(alignment))
index 61c3920..88d08ee 100644 (file)
@@ -54,7 +54,6 @@ bool ModuleParser::parse()
         return false;
     }
 
-    // Skip the version number for now since we don't do anything with it.
     uint32_t versionNumber;
     if (!parseUInt32(versionNumber)) {
         // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
@@ -62,7 +61,7 @@ bool ModuleParser::parse()
         return false;
     }
 
-    if (versionNumber != magicNumber) {
+    if (versionNumber != expectedVersionNumber) {
         // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
         m_errorMessage = "unexpected version number";
         return false;
@@ -169,7 +168,7 @@ bool ModuleParser::parseType()
         int8_t type;
         if (!parseInt7(type))
             return false;
-        if (type != -0x20) // Function type constant. FIXME auto-generate from JSON file.
+        if (type != Func)
             return false;
 
         if (verbose)
index 2583315..58a24d6 100644 (file)
@@ -37,8 +37,6 @@ namespace JSC { namespace Wasm {
 class ModuleParser : public Parser {
 public:
 
-    static const unsigned magicNumber = 0xc;
-
     ModuleParser(VM* vm, const uint8_t* sourceBuffer, size_t sourceLength)
         : Parser(sourceBuffer, sourceLength)
         , m_vm(vm)
index b61061b..cbd67b3 100644 (file)
@@ -169,10 +169,10 @@ ALWAYS_INLINE bool Parser::parseVarUInt1(uint8_t& result)
 
 ALWAYS_INLINE bool Parser::parseResultType(Type& result)
 {
-    uint8_t value;
-    if (!parseUInt7(value))
+    int8_t value;
+    if (!parseInt7(value))
         return false;
-    if (value > static_cast<uint8_t>(Type::LastValueType))
+    if (!isValidType(value))
         return false;
     result = static_cast<Type>(value);
     return true;
index 53a45a7..6e1ddc2 100755 (executable)
@@ -33,6 +33,11 @@ class Wasm:
         wasmFile = open(jsonPath, "r")
         wasm = json.load(open(jsonPath, "r"))
         wasmFile.close()
+        for pre in wasm["preamble"]:
+            if pre["name"] == "version":
+                self.expectedVersionNumber = str(pre["value"])
+        self.preamble = wasm["preamble"]
+        self.types = wasm["type"]
         self.opcodes = wasm["opcode"]
         self.header = """/*
  * Copyright (C) 2016 Apple Inc. All rights reserved.
index 729b82a..ce89484 100755 (executable)
@@ -35,20 +35,34 @@ if len(args) != 3:
     parser.error(parser.usage)
 
 wasm = Wasm(args[0], args[1])
+types = wasm.types
 opcodes = wasm.opcodes
 wasmOpsHFile = open(args[2], "w")
 
 
-def cppMacro(wasmOpcode, value, b3Opcode):
-    return " \\\n    macro(" + wasm.toCpp(wasmOpcode) + ", " + hex(int(value)) + ", " + b3Opcode + ")"
+def cppMacro(wasmOpcode, value, b3, inc):
+    return " \\\n    macro(" + wasm.toCpp(wasmOpcode) + ", " + hex(int(value)) + ", " + b3 + ", " + str(inc) + ")"
+
+
+def typeMacroizer():
+    inc = 0
+    for ty in wasm.types:
+        yield cppMacro(ty, wasm.types[ty]["value"], wasm.types[ty]["b3type"], inc)
+        inc += 1
+
+type_definitions = ["#define FOR_EACH_WASM_TYPE(macro)"]
+type_definitions.extend([t for t in typeMacroizer()])
+type_definitions = "".join(type_definitions)
 
 
 def opcodeMacroizer(filter):
+    inc = 0
     for op in wasm.opcodeIterator(filter):
         b3op = "Oops"
         if isSimple(op["opcode"]):
             b3op = op["opcode"]["b3op"]
-        yield cppMacro(op["name"], op["opcode"]["value"], b3op)
+        yield cppMacro(op["name"], op["opcode"]["value"], b3op, inc)
+        inc += 1
 
 defines = ["#define FOR_EACH_WASM_SPECIAL_OP(macro)"]
 defines.extend([op for op in opcodeMacroizer(lambda op: op["category"] == "special" or op["category"] == "call")])
@@ -101,6 +115,75 @@ contents = wasm.header + """
 
 namespace JSC { namespace Wasm {
 
+static constexpr unsigned expectedVersionNumber = """ + wasm.expectedVersionNumber + """;
+
+static constexpr unsigned numTypes = """ + str(len(types)) + """;
+
+""" + type_definitions + """
+#define CREATE_ENUM_VALUE(name, id, b3type, inc) name = id,
+enum Type : int8_t {
+    FOR_EACH_WASM_TYPE(CREATE_ENUM_VALUE)
+};
+#undef CREATE_ENUM_VALUE
+
+#define CREATE_CASE(name, id, b3type, inc) case id: return true;
+template <typename Int>
+inline bool isValidType(Int i)
+{
+    switch (i) {
+    default: return false;
+    FOR_EACH_WASM_TYPE(CREATE_CASE)
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+    return false;
+}
+#undef CREATE_CASE
+
+#define CREATE_CASE(name, id, b3type, inc) case name: return b3type;
+inline B3::Type toB3Type(Type type)
+{
+    switch (type) {
+    FOR_EACH_WASM_TYPE(CREATE_CASE)
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+    return B3::Void;
+}
+#undef CREATE_CASE
+
+#define CREATE_CASE(name, id, b3type, inc) case name: return "name";
+inline const char* toString(Type type)
+{
+    switch (type) {
+    FOR_EACH_WASM_TYPE(CREATE_CASE)
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+    return nullptr;
+}
+#undef CREATE_CASE
+
+#define CREATE_CASE(name, id, b3type, inc) case id: return inc;
+inline int linearizeType(Type type)
+{
+    switch (type) {
+    FOR_EACH_WASM_TYPE(CREATE_CASE)
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+    return 0;
+}
+#undef CREATE_CASE
+
+#define CREATE_CASE(name, id, b3type, inc) case inc: return name;
+inline Type linearizedToType(int i)
+{
+    switch (i) {
+    FOR_EACH_WASM_TYPE(CREATE_CASE)
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+    return Void;
+}
+#undef CREATE_CASE
+
+
 """ + defines + """
 #define FOR_EACH_WASM_OP(macro) \\
     FOR_EACH_WASM_SPECIAL_OP(macro) \\
@@ -110,7 +193,7 @@ namespace JSC { namespace Wasm {
     FOR_EACH_WASM_MEMORY_LOAD_OP(macro) \\
     FOR_EACH_WASM_MEMORY_STORE_OP(macro)
 
-#define CREATE_ENUM_VALUE(name, id, b3op) name = id,
+#define CREATE_ENUM_VALUE(name, id, b3op, inc) name = id,
 
 enum OpType : uint8_t {
     FOR_EACH_WASM_OP(CREATE_ENUM_VALUE)
@@ -145,7 +228,7 @@ enum class StoreOpType : uint8_t {
 inline bool isControlOp(OpType op)
 {
     switch (op) {
-#define CREATE_CASE(name, id, b3op) case OpType::name:
+#define CREATE_CASE(name, id, b3op, inc) case OpType::name:
     FOR_EACH_WASM_CONTROL_FLOW_OP(CREATE_CASE)
         return true;
 #undef CREATE_CASE
@@ -158,7 +241,7 @@ inline bool isControlOp(OpType op)
 inline bool isSimple(UnaryOpType op)
 {
     switch (op) {
-#define CREATE_CASE(name, id, b3op) case UnaryOpType::name:
+#define CREATE_CASE(name, id, b3op, inc) case UnaryOpType::name:
     FOR_EACH_WASM_SIMPLE_UNARY_OP(CREATE_CASE)
         return true;
 #undef CREATE_CASE
@@ -171,7 +254,7 @@ inline bool isSimple(UnaryOpType op)
 inline bool isSimple(BinaryOpType op)
 {
     switch (op) {
-#define CREATE_CASE(name, id, b3op) case BinaryOpType::name:
+#define CREATE_CASE(name, id, b3op, inc) case BinaryOpType::name:
     FOR_EACH_WASM_SIMPLE_BINARY_OP(CREATE_CASE)
         return true;
 #undef CREATE_CASE
index c5c10ff..8d3e53b 100644 (file)
@@ -63,10 +63,6 @@ static EncodedJSValue JSC_HOST_CALL callWebAssemblyFunction(ExecState* state)
     for (unsigned argIndex = 0; argIndex < state->argumentCount(); ++argIndex) {
         JSValue arg = state->uncheckedArgument(argIndex);
         switch (signature->arguments[argIndex]) {
-        case Wasm::Void:
-        case Wasm::I64:
-            RELEASE_ASSERT_NOT_REACHED();
-            break;
         case Wasm::I32:
             arg = JSValue::decode(arg.toInt32(state));
             break;
@@ -76,6 +72,11 @@ static EncodedJSValue JSC_HOST_CALL callWebAssemblyFunction(ExecState* state)
         case Wasm::F64:
             arg = JSValue::decode(bitwise_cast<uint64_t>(arg.toNumber(state)));
             break;
+        case Wasm::Void:
+        case Wasm::I64:
+        case Wasm::Func:
+        case Wasm::Anyfunc:
+            RELEASE_ASSERT_NOT_REACHED();
         }
         RETURN_IF_EXCEPTION(scope, encodedJSValue());
         boxedArgs.append(arg);
@@ -99,17 +100,20 @@ static EncodedJSValue JSC_HOST_CALL callWebAssemblyFunction(ExecState* state)
     switch (signature->returnType) {
     case Wasm::Void:
         return JSValue::encode(jsUndefined());
-    case Wasm::I64:
-        RELEASE_ASSERT_NOT_REACHED();
     case Wasm::I32:
         return JSValue::encode(JSValue(static_cast<int32_t>(rawResult)));
     case Wasm::F32:
         return JSValue::encode(JSValue(bitwise_cast<float>(static_cast<int32_t>(rawResult))));
     case Wasm::F64:
         return JSValue::encode(JSValue(bitwise_cast<double>(rawResult)));
+    case Wasm::I64:
+    case Wasm::Func:
+    case Wasm::Anyfunc:
+        break;
     }
 
     RELEASE_ASSERT_NOT_REACHED();
+    return EncodedJSValue();
 }
 
 WebAssemblyFunction* WebAssemblyFunction::create(VM& vm, JSGlobalObject* globalObject, int length, const String& name, JSWebAssemblyInstance* instance, CallableWebAssemblyFunction&& callable)
index d8f7c91..34878ea 100644 (file)
@@ -1,25 +1,23 @@
 {
     "comments": ["This file describes the WebAssembly ISA.",
-                 "Scripts in this folder auto-generate C++ code for JavaScriptCore as well as the testing DSL which WebKit's WebAssembly tests use.",
-                 "When you update this file you need to re-generate the C++ code: jsc ./JSTests/stress/wasm/generate-wasmops-header.js > ./Source/JavaScriptCore/wasm/WASMOps.h"
+                 "Scripts in this folder auto-generate C++ code for JavaScriptCore as well as the testing DSL which WebKit's WebAssembly tests use."
                 ],
     "preamble": [
         { "name": "magic number", "type": "uint32", "value": 1836278016, "description": "NULL character followed by 'asm'" },
-        { "name": "version",      "type": "uint32", "value":         12, "description": "Version number, will be reset to 1 for MVP" }
+        { "name": "version",      "type": "uint32", "value":         13, "description": "Version number, will be reset to 1 for MVP" }
     ],
-    "value_type" : {
-        "i32": { "type": "uint8", "value": 1 },
-        "i64": { "type": "uint8", "value": 2 },
-        "f32": { "type": "uint8", "value": 3 },
-        "f64": { "type": "uint8", "value": 4 }
-    },
-    "inline_signature_type" : {
-        "void": { "type": "uint8", "value": 0 },
-        "i32":  { "type": "uint8", "value": 1 },
-        "i64":  { "type": "uint8", "value": 2 },
-        "f32":  { "type": "uint8", "value": 3 },
-        "f64":  { "type": "uint8", "value": 4 }
+    "type" : {
+        "i32":     { "type": "varint7", "value":  -1, "b3type": "B3::Int32" },
+        "i64":     { "type": "varint7", "value":  -2, "b3type": "B3::Int64" },
+        "f32":     { "type": "varint7", "value":  -3, "b3type": "B3::Float" },
+        "f64":     { "type": "varint7", "value":  -4, "b3type": "B3::Double" },
+        "anyfunc": { "type": "varint7", "value": -16, "b3type": "B3::Void" },
+        "func":    { "type": "varint7", "value": -32, "b3type": "B3::Void" },
+        "void":    { "type": "varint7", "value": -64, "b3type": "B3::Void" }
     },
+    "value_type": ["i32", "i64", "f32", "f64"],
+    "block_type": ["i32", "i64", "f32", "f64", "void"],
+    "elem_type": ["anyfunc"],
     "external_kind": {
         "Function": { "type": "uint8", "value": 0 },
         "Table":    { "type": "uint8", "value": 1 },
     },
     "opcode": {
         "unreachable":         { "category": "control",    "value":   0, "return": [],           "parameter": [],                      "immediate": [],                                                                                         "description": "trap immediately" },
-        "block":               { "category": "control",    "value":   1, "return": ["control"],  "parameter": [],                      "immediate": [{"name": "sig", "type": "inline_signature_type"}],                                         "description": "begin a sequence of expressions, yielding 0 or 1 values" },
-        "loop":                { "category": "control",    "value":   2, "return": ["control"],  "parameter": [],                      "immediate": [{"name": "sig", "type": "inline_signature_type"}],                                         "description": "begin a block which can also form control flow loops" },
-        "if":                  { "category": "control",    "value":   3, "return": ["control"],  "parameter": ["bool"],                "immediate": [{"name": "sig", "type": "inline_signature_type"}],                                         "description": "begin if expression" },
-        "else":                { "category": "control",    "value":   4, "return": ["control"],  "parameter": [],                      "immediate": [],                                                                                         "description": "begin else expression of if" },
-        "select":              { "category": "control",    "value":   5, "return": ["prev"],     "parameter": ["any", "prev", "bool"], "immediate": [],                                                                                         "description": "select one of two values based on condition" },
-        "br":                  { "category": "control",    "value":   6, "return": [],           "parameter": [],                      "immediate": [{"name": "relative_depth", "type": "varuint32"}],                                          "description": "break that targets an outer nested block" },
-        "br_if":               { "category": "control",    "value":   7, "return": [],           "parameter": [],                      "immediate": [{"name": "relative_depth", "type": "varuint32"}],                                          "description": "conditional break that targets an outer nested block" },
-        "br_table":            { "category": "control",    "value":   8, "return": [],           "parameter": [],                      "immediate": [{"name": "target_count",   "type": "varuint32",                                            "description": "number of entries in the target_table"},
+        "block":               { "category": "control",    "value":   2, "return": ["control"],  "parameter": [],                      "immediate": [{"name": "sig", "type": "block_type"}],                                                    "description": "begin a sequence of expressions, yielding 0 or 1 values" },
+        "loop":                { "category": "control",    "value":   3, "return": ["control"],  "parameter": [],                      "immediate": [{"name": "sig", "type": "block_type"}],                                                    "description": "begin a block which can also form control flow loops" },
+        "if":                  { "category": "control",    "value":   4, "return": ["control"],  "parameter": ["bool"],                "immediate": [{"name": "sig", "type": "block_type"}],                                                    "description": "begin if expression" },
+        "else":                { "category": "control",    "value":   5, "return": ["control"],  "parameter": [],                      "immediate": [],                                                                                         "description": "begin else expression of if" },
+        "select":              { "category": "control",    "value":  27, "return": ["prev"],     "parameter": ["any", "prev", "bool"], "immediate": [],                                                                                         "description": "select one of two values based on condition" },
+        "br":                  { "category": "control",    "value":  12, "return": [],           "parameter": [],                      "immediate": [{"name": "relative_depth", "type": "varuint32"}],                                          "description": "break that targets an outer nested block" },
+        "br_if":               { "category": "control",    "value":  13, "return": [],           "parameter": [],                      "immediate": [{"name": "relative_depth", "type": "varuint32"}],                                          "description": "conditional break that targets an outer nested block" },
+        "br_table":            { "category": "control",    "value":  14, "return": [],           "parameter": [],                      "immediate": [{"name": "target_count",   "type": "varuint32",                                            "description": "number of entries in the target_table"},
                                                                                                                                                      {"name": "target_table",   "type": "varuint32*",                                           "description": "target entries that indicate an outer block or loop to which to break"},
                                                                                                                                                      {"name": "default_target", "type": "varuint32",                                            "description": "an outer block or loop to which to break in the default case"}],
                                                                                                                                                                                                                                                 "description": "branch table control flow construct" },
-        "return":              { "category": "control",    "value":   9, "return": [],           "parameter": [],                       "immediate": [],                                                                                         "description": "return zero or one value from this function" },
-        "drop":                { "category": "control",    "value":  11, "return": [],           "parameter": ["any"],                  "immediate": [],                                                                                         "description": "ignore value" },
-        "nop":                 { "category": "control",    "value":  10, "return": [],           "parameter": [],                       "immediate": [],                                                                                         "description": "no operation" },
-        "end":                 { "category": "control",    "value":  15, "return": [],           "parameter": [],                       "immediate": [],                                                                                         "description": "end a block, loop, or if" },
-        "i32.const":           { "category": "special",    "value":  16, "return": ["i32"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "varint32"}],                                           "description": "a constant value interpreted as i32" },
-        "i64.const":           { "category": "special",    "value":  17, "return": ["i64"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "varint64"}],                                           "description": "a constant value interpreted as i64" },
-        "f64.const":           { "category": "special",    "value":  18, "return": ["f64"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "uint64"}],                                             "description": "a constant value interpreted as f64" },
-        "f32.const":           { "category": "special",    "value":  19, "return": ["f32"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "uint32"}],                                             "description": "a constant value interpreted as f32" },
-        "get_local":           { "category": "special",    "value":  20, "return": ["local"],    "parameter": [],                       "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "read a local variable or parameter" },
-        "set_local":           { "category": "special",    "value":  21, "return": [],           "parameter": ["local"],                "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "write a local variable or parameter" },
-        "tee_local":           { "category": "special",    "value":  25, "return": ["prev"],     "parameter": ["any"],                  "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "write a local variable or parameter and return the same value" },
-        "get_global":          { "category": "special",    "value": 187, "return": ["global"],   "parameter": [],                       "immediate": [{"name": "global_index",   "type": "varuint32"}],                                          "description": "read a global variable" },
-        "set_global":          { "category": "special",    "value": 188, "return": [""],         "parameter": ["global"],               "immediate": [{"name": "global_index",   "type": "varuint32"}],                                          "description": "write a global variable" },
-        "call":                { "category": "call",       "value":  22, "return": ["call"],     "parameter": ["call"],                 "immediate": [{"name": "function_index", "type": "varuint32"}],                                          "description": "call a function by its index" },
-        "call_indirect":       { "category": "call",       "value":  23, "return": ["call"],     "parameter": ["call"],                 "immediate": [{"name": "type_index",     "type": "varuint32"}],                                          "description": "call a function indirect with an expected signature" },
-        "i32.load8_s":         { "category": "memory",     "value":  32, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "i32.load8_u":         { "category": "memory",     "value":  33, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "i32.load16_s":        { "category": "memory",     "value":  34, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "i32.load16_u":        { "category": "memory",     "value":  35, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "i64.load8_s":         { "category": "memory",     "value":  36, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "i64.load8_u":         { "category": "memory",     "value":  37, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "i64.load16_s":        { "category": "memory",     "value":  38, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "i64.load16_u":        { "category": "memory",     "value":  39, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "i64.load32_s":        { "category": "memory",     "value":  40, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "i64.load32_u":        { "category": "memory",     "value":  41, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "i32.load":            { "category": "memory",     "value":  42, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "i64.load":            { "category": "memory",     "value":  43, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "f32.load":            { "category": "memory",     "value":  44, "return": ["f32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "f64.load":            { "category": "memory",     "value":  45, "return": ["f64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
-        "i32.store8":          { "category": "memory",     "value":  46, "return": [],           "parameter": ["addr", "i32"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
-        "i32.store16":         { "category": "memory",     "value":  47, "return": [],           "parameter": ["addr", "i32"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
-        "i64.store8":          { "category": "memory",     "value":  48, "return": [],           "parameter": ["addr", "i64"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
-        "i64.store16":         { "category": "memory",     "value":  49, "return": [],           "parameter": ["addr", "i64"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
-        "i64.store32":         { "category": "memory",     "value":  50, "return": [],           "parameter": ["addr", "i64"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
-        "i32.store":           { "category": "memory",     "value":  51, "return": [],           "parameter": ["addr", "i32"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
-        "i64.store":           { "category": "memory",     "value":  52, "return": [],           "parameter": ["addr", "i64"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
-        "f32.store":           { "category": "memory",     "value":  53, "return": [],           "parameter": ["addr", "f32"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
-        "f64.store":           { "category": "memory",     "value":  54, "return": [],           "parameter": ["addr", "f64"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
-        "current_memory":      { "category": "operation",  "value":  59, "return": ["size"],     "parameter": [],                       "immediate": [],                                                                                         "description": "query the size of memory" },
-        "grow_memory":         { "category": "operation",  "value":  57, "return": ["size"],     "parameter": ["size"],                 "immediate": [],                                                                                         "description": "grow the size of memory" },
-        "i32.add":             { "category": "arithmetic", "value":  64, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Add"          },
-        "i32.sub":             { "category": "arithmetic", "value":  65, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Sub"          },
-        "i32.mul":             { "category": "arithmetic", "value":  66, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Mul"          },
-        "i32.div_s":           { "category": "arithmetic", "value":  67, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Div"          },
-        "i32.div_u":           { "category": "arithmetic", "value":  68, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "UDiv"         },
-        "i32.rem_s":           { "category": "arithmetic", "value":  69, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Mod"          },
-        "i32.rem_u":           { "category": "arithmetic", "value":  70, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "UMod"         },
-        "i32.and":             { "category": "arithmetic", "value":  71, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "BitAnd"       },
-        "i32.or":              { "category": "arithmetic", "value":  72, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "BitOr"        },
-        "i32.xor":             { "category": "arithmetic", "value":  73, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "BitXor"       },
-        "i32.shl":             { "category": "arithmetic", "value":  74, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Shl"          },
-        "i32.shr_u":           { "category": "arithmetic", "value":  75, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "SShr"         },
-        "i32.shr_s":           { "category": "arithmetic", "value":  76, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "ZShr"         },
-        "i32.rotr":            { "category": "arithmetic", "value": 182, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "RotR"         },
-        "i32.rotl":            { "category": "arithmetic", "value": 183, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "RotL"         },
-        "i32.eq":              { "category": "comparison", "value":  77, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Equal"        },
-        "i32.ne":              { "category": "comparison", "value":  78, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "NotEqual"     },
-        "i32.lt_s":            { "category": "comparison", "value":  79, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "LessThan"     },
-        "i32.le_s":            { "category": "comparison", "value":  80, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "LessEqual"    },
-        "i32.lt_u":            { "category": "comparison", "value":  81, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Below"        },
-        "i32.le_u":            { "category": "comparison", "value":  82, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "BelowEqual"   },
-        "i32.gt_s":            { "category": "comparison", "value":  83, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "GreaterThan"  },
-        "i32.ge_s":            { "category": "comparison", "value":  84, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "GreaterEqual" },
-        "i32.gt_u":            { "category": "comparison", "value":  85, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Above"        },
-        "i32.ge_u":            { "category": "comparison", "value":  86, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "AboveEqual"   },
-        "i32.clz":             { "category": "arithmetic", "value":  87, "return": ["i32"],      "parameter": ["i32"],                  "immediate": [], "b3op": "Clz"          },
-        "i32.ctz":             { "category": "arithmetic", "value":  88, "return": ["i32"],      "parameter": ["i32"],                  "immediate": []                         },
-        "i32.popcnt":          { "category": "arithmetic", "value":  89, "return": ["i32"],      "parameter": ["i32"],                  "immediate": []                         },
-        "i32.eqz":             { "category": "comparison", "value":  90, "return": ["bool"],     "parameter": ["i32"],                  "immediate": [], "b3op": "Equal(i32(0), @0)" },
-        "i64.add":             { "category": "arithmetic", "value":  91, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Add"          },
-        "i64.sub":             { "category": "arithmetic", "value":  92, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Sub"          },
-        "i64.mul":             { "category": "arithmetic", "value":  93, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Mul"          },
-        "i64.div_s":           { "category": "arithmetic", "value":  94, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Div"          },
-        "i64.div_u":           { "category": "arithmetic", "value":  95, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "UDiv"         },
-        "i64.rem_s":           { "category": "arithmetic", "value":  96, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Mod"          },
-        "i64.rem_u":           { "category": "arithmetic", "value":  97, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "UDiv"         },
-        "i64.and":             { "category": "arithmetic", "value":  98, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "BitAnd"       },
-        "i64.or":              { "category": "arithmetic", "value":  99, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "BitOr"        },
-        "i64.xor":             { "category": "arithmetic", "value": 100, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "BitXor"       },
-        "i64.shl":             { "category": "arithmetic", "value": 101, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Shl"          },
-        "i64.shr_u":           { "category": "arithmetic", "value": 102, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "SShr"         },
-        "i64.shr_s":           { "category": "arithmetic", "value": 103, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "ZShr"         },
-        "i64.rotr":            { "category": "arithmetic", "value": 184, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "RotR"         },
-        "i64.rotl":            { "category": "arithmetic", "value": 185, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "RotL"         },
-        "i64.eq":              { "category": "comparison", "value": 104, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Equal"        },
-        "i64.ne":              { "category": "comparison", "value": 105, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "NotEqual"     },
-        "i64.lt_s":            { "category": "comparison", "value": 106, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "LessThan"     },
-        "i64.le_s":            { "category": "comparison", "value": 107, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "LessEqual"    },
-        "i64.lt_u":            { "category": "comparison", "value": 108, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Below"        },
-        "i64.le_u":            { "category": "comparison", "value": 109, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "BelowEqual"   },
-        "i64.gt_s":            { "category": "comparison", "value": 110, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "GreaterThan"  },
-        "i64.ge_s":            { "category": "comparison", "value": 111, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "GreaterEqual" },
-        "i64.gt_u":            { "category": "comparison", "value": 112, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Above"        },
-        "i64.ge_u":            { "category": "comparison", "value": 113, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "AboveEqual"   },
-        "i64.clz":             { "category": "arithmetic", "value": 114, "return": ["i64"],      "parameter": ["i64"],                  "immediate": [], "b3op": "Clz"          },
-        "i64.ctz":             { "category": "arithmetic", "value": 115, "return": ["i64"],      "parameter": ["i64"],                  "immediate": []                         },
-        "i64.popcnt":          { "category": "arithmetic", "value": 116, "return": ["i64"],      "parameter": ["i64"],                  "immediate": []                         },
-        "i64.eqz":             { "category": "comparison", "value": 186, "return": ["bool"],     "parameter": ["i64"],                  "immediate": [], "b3op": "Equal(i32(0), @0)" },
-        "f32.add":             { "category": "arithmetic", "value": 117, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Add"          },
-        "f32.sub":             { "category": "arithmetic", "value": 118, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Sub"          },
-        "f32.mul":             { "category": "arithmetic", "value": 119, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Mul"          },
-        "f32.div":             { "category": "arithmetic", "value": 120, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Div"          },
-        "f32.min":             { "category": "arithmetic", "value": 121, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Select(LessThan(@0, @1), @0, @1)" },
-        "f32.max":             { "category": "arithmetic", "value": 122, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Select(LessThan(@0, @1), @1, @0)" },
-        "f32.abs":             { "category": "arithmetic", "value": 123, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Abs"          },
-        "f32.neg":             { "category": "arithmetic", "value": 124, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Neg"          },
-        "f32.copysign":        { "category": "arithmetic", "value": 125, "return": ["f32"],      "parameter": ["f32"],                  "immediate": []                         },
-        "f32.ceil":            { "category": "arithmetic", "value": 126, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Ceil"         },
-        "f32.floor":           { "category": "arithmetic", "value": 127, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Floor"        },
-        "f32.trunc":           { "category": "arithmetic", "value": 128, "return": ["f32"],      "parameter": ["f32"],                  "immediate": []                         },
-        "f32.nearest":         { "category": "arithmetic", "value": 129, "return": ["f32"],      "parameter": ["f32"],                  "immediate": []                         },
-        "f32.sqrt":            { "category": "arithmetic", "value": 130, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Sqrt"         },
-        "f32.eq":              { "category": "comparison", "value": 131, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Equal"        },
-        "f32.ne":              { "category": "comparison", "value": 132, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "NotEqual"     },
-        "f32.lt":              { "category": "comparison", "value": 133, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "LessThan"     },
-        "f32.le":              { "category": "comparison", "value": 134, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "LessEqual"    },
-        "f32.gt":              { "category": "comparison", "value": 135, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "GreaterThan"  },
-        "f32.ge":              { "category": "comparison", "value": 136, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "GreaterEqual" },
-        "f64.add":             { "category": "arithmetic", "value": 137, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Add"          },
-        "f64.sub":             { "category": "arithmetic", "value": 138, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Sub"          },
-        "f64.mul":             { "category": "arithmetic", "value": 139, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Mul"          },
-        "f64.div":             { "category": "arithmetic", "value": 140, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Div"          },
-        "f64.min":             { "category": "arithmetic", "value": 141, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Select(LessThan(@0, @1), @0, @1)" },
-        "f64.max":             { "category": "arithmetic", "value": 142, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Select(LessThan(@0, @1), @1, @0)" },
-        "f64.abs":             { "category": "arithmetic", "value": 143, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Abs"          },
-        "f64.neg":             { "category": "arithmetic", "value": 144, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Neg"          },
-        "f64.copysign":        { "category": "arithmetic", "value": 145, "return": ["f64"],      "parameter": ["f64"],                  "immediate": []                         },
-        "f64.ceil":            { "category": "arithmetic", "value": 146, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Ceil"         },
-        "f64.floor":           { "category": "arithmetic", "value": 147, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Floor"        },
-        "f64.trunc":           { "category": "arithmetic", "value": 148, "return": ["f64"],      "parameter": ["f64"],                  "immediate": []                         },
-        "f64.nearest":         { "category": "arithmetic", "value": 149, "return": ["f64"],      "parameter": ["f64"],                  "immediate": []                         },
-        "f64.sqrt":            { "category": "arithmetic", "value": 150, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Sqrt"         },
-        "f64.eq":              { "category": "comparison", "value": 151, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Equal"        },
-        "f64.ne":              { "category": "comparison", "value": 152, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "NotEqual"     },
-        "f64.lt":              { "category": "comparison", "value": 153, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "LessThan"     },
-        "f64.le":              { "category": "comparison", "value": 154, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "LessEqual"    },
-        "f64.gt":              { "category": "comparison", "value": 155, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "GreaterThan"  },
-        "f64.ge":              { "category": "comparison", "value": 156, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "GreaterEqual" },
-        "i32.trunc_s/f32":     { "category": "conversion", "value": 157, "return": ["i32"],      "parameter": ["f32"],                  "immediate": []                         },
-        "i32.trunc_s/f64":     { "category": "conversion", "value": 158, "return": ["i32"],      "parameter": ["f64"],                  "immediate": []                         },
-        "i32.trunc_u/f32":     { "category": "conversion", "value": 159, "return": ["i32"],      "parameter": ["f32"],                  "immediate": []                         },
-        "i32.trunc_u/f64":     { "category": "conversion", "value": 160, "return": ["i32"],      "parameter": ["f64"],                  "immediate": []                         },
-        "i32.wrap/i64":        { "category": "conversion", "value": 161, "return": ["i32"],      "parameter": ["i64"],                  "immediate": []                         },
-        "i64.trunc_s/f32":     { "category": "conversion", "value": 162, "return": ["i64"],      "parameter": ["f32"],                  "immediate": []                         },
-        "i64.trunc_s/f64":     { "category": "conversion", "value": 163, "return": ["i64"],      "parameter": ["f64"],                  "immediate": []                         },
-        "i64.trunc_u/f32":     { "category": "conversion", "value": 164, "return": ["i64"],      "parameter": ["f32"],                  "immediate": []                         },
-        "i64.trunc_u/f64":     { "category": "conversion", "value": 165, "return": ["i64"],      "parameter": ["f64"],                  "immediate": []                         },
-        "i64.extend_s/i32":    { "category": "conversion", "value": 166, "return": ["i64"],      "parameter": ["i32"],                  "immediate": [], "b3op": "SExt32"       },
-        "i64.extend_u/i32":    { "category": "conversion", "value": 167, "return": ["i64"],      "parameter": ["i32"],                  "immediate": [], "b3op": "ZExt32"       },
-        "f32.convert_s/i32":   { "category": "conversion", "value": 168, "return": ["f32"],      "parameter": ["i32"],                  "immediate": []                         },
-        "f32.convert_u/i32":   { "category": "conversion", "value": 169, "return": ["f32"],      "parameter": ["i32"],                  "immediate": []                         },
-        "f32.convert_s/i64":   { "category": "conversion", "value": 170, "return": ["f32"],      "parameter": ["i64"],                  "immediate": []                         },
-        "f32.convert_u/i64":   { "category": "conversion", "value": 171, "return": ["f32"],      "parameter": ["i64"],                  "immediate": []                         },
-        "f32.demote/f64":      { "category": "conversion", "value": 172, "return": ["f32"],      "parameter": ["f64"],                  "immediate": [], "b3op": "DoubleToFloat"},
-        "f32.reinterpret/i32": { "category": "conversion", "value": 173, "return": ["f32"],      "parameter": ["i32"],                  "immediate": [], "b3op": "BitwiseCast"  },
-        "f64.convert_s/i32":   { "category": "conversion", "value": 174, "return": ["f64"],      "parameter": ["i32"],                  "immediate": []                         },
-        "f64.convert_u/i32":   { "category": "conversion", "value": 175, "return": ["f64"],      "parameter": ["i32"],                  "immediate": []                         },
-        "f64.convert_s/i64":   { "category": "conversion", "value": 176, "return": ["f64"],      "parameter": ["i64"],                  "immediate": []                         },
-        "f64.convert_u/i64":   { "category": "conversion", "value": 177, "return": ["f64"],      "parameter": ["i64"],                  "immediate": []                         },
-        "f64.promote/f32":     { "category": "conversion", "value": 178, "return": ["f64"],      "parameter": ["f32"],                  "immediate": [], "b3op": "FloatToDouble"},
-        "f64.reinterpret/i64": { "category": "conversion", "value": 179, "return": ["f64"],      "parameter": ["i64"],                  "immediate": [], "b3op": "BitwiseCast"  },
-        "i32.reinterpret/f32": { "category": "conversion", "value": 180, "return": ["i32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "BitwiseCast"  },
-        "i64.reinterpret/f64": { "category": "conversion", "value": 181, "return": ["i64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "BitwiseCast"  }
+        "return":              { "category": "control",    "value":  15, "return": [],           "parameter": [],                       "immediate": [],                                                                                         "description": "return zero or one value from this function" },
+        "drop":                { "category": "control",    "value":  26, "return": [],           "parameter": ["any"],                  "immediate": [],                                                                                         "description": "ignore value" },
+        "nop":                 { "category": "control",    "value":   1, "return": [],           "parameter": [],                       "immediate": [],                                                                                         "description": "no operation" },
+        "end":                 { "category": "control",    "value":  11, "return": [],           "parameter": [],                       "immediate": [],                                                                                         "description": "end a block, loop, or if" },
+        "i32.const":           { "category": "special",    "value":  65, "return": ["i32"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "varint32"}],                                           "description": "a constant value interpreted as i32" },
+        "i64.const":           { "category": "special",    "value":  66, "return": ["i64"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "varint64"}],                                           "description": "a constant value interpreted as i64" },
+        "f64.const":           { "category": "special",    "value":  68, "return": ["f64"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "uint64"}],                                             "description": "a constant value interpreted as f64" },
+        "f32.const":           { "category": "special",    "value":  67, "return": ["f32"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "uint32"}],                                             "description": "a constant value interpreted as f32" },
+        "get_local":           { "category": "special",    "value":  32, "return": ["local"],    "parameter": [],                       "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "read a local variable or parameter" },
+        "set_local":           { "category": "special",    "value":  33, "return": [],           "parameter": ["local"],                "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "write a local variable or parameter" },
+        "tee_local":           { "category": "special",    "value":  34, "return": ["prev"],     "parameter": ["any"],                  "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "write a local variable or parameter and return the same value" },
+        "get_global":          { "category": "special",    "value":  35, "return": ["global"],   "parameter": [],                       "immediate": [{"name": "global_index",   "type": "varuint32"}],                                          "description": "read a global variable" },
+        "set_global":          { "category": "special",    "value":  36, "return": [""],         "parameter": ["global"],               "immediate": [{"name": "global_index",   "type": "varuint32"}],                                          "description": "write a global variable" },
+        "call":                { "category": "call",       "value":  16, "return": ["call"],     "parameter": ["call"],                 "immediate": [{"name": "function_index", "type": "varuint32"}],                                          "description": "call a function by its index" },
+        "call_indirect":       { "category": "call",       "value":  17, "return": ["call"],     "parameter": ["call"],                 "immediate": [{"name": "type_index",     "type": "varuint32"}],                                          "description": "call a function indirect with an expected signature" },
+        "i32.load8_s":         { "category": "memory",     "value":  44, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i32.load8_u":         { "category": "memory",     "value":  45, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i32.load16_s":        { "category": "memory",     "value":  46, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i32.load16_u":        { "category": "memory",     "value":  47, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i64.load8_s":         { "category": "memory",     "value":  48, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i64.load8_u":         { "category": "memory",     "value":  49, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i64.load16_s":        { "category": "memory",     "value":  50, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i64.load16_u":        { "category": "memory",     "value":  51, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i64.load32_s":        { "category": "memory",     "value":  52, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i64.load32_u":        { "category": "memory",     "value":  53, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i32.load":            { "category": "memory",     "value":  40, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i64.load":            { "category": "memory",     "value":  41, "return": ["i64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "f32.load":            { "category": "memory",     "value":  42, "return": ["f32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "f64.load":            { "category": "memory",     "value":  43, "return": ["f64"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
+        "i32.store8":          { "category": "memory",     "value":  58, "return": [],           "parameter": ["addr", "i32"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "i32.store16":         { "category": "memory",     "value":  59, "return": [],           "parameter": ["addr", "i32"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "i64.store8":          { "category": "memory",     "value":  60, "return": [],           "parameter": ["addr", "i64"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "i64.store16":         { "category": "memory",     "value":  61, "return": [],           "parameter": ["addr", "i64"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "i64.store32":         { "category": "memory",     "value":  62, "return": [],           "parameter": ["addr", "i64"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "i32.store":           { "category": "memory",     "value":  54, "return": [],           "parameter": ["addr", "i32"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "i64.store":           { "category": "memory",     "value":  55, "return": [],           "parameter": ["addr", "i64"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "f32.store":           { "category": "memory",     "value":  56, "return": [],           "parameter": ["addr", "f32"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "f64.store":           { "category": "memory",     "value":  57, "return": [],           "parameter": ["addr", "f64"],          "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "store to memory" },
+        "current_memory":      { "category": "operation",  "value":  63, "return": ["size"],     "parameter": [],                       "immediate": [],                                                                                         "description": "query the size of memory" },
+        "grow_memory":         { "category": "operation",  "value":  64, "return": ["size"],     "parameter": ["size"],                 "immediate": [],                                                                                         "description": "grow the size of memory" },
+        "i32.add":             { "category": "arithmetic", "value": 106, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Add"          },
+        "i32.sub":             { "category": "arithmetic", "value": 107, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Sub"          },
+        "i32.mul":             { "category": "arithmetic", "value": 108, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Mul"          },
+        "i32.div_s":           { "category": "arithmetic", "value": 109, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Div"          },
+        "i32.div_u":           { "category": "arithmetic", "value": 110, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "UDiv"         },
+        "i32.rem_s":           { "category": "arithmetic", "value": 111, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Mod"          },
+        "i32.rem_u":           { "category": "arithmetic", "value": 112, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "UMod"         },
+        "i32.and":             { "category": "arithmetic", "value": 113, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "BitAnd"       },
+        "i32.or":              { "category": "arithmetic", "value": 114, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "BitOr"        },
+        "i32.xor":             { "category": "arithmetic", "value": 115, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "BitXor"       },
+        "i32.shl":             { "category": "arithmetic", "value": 116, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Shl"          },
+        "i32.shr_u":           { "category": "arithmetic", "value": 118, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "SShr"         },
+        "i32.shr_s":           { "category": "arithmetic", "value": 117, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "ZShr"         },
+        "i32.rotr":            { "category": "arithmetic", "value": 120, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "RotR"         },
+        "i32.rotl":            { "category": "arithmetic", "value": 119, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "RotL"         },
+        "i32.eq":              { "category": "comparison", "value":  70, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Equal"        },
+        "i32.ne":              { "category": "comparison", "value":  71, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "NotEqual"     },
+        "i32.lt_s":            { "category": "comparison", "value":  72, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "LessThan"     },
+        "i32.le_s":            { "category": "comparison", "value":  76, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "LessEqual"    },
+        "i32.lt_u":            { "category": "comparison", "value":  73, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Below"        },
+        "i32.le_u":            { "category": "comparison", "value":  77, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "BelowEqual"   },
+        "i32.gt_s":            { "category": "comparison", "value":  74, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "GreaterThan"  },
+        "i32.ge_s":            { "category": "comparison", "value":  78, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "GreaterEqual" },
+        "i32.gt_u":            { "category": "comparison", "value":  75, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Above"        },
+        "i32.ge_u":            { "category": "comparison", "value":  79, "return": ["bool"],     "parameter": ["i32", "i32"],           "immediate": [], "b3op": "AboveEqual"   },
+        "i32.clz":             { "category": "arithmetic", "value": 103, "return": ["i32"],      "parameter": ["i32"],                  "immediate": [], "b3op": "Clz"          },
+        "i32.ctz":             { "category": "arithmetic", "value": 104, "return": ["i32"],      "parameter": ["i32"],                  "immediate": []                         },
+        "i32.popcnt":          { "category": "arithmetic", "value": 105, "return": ["i32"],      "parameter": ["i32"],                  "immediate": []                         },
+        "i32.eqz":             { "category": "comparison", "value":  69, "return": ["bool"],     "parameter": ["i32"],                  "immediate": [], "b3op": "Equal(i32(0), @0)" },
+        "i64.add":             { "category": "arithmetic", "value": 124, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Add"          },
+        "i64.sub":             { "category": "arithmetic", "value": 125, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Sub"          },
+        "i64.mul":             { "category": "arithmetic", "value": 126, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Mul"          },
+        "i64.div_s":           { "category": "arithmetic", "value": 127, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Div"          },
+        "i64.div_u":           { "category": "arithmetic", "value": 128, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "UDiv"         },
+        "i64.rem_s":           { "category": "arithmetic", "value": 129, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Mod"          },
+        "i64.rem_u":           { "category": "arithmetic", "value": 130, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "UDiv"         },
+        "i64.and":             { "category": "arithmetic", "value": 131, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "BitAnd"       },
+        "i64.or":              { "category": "arithmetic", "value": 132, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "BitOr"        },
+        "i64.xor":             { "category": "arithmetic", "value": 133, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "BitXor"       },
+        "i64.shl":             { "category": "arithmetic", "value": 134, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Shl"          },
+        "i64.shr_u":           { "category": "arithmetic", "value": 136, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "SShr"         },
+        "i64.shr_s":           { "category": "arithmetic", "value": 135, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "ZShr"         },
+        "i64.rotr":            { "category": "arithmetic", "value": 138, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "RotR"         },
+        "i64.rotl":            { "category": "arithmetic", "value": 137, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "RotL"         },
+        "i64.eq":              { "category": "comparison", "value":  81, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Equal"        },
+        "i64.ne":              { "category": "comparison", "value":  82, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "NotEqual"     },
+        "i64.lt_s":            { "category": "comparison", "value":  83, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "LessThan"     },
+        "i64.le_s":            { "category": "comparison", "value":  87, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "LessEqual"    },
+        "i64.lt_u":            { "category": "comparison", "value":  84, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Below"        },
+        "i64.le_u":            { "category": "comparison", "value":  88, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "BelowEqual"   },
+        "i64.gt_s":            { "category": "comparison", "value":  85, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "GreaterThan"  },
+        "i64.ge_s":            { "category": "comparison", "value":  89, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "GreaterEqual" },
+        "i64.gt_u":            { "category": "comparison", "value":  86, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Above"        },
+        "i64.ge_u":            { "category": "comparison", "value":  90, "return": ["bool"],     "parameter": ["i64", "i64"],           "immediate": [], "b3op": "AboveEqual"   },
+        "i64.clz":             { "category": "arithmetic", "value": 121, "return": ["i64"],      "parameter": ["i64"],                  "immediate": [], "b3op": "Clz"          },
+        "i64.ctz":             { "category": "arithmetic", "value": 122, "return": ["i64"],      "parameter": ["i64"],                  "immediate": []                         },
+        "i64.popcnt":          { "category": "arithmetic", "value": 123, "return": ["i64"],      "parameter": ["i64"],                  "immediate": []                         },
+        "i64.eqz":             { "category": "comparison", "value":  80, "return": ["bool"],     "parameter": ["i64"],                  "immediate": [], "b3op": "Equal(i32(0), @0)" },
+        "f32.add":             { "category": "arithmetic", "value": 146, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Add"          },
+        "f32.sub":             { "category": "arithmetic", "value": 147, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Sub"          },
+        "f32.mul":             { "category": "arithmetic", "value": 148, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Mul"          },
+        "f32.div":             { "category": "arithmetic", "value": 149, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Div"          },
+        "f32.min":             { "category": "arithmetic", "value": 150, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Select(LessThan(@0, @1), @0, @1)" },
+        "f32.max":             { "category": "arithmetic", "value": 151, "return": ["f32"],      "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Select(LessThan(@0, @1), @1, @0)" },
+        "f32.abs":             { "category": "arithmetic", "value": 139, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Abs"          },
+        "f32.neg":             { "category": "arithmetic", "value": 140, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Neg"          },
+        "f32.copysign":        { "category": "arithmetic", "value": 152, "return": ["f32"],      "parameter": ["f32"],                  "immediate": []                         },
+        "f32.ceil":            { "category": "arithmetic", "value": 141, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Ceil"         },
+        "f32.floor":           { "category": "arithmetic", "value": 142, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Floor"        },
+        "f32.trunc":           { "category": "arithmetic", "value": 143, "return": ["f32"],      "parameter": ["f32"],                  "immediate": []                         },
+        "f32.nearest":         { "category": "arithmetic", "value": 144, "return": ["f32"],      "parameter": ["f32"],                  "immediate": []                         },
+        "f32.sqrt":            { "category": "arithmetic", "value": 145, "return": ["f32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "Sqrt"         },
+        "f32.eq":              { "category": "comparison", "value":  91, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "Equal"        },
+        "f32.ne":              { "category": "comparison", "value":  92, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "NotEqual"     },
+        "f32.lt":              { "category": "comparison", "value":  93, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "LessThan"     },
+        "f32.le":              { "category": "comparison", "value":  95, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "LessEqual"    },
+        "f32.gt":              { "category": "comparison", "value":  94, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "GreaterThan"  },
+        "f32.ge":              { "category": "comparison", "value":  96, "return": ["bool"],     "parameter": ["f32", "f32"],           "immediate": [], "b3op": "GreaterEqual" },
+        "f64.add":             { "category": "arithmetic", "value": 160, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Add"          },
+        "f64.sub":             { "category": "arithmetic", "value": 161, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Sub"          },
+        "f64.mul":             { "category": "arithmetic", "value": 162, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Mul"          },
+        "f64.div":             { "category": "arithmetic", "value": 163, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Div"          },
+        "f64.min":             { "category": "arithmetic", "value": 164, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Select(LessThan(@0, @1), @0, @1)" },
+        "f64.max":             { "category": "arithmetic", "value": 165, "return": ["f64"],      "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Select(LessThan(@0, @1), @1, @0)" },
+        "f64.abs":             { "category": "arithmetic", "value": 153, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Abs"          },
+        "f64.neg":             { "category": "arithmetic", "value": 154, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Neg"          },
+        "f64.copysign":        { "category": "arithmetic", "value": 166, "return": ["f64"],      "parameter": ["f64"],                  "immediate": []                         },
+        "f64.ceil":            { "category": "arithmetic", "value": 155, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Ceil"         },
+        "f64.floor":           { "category": "arithmetic", "value": 156, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Floor"        },
+        "f64.trunc":           { "category": "arithmetic", "value": 157, "return": ["f64"],      "parameter": ["f64"],                  "immediate": []                         },
+        "f64.nearest":         { "category": "arithmetic", "value": 158, "return": ["f64"],      "parameter": ["f64"],                  "immediate": []                         },
+        "f64.sqrt":            { "category": "arithmetic", "value": 159, "return": ["f64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "Sqrt"         },
+        "f64.eq":              { "category": "comparison", "value":  97, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "Equal"        },
+        "f64.ne":              { "category": "comparison", "value":  98, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "NotEqual"     },
+        "f64.lt":              { "category": "comparison", "value":  99, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "LessThan"     },
+        "f64.le":              { "category": "comparison", "value": 101, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "LessEqual"    },
+        "f64.gt":              { "category": "comparison", "value": 100, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "GreaterThan"  },
+        "f64.ge":              { "category": "comparison", "value": 102, "return": ["bool"],     "parameter": ["f64", "f64"],           "immediate": [], "b3op": "GreaterEqual" },
+        "i32.trunc_s/f32":     { "category": "conversion", "value": 168, "return": ["i32"],      "parameter": ["f32"],                  "immediate": []                         },
+        "i32.trunc_s/f64":     { "category": "conversion", "value": 170, "return": ["i32"],      "parameter": ["f64"],                  "immediate": []                         },
+        "i32.trunc_u/f32":     { "category": "conversion", "value": 169, "return": ["i32"],      "parameter": ["f32"],                  "immediate": []                         },
+        "i32.trunc_u/f64":     { "category": "conversion", "value": 171, "return": ["i32"],      "parameter": ["f64"],                  "immediate": []                         },
+        "i32.wrap/i64":        { "category": "conversion", "value": 167, "return": ["i32"],      "parameter": ["i64"],                  "immediate": []                         },
+        "i64.trunc_s/f32":     { "category": "conversion", "value": 174, "return": ["i64"],      "parameter": ["f32"],                  "immediate": []                         },
+        "i64.trunc_s/f64":     { "category": "conversion", "value": 176, "return": ["i64"],      "parameter": ["f64"],                  "immediate": []                         },
+        "i64.trunc_u/f32":     { "category": "conversion", "value": 175, "return": ["i64"],      "parameter": ["f32"],                  "immediate": []                         },
+        "i64.trunc_u/f64":     { "category": "conversion", "value": 177, "return": ["i64"],      "parameter": ["f64"],                  "immediate": []                         },
+        "i64.extend_s/i32":    { "category": "conversion", "value": 172, "return": ["i64"],      "parameter": ["i32"],                  "immediate": [], "b3op": "SExt32"       },
+        "i64.extend_u/i32":    { "category": "conversion", "value": 173, "return": ["i64"],      "parameter": ["i32"],                  "immediate": [], "b3op": "ZExt32"       },
+        "f32.convert_s/i32":   { "category": "conversion", "value": 178, "return": ["f32"],      "parameter": ["i32"],                  "immediate": []                         },
+        "f32.convert_u/i32":   { "category": "conversion", "value": 179, "return": ["f32"],      "parameter": ["i32"],                  "immediate": []                         },
+        "f32.convert_s/i64":   { "category": "conversion", "value": 180, "return": ["f32"],      "parameter": ["i64"],                  "immediate": []                         },
+        "f32.convert_u/i64":   { "category": "conversion", "value": 181, "return": ["f32"],      "parameter": ["i64"],                  "immediate": []                         },
+        "f32.demote/f64":      { "category": "conversion", "value": 182, "return": ["f32"],      "parameter": ["f64"],                  "immediate": [], "b3op": "DoubleToFloat"},
+        "f32.reinterpret/i32": { "category": "conversion", "value": 190, "return": ["f32"],      "parameter": ["i32"],                  "immediate": [], "b3op": "BitwiseCast"  },
+        "f64.convert_s/i32":   { "category": "conversion", "value": 183, "return": ["f64"],      "parameter": ["i32"],                  "immediate": []                         },
+        "f64.convert_u/i32":   { "category": "conversion", "value": 184, "return": ["f64"],      "parameter": ["i32"],                  "immediate": []                         },
+        "f64.convert_s/i64":   { "category": "conversion", "value": 185, "return": ["f64"],      "parameter": ["i64"],                  "immediate": []                         },
+        "f64.convert_u/i64":   { "category": "conversion", "value": 186, "return": ["f64"],      "parameter": ["i64"],                  "immediate": []                         },
+        "f64.promote/f32":     { "category": "conversion", "value": 187, "return": ["f64"],      "parameter": ["f32"],                  "immediate": [], "b3op": "FloatToDouble"},
+        "f64.reinterpret/i64": { "category": "conversion", "value": 191, "return": ["f64"],      "parameter": ["i64"],                  "immediate": [], "b3op": "BitwiseCast"  },
+        "i32.reinterpret/f32": { "category": "conversion", "value": 188, "return": ["i32"],      "parameter": ["f32"],                  "immediate": [], "b3op": "BitwiseCast"  },
+        "i64.reinterpret/f64": { "category": "conversion", "value": 189, "return": ["i64"],      "parameter": ["f64"],                  "immediate": [], "b3op": "BitwiseCast"  }
     }
 }