diff options
author | Daniel Wirtz <dcode@dcode.io> | 2020-09-09 03:40:09 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-09-09 03:40:09 +0200 |
commit | 916ce6f1a9f7c85102a8c69f593b301c8df5d19d (patch) | |
tree | 93b22be9f2c0718248528d140b05221cb6878600 | |
parent | 0fdcf5b51a0c8c379b2d3ad8262aa22bb234f0e9 (diff) | |
download | binaryen-916ce6f1a9f7c85102a8c69f593b301c8df5d19d.tar.gz binaryen-916ce6f1a9f7c85102a8c69f593b301c8df5d19d.tar.bz2 binaryen-916ce6f1a9f7c85102a8c69f593b301c8df5d19d.zip |
Update reference types (#3084)
Align with the current state of the reference types proposal:
* Remove `nullref`
* Remove `externref` and `funcref` subtyping
* A `Literal` of a nullable reference type can now represent `null` (previously was type `nullref`)
* Update the tests and temporarily comment out those tests relying on subtyping
87 files changed, 2060 insertions, 1864 deletions
diff --git a/scripts/gen-s-parser.py b/scripts/gen-s-parser.py index 2d22c2cbd..f105e6407 100755 --- a/scripts/gen-s-parser.py +++ b/scripts/gen-s-parser.py @@ -50,7 +50,6 @@ instructions = [ ("v128.pop", "makePop(Type::v128)"), ("funcref.pop", "makePop(Type::funcref)"), ("externref.pop", "makePop(Type::externref)"), - ("nullref.pop", "makePop(Type::nullref)"), ("exnref.pop", "makePop(Type::exnref)"), ("i32.load", "makeLoad(s, Type::i32, /*isAtomic=*/false)"), ("i64.load", "makeLoad(s, Type::i64, /*isAtomic=*/false)"), diff --git a/src/asmjs/asm_v_wasm.cpp b/src/asmjs/asm_v_wasm.cpp index 4a79d9caf..ddcb27d3d 100644 --- a/src/asmjs/asm_v_wasm.cpp +++ b/src/asmjs/asm_v_wasm.cpp @@ -56,7 +56,6 @@ AsmType wasmToAsmType(Type type) { assert(false && "v128 not implemented yet"); case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: assert(false && "reference types are not supported by asm2wasm"); case Type::none: @@ -84,8 +83,6 @@ char getSig(Type type) { return 'F'; case Type::externref: return 'X'; - case Type::nullref: - return 'N'; case Type::exnref: return 'E'; case Type::none: diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 4c5063114..a3aa0cd94 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -69,12 +69,12 @@ BinaryenLiteral toBinaryenLiteral(Literal x) { memcpy(&ret.v128, x.getv128Ptr(), 16); break; case Type::funcref: - ret.func = x.getFunc().c_str(); - break; - case Type::nullref: + ret.func = x.isNull() ? nullptr : x.getFunc().c_str(); break; case Type::externref: case Type::exnref: + assert(x.isNull()); + break; case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -95,11 +95,10 @@ Literal fromBinaryenLiteral(BinaryenLiteral x) { case Type::v128: return Literal(x.v128); case Type::funcref: - return Literal::makeFuncref(x.func); - case Type::nullref: - return Literal::makeNullref(); + return Literal::makeFunc(x.func); case Type::externref: case Type::exnref: + return Literal::makeNull(Type(x.type)); case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -133,7 +132,6 @@ BinaryenType BinaryenTypeFloat64(void) { return Type::f64; } BinaryenType BinaryenTypeVec128(void) { return Type::v128; } BinaryenType BinaryenTypeFuncref(void) { return Type::funcref; } BinaryenType BinaryenTypeExternref(void) { return Type::externref; } -BinaryenType BinaryenTypeNullref(void) { return Type::nullref; } BinaryenType BinaryenTypeExnref(void) { return Type::exnref; } BinaryenType BinaryenTypeUnreachable(void) { return Type::unreachable; } BinaryenType BinaryenTypeAuto(void) { return uintptr_t(-1); } @@ -1264,8 +1262,11 @@ BinaryenExpressionRef BinaryenPop(BinaryenModuleRef module, BinaryenType type) { Builder(*(Module*)module).makePop(Type(type))); } -BinaryenExpressionRef BinaryenRefNull(BinaryenModuleRef module) { - return static_cast<Expression*>(Builder(*(Module*)module).makeRefNull()); +BinaryenExpressionRef BinaryenRefNull(BinaryenModuleRef module, + BinaryenType type) { + Type type_(type); + assert(type_.isNullable()); + return static_cast<Expression*>(Builder(*(Module*)module).makeRefNull(type_)); } BinaryenExpressionRef BinaryenRefIsNull(BinaryenModuleRef module, diff --git a/src/binaryen-c.h b/src/binaryen-c.h index 893d44e3c..beaf72499 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -100,7 +100,6 @@ BINARYEN_API BinaryenType BinaryenTypeFloat64(void); BINARYEN_API BinaryenType BinaryenTypeVec128(void); BINARYEN_API BinaryenType BinaryenTypeFuncref(void); BINARYEN_API BinaryenType BinaryenTypeExternref(void); -BINARYEN_API BinaryenType BinaryenTypeNullref(void); BINARYEN_API BinaryenType BinaryenTypeExnref(void); BINARYEN_API BinaryenType BinaryenTypeUnreachable(void); // Not a real type. Used as the last parameter to BinaryenBlock to let @@ -826,7 +825,8 @@ BinaryenMemoryFill(BinaryenModuleRef module, BinaryenExpressionRef dest, BinaryenExpressionRef value, BinaryenExpressionRef size); -BINARYEN_API BinaryenExpressionRef BinaryenRefNull(BinaryenModuleRef module); +BINARYEN_API BinaryenExpressionRef BinaryenRefNull(BinaryenModuleRef module, + BinaryenType type); BINARYEN_API BinaryenExpressionRef BinaryenRefIsNull(BinaryenModuleRef module, BinaryenExpressionRef value); BINARYEN_API BinaryenExpressionRef BinaryenRefFunc(BinaryenModuleRef module, diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc index 5e6beb4ac..97ba15c32 100644 --- a/src/gen-s-parser.inc +++ b/src/gen-s-parser.inc @@ -2560,17 +2560,9 @@ switch (op[0]) { default: goto parse_error; } } - case 'n': { - switch (op[1]) { - case 'o': - if (strcmp(op, "nop") == 0) { return makeNop(); } - goto parse_error; - case 'u': - if (strcmp(op, "nullref.pop") == 0) { return makePop(Type::nullref); } - goto parse_error; - default: goto parse_error; - } - } + case 'n': + if (strcmp(op, "nop") == 0) { return makeNop(); } + goto parse_error; case 'r': { switch (op[2]) { case 'f': { diff --git a/src/ir/ExpressionManipulator.cpp b/src/ir/ExpressionManipulator.cpp index 57048b9bd..6f64ec77b 100644 --- a/src/ir/ExpressionManipulator.cpp +++ b/src/ir/ExpressionManipulator.cpp @@ -227,7 +227,9 @@ flexibleCopy(Expression* original, Module& wasm, CustomCopier custom) { builder.makeHost(curr->op, curr->nameOperand, std::move(operands)); return ret; } - Expression* visitRefNull(RefNull* curr) { return builder.makeRefNull(); } + Expression* visitRefNull(RefNull* curr) { + return builder.makeRefNull(curr->type); + } Expression* visitRefIsNull(RefIsNull* curr) { return builder.makeRefIsNull(copy(curr->value)); } diff --git a/src/ir/abstract.h b/src/ir/abstract.h index f706e9972..b00537bf5 100644 --- a/src/ir/abstract.h +++ b/src/ir/abstract.h @@ -103,7 +103,6 @@ inline UnaryOp getUnary(Type type, Op op) { } case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: case Type::unreachable: { @@ -268,7 +267,6 @@ inline BinaryOp getBinary(Type type, Op op) { } case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: case Type::unreachable: { diff --git a/src/ir/manipulation.h b/src/ir/manipulation.h index 49ed7e11e..fb1f0181e 100644 --- a/src/ir/manipulation.h +++ b/src/ir/manipulation.h @@ -40,9 +40,10 @@ template<typename InputType> inline Nop* nop(InputType* target) { return ret; } -template<typename InputType> inline RefNull* refNull(InputType* target) { +template<typename InputType> +inline RefNull* refNull(InputType* target, Type type) { auto* ret = convert<InputType, RefNull>(target); - ret->finalize(); + ret->finalize(type); return ret; } diff --git a/src/ir/properties.h b/src/ir/properties.h index 0c6824e4a..ac61f787e 100644 --- a/src/ir/properties.h +++ b/src/ir/properties.h @@ -93,10 +93,10 @@ inline bool isConstantExpression(const Expression* curr) { inline Literal getSingleLiteral(const Expression* curr) { if (auto* c = curr->dynCast<Const>()) { return c->value; - } else if (curr->is<RefNull>()) { - return Literal(Type::nullref); - } else if (auto* c = curr->dynCast<RefFunc>()) { - return Literal(c->func); + } else if (auto* n = curr->dynCast<RefNull>()) { + return Literal(n->type); + } else if (auto* r = curr->dynCast<RefFunc>()) { + return Literal(r->func); } else { WASM_UNREACHABLE("non-constant expression"); } diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index 4e673ab4b..66de10848 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -35,7 +35,6 @@ function initializeConstants() { ['v128', 'Vec128'], ['funcref', 'Funcref'], ['externref', 'Externref'], - ['nullref', 'Nullref'], ['exnref', 'Exnref'], ['unreachable', 'Unreachable'], ['auto', 'Auto'] @@ -2058,12 +2057,6 @@ function wrapModule(module, self = {}) { } }; - self['nullref'] = { - 'pop'() { - return Module['_BinaryenPop'](module, Module['nullref']); - } - }; - self['exnref'] = { 'pop'() { return Module['_BinaryenPop'](module, Module['exnref']); @@ -2071,8 +2064,8 @@ function wrapModule(module, self = {}) { }; self['ref'] = { - 'null'() { - return Module['_BinaryenRefNull'](module); + 'null'(type) { + return Module['_BinaryenRefNull'](module, type); }, 'is_null'(value) { return Module['_BinaryenRefIsNull'](module, value); diff --git a/src/literal.h b/src/literal.h index 4cbc16786..1b3949d21 100644 --- a/src/literal.h +++ b/src/literal.h @@ -39,8 +39,14 @@ class Literal { int32_t i32; int64_t i64; uint8_t v128[16]; - Name func; // function name for funcref + // funcref function name. `isNull()` indicates a `null` value. + Name func; + // exnref package. `nullptr` indicates a `null` value. std::unique_ptr<ExceptionPackage> exn; + // TODO: Literals of type `externref` can only be `null` currently but we + // will need to represent extern values eventually, to + // 1) run the spec tests and fuzzer with reference types enabled and + // 2) avoid bailing out when seeing a reference typed value in precompute }; public: @@ -48,10 +54,7 @@ public: const Type type; Literal() : v128(), type(Type::none) {} - explicit Literal(Type type) : v128(), type(type) { - assert(type != Type::unreachable && type != Type::funcref && - type != Type::exnref); - } + explicit Literal(Type type); explicit Literal(Type::BasicID typeId) : Literal(Type(typeId)) {} explicit Literal(int32_t init) : i32(init), type(Type::i32) {} explicit Literal(uint32_t init) : i32(init), type(Type::i32) {} @@ -74,13 +77,25 @@ public: Literal(const Literal& other); Literal& operator=(const Literal& other); ~Literal() { - if (type == Type::exnref) { + if (type.isException()) { exn.~unique_ptr(); } } bool isConcrete() const { return type != Type::none; } bool isNone() const { return type == Type::none; } + bool isNull() const { + if (type.isNullable()) { + if (type.isFunction()) { + return func.isNull(); + } + if (type.isException()) { + return !exn; + } + return true; + } + return false; + } static Literal makeFromInt32(int32_t x, Type type) { switch (type.getBasic()) { @@ -105,9 +120,12 @@ public: static Literals makeZero(Type type); static Literal makeSingleZero(Type type); - static Literal makeNullref() { return Literal(Type(Type::nullref)); } - static Literal makeFuncref(Name func) { return Literal(func.c_str()); } - static Literal makeExnref(std::unique_ptr<ExceptionPackage>&& exn) { + static Literal makeNull(Type type) { + assert(type.isNullable()); + return Literal(type); + } + static Literal makeFunc(Name func) { return Literal(func.c_str()); } + static Literal makeExn(std::unique_ptr<ExceptionPackage>&& exn) { return Literal(std::move(exn)); } @@ -134,7 +152,7 @@ public: } std::array<uint8_t, 16> getv128() const; Name getFunc() const { - assert(type == Type::funcref); + assert(type.isFunction() && !func.isNull()); return func; } ExceptionPackage getExceptionPackage() const; @@ -502,6 +520,12 @@ public: struct ExceptionPackage { Name event; Literals values; + bool operator==(const ExceptionPackage& other) const { + return event == other.event && values == other.values; + } + bool operator!=(const ExceptionPackage& other) const { + return !(*this == other); + } }; std::ostream& operator<<(std::ostream& o, wasm::Literal literal); @@ -554,7 +578,6 @@ template<> struct less<wasm::Literal> { return memcmp(a.getv128Ptr(), b.getv128Ptr(), 16) < 0; case wasm::Type::funcref: case wasm::Type::externref: - case wasm::Type::nullref: case wasm::Type::exnref: case wasm::Type::none: case wasm::Type::unreachable: diff --git a/src/parsing.h b/src/parsing.h index a3eab1af3..663b901fd 100644 --- a/src/parsing.h +++ b/src/parsing.h @@ -265,7 +265,6 @@ parseConst(cashew::IString s, Type type, MixedArena& allocator) { case Type::v128: case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: WASM_UNREACHABLE("unexpected const type"); case Type::none: diff --git a/src/passes/ConstHoisting.cpp b/src/passes/ConstHoisting.cpp index 3cef0773c..e3583d3bb 100644 --- a/src/passes/ConstHoisting.cpp +++ b/src/passes/ConstHoisting.cpp @@ -96,7 +96,6 @@ private: case Type::v128: case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: { return false; } diff --git a/src/passes/Flatten.cpp b/src/passes/Flatten.cpp index 54da8a86e..c7b4acbd9 100644 --- a/src/passes/Flatten.cpp +++ b/src/passes/Flatten.cpp @@ -211,19 +211,19 @@ struct Flatten // the return type of the block this branch is targetting, which may // not be the same with the innermost block's return type. For // example, - // (block $any (result externref) - // (block (result nullref) + // (block $any (result anyref) + // (block (result funcref) // (local.tee $0 // (br_if $any - // (ref.null) + // (ref.null func) // (i32.const 0) // ) // ) // ) // ) // In this case we need two locals to store (ref.null); one with - // externref type that's for the target block ($label0) and one more - // with nullref type in case for flowing out. Here we create the + // funcref type that's for the target block ($label0) and one more + // with anyref type in case for flowing out. Here we create the // second 'flowing out' local in case two block's types are // different. if (type != blockType) { diff --git a/src/passes/FuncCastEmulation.cpp b/src/passes/FuncCastEmulation.cpp index 13fb89988..160895f23 100644 --- a/src/passes/FuncCastEmulation.cpp +++ b/src/passes/FuncCastEmulation.cpp @@ -67,7 +67,6 @@ static Expression* toABI(Expression* value, Module* module) { } case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: { WASM_UNREACHABLE("reference types cannot be converted to i64"); } @@ -111,7 +110,6 @@ static Expression* fromABI(Expression* value, Type type, Module* module) { } case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: { WASM_UNREACHABLE("reference types cannot be converted from i64"); } diff --git a/src/passes/InstrumentLocals.cpp b/src/passes/InstrumentLocals.cpp index f95d169e9..ee288c103 100644 --- a/src/passes/InstrumentLocals.cpp +++ b/src/passes/InstrumentLocals.cpp @@ -58,7 +58,6 @@ Name get_f32("get_f32"); Name get_f64("get_f64"); Name get_funcref("get_funcref"); Name get_externref("get_externref"); -Name get_nullref("get_nullref"); Name get_exnref("get_exnref"); Name get_v128("get_v128"); @@ -68,7 +67,6 @@ Name set_f32("set_f32"); Name set_f64("set_f64"); Name set_funcref("set_funcref"); Name set_externref("set_externref"); -Name set_nullref("set_nullref"); Name set_exnref("set_exnref"); Name set_v128("set_v128"); @@ -98,9 +96,6 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> { case Type::externref: import = get_externref; break; - case Type::nullref: - import = get_nullref; - break; case Type::exnref: import = get_exnref; break; @@ -147,9 +142,6 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> { case Type::externref: import = set_externref; break; - case Type::nullref: - import = set_nullref; - break; case Type::exnref: import = set_exnref; break; @@ -192,14 +184,6 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> { set_externref, {Type::i32, Type::i32, Type::externref}, Type::externref); - addImport(curr, - get_nullref, - {Type::i32, Type::i32, Type::nullref}, - Type::nullref); - addImport(curr, - set_nullref, - {Type::i32, Type::i32, Type::nullref}, - Type::nullref); } if (curr->features.hasExceptionHandling()) { addImport( diff --git a/src/passes/Precompute.cpp b/src/passes/Precompute.cpp index 695b62ab2..0b67a25aa 100644 --- a/src/passes/Precompute.cpp +++ b/src/passes/Precompute.cpp @@ -134,7 +134,7 @@ struct Precompute curr->finalize(); return; } - } else if (singleValue.type == Type::nullref && + } else if (singleValue.isNull() && curr->value->template is<RefNull>()) { return; } else if (singleValue.type == Type::funcref) { diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index f35f0d626..04fcdc0b3 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -1440,7 +1440,10 @@ struct PrintExpressionContents break; } } - void visitRefNull(RefNull* curr) { printMedium(o, "ref.null"); } + void visitRefNull(RefNull* curr) { + printMedium(o, "ref.null "); + o << curr->type.getHeapType(); + } void visitRefIsNull(RefIsNull* curr) { printMedium(o, "ref.is_null"); } void visitRefFunc(RefFunc* curr) { printMedium(o, "ref.func "); diff --git a/src/shell-interface.h b/src/shell-interface.h index a32ae6344..92f562b48 100644 --- a/src/shell-interface.h +++ b/src/shell-interface.h @@ -117,9 +117,8 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface { assert(false && "v128 not implemented yet"); case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: - globals[import->name] = {Literal::makeNullref()}; + globals[import->name] = {Literal::makeNull(import->type)}; break; case Type::none: case Type::unreachable: diff --git a/src/tools/execution-results.h b/src/tools/execution-results.h index 38989aedf..c41b0c208 100644 --- a/src/tools/execution-results.h +++ b/src/tools/execution-results.h @@ -74,7 +74,7 @@ struct ExecutionResults { // while the function contents are still the same for (Literal& val : ret) { if (val.type == Type::funcref) { - val = Literal::makeFuncref(Name("funcref")); + val = Literal::makeFunc(Name("funcref")); } } results[exp->name] = ret; diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h index b3c1212d4..ef7844c60 100644 --- a/src/tools/fuzzing.h +++ b/src/tools/fuzzing.h @@ -315,21 +315,7 @@ private: } SmallVector<Type, 2> options; options.push_back(type); // includes itself - TODO_SINGLE_COMPOUND(type); - switch (type.getBasic()) { - case Type::externref: - if (wasm.features.hasExceptionHandling()) { - options.push_back(Type::exnref); - } - options.push_back(Type::funcref); - // falls through - case Type::funcref: - case Type::exnref: - options.push_back(Type::nullref); - break; - default: - break; - } + // TODO (GC): subtyping return pick(options); } @@ -1362,7 +1348,6 @@ private: } case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: case Type::unreachable: @@ -1466,7 +1451,6 @@ private: } case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: case Type::unreachable: @@ -1595,7 +1579,6 @@ private: case Type::v128: case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: case Type::unreachable: @@ -1640,7 +1623,6 @@ private: case Type::v128: case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: case Type::unreachable: @@ -1708,7 +1690,6 @@ private: case Type::v128: case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: case Type::unreachable: @@ -1735,7 +1716,6 @@ private: case Type::v128: case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: case Type::unreachable: @@ -1763,7 +1743,7 @@ private: } return builder.makeRefFunc(target->name); } - return builder.makeRefNull(); + return builder.makeRefNull(type); } if (type.isTuple()) { std::vector<Expression*> operands; @@ -1845,7 +1825,6 @@ private: } case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: return makeTrivial(type); case Type::none: @@ -1990,7 +1969,6 @@ private: } case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: case Type::unreachable: @@ -2227,7 +2205,6 @@ private: } case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: case Type::unreachable: @@ -2434,7 +2411,6 @@ private: case Type::v128: case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: case Type::unreachable: @@ -2610,14 +2586,13 @@ private: Expression* makeRefIsNull(Type type) { assert(type == Type::i32); assert(wasm.features.hasReferenceTypes()); - Type refType; + SmallVector<Type, 2> options; + options.push_back(Type::externref); + options.push_back(Type::funcref); if (wasm.features.hasExceptionHandling()) { - refType = - pick(Type::funcref, Type::externref, Type::nullref, Type::exnref); - } else { - refType = pick(Type::funcref, Type::externref, Type::nullref); + options.push_back(Type::exnref); } - return builder.makeRefIsNull(make(refType)); + return builder.makeRefIsNull(make(pick(options))); } Expression* makeMemoryInit() { @@ -2680,10 +2655,7 @@ private: FeatureOptions<Type>() .add(FeatureSet::MVP, Type::i32, Type::i64, Type::f32, Type::f64) .add(FeatureSet::SIMD, Type::v128) - .add(FeatureSet::ReferenceTypes, - Type::funcref, - Type::externref, - Type::nullref) + .add(FeatureSet::ReferenceTypes, Type::funcref, Type::externref) .add(FeatureSet::ReferenceTypes | FeatureSet::ExceptionHandling, Type::exnref)); } @@ -2732,7 +2704,6 @@ private: FeatureOptions<Type>() .add(FeatureSet::MVP, Type::i32, Type::i64, Type::f32, Type::f64) .add(FeatureSet::SIMD, Type::v128) - .add(FeatureSet::ReferenceTypes, Type::nullref) .add(FeatureSet::ReferenceTypes | FeatureSet::ExceptionHandling, Type::exnref)); } diff --git a/src/tools/spec-wrapper.h b/src/tools/spec-wrapper.h index 44f92b56d..c073a994c 100644 --- a/src/tools/spec-wrapper.h +++ b/src/tools/spec-wrapper.h @@ -50,10 +50,13 @@ static std::string generateSpecWrapper(Module& wasm) { ret += "(v128.const i32x4 0 0 0 0)"; break; case Type::funcref: + ret += "(ref.null func)"; + break; case Type::externref: - case Type::nullref: + ret += "(ref.null extern)"; + break; case Type::exnref: - ret += "(ref.null)"; + ret += "(ref.null exn)"; break; case Type::none: case Type::unreachable: diff --git a/src/tools/wasm-reduce.cpp b/src/tools/wasm-reduce.cpp index 9c9978b63..1a7c3544d 100644 --- a/src/tools/wasm-reduce.cpp +++ b/src/tools/wasm-reduce.cpp @@ -597,7 +597,6 @@ struct Reducer case Type::v128: case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: continue; // not implemented yet case Type::none: @@ -623,7 +622,6 @@ struct Reducer case Type::v128: case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: continue; // not implemented yet case Type::none: @@ -649,7 +647,6 @@ struct Reducer case Type::v128: case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: continue; // not implemented yet case Type::none: @@ -675,7 +672,6 @@ struct Reducer case Type::v128: case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: continue; // not implemented yet case Type::none: @@ -687,7 +683,6 @@ struct Reducer case Type::v128: case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: continue; // not implemented yet case Type::none: @@ -1015,8 +1010,8 @@ struct Reducer return false; } // try to replace with a trivial value - if (curr->type.isRef()) { - RefNull* n = builder->makeRefNull(); + if (curr->type.isNullable()) { + RefNull* n = builder->makeRefNull(curr->type); return tryToReplaceCurrent(n); } if (curr->type.isTuple()) { diff --git a/src/wasm-binary.h b/src/wasm-binary.h index ab9ee5152..865a882df 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -347,8 +347,6 @@ enum EncodedType { funcref = -0x10, // 0x70 // opaque host reference type externref = -0x11, // 0x6f - // null reference type - nullref = -0x12, // 0x6e // exception reference type exnref = -0x18, // 0x68 // func_type form @@ -357,6 +355,12 @@ enum EncodedType { Empty = -0x40 // 0x40 }; +enum EncodedHeapType { + func = -0x10, // 0x70 + extern_ = -0x11, // 0x6f + exn = -0x18, // 0x68 +}; + namespace UserSections { extern const char* Name; extern const char* SourceMapUrl; @@ -968,9 +972,6 @@ inline S32LEB binaryType(Type type) { case Type::externref: ret = BinaryConsts::EncodedType::externref; break; - case Type::nullref: - ret = BinaryConsts::EncodedType::nullref; - break; case Type::exnref: ret = BinaryConsts::EncodedType::exnref; break; @@ -980,6 +981,29 @@ inline S32LEB binaryType(Type type) { return S32LEB(ret); } +inline S32LEB binaryHeapType(HeapType type) { + int ret = 0; + switch (type.kind) { + case HeapType::FuncKind: + ret = BinaryConsts::EncodedHeapType::func; + break; + case HeapType::ExternKind: + ret = BinaryConsts::EncodedHeapType::extern_; + break; + case HeapType::ExnKind: + ret = BinaryConsts::EncodedHeapType::exn; + break; + case HeapType::AnyKind: + case HeapType::EqKind: + case HeapType::I31Kind: + case HeapType::SignatureKind: + case HeapType::StructKind: + case HeapType::ArrayKind: + WASM_UNREACHABLE("TODO: GC types"); + } + return S32LEB(ret); // TODO: Actually encoded as s33 +} + // Writes out wasm to the binary format class WasmBinaryWriter { @@ -1209,6 +1233,7 @@ public: int32_t getS32LEB(); int64_t getS64LEB(); Type getType(); + HeapType getHeapType(); Type getConcreteType(); Name getInlineString(); void verifyInt8(int8_t x); diff --git a/src/wasm-builder.h b/src/wasm-builder.h index 4e94da090..1ce3a507c 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -528,9 +528,9 @@ public: ret->finalize(); return ret; } - RefNull* makeRefNull() { + RefNull* makeRefNull(Type type) { auto* ret = allocator.alloc<RefNull>(); - ret->finalize(); + ret->finalize(type); return ret; } RefIsNull* makeRefIsNull(Expression* value) { @@ -624,13 +624,15 @@ public: Expression* makeConstantExpression(Literal value) { TODO_SINGLE_COMPOUND(value.type); switch (value.type.getBasic()) { - case Type::nullref: - return makeRefNull(); case Type::funcref: - if (value.getFunc()[0] != 0) { + if (!value.isNull()) { return makeRefFunc(value.getFunc()); } - return makeRefNull(); + return makeRefNull(value.type); + case Type::externref: + case Type::exnref: // TODO: ExceptionPackage? + assert(value.isNull()); + return makeRefNull(value.type); default: assert(value.type.isNumber()); return makeConst(value); @@ -822,9 +824,8 @@ public: } case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: - return ExpressionManipulator::refNull(curr); + return ExpressionManipulator::refNull(curr, curr->type); case Type::none: return ExpressionManipulator::nop(curr); case Type::unreachable: diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 3eab81cc5..44cac9d49 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -1242,7 +1242,7 @@ public: Flow visitPop(Pop* curr) { WASM_UNREACHABLE("unimp"); } Flow visitRefNull(RefNull* curr) { NOTE_ENTER("RefNull"); - return Literal::makeNullref(); + return Literal::makeNull(curr->type); } Flow visitRefIsNull(RefIsNull* curr) { NOTE_ENTER("RefIsNull"); @@ -1250,14 +1250,14 @@ public: if (flow.breaking()) { return flow; } - Literal value = flow.getSingleValue(); + const auto& value = flow.getSingleValue(); NOTE_EVAL1(value); - return Literal(value.type == Type::nullref); + return Literal(value.isNull()); } Flow visitRefFunc(RefFunc* curr) { NOTE_ENTER("RefFunc"); NOTE_NAME(curr->func); - return Literal::makeFuncref(curr->func); + return Literal::makeFunc(curr->func); } Flow visitTry(Try* curr) { WASM_UNREACHABLE("unimp"); } Flow visitThrow(Throw* curr) { @@ -1273,7 +1273,7 @@ public: for (auto item : arguments) { exn->values.push_back(item); } - throwException(Literal::makeExnref(std::move(exn))); + throwException(Literal::makeExn(std::move(exn))); WASM_UNREACHABLE("throw"); } Flow visitRethrow(Rethrow* curr) { @@ -1282,10 +1282,11 @@ public: if (flow.breaking()) { return flow; } - if (flow.getType() == Type::nullref) { + const auto& value = flow.getSingleValue(); + if (value.isNull()) { trap("rethrow: argument is null"); } - throwException(flow.getSingleValue()); + throwException(value); WASM_UNREACHABLE("rethrow"); } Flow visitBrOnExn(BrOnExn* curr) { @@ -1294,10 +1295,11 @@ public: if (flow.breaking()) { return flow; } - if (flow.getType() == Type::nullref) { + const auto& value = flow.getSingleValue(); + if (value.isNull()) { trap("br_on_exn: argument is null"); } - auto ex = flow.getSingleValue().getExceptionPackage(); + auto ex = value.getExceptionPackage(); if (curr->event != ex.event) { // Not taken return flow; } @@ -1644,7 +1646,6 @@ public: return Literal(load128(addr).data()); case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: case Type::unreachable: @@ -1701,7 +1702,6 @@ public: break; case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: case Type::unreachable: diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index 6cbef5599..76a60d7d9 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -160,6 +160,10 @@ private: } Type stringToType(const char* str, bool allowError = false, bool prefix = false); + HeapType stringToHeapType(cashew::IString str, bool prefix = false) { + return stringToHeapType(str.str, prefix); + } + HeapType stringToHeapType(const char* str, bool prefix = false); Type elementToType(Element& s); Type stringToLaneType(const char* str); bool isType(cashew::IString str) { diff --git a/src/wasm-type.h b/src/wasm-type.h index 135c2e751..384cc589f 100644 --- a/src/wasm-type.h +++ b/src/wasm-type.h @@ -49,7 +49,6 @@ public: v128, funcref, externref, - nullref, exnref, _last_basic_id = exnref }; @@ -93,7 +92,6 @@ public: // │ anyref ║ x │ │ x │ x │ f? n │ │ ┐ // │ eqref ║ x │ │ x │ x │ n │ │ │ TODO (GC) // │ i31ref ║ x │ │ x │ x │ │ │ ┘ - // │ nullref ║ x │ │ x │ x │ f? n │ │ ◄ TODO (removed) // │ exnref ║ x │ │ x │ x │ n │ │ // ├─ Compound ──╫───┼───┼───┼───┤───────┤ │ // │ Ref ║ │ x │ x │ x │ f? n? │◄┘ @@ -110,6 +108,8 @@ public: bool isTuple() const; bool isSingle() const { return isConcrete() && !isTuple(); } bool isRef() const; + bool isFunction() const; + bool isException() const; bool isNullable() const; bool isRtt() const; @@ -154,6 +154,9 @@ public: // Returns the feature set required to use this type. FeatureSet getFeatures() const; + // Gets the heap type corresponding to this type + HeapType getHeapType() const; + // Returns a number type based on its size in bytes and whether it is a float // type. static Type get(unsigned byteSize, bool float_); @@ -368,6 +371,7 @@ struct HeapType { assert(isArray() && "Not an array"); return array; } + bool isException() const { return kind == ExnKind; } bool operator==(const HeapType& other) const; bool operator!=(const HeapType& other) const { return !(*this == other); } diff --git a/src/wasm.h b/src/wasm.h index 3d658d367..edcda4219 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -1095,6 +1095,8 @@ public: RefNull(MixedArena& allocator) {} void finalize(); + void finalize(HeapType heapType); + void finalize(Type type); }; class RefIsNull : public SpecificExpression<Expression::RefIsNullId> { diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp index 3f635ca19..ec8642865 100644 --- a/src/wasm/literal.cpp +++ b/src/wasm/literal.cpp @@ -29,37 +29,52 @@ namespace wasm { template<int N> using LaneArray = std::array<Literal, N>; +Literal::Literal(Type type) : type(type) { + assert(type != Type::unreachable && (!type.isRef() || type.isNullable())); + if (type.isException()) { + new (&exn) std::unique_ptr<ExceptionPackage>(); + } else { + memset(&v128, 0, 16); + } +} + Literal::Literal(const uint8_t init[16]) : type(Type::v128) { memcpy(&v128, init, 16); } Literal::Literal(const Literal& other) : type(other.type) { - TODO_SINGLE_COMPOUND(type); - switch (type.getBasic()) { - case Type::i32: - case Type::f32: - i32 = other.i32; - break; - case Type::i64: - case Type::f64: - i64 = other.i64; - break; - case Type::v128: - memcpy(&v128, other.v128, 16); - break; - case Type::funcref: - func = other.func; - break; - case Type::exnref: - // Avoid calling the destructor on an uninitialized value + if (type.isException()) { + // Avoid calling the destructor on an uninitialized value + if (other.exn != nullptr) { new (&exn) auto(std::make_unique<ExceptionPackage>(*other.exn)); - break; - case Type::none: - case Type::nullref: - break; - case Type::externref: - case Type::unreachable: - WASM_UNREACHABLE("unexpected type"); + } else { + new (&exn) std::unique_ptr<ExceptionPackage>(); + } + } else if (type.isFunction()) { + func = other.func; + } else { + TODO_SINGLE_COMPOUND(type); + switch (type.getBasic()) { + case Type::i32: + case Type::f32: + i32 = other.i32; + break; + case Type::i64: + case Type::f64: + i64 = other.i64; + break; + case Type::v128: + memcpy(&v128, other.v128, 16); + break; + case Type::none: + break; + case Type::externref: + break; // null + case Type::funcref: + case Type::exnref: + case Type::unreachable: + WASM_UNREACHABLE("unexpected type"); + } } } @@ -116,7 +131,7 @@ Literals Literal::makeZero(Type type) { Literal Literal::makeSingleZero(Type type) { assert(type.isSingle()); if (type.isRef()) { - return makeNullref(); + return makeNull(type); } else { return makeFromInt32(0, type); } @@ -130,8 +145,8 @@ std::array<uint8_t, 16> Literal::getv128() const { } ExceptionPackage Literal::getExceptionPackage() const { - assert(type == Type::exnref); - return *exn.get(); + assert(type.isException() && exn != nullptr); + return *exn; } Literal Literal::castToF32() { @@ -199,11 +214,17 @@ void Literal::getBits(uint8_t (&buf)[16]) const { case Type::v128: memcpy(buf, &v128, sizeof(v128)); break; + // TODO: investigate changing bits returned for reference types. currently, + // `null` values and even non-`null` functions return all zeroes, but only + // to avoid introducing a functional change. case Type::funcref: - case Type::nullref: break; case Type::externref: case Type::exnref: + if (isNull()) { + break; + } + // falls through case Type::none: case Type::unreachable: WASM_UNREACHABLE("invalid type"); @@ -211,22 +232,22 @@ void Literal::getBits(uint8_t (&buf)[16]) const { } bool Literal::operator==(const Literal& other) const { - if (type.isRef() && other.type.isRef()) { - if (type == Type::nullref && other.type == Type::nullref) { - return true; - } - if (type == Type::funcref && other.type == Type::funcref && - func == other.func) { - return true; - } - return false; - } if (type != other.type) { return false; } if (type == Type::none) { return true; } + if (isNull() || other.isNull()) { + return isNull() == other.isNull(); + } + if (type.isFunction()) { + return func == other.func; + } + if (type.isException()) { + assert(exn != nullptr && other.exn != nullptr); + return *exn == *other.exn; + } uint8_t bits[16], other_bits[16]; getBits(bits); other.getBits(other_bits); @@ -350,15 +371,23 @@ std::ostream& operator<<(std::ostream& o, Literal literal) { literal.printVec128(o, literal.getv128()); break; case Type::funcref: - o << "funcref(" << literal.getFunc() << ")"; - break; - case Type::nullref: - o << "nullref"; + if (literal.isNull()) { + o << "funcref(null)"; + } else { + o << "funcref(" << literal.getFunc() << ")"; + } break; case Type::exnref: - o << "exnref(" << literal.getExceptionPackage() << ")"; + if (literal.isNull()) { + o << "exnref(null)"; + } else { + o << "exnref(" << literal.getExceptionPackage() << ")"; + } break; case Type::externref: + assert(literal.isNull() && "TODO: non-null externref values"); + o << "externref(null)"; + break; case Type::unreachable: WASM_UNREACHABLE("invalid type"); } @@ -582,7 +611,6 @@ Literal Literal::eqz() const { case Type::v128: case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: case Type::unreachable: @@ -604,7 +632,6 @@ Literal Literal::neg() const { case Type::v128: case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: case Type::unreachable: @@ -626,7 +653,6 @@ Literal Literal::abs() const { case Type::v128: case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: case Type::unreachable: @@ -731,7 +757,6 @@ Literal Literal::add(const Literal& other) const { case Type::v128: case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: case Type::unreachable: @@ -753,7 +778,6 @@ Literal Literal::sub(const Literal& other) const { case Type::v128: case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: case Type::unreachable: @@ -846,7 +870,6 @@ Literal Literal::mul(const Literal& other) const { case Type::v128: case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: case Type::unreachable: @@ -1100,7 +1123,6 @@ Literal Literal::eq(const Literal& other) const { case Type::v128: case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: case Type::unreachable: @@ -1122,7 +1144,6 @@ Literal Literal::ne(const Literal& other) const { case Type::v128: case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: case Type::unreachable: diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index ae10687fb..b78d6b86b 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -1136,8 +1136,6 @@ Type WasmBinaryBuilder::getType() { return Type::funcref; case BinaryConsts::EncodedType::externref: return Type::externref; - case BinaryConsts::EncodedType::nullref: - return Type::nullref; case BinaryConsts::EncodedType::exnref: return Type::exnref; default: @@ -1146,6 +1144,28 @@ Type WasmBinaryBuilder::getType() { WASM_UNREACHABLE("unexpeced type"); } +HeapType WasmBinaryBuilder::getHeapType() { + int type = getS32LEB(); // TODO: Actually encoded as s33 + // Single heap types are negative; heap type indices are non-negative + if (type >= 0) { + if (size_t(type) >= signatures.size()) { + throwError("invalid signature index: " + std::to_string(type)); + } + return HeapType(signatures[type]); + } + switch (type) { + case BinaryConsts::EncodedHeapType::func: + return HeapType::FuncKind; + case BinaryConsts::EncodedHeapType::extern_: + return HeapType::ExternKind; + case BinaryConsts::EncodedHeapType::exn: + return HeapType::ExnKind; + default: + throwError("invalid wasm heap type: " + std::to_string(type)); + } + WASM_UNREACHABLE("unexpeced type"); +} + Type WasmBinaryBuilder::getConcreteType() { auto type = getType(); if (!type.isConcrete()) { @@ -4689,7 +4709,7 @@ void WasmBinaryBuilder::visitDrop(Drop* curr) { void WasmBinaryBuilder::visitRefNull(RefNull* curr) { BYN_TRACE("zz node: RefNull\n"); - curr->finalize(); + curr->finalize(getHeapType()); } void WasmBinaryBuilder::visitRefIsNull(RefIsNull* curr) { diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 931cd1bf0..0e4202a24 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -869,9 +869,6 @@ Type SExpressionWasmBuilder::stringToType(const char* str, if (strncmp(str, "externref", 9) == 0 && (prefix || str[9] == 0)) { return Type::externref; } - if (strncmp(str, "nullref", 7) == 0 && (prefix || str[7] == 0)) { - return Type::nullref; - } if (strncmp(str, "exnref", 6) == 0 && (prefix || str[6] == 0)) { return Type::exnref; } @@ -881,6 +878,41 @@ Type SExpressionWasmBuilder::stringToType(const char* str, throw ParseException(std::string("invalid wasm type: ") + str); } +HeapType SExpressionWasmBuilder::stringToHeapType(const char* str, + bool prefix) { + if (str[0] == 'a') { + if (str[1] == 'n' && str[2] == 'y' && (prefix || str[3] == 0)) { + return HeapType::AnyKind; + } + } + if (str[0] == 'e') { + if (str[1] == 'q' && (prefix || str[2] == 0)) { + return HeapType::EqKind; + } + if (str[1] == 'x') { + if (str[2] == 'n' && (prefix || str[3] == 0)) { + return HeapType::ExnKind; + } + if (str[2] == 't' && str[3] == 'e' && str[4] == 'r' && str[5] == 'n' && + (prefix || str[6] == 0)) { + return HeapType::ExternKind; + } + } + } + if (str[0] == 'i') { + if (str[1] == '3' && str[2] == '1' && (prefix || str[3] == 0)) { + return HeapType::I31Kind; + } + } + if (str[0] == 'f') { + if (str[1] == 'u' && str[2] == 'n' && str[3] == 'c' && + (prefix || str[4] == 0)) { + return HeapType::FuncKind; + } + } + throw ParseException(std::string("invalid wasm heap type: ") + str); +} + Type SExpressionWasmBuilder::elementToType(Element& s) { if (s.isStr()) { return stringToType(s.str(), false, false); @@ -1779,8 +1811,12 @@ Expression* SExpressionWasmBuilder::makeReturn(Element& s) { } Expression* SExpressionWasmBuilder::makeRefNull(Element& s) { + if (s.size() != 2) { + throw ParseException("invalid heap type reference", s.line, s.col); + } + auto heapType = stringToHeapType(s[1]->str()); auto ret = allocator.alloc<RefNull>(); - ret->finalize(); + ret->finalize(heapType); return ret; } diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 88f90378c..aee5079c2 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -190,7 +190,6 @@ void BinaryInstWriter::visitLoad(Load* curr) { return; case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: WASM_UNREACHABLE("unexpected type"); @@ -292,7 +291,6 @@ void BinaryInstWriter::visitStore(Store* curr) { break; case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: case Type::unreachable: @@ -695,7 +693,6 @@ void BinaryInstWriter::visitConst(Const* curr) { } case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: case Type::unreachable: @@ -1686,7 +1683,8 @@ void BinaryInstWriter::visitHost(Host* curr) { } void BinaryInstWriter::visitRefNull(RefNull* curr) { - o << int8_t(BinaryConsts::RefNull); + o << int8_t(BinaryConsts::RefNull) + << binaryHeapType(curr->type.getHeapType()); } void BinaryInstWriter::visitRefIsNull(RefIsNull* curr) { diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index e46cb5886..729cc88f5 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -260,7 +260,6 @@ std::unordered_map<TypeInfo, uintptr_t> indices = { // * `(ref null any) == anyref` // * `(ref null eq) == eqref` // * `(ref i31) == i31ref` - {TypeInfo({Type::nullref}), Type::nullref}, // TODO (removed) {TypeInfo({Type::exnref}), Type::exnref}, {TypeInfo(HeapType(HeapType::ExnKind), true), Type::exnref}, }; @@ -347,6 +346,24 @@ bool Type::isRef() const { } } +bool Type::isFunction() const { + if (isBasic()) { + return id == funcref; + } else { + auto* info = getTypeInfo(*this); + return info->isRef() && info->ref.heapType.isSignature(); + } +} + +bool Type::isException() const { + if (isBasic()) { + return id == exnref; + } else { + auto* info = getTypeInfo(*this); + return info->isRef() && info->ref.heapType.isException(); + } +} + bool Type::isNullable() const { if (isBasic()) { return id >= funcref && id <= exnref; @@ -389,7 +406,6 @@ unsigned Type::getByteSize() const { return 16; case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: case Type::unreachable: @@ -432,7 +448,6 @@ FeatureSet Type::getFeatures() const { return FeatureSet::SIMD; case Type::funcref: case Type::externref: - case Type::nullref: return FeatureSet::ReferenceTypes; case Type::exnref: return FeatureSet::ReferenceTypes | FeatureSet::ExceptionHandling; @@ -451,6 +466,25 @@ FeatureSet Type::getFeatures() const { return getSingleFeatures(*this); } +HeapType Type::getHeapType() const { + if (isRef()) { + if (isCompound()) { + return getTypeInfo(*this)->ref.heapType; + } + switch (getBasic()) { + case funcref: + return HeapType::FuncKind; + case externref: + return HeapType::ExternKind; + case exnref: + return HeapType::ExnKind; + default: + break; + } + } + WASM_UNREACHABLE("unexpected type"); +} + Type Type::get(unsigned byteSize, bool float_) { if (byteSize < 4) { return Type::i32; @@ -468,13 +502,10 @@ Type Type::get(unsigned byteSize, bool float_) { } bool Type::isSubType(Type left, Type right) { + // TODO (GC): subtyping, currently checks for equality only if (left == right) { return true; } - if (left.isRef() && right.isRef() && - (right == Type::externref || left == Type::nullref)) { - return true; - } if (left.isTuple() && right.isTuple()) { if (left.size() != right.size()) { return false; @@ -513,16 +544,7 @@ Type Type::getLeastUpperBound(Type a, Type b) { } return Type(types); } - if (!a.isRef() || !b.isRef()) { - return Type::none; - } - if (a == Type::nullref) { - return b; - } - if (b == Type::nullref) { - return a; - } - return Type::externref; + return Type::none; } Type::Iterator Type::end() const { @@ -554,8 +576,7 @@ const Type& Type::operator[](size_t index) const { } } -HeapType::HeapType(const HeapType& other) { - kind = other.kind; +HeapType::HeapType(const HeapType& other) : kind(other.kind) { switch (kind) { case FuncKind: case ExternKind: @@ -708,9 +729,6 @@ std::ostream& operator<<(std::ostream& os, Type type) { case Type::externref: os << "externref"; break; - case Type::nullref: - os << "nullref"; - break; case Type::exnref: os << "exnref"; break; diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 3e1a057ce..b236f9120 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -1264,7 +1264,6 @@ void FunctionValidator::validateMemBytes(uint8_t bytes, break; case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: WASM_UNREACHABLE("unexpected type"); @@ -2074,7 +2073,6 @@ void FunctionValidator::validateAlignment( break; case Type::funcref: case Type::externref: - case Type::nullref: case Type::exnref: case Type::none: WASM_UNREACHABLE("invalid type"); diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index 387ea577f..fe7c1b229 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -209,10 +209,10 @@ const char* getExpressionName(Expression* curr) { Literal getSingleLiteralFromConstExpression(Expression* curr) { if (auto* c = curr->dynCast<Const>()) { return c->value; - } else if (curr->is<RefNull>()) { - return Literal::makeNullref(); + } else if (auto* n = curr->dynCast<RefNull>()) { + return Literal::makeNull(n->type); } else if (auto* r = curr->dynCast<RefFunc>()) { - return Literal::makeFuncref(r->func); + return Literal::makeFunc(r->func); } else { WASM_UNREACHABLE("Not a constant expression"); } @@ -896,7 +896,16 @@ void Host::finalize() { } } -void RefNull::finalize() { type = Type::nullref; } +void RefNull::finalize(HeapType heapType) { type = Type(heapType, true); } + +void RefNull::finalize(Type type_) { + assert(type_ == Type::unreachable || type_.isNullable()); + type = type_; +} + +void RefNull::finalize() { + assert(type == Type::unreachable || type.isNullable()); +} void RefIsNull::finalize() { if (value->type == Type::unreachable) { diff --git a/test/binaryen.js/exception-handling.js.txt b/test/binaryen.js/exception-handling.js.txt index 380ce34d6..d590d0b4b 100644 --- a/test/binaryen.js/exception-handling.js.txt +++ b/test/binaryen.js/exception-handling.js.txt @@ -29,6 +29,6 @@ ) getExpressionInfo(throw) = {"id":43,"type":1,"event":"e"} -getExpressionInfo(br_on_exn) = {"id":45,"type":10,"name":"l","event":"e"} +getExpressionInfo(br_on_exn) = {"id":45,"type":9,"name":"l","event":"e"} getExpressionInfo(rethrow) = {"id":44,"type":1} getExpressionInfo(try) = {"id":42,"type":0} diff --git a/test/binaryen.js/kitchen-sink.js b/test/binaryen.js/kitchen-sink.js index 93ed27334..e82090858 100644 --- a/test/binaryen.js/kitchen-sink.js +++ b/test/binaryen.js/kitchen-sink.js @@ -48,44 +48,47 @@ function makeDroppedInt32(x) { function test_types() { console.log(" // BinaryenTypeNone: " + binaryen.none); - console.log(" //", binaryen.expandType(binaryen.none)); + console.log(" //", binaryen.expandType(binaryen.none).join(",")); console.log(" // BinaryenTypeUnreachable: " + binaryen.unreachable); - console.log(" //", binaryen.expandType(binaryen.unreachable)); + console.log(" //", binaryen.expandType(binaryen.unreachable).join(",")); console.log(" // BinaryenTypeInt32: " + binaryen.i32); - console.log(" //", binaryen.expandType(binaryen.i32)); + console.log(" //", binaryen.expandType(binaryen.i32).join(",")); console.log(" // BinaryenTypeInt64: " + binaryen.i64); - console.log(" //", binaryen.expandType(binaryen.i64)); + console.log(" //", binaryen.expandType(binaryen.i64).join(",")); console.log(" // BinaryenTypeFloat32: " + binaryen.f32); - console.log(" //", binaryen.expandType(binaryen.f32)); + console.log(" //", binaryen.expandType(binaryen.f32).join(",")); console.log(" // BinaryenTypeFloat64: " + binaryen.f64); - console.log(" //", binaryen.expandType(binaryen.f64)); + console.log(" //", binaryen.expandType(binaryen.f64).join(",")); console.log(" // BinaryenTypeVec128: " + binaryen.v128); - console.log(" //", binaryen.expandType(binaryen.v128)); + console.log(" //", binaryen.expandType(binaryen.v128).join(",")); + + console.log(" // BinaryenTypeFuncref: " + binaryen.funcref); + console.log(" //", binaryen.expandType(binaryen.funcref).join(",")); console.log(" // BinaryenTypeExternref: " + binaryen.externref); - console.log(" //", binaryen.expandType(binaryen.externref)); + console.log(" //", binaryen.expandType(binaryen.externref).join(",")); console.log(" // BinaryenTypeExnref: " + binaryen.exnref); - console.log(" //", binaryen.expandType(binaryen.exnref)); + console.log(" //", binaryen.expandType(binaryen.exnref).join(",")); console.log(" // BinaryenTypeAuto: " + binaryen.auto); var i32_pair = binaryen.createType([binaryen.i32, binaryen.i32]); - console.log(" //", binaryen.expandType(i32_pair)); + console.log(" //", binaryen.expandType(i32_pair).join(",")); var duplicate_pair = binaryen.createType([binaryen.i32, binaryen.i32]); - console.log(" //", binaryen.expandType(duplicate_pair)); + console.log(" //", binaryen.expandType(duplicate_pair).join(",")); assert(i32_pair == duplicate_pair); var f32_pair = binaryen.createType([binaryen.f32, binaryen.f32]); - console.log(" //", binaryen.expandType(f32_pair)); + console.log(" //", binaryen.expandType(f32_pair).join(",")); } function test_features() { @@ -502,9 +505,10 @@ function test_core() { module.return_call_indirect(makeInt32(2449), [ makeInt32(13), makeInt64(37, 0), makeFloat32(1.3), makeFloat64(3.7) ], iIfF, binaryen.i32), // Reference types - module.ref.is_null(module.ref.null()), + module.ref.is_null(module.ref.null(binaryen.externref)), + module.ref.is_null(module.ref.null(binaryen.funcref)), module.ref.is_null(module.ref.func("kitchen()sinker")), - module.select(temp10, module.ref.null(), module.ref.func("kitchen()sinker"), binaryen.funcref), + module.select(temp10, module.ref.null(binaryen.funcref), module.ref.func("kitchen()sinker"), binaryen.funcref), // Exception handling module.try( @@ -563,7 +567,6 @@ function test_core() { module.v128.pop(), module.externref.pop(), module.funcref.pop(), - module.nullref.pop(), module.exnref.pop(), // TODO: Host module.nop(), diff --git a/test/binaryen.js/kitchen-sink.js.txt b/test/binaryen.js/kitchen-sink.js.txt index c58f1f563..917525eeb 100644 --- a/test/binaryen.js/kitchen-sink.js.txt +++ b/test/binaryen.js/kitchen-sink.js.txt @@ -1,25 +1,27 @@ // BinaryenTypeNone: 0 - // [] + // // BinaryenTypeUnreachable: 1 - // [ 1 ] + // 1 // BinaryenTypeInt32: 2 - // [ 2 ] + // 2 // BinaryenTypeInt64: 3 - // [ 3 ] + // 3 // BinaryenTypeFloat32: 4 - // [ 4 ] + // 4 // BinaryenTypeFloat64: 5 - // [ 5 ] + // 5 // BinaryenTypeVec128: 6 - // [ 6 ] + // 6 + // BinaryenTypeFuncref: 7 + // 7 // BinaryenTypeExternref: 8 - // [ 8 ] - // BinaryenTypeExnref: 10 - // [ 10 ] + // 8 + // BinaryenTypeExnref: 9 + // 9 // BinaryenTypeAuto: -1 - // [ 2, 2 ] - // [ 2, 2 ] - // [ 4, 4 ] + // 2,2 + // 2,2 + // 4,4 Features.MVP: 0 Features.Atomics: 1 Features.BulkMemory: 16 @@ -1811,7 +1813,12 @@ getExpressionInfo(tuple[3])={"id":14,"type":5,"value":3.7} ) (drop (ref.is_null - (ref.null) + (ref.null extern) + ) + ) + (drop + (ref.is_null + (ref.null func) ) ) (drop @@ -1821,7 +1828,7 @@ getExpressionInfo(tuple[3])={"id":14,"type":5,"value":3.7} ) (drop (select (result funcref) - (ref.null) + (ref.null func) (ref.func "$kitchen()sinker") (i32.const 1) ) @@ -1907,9 +1914,6 @@ getExpressionInfo(tuple[3])={"id":14,"type":5,"value":3.7} (funcref.pop) ) (drop - (nullref.pop) - ) - (drop (exnref.pop) ) (nop) @@ -3649,7 +3653,12 @@ getExpressionInfo(tuple[3])={"id":14,"type":5,"value":3.7} ) (drop (ref.is_null - (ref.null) + (ref.null extern) + ) + ) + (drop + (ref.is_null + (ref.null func) ) ) (drop @@ -3659,7 +3668,7 @@ getExpressionInfo(tuple[3])={"id":14,"type":5,"value":3.7} ) (drop (select (result funcref) - (ref.null) + (ref.null func) (ref.func "$kitchen()sinker") (i32.const 1) ) @@ -3745,9 +3754,6 @@ getExpressionInfo(tuple[3])={"id":14,"type":5,"value":3.7} (funcref.pop) ) (drop - (nullref.pop) - ) - (drop (exnref.pop) ) (nop) diff --git a/test/ctor-eval/bad-indirect-call3.wast b/test/ctor-eval/bad-indirect-call3.wast index cadff8097..7a16889ce 100644 --- a/test/ctor-eval/bad-indirect-call3.wast +++ b/test/ctor-eval/bad-indirect-call3.wast @@ -9,7 +9,7 @@ ) (func $sig_mismatch (call_indirect (type $funcref_=>_none) ;; unsafe to call, signature mismatch - (ref.null) + (ref.null func) (i32.const 0) ) ) diff --git a/test/ctor-eval/bad-indirect-call3.wast.out b/test/ctor-eval/bad-indirect-call3.wast.out index 9e4881344..28a7c5ed5 100644 --- a/test/ctor-eval/bad-indirect-call3.wast.out +++ b/test/ctor-eval/bad-indirect-call3.wast.out @@ -15,7 +15,7 @@ ) (func $sig_mismatch (call_indirect (type $funcref_=>_none) - (ref.null) + (ref.null func) (i32.const 0) ) ) diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index b1dbae7d5..b0a3ad302 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -205,12 +205,6 @@ void test_types() { BinaryenTypeExpand(externref, &valueType); assert(valueType == externref); - BinaryenType nullref = BinaryenTypeNullref(); - printf(" // BinaryenTypeNullref: %d\n", nullref); - assert(BinaryenTypeArity(nullref) == 1); - BinaryenTypeExpand(nullref, &valueType); - assert(valueType == nullref); - BinaryenType exnref = BinaryenTypeExnref(); printf(" // BinaryenTypeExnref: %d\n", exnref); assert(BinaryenTypeArity(exnref) == 1); @@ -294,9 +288,10 @@ void test_core() { temp10 = makeInt32(module, 1), temp11 = makeInt32(module, 3), temp12 = makeInt32(module, 5), temp13 = makeInt32(module, 10), temp14 = makeInt32(module, 11), temp15 = makeInt32(module, 110), temp16 = makeInt64(module, 111); - BinaryenExpressionRef nullrefExpr = BinaryenRefNull(module); - BinaryenExpressionRef funcrefExpr = - BinaryenRefFunc(module, "kitchen()sinker"); + BinaryenExpressionRef externrefExpr = BinaryenRefNull(module, BinaryenTypeExternref()); + BinaryenExpressionRef funcrefExpr = BinaryenRefNull(module, BinaryenTypeFuncref()); + funcrefExpr = BinaryenRefFunc(module, "kitchen()sinker"); + BinaryenExpressionRef exnrefExpr = BinaryenRefNull(module, BinaryenTypeExnref()); // Events BinaryenAddEvent( @@ -718,10 +713,11 @@ void test_core() { iIfF, BinaryenTypeInt32()), // Reference types - BinaryenRefIsNull(module, nullrefExpr), + BinaryenRefIsNull(module, externrefExpr), BinaryenRefIsNull(module, funcrefExpr), + BinaryenRefIsNull(module, exnrefExpr), BinaryenSelect( - module, temp10, nullrefExpr, funcrefExpr, BinaryenTypeFuncref()), + module, temp10, BinaryenRefNull(module, BinaryenTypeFuncref()), BinaryenRefFunc(module, "kitchen()sinker"), BinaryenTypeFuncref()), // Exception handling BinaryenTry(module, tryBody, catchBody), // Atomics @@ -748,10 +744,6 @@ void test_core() { BinaryenPop(module, BinaryenTypeFloat64()), BinaryenPop(module, BinaryenTypeFuncref()), BinaryenPop(module, BinaryenTypeExternref()), - BinaryenPop(module, BinaryenTypeNullref()), - BinaryenPop(module, BinaryenTypeExnref()), - BinaryenPop(module, BinaryenTypeFuncref()), - BinaryenPop(module, BinaryenTypeNullref()), BinaryenPop(module, BinaryenTypeExnref()), // TODO: Host diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt index b0aae7f3b..288174b99 100644 --- a/test/example/c-api-kitchen-sink.txt +++ b/test/example/c-api-kitchen-sink.txt @@ -7,8 +7,7 @@ // BinaryenTypeVec128: 6 // BinaryenTypeFuncref: 7 // BinaryenTypeExternref: 8 - // BinaryenTypeNullref: 9 - // BinaryenTypeExnref: 10 + // BinaryenTypeExnref: 9 // BinaryenTypeAuto: -1 BinaryenFeatureMVP: 0 BinaryenFeatureAtomics: 1 @@ -1753,7 +1752,7 @@ BinaryenFeatureAll: 1023 ) (drop (ref.is_null - (ref.null) + (ref.null extern) ) ) (drop @@ -1762,8 +1761,13 @@ BinaryenFeatureAll: 1023 ) ) (drop + (ref.is_null + (ref.null exn) + ) + ) + (drop (select (result funcref) - (ref.null) + (ref.null func) (ref.func "$kitchen()sinker") (i32.const 1) ) @@ -1846,18 +1850,6 @@ BinaryenFeatureAll: 1023 (externref.pop) ) (drop - (nullref.pop) - ) - (drop - (exnref.pop) - ) - (drop - (funcref.pop) - ) - (drop - (nullref.pop) - ) - (drop (exnref.pop) ) (nop) diff --git a/test/exception-handling.wast b/test/exception-handling.wast index 7f16a237b..3dcff41e4 100644 --- a/test/exception-handling.wast +++ b/test/exception-handling.wast @@ -59,23 +59,4 @@ ) ) ) - - ;; Test subtype relationship - (func $subtype_test - (try - (do) - (catch - (drop (exnref.pop)) - (drop - (block $l0 (result i32) - (rethrow - (br_on_exn $l0 $e0 (ref.null)) - ) - ) - ) - ) - ) - - (throw $e1 (ref.null)) - ) ) diff --git a/test/exception-handling.wast.from-wast b/test/exception-handling.wast.from-wast index 4430bf0f0..a5fb02d56 100644 --- a/test/exception-handling.wast.from-wast +++ b/test/exception-handling.wast.from-wast @@ -71,28 +71,4 @@ ) ) ) - (func $subtype_test - (try - (do - (nop) - ) - (catch - (drop - (exnref.pop) - ) - (drop - (block $l0 (result i32) - (rethrow - (br_on_exn $l0 $e0 - (ref.null) - ) - ) - ) - ) - ) - ) - (throw $e1 - (ref.null) - ) - ) ) diff --git a/test/exception-handling.wast.fromBinary b/test/exception-handling.wast.fromBinary index fc3dc3804..24af9294e 100644 --- a/test/exception-handling.wast.fromBinary +++ b/test/exception-handling.wast.fromBinary @@ -74,29 +74,5 @@ ) ) ) - (func $subtype_test - (try - (do - (nop) - ) - (catch - (drop - (exnref.pop) - ) - (drop - (block $label$3 (result i32) - (rethrow - (br_on_exn $label$3 $event$0 - (ref.null) - ) - ) - ) - ) - ) - ) - (throw $event$1 - (ref.null) - ) - ) ) diff --git a/test/exception-handling.wast.fromBinary.noDebugInfo b/test/exception-handling.wast.fromBinary.noDebugInfo index 96cc9c4c6..69abafdbf 100644 --- a/test/exception-handling.wast.fromBinary.noDebugInfo +++ b/test/exception-handling.wast.fromBinary.noDebugInfo @@ -74,29 +74,5 @@ ) ) ) - (func $4 - (try - (do - (nop) - ) - (catch - (drop - (exnref.pop) - ) - (drop - (block $label$3 (result i32) - (rethrow - (br_on_exn $label$3 $event$0 - (ref.null) - ) - ) - ) - ) - ) - ) - (throw $event$1 - (ref.null) - ) - ) ) diff --git a/test/multivalue.wast b/test/multivalue.wast index 01e1237f3..8b0c5664e 100644 --- a/test/multivalue.wast +++ b/test/multivalue.wast @@ -129,17 +129,17 @@ ) ) (func $mv-if (result i32 i64 externref) - (if (result i32 i64 nullref) + (if (result i32 i64 externref) (i32.const 1) (tuple.make (i32.const 42) (i64.const 42) - (ref.null) + (ref.null extern) ) (tuple.make (i32.const 42) (i64.const 42) - (ref.null) + (ref.null extern) ) ) ) diff --git a/test/multivalue.wast.from-wast b/test/multivalue.wast.from-wast index db0a4b2d0..64449925c 100644 --- a/test/multivalue.wast.from-wast +++ b/test/multivalue.wast.from-wast @@ -1,12 +1,11 @@ (module (type $none_=>_i32_i64 (func (result i32 i64))) (type $none_=>_none (func)) + (type $none_=>_i32_i64_externref (func (result i32 i64 externref))) (type $none_=>_i64 (func (result i64))) (type $none_=>_f32_i64_i32 (func (result f32 i64 i32))) (type $none_=>_i32 (func (result i32))) (type $none_=>_i32_i64_f32 (func (result i32 i64 f32))) - (type $none_=>_i32_i64_externref (func (result i32 i64 externref))) - (type $none_=>_i32_i64_nullref (func (result i32 i64 nullref))) (type $none_=>_f32 (func (result f32))) (import "env" "pair" (func $pair (result i32 i64))) (global $g1 (mut (i32 i64)) (tuple.make @@ -137,17 +136,17 @@ ) ) (func $mv-if (result i32 i64 externref) - (if (result i32 i64 nullref) + (if (result i32 i64 externref) (i32.const 1) (tuple.make (i32.const 42) (i64.const 42) - (ref.null) + (ref.null extern) ) (tuple.make (i32.const 42) (i64.const 42) - (ref.null) + (ref.null extern) ) ) ) diff --git a/test/multivalue.wast.fromBinary b/test/multivalue.wast.fromBinary index 190194fcf..f4a8e20b7 100644 --- a/test/multivalue.wast.fromBinary +++ b/test/multivalue.wast.fromBinary @@ -6,7 +6,6 @@ (type $none_=>_f32_i64_i32 (func (result f32 i64 i32))) (type $none_=>_i32 (func (result i32))) (type $none_=>_i32_i64_f32 (func (result i32 i64 f32))) - (type $none_=>_i32_i64_nullref (func (result i32 i64 nullref))) (type $none_=>_f32 (func (result f32))) (import "env" "pair" (func $pair (result i32 i64))) (global $global$0 (mut i32) (i32.const 0)) @@ -391,19 +390,19 @@ ) ) (func $mv-if (result i32 i64 externref) - (local $0 (i32 i64 nullref)) + (local $0 (i32 i64 externref)) (local.set $0 - (if (result i32 i64 nullref) + (if (result i32 i64 externref) (i32.const 1) (tuple.make (i32.const 42) (i64.const 42) - (ref.null) + (ref.null extern) ) (tuple.make (i32.const 42) (i64.const 42) - (ref.null) + (ref.null extern) ) ) ) diff --git a/test/multivalue.wast.fromBinary.noDebugInfo b/test/multivalue.wast.fromBinary.noDebugInfo index 226490f26..106e7c436 100644 --- a/test/multivalue.wast.fromBinary.noDebugInfo +++ b/test/multivalue.wast.fromBinary.noDebugInfo @@ -6,7 +6,6 @@ (type $none_=>_f32_i64_i32 (func (result f32 i64 i32))) (type $none_=>_i32 (func (result i32))) (type $none_=>_i32_i64_f32 (func (result i32 i64 f32))) - (type $none_=>_i32_i64_nullref (func (result i32 i64 nullref))) (type $none_=>_f32 (func (result f32))) (import "env" "pair" (func $fimport$0 (result i32 i64))) (global $global$0 (mut i32) (i32.const 0)) @@ -391,19 +390,19 @@ ) ) (func $14 (result i32 i64 externref) - (local $0 (i32 i64 nullref)) + (local $0 (i32 i64 externref)) (local.set $0 - (if (result i32 i64 nullref) + (if (result i32 i64 externref) (i32.const 1) (tuple.make (i32.const 42) (i64.const 42) - (ref.null) + (ref.null extern) ) (tuple.make (i32.const 42) (i64.const 42) - (ref.null) + (ref.null extern) ) ) ) diff --git a/test/passes/dce_all-features.txt b/test/passes/dce_all-features.txt index 59f32f1be..c5094b301 100644 --- a/test/passes/dce_all-features.txt +++ b/test/passes/dce_all-features.txt @@ -547,7 +547,7 @@ ) (func $rethrow (rethrow - (ref.null) + (ref.null exn) ) ) ) diff --git a/test/passes/dce_all-features.wast b/test/passes/dce_all-features.wast index 77e781097..78324b941 100644 --- a/test/passes/dce_all-features.wast +++ b/test/passes/dce_all-features.wast @@ -779,7 +779,7 @@ (func $throw (drop - (block $label$0 (result nullref) + (block $label$0 (result externref) (if (i32.clz (block $label$1 (result i32) @@ -788,25 +788,25 @@ ) (nop) ) - (ref.null) + (ref.null extern) ) ) ) (func $rethrow (drop - (block $label$0 (result nullref) + (block $label$0 (result externref) (if (i32.clz (block $label$1 (result i32) (rethrow - (ref.null) + (ref.null exn) ) ) ) (nop) ) - (ref.null) + (ref.null extern) ) ) ) diff --git a/test/passes/flatten_all-features.txt b/test/passes/flatten_all-features.txt index e52f9e826..896dc4ed0 100644 --- a/test/passes/flatten_all-features.txt +++ b/test/passes/flatten_all-features.txt @@ -5,7 +5,6 @@ (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_f32 (func (result f32))) (type $i64_i64_=>_i64 (func (param i64 i64) (result i64))) - (type $none_=>_externref (func (result externref))) (memory $0 10) (table $0 1 1 funcref) (elem (i32.const 0) $call-me) @@ -2376,53 +2375,6 @@ ) (unreachable) ) - (func $subtype (result externref) - (local $0 nullref) - (local $1 externref) - (local $2 nullref) - (local $3 nullref) - (local $4 nullref) - (local $5 nullref) - (local $6 nullref) - (local $7 externref) - (block $label0 - (block $block - (local.set $1 - (ref.null) - ) - (local.set $2 - (ref.null) - ) - (br_if $label0 - (i32.const 0) - ) - (local.set $3 - (local.get $2) - ) - (local.set $0 - (local.get $3) - ) - (local.set $4 - (local.get $0) - ) - (local.set $5 - (local.get $4) - ) - ) - (local.set $6 - (local.get $5) - ) - (local.set $1 - (local.get $6) - ) - ) - (local.set $7 - (local.get $1) - ) - (return - (local.get $7) - ) - ) ) (module (type $i64_f32_=>_none (func (param i64 f32))) diff --git a/test/passes/flatten_all-features.wast b/test/passes/flatten_all-features.wast index f07175bd2..68bd7a64b 100644 --- a/test/passes/flatten_all-features.wast +++ b/test/passes/flatten_all-features.wast @@ -1020,6 +1020,7 @@ (return (i32.sub (i32.const 1) (i32.const 2))) ) + ;; TODO (GC) ;; subtypes ;; br_if leaves a value on the stack if not taken, which later can be the last @@ -1027,18 +1028,19 @@ ;; targets an outer branch whose return type is a supertype of the br_if's ;; value type, we need the value to be set into two locals: one with the outer ;; block's type, and one with its value type. - (func $subtype (result externref) (local $0 nullref) - (block $label0 (result externref) - (block (result nullref) - (local.tee $0 - (br_if $label0 - (ref.null) - (i32.const 0) - ) - ) - ) - ) - ) + ;; (func $subtype (result externref) + ;; (local $0 anyref) + ;; (block $label0 (result externref) + ;; (block (result anyref) + ;; (local.tee $0 + ;; (br_if $label0 + ;; (ref.null extern) + ;; (i32.const 0) + ;; ) + ;; ) + ;; ) + ;; ) + ;; ) ) (module (func $0 (param $0 i64) (param $1 f32) diff --git a/test/passes/flatten_local-cse_all-features.txt b/test/passes/flatten_local-cse_all-features.txt index 5f3adace7..201a6f793 100644 --- a/test/passes/flatten_local-cse_all-features.txt +++ b/test/passes/flatten_local-cse_all-features.txt @@ -764,52 +764,3 @@ ) ) ) -(module - (type $none_=>_none (func)) - (type $none_=>_funcref (func (result funcref))) - (func $subtype-test (result funcref) - (local $0 nullref) - (local $1 nullref) - (local $2 funcref) - (local $3 funcref) - (block - (nop) - (loop $label$1 - (local.set $0 - (ref.null) - ) - ) - (local.set $1 - (local.get $0) - ) - (local.set $2 - (local.get $0) - ) - ) - (local.set $3 - (local.get $2) - ) - (return - (local.get $2) - ) - ) - (func $test - (local $0 externref) - (local $1 nullref) - (local $2 nullref) - (block $label$1 - (local.set $0 - (ref.null) - ) - (local.set $1 - (ref.null) - ) - ) - (local.set $2 - (local.get $1) - ) - (drop - (local.get $1) - ) - ) -) diff --git a/test/passes/flatten_local-cse_all-features.wast b/test/passes/flatten_local-cse_all-features.wast index 1b4dc37c2..05fbcb2ac 100644 --- a/test/passes/flatten_local-cse_all-features.wast +++ b/test/passes/flatten_local-cse_all-features.wast @@ -288,29 +288,30 @@ ) ) -(module - ;; After --flatten, there will be a series of chain copies between multiple - ;; locals, but some of the locals will be nullref type and others funcref type. - ;; We cannot make locals of different types a common subexpression. - (func $subtype-test (result funcref) - (nop) - (loop $label$1 (result nullref) - (ref.null) - ) - ) +;; TODO (GC) +;; (module +;; ;; After --flatten, there will be a series of chain copies between multiple +;; ;; locals, but some of the locals will be funcref type and others anyref +;; ;; type. We cannot make locals of different types a common subexpression. +;; (func $subtype-test (result anyref) +;; (nop) +;; (loop $label$1 (result funcref) +;; (ref.null func) +;; ) +;; ) - (func $test - (local $0 externref) - (drop - (block $label$1 (result nullref) - (local.set $0 - (ref.null) - ) - ;; After --flatten, this will be assigned to a local of nullref type. After - ;; --local-cse, even if we set (ref.null) to local $0 above, this should not - ;; be replaced with $0, because it is of type externref. - (ref.null) - ) - ) - ) -) +;; (func $test +;; (local $0 anyref) +;; (drop +;; (block $label$1 (result funcref) +;; (local.set $0 +;; (ref.null func) +;; ) +;; ;; After --flatten, this will be assigned to a local of funcref type. After +;; ;; --local-cse, even if we set (ref.null) to local $0 above, this should not +;; ;; be replaced with $0, because it is of type anyref. +;; (ref.null func) +;; ) +;; ) +;; ) +;; ) diff --git a/test/passes/inlining_all-features.txt b/test/passes/inlining_all-features.txt index cb24b9e8b..b2f483d3d 100644 --- a/test/passes/inlining_all-features.txt +++ b/test/passes/inlining_all-features.txt @@ -23,7 +23,7 @@ (block (block $__inlined_func$func_inner (local.set $1 - (ref.null) + (ref.null exn) ) (drop (block $l0 (result i32) diff --git a/test/passes/instrument-locals_all-features.txt b/test/passes/instrument-locals_all-features.txt index e2ba3e107..91e71a48d 100644 --- a/test/passes/instrument-locals_all-features.txt +++ b/test/passes/instrument-locals_all-features.txt @@ -6,7 +6,6 @@ (type $i32_i32_v128_=>_v128 (func (param i32 i32 v128) (result v128))) (type $i32_i32_funcref_=>_funcref (func (param i32 i32 funcref) (result funcref))) (type $i32_i32_externref_=>_externref (func (param i32 i32 externref) (result externref))) - (type $i32_i32_nullref_=>_nullref (func (param i32 i32 nullref) (result nullref))) (type $i32_i32_exnref_=>_exnref (func (param i32 i32 exnref) (result exnref))) (type $none_=>_none (func)) (import "env" "get_i32" (func $get_i32 (param i32 i32 i32) (result i32))) @@ -21,8 +20,6 @@ (import "env" "set_funcref" (func $set_funcref (param i32 i32 funcref) (result funcref))) (import "env" "get_externref" (func $get_externref (param i32 i32 externref) (result externref))) (import "env" "set_externref" (func $set_externref (param i32 i32 externref) (result externref))) - (import "env" "get_nullref" (func $get_nullref (param i32 i32 nullref) (result nullref))) - (import "env" "set_nullref" (func $set_nullref (param i32 i32 nullref) (result nullref))) (import "env" "get_exnref" (func $get_exnref (param i32 i32 exnref) (result exnref))) (import "env" "set_exnref" (func $set_exnref (param i32 i32 exnref) (result exnref))) (import "env" "get_v128" (func $get_v128 (param i32 i32 v128) (result v128))) @@ -34,7 +31,6 @@ (local $w f64) (local $F funcref) (local $X externref) - (local $N nullref) (local $E exnref) (local $S v128) (drop @@ -76,22 +72,15 @@ ) ) (drop - (call $get_nullref - (i32.const 5) - (i32.const 6) - (local.get $N) - ) - ) - (drop (call $get_exnref + (i32.const 5) (i32.const 6) - (i32.const 7) (local.get $E) ) ) (drop (call $get_i32 - (i32.const 7) + (i32.const 6) (i32.const 0) (local.get $x) ) @@ -101,49 +90,42 @@ ) (drop (call $get_f32 - (i32.const 8) + (i32.const 7) (i32.const 2) (local.get $z) ) ) (drop (call $get_f64 - (i32.const 9) + (i32.const 8) (i32.const 3) (local.get $w) ) ) (drop (call $get_funcref - (i32.const 10) + (i32.const 9) (i32.const 4) (local.get $F) ) ) (drop (call $get_externref - (i32.const 11) + (i32.const 10) (i32.const 5) (local.get $X) ) ) (drop - (call $get_nullref - (i32.const 12) - (i32.const 6) - (local.get $N) - ) - ) - (drop (call $get_exnref - (i32.const 13) - (i32.const 7) + (i32.const 11) + (i32.const 6) (local.get $E) ) ) (local.set $x (call $set_i32 - (i32.const 14) + (i32.const 12) (i32.const 0) (i32.const 1) ) @@ -153,57 +135,50 @@ ) (local.set $z (call $set_f32 - (i32.const 15) + (i32.const 13) (i32.const 2) (f32.const 3.2100000381469727) ) ) (local.set $w (call $set_f64 - (i32.const 16) + (i32.const 14) (i32.const 3) (f64.const 4.321) ) ) (local.set $F (call $set_funcref - (i32.const 17) + (i32.const 15) (i32.const 4) (ref.func $test) ) ) (local.set $X (call $set_externref - (i32.const 19) + (i32.const 17) (i32.const 5) (call $get_externref - (i32.const 18) + (i32.const 16) (i32.const 5) (local.get $X) ) ) ) - (local.set $N - (call $set_nullref - (i32.const 20) - (i32.const 6) - (ref.null) - ) - ) (local.set $E (call $set_exnref - (i32.const 22) - (i32.const 7) + (i32.const 19) + (i32.const 6) (call $get_exnref - (i32.const 21) - (i32.const 7) + (i32.const 18) + (i32.const 6) (local.get $E) ) ) ) (local.set $x (call $set_i32 - (i32.const 23) + (i32.const 20) (i32.const 0) (i32.const 11) ) @@ -213,24 +188,24 @@ ) (local.set $z (call $set_f32 - (i32.const 24) + (i32.const 21) (i32.const 2) (f32.const 33.209999084472656) ) ) (local.set $w (call $set_f64 - (i32.const 25) + (i32.const 22) (i32.const 3) (f64.const 44.321) ) ) (local.set $F (call $set_funcref - (i32.const 27) + (i32.const 24) (i32.const 4) (call $get_funcref - (i32.const 26) + (i32.const 23) (i32.const 4) (local.get $F) ) @@ -238,33 +213,22 @@ ) (local.set $X (call $set_externref - (i32.const 29) + (i32.const 26) (i32.const 5) (call $get_externref - (i32.const 28) + (i32.const 25) (i32.const 5) (local.get $X) ) ) ) - (local.set $N - (call $set_nullref - (i32.const 31) - (i32.const 6) - (call $get_nullref - (i32.const 30) - (i32.const 6) - (local.get $N) - ) - ) - ) (local.set $E (call $set_exnref - (i32.const 33) - (i32.const 7) + (i32.const 28) + (i32.const 6) (call $get_exnref - (i32.const 32) - (i32.const 7) + (i32.const 27) + (i32.const 6) (local.get $E) ) ) @@ -275,23 +239,20 @@ (local.set $X (externref.pop) ) - (local.set $N - (nullref.pop) - ) (local.set $E (exnref.pop) ) (drop (call $get_v128 - (i32.const 34) - (i32.const 8) + (i32.const 29) + (i32.const 7) (local.get $S) ) ) (local.set $S (call $set_v128 - (i32.const 35) - (i32.const 8) + (i32.const 30) + (i32.const 7) (v128.const i32x4 0x00000000 0x00000001 0x00000002 0x00000003) ) ) diff --git a/test/passes/instrument-locals_all-features.wast b/test/passes/instrument-locals_all-features.wast index 5640b1661..2110ce7db 100644 --- a/test/passes/instrument-locals_all-features.wast +++ b/test/passes/instrument-locals_all-features.wast @@ -6,7 +6,6 @@ (local $w f64) (local $F funcref) (local $X externref) - (local $N nullref) (local $E exnref) (local $S v128) @@ -16,7 +15,6 @@ (drop (local.get $w)) (drop (local.get $F)) (drop (local.get $X)) - (drop (local.get $N)) (drop (local.get $E)) (drop (local.get $x)) @@ -25,7 +23,6 @@ (drop (local.get $w)) (drop (local.get $F)) (drop (local.get $X)) - (drop (local.get $N)) (drop (local.get $E)) (local.set $x (i32.const 1)) @@ -34,7 +31,6 @@ (local.set $w (f64.const 4.321)) (local.set $F (ref.func $test)) (local.set $X (local.get $X)) - (local.set $N (ref.null)) (local.set $E (local.get $E)) (local.set $x (i32.const 11)) @@ -43,13 +39,11 @@ (local.set $w (f64.const 44.321)) (local.set $F (local.get $F)) (local.set $X (local.get $X)) - (local.set $N (local.get $N)) (local.set $E (local.get $E)) ;; Pop instructions should not be instrumented (local.set $F (funcref.pop)) (local.set $X (externref.pop)) - (local.set $N (nullref.pop)) (local.set $E (exnref.pop)) ;; Add new instructions here so expected output doesn't change too much, it diff --git a/test/passes/merge-locals_all-features.txt b/test/passes/merge-locals_all-features.txt index e4d325695..15039b4ce 100644 --- a/test/passes/merge-locals_all-features.txt +++ b/test/passes/merge-locals_all-features.txt @@ -1,7 +1,6 @@ (module (type $i32_i32_=>_none (func (param i32 i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (type $none_=>_none (func)) (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) (type $i32_f32_f32_=>_i64 (func (param i32 f32 f32) (result i64))) (global $global$0 (mut i32) (i32.const 10)) @@ -457,15 +456,4 @@ ) ) ) - (func $subtype-test - (local $0 externref) - (local $1 nullref) - (local $2 nullref) - (local.set $0 - (local.get $1) - ) - (local.set $2 - (local.get $1) - ) - ) ) diff --git a/test/passes/merge-locals_all-features.wast b/test/passes/merge-locals_all-features.wast index 2a0a3d292..c12a02426 100644 --- a/test/passes/merge-locals_all-features.wast +++ b/test/passes/merge-locals_all-features.wast @@ -375,17 +375,18 @@ ) ) ) - (func $subtype-test - (local $0 externref) - (local $1 nullref) - (local $2 nullref) - (local.set $0 - (local.get $1) - ) - (local.set $2 - ;; This should NOT become $0, because types of $0 and $1 are different - (local.get $1) - ) - ) + ;; TODO (GC) + ;; (func $subtype-test + ;; (local $0 anyref) + ;; (local $1 funcref) + ;; (local $2 funcref) + ;; (local.set $0 + ;; (local.get $1) + ;; ) + ;; (local.set $2 + ;; ;; This should NOT become $0, because types of $0 and $1 are different + ;; (local.get $1) + ;; ) + ;; ) ) diff --git a/test/passes/optimize-instructions_all-features.txt b/test/passes/optimize-instructions_all-features.txt index 2aaba9071..5677624cb 100644 --- a/test/passes/optimize-instructions_all-features.txt +++ b/test/passes/optimize-instructions_all-features.txt @@ -14,7 +14,6 @@ (type $i32_i32_f64_f64_=>_none (func (param i32 i32 f64 f64))) (type $i32_i64_f64_i32_=>_none (func (param i32 i64 f64 i32))) (type $none_=>_f64 (func (result f64))) - (type $none_=>_externref (func (result externref))) (memory $0 0) (export "load-off-2" (func $load-off-2)) (func $f (param $i1 i32) (param $i2 i64) @@ -3712,9 +3711,6 @@ (unreachable) ) ) - (func $if-arms-subtype (result externref) - (ref.null) - ) (func $optimize-boolean-context (param $x i32) (param $y i32) (if (local.get $x) diff --git a/test/passes/optimize-instructions_all-features.wast b/test/passes/optimize-instructions_all-features.wast index e336ac2f9..37d0d7618 100644 --- a/test/passes/optimize-instructions_all-features.wast +++ b/test/passes/optimize-instructions_all-features.wast @@ -4207,14 +4207,15 @@ (unreachable) ) ) + ;; TODO (GC) ;; Tests when if arms are subtype of if's type - (func $if-arms-subtype (result externref) - (if (result externref) - (i32.const 0) - (ref.null) - (ref.null) - ) - ) + ;; (func $if-arms-subtype (result anyref) + ;; (if (result anyref) + ;; (i32.const 0) + ;; (ref.null extern) + ;; (ref.null func) + ;; ) + ;; ) (func $optimize-boolean-context (param $x i32) (param $y i32) ;; 0 - x ==> x (if diff --git a/test/passes/precompute_all-features.txt b/test/passes/precompute_all-features.txt index 4253d3c42..89f40adf5 100644 --- a/test/passes/precompute_all-features.txt +++ b/test/passes/precompute_all-features.txt @@ -5,7 +5,7 @@ (type $none_=>_v128 (func (result v128))) (type $i32_=>_none (func (param i32))) (type $none_=>_i32_i64 (func (result i32 i64))) - (type $none_=>_nullref (func (result nullref))) + (type $none_=>_externref (func (result externref))) (memory $0 512 512) (data (i32.const 0) "passive") (global $global i32 (i32.const 1)) @@ -262,8 +262,8 @@ (func $loop-precompute (result i32) (i32.const 1) ) - (func $reftype-test (result nullref) - (ref.null) + (func $reftype-test (result externref) + (ref.null extern) ) (func $dummy (nop) @@ -285,18 +285,18 @@ ) ) (drop - (block $l2 (result nullref) + (block $l2 (result externref) (drop (block $l3 (global.set $global-mut (i32.const 1) ) (br $l2 - (ref.null) + (ref.null extern) ) ) ) - (ref.null) + (ref.null extern) ) ) (drop @@ -311,7 +311,7 @@ ) ) ) - (ref.null) + (ref.null func) ) ) ) diff --git a/test/passes/precompute_all-features.wast b/test/passes/precompute_all-features.wast index 343b01ff1..ca849b88c 100644 --- a/test/passes/precompute_all-features.wast +++ b/test/passes/precompute_all-features.wast @@ -385,13 +385,13 @@ ) ;; Check if Precompute pass does not crash on reference types - (func $reftype-test (result nullref) - (ref.null) + (func $reftype-test (result externref) + (ref.null extern) ) ;; Check if constant nodes (const, ref.null, and ref.func) are correctly ;; reused. (We shouldn't reuse a const node for something like ref.null, which - ;; will incorrectly cause an expression like 'nullref.const'.) + ;; will incorrectly cause an expression like 'someref.const'.) (func $dummy) (func $br_reuse_node (drop @@ -418,7 +418,7 @@ ) (drop - (block $l2 (result nullref) + (block $l2 (result externref) (drop (block $l3 (result i32) (global.set $global-mut @@ -428,14 +428,14 @@ (i32.const 1) (ref.is_null (br_if $l2 - (ref.null) + (ref.null extern) (i32.const 3) ) ) ) ) ) - (ref.null) + (ref.null extern) ) ) @@ -457,7 +457,7 @@ ) ) ) - (ref.null) + (ref.null func) ) ) ) @@ -469,7 +469,7 @@ (block $label$1 (drop (br_on_exn $label$1 $event$0 - (loop $label$2 (result nullref) + (loop $label$2 (result exnref) (br $label$2) ) ) diff --git a/test/passes/remove-unused-names_code-folding_all-features.txt b/test/passes/remove-unused-names_code-folding_all-features.txt index 1cb02c26e..946545144 100644 --- a/test/passes/remove-unused-names_code-folding_all-features.txt +++ b/test/passes/remove-unused-names_code-folding_all-features.txt @@ -1799,7 +1799,7 @@ (call $foo) (call $foo) (return - (ref.null) + (ref.null exn) ) ) (catch @@ -1811,11 +1811,11 @@ (call $foo) (call $foo) (return - (ref.null) + (ref.null exn) ) ) ) - (ref.null) + (ref.null exn) ) (func $try-call-optimize-expression-tails (local $exn exnref) diff --git a/test/passes/remove-unused-names_code-folding_all-features.wast b/test/passes/remove-unused-names_code-folding_all-features.wast index ab5f222ca..b982a10fb 100644 --- a/test/passes/remove-unused-names_code-folding_all-features.wast +++ b/test/passes/remove-unused-names_code-folding_all-features.wast @@ -1254,7 +1254,7 @@ (call $foo) (call $foo) (call $foo) - (return (ref.null)) + (return (ref.null exn)) ) (catch (drop (exnref.pop)) @@ -1262,10 +1262,10 @@ (call $foo) (call $foo) (call $foo) - (return (ref.null)) + (return (ref.null exn)) ) ) - (ref.null) + (ref.null exn) ) (func $try-call-optimize-expression-tails (local $exn exnref) diff --git a/test/passes/simplify-globals_all-features.txt b/test/passes/simplify-globals_all-features.txt index dc766683e..ace056aac 100644 --- a/test/passes/simplify-globals_all-features.txt +++ b/test/passes/simplify-globals_all-features.txt @@ -215,7 +215,7 @@ (type $none_=>_none (func)) (import "env" "global-1" (global $g1 externref)) (global $g2 externref (global.get $g1)) - (global $g3 externref (ref.null)) + (global $g3 externref (ref.null extern)) (func $test1 (drop (global.get $g1) @@ -226,7 +226,7 @@ ) (func $test2 (drop - (ref.null) + (ref.null extern) ) ) ) diff --git a/test/passes/simplify-globals_all-features.wast b/test/passes/simplify-globals_all-features.wast index 3c7c61a9f..83c23bae5 100644 --- a/test/passes/simplify-globals_all-features.wast +++ b/test/passes/simplify-globals_all-features.wast @@ -130,7 +130,7 @@ (module (import "env" "global-1" (global $g1 externref)) (global $g2 (mut externref) (global.get $g1)) - (global $g3 externref (ref.null)) + (global $g3 externref (ref.null extern)) (func $test1 (drop (global.get $g1)) (drop (global.get $g2)) diff --git a/test/passes/simplify-locals_all-features.txt b/test/passes/simplify-locals_all-features.txt index 34efb8726..f461a7580 100644 --- a/test/passes/simplify-locals_all-features.txt +++ b/test/passes/simplify-locals_all-features.txt @@ -1882,19 +1882,6 @@ ) ) (module - (type $none_=>_funcref (func (result funcref))) - (func $subtype-test (result funcref) - (local $0 nullref) - (local $1 funcref) - (local $2 funcref) - (block $block - (nop) - ) - (nop) - (local.get $0) - ) -) -(module (type $none_=>_none (func)) (type $i32_exnref_=>_none (func (param i32 exnref))) (type $exnref_=>_none (func (param exnref))) @@ -1907,7 +1894,7 @@ (block $label$0 (local.set $0 (br_on_exn $label$0 $event$0 - (ref.null) + (ref.null exn) ) ) ) @@ -1918,7 +1905,7 @@ (drop (block $label$1 (result exnref) (br_on_exn $label$1 $event$1 - (ref.null) + (ref.null exn) ) ) ) @@ -1930,7 +1917,7 @@ (try (do (rethrow - (ref.null) + (ref.null exn) ) ) (catch @@ -1973,7 +1960,7 @@ (i32.const 3) (try (result exnref) (do - (ref.null) + (ref.null exn) ) (catch (exnref.pop) diff --git a/test/passes/simplify-locals_all-features.wast b/test/passes/simplify-locals_all-features.wast index 3edffca7e..b32da3df8 100644 --- a/test/passes/simplify-locals_all-features.wast +++ b/test/passes/simplify-locals_all-features.wast @@ -1655,22 +1655,23 @@ ) ) ) -(module - (func $subtype-test (result funcref) - (local $0 nullref) - (local $1 funcref) - (local $2 funcref) - (block - (local.set $1 - (local.get $0) - ) - ) - (local.set $2 - (local.get $1) - ) - (local.get $1) - ) -) +;; TODO (GC) +;; (module +;; (func $subtype-test (result anyref) +;; (local $0 anyref) +;; (local $1 externref) +;; (local $2 externref) +;; (block +;; (local.set $1 +;; (local.get $0) +;; ) +;; ) +;; (local.set $2 +;; (local.get $1) +;; ) +;; (local.get $1) +;; ) +;; ) (module (event $event$0 (attr 0) (param)) (func $unoptimizable-br_on_exn-block (result exnref) (local $0 exnref) @@ -1678,7 +1679,7 @@ (local.set $0 ;; br_on_exn's target block cannot be optimized to have a return value (br_on_exn $label$0 $event$0 - (ref.null) + (ref.null exn) ) ) ) @@ -1692,7 +1693,7 @@ (local.set $0 (block $label$1 (result exnref) (br_on_exn $label$1 $event$1 - (ref.null) + (ref.null exn) ) ) ) @@ -1704,7 +1705,7 @@ (local.set $0 (block $label$1 (result i32) (try - (do (rethrow (ref.null))) + (do (rethrow (ref.null exn))) (catch) ) (i32.const 0) @@ -1738,7 +1739,7 @@ ;; try-catch, so it is OK. (local.set $0 (try (result exnref) - (do (ref.null)) + (do (ref.null exn)) (catch (exnref.pop)) ) ) diff --git a/test/passes/simplify-locals_all-features_disable-exception-handling.txt b/test/passes/simplify-locals_all-features_disable-exception-handling.txt index 0d035234b..b01941639 100644 --- a/test/passes/simplify-locals_all-features_disable-exception-handling.txt +++ b/test/passes/simplify-locals_all-features_disable-exception-handling.txt @@ -1875,16 +1875,3 @@ ) ) ) -(module - (type $none_=>_funcref (func (result funcref))) - (func $subtype-test (result funcref) - (local $0 nullref) - (local $1 funcref) - (local $2 funcref) - (block $block - (nop) - ) - (nop) - (local.get $0) - ) -) diff --git a/test/passes/simplify-locals_all-features_disable-exception-handling.wast b/test/passes/simplify-locals_all-features_disable-exception-handling.wast index a819dda15..c0f279cd0 100644 --- a/test/passes/simplify-locals_all-features_disable-exception-handling.wast +++ b/test/passes/simplify-locals_all-features_disable-exception-handling.wast @@ -1655,19 +1655,20 @@ ) ) ) -(module - (func $subtype-test (result funcref) - (local $0 nullref) - (local $1 funcref) - (local $2 funcref) - (block - (local.set $1 - (local.get $0) - ) - ) - (local.set $2 - (local.get $1) - ) - (local.get $1) - ) -) +;; TODO (GC) +;; (module +;; (func $subtype-test (result anyref) +;; (local $0 funcref) +;; (local $1 anyref) +;; (local $2 anyref) +;; (block +;; (local.set $1 +;; (local.get $0) +;; ) +;; ) +;; (local.set $2 +;; (local.get $1) +;; ) +;; (local.get $1) +;; ) +;; ) diff --git a/test/passes/strip-target-features_roundtrip_print-features_all-features.txt b/test/passes/strip-target-features_roundtrip_print-features_all-features.txt index e6ff57ce1..d54c7bb4e 100644 --- a/test/passes/strip-target-features_roundtrip_print-features_all-features.txt +++ b/test/passes/strip-target-features_roundtrip_print-features_all-features.txt @@ -13,7 +13,7 @@ (func $foo (result v128 externref) (tuple.make (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000) - (ref.null) + (ref.null extern) ) ) (func $bar (result v128 externref) diff --git a/test/passes/strip-target-features_roundtrip_print-features_all-features.wast b/test/passes/strip-target-features_roundtrip_print-features_all-features.wast index 614804f9d..f073de7a4 100644 --- a/test/passes/strip-target-features_roundtrip_print-features_all-features.wast +++ b/test/passes/strip-target-features_roundtrip_print-features_all-features.wast @@ -5,7 +5,7 @@ (func $foo (result v128 externref ) (tuple.make (v128.const i32x4 0 0 0 0) - (ref.null) + (ref.null extern) ) ) (func $bar (result v128 externref) diff --git a/test/passes/translate-to-fuzz_all-features.txt b/test/passes/translate-to-fuzz_all-features.txt index 5cfe2bc41..ab9a5b946 100644 --- a/test/passes/translate-to-fuzz_all-features.txt +++ b/test/passes/translate-to-fuzz_all-features.txt @@ -1,54 +1,53 @@ (module (type $none_=>_none (func)) - (type $f32_=>_none (func (param f32))) - (type $nullref_=>_none (func (param nullref))) - (type $none_=>_externref_exnref_exnref_exnref (func (result externref exnref exnref exnref))) - (type $none_=>_exnref (func (result exnref))) (type $i32_=>_none (func (param i32))) + (type $none_=>_funcref_exnref_i32_externref (func (result funcref exnref i32 externref))) + (type $i32_funcref_f64_v128_i32_=>_none (func (param i32 funcref f64 v128 i32))) (type $i64_=>_none (func (param i64))) + (type $f32_=>_none (func (param f32))) (type $f64_=>_none (func (param f64))) - (type $f64_i32_i64_f64_v128_=>_none (func (param f64 i32 i64 f64 v128))) (type $v128_=>_none (func (param v128))) (type $exnref_=>_none (func (param exnref))) (type $none_=>_i32 (func (result i32))) - (type $funcref_f64_f32_v128_exnref_f32_=>_i64 (func (param funcref f64 f32 v128 exnref f32) (result i64))) - (type $externref_externref_f32_v128_funcref_funcref_=>_v128 (func (param externref externref f32 v128 funcref funcref) (result v128))) - (type $v128_=>_funcref (func (param v128) (result funcref))) + (type $i32_v128_f64_i32_=>_i32 (func (param i32 v128 f64 i32) (result i32))) + (type $none_=>_i64 (func (result i64))) + (type $none_=>_f32 (func (result f32))) + (type $i64_f32_=>_f64 (func (param i64 f32) (result f64))) + (type $none_=>_v128 (func (result v128))) + (type $none_=>_funcref (func (result funcref))) (import "fuzzing-support" "log-i32" (func $log-i32 (param i32))) (import "fuzzing-support" "log-i64" (func $log-i64 (param i64))) (import "fuzzing-support" "log-f32" (func $log-f32 (param f32))) (import "fuzzing-support" "log-f64" (func $log-f64 (param f64))) (import "fuzzing-support" "log-v128" (func $log-v128 (param v128))) - (import "fuzzing-support" "log-nullref" (func $log-nullref (param nullref))) (import "fuzzing-support" "log-exnref" (func $log-exnref (param exnref))) (memory $0 (shared 1 1)) (data (i32.const 0) "N\0fN\f5\f9\b1\ff\fa\eb\e5\fe\a7\ec\fb\fc\f4\a6\e4\ea\f0\ae\e3") - (table $0 2 2 funcref) - (elem (i32.const 0) $func_8 $func_12) - (global $global$5 (mut f32) (f32.const 74)) - (global $global$4 (mut nullref) (ref.null)) - (global $global$3 (mut i32) (i32.const 1263230471)) - (global $global$2 (mut i32) (i32.const -131072)) - (global $global$1 (mut (funcref nullref nullref externref exnref f64)) (tuple.make - (ref.null) - (ref.null) - (ref.null) - (ref.null) - (ref.null) - (f64.const 1.1754943508222875e-38) + (table $0 5 5 funcref) + (elem (i32.const 0) $func_9 $func_10 $func_12 $func_12 $func_14) + (global $global$5 (mut exnref) (ref.null exn)) + (global $global$4 (mut f64) (f64.const 13)) + (global $global$3 (mut f32) (f32.const 16448)) + (global $global$2 (mut (v128 i32 i32 f64 exnref exnref)) (tuple.make + (v128.const i32x4 0x4d5affff 0x055b007b 0xff830011 0xffee0040) + (i32.const -32767) + (i32.const 44) + (f64.const 1797693134862315708145274e284) + (ref.null exn) + (ref.null exn) )) + (global $global$1 (mut exnref) (ref.null exn)) (global $hangLimit (mut i32) (i32.const 10)) - (event $event$0 (attr 0) (param nullref)) - (event $event$1 (attr 0) (param f32)) + (event $event$0 (attr 0) (param i32)) (export "hashMemory" (func $hashMemory)) (export "memory" (memory $0)) - (export "func_8" (func $func_8)) - (export "func_8_invoker" (func $func_8_invoker)) - (export "func_11" (func $func_11)) + (export "func_7_invoker" (func $func_7_invoker)) + (export "func_9" (func $func_9)) + (export "func_10_invoker" (func $func_10_invoker)) (export "func_12" (func $func_12)) (export "func_12_invoker" (func $func_12_invoker)) - (export "func_14" (func $func_14)) - (export "func_15" (func $func_15)) + (export "func_16_invoker" (func $func_16_invoker)) + (export "func_19" (func $func_19)) (export "hangLimitInitializer" (func $hangLimitInitializer)) (func $hashMemory (result i32) (local $0 i32) @@ -281,17 +280,14 @@ ) (local.get $0) ) - (func $func_8 (result exnref) - (local $0 i64) - (local $1 i64) - (local $2 exnref) + (func $func_7 (param $0 i32) (param $1 v128) (param $2 f64) (param $3 i32) (result i32) (block (if (i32.eqz (global.get $hangLimit) ) (return - (ref.null) + (i32.const 4883) ) ) (global.set $hangLimit @@ -301,26 +297,65 @@ ) ) ) - (ref.null) - ) - (func $func_8_invoker - (drop - (call $func_8) + (local.tee $3 + (local.tee $0 + (local.get $3) + ) ) + ) + (func $func_7_invoker (drop - (call $func_8) + (call $func_7 + (i32.const -119) + (v128.const i32x4 0x00000000 0x40410000 0x00000000 0x3ff00000) + (f64.const 3.433897990215153e-220) + (i32.const 255) + ) ) (call $log-i32 (call $hashMemory) ) - (drop - (call $func_8) + ) + (func $func_9 (result funcref) + (local $0 i64) + (local $1 i64) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (ref.func $log-f32) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) ) - (call $log-i32 - (call $hashMemory) + (block $label$0 + (f64.store offset=22 align=2 + (i32.and + (i32.const -65535) + (i32.const 15) + ) + (f64.const 8589934593) + ) + (return + (ref.func $log-exnref) + ) ) ) - (func $func_10 (result externref exnref exnref exnref) + (func $func_10 (result funcref exnref i32 externref) + (local $0 i64) + (local $1 exnref) + (local $2 f32) + (local $3 externref) + (local $4 externref) + (local $5 f32) + (local $6 i64) (block (if (i32.eqz @@ -328,10 +363,10 @@ ) (return (tuple.make - (ref.null) - (ref.null) - (ref.null) - (ref.null) + (ref.func $func_10) + (ref.null exn) + (i32.const 0) + (ref.null extern) ) ) ) @@ -343,14 +378,22 @@ ) ) (tuple.make - (ref.null) - (ref.null) - (ref.null) - (ref.null) + (ref.func $log-v128) + (ref.null exn) + (i32.const 26155) + (ref.null extern) ) ) - (func $func_11 (param $0 f64) (param $1 i32) (param $2 i64) (param $3 f64) (param $4 v128) - (local $5 nullref) + (func $func_10_invoker + (drop + (call $func_10) + ) + (call $log-i32 + (call $hashMemory) + ) + ) + (func $func_12 + (local $0 exnref) (block (if (i32.eqz @@ -365,30 +408,56 @@ ) ) ) - (block $label$0 - (call $log-i32 - (call $hashMemory) + (call $log-i32 + (i32.const 1) + ) + ) + (func $func_12_invoker + (call $func_12) + ) + (func $func_14 (result v128) + (local $0 i32) + (local $1 f32) + (local $2 f32) + (local $3 externref) + (local $4 exnref) + (local $5 f64) + (local $6 i64) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (v128.const i32x4 0x5ea21f0a 0x52800ae0 0x002a5300 0xe4010058) + ) ) - (call $log-exnref - (ref.null) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) ) ) + (v128.const i32x4 0x1d00ff00 0x2a255500 0x01fbf800 0x0a000002) ) - (func $func_12 (param $0 funcref) (param $1 f64) (param $2 f32) (param $3 v128) (param $4 exnref) (param $5 f32) (result i64) - (local $6 nullref) - (local $7 f32) - (local $8 exnref) - (local $9 f32) - (local $10 f64) - (local $11 i64) - (local $12 i32) + (func $func_15 (result i64) + (local $0 f32) + (local $1 funcref) + (local $2 f32) + (local $3 i32) + (local $4 f32) + (local $5 v128) + (local $6 f64) + (local $7 funcref) + (local $8 externref) (block (if (i32.eqz (global.get $hangLimit) ) (return - (local.get $11) + (i64.const -2097152) ) ) (global.set $hangLimit @@ -399,55 +468,64 @@ ) ) (block $label$0 - (call $log-f32 - (f32.const -nan:0x7fffe0) - ) + (nop) (return - (local.get $11) + (i64.const -61) ) ) ) - (func $func_12_invoker - (drop - (call $func_12 - (ref.null) - (f64.const -nan:0xfffffffffffec) - (f32.const 244) - (v128.const i32x4 0x5e58601d 0x5e555c53 0xffff0001 0xffffffff) - (ref.null) - (f32.const 72) + (func $func_16 (param $0 i32) (param $1 funcref) (param $2 f64) (param $3 v128) (param $4 i32) + (local $5 (i32 f64)) + (local $6 i64) + (local $7 (i32 i64)) + (local $8 i32) + (local $9 funcref) + (local $10 f32) + (local $11 (i64 v128 f32)) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return) ) - ) - (drop - (call $func_12 - (ref.func $log-v128) - (f64.const 32) - (f32.const 18014398509481984) - (v128.const i32x4 0x367f7324 0x5f000000 0x4e80108b 0xcf000000) - (ref.null) - (f32.const -549755813888) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) ) ) - (drop - (call $func_12 - (ref.func $func_12) - (f64.const 4294967295.799) - (f32.const 1279937664) - (v128.const i32x4 0xffffffb6 0x00000000 0x4041414b 0x4478405c) - (ref.null) - (f32.const 10284) - ) + (nop) + ) + (func $func_16_invoker + (call $func_16 + (i32.const -19) + (ref.func $hashMemory) + (f64.const -2305843009213693952) + (v128.const i32x4 0x2b27212f 0x322e2366 0x0000343b 0x00000000) + (i32.const 24) + ) + (call $func_16 + (i32.const 2147483646) + (ref.null func) + (f64.const 23348) + (v128.const i32x4 0x0000007c 0x00000000 0x00000000 0xc0000000) + (i32.const 521672456) ) ) - (func $func_14 (param $0 externref) (param $1 externref) (param $2 f32) (param $3 v128) (param $4 funcref) (param $5 funcref) (result v128) - (local $6 (i64 i32 i32 i64 funcref)) + (func $func_18 (param $0 i64) (param $1 f32) (result f64) + (local $2 (f64 f64 i32)) + (local $3 i64) + (local $4 f32) + (local $5 externref) (block (if (i32.eqz (global.get $hangLimit) ) (return - (local.get $3) + (f64.const -1073741824) ) ) (global.set $hangLimit @@ -457,118 +535,168 @@ ) ) ) - (block $label$0 (result v128) - (i32.atomic.store8 offset=3 - (i32.and - (if (result i32) - (global.get $global$3) - (i32.const 15) - (i32.const 1) + (select + (f64.const 35184372088832) + (f64x2.extract_lane 0 + (v128.const i32x4 0x55800000 0x4f800000 0x3def9db2 0x4e6dcc9d) + ) + (loop $label$0 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (f64.const 4294967213) + ) ) - (i32.const 15) - ) - (i32.load offset=3 align=2 - (i32.and - (i32.const 15) - (i32.const 15) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) ) ) - ) - (local.tee $3 - (block $label$16 (result v128) - (loop $label$17 - (block - (if - (i32.eqz - (global.get $hangLimit) - ) - (return - (v128.const i32x4 0xffff0009 0xfffeffff 0x00005a18 0xffff7fff) - ) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) - ) - ) + (block (result i32) + (block $label$1 + (call_indirect (type $none_=>_none) + (i32.const 2) ) - (block - (local.set $5 - (tuple.extract 2 - (tuple.make - (f32.const 3366576023666688) - (f32.const 1897033472) - (ref.null) - (ref.func $log-exnref) - (ref.null) + (nop) + ) + (br_if $label$0 + (i32.eqz + (loop $label$2 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (f64.const 8589934591.815) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) ) ) - ) - (local.set $5 - (tuple.extract 2 - (tuple.make - (f32.const 3366576023666688) - (f32.const 1897033472) - (ref.null) - (ref.func $log-exnref) - (ref.null) + (block (result i32) + (block $label$15 + (memory.copy + (i32.and + (i32.const -8192) + (i32.const 15) + ) + (i32.and + (i8x16.extract_lane_s 1 + (v128.const i32x4 0x3329287c 0x00007fff 0x00000002 0x00002966) + ) + (i32.const 15) + ) + (i32.atomic.rmw8.add_u offset=1 + (i32.and + (i32.const -93) + (i32.const 15) + ) + (i32.const 26) + ) + ) + (br_if $label$15 + (i32.eqz + (i32.const 169416729) + ) + ) + ) + (br_if $label$2 + (i32.const 1397565735) + ) + (tuple.extract 1 + (tuple.make + (f64.const -2.2250738585072014e-308) + (i32.const -86) + ) ) ) ) - (if - (i32.eqz - (i8x16.extract_lane_u 13 - (i16x8.neg - (local.get $3) + ) + ) + (if (result i32) + (if (result i32) + (i32.const -33) + (i32.trunc_f32_s + (f32.load offset=4 align=1 + (i32.const 1347440720) + ) + ) + (i32.const -83) + ) + (block $label$12 (result i32) + (nop) + (i32.const -5) + ) + (if (result i32) + (i32.eqz + (i32.load offset=3 align=1 + (i32.and + (block $label$23 + (nop) + (return + (f64.const -1) + ) ) + (i32.const 15) ) ) - (block $label$18 - (loop $label$19 - (block - (if - (i32.eqz - (global.get $hangLimit) + ) + (block $label$13 (result i32) + (call $log-i32 + (i32.load offset=4 align=1 + (i32.and + (i32.const 2049) + (block $label$24 + (global.set $global$4 + (f64.const 3.475623083072852e-234) ) (return - (v128.const i32x4 0x2a230007 0x24000cff 0x01000405 0xe6abf412) - ) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) + (f64.const -2147483647.157) ) ) ) - (drop - (v128.const i32x4 0xffff8001 0xffffffff 0xfc000000 0xffffffff) - ) ) - (call $func_12_invoker) ) - (drop - (local.tee $0 - (local.get $1) + (block $label$14 + (call $log-i64 + (local.get $0) + ) + (nop) + ) + (f32.gt + (f32.sqrt + (local.tee $4 + (local.get $1) + ) ) + (f32.const 512.2849731445312) ) ) + (i32.const 0) ) ) - (local.get $3) ) ) ) ) - (func $func_15 (param $0 v128) (result funcref) + (func $func_19 (result f32) (block (if (i32.eqz (global.get $hangLimit) ) (return - (ref.null) + (f32.const 8589934592) ) ) (global.set $hangLimit @@ -578,88 +706,34 @@ ) ) ) - (select (result nullref) - (if (result nullref) - (loop $label$10 (result i32) - (block - (if - (i32.eqz - (global.get $hangLimit) - ) - (return - (ref.func $log-f64) - ) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) - ) - ) - ) - (block (result i32) - (block $label$11 - (i32.atomic.store8 offset=4 - (i32.and - (i32.load8_s offset=3 + (f32.load offset=4 align=2 + (i32.and + (i32.popcnt + (ref.is_null + (block $label$0 (result exnref) + (nop) + (call $log-f32 + (f32.convert_i64_s + (i32.atomic.rmw.cmpxchg offset=22 (i32.and - (i32.const 1026044209) + (block $label$1 + (atomic.fence) + (return + (f32.const -512.8049926757812) + ) + ) (i32.const 15) ) + (i64.const -28) + (i64.const -524289) ) - (i32.const 15) ) - (i32.const 0) - ) - (drop - (local.get $0) - ) - ) - (br_if $label$10 - (i32.const 128) - ) - (select - (select - (i32.const -127) - (i32.const -65537) - (i32.const -254) ) - (i32.const 102650628) - (i32.const 810034249) + (ref.null exn) ) ) ) - (ref.null) - (block $label$13 (result nullref) - (loop $label$14 - (block - (if - (i32.eqz - (global.get $hangLimit) - ) - (return - (ref.func $func_8) - ) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) - ) - ) - ) - (nop) - ) - (ref.null) - ) - ) - (ref.null) - (i32.atomic.load8_u offset=1 - (ref.is_null - (call_indirect (type $none_=>_exnref) - (i32.const 0) - ) - ) + (i32.const 15) ) ) ) diff --git a/test/reference-types.wast b/test/reference-types.wast index 8bea4e8e4..80755124e 100644 --- a/test/reference-types.wast +++ b/test/reference-types.wast @@ -1,88 +1,156 @@ -;; reftype :: externref | funcref | exnref | nullref +;; reftype :: externref | funcref | exnref -;; t <: externref for all reftypes t -;; nullref <: externref, nullref <: funcref and nullref <: exnref -;; TODO: the subtyping relationship has been removed from the current proposal -;; so it also needs to be removed from Binaryen still both in the tests but -;; also inside the validation, fuzzing, etc. -;; https://github.com/WebAssembly/reference-types/pull/87 +;; TODO (GC): the subtyping relationship has been removed from the current +;; proposal so the relevant test cases have been disabled. Once `anyref` becomes +;; enabled, these tests can be uncommented again. (module (type $sig_externref (func (param externref))) (type $sig_funcref (func (param funcref))) (type $sig_exnref (func (param exnref))) - (type $sig_nullref (func (param nullref))) + ;; (type $sig_anyref (func (param anyref))) (func $take_externref (param externref)) (func $take_funcref (param funcref)) (func $take_exnref (param exnref)) - (func $take_nullref (param nullref)) + ;; (func $take_anyref (param anyref)) (func $foo) - (table funcref (elem $take_externref $take_funcref $take_exnref $take_nullref)) + (table funcref (elem $take_externref $take_funcref $take_exnref)) ;; $take_anyref (import "env" "import_func" (func $import_func (param externref) (result funcref))) (import "env" "import_global" (global $import_global externref)) (export "export_func" (func $import_func (param externref) (result funcref))) (export "export_global" (global $import_global)) + ;; Test global initializer expressions + (global $global_externref (mut externref) (ref.null extern)) + (global $global_funcref (mut funcref) (ref.null func)) + (global $global_funcref_func (mut funcref) (ref.func $foo)) + (global $global_exnref (mut exnref) (ref.null exn)) + ;; (global $global_anyref (mut anyref) (ref.null any)) + ;; Test subtype relationship in global initializer expressions - (global $global_externref (mut externref) (ref.null)) - (global $global_funcref (mut funcref) (ref.null)) - (global $global_exnref (mut exnref) (ref.null)) - (global $global_nullref (mut nullref) (ref.null)) - (global $global_externref2 (mut externref) (ref.func $foo)) - (global $global_funcref2 (mut funcref) (ref.func $foo)) + ;; (global $global_anyref2 (mut anyref) (ref.null extern)) + ;; (global $global_anyref3 (mut anyref) (ref.null func)) + ;; (global $global_anyref4 (mut anyref) (ref.func $foo)) + ;; (global $global_anyref5 (mut anyref) (ref.null exn)) + + (func $test + (local $local_externref externref) + (local $local_funcref funcref) + (local $local_exnref exnref) + ;; (local $local_anyref anyref) - (func $test (local $local_externref externref) (local $local_funcref funcref) - (local $local_exnref exnref) (local $local_nullref nullref) - ;; Test subtype relationship for local.set & Test types for local.get + ;; Test types for local.get/set (local.set $local_externref (local.get $local_externref)) - (local.set $local_externref (local.get $local_funcref)) - (local.set $local_externref (local.get $local_exnref)) - (local.set $local_externref (local.get $local_nullref)) - (local.set $local_externref (ref.null)) - (local.set $local_externref (ref.func $foo)) + (local.set $local_externref (global.get $global_externref)) + (local.set $local_externref (ref.null extern)) (local.set $local_funcref (local.get $local_funcref)) - (local.set $local_funcref (ref.null)) + (local.set $local_funcref (global.get $global_funcref)) + (local.set $local_funcref (ref.null func)) (local.set $local_funcref (ref.func $foo)) (local.set $local_exnref (local.get $local_exnref)) - (local.set $local_exnref (ref.null)) - (local.set $local_nullref (local.get $local_nullref)) - (local.set $local_nullref (ref.null)) + (local.set $local_exnref (global.get $global_exnref)) + (local.set $local_exnref (ref.null exn)) + ;; (local.set $local_anyref (local.get $local_anyref)) + ;; (local.set $local_anyref (global.get $global_anyref)) + ;; (local.set $local_anyref (ref.null any)) - ;; Test subtype relationship for global.set & Test types for global.get + ;; Test subtype relationship for local.set + ;; (local.set $local_anyref (local.get $local_externref)) + ;; (local.set $local_anyref (global.get $global_externref)) + ;; (local.set $local_anyref (ref.null extern)) + ;; (local.set $local_anyref (local.get $local_funcref)) + ;; (local.set $local_anyref (global.get $global_funcref)) + ;; (local.set $local_anyref (ref.null func)) + ;; (local.set $local_anyref (ref.func $foo)) + ;; (local.set $local_anyref (local.get $local_exnref)) + ;; (local.set $local_anyref (global.get $global_exnref)) + ;; (local.set $local_anyref (ref.null exn)) + + ;; Test types for global.get/set (global.set $global_externref (global.get $global_externref)) - (global.set $global_externref (global.get $global_funcref)) - (global.set $global_externref (global.get $global_exnref)) - (global.set $global_externref (global.get $global_nullref)) - (global.set $global_externref (ref.null)) - (global.set $global_externref (ref.func $foo)) + (global.set $global_externref (local.get $local_externref)) + (global.set $global_externref (ref.null extern)) (global.set $global_funcref (global.get $global_funcref)) - (global.set $global_funcref (ref.null)) + (global.set $global_funcref (local.get $local_funcref)) + (global.set $global_funcref (ref.null func)) (global.set $global_funcref (ref.func $foo)) (global.set $global_exnref (global.get $global_exnref)) - (global.set $global_exnref (ref.null)) - (global.set $global_nullref (global.get $global_nullref)) - (global.set $global_nullref (ref.null)) + (global.set $global_exnref (local.get $local_exnref)) + (global.set $global_exnref (ref.null exn)) + ;; (global.set $global_anyref (global.get $global_anyref)) + ;; (global.set $global_anyref (local.get $local_anyref)) + ;; (global.set $global_anyref (ref.null any)) + + ;; Test subtype relationship for global.set + ;; (global.set $global_anyref (global.get $global_externref)) + ;; (global.set $global_anyref (local.get $local_externref)) + ;; (global.set $global_anyref (ref.null extern)) + ;; (global.set $global_anyref (global.get $global_funcref)) + ;; (global.set $global_anyref (local.get $local_funcref)) + ;; (global.set $global_anyref (ref.null func)) + ;; (global.set $global_anyref (ref.func $foo)) + ;; (global.set $global_anyref (global.get $global_exnref)) + ;; (global.set $global_anyref (local.get $local_exnref)) + ;; (global.set $global_anyref (ref.null exn)) - ;; Test subtype relationship for function call / call_indirect params + ;; Test function call params (call $take_externref (local.get $local_externref)) - (call $take_externref (local.get $local_funcref)) - (call $take_externref (local.get $local_exnref)) - (call $take_externref (ref.null)) + (call $take_externref (global.get $global_externref)) + (call $take_externref (ref.null extern)) + (call $take_funcref (local.get $local_funcref)) + (call $take_funcref (global.get $global_funcref)) + (call $take_funcref (ref.null func)) + (call $take_funcref (ref.func $foo)) + (call $take_exnref (local.get $local_exnref)) + (call $take_exnref (global.get $global_exnref)) + (call $take_exnref (ref.null exn)) + ;; (call $take_anyref (local.get $local_anyref)) + ;; (call $take_anyref (global.get $global_anyref)) + ;; (call $take_anyref (ref.null any)) + + ;; Test subtype relationship for function call params + ;; (call $take_anyref (local.get $local_externref)) + ;; (call $take_anyref (global.get $global_externref)) + ;; (call $take_anyref (ref.null extern)) + ;; (call $take_anyref (local.get $local_funcref)) + ;; (call $take_anyref (global.get $global_funcref)) + ;; (call $take_anyref (ref.null func)) + ;; (call $take_anyref (ref.func $foo)) + ;; (call $take_anyref (local.get $local_exnref)) + ;; (call $take_anyref (global.get $global_exnref)) + ;; (call $take_anyref (ref.null exn)) + + ;; Test call_indirect params (call_indirect (type $sig_externref) (local.get $local_externref) (i32.const 0)) - (call_indirect (type $sig_externref) (local.get $local_funcref) (i32.const 0)) - (call_indirect (type $sig_externref) (local.get $local_exnref) (i32.const 0)) - (call_indirect (type $sig_externref) (ref.null) (i32.const 0)) + (call_indirect (type $sig_externref) (global.get $global_externref) (i32.const 0)) + (call_indirect (type $sig_externref) (ref.null extern) (i32.const 0)) (call_indirect (type $sig_funcref) (local.get $local_funcref) (i32.const 1)) - (call_indirect (type $sig_funcref) (ref.null) (i32.const 1)) + (call_indirect (type $sig_funcref) (global.get $global_funcref) (i32.const 1)) + (call_indirect (type $sig_funcref) (ref.null func) (i32.const 1)) + (call_indirect (type $sig_funcref) (ref.func $foo) (i32.const 1)) (call_indirect (type $sig_exnref) (local.get $local_exnref) (i32.const 2)) - (call_indirect (type $sig_exnref) (ref.null) (i32.const 2)) - (call_indirect (type $sig_nullref) (local.get $local_nullref) (i32.const 3)) - (call_indirect (type $sig_nullref) (ref.null) (i32.const 3)) + (call_indirect (type $sig_exnref) (global.get $global_exnref) (i32.const 2)) + (call_indirect (type $sig_exnref) (ref.null exn) (i32.const 2)) + ;; (call_indirect (type $sig_anyref) (local.get $local_anyref) (i32.const 3)) + ;; (call_indirect (type $sig_anyref) (global.get $global_anyref) (i32.const 3)) + ;; (call_indirect (type $sig_anyref) (ref.null any) (i32.const 3)) - ;; Test subtype relationship for block return type + ;; Test subtype relationship for call_indirect params + ;; (call_indirect (type $sig_anyref) (local.get $local_externref) (i32.const 3)) + ;; (call_indirect (type $sig_anyref) (global.get $global_externref) (i32.const 3)) + ;; (call_indirect (type $sig_anyref) (ref.null extern) (i32.const 3)) + ;; (call_indirect (type $sig_anyref) (local.get $local_funcref) (i32.const 3)) + ;; (call_indirect (type $sig_anyref) (global.get $global_funcref) (i32.const 3)) + ;; (call_indirect (type $sig_anyref) (ref.null func) (i32.const 3)) + ;; (call_indirect (type $sig_anyref) (ref.func $foo) (i32.const 3)) + ;; (call_indirect (type $sig_anyref) (local.get $local_exnref) (i32.const 3) + ;; (call_indirect (type $sig_anyref) (global.get $global_exnref) (i32.const 3) + ;; (call_indirect (type $sig_anyref) (ref.null exn) (i32.const 3)) + + ;; Test block return type (drop (block (result externref) (br_if 0 (local.get $local_externref) (i32.const 1)) @@ -90,36 +158,103 @@ ) (drop (block (result externref) - (br_if 0 (local.get $local_funcref) (i32.const 1)) + (br_if 0 (global.get $global_externref) (i32.const 1)) ) ) (drop (block (result externref) - (br_if 0 (local.get $local_exnref) (i32.const 1)) + (br_if 0 (ref.null extern) (i32.const 1)) ) ) (drop - (block (result externref) - (br_if 0 (ref.null) (i32.const 1)) + (block (result funcref) + (br_if 0 (local.get $local_funcref) (i32.const 1)) + ) + ) + (drop + (block (result funcref) + (br_if 0 (global.get $global_funcref) (i32.const 1)) + ) + ) + (drop + (block (result funcref) + (br_if 0 (ref.null func) (i32.const 1)) ) ) (drop (block (result funcref) - (br_if 0 (ref.null) (i32.const 1)) + (br_if 0 (ref.func $foo) (i32.const 1)) ) ) (drop (block (result exnref) - (br_if 0 (ref.null) (i32.const 1)) + (br_if 0 (local.get $local_exnref) (i32.const 1)) ) ) (drop - (block (result nullref) - (br_if 0 (ref.null) (i32.const 1)) + (block (result exnref) + (br_if 0 (global.get $global_exnref) (i32.const 1)) ) ) + (drop + (block (result exnref) + (br_if 0 (ref.null exn) (i32.const 1)) + ) + ) + ;; (drop + ;; (block (result anyref) + ;; (br_if 0 (local.get $local_anyref) (i32.const 1)) + ;; ) + ;; ) + ;; (drop + ;; (block (result anyref) + ;; (br_if 0 (global.get $global_anyref) (i32.const 1)) + ;; ) + ;; ) + ;; (drop + ;; (block (result anyref) + ;; (br_if 0 (ref.null any) (i32.const 1)) + ;; ) + ;; ) - ;; Test subtype relationship for loop return type + ;; Test subtype relationship for block return type + ;; (drop + ;; (block (result anyref) + ;; (br_if 0 (local.get $local_externref) (i32.const 1)) + ;; ) + ;; ) + ;; (drop + ;; (block (result anyref) + ;; (br_if 0 (local.get $local_funcref) (i32.const 1)) + ;; ) + ;; ) + ;; (drop + ;; (block (result anyref) + ;; (br_if 0 (local.get $local_exnref) (i32.const 1)) + ;; ) + ;; ) + ;; (drop + ;; (block (result anyref) + ;; (br_if 0 (ref.null extern) (i32.const 1)) + ;; ) + ;; ) + ;; (drop + ;; (block (result anyref) + ;; (br_if 0 (ref.null func) (i32.const 1)) + ;; ) + ;; ) + ;; (drop + ;; (block (result anyref) + ;; (br_if 0 (ref.func $foo) (i32.const 1)) + ;; ) + ;; ) + ;; (drop + ;; (block (result anyref) + ;; (br_if 0 (ref.null exn) (i32.const 1)) + ;; ) + ;; ) + + ;; Test loop return type (drop (loop (result externref) (local.get $local_externref) @@ -127,101 +262,207 @@ ) (drop (loop (result externref) - (local.get $local_funcref) + (global.get $global_externref) ) ) (drop (loop (result externref) - (local.get $local_exnref) + (ref.null extern) ) ) (drop - (loop (result externref) - (ref.null) + (loop (result funcref) + (local.get $local_funcref) ) ) (drop (loop (result funcref) - (local.get $local_funcref) + (global.get $global_funcref) ) ) (drop (loop (result funcref) - (ref.null) + (ref.null func) ) ) (drop - (loop (result exnref) - (local.get $local_exnref) + (loop (result funcref) + (ref.func $foo) ) ) (drop (loop (result exnref) - (ref.null) + (local.get $local_exnref) ) ) (drop - (loop (result nullref) - (ref.null) + (loop (result exnref) + (global.get $global_exnref) ) ) + (drop + (loop (result exnref) + (ref.null exn) + ) + ) + ;; (drop + ;; (loop (result anyref) + ;; (local.get $local_anyref) + ;; ) + ;; ) + ;; (drop + ;; (loop (result anyref) + ;; (global.get $global_anyref) + ;; ) + ;; ) + ;; (drop + ;; (loop (result anyref) + ;; (ref.null any) + ;; ) + ;; ) - ;; Test subtype relationship for if return type + ;; Test subtype relationship for loop return type + ;; (drop + ;; (loop (result anyref) + ;; (local.get $local_externref) + ;; ) + ;; ) + ;; (drop + ;; (loop (result anyref) + ;; (global.get $global_externref) + ;; ) + ;; ) + ;; (drop + ;; (loop (result anyref) + ;; (ref.null extern) + ;; ) + ;; ) + ;; (drop + ;; (loop (result anyref) + ;; (local.get $local_funcref) + ;; ) + ;; ) + ;; (drop + ;; (loop (result anyref) + ;; (global.get $global_funcref) + ;; ) + ;; ) + ;; (drop + ;; (loop (result anyref) + ;; (ref.null func) + ;; ) + ;; ) + ;; (drop + ;; (loop (result anyref) + ;; (ref.func $foo) + ;; ) + ;; ) + ;; (drop + ;; (loop (result anyref) + ;; (local.get $local_exnref) + ;; ) + ;; ) + ;; (drop + ;; (loop (result anyref) + ;; (global.get $global_exnref) + ;; ) + ;; ) + ;; (drop + ;; (loop (result anyref) + ;; (ref.null exn) + ;; ) + ;; ) + + ;; Test if return type (drop (if (result externref) (i32.const 1) (local.get $local_externref) - (local.get $local_exnref) - ) - ) - (drop - (if (result externref) - (i32.const 1) - (ref.func $foo) - (ref.null) + (ref.null extern) ) ) (drop (if (result funcref) (i32.const 1) - (ref.func $foo) - (ref.null) + (local.get $local_funcref) + (ref.null func) ) ) (drop (if (result exnref) (i32.const 1) (local.get $local_exnref) - (ref.null) - ) - ) - (drop - (if (result nullref) - (i32.const 1) - (local.get $local_nullref) - (ref.null) + (ref.null exn) ) ) + ;; (drop + ;; (if (result anyref) + ;; (i32.const 1) + ;; (local.get $local_anyref) + ;; (ref.null any) + ;; ) + ;; ) - ;; Test subtype relationship for try return type + ;; Test subtype relationship for if return type + ;; (drop + ;; (if (result anyref) + ;; (i32.const 1) + ;; (local.get $local_externref) + ;; (local.get $local_funcref) + ;; ) + ;; ) + ;; (drop + ;; (if (result anyref) + ;; (i32.const 1) + ;; (local.get $local_externref) + ;; (local.get $local_exnref) + ;; ) + ;; ) + ;; (drop + ;; (if (result anyref) + ;; (i32.const 1) + ;; (local.get $local_funcref) + ;; (local.get $local_exnref) + ;; ) + ;; ) + ;; (drop + ;; (if (result anyref) + ;; (i32.const 1) + ;; (ref.null extern) + ;; (ref.null func) + ;; ) + ;; ) + ;; (drop + ;; (if (result anyref) + ;; (i32.const 1) + ;; (ref.null extern) + ;; (ref.null exn) + ;; ) + ;; ) + ;; (drop + ;; (if (result anyref) + ;; (i32.const 1) + ;; (ref.null func) + ;; (ref.null exn) + ;; ) + ;; ) + ;; (drop + ;; (if (result anyref) + ;; (i32.const 1) + ;; (ref.func $foo) + ;; (ref.null extern) + ;; ) + ;; ) + + ;; Test try return type (drop (try (result externref) (do (local.get $local_externref) ) (catch - (exnref.pop) - ) - ) - ) - (drop - (try (result externref) - (do - (ref.func $foo) - ) - (catch (drop (exnref.pop)) - (ref.null) + (ref.null extern) ) ) ) @@ -232,79 +473,106 @@ ) (catch (drop (exnref.pop)) - (ref.null) + (ref.null func) ) ) ) (drop (try (result exnref) (do - (ref.null) + (ref.null exn) ) (catch (exnref.pop) ) ) ) - (drop - (try (result nullref) - (do - (ref.null) - ) - (catch - (drop (exnref.pop)) - (ref.null) - ) - ) - ) - ;; Test subtype relationship for typed select - (drop - (select (result externref) - (local.get $local_externref) - (ref.func $foo) - (i32.const 1) - ) - ) - (drop - (select (result externref) - (local.get $local_exnref) - (local.get $local_externref) - (i32.const 1) - ) - ) + ;; Test subtype relationship for try return type + ;; (drop + ;; (try (result anyref) + ;; (do + ;; (local.get $local_externref) + ;; ) + ;; (catch + ;; (drop (exnref.pop)) + ;; (ref.func $foo) + ;; ) + ;; ) + ;; ) + ;; (drop + ;; (try (result anyref) + ;; (do + ;; (local.get $local_externref) + ;; ) + ;; (catch + ;; (exnref.pop) + ;; ) + ;; ) + ;; ) + ;; (drop + ;; (try (result anyref) + ;; (do + ;; (ref.func $foo) + ;; ) + ;; (catch + ;; (drop (exnref.pop)) + ;; (local.get $local_externref) + ;; ) + ;; ) + ;; ) + ;; (drop + ;; (try (result anyref) + ;; (do + ;; (ref.func $foo) + ;; ) + ;; (catch + ;; (exnref.pop) + ;; ) + ;; ) + ;; ) + ;; (drop + ;; (try (result anyref) + ;; (do + ;; (ref.null exn) + ;; ) + ;; (catch + ;; (drop (exnref.pop)) + ;; (local.get $local_externref) + ;; ) + ;; ) + ;; ) + ;; (drop + ;; (try (result anyref) + ;; (do + ;; (ref.null exn) + ;; ) + ;; (catch + ;; (drop (exnref.pop)) + ;; (ref.func $foo) + ;; ) + ;; ) + ;; ) + + ;; Test typed select (drop (select (result externref) (local.get $local_externref) - (ref.null) - (i32.const 1) - ) - ) - (drop - (select (result externref) - (ref.null) - (ref.func $foo) + (ref.null extern) (i32.const 1) ) ) (drop (select (result funcref) - (ref.func $foo) - (ref.null) + (local.get $local_funcref) + (ref.null func) (i32.const 1) ) ) (drop (select (result exnref) - (ref.null) (local.get $local_exnref) - (i32.const 1) - ) - ) - (drop - (select (result nullref) - (ref.null) - (ref.null) + (ref.null exn) (i32.const 1) ) ) @@ -316,60 +584,187 @@ ) ) + ;; Test subtype relationship for typed select + ;; (drop + ;; (select (result anyref) + ;; (local.get $local_externref) + ;; (local.get $local_funcref) + ;; (i32.const 1) + ;; ) + ;; ) + ;; (drop + ;; (select (result anyref) + ;; (local.get $local_externref) + ;; (local.get $local_exnref) + ;; (i32.const 1) + ;; ) + ;; ) + ;; (drop + ;; (select (result anyref) + ;; (local.get $local_funcref) + ;; (local.get $local_externref) + ;; (i32.const 1) + ;; ) + ;; ) + ;; (drop + ;; (select (result anyref) + ;; (local.get $local_funcref) + ;; (local.get $local_exnref) + ;; (i32.const 1) + ;; ) + ;; ) + ;; (drop + ;; (select (result anyref) + ;; (local.get $local_exnref) + ;; (local.get $local_externref) + ;; (i32.const 1) + ;; ) + ;; ) + ;; (drop + ;; (select (result anyref) + ;; (local.get $local_exnref) + ;; (local.get $local_funcref) + ;; (i32.const 1) + ;; ) + ;; ) + ;; ref.is_null takes any reference types (drop (ref.is_null (local.get $local_externref))) - (drop (ref.is_null (local.get $local_exnref))) + (drop (ref.is_null (global.get $global_externref))) + (drop (ref.is_null (ref.null extern))) + (drop (ref.is_null (local.get $local_funcref))) + (drop (ref.is_null (global.get $global_funcref))) + (drop (ref.is_null (ref.null func))) (drop (ref.is_null (ref.func $foo))) - (drop (ref.is_null (ref.null))) + (drop (ref.is_null (local.get $local_exnref))) + (drop (ref.is_null (global.get $global_exnref))) + (drop (ref.is_null (ref.null exn))) + ;; (drop (ref.is_null (local.get $local_anyref))) + ;; (drop (ref.is_null (global.get $global_anyref))) + ;; (drop (ref.is_null (ref.null any))) ) - ;; Test subtype relationship in function return type - (func $return_externref (result externref) (local $local_externref externref) + ;; Test function return type + (func $return_externref_local (result externref) + (local $local_externref externref) (local.get $local_externref) ) - (func $return_externref2 (result externref) - (ref.func $foo) + (func $return_externref_global (result externref) + (global.get $global_externref) ) - (func $return_externref3 (result externref) (local $local_exnref exnref) - (local.get $local_exnref) + (func $return_externref_null (result externref) + (ref.null extern) ) - (func $return_externref4 (result externref) - (ref.null) + (func $return_funcref_local (result funcref) + (local $local_funcref funcref) + (local.get $local_funcref) ) - (func $return_funcref (result funcref) - (ref.func $foo) + (func $return_funcref_global (result funcref) + (global.get $global_funcref) + ) + (func $return_funcref_null (result funcref) + (ref.null func) ) - (func $return_funcref2 (result funcref) - (ref.null) + (func $return_funcref_func (result funcref) + (ref.func $foo) ) - (func $return_exnref (result exnref) (local $local_exnref exnref) + (func $return_exnref_local (result exnref) + (local $local_exnref exnref) (local.get $local_exnref) ) - (func $return_exnref2 (result exnref) - (ref.null) + (func $return_exnref_global (result exnref) + (global.get $global_exnref) ) - (func $return_nullref (result nullref) (local $local_nullref nullref) - (local.get $local_nullref) + (func $return_exnref_null (result exnref) + (ref.null exn) ) + ;; (func $return_anyref_local (result anyref) + ;; (local $local_anyref anyref) + ;; (local.get $local_anyref) + ;; ) + ;; (func $return_anyref_global (result anyref) + ;; (global.get $global_anyref) + ;; ) + ;; (func $return_anyref_null (result anyref) + ;; (ref.null any) + ;; ) - ;; Test subtype relationship in returns - (func $return_externref_returns (result externref) (local $local_externref externref) - (local $local_exnref exnref) + ;; Test subtype relationship in function return type + ;; (func $return_anyref2 (result anyref) + ;; (local $local_externref externref) + ;; (local.get $local_externref) + ;; ) + ;; (func $return_anyref3 (result anyref) + ;; (global.get $global_externref) + ;; ) + ;; (func $return_anyref4 (result anyref) + ;; (ref.null extern) + ;; ) + ;; (func $return_anyref5 (result anyref) + ;; (local $local_funcref funcref) + ;; (local.get $local_funcref) + ;; ) + ;; (func $return_anyref6 (result anyref) + ;; (global.get $global_funcref) + ;; ) + ;; (func $return_anyref7 (result anyref) + ;; (ref.null func) + ;; ) + ;; (func $return_anyref8 (result anyref) + ;; (ref.func $foo) + ;; ) + ;; (func $return_anyref9 (result anyref) + ;; (local $local_exnnref exnref) + ;; (local.get $local_exnref) + ;; ) + ;; (func $return_anyref10 (result anyref) + ;; (global.get $global_exnref) + ;; ) + ;; (func $return_anyref11 (result anyref) + ;; (ref.null exn) + ;; ) + + ;; Test returns + (func $returns_externref (result externref) + (local $local_externref externref) (return (local.get $local_externref)) - (return (local.get $local_exnref)) - (return (ref.func $foo)) - (return (ref.null)) + (return (global.get $global_externref)) + (return (ref.null extern)) ) - (func $return_funcref_returns (result funcref) + (func $returns_funcref (result funcref) + (local $local_funcref funcref) + (return (local.get $local_funcref)) + (return (global.get $global_funcref)) (return (ref.func $foo)) - (return (ref.null)) + (return (ref.null func)) ) - (func $return_exnref_returns (result exnref) (local $local_exnref exnref) + (func $returns_exnref (result exnref) + (local $local_exnref exnref) (return (local.get $local_exnref)) - (return (ref.null)) - ) - (func $return_nullref_returns (result nullref) (local $local_nullref nullref) - (return (local.get $local_nullref)) - (return (ref.null)) + (return (global.get $global_exnref)) + (return (ref.null exn)) ) + ;; (func $returns_anyref (result anyref) + ;; (local $local_anyref anyref) + ;; (return (local.get $local_anyref)) + ;; (return (global.get $global_anyref)) + ;; (return (ref.null any)) + ;; ) + + ;; Test subtype relationship in returns + ;; (func $returns_anyref2 (result anyref) + ;; (local $local_externref externref) + ;; (local $local_funcref funcref) + ;; (local $local_exnref exnref) + ;; (return (local.get $local_externref)) + ;; (return (global.get $global_externref)) + ;; (return (ref.null extern)) + ;; (return (local.get $local_funcref)) + ;; (return (global.get $global_funcref)) + ;; (return (ref.func $foo)) + ;; (return (ref.null func)) + ;; (return (local.get $local_exnref)) + ;; (return (global.get $global_exnref)) + ;; (return (ref.null exn)) + ;; ) ) diff --git a/test/reference-types.wast.from-wast b/test/reference-types.wast.from-wast index 3916606c0..ac9660531 100644 --- a/test/reference-types.wast.from-wast +++ b/test/reference-types.wast.from-wast @@ -1,24 +1,20 @@ (module - (type $externref_=>_none (func (param externref))) - (type $none_=>_externref (func (result externref))) (type $funcref_=>_none (func (param funcref))) - (type $nullref_=>_none (func (param nullref))) - (type $exnref_=>_none (func (param exnref))) (type $none_=>_funcref (func (result funcref))) + (type $externref_=>_none (func (param externref))) + (type $exnref_=>_none (func (param exnref))) + (type $none_=>_externref (func (result externref))) (type $none_=>_exnref (func (result exnref))) (type $none_=>_none (func)) - (type $none_=>_nullref (func (result nullref))) (type $externref_=>_funcref (func (param externref) (result funcref))) (import "env" "import_global" (global $import_global externref)) (import "env" "import_func" (func $import_func (param externref) (result funcref))) - (table $0 4 4 funcref) - (elem (i32.const 0) $take_externref $take_funcref $take_exnref $take_nullref) - (global $global_externref (mut externref) (ref.null)) - (global $global_funcref (mut funcref) (ref.null)) - (global $global_exnref (mut exnref) (ref.null)) - (global $global_nullref (mut nullref) (ref.null)) - (global $global_externref2 (mut externref) (ref.func $foo)) - (global $global_funcref2 (mut funcref) (ref.func $foo)) + (table $0 3 3 funcref) + (elem (i32.const 0) $take_externref $take_funcref $take_exnref) + (global $global_externref (mut externref) (ref.null extern)) + (global $global_funcref (mut funcref) (ref.null func)) + (global $global_funcref_func (mut funcref) (ref.func $foo)) + (global $global_exnref (mut exnref) (ref.null exn)) (export "export_func" (func $import_func)) (export "export_global" (global $import_global)) (func $take_externref (param $0 externref) @@ -30,9 +26,6 @@ (func $take_exnref (param $0 exnref) (nop) ) - (func $take_nullref (param $0 nullref) - (nop) - ) (func $foo (nop) ) @@ -40,30 +33,23 @@ (local $local_externref externref) (local $local_funcref funcref) (local $local_exnref exnref) - (local $local_nullref nullref) (local.set $local_externref (local.get $local_externref) ) (local.set $local_externref - (local.get $local_funcref) - ) - (local.set $local_externref - (local.get $local_exnref) - ) - (local.set $local_externref - (local.get $local_nullref) - ) - (local.set $local_externref - (ref.null) + (global.get $global_externref) ) (local.set $local_externref - (ref.func $foo) + (ref.null extern) ) (local.set $local_funcref (local.get $local_funcref) ) (local.set $local_funcref - (ref.null) + (global.get $global_funcref) + ) + (local.set $local_funcref + (ref.null func) ) (local.set $local_funcref (ref.func $foo) @@ -72,37 +58,28 @@ (local.get $local_exnref) ) (local.set $local_exnref - (ref.null) - ) - (local.set $local_nullref - (local.get $local_nullref) + (global.get $global_exnref) ) - (local.set $local_nullref - (ref.null) + (local.set $local_exnref + (ref.null exn) ) (global.set $global_externref (global.get $global_externref) ) (global.set $global_externref - (global.get $global_funcref) - ) - (global.set $global_externref - (global.get $global_exnref) - ) - (global.set $global_externref - (global.get $global_nullref) - ) - (global.set $global_externref - (ref.null) + (local.get $local_externref) ) (global.set $global_externref - (ref.func $foo) + (ref.null extern) ) (global.set $global_funcref (global.get $global_funcref) ) (global.set $global_funcref - (ref.null) + (local.get $local_funcref) + ) + (global.set $global_funcref + (ref.null func) ) (global.set $global_funcref (ref.func $foo) @@ -111,40 +88,51 @@ (global.get $global_exnref) ) (global.set $global_exnref - (ref.null) - ) - (global.set $global_nullref - (global.get $global_nullref) + (local.get $local_exnref) ) - (global.set $global_nullref - (ref.null) + (global.set $global_exnref + (ref.null exn) ) (call $take_externref (local.get $local_externref) ) (call $take_externref - (local.get $local_funcref) + (global.get $global_externref) ) (call $take_externref + (ref.null extern) + ) + (call $take_funcref + (local.get $local_funcref) + ) + (call $take_funcref + (global.get $global_funcref) + ) + (call $take_funcref + (ref.null func) + ) + (call $take_funcref + (ref.func $foo) + ) + (call $take_exnref (local.get $local_exnref) ) - (call $take_externref - (ref.null) + (call $take_exnref + (global.get $global_exnref) ) - (call_indirect (type $externref_=>_none) - (local.get $local_externref) - (i32.const 0) + (call $take_exnref + (ref.null exn) ) (call_indirect (type $externref_=>_none) - (local.get $local_funcref) + (local.get $local_externref) (i32.const 0) ) (call_indirect (type $externref_=>_none) - (local.get $local_exnref) + (global.get $global_externref) (i32.const 0) ) (call_indirect (type $externref_=>_none) - (ref.null) + (ref.null extern) (i32.const 0) ) (call_indirect (type $funcref_=>_none) @@ -152,7 +140,15 @@ (i32.const 1) ) (call_indirect (type $funcref_=>_none) - (ref.null) + (global.get $global_funcref) + (i32.const 1) + ) + (call_indirect (type $funcref_=>_none) + (ref.null func) + (i32.const 1) + ) + (call_indirect (type $funcref_=>_none) + (ref.func $foo) (i32.const 1) ) (call_indirect (type $exnref_=>_none) @@ -160,16 +156,12 @@ (i32.const 2) ) (call_indirect (type $exnref_=>_none) - (ref.null) + (global.get $global_exnref) (i32.const 2) ) - (call_indirect (type $nullref_=>_none) - (local.get $local_nullref) - (i32.const 3) - ) - (call_indirect (type $nullref_=>_none) - (ref.null) - (i32.const 3) + (call_indirect (type $exnref_=>_none) + (ref.null exn) + (i32.const 2) ) (drop (block $block (result externref) @@ -182,7 +174,7 @@ (drop (block $block0 (result externref) (br_if $block0 - (local.get $local_funcref) + (global.get $global_externref) (i32.const 1) ) ) @@ -190,15 +182,15 @@ (drop (block $block1 (result externref) (br_if $block1 - (local.get $local_exnref) + (ref.null extern) (i32.const 1) ) ) ) (drop - (block $block2 (result externref) + (block $block2 (result funcref) (br_if $block2 - (ref.null) + (local.get $local_funcref) (i32.const 1) ) ) @@ -206,23 +198,47 @@ (drop (block $block3 (result funcref) (br_if $block3 - (ref.null) + (global.get $global_funcref) (i32.const 1) ) ) ) (drop - (block $block4 (result exnref) + (block $block4 (result funcref) (br_if $block4 - (ref.null) + (ref.null func) (i32.const 1) ) ) ) (drop - (block $block5 (result nullref) + (block $block5 (result funcref) (br_if $block5 - (ref.null) + (ref.func $foo) + (i32.const 1) + ) + ) + ) + (drop + (block $block6 (result exnref) + (br_if $block6 + (local.get $local_exnref) + (i32.const 1) + ) + ) + ) + (drop + (block $block7 (result exnref) + (br_if $block7 + (global.get $global_exnref) + (i32.const 1) + ) + ) + ) + (drop + (block $block8 (result exnref) + (br_if $block8 + (ref.null exn) (i32.const 1) ) ) @@ -233,78 +249,69 @@ ) ) (drop - (loop $loop-in6 (result externref) - (local.get $local_funcref) + (loop $loop-in9 (result externref) + (global.get $global_externref) ) ) (drop - (loop $loop-in7 (result externref) - (local.get $local_exnref) + (loop $loop-in10 (result externref) + (ref.null extern) ) ) (drop - (loop $loop-in8 (result externref) - (ref.null) + (loop $loop-in11 (result funcref) + (local.get $local_funcref) ) ) (drop - (loop $loop-in9 (result funcref) - (local.get $local_funcref) + (loop $loop-in12 (result funcref) + (global.get $global_funcref) ) ) (drop - (loop $loop-in10 (result funcref) - (ref.null) + (loop $loop-in13 (result funcref) + (ref.null func) ) ) (drop - (loop $loop-in11 (result exnref) - (local.get $local_exnref) + (loop $loop-in14 (result funcref) + (ref.func $foo) ) ) (drop - (loop $loop-in12 (result exnref) - (ref.null) + (loop $loop-in15 (result exnref) + (local.get $local_exnref) ) ) (drop - (loop $loop-in13 (result nullref) - (ref.null) + (loop $loop-in16 (result exnref) + (global.get $global_exnref) ) ) (drop - (if (result externref) - (i32.const 1) - (local.get $local_externref) - (local.get $local_exnref) + (loop $loop-in17 (result exnref) + (ref.null exn) ) ) (drop (if (result externref) (i32.const 1) - (ref.func $foo) - (ref.null) + (local.get $local_externref) + (ref.null extern) ) ) (drop (if (result funcref) (i32.const 1) - (ref.func $foo) - (ref.null) + (local.get $local_funcref) + (ref.null func) ) ) (drop (if (result exnref) (i32.const 1) (local.get $local_exnref) - (ref.null) - ) - ) - (drop - (if (result nullref) - (i32.const 1) - (local.get $local_nullref) - (ref.null) + (ref.null exn) ) ) (drop @@ -313,20 +320,10 @@ (local.get $local_externref) ) (catch - (exnref.pop) - ) - ) - ) - (drop - (try (result externref) - (do - (ref.func $foo) - ) - (catch (drop (exnref.pop) ) - (ref.null) + (ref.null extern) ) ) ) @@ -339,14 +336,14 @@ (drop (exnref.pop) ) - (ref.null) + (ref.null func) ) ) ) (drop (try (result exnref) (do - (ref.null) + (ref.null exn) ) (catch (exnref.pop) @@ -354,77 +351,66 @@ ) ) (drop - (try (result nullref) - (do - (ref.null) - ) - (catch - (drop - (exnref.pop) - ) - (ref.null) - ) + (select (result externref) + (local.get $local_externref) + (ref.null extern) + (i32.const 1) ) ) (drop - (select (result externref) - (local.get $local_externref) - (ref.func $foo) + (select (result funcref) + (local.get $local_funcref) + (ref.null func) (i32.const 1) ) ) (drop - (select (result externref) + (select (result exnref) (local.get $local_exnref) - (local.get $local_externref) + (ref.null exn) (i32.const 1) ) ) (drop - (select (result externref) - (local.get $local_externref) - (ref.null) + (select + (i32.const 0) + (i32.const 2) (i32.const 1) ) ) (drop - (select (result externref) - (ref.null) - (ref.func $foo) - (i32.const 1) + (ref.is_null + (local.get $local_externref) ) ) (drop - (select (result funcref) - (ref.func $foo) - (ref.null) - (i32.const 1) + (ref.is_null + (global.get $global_externref) ) ) (drop - (select (result exnref) - (ref.null) - (local.get $local_exnref) - (i32.const 1) + (ref.is_null + (ref.null extern) ) ) (drop - (select (result nullref) - (ref.null) - (ref.null) - (i32.const 1) + (ref.is_null + (local.get $local_funcref) ) ) (drop - (select - (i32.const 0) - (i32.const 2) - (i32.const 1) + (ref.is_null + (global.get $global_funcref) ) ) (drop (ref.is_null - (local.get $local_externref) + (ref.null func) + ) + ) + (drop + (ref.is_null + (ref.func $foo) ) ) (drop @@ -434,86 +420,85 @@ ) (drop (ref.is_null - (ref.func $foo) + (global.get $global_exnref) ) ) (drop (ref.is_null - (ref.null) + (ref.null exn) ) ) ) - (func $return_externref (result externref) + (func $return_externref_local (result externref) (local $local_externref externref) (local.get $local_externref) ) - (func $return_externref2 (result externref) - (ref.func $foo) + (func $return_externref_global (result externref) + (global.get $global_externref) ) - (func $return_externref3 (result externref) - (local $local_exnref exnref) - (local.get $local_exnref) + (func $return_externref_null (result externref) + (ref.null extern) + ) + (func $return_funcref_local (result funcref) + (local $local_funcref funcref) + (local.get $local_funcref) ) - (func $return_externref4 (result externref) - (ref.null) + (func $return_funcref_global (result funcref) + (global.get $global_funcref) ) - (func $return_funcref (result funcref) - (ref.func $foo) + (func $return_funcref_null (result funcref) + (ref.null func) ) - (func $return_funcref2 (result funcref) - (ref.null) + (func $return_funcref_func (result funcref) + (ref.func $foo) ) - (func $return_exnref (result exnref) + (func $return_exnref_local (result exnref) (local $local_exnref exnref) (local.get $local_exnref) ) - (func $return_exnref2 (result exnref) - (ref.null) + (func $return_exnref_global (result exnref) + (global.get $global_exnref) ) - (func $return_nullref (result nullref) - (local $local_nullref nullref) - (local.get $local_nullref) + (func $return_exnref_null (result exnref) + (ref.null exn) ) - (func $return_externref_returns (result externref) + (func $returns_externref (result externref) (local $local_externref externref) - (local $local_exnref exnref) (return (local.get $local_externref) ) (return - (local.get $local_exnref) + (global.get $global_externref) ) (return - (ref.func $foo) + (ref.null extern) ) + ) + (func $returns_funcref (result funcref) + (local $local_funcref funcref) (return - (ref.null) + (local.get $local_funcref) + ) + (return + (global.get $global_funcref) ) - ) - (func $return_funcref_returns (result funcref) (return (ref.func $foo) ) (return - (ref.null) + (ref.null func) ) ) - (func $return_exnref_returns (result exnref) + (func $returns_exnref (result exnref) (local $local_exnref exnref) (return (local.get $local_exnref) ) (return - (ref.null) - ) - ) - (func $return_nullref_returns (result nullref) - (local $local_nullref nullref) - (return - (local.get $local_nullref) + (global.get $global_exnref) ) (return - (ref.null) + (ref.null exn) ) ) ) diff --git a/test/reference-types.wast.fromBinary b/test/reference-types.wast.fromBinary index ae36b9209..f4a958d99 100644 --- a/test/reference-types.wast.fromBinary +++ b/test/reference-types.wast.fromBinary @@ -1,24 +1,20 @@ (module - (type $externref_=>_none (func (param externref))) - (type $none_=>_externref (func (result externref))) (type $funcref_=>_none (func (param funcref))) - (type $nullref_=>_none (func (param nullref))) - (type $exnref_=>_none (func (param exnref))) (type $none_=>_funcref (func (result funcref))) + (type $externref_=>_none (func (param externref))) + (type $exnref_=>_none (func (param exnref))) + (type $none_=>_externref (func (result externref))) (type $none_=>_exnref (func (result exnref))) (type $none_=>_none (func)) - (type $none_=>_nullref (func (result nullref))) (type $externref_=>_funcref (func (param externref) (result funcref))) (import "env" "import_global" (global $gimport$1 externref)) (import "env" "import_func" (func $import_func (param externref) (result funcref))) - (table $0 4 4 funcref) - (elem (i32.const 0) $take_externref $take_funcref $take_exnref $take_nullref) - (global $global$0 (mut externref) (ref.null)) - (global $global$1 (mut funcref) (ref.null)) - (global $global$2 (mut exnref) (ref.null)) - (global $global$3 (mut nullref) (ref.null)) - (global $global$4 (mut externref) (ref.func $foo)) - (global $global$5 (mut funcref) (ref.func $foo)) + (table $0 3 3 funcref) + (elem (i32.const 0) $take_externref $take_funcref $take_exnref) + (global $global$0 (mut externref) (ref.null extern)) + (global $global$1 (mut funcref) (ref.null func)) + (global $global$2 (mut funcref) (ref.func $foo)) + (global $global$3 (mut exnref) (ref.null exn)) (export "export_func" (func $import_func)) (export "export_global" (global $gimport$1)) (func $take_externref (param $0 externref) @@ -30,121 +26,113 @@ (func $take_exnref (param $0 exnref) (nop) ) - (func $take_nullref (param $0 nullref) - (nop) - ) (func $foo (nop) ) (func $test (local $0 funcref) (local $1 externref) - (local $2 nullref) - (local $3 exnref) + (local $2 exnref) (local.set $1 (local.get $1) ) (local.set $1 - (local.get $0) - ) - (local.set $1 - (local.get $3) - ) - (local.set $1 - (local.get $2) - ) - (local.set $1 - (ref.null) + (global.get $global$0) ) (local.set $1 - (ref.func $foo) + (ref.null extern) ) (local.set $0 (local.get $0) ) (local.set $0 - (ref.null) + (global.get $global$1) ) (local.set $0 - (ref.func $foo) - ) - (local.set $3 - (local.get $3) + (ref.null func) ) - (local.set $3 - (ref.null) + (local.set $0 + (ref.func $foo) ) (local.set $2 (local.get $2) ) (local.set $2 - (ref.null) - ) - (global.set $global$0 - (global.get $global$0) - ) - (global.set $global$0 - (global.get $global$1) + (global.get $global$3) ) - (global.set $global$0 - (global.get $global$2) + (local.set $2 + (ref.null exn) ) (global.set $global$0 - (global.get $global$3) + (global.get $global$0) ) (global.set $global$0 - (ref.null) + (local.get $1) ) (global.set $global$0 - (ref.func $foo) + (ref.null extern) ) (global.set $global$1 (global.get $global$1) ) (global.set $global$1 - (ref.null) + (local.get $0) ) (global.set $global$1 - (ref.func $foo) - ) - (global.set $global$2 - (global.get $global$2) + (ref.null func) ) - (global.set $global$2 - (ref.null) + (global.set $global$1 + (ref.func $foo) ) (global.set $global$3 (global.get $global$3) ) (global.set $global$3 - (ref.null) + (local.get $2) + ) + (global.set $global$3 + (ref.null exn) ) (call $take_externref (local.get $1) ) (call $take_externref - (local.get $0) + (global.get $global$0) ) (call $take_externref - (local.get $3) + (ref.null extern) ) - (call $take_externref - (ref.null) + (call $take_funcref + (local.get $0) ) - (call_indirect (type $externref_=>_none) - (local.get $1) - (i32.const 0) + (call $take_funcref + (global.get $global$1) + ) + (call $take_funcref + (ref.null func) + ) + (call $take_funcref + (ref.func $foo) + ) + (call $take_exnref + (local.get $2) + ) + (call $take_exnref + (global.get $global$3) + ) + (call $take_exnref + (ref.null exn) ) (call_indirect (type $externref_=>_none) - (local.get $0) + (local.get $1) (i32.const 0) ) (call_indirect (type $externref_=>_none) - (local.get $3) + (global.get $global$0) (i32.const 0) ) (call_indirect (type $externref_=>_none) - (ref.null) + (ref.null extern) (i32.const 0) ) (call_indirect (type $funcref_=>_none) @@ -152,24 +140,28 @@ (i32.const 1) ) (call_indirect (type $funcref_=>_none) - (ref.null) + (global.get $global$1) + (i32.const 1) + ) + (call_indirect (type $funcref_=>_none) + (ref.null func) + (i32.const 1) + ) + (call_indirect (type $funcref_=>_none) + (ref.func $foo) (i32.const 1) ) (call_indirect (type $exnref_=>_none) - (local.get $3) + (local.get $2) (i32.const 2) ) (call_indirect (type $exnref_=>_none) - (ref.null) + (global.get $global$3) (i32.const 2) ) - (call_indirect (type $nullref_=>_none) - (local.get $2) - (i32.const 3) - ) - (call_indirect (type $nullref_=>_none) - (ref.null) - (i32.const 3) + (call_indirect (type $exnref_=>_none) + (ref.null exn) + (i32.const 2) ) (drop (block $label$1 (result externref) @@ -182,7 +174,7 @@ (drop (block $label$2 (result externref) (br_if $label$2 - (local.get $0) + (global.get $global$0) (i32.const 1) ) ) @@ -190,15 +182,15 @@ (drop (block $label$3 (result externref) (br_if $label$3 - (local.get $3) + (ref.null extern) (i32.const 1) ) ) ) (drop - (block $label$4 (result externref) + (block $label$4 (result funcref) (br_if $label$4 - (ref.null) + (local.get $0) (i32.const 1) ) ) @@ -206,105 +198,120 @@ (drop (block $label$5 (result funcref) (br_if $label$5 - (ref.null) + (global.get $global$1) (i32.const 1) ) ) ) (drop - (block $label$6 (result exnref) + (block $label$6 (result funcref) (br_if $label$6 - (ref.null) + (ref.null func) (i32.const 1) ) ) ) (drop - (block $label$7 (result nullref) + (block $label$7 (result funcref) (br_if $label$7 - (ref.null) + (ref.func $foo) (i32.const 1) ) ) ) (drop - (loop $label$8 (result externref) - (local.get $1) + (block $label$8 (result exnref) + (br_if $label$8 + (local.get $2) + (i32.const 1) + ) ) ) (drop - (loop $label$9 (result externref) - (local.get $0) + (block $label$9 (result exnref) + (br_if $label$9 + (global.get $global$3) + (i32.const 1) + ) ) ) (drop - (loop $label$10 (result externref) - (local.get $3) + (block $label$10 (result exnref) + (br_if $label$10 + (ref.null exn) + (i32.const 1) + ) ) ) (drop (loop $label$11 (result externref) - (ref.null) + (local.get $1) ) ) (drop - (loop $label$12 (result funcref) + (loop $label$12 (result externref) + (global.get $global$0) + ) + ) + (drop + (loop $label$13 (result externref) + (ref.null extern) + ) + ) + (drop + (loop $label$14 (result funcref) (local.get $0) ) ) (drop - (loop $label$13 (result funcref) - (ref.null) + (loop $label$15 (result funcref) + (global.get $global$1) ) ) (drop - (loop $label$14 (result exnref) - (local.get $3) + (loop $label$16 (result funcref) + (ref.null func) ) ) (drop - (loop $label$15 (result exnref) - (ref.null) + (loop $label$17 (result funcref) + (ref.func $foo) ) ) (drop - (loop $label$16 (result nullref) - (ref.null) + (loop $label$18 (result exnref) + (local.get $2) ) ) (drop - (if (result externref) - (i32.const 1) - (local.get $1) - (local.get $3) + (loop $label$19 (result exnref) + (global.get $global$3) ) ) (drop - (if (result externref) - (i32.const 1) - (ref.func $foo) - (ref.null) + (loop $label$20 (result exnref) + (ref.null exn) ) ) (drop - (if (result funcref) + (if (result externref) (i32.const 1) - (ref.func $foo) - (ref.null) + (local.get $1) + (ref.null extern) ) ) (drop - (if (result exnref) + (if (result funcref) (i32.const 1) - (local.get $3) - (ref.null) + (local.get $0) + (ref.null func) ) ) (drop - (if (result nullref) + (if (result exnref) (i32.const 1) (local.get $2) - (ref.null) + (ref.null exn) ) ) (drop @@ -313,20 +320,10 @@ (local.get $1) ) (catch - (exnref.pop) - ) - ) - ) - (drop - (try (result externref) - (do - (ref.func $foo) - ) - (catch (drop (exnref.pop) ) - (ref.null) + (ref.null extern) ) ) ) @@ -339,14 +336,14 @@ (drop (exnref.pop) ) - (ref.null) + (ref.null func) ) ) ) (drop (try (result exnref) (do - (ref.null) + (ref.null exn) ) (catch (exnref.pop) @@ -354,82 +351,61 @@ ) ) (drop - (try (result nullref) - (do - (ref.null) - ) - (catch - (drop - (exnref.pop) - ) - (ref.null) - ) - ) - ) - (drop (select (result externref) (local.get $1) - (ref.func $foo) + (ref.null extern) (i32.const 1) ) ) (drop - (select (result externref) - (local.get $3) - (local.get $1) + (select (result funcref) + (local.get $0) + (ref.null func) (i32.const 1) ) ) (drop - (select (result externref) - (local.get $1) - (ref.null) + (select (result exnref) + (local.get $2) + (ref.null exn) (i32.const 1) ) ) (drop - (select (result externref) - (ref.null) - (ref.func $foo) + (select + (i32.const 0) + (i32.const 2) (i32.const 1) ) ) (drop - (select (result funcref) - (ref.func $foo) - (ref.null) - (i32.const 1) + (ref.is_null + (local.get $1) ) ) (drop - (select (result exnref) - (ref.null) - (local.get $3) - (i32.const 1) + (ref.is_null + (global.get $global$0) ) ) (drop - (select (result nullref) - (ref.null) - (ref.null) - (i32.const 1) + (ref.is_null + (ref.null extern) ) ) (drop - (select - (i32.const 0) - (i32.const 2) - (i32.const 1) + (ref.is_null + (local.get $0) ) ) (drop (ref.is_null - (local.get $1) + (global.get $global$1) ) ) (drop (ref.is_null - (local.get $3) + (ref.null func) ) ) (drop @@ -439,61 +415,67 @@ ) (drop (ref.is_null - (ref.null) + (local.get $2) + ) + ) + (drop + (ref.is_null + (global.get $global$3) + ) + ) + (drop + (ref.is_null + (ref.null exn) ) ) ) - (func $return_externref (result externref) + (func $return_externref_local (result externref) (local $0 externref) (local.get $0) ) - (func $return_externref2 (result externref) - (ref.func $foo) + (func $return_externref_global (result externref) + (global.get $global$0) ) - (func $return_externref3 (result externref) - (local $0 exnref) + (func $return_externref_null (result externref) + (ref.null extern) + ) + (func $return_funcref_local (result funcref) + (local $0 funcref) (local.get $0) ) - (func $return_externref4 (result externref) - (ref.null) + (func $return_funcref_global (result funcref) + (global.get $global$1) ) - (func $return_funcref (result funcref) - (ref.func $foo) + (func $return_funcref_null (result funcref) + (ref.null func) ) - (func $return_funcref2 (result funcref) - (ref.null) + (func $return_funcref_func (result funcref) + (ref.func $foo) ) - (func $return_exnref (result exnref) + (func $return_exnref_local (result exnref) (local $0 exnref) (local.get $0) ) - (func $return_exnref2 (result exnref) - (ref.null) + (func $return_exnref_global (result exnref) + (global.get $global$3) ) - (func $return_nullref (result nullref) - (local $0 nullref) - (local.get $0) + (func $return_exnref_null (result exnref) + (ref.null exn) ) - (func $return_externref_returns (result externref) + (func $returns_externref (result externref) (local $0 externref) - (local $1 exnref) (return (local.get $0) ) ) - (func $return_funcref_returns (result funcref) - (return - (ref.func $foo) - ) - ) - (func $return_exnref_returns (result exnref) - (local $0 exnref) + (func $returns_funcref (result funcref) + (local $0 funcref) (return (local.get $0) ) ) - (func $return_nullref_returns (result nullref) - (local $0 nullref) + (func $returns_exnref (result exnref) + (local $0 exnref) (return (local.get $0) ) diff --git a/test/reference-types.wast.fromBinary.noDebugInfo b/test/reference-types.wast.fromBinary.noDebugInfo index 9e8dac3a3..f0282f1e2 100644 --- a/test/reference-types.wast.fromBinary.noDebugInfo +++ b/test/reference-types.wast.fromBinary.noDebugInfo @@ -1,24 +1,20 @@ (module - (type $externref_=>_none (func (param externref))) - (type $none_=>_externref (func (result externref))) (type $funcref_=>_none (func (param funcref))) - (type $nullref_=>_none (func (param nullref))) - (type $exnref_=>_none (func (param exnref))) (type $none_=>_funcref (func (result funcref))) + (type $externref_=>_none (func (param externref))) + (type $exnref_=>_none (func (param exnref))) + (type $none_=>_externref (func (result externref))) (type $none_=>_exnref (func (result exnref))) (type $none_=>_none (func)) - (type $none_=>_nullref (func (result nullref))) (type $externref_=>_funcref (func (param externref) (result funcref))) (import "env" "import_global" (global $gimport$1 externref)) (import "env" "import_func" (func $fimport$0 (param externref) (result funcref))) - (table $0 4 4 funcref) - (elem (i32.const 0) $0 $1 $2 $3) - (global $global$0 (mut externref) (ref.null)) - (global $global$1 (mut funcref) (ref.null)) - (global $global$2 (mut exnref) (ref.null)) - (global $global$3 (mut nullref) (ref.null)) - (global $global$4 (mut externref) (ref.func $4)) - (global $global$5 (mut funcref) (ref.func $4)) + (table $0 3 3 funcref) + (elem (i32.const 0) $0 $1 $2) + (global $global$0 (mut externref) (ref.null extern)) + (global $global$1 (mut funcref) (ref.null func)) + (global $global$2 (mut funcref) (ref.func $3)) + (global $global$3 (mut exnref) (ref.null exn)) (export "export_func" (func $fimport$0)) (export "export_global" (global $gimport$1)) (func $0 (param $0 externref) @@ -30,121 +26,113 @@ (func $2 (param $0 exnref) (nop) ) - (func $3 (param $0 nullref) + (func $3 (nop) ) (func $4 - (nop) - ) - (func $5 (local $0 funcref) (local $1 externref) - (local $2 nullref) - (local $3 exnref) + (local $2 exnref) (local.set $1 (local.get $1) ) (local.set $1 - (local.get $0) - ) - (local.set $1 - (local.get $3) - ) - (local.set $1 - (local.get $2) - ) - (local.set $1 - (ref.null) + (global.get $global$0) ) (local.set $1 - (ref.func $4) + (ref.null extern) ) (local.set $0 (local.get $0) ) (local.set $0 - (ref.null) + (global.get $global$1) ) (local.set $0 - (ref.func $4) - ) - (local.set $3 - (local.get $3) + (ref.null func) ) - (local.set $3 - (ref.null) + (local.set $0 + (ref.func $3) ) (local.set $2 (local.get $2) ) (local.set $2 - (ref.null) - ) - (global.set $global$0 - (global.get $global$0) - ) - (global.set $global$0 - (global.get $global$1) + (global.get $global$3) ) - (global.set $global$0 - (global.get $global$2) + (local.set $2 + (ref.null exn) ) (global.set $global$0 - (global.get $global$3) + (global.get $global$0) ) (global.set $global$0 - (ref.null) + (local.get $1) ) (global.set $global$0 - (ref.func $4) + (ref.null extern) ) (global.set $global$1 (global.get $global$1) ) (global.set $global$1 - (ref.null) + (local.get $0) ) (global.set $global$1 - (ref.func $4) - ) - (global.set $global$2 - (global.get $global$2) + (ref.null func) ) - (global.set $global$2 - (ref.null) + (global.set $global$1 + (ref.func $3) ) (global.set $global$3 (global.get $global$3) ) (global.set $global$3 - (ref.null) + (local.get $2) + ) + (global.set $global$3 + (ref.null exn) ) (call $0 (local.get $1) ) (call $0 - (local.get $0) + (global.get $global$0) ) (call $0 - (local.get $3) + (ref.null extern) ) - (call $0 - (ref.null) + (call $1 + (local.get $0) ) - (call_indirect (type $externref_=>_none) - (local.get $1) - (i32.const 0) + (call $1 + (global.get $global$1) + ) + (call $1 + (ref.null func) + ) + (call $1 + (ref.func $3) + ) + (call $2 + (local.get $2) + ) + (call $2 + (global.get $global$3) + ) + (call $2 + (ref.null exn) ) (call_indirect (type $externref_=>_none) - (local.get $0) + (local.get $1) (i32.const 0) ) (call_indirect (type $externref_=>_none) - (local.get $3) + (global.get $global$0) (i32.const 0) ) (call_indirect (type $externref_=>_none) - (ref.null) + (ref.null extern) (i32.const 0) ) (call_indirect (type $funcref_=>_none) @@ -152,24 +140,28 @@ (i32.const 1) ) (call_indirect (type $funcref_=>_none) - (ref.null) + (global.get $global$1) + (i32.const 1) + ) + (call_indirect (type $funcref_=>_none) + (ref.null func) + (i32.const 1) + ) + (call_indirect (type $funcref_=>_none) + (ref.func $3) (i32.const 1) ) (call_indirect (type $exnref_=>_none) - (local.get $3) + (local.get $2) (i32.const 2) ) (call_indirect (type $exnref_=>_none) - (ref.null) + (global.get $global$3) (i32.const 2) ) - (call_indirect (type $nullref_=>_none) - (local.get $2) - (i32.const 3) - ) - (call_indirect (type $nullref_=>_none) - (ref.null) - (i32.const 3) + (call_indirect (type $exnref_=>_none) + (ref.null exn) + (i32.const 2) ) (drop (block $label$1 (result externref) @@ -182,7 +174,7 @@ (drop (block $label$2 (result externref) (br_if $label$2 - (local.get $0) + (global.get $global$0) (i32.const 1) ) ) @@ -190,15 +182,15 @@ (drop (block $label$3 (result externref) (br_if $label$3 - (local.get $3) + (ref.null extern) (i32.const 1) ) ) ) (drop - (block $label$4 (result externref) + (block $label$4 (result funcref) (br_if $label$4 - (ref.null) + (local.get $0) (i32.const 1) ) ) @@ -206,105 +198,120 @@ (drop (block $label$5 (result funcref) (br_if $label$5 - (ref.null) + (global.get $global$1) (i32.const 1) ) ) ) (drop - (block $label$6 (result exnref) + (block $label$6 (result funcref) (br_if $label$6 - (ref.null) + (ref.null func) (i32.const 1) ) ) ) (drop - (block $label$7 (result nullref) + (block $label$7 (result funcref) (br_if $label$7 - (ref.null) + (ref.func $3) (i32.const 1) ) ) ) (drop - (loop $label$8 (result externref) - (local.get $1) + (block $label$8 (result exnref) + (br_if $label$8 + (local.get $2) + (i32.const 1) + ) ) ) (drop - (loop $label$9 (result externref) - (local.get $0) + (block $label$9 (result exnref) + (br_if $label$9 + (global.get $global$3) + (i32.const 1) + ) ) ) (drop - (loop $label$10 (result externref) - (local.get $3) + (block $label$10 (result exnref) + (br_if $label$10 + (ref.null exn) + (i32.const 1) + ) ) ) (drop (loop $label$11 (result externref) - (ref.null) + (local.get $1) ) ) (drop - (loop $label$12 (result funcref) + (loop $label$12 (result externref) + (global.get $global$0) + ) + ) + (drop + (loop $label$13 (result externref) + (ref.null extern) + ) + ) + (drop + (loop $label$14 (result funcref) (local.get $0) ) ) (drop - (loop $label$13 (result funcref) - (ref.null) + (loop $label$15 (result funcref) + (global.get $global$1) ) ) (drop - (loop $label$14 (result exnref) - (local.get $3) + (loop $label$16 (result funcref) + (ref.null func) ) ) (drop - (loop $label$15 (result exnref) - (ref.null) + (loop $label$17 (result funcref) + (ref.func $3) ) ) (drop - (loop $label$16 (result nullref) - (ref.null) + (loop $label$18 (result exnref) + (local.get $2) ) ) (drop - (if (result externref) - (i32.const 1) - (local.get $1) - (local.get $3) + (loop $label$19 (result exnref) + (global.get $global$3) ) ) (drop - (if (result externref) - (i32.const 1) - (ref.func $4) - (ref.null) + (loop $label$20 (result exnref) + (ref.null exn) ) ) (drop - (if (result funcref) + (if (result externref) (i32.const 1) - (ref.func $4) - (ref.null) + (local.get $1) + (ref.null extern) ) ) (drop - (if (result exnref) + (if (result funcref) (i32.const 1) - (local.get $3) - (ref.null) + (local.get $0) + (ref.null func) ) ) (drop - (if (result nullref) + (if (result exnref) (i32.const 1) (local.get $2) - (ref.null) + (ref.null exn) ) ) (drop @@ -313,40 +320,30 @@ (local.get $1) ) (catch - (exnref.pop) - ) - ) - ) - (drop - (try (result externref) - (do - (ref.func $4) - ) - (catch (drop (exnref.pop) ) - (ref.null) + (ref.null extern) ) ) ) (drop (try (result funcref) (do - (ref.func $4) + (ref.func $3) ) (catch (drop (exnref.pop) ) - (ref.null) + (ref.null func) ) ) ) (drop (try (result exnref) (do - (ref.null) + (ref.null exn) ) (catch (exnref.pop) @@ -354,136 +351,127 @@ ) ) (drop - (try (result nullref) - (do - (ref.null) - ) - (catch - (drop - (exnref.pop) - ) - (ref.null) - ) - ) - ) - (drop (select (result externref) (local.get $1) - (ref.func $4) + (ref.null extern) (i32.const 1) ) ) (drop - (select (result externref) - (local.get $3) - (local.get $1) + (select (result funcref) + (local.get $0) + (ref.null func) (i32.const 1) ) ) (drop - (select (result externref) - (local.get $1) - (ref.null) + (select (result exnref) + (local.get $2) + (ref.null exn) (i32.const 1) ) ) (drop - (select (result externref) - (ref.null) - (ref.func $4) + (select + (i32.const 0) + (i32.const 2) (i32.const 1) ) ) (drop - (select (result funcref) - (ref.func $4) - (ref.null) - (i32.const 1) + (ref.is_null + (local.get $1) ) ) (drop - (select (result exnref) - (ref.null) - (local.get $3) - (i32.const 1) + (ref.is_null + (global.get $global$0) ) ) (drop - (select (result nullref) - (ref.null) - (ref.null) - (i32.const 1) + (ref.is_null + (ref.null extern) ) ) (drop - (select - (i32.const 0) - (i32.const 2) - (i32.const 1) + (ref.is_null + (local.get $0) ) ) (drop (ref.is_null - (local.get $1) + (global.get $global$1) ) ) (drop (ref.is_null - (local.get $3) + (ref.null func) ) ) (drop (ref.is_null - (ref.func $4) + (ref.func $3) ) ) (drop (ref.is_null - (ref.null) + (local.get $2) + ) + ) + (drop + (ref.is_null + (global.get $global$3) + ) + ) + (drop + (ref.is_null + (ref.null exn) ) ) ) - (func $6 (result externref) + (func $5 (result externref) (local $0 externref) (local.get $0) ) + (func $6 (result externref) + (global.get $global$0) + ) (func $7 (result externref) - (ref.func $4) + (ref.null extern) ) - (func $8 (result externref) - (local $0 exnref) + (func $8 (result funcref) + (local $0 funcref) (local.get $0) ) - (func $9 (result externref) - (ref.null) + (func $9 (result funcref) + (global.get $global$1) ) (func $10 (result funcref) - (ref.func $4) + (ref.null func) ) (func $11 (result funcref) - (ref.null) + (ref.func $3) ) (func $12 (result exnref) (local $0 exnref) (local.get $0) ) (func $13 (result exnref) - (ref.null) + (global.get $global$3) ) - (func $14 (result nullref) - (local $0 nullref) - (local.get $0) + (func $14 (result exnref) + (ref.null exn) ) (func $15 (result externref) (local $0 externref) - (local $1 exnref) (return (local.get $0) ) ) (func $16 (result funcref) + (local $0 funcref) (return - (ref.func $4) + (local.get $0) ) ) (func $17 (result exnref) @@ -492,11 +480,5 @@ (local.get $0) ) ) - (func $18 (result nullref) - (local $0 nullref) - (return - (local.get $0) - ) - ) ) diff --git a/test/spec/call_indirect_sig_mismatch.wast b/test/spec/call_indirect_sig_mismatch.wast index 15e5d6a5a..69cca17ba 100644 --- a/test/spec/call_indirect_sig_mismatch.wast +++ b/test/spec/call_indirect_sig_mismatch.wast @@ -5,7 +5,7 @@ (func $callee (param $0 exnref)) (func $sig_mismatch (call_indirect (type $funcref_=>_none) - (ref.null) + (ref.null func) (i32.const 0) ) ) diff --git a/test/spec/exception-handling.wast b/test/spec/exception-handling.wast index c3b80896e..0188865ac 100644 --- a/test/spec/exception-handling.wast +++ b/test/spec/exception-handling.wast @@ -11,8 +11,8 @@ (throw $e-i32-f32 (i32.const 3) (f32.const 3.5)) ) - (func (export "rethrow_nullref") - (rethrow (ref.null)) + (func (export "rethrow_null") + (rethrow (ref.null exn)) ) (func (export "try_nothrow") (result i32) @@ -74,10 +74,10 @@ ) ) - (func (export "br_on_exn_nullref") (result i32) + (func (export "br_on_exn_null") (result i32) (block $l0 (result i32) (drop - (br_on_exn $l0 $e-i32 (ref.null)) + (br_on_exn $l0 $e-i32 (ref.null exn)) ) (i32.const 0) ) @@ -185,13 +185,13 @@ (assert_trap (invoke "throw_single_value")) (assert_trap (invoke "throw_multiple_values")) -(assert_trap (invoke "rethrow_nullref")) +(assert_trap (invoke "rethrow_null")) (assert_return (invoke "try_nothrow") (i32.const 3)) (assert_return (invoke "try_throw_catch") (i32.const 3)) (assert_return (invoke "try_call_catch") (i32.const 3)) (assert_trap (invoke "try_throw_rethrow")) (assert_trap (invoke "try_call_rethrow")) -(assert_trap (invoke "br_on_exn_nullref")) +(assert_trap (invoke "br_on_exn_null")) (assert_return (invoke "br_on_exn_match_no_value")) (assert_return (invoke "br_on_exn_match_single_value") (i32.const 5)) (assert_return (invoke "br_on_exn_match_multiple_values") (tuple.make (i32.const 3) (f32.const 3.5))) diff --git a/test/spec/old_select.wast b/test/spec/old_select.wast index e1dd40654..5228017b0 100644 --- a/test/spec/old_select.wast +++ b/test/spec/old_select.wast @@ -23,9 +23,6 @@ (select (result f64) (local.get 0) (local.get 1) (local.get 2)) ) - (func (export "select-nullref") (param nullref nullref i32) (result nullref) - (select (result nullref) (local.get 0) (local.get 1) (local.get 2)) - ) (func (export "select-funcref") (param funcref funcref i32) (result funcref) (select (result funcref) (local.get 0) (local.get 1) (local.get 2)) ) @@ -38,24 +35,6 @@ (select (unreachable) (i32.const 0) (local.get $cond))) (func (export "select_trap_r") (param $cond i32) (result i32) (select (i32.const 0) (unreachable) (local.get $cond))) - - (func (export "join-nullref") (param i32) (result externref) - (select (result externref) (ref.null) (ref.null) (local.get 0)) - ) - (func (export "join-funcref") (param i32) (result externref) - (select (result externref) - (ref.func $dummy) - (ref.null) - (local.get 0) - ) - ) - (func (export "join-externref") (param i32) (param externref) (result externref) - (select (result externref) - (ref.func $dummy) - (local.get 1) - (local.get 0) - ) - ) ) (assert_return (invoke "select_i32" (i32.const 1) (i32.const 2) (i32.const 1)) (i32.const 1)) @@ -90,15 +69,11 @@ (assert_return (invoke "select-i64-t" (i64.const 2) (i64.const 1) (i32.const 1)) (i64.const 2)) (assert_return (invoke "select-f32-t" (f32.const 1) (f32.const 2) (i32.const 1)) (f32.const 1)) (assert_return (invoke "select-f64-t" (f64.const 1) (f64.const 2) (i32.const 1)) (f64.const 1)) -(assert_return (invoke "select-nullref" (ref.null) (ref.null) (i32.const 1)) (ref.null)) -(assert_return (invoke "select-funcref" (ref.func "dummy") (ref.null) (i32.const 1)) (ref.func "dummy")) -(assert_return (invoke "select-externref" (ref.null) (ref.func "dummy") (i32.const 1)) (ref.null)) (assert_return (invoke "select-i32-t" (i32.const 1) (i32.const 2) (i32.const 0)) (i32.const 2)) (assert_return (invoke "select-i32-t" (i32.const 2) (i32.const 1) (i32.const 0)) (i32.const 1)) (assert_return (invoke "select-i64-t" (i64.const 2) (i64.const 1) (i32.const -1)) (i64.const 2)) (assert_return (invoke "select-i64-t" (i64.const 2) (i64.const 1) (i32.const 0xf0f0f0f0)) (i64.const 2)) -(assert_return (invoke "select-externref" (ref.null) (ref.func "dummy") (i32.const 0)) (ref.func "dummy")) (assert_return (invoke "select-f32-t" (f32.const nan) (f32.const 1) (i32.const 1)) (f32.const nan)) (assert_return (invoke "select-f32-t" (f32.const nan:0x20304) (f32.const 1) (i32.const 1)) (f32.const nan:0x20304)) @@ -118,14 +93,10 @@ (assert_return (invoke "select-f64-t" (f64.const 2) (f64.const nan) (i32.const 0)) (f64.const nan)) (assert_return (invoke "select-f64-t" (f64.const 2) (f64.const nan:0x20304) (i32.const 0)) (f64.const nan:0x20304)) -(assert_return (invoke "join-nullref" (i32.const 1)) (ref.null)) -(assert_return (invoke "join-nullref" (i32.const 0)) (ref.null)) - -(assert_return_func (invoke "join-funcref" (i32.const 1))) -(assert_return (invoke "join-funcref" (i32.const 0)) (ref.null)) - -(assert_return_func (invoke "join-externref" (i32.const 1) (ref.null))) -(assert_return (invoke "join-externref" (i32.const 0) (ref.null)) (ref.null)) +(assert_return (invoke "select-funcref" (ref.func "dummy") (ref.null func) (i32.const 1)) (ref.func "dummy")) +(assert_return (invoke "select-funcref" (ref.func "dummy") (ref.null func) (i32.const 0)) (ref.null func)) +(assert_return (invoke "select-externref" (ref.null extern) (ref.null extern) (i32.const 1)) (ref.null extern)) +(assert_return (invoke "select-externref" (ref.null extern) (ref.null extern) (i32.const 0)) (ref.null extern)) (assert_trap (invoke "select_trap_l" (i32.const 1)) "unreachable executed") (assert_trap (invoke "select_trap_l" (i32.const 0)) "unreachable executed") diff --git a/test/spec/ref_func.wast b/test/spec/ref_func.wast index 79bf584be..f68e6166d 100644 --- a/test/spec/ref_func.wast +++ b/test/spec/ref_func.wast @@ -5,8 +5,7 @@ (func $f (import "M" "f") (param i32) (result i32)) (func $g (param $x i32) (result i32) (i32.add (local.get $x) (i32.const 1))) - (global externref (ref.func $f)) - (global externref (ref.func $g)) + (global externref (ref.null extern)) (global funcref (ref.func $f)) (global funcref (ref.func $g)) (global $v (mut funcref) (ref.func $f)) diff --git a/test/spec/ref_is_null.wast b/test/spec/ref_is_null.wast index e44fcf496..8f820d2bc 100644 --- a/test/spec/ref_is_null.wast +++ b/test/spec/ref_is_null.wast @@ -1,15 +1,11 @@ (module - (func $f1 (export "nullref") (param $x nullref) (result i32) + (func $f1 (export "externref") (param $x externref) (result i32) (ref.is_null (local.get $x)) ) - (func $f2 (export "externref") (param $x externref) (result i32) - (ref.is_null (local.get $x)) - ) - (func $f3 (export "funcref") (param $x funcref) (result i32) + (func $f2 (export "funcref") (param $x funcref) (result i32) (ref.is_null (local.get $x)) ) ) -(assert_return (invoke "nullref" (ref.null)) (i32.const 1)) -(assert_return (invoke "externref" (ref.null)) (i32.const 1)) -(assert_return (invoke "funcref" (ref.null)) (i32.const 1)) +(assert_return (invoke "externref" (ref.null extern)) (i32.const 1)) +(assert_return (invoke "funcref" (ref.null func)) (i32.const 1)) diff --git a/test/spec/ref_null.wast b/test/spec/ref_null.wast index 93e6acbd2..b88b0888f 100644 --- a/test/spec/ref_null.wast +++ b/test/spec/ref_null.wast @@ -1,13 +1,10 @@ (module - (func (export "externref") (result externref) (ref.null)) - (func (export "funcref") (result funcref) (ref.null)) - (func (export "nullref") (result nullref) (ref.null)) + (func (export "externref") (result externref) (ref.null extern)) + (func (export "funcref") (result funcref) (ref.null func)) - (global externref (ref.null)) - (global funcref (ref.null)) - (global nullref (ref.null)) + (global externref (ref.null extern)) + (global funcref (ref.null func)) ) -(assert_return (invoke "externref") (ref.null)) -(assert_return (invoke "funcref") (ref.null)) -(assert_return (invoke "nullref") (ref.null)) +(assert_return (invoke "externref") (ref.null extern)) +(assert_return (invoke "funcref") (ref.null func)) |