diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/asmjs/asm_v_wasm.cpp | 6 | ||||
-rw-r--r-- | src/binaryen-c.cpp | 10 | ||||
-rw-r--r-- | src/binaryen-c.h | 2 | ||||
-rw-r--r-- | src/ir/abstract.h | 4 | ||||
-rw-r--r-- | src/js/binaryen.js-post.js | 14 | ||||
-rw-r--r-- | src/literal.h | 2 | ||||
-rw-r--r-- | src/parsing.h | 2 | ||||
-rw-r--r-- | src/passes/ConstHoisting.cpp | 4 | ||||
-rw-r--r-- | src/passes/FuncCastEmulation.cpp | 8 | ||||
-rw-r--r-- | src/passes/InstrumentLocals.cpp | 24 | ||||
-rw-r--r-- | src/shell-interface.h | 3 | ||||
-rw-r--r-- | src/tools/fuzzing.h | 37 | ||||
-rw-r--r-- | src/tools/spec-wrapper.h | 5 | ||||
-rw-r--r-- | src/tools/wasm-reduce.cpp | 10 | ||||
-rw-r--r-- | src/wasm-binary.h | 18 | ||||
-rw-r--r-- | src/wasm-builder.h | 8 | ||||
-rw-r--r-- | src/wasm-interpreter.h | 4 | ||||
-rw-r--r-- | src/wasm-type.h | 4 | ||||
-rw-r--r-- | src/wasm/literal.cpp | 42 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 12 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 6 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 6 | ||||
-rw-r--r-- | src/wasm/wasm-type.cpp | 32 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 4 |
24 files changed, 242 insertions, 25 deletions
diff --git a/src/asmjs/asm_v_wasm.cpp b/src/asmjs/asm_v_wasm.cpp index 8d2894f13..e7b4d6edd 100644 --- a/src/asmjs/asm_v_wasm.cpp +++ b/src/asmjs/asm_v_wasm.cpp @@ -58,6 +58,8 @@ AsmType wasmToAsmType(Type type) { case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: assert(false && "reference types are not supported by asm2wasm"); case Type::none: return ASM_NONE; @@ -88,6 +90,10 @@ char getSig(Type type) { return 'E'; case Type::anyref: return 'A'; + case Type::eqref: + return 'Q'; + case Type::i31ref: + return 'I'; case Type::none: return 'v'; case Type::unreachable: diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 1c938faab..2f1d3f5ff 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -74,8 +74,11 @@ BinaryenLiteral toBinaryenLiteral(Literal x) { case Type::externref: case Type::exnref: case Type::anyref: - assert(x.isNull()); + case Type::eqref: + assert(x.isNull() && "unexpected non-null reference type literal"); break; + case Type::i31ref: + WASM_UNREACHABLE("TODO: i31ref"); case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -100,7 +103,10 @@ Literal fromBinaryenLiteral(BinaryenLiteral x) { case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: return Literal::makeNull(Type(x.type)); + case Type::i31ref: + WASM_UNREACHABLE("TODO: i31ref"); case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -136,6 +142,8 @@ BinaryenType BinaryenTypeFuncref(void) { return Type::funcref; } BinaryenType BinaryenTypeExternref(void) { return Type::externref; } BinaryenType BinaryenTypeExnref(void) { return Type::exnref; } BinaryenType BinaryenTypeAnyref(void) { return Type::anyref; } +BinaryenType BinaryenTypeEqref(void) { return Type::eqref; } +BinaryenType BinaryenTypeI31ref(void) { return Type::i31ref; } BinaryenType BinaryenTypeUnreachable(void) { return Type::unreachable; } BinaryenType BinaryenTypeAuto(void) { return uintptr_t(-1); } diff --git a/src/binaryen-c.h b/src/binaryen-c.h index f368ad122..3a3be4608 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -102,6 +102,8 @@ BINARYEN_API BinaryenType BinaryenTypeFuncref(void); BINARYEN_API BinaryenType BinaryenTypeExternref(void); BINARYEN_API BinaryenType BinaryenTypeExnref(void); BINARYEN_API BinaryenType BinaryenTypeAnyref(void); +BINARYEN_API BinaryenType BinaryenTypeEqref(void); +BINARYEN_API BinaryenType BinaryenTypeI31ref(void); BINARYEN_API BinaryenType BinaryenTypeUnreachable(void); // Not a real type. Used as the last parameter to BinaryenBlock to let // the API figure out the type instead of providing one. diff --git a/src/ir/abstract.h b/src/ir/abstract.h index ce5b6b008..ac67a59b3 100644 --- a/src/ir/abstract.h +++ b/src/ir/abstract.h @@ -103,6 +103,8 @@ inline UnaryOp getUnary(Type type, Op op) { case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: case Type::unreachable: { return InvalidUnary; @@ -266,6 +268,8 @@ inline BinaryOp getBinary(Type type, Op op) { case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: case Type::unreachable: { return InvalidBinary; diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index 87a6bacda..4703abc54 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -37,6 +37,8 @@ function initializeConstants() { ['externref', 'Externref'], ['exnref', 'Exnref'], ['anyref', 'Anyref'], + ['eqref', 'Eqref'], + ['i31ref', 'I31ref'], ['unreachable', 'Unreachable'], ['auto', 'Auto'] ].forEach(entry => { @@ -2070,6 +2072,18 @@ function wrapModule(module, self = {}) { } }; + self['eqref'] = { + 'pop'() { + return Module['_BinaryenPop'](module, Module['eqref']); + } + }; + + self['i31ref'] = { + 'pop'() { + return Module['_BinaryenPop'](module, Module['i31ref']); + } + }; + self['ref'] = { 'null'(type) { return Module['_BinaryenRefNull'](module, type); diff --git a/src/literal.h b/src/literal.h index c617f56f0..698063cbe 100644 --- a/src/literal.h +++ b/src/literal.h @@ -595,6 +595,8 @@ template<> struct less<wasm::Literal> { case wasm::Type::externref: case wasm::Type::exnref: case wasm::Type::anyref: + case wasm::Type::eqref: + case wasm::Type::i31ref: case wasm::Type::none: case wasm::Type::unreachable: return false; diff --git a/src/parsing.h b/src/parsing.h index d809cbedd..bdc3e63b7 100644 --- a/src/parsing.h +++ b/src/parsing.h @@ -267,6 +267,8 @@ parseConst(cashew::IString s, Type type, MixedArena& allocator) { case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: WASM_UNREACHABLE("unexpected const type"); case Type::none: case Type::unreachable: { diff --git a/src/passes/ConstHoisting.cpp b/src/passes/ConstHoisting.cpp index 3b34751ff..a972c05fb 100644 --- a/src/passes/ConstHoisting.cpp +++ b/src/passes/ConstHoisting.cpp @@ -97,7 +97,9 @@ private: case Type::funcref: case Type::externref: case Type::exnref: - case Type::anyref: { + case Type::anyref: + case Type::eqref: + case Type::i31ref: { return false; } case Type::none: diff --git a/src/passes/FuncCastEmulation.cpp b/src/passes/FuncCastEmulation.cpp index 101834790..6f5e9d611 100644 --- a/src/passes/FuncCastEmulation.cpp +++ b/src/passes/FuncCastEmulation.cpp @@ -68,7 +68,9 @@ static Expression* toABI(Expression* value, Module* module) { case Type::funcref: case Type::externref: case Type::exnref: - case Type::anyref: { + case Type::anyref: + case Type::eqref: + case Type::i31ref: { WASM_UNREACHABLE("reference types cannot be converted to i64"); } case Type::none: { @@ -112,7 +114,9 @@ static Expression* fromABI(Expression* value, Type type, Module* module) { case Type::funcref: case Type::externref: case Type::exnref: - case Type::anyref: { + case Type::anyref: + case Type::eqref: + case Type::i31ref: { WASM_UNREACHABLE("reference types cannot be converted from i64"); } case Type::none: { diff --git a/src/passes/InstrumentLocals.cpp b/src/passes/InstrumentLocals.cpp index f9c26d788..8803a7811 100644 --- a/src/passes/InstrumentLocals.cpp +++ b/src/passes/InstrumentLocals.cpp @@ -60,6 +60,8 @@ Name get_funcref("get_funcref"); Name get_externref("get_externref"); Name get_exnref("get_exnref"); Name get_anyref("get_anyref"); +Name get_eqref("get_eqref"); +Name get_i31ref("get_i31ref"); Name get_v128("get_v128"); Name set_i32("set_i32"); @@ -70,6 +72,8 @@ Name set_funcref("set_funcref"); Name set_externref("set_externref"); Name set_exnref("set_exnref"); Name set_anyref("set_anyref"); +Name set_eqref("set_eqref"); +Name set_i31ref("set_i31ref"); Name set_v128("set_v128"); struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> { @@ -104,6 +108,12 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> { case Type::anyref: import = get_anyref; break; + case Type::eqref: + import = get_eqref; + break; + case Type::i31ref: + import = get_i31ref; + break; case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -153,6 +163,12 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> { case Type::anyref: import = set_anyref; break; + case Type::eqref: + import = set_eqref; + break; + case Type::i31ref: + import = set_i31ref; + break; case Type::unreachable: return; // nothing to do here case Type::none: @@ -203,6 +219,14 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> { curr, get_anyref, {Type::i32, Type::i32, Type::anyref}, Type::anyref); addImport( curr, set_anyref, {Type::i32, Type::i32, Type::anyref}, Type::anyref); + addImport( + curr, get_eqref, {Type::i32, Type::i32, Type::eqref}, Type::eqref); + addImport( + curr, set_eqref, {Type::i32, Type::i32, Type::eqref}, Type::eqref); + addImport( + curr, get_i31ref, {Type::i32, Type::i32, Type::i31ref}, Type::i31ref); + addImport( + curr, set_i31ref, {Type::i32, Type::i32, Type::i31ref}, Type::i31ref); } } if (curr->features.hasSIMD()) { diff --git a/src/shell-interface.h b/src/shell-interface.h index ae86d13ec..8d35905ee 100644 --- a/src/shell-interface.h +++ b/src/shell-interface.h @@ -119,8 +119,11 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface { case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: globals[import->name] = {Literal::makeNull(import->type)}; break; + case Type::i31ref: + WASM_UNREACHABLE("TODO: i31ref"); case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h index e6cc4e444..0783588cd 100644 --- a/src/tools/fuzzing.h +++ b/src/tools/fuzzing.h @@ -324,6 +324,15 @@ private: if (wasm.features.hasExceptionHandling()) { options.push_back(Type::exnref); } + if (wasm.features.hasGC()) { + options.push_back(Type::eqref); + // TODO: i31ref + } + } + break; + case Type::eqref: + if (wasm.features.hasGC()) { + // TODO: i31ref } break; default: @@ -1362,6 +1371,8 @@ private: case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("invalid type"); @@ -1466,6 +1477,8 @@ private: case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("invalid type"); @@ -1595,6 +1608,8 @@ private: case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("invalid type"); @@ -1640,6 +1655,8 @@ private: case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -1708,6 +1725,8 @@ private: case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -1735,6 +1754,8 @@ private: case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -1845,6 +1866,8 @@ private: case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: return makeTrivial(type); case Type::none: case Type::unreachable: @@ -1990,6 +2013,8 @@ private: case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -2227,6 +2252,8 @@ private: case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -2434,6 +2461,8 @@ private: case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -2674,7 +2703,9 @@ private: .add(FeatureSet::ReferenceTypes, Type::funcref, Type::externref) .add(FeatureSet::ReferenceTypes | FeatureSet::ExceptionHandling, Type::exnref) - .add(FeatureSet::ReferenceTypes | FeatureSet::GC, Type::anyref)); + .add(FeatureSet::ReferenceTypes | FeatureSet::GC, + Type::anyref, + Type::eqref)); // TODO: i31ref } Type getSingleConcreteType() { return pick(getSingleConcreteTypes()); } @@ -2685,7 +2716,9 @@ private: .add(FeatureSet::ReferenceTypes, Type::funcref, Type::externref) .add(FeatureSet::ReferenceTypes | FeatureSet::ExceptionHandling, Type::exnref) - .add(FeatureSet::ReferenceTypes | FeatureSet::GC, Type::anyref)); + .add(FeatureSet::ReferenceTypes | FeatureSet::GC, + Type::anyref, + Type::eqref)); // TODO: i31ref } Type getReferenceType() { return pick(getReferenceTypes()); } diff --git a/src/tools/spec-wrapper.h b/src/tools/spec-wrapper.h index 200571fd0..5a61d72b6 100644 --- a/src/tools/spec-wrapper.h +++ b/src/tools/spec-wrapper.h @@ -61,6 +61,11 @@ static std::string generateSpecWrapper(Module& wasm) { case Type::anyref: ret += "(ref.null any)"; break; + case Type::eqref: + ret += "(ref.null eq)"; + break; + case Type::i31ref: + WASM_UNREACHABLE("TODO: i31ref"); case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); diff --git a/src/tools/wasm-reduce.cpp b/src/tools/wasm-reduce.cpp index 7410ff91e..7a81007dc 100644 --- a/src/tools/wasm-reduce.cpp +++ b/src/tools/wasm-reduce.cpp @@ -599,6 +599,8 @@ struct Reducer case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: continue; // not implemented yet case Type::none: case Type::unreachable: @@ -625,6 +627,8 @@ struct Reducer case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: continue; // not implemented yet case Type::none: case Type::unreachable: @@ -651,6 +655,8 @@ struct Reducer case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: continue; // not implemented yet case Type::none: case Type::unreachable: @@ -677,6 +683,8 @@ struct Reducer case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: continue; // not implemented yet case Type::none: case Type::unreachable: @@ -689,6 +697,8 @@ struct Reducer case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: continue; // not implemented yet case Type::none: case Type::unreachable: diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 7666fa842..39980ee04 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -346,6 +346,10 @@ enum EncodedType { externref = -0x11, // 0x6f // any reference type anyref = -0x12, // 0x6e + // comparable reference type + eqref = -0x13, // 0x6d + // integer reference type + i31ref = -0x16, // 0x6a // exception reference type exnref = -0x18, // 0x68 // func_type form @@ -358,6 +362,8 @@ enum EncodedHeapType { func = -0x10, // 0x70 extern_ = -0x11, // 0x6f any = -0x12, // 0x6e + eq = -0x13, // 0x6d + i31 = -0x17, // 0x69, != i31ref exn = -0x18, // 0x68 }; @@ -981,6 +987,12 @@ inline S32LEB binaryType(Type type) { case Type::anyref: ret = BinaryConsts::EncodedType::anyref; break; + case Type::eqref: + ret = BinaryConsts::EncodedType::eqref; + break; + case Type::i31ref: + ret = BinaryConsts::EncodedType::i31ref; + break; case Type::unreachable: WASM_UNREACHABLE("unexpected type"); } @@ -1003,11 +1015,15 @@ inline S32LEB binaryHeapType(HeapType type) { ret = BinaryConsts::EncodedHeapType::any; break; case HeapType::EqKind: + ret = BinaryConsts::EncodedHeapType::eq; + break; case HeapType::I31Kind: + ret = BinaryConsts::EncodedHeapType::i31; + break; case HeapType::SignatureKind: case HeapType::StructKind: case HeapType::ArrayKind: - WASM_UNREACHABLE("TODO: GC types"); + WASM_UNREACHABLE("TODO: compound GC types"); } return S32LEB(ret); // TODO: Actually encoded as s33 } diff --git a/src/wasm-builder.h b/src/wasm-builder.h index b35fde376..737dad16a 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -645,8 +645,11 @@ public: case Type::externref: case Type::exnref: // TODO: ExceptionPackage? case Type::anyref: - assert(value.isNull()); + case Type::eqref: + assert(value.isNull() && "unexpected non-null reference type literal"); return makeRefNull(value.type); + case Type::i31ref: + WASM_UNREACHABLE("TODO: i31ref"); default: assert(value.type.isNumber()); return makeConst(value); @@ -840,7 +843,10 @@ public: case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: return ExpressionManipulator::refNull(curr, curr->type); + case Type::i31ref: + WASM_UNREACHABLE("TODO: i31ref"); case Type::none: return ExpressionManipulator::nop(curr); case Type::unreachable: diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 51cc24d01..69d6ff771 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -1653,6 +1653,8 @@ public: case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -1710,6 +1712,8 @@ public: case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); diff --git a/src/wasm-type.h b/src/wasm-type.h index f3973068f..4a55d7b33 100644 --- a/src/wasm-type.h +++ b/src/wasm-type.h @@ -51,7 +51,9 @@ public: externref, exnref, anyref, - _last_basic_id = anyref + eqref, + i31ref, + _last_basic_id = i31ref, }; Type() = default; diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp index 39a4cea3c..4a89b5cd1 100644 --- a/src/wasm/literal.cpp +++ b/src/wasm/literal.cpp @@ -70,7 +70,10 @@ Literal::Literal(const Literal& other) : type(other.type) { break; case Type::externref: case Type::anyref: + case Type::eqref: break; // null + case Type::i31ref: + WASM_UNREACHABLE("TODO: i31ref"); case Type::funcref: case Type::exnref: case Type::unreachable: @@ -223,10 +226,11 @@ void Literal::getBits(uint8_t (&buf)[16]) const { case Type::externref: case Type::exnref: case Type::anyref: - if (isNull()) { - break; - } - // falls through + case Type::eqref: + assert(isNull() && "unexpected non-null reference type literal"); + break; + case Type::i31ref: + WASM_UNREACHABLE("TODO: i31ref"); case Type::none: case Type::unreachable: WASM_UNREACHABLE("invalid type"); @@ -379,6 +383,10 @@ std::ostream& operator<<(std::ostream& o, Literal literal) { o << "funcref(" << literal.getFunc() << ")"; } break; + case Type::externref: + assert(literal.isNull() && "unexpected non-null externref literal"); + o << "externref(null)"; + break; case Type::exnref: if (literal.isNull()) { o << "exnref(null)"; @@ -387,13 +395,15 @@ std::ostream& operator<<(std::ostream& o, Literal literal) { } break; case Type::anyref: - assert(literal.isNull() && "TODO: non-null anyref values"); + assert(literal.isNull() && "unexpected non-null anyref literal"); o << "anyref(null)"; break; - case Type::externref: - assert(literal.isNull() && "TODO: non-null externref values"); - o << "externref(null)"; + case Type::eqref: + assert(literal.isNull() && "unexpected non-null eqref literal"); + o << "eqref(null)"; break; + case Type::i31ref: + WASM_UNREACHABLE("TODO: i31ref"); case Type::unreachable: WASM_UNREACHABLE("invalid type"); } @@ -619,6 +629,8 @@ Literal Literal::eqz() const { case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -641,6 +653,8 @@ Literal Literal::neg() const { case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -663,6 +677,8 @@ Literal Literal::abs() const { case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -768,6 +784,8 @@ Literal Literal::add(const Literal& other) const { case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -790,6 +808,8 @@ Literal Literal::sub(const Literal& other) const { case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -908,6 +928,8 @@ Literal Literal::mul(const Literal& other) const { case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -1154,6 +1176,8 @@ Literal Literal::eq(const Literal& other) const { case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -1176,6 +1200,8 @@ Literal Literal::ne(const Literal& other) const { case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 18a66fb2c..a6299c892 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -1206,10 +1206,14 @@ Type WasmBinaryBuilder::getType() { return Type::exnref; case BinaryConsts::EncodedType::anyref: return Type::anyref; + case BinaryConsts::EncodedType::eqref: + return Type::eqref; + case BinaryConsts::EncodedType::i31ref: + return Type::i31ref; default: throwError("invalid wasm type: " + std::to_string(type)); } - WASM_UNREACHABLE("unexpeced type"); + WASM_UNREACHABLE("unexpected type"); } HeapType WasmBinaryBuilder::getHeapType() { @@ -1230,10 +1234,14 @@ HeapType WasmBinaryBuilder::getHeapType() { return HeapType::ExnKind; case BinaryConsts::EncodedHeapType::any: return HeapType::AnyKind; + case BinaryConsts::EncodedHeapType::eq: + return HeapType::EqKind; + case BinaryConsts::EncodedHeapType::i31: + return HeapType::I31Kind; default: throwError("invalid wasm heap type: " + std::to_string(type)); } - WASM_UNREACHABLE("unexpeced type"); + WASM_UNREACHABLE("unexpected type"); } Type WasmBinaryBuilder::getConcreteType() { diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 8bbcc9ac0..2aa60979f 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -875,6 +875,12 @@ Type SExpressionWasmBuilder::stringToType(const char* str, if (strncmp(str, "anyref", 6) == 0 && (prefix || str[6] == 0)) { return Type::anyref; } + if (strncmp(str, "eqref", 5) == 0 && (prefix || str[5] == 0)) { + return Type::eqref; + } + if (strncmp(str, "i31ref", 6) == 0 && (prefix || str[6] == 0)) { + return Type::i31ref; + } if (allowError) { return Type::none; } diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 30816546a..66f9e02dd 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -192,6 +192,8 @@ void BinaryInstWriter::visitLoad(Load* curr) { case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: WASM_UNREACHABLE("unexpected type"); } @@ -294,6 +296,8 @@ void BinaryInstWriter::visitStore(Store* curr) { case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -697,6 +701,8 @@ void BinaryInstWriter::visitConst(Const* curr) { case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index d88b7b027..cf68d92e9 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -260,9 +260,10 @@ std::unordered_map<TypeInfo, uintptr_t> indices = { {TypeInfo(HeapType(HeapType::ExnKind), true), Type::exnref}, {TypeInfo({Type::anyref}), Type::anyref}, {TypeInfo(HeapType(HeapType::AnyKind), true), Type::anyref}, - // TODO (GC): Add canonical ids - // * `(ref null eq) == eqref` - // * `(ref i31) == i31ref` + {TypeInfo({Type::eqref}), Type::eqref}, + {TypeInfo(HeapType(HeapType::EqKind), true), Type::eqref}, + {TypeInfo({Type::i31ref}), Type::i31ref}, + {TypeInfo(HeapType(HeapType::I31Kind), false), Type::i31ref}, }; } // anonymous namespace @@ -341,7 +342,7 @@ bool Type::isTuple() const { bool Type::isRef() const { if (isBasic()) { - return id >= funcref && id <= anyref; + return id >= funcref && id <= i31ref; } else { return getTypeInfo(*this)->isRef(); } @@ -367,7 +368,7 @@ bool Type::isException() const { bool Type::isNullable() const { if (isBasic()) { - return id >= funcref && id <= anyref; + return id >= funcref && id <= eqref; // except i31ref } else { return getTypeInfo(*this)->isNullable(); } @@ -409,6 +410,8 @@ unsigned Type::getByteSize() const { case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: case Type::unreachable: break; @@ -454,6 +457,8 @@ FeatureSet Type::getFeatures() const { case Type::exnref: return FeatureSet::ReferenceTypes | FeatureSet::ExceptionHandling; case Type::anyref: + case Type::eqref: + case Type::i31ref: return FeatureSet::ReferenceTypes | FeatureSet::GC; default: return FeatureSet::MVP; @@ -484,6 +489,10 @@ HeapType Type::getHeapType() const { return HeapType::ExnKind; case anyref: return HeapType::AnyKind; + case eqref: + return HeapType::EqKind; + case i31ref: + return HeapType::I31Kind; default: break; } @@ -512,7 +521,8 @@ bool Type::isSubType(Type left, Type right) { return true; } if (left.isRef() && right.isRef()) { - return right == Type::anyref; + return right == Type::anyref || + (left == Type::i31ref && right == Type::eqref); } if (left.isTuple() && right.isTuple()) { if (left.size() != right.size()) { @@ -543,6 +553,10 @@ Type Type::getLeastUpperBound(Type a, Type b) { } if (a.isRef()) { if (b.isRef()) { + if ((a == Type::i31ref && b == Type::eqref) || + (a == Type::eqref && b == Type::i31ref)) { + return Type::eqref; + } // The LUB of two different reference types is anyref, which may or may // not be a valid type depending on whether the anyref feature is enabled. // When anyref is disabled, it is possible for the finalization of invalid @@ -754,6 +768,12 @@ std::ostream& operator<<(std::ostream& os, Type type) { case Type::anyref: os << "anyref"; break; + case Type::eqref: + os << "eqref"; + break; + case Type::i31ref: + os << "i31ref"; + break; } } else { os << *getTypeInfo(type); diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 505753c88..16ba60d72 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -1396,6 +1396,8 @@ void FunctionValidator::validateMemBytes(uint8_t bytes, case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: WASM_UNREACHABLE("unexpected type"); } @@ -2204,6 +2206,8 @@ void FunctionValidator::validateAlignment( case Type::externref: case Type::exnref: case Type::anyref: + case Type::eqref: + case Type::i31ref: case Type::none: WASM_UNREACHABLE("invalid type"); } |