From 697f8d5c0fddfb7924fae64cd1dafe572dd2ee0a Mon Sep 17 00:00:00 2001 From: Asumu Takikawa Date: Thu, 10 Aug 2023 10:06:52 -0700 Subject: [PATCH] [Wasm-GC] Add nullexternref and nullfuncref types https://bugs.webkit.org/show_bug.cgi?id=254695 Reviewed by Yusuke Suzuki. * JSTests/wasm/gc/any.js: (testNullfuncref): (testNullexternref): * Source/JavaScriptCore/wasm/WasmBBQJIT.cpp: (JSC::Wasm::BBQJIT::sizeOfType): (JSC::Wasm::BBQJIT::toValueKind): (JSC::Wasm::BBQJIT::addConstant): (JSC::Wasm::BBQJIT::getGlobal): (JSC::Wasm::BBQJIT::setGlobal): (JSC::Wasm::BBQJIT::addTopLevel): (JSC::Wasm::BBQJIT::toB3Type): (JSC::Wasm::BBQJIT::emitCatchImpl): (JSC::Wasm::BBQJIT::emitCCall): (JSC::Wasm::BBQJIT::emitStoreConst): (JSC::Wasm::BBQJIT::emitMoveConst): (JSC::Wasm::BBQJIT::emitStore): (JSC::Wasm::BBQJIT::emitMoveMemory): (JSC::Wasm::BBQJIT::emitMoveRegister): (JSC::Wasm::BBQJIT::emitLoad): * Source/JavaScriptCore/wasm/WasmCallingConvention.h: (JSC::Wasm::WasmCallingConvention::numberOfStackResults const): (JSC::Wasm::WasmCallingConvention::numberOfStackArguments const): * Source/JavaScriptCore/wasm/WasmFormat.h: (JSC::Wasm::isNullfuncref): (JSC::Wasm::isNullexternref): (JSC::Wasm::isSubtype): (JSC::Wasm::isValidHeapTypeKind): * Source/JavaScriptCore/wasm/WasmLLIntGenerator.cpp: (JSC::Wasm::LLIntGenerator::callInformationForCaller): (JSC::Wasm::LLIntGenerator::callInformationForCallee): (JSC::Wasm::LLIntGenerator::addArguments): * Source/JavaScriptCore/wasm/WasmTypeDefinition.cpp: (JSC::Wasm::TypeInformation::castReference): * Source/JavaScriptCore/wasm/WasmTypeDefinition.h: (JSC::Wasm::typeKindSizeInBytes): * Source/JavaScriptCore/wasm/js/JSWebAssemblyStruct.cpp: (JSC::JSWebAssemblyStruct::set): * Source/JavaScriptCore/wasm/js/WasmToJS.cpp: (JSC::Wasm::wasmToJS): * Source/JavaScriptCore/wasm/wasm.json: Canonical link: https://commits.webkit.org/266766@main --- JSTests/wasm/gc/any.js | 80 +++++++++++++++++++ JSTests/wasm/gc/casts.js | 50 ++++++++++++ .../wasm/WasmAirIRGeneratorBase.h | 2 + .../JavaScriptCore/wasm/WasmB3IRGenerator.cpp | 2 + Source/JavaScriptCore/wasm/WasmBBQJIT.cpp | 30 +++++++ .../wasm/WasmCallingConvention.h | 4 + Source/JavaScriptCore/wasm/WasmFormat.h | 22 +++++ .../JavaScriptCore/wasm/WasmFunctionParser.h | 4 +- .../wasm/WasmLLIntGenerator.cpp | 8 ++ .../wasm/WasmTypeDefinition.cpp | 2 + .../JavaScriptCore/wasm/WasmTypeDefinition.h | 2 + .../wasm/js/JSWebAssemblyStruct.cpp | 2 + Source/JavaScriptCore/wasm/js/WasmToJS.cpp | 4 + Source/JavaScriptCore/wasm/wasm.json | 44 +++++----- 14 files changed, 234 insertions(+), 22 deletions(-) diff --git a/JSTests/wasm/gc/any.js b/JSTests/wasm/gc/any.js index e5346ed8cb17..e1c636fee963 100644 --- a/JSTests/wasm/gc/any.js +++ b/JSTests/wasm/gc/any.js @@ -88,6 +88,86 @@ function testNullref() { `).exports.f(); } +function testNullfuncref() { + instantiate(` + (module + (func (param nullfuncref) (result)) + (func (export "f") (call 0 (ref.null nofunc)))) + `).exports.f(); + + instantiate(` + (module + (func (export "f") (result funcref) (ref.null nofunc))) + `).exports.f(); + + assert.throws( + () => compile(` + (module + (func (export "f") (result nullfuncref) (ref.null func))) + `), + WebAssembly.CompileError, + "WebAssembly.Module doesn't validate: control flow returns with unexpected type. Funcref is not a Nullfuncref" + ) + + assert.throws( + () => compile(` + (module + (func (export "f") (result nullref) (ref.null nofunc))) + `), + WebAssembly.CompileError, + "WebAssembly.Module doesn't validate: control flow returns with unexpected type. Nullfuncref is not a Nullref" + ) + + instantiate(` + (module + (func (result nullfuncref) (local nullfuncref) + (local.set 0 (ref.null nofunc)) + (local.get 0)) + (func (export "f") (call 0) (drop))) + `).exports.f(); +} + +function testNullexternref() { + instantiate(` + (module + (func (param nullexternref) (result)) + (func (export "f") (call 0 (ref.null noextern)))) + `).exports.f(); + + instantiate(` + (module + (func (export "f") (result externref) (ref.null noextern))) + `).exports.f(); + + assert.throws( + () => compile(` + (module + (func (export "f") (result nullexternref) (ref.null extern))) + `), + WebAssembly.CompileError, + "WebAssembly.Module doesn't validate: control flow returns with unexpected type. Externref is not a Nullexternref" + ) + + assert.throws( + () => compile(` + (module + (func (export "f") (result nullref) (ref.null noextern))) + `), + WebAssembly.CompileError, + "WebAssembly.Module doesn't validate: control flow returns with unexpected type. Nullexternref is not a Nullref" + ) + + instantiate(` + (module + (func (result nullexternref) (local nullexternref) + (local.set 0 (ref.null noextern)) + (local.get 0)) + (func (export "f") (call 0) (drop))) + `).exports.f(); +} + testValidation(); testAnyref(); testNullref(); +testNullfuncref(); +testNullexternref(); diff --git a/JSTests/wasm/gc/casts.js b/JSTests/wasm/gc/casts.js index 9a2e4c68aaa9..99256ea87238 100644 --- a/JSTests/wasm/gc/casts.js +++ b/JSTests/wasm/gc/casts.js @@ -845,6 +845,56 @@ function testNullCasts() { 0 ); + assert.throws( + () => instantiate(` + (module + (start 1) + (func (param funcref) (result nullfuncref) + (ref.cast (ref nofunc) (local.get 0))) + (func + (call 0 (ref.null func)) + drop)) + `), + WebAssembly.RuntimeError, + "ref.cast failed to cast reference to target heap type" + ) + + assert.eq( + instantiate(` + (module + (func (param funcref) (result i32) + (ref.test (ref nofunc) (local.get 0))) + (func (export "f") (result i32) + (call 0 (ref.null func)))) + `).exports.f(), + 0 + ); + + assert.throws( + () => instantiate(` + (module + (start 1) + (func (param externref) (result nullexternref) + (ref.cast (ref noextern) (local.get 0))) + (func + (call 0 (ref.null extern)) + drop)) + `), + WebAssembly.RuntimeError, + "ref.cast failed to cast reference to target heap type" + ) + + assert.eq( + instantiate(` + (module + (func (param externref) (result i32) + (ref.test (ref noextern) (local.get 0))) + (func (export "f") (result i32) + (call 0 (ref.null extern)))) + `).exports.f(), + 0 + ); + assert.throws( () => instantiate(` (module diff --git a/Source/JavaScriptCore/wasm/WasmAirIRGeneratorBase.h b/Source/JavaScriptCore/wasm/WasmAirIRGeneratorBase.h index 43455e6df15d..dde9321cdd1f 100644 --- a/Source/JavaScriptCore/wasm/WasmAirIRGeneratorBase.h +++ b/Source/JavaScriptCore/wasm/WasmAirIRGeneratorBase.h @@ -2871,6 +2871,8 @@ void AirIRGeneratorBase::emitRefTestOrCast(CastKind cas // Casts to these types cannot fail as they are the top types of their respective hierarchies, and static type-checking does not allow cross-hierarchy casts. break; case Wasm::TypeKind::Nullref: + case Wasm::TypeKind::Nullfuncref: + case Wasm::TypeKind::Nullexternref: // Casts to any bottom type should always fail. if (castKind == CastKind::Cast) { B3::PatchpointValue* throwException = addPatchpoint(B3::Void); diff --git a/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp b/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp index 3f834b8589da..387a3f4e020e 100644 --- a/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp +++ b/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp @@ -3389,6 +3389,8 @@ void B3IRGenerator::emitRefTestOrCast(CastKind castKind, ExpressionType referenc // Casts to these types cannot fail as they are the top types of their respective hierarchies, and static type-checking does not allow cross-hierarchy casts. break; case Wasm::TypeKind::Nullref: + case Wasm::TypeKind::Nullfuncref: + case Wasm::TypeKind::Nullexternref: // Casts to any bottom type should always fail. if (castKind == CastKind::Cast) { B3::PatchpointValue* throwException = m_currentBlock->appendNew(m_proc, B3::Void, origin()); diff --git a/Source/JavaScriptCore/wasm/WasmBBQJIT.cpp b/Source/JavaScriptCore/wasm/WasmBBQJIT.cpp index 8920710ea86c..01f416674a46 100644 --- a/Source/JavaScriptCore/wasm/WasmBBQJIT.cpp +++ b/Source/JavaScriptCore/wasm/WasmBBQJIT.cpp @@ -397,6 +397,8 @@ class BBQJIT { case TypeKind::Eqref: case TypeKind::Anyref: case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: return sizeof(EncodedJSValue); case TypeKind::Void: return 0; @@ -428,6 +430,8 @@ class BBQJIT { case TypeKind::Eqref: case TypeKind::Anyref: case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: return TypeKind::I64; case TypeKind::Void: RELEASE_ASSERT_NOT_REACHED(); @@ -1428,6 +1432,8 @@ class BBQJIT { case TypeKind::Eqref: case TypeKind::Anyref: case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: result = Value::fromRef(type.kind, static_cast(value)); LOG_INSTRUCTION("RefConst", makeString(type.kind), RESULT(result)); break; @@ -1718,6 +1724,8 @@ class BBQJIT { case TypeKind::Eqref: case TypeKind::Anyref: case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: m_jit.load64(Address(wasmScratchGPR), resultLocation.asGPR()); break; case TypeKind::Void: @@ -1833,6 +1841,8 @@ class BBQJIT { case TypeKind::Eqref: case TypeKind::Anyref: case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: m_jit.store64(valueLocation.asGPR(), Address(wasmScratchGPR)); break; case TypeKind::Void: @@ -6825,6 +6835,8 @@ class BBQJIT { case TypeKind::Eqref: case TypeKind::Anyref: case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: clear(ClearMode::JSNull, type, m_locals[i]); break; default: @@ -6924,6 +6936,8 @@ class BBQJIT { case TypeKind::Eqref: case TypeKind::Anyref: case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: return B3::Type(B3::Int64); case TypeKind::F32: return B3::Type(B3::Float); @@ -7173,6 +7187,8 @@ class BBQJIT { case TypeKind::Eqref: case TypeKind::Anyref: case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: case TypeKind::Rec: case TypeKind::Sub: case TypeKind::Array: @@ -7841,6 +7857,8 @@ class BBQJIT { case TypeKind::Eqref: case TypeKind::Anyref: case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: case TypeKind::Rec: case TypeKind::Sub: case TypeKind::Array: @@ -9349,6 +9367,8 @@ class BBQJIT { case TypeKind::Eqref: case TypeKind::Anyref: case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: m_jit.store64(TrustedImm64(constant.asRef()), loc.asAddress()); break; case TypeKind::I64: @@ -9390,6 +9410,8 @@ class BBQJIT { case TypeKind::Eqref: case TypeKind::Anyref: case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: m_jit.move(TrustedImm64(constant.asRef()), loc.asGPR()); break; case TypeKind::F32: @@ -9432,6 +9454,8 @@ class BBQJIT { case TypeKind::Eqref: case TypeKind::Anyref: case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: m_jit.store64(src.asGPR(), dst.asAddress()); break; case TypeKind::V128: @@ -9481,6 +9505,8 @@ class BBQJIT { case TypeKind::Eqref: case TypeKind::Anyref: case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: m_jit.transfer64(src.asAddress(), dst.asAddress()); break; case TypeKind::V128: { @@ -9522,6 +9548,8 @@ class BBQJIT { case TypeKind::Eqref: case TypeKind::Anyref: case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: m_jit.move(src.asGPR(), dst.asGPR()); break; case TypeKind::F32: @@ -9572,6 +9600,8 @@ class BBQJIT { case TypeKind::Eqref: case TypeKind::Anyref: case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: m_jit.load64(src.asAddress(), dst.asGPR()); break; case TypeKind::V128: diff --git a/Source/JavaScriptCore/wasm/WasmCallingConvention.h b/Source/JavaScriptCore/wasm/WasmCallingConvention.h index 730390c593da..da751b83f357 100644 --- a/Source/JavaScriptCore/wasm/WasmCallingConvention.h +++ b/Source/JavaScriptCore/wasm/WasmCallingConvention.h @@ -185,6 +185,8 @@ class WasmCallingConvention { case TypeKind::Eqref: case TypeKind::Anyref: case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: case TypeKind::I31ref: case TypeKind::Sub: case TypeKind::Rec: @@ -231,6 +233,8 @@ class WasmCallingConvention { case TypeKind::Eqref: case TypeKind::Anyref: case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: case TypeKind::I31ref: case TypeKind::Sub: case TypeKind::Rec: diff --git a/Source/JavaScriptCore/wasm/WasmFormat.h b/Source/JavaScriptCore/wasm/WasmFormat.h index f476f7ade52a..6d3c9a6d5fc8 100644 --- a/Source/JavaScriptCore/wasm/WasmFormat.h +++ b/Source/JavaScriptCore/wasm/WasmFormat.h @@ -151,6 +151,20 @@ inline bool isNullref(Type type) return isRefType(type) && type.index == static_cast(TypeKind::Nullref); } +inline bool isNullfuncref(Type type) +{ + if (!Options::useWebAssemblyGC()) + return false; + return isRefType(type) && type.index == static_cast(TypeKind::Nullfuncref); +} + +inline bool isNullexternref(Type type) +{ + if (!Options::useWebAssemblyGC()) + return false; + return isRefType(type) && type.index == static_cast(TypeKind::Nullexternref); +} + inline bool isInternalref(Type type) { if (!Options::useWebAssemblyGC() || !isRefType(type) || !typeIndexIsType(type.index)) @@ -307,6 +321,12 @@ inline bool isSubtype(Type sub, Type parent) if (isNullref(sub)) return isInternalref(parent); + if (isNullfuncref(sub)) + return isSubtype(parent, funcrefType()); + + if (isNullexternref(sub)) + return sub == parent || isExternref(parent); + if (sub.isRef() && parent.isRefNull()) return sub.index == parent.index; @@ -334,6 +354,8 @@ inline bool isValidHeapTypeKind(TypeKind kind) case TypeKind::Eqref: case TypeKind::Anyref: case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: return Options::useWebAssemblyGC(); default: break; diff --git a/Source/JavaScriptCore/wasm/WasmFunctionParser.h b/Source/JavaScriptCore/wasm/WasmFunctionParser.h index ec0aa67c411f..6507fcfa0192 100644 --- a/Source/JavaScriptCore/wasm/WasmFunctionParser.h +++ b/Source/JavaScriptCore/wasm/WasmFunctionParser.h @@ -2190,10 +2190,12 @@ FOR_EACH_WASM_MEMORY_STORE_OP(CREATE_CASE) TypeIndex resultTypeIndex = static_cast(heapType); switch (static_cast(heapType)) { case TypeKind::Funcref: + case TypeKind::Nullfuncref: WASM_VALIDATOR_FAIL_IF(!isSubtype(ref.type(), funcrefType()), opName, " to type ", ref.type(), " expected a funcref"); break; case TypeKind::Externref: - WASM_VALIDATOR_FAIL_IF(!isExternref(ref.type()), opName, " to type ", ref.type(), " expected an externref"); + case TypeKind::Nullexternref: + WASM_VALIDATOR_FAIL_IF(!isSubtype(ref.type(), externrefType()), opName, " to type ", ref.type(), " expected an externref"); break; case TypeKind::Eqref: case TypeKind::Anyref: diff --git a/Source/JavaScriptCore/wasm/WasmLLIntGenerator.cpp b/Source/JavaScriptCore/wasm/WasmLLIntGenerator.cpp index 96264d8858f6..24c05d389665 100644 --- a/Source/JavaScriptCore/wasm/WasmLLIntGenerator.cpp +++ b/Source/JavaScriptCore/wasm/WasmLLIntGenerator.cpp @@ -723,6 +723,8 @@ auto LLIntGenerator::callInformationForCaller(const FunctionSignature& signature case TypeKind::Eqref: case TypeKind::Anyref: case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: case TypeKind::I31ref: case TypeKind::Rec: case TypeKind::Sub: @@ -763,6 +765,8 @@ auto LLIntGenerator::callInformationForCaller(const FunctionSignature& signature case TypeKind::Eqref: case TypeKind::Anyref: case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: case TypeKind::I31ref: case TypeKind::Rec: case TypeKind::Sub: @@ -833,6 +837,8 @@ auto LLIntGenerator::callInformationForCallee(const FunctionSignature& signature case TypeKind::Eqref: case TypeKind::Anyref: case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: case TypeKind::I31ref: case TypeKind::Rec: case TypeKind::Sub: @@ -899,6 +905,8 @@ auto LLIntGenerator::addArguments(const TypeDefinition& signature) -> PartialRes case TypeKind::Eqref: case TypeKind::Anyref: case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: case TypeKind::I31ref: case TypeKind::Rec: case TypeKind::Sub: diff --git a/Source/JavaScriptCore/wasm/WasmTypeDefinition.cpp b/Source/JavaScriptCore/wasm/WasmTypeDefinition.cpp index ca566635c8c7..f0f79a3da734 100644 --- a/Source/JavaScriptCore/wasm/WasmTypeDefinition.cpp +++ b/Source/JavaScriptCore/wasm/WasmTypeDefinition.cpp @@ -1031,6 +1031,8 @@ bool TypeInformation::castReference(JSValue refValue, bool allowNull, TypeIndex case TypeKind::Eqref: return (refValue.isInt32() && refValue.asInt32() <= maxI31ref && refValue.asInt32() >= minI31ref) || jsDynamicCast(refValue) || jsDynamicCast(refValue); case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: return false; case TypeKind::I31ref: return refValue.isInt32() && refValue.asInt32() <= maxI31ref && refValue.asInt32() >= minI31ref; diff --git a/Source/JavaScriptCore/wasm/WasmTypeDefinition.h b/Source/JavaScriptCore/wasm/WasmTypeDefinition.h index b3ca04a2820f..d460a0a440ba 100644 --- a/Source/JavaScriptCore/wasm/WasmTypeDefinition.h +++ b/Source/JavaScriptCore/wasm/WasmTypeDefinition.h @@ -303,6 +303,8 @@ constexpr size_t typeKindSizeInBytes(TypeKind kind) case TypeKind::Eqref: case TypeKind::Anyref: case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: case TypeKind::I31ref: { break; } diff --git a/Source/JavaScriptCore/wasm/js/JSWebAssemblyStruct.cpp b/Source/JavaScriptCore/wasm/js/JSWebAssemblyStruct.cpp index b0508069b07f..323d5a3746d1 100644 --- a/Source/JavaScriptCore/wasm/js/JSWebAssemblyStruct.cpp +++ b/Source/JavaScriptCore/wasm/js/JSWebAssemblyStruct.cpp @@ -151,6 +151,8 @@ void JSWebAssemblyStruct::set(JSGlobalObject* globalObject, uint32_t fieldIndex, case TypeKind::Eqref: case TypeKind::Anyref: case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: case TypeKind::I31ref: { break; } diff --git a/Source/JavaScriptCore/wasm/js/WasmToJS.cpp b/Source/JavaScriptCore/wasm/js/WasmToJS.cpp index 923632566e4f..6b27655fe5b9 100644 --- a/Source/JavaScriptCore/wasm/js/WasmToJS.cpp +++ b/Source/JavaScriptCore/wasm/js/WasmToJS.cpp @@ -156,6 +156,8 @@ Expected, BindingFailure> wasmToJS(VM& vm case TypeKind::Eqref: case TypeKind::Anyref: case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: case TypeKind::I31ref: case TypeKind::Rec: case TypeKind::Sub: @@ -247,6 +249,8 @@ Expected, BindingFailure> wasmToJS(VM& vm case TypeKind::Eqref: case TypeKind::Anyref: case TypeKind::Nullref: + case TypeKind::Nullfuncref: + case TypeKind::Nullexternref: case TypeKind::I31ref: case TypeKind::Rec: case TypeKind::Sub: diff --git a/Source/JavaScriptCore/wasm/wasm.json b/Source/JavaScriptCore/wasm/wasm.json index 0549053c5000..5df6a78e526d 100644 --- a/Source/JavaScriptCore/wasm/wasm.json +++ b/Source/JavaScriptCore/wasm/wasm.json @@ -7,27 +7,29 @@ { "name": "version", "type": "uint32", "value": 1, "description": "Version number" } ], "type" : { - "i32": { "type": "varint7", "value": -1, "b3type": "B3::Int32", "width": 32 }, - "i64": { "type": "varint7", "value": -2, "b3type": "B3::Int64", "width": 64 }, - "f32": { "type": "varint7", "value": -3, "b3type": "B3::Float", "width": 32 }, - "f64": { "type": "varint7", "value": -4, "b3type": "B3::Double", "width": 64 }, - "v128": { "type": "varint7", "value": -5, "b3type": "B3::V128", "width": 128 }, - "funcref": { "type": "varint7", "value": -16, "b3type": "B3::Int64", "width": 64 }, - "externref": { "type": "varint7", "value": -17, "b3type": "B3::Int64", "width": 64 }, - "anyref": { "type": "varint7", "value": -18, "b3type": "B3::Void", "width": 0 }, - "eqref": { "type": "varint7", "value": -19, "b3type": "B3::Void", "width": 0 }, - "ref_null": { "type": "varint7", "value": -20, "b3type": "B3::Int64", "width": 64 }, - "ref": { "type": "varint7", "value": -21, "b3type": "B3::Int64", "width": 64 }, - "i31ref": { "type": "varint7", "value": -22, "b3type": "B3::Void", "width": 0 }, - "structref": { "type": "varint7", "value": -25, "b3type": "B3::Int64", "width": 0 }, - "arrayref": { "type": "varint7", "value": -26, "b3type": "B3::Int64", "width": 0 }, - "nullref": { "type": "varint7", "value": -27, "b3type": "B3::Void", "width": 0 }, - "func": { "type": "varint7", "value": -32, "b3type": "B3::Void", "width": 0 }, - "struct": { "type": "varint7", "value": -33, "b3type": "B3::Void", "width": 0 }, - "array": { "type": "varint7", "value": -34, "b3type": "B3::Void", "width": 0 }, - "sub": { "type": "varint7", "value": -48, "b3type": "B3::Void", "width": 0 }, - "rec": { "type": "varint7", "value": -49, "b3type": "B3::Void", "width": 0 }, - "void": { "type": "varint7", "value": -64, "b3type": "B3::Void", "width": 0 } + "i32": { "type": "varint7", "value": -1, "b3type": "B3::Int32", "width": 32 }, + "i64": { "type": "varint7", "value": -2, "b3type": "B3::Int64", "width": 64 }, + "f32": { "type": "varint7", "value": -3, "b3type": "B3::Float", "width": 32 }, + "f64": { "type": "varint7", "value": -4, "b3type": "B3::Double", "width": 64 }, + "v128": { "type": "varint7", "value": -5, "b3type": "B3::V128", "width": 128 }, + "funcref": { "type": "varint7", "value": -16, "b3type": "B3::Int64", "width": 64 }, + "externref": { "type": "varint7", "value": -17, "b3type": "B3::Int64", "width": 64 }, + "anyref": { "type": "varint7", "value": -18, "b3type": "B3::Void", "width": 0 }, + "eqref": { "type": "varint7", "value": -19, "b3type": "B3::Void", "width": 0 }, + "ref_null": { "type": "varint7", "value": -20, "b3type": "B3::Int64", "width": 64 }, + "ref": { "type": "varint7", "value": -21, "b3type": "B3::Int64", "width": 64 }, + "i31ref": { "type": "varint7", "value": -22, "b3type": "B3::Void", "width": 0 }, + "nullfuncref": { "type": "varint7", "value": -23, "b3type": "B3::Void", "width": 0 }, + "nullexternref": { "type": "varint7", "value": -24, "b3type": "B3::Void", "width": 0 }, + "structref": { "type": "varint7", "value": -25, "b3type": "B3::Int64", "width": 0 }, + "arrayref": { "type": "varint7", "value": -26, "b3type": "B3::Int64", "width": 0 }, + "nullref": { "type": "varint7", "value": -27, "b3type": "B3::Void", "width": 0 }, + "func": { "type": "varint7", "value": -32, "b3type": "B3::Void", "width": 0 }, + "struct": { "type": "varint7", "value": -33, "b3type": "B3::Void", "width": 0 }, + "array": { "type": "varint7", "value": -34, "b3type": "B3::Void", "width": 0 }, + "sub": { "type": "varint7", "value": -48, "b3type": "B3::Void", "width": 0 }, + "rec": { "type": "varint7", "value": -49, "b3type": "B3::Void", "width": 0 }, + "void": { "type": "varint7", "value": -64, "b3type": "B3::Void", "width": 0 } }, "packed_type": { "i8": { "type": "varint7", "value": -6},