From ac5581801a6ceebd7730c342d756435654621a8c Mon Sep 17 00:00:00 2001 From: dcode Date: Wed, 9 Sep 2020 04:01:04 +0200 Subject: [PATCH 01/14] Add anyref feature and type --- scripts/fuzz_opt.py | 8 +- scripts/gen-s-parser.py | 1 + src/asmjs/asm_v_wasm.cpp | 3 + src/binaryen-c.cpp | 6 + src/binaryen-c.h | 2 + src/gen-s-parser.inc | 18 +- src/ir/abstract.h | 2 + src/js/binaryen.js-post.js | 8 + src/literal.h | 1 + src/parsing.h | 1 + src/passes/ConstHoisting.cpp | 3 +- src/passes/FuncCastEmulation.cpp | 6 +- src/passes/InstrumentLocals.cpp | 14 + src/shell-interface.h | 1 + src/tools/fuzzing.h | 34 +- src/tools/spec-wrapper.h | 3 + src/tools/tool-options.h | 1 + src/tools/wasm-reduce.cpp | 5 + src/wasm-binary.h | 9 + src/wasm-builder.h | 2 + src/wasm-features.h | 7 +- src/wasm-interpreter.h | 2 + src/wasm-type.h | 15 +- src/wasm/literal.cpp | 14 + src/wasm/wasm-binary.cpp | 8 + src/wasm/wasm-s-parser.cpp | 3 + src/wasm/wasm-stack.cpp | 3 + src/wasm/wasm-type.cpp | 28 +- src/wasm/wasm-validator.cpp | 2 + src/wasm/wasm.cpp | 1 + test/binaryen.js/kitchen-sink.js | 4 + test/binaryen.js/kitchen-sink.js.txt | 5 +- test/example/c-api-kitchen-sink.c | 7 + test/example/c-api-kitchen-sink.txt | 4 +- test/example/typeinfo.cpp | 16 +- test/example/typeinfo.txt | 2 +- test/passes/flatten_all-features.txt | 48 + test/passes/flatten_all-features.wast | 26 +- .../passes/flatten_local-cse_all-features.txt | 49 + .../flatten_local-cse_all-features.wast | 51 +- .../passes/instrument-locals_all-features.txt | 3 + test/passes/merge-locals_all-features.txt | 12 + test/passes/merge-locals_all-features.wast | 26 +- .../optimize-instructions_all-features.txt | 4 + .../optimize-instructions_all-features.wast | 15 +- test/passes/simplify-locals_all-features.txt | 13 + test/passes/simplify-locals_all-features.wast | 33 +- ...ll-features_disable-exception-handling.txt | 13 + ...l-features_disable-exception-handling.wast | 33 +- ..._roundtrip_print-features_all-features.txt | 1 + .../passes/translate-to-fuzz_all-features.txt | 1088 ++++++++++++----- test/reference-types.wast | 818 ++++++------- test/reference-types.wast.from-wast | 622 +++++++++- test/reference-types.wast.fromBinary | 591 ++++++++- ...eference-types.wast.fromBinary.noDebugInfo | 639 +++++++++- test/unit/input/anyref_target_feature.wasm | Bin 0 -> 60 bytes test/unit/test_features.py | 9 +- 57 files changed, 3425 insertions(+), 918 deletions(-) create mode 100644 test/unit/input/anyref_target_feature.wasm diff --git a/scripts/fuzz_opt.py b/scripts/fuzz_opt.py index bf1f7f40933..49910349f29 100755 --- a/scripts/fuzz_opt.py +++ b/scripts/fuzz_opt.py @@ -402,7 +402,7 @@ def can_run(self, wasm): if random.random() < 0.5: return False # wasm2c doesn't support most features - return all([x in FEATURE_OPTS for x in ['--disable-exception-handling', '--disable-simd', '--disable-threads', '--disable-bulk-memory', '--disable-nontrapping-float-to-int', '--disable-tail-call', '--disable-sign-ext', '--disable-reference-types', '--disable-multivalue']]) + return all([x in FEATURE_OPTS for x in ['--disable-exception-handling', '--disable-simd', '--disable-threads', '--disable-bulk-memory', '--disable-nontrapping-float-to-int', '--disable-tail-call', '--disable-sign-ext', '--disable-reference-types', '--disable-multivalue', '--disable-anyref']]) def run(self, wasm): run([in_bin('wasm-opt'), wasm, '--emit-wasm2c-wrapper=main.c'] + FEATURE_OPTS) @@ -502,7 +502,7 @@ def compare_before_and_after(self, before, after): compare(before[vm], after[vm], 'CompareVMs between before and after: ' + vm.name) def can_run_on_feature_opts(self, feature_opts): - return all([x in feature_opts for x in ['--disable-simd', '--disable-reference-types', '--disable-exception-handling', '--disable-multivalue']]) + return all([x in feature_opts for x in ['--disable-simd', '--disable-reference-types', '--disable-exception-handling', '--disable-multivalue', '--disable-anyref']]) # Check for determinism - the same command must have the same output. @@ -633,7 +633,7 @@ def run(self, wasm): return run_vm([shared.NODEJS, js_file, 'a.wasm']) def can_run_on_feature_opts(self, feature_opts): - return all([x in feature_opts for x in ['--disable-exception-handling', '--disable-simd', '--disable-threads', '--disable-bulk-memory', '--disable-nontrapping-float-to-int', '--disable-tail-call', '--disable-sign-ext', '--disable-reference-types', '--disable-multivalue']]) + return all([x in feature_opts for x in ['--disable-exception-handling', '--disable-simd', '--disable-threads', '--disable-bulk-memory', '--disable-nontrapping-float-to-int', '--disable-tail-call', '--disable-sign-ext', '--disable-reference-types', '--disable-multivalue', '--disable-anyref']]) class Asyncify(TestCaseHandler): @@ -687,7 +687,7 @@ def do_asyncify(wasm): compare(before, after_asyncify, 'Asyncify (before/after_asyncify)') def can_run_on_feature_opts(self, feature_opts): - return all([x in feature_opts for x in ['--disable-exception-handling', '--disable-simd', '--disable-tail-call', '--disable-reference-types', '--disable-multivalue']]) + return all([x in feature_opts for x in ['--disable-exception-handling', '--disable-simd', '--disable-tail-call', '--disable-reference-types', '--disable-multivalue', '--disable-anyref']]) # The global list of all test case handlers diff --git a/scripts/gen-s-parser.py b/scripts/gen-s-parser.py index f105e640783..5e49c861468 100755 --- a/scripts/gen-s-parser.py +++ b/scripts/gen-s-parser.py @@ -51,6 +51,7 @@ ("funcref.pop", "makePop(Type::funcref)"), ("externref.pop", "makePop(Type::externref)"), ("exnref.pop", "makePop(Type::exnref)"), + ("anyref.pop", "makePop(Type::anyref)"), ("i32.load", "makeLoad(s, Type::i32, /*isAtomic=*/false)"), ("i64.load", "makeLoad(s, Type::i64, /*isAtomic=*/false)"), ("f32.load", "makeLoad(s, Type::f32, /*isAtomic=*/false)"), diff --git a/src/asmjs/asm_v_wasm.cpp b/src/asmjs/asm_v_wasm.cpp index ddcb27d3dc9..8d2894f1359 100644 --- a/src/asmjs/asm_v_wasm.cpp +++ b/src/asmjs/asm_v_wasm.cpp @@ -57,6 +57,7 @@ AsmType wasmToAsmType(Type type) { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: assert(false && "reference types are not supported by asm2wasm"); case Type::none: return ASM_NONE; @@ -85,6 +86,8 @@ char getSig(Type type) { return 'X'; case Type::exnref: return 'E'; + case Type::anyref: + return 'A'; case Type::none: return 'v'; case Type::unreachable: diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index a3aa0cd94c8..cb638e7111d 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -73,6 +73,7 @@ BinaryenLiteral toBinaryenLiteral(Literal x) { break; case Type::externref: case Type::exnref: + case Type::anyref: assert(x.isNull()); break; case Type::none: @@ -98,6 +99,7 @@ Literal fromBinaryenLiteral(BinaryenLiteral x) { return Literal::makeFunc(x.func); case Type::externref: case Type::exnref: + case Type::anyref: return Literal::makeNull(Type(x.type)); case Type::none: case Type::unreachable: @@ -133,6 +135,7 @@ BinaryenType BinaryenTypeVec128(void) { return Type::v128; } BinaryenType BinaryenTypeFuncref(void) { return Type::funcref; } BinaryenType BinaryenTypeExternref(void) { return Type::externref; } BinaryenType BinaryenTypeExnref(void) { return Type::exnref; } +BinaryenType BinaryenTypeAnyref(void) { return Type::anyref; } BinaryenType BinaryenTypeUnreachable(void) { return Type::unreachable; } BinaryenType BinaryenTypeAuto(void) { return uintptr_t(-1); } @@ -324,6 +327,9 @@ BinaryenFeatures BinaryenFeatureReferenceTypes(void) { BinaryenFeatures BinaryenFeatureMultivalue(void) { return static_cast(FeatureSet::Multivalue); } +BinaryenFeatures BinaryenFeatureAnyref(void) { + return static_cast(FeatureSet::Anyref); +} BinaryenFeatures BinaryenFeatureAll(void) { return static_cast(FeatureSet::All); } diff --git a/src/binaryen-c.h b/src/binaryen-c.h index beaf7249951..e622419ac41 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -101,6 +101,7 @@ BINARYEN_API BinaryenType BinaryenTypeVec128(void); BINARYEN_API BinaryenType BinaryenTypeFuncref(void); BINARYEN_API BinaryenType BinaryenTypeExternref(void); BINARYEN_API BinaryenType BinaryenTypeExnref(void); +BINARYEN_API BinaryenType BinaryenTypeAnyref(void); BINARYEN_API BinaryenType BinaryenTypeUnreachable(void); // Not a real type. Used as the last parameter to BinaryenBlock to let // the API figure out the type instead of providing one. @@ -196,6 +197,7 @@ BINARYEN_API BinaryenFeatures BinaryenFeatureExceptionHandling(void); BINARYEN_API BinaryenFeatures BinaryenFeatureTailCall(void); BINARYEN_API BinaryenFeatures BinaryenFeatureReferenceTypes(void); BINARYEN_API BinaryenFeatures BinaryenFeatureMultivalue(void); +BINARYEN_API BinaryenFeatures BinaryenFeatureAnyref(void); BINARYEN_API BinaryenFeatures BinaryenFeatureAll(void); // Modules diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc index 97ba15c32a3..4b02b09c27b 100644 --- a/src/gen-s-parser.inc +++ b/src/gen-s-parser.inc @@ -8,13 +8,21 @@ char op[27] = {'\0'}; strncpy(op, s[0]->c_str(), 26); switch (op[0]) { case 'a': { - switch (op[7]) { - case 'f': - if (strcmp(op, "atomic.fence") == 0) { return makeAtomicFence(s); } - goto parse_error; + switch (op[1]) { case 'n': - if (strcmp(op, "atomic.notify") == 0) { return makeAtomicNotify(s); } + if (strcmp(op, "anyref.pop") == 0) { return makePop(Type::anyref); } goto parse_error; + case 't': { + switch (op[7]) { + case 'f': + if (strcmp(op, "atomic.fence") == 0) { return makeAtomicFence(s); } + goto parse_error; + case 'n': + if (strcmp(op, "atomic.notify") == 0) { return makeAtomicNotify(s); } + goto parse_error; + default: goto parse_error; + } + } default: goto parse_error; } } diff --git a/src/ir/abstract.h b/src/ir/abstract.h index b00537bf59f..5f1fd393e4a 100644 --- a/src/ir/abstract.h +++ b/src/ir/abstract.h @@ -104,6 +104,7 @@ inline UnaryOp getUnary(Type type, Op op) { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: case Type::unreachable: { return InvalidUnary; @@ -268,6 +269,7 @@ inline BinaryOp getBinary(Type type, Op op) { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: case Type::unreachable: { return InvalidBinary; diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index 66de10848e1..fd121b8af38 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -36,6 +36,7 @@ function initializeConstants() { ['funcref', 'Funcref'], ['externref', 'Externref'], ['exnref', 'Exnref'], + ['anyref', 'Anyref'], ['unreachable', 'Unreachable'], ['auto', 'Auto'] ].forEach(entry => { @@ -120,6 +121,7 @@ function initializeConstants() { 'TailCall', 'ReferenceTypes', 'Multivalue', + 'Anyref', 'All' ].forEach(name => { Module['Features'][name] = Module['_BinaryenFeature' + name](); @@ -2063,6 +2065,12 @@ function wrapModule(module, self = {}) { } }; + self['anyref'] = { + 'pop'() { + return Module['_BinaryenPop'](module, Module['anyref']); + } + }; + self['ref'] = { 'null'(type) { return Module['_BinaryenRefNull'](module, type); diff --git a/src/literal.h b/src/literal.h index 1b3949d2114..981f5b6d4f8 100644 --- a/src/literal.h +++ b/src/literal.h @@ -579,6 +579,7 @@ template<> struct less { case wasm::Type::funcref: case wasm::Type::externref: case wasm::Type::exnref: + case wasm::Type::anyref: case wasm::Type::none: case wasm::Type::unreachable: return false; diff --git a/src/parsing.h b/src/parsing.h index 663b901fdce..d809cbedd2a 100644 --- a/src/parsing.h +++ b/src/parsing.h @@ -266,6 +266,7 @@ parseConst(cashew::IString s, Type type, MixedArena& allocator) { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: WASM_UNREACHABLE("unexpected const type"); case Type::none: case Type::unreachable: { diff --git a/src/passes/ConstHoisting.cpp b/src/passes/ConstHoisting.cpp index e3583d3bbfd..3b34751ffc9 100644 --- a/src/passes/ConstHoisting.cpp +++ b/src/passes/ConstHoisting.cpp @@ -96,7 +96,8 @@ struct ConstHoisting : public WalkerPass> { case Type::v128: case Type::funcref: case Type::externref: - case Type::exnref: { + case Type::exnref: + case Type::anyref: { return false; } case Type::none: diff --git a/src/passes/FuncCastEmulation.cpp b/src/passes/FuncCastEmulation.cpp index 160895f23be..10183479085 100644 --- a/src/passes/FuncCastEmulation.cpp +++ b/src/passes/FuncCastEmulation.cpp @@ -67,7 +67,8 @@ static Expression* toABI(Expression* value, Module* module) { } case Type::funcref: case Type::externref: - case Type::exnref: { + case Type::exnref: + case Type::anyref: { WASM_UNREACHABLE("reference types cannot be converted to i64"); } case Type::none: { @@ -110,7 +111,8 @@ static Expression* fromABI(Expression* value, Type type, Module* module) { } case Type::funcref: case Type::externref: - case Type::exnref: { + case Type::exnref: + case Type::anyref: { WASM_UNREACHABLE("reference types cannot be converted from i64"); } case Type::none: { diff --git a/src/passes/InstrumentLocals.cpp b/src/passes/InstrumentLocals.cpp index ee288c103b2..2a8a02e690c 100644 --- a/src/passes/InstrumentLocals.cpp +++ b/src/passes/InstrumentLocals.cpp @@ -59,6 +59,7 @@ Name get_f64("get_f64"); Name get_funcref("get_funcref"); Name get_externref("get_externref"); Name get_exnref("get_exnref"); +Name get_anyref("get_anyref"); Name get_v128("get_v128"); Name set_i32("set_i32"); @@ -68,6 +69,7 @@ Name set_f64("set_f64"); Name set_funcref("set_funcref"); Name set_externref("set_externref"); Name set_exnref("set_exnref"); +Name set_anyref("set_anyref"); Name set_v128("set_v128"); struct InstrumentLocals : public WalkerPass> { @@ -99,6 +101,9 @@ struct InstrumentLocals : public WalkerPass> { case Type::exnref: import = get_exnref; break; + case Type::anyref: + import = get_anyref; + break; case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -145,6 +150,9 @@ struct InstrumentLocals : public WalkerPass> { case Type::exnref: import = set_exnref; break; + case Type::anyref: + import = set_anyref; + break; case Type::unreachable: return; // nothing to do here case Type::none: @@ -191,6 +199,12 @@ struct InstrumentLocals : public WalkerPass> { addImport( curr, set_exnref, {Type::i32, Type::i32, Type::exnref}, Type::exnref); } + if (curr->features.hasAnyref()) { + addImport( + curr, get_anyref, {Type::i32, Type::i32, Type::anyref}, Type::anyref); + addImport( + curr, set_anyref, {Type::i32, Type::i32, Type::anyref}, Type::anyref); + } if (curr->features.hasSIMD()) { addImport(curr, get_v128, {Type::i32, Type::i32, Type::v128}, Type::v128); addImport(curr, set_v128, {Type::i32, Type::i32, Type::v128}, Type::v128); diff --git a/src/shell-interface.h b/src/shell-interface.h index 92f562b48c2..ae86d13ecd9 100644 --- a/src/shell-interface.h +++ b/src/shell-interface.h @@ -118,6 +118,7 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: globals[import->name] = {Literal::makeNull(import->type)}; break; case Type::none: diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h index ef7844c6046..641a7583f11 100644 --- a/src/tools/fuzzing.h +++ b/src/tools/fuzzing.h @@ -315,7 +315,21 @@ class TranslateToFuzzReader { } SmallVector options; options.push_back(type); // includes itself - // TODO (GC): subtyping + TODO_SINGLE_COMPOUND(type); + switch (type.getBasic()) { + case Type::anyref: + assert(wasm.features.hasAnyref()); + if (wasm.features.hasReferenceTypes()) { + options.push_back(Type::funcref); + options.push_back(Type::externref); + } + if (wasm.features.hasExceptionHandling()) { + options.push_back(Type::exnref); + } + break; + default: + break; + } return pick(options); } @@ -1349,6 +1363,7 @@ class TranslateToFuzzReader { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("invalid type"); @@ -1452,6 +1467,7 @@ class TranslateToFuzzReader { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("invalid type"); @@ -1580,6 +1596,7 @@ class TranslateToFuzzReader { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("invalid type"); @@ -1624,6 +1641,7 @@ class TranslateToFuzzReader { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -1691,6 +1709,7 @@ class TranslateToFuzzReader { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -1717,6 +1736,7 @@ class TranslateToFuzzReader { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -1826,6 +1846,7 @@ class TranslateToFuzzReader { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: return makeTrivial(type); case Type::none: case Type::unreachable: @@ -1970,6 +1991,7 @@ class TranslateToFuzzReader { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -2206,6 +2228,7 @@ class TranslateToFuzzReader { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -2412,6 +2435,7 @@ class TranslateToFuzzReader { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -2592,6 +2616,9 @@ class TranslateToFuzzReader { if (wasm.features.hasExceptionHandling()) { options.push_back(Type::exnref); } + if (wasm.features.hasAnyref()) { + options.push_back(Type::anyref); + } return builder.makeRefIsNull(make(pick(options))); } @@ -2657,7 +2684,8 @@ class TranslateToFuzzReader { .add(FeatureSet::SIMD, Type::v128) .add(FeatureSet::ReferenceTypes, Type::funcref, Type::externref) .add(FeatureSet::ReferenceTypes | FeatureSet::ExceptionHandling, - Type::exnref)); + Type::exnref) + .add(FeatureSet::ReferenceTypes | FeatureSet::Anyref, Type::anyref)); } Type getSingleConcreteType() { return pick(getSingleConcreteTypes()); } @@ -2697,7 +2725,7 @@ class TranslateToFuzzReader { // - funcref cannot be logged because referenced functions can be inlined or // removed during optimization - // - there's no point in logging externref because it is opaque + // - there's no point in logging externref or anyref because these are opaque // - don't bother logging tuples std::vector getLoggableTypes() { return items( diff --git a/src/tools/spec-wrapper.h b/src/tools/spec-wrapper.h index c073a994cc8..200571fd047 100644 --- a/src/tools/spec-wrapper.h +++ b/src/tools/spec-wrapper.h @@ -58,6 +58,9 @@ static std::string generateSpecWrapper(Module& wasm) { case Type::exnref: ret += "(ref.null exn)"; break; + case Type::anyref: + ret += "(ref.null any)"; + break; case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); diff --git a/src/tools/tool-options.h b/src/tools/tool-options.h index 6f0592a4531..12860bf1568 100644 --- a/src/tools/tool-options.h +++ b/src/tools/tool-options.h @@ -80,6 +80,7 @@ struct ToolOptions : public Options { .addFeature(FeatureSet::TailCall, "tail call operations") .addFeature(FeatureSet::ReferenceTypes, "reference types") .addFeature(FeatureSet::Multivalue, "multivalue functions") + .addFeature(FeatureSet::Anyref, "anyref type (without GC)") .add("--no-validation", "-n", "Disables validation, assumes inputs are correct", diff --git a/src/tools/wasm-reduce.cpp b/src/tools/wasm-reduce.cpp index 1a7c3544daa..7410ff91eb5 100644 --- a/src/tools/wasm-reduce.cpp +++ b/src/tools/wasm-reduce.cpp @@ -598,6 +598,7 @@ struct Reducer case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: continue; // not implemented yet case Type::none: case Type::unreachable: @@ -623,6 +624,7 @@ struct Reducer case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: continue; // not implemented yet case Type::none: case Type::unreachable: @@ -648,6 +650,7 @@ struct Reducer case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: continue; // not implemented yet case Type::none: case Type::unreachable: @@ -673,6 +676,7 @@ struct Reducer case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: continue; // not implemented yet case Type::none: case Type::unreachable: @@ -684,6 +688,7 @@ struct Reducer case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: continue; // not implemented yet case Type::none: case Type::unreachable: diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 865a882df65..33f78ce7f47 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -347,6 +347,8 @@ enum EncodedType { funcref = -0x10, // 0x70 // opaque host reference type externref = -0x11, // 0x6f + // any reference type + anyref = -0x12, // 0x6e // exception reference type exnref = -0x18, // 0x68 // func_type form @@ -358,6 +360,7 @@ enum EncodedType { enum EncodedHeapType { func = -0x10, // 0x70 extern_ = -0x11, // 0x6f + any = -0x12, // 0x6e exn = -0x18, // 0x68 }; @@ -380,6 +383,7 @@ extern const char* ExceptionHandlingFeature; extern const char* TailCallFeature; extern const char* ReferenceTypesFeature; extern const char* MultivalueFeature; +extern const char* AnyrefFeature; enum Subsection { NameFunction = 1, @@ -975,6 +979,9 @@ inline S32LEB binaryType(Type type) { case Type::exnref: ret = BinaryConsts::EncodedType::exnref; break; + case Type::anyref: + ret = BinaryConsts::EncodedType::anyref; + break; case Type::unreachable: WASM_UNREACHABLE("unexpected type"); } @@ -994,6 +1001,8 @@ inline S32LEB binaryHeapType(HeapType type) { ret = BinaryConsts::EncodedHeapType::exn; break; case HeapType::AnyKind: + ret = BinaryConsts::EncodedHeapType::any; + break; case HeapType::EqKind: case HeapType::I31Kind: case HeapType::SignatureKind: diff --git a/src/wasm-builder.h b/src/wasm-builder.h index 1ce3a507c6b..6c192348242 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -631,6 +631,7 @@ class Builder { return makeRefNull(value.type); case Type::externref: case Type::exnref: // TODO: ExceptionPackage? + case Type::anyref: assert(value.isNull()); return makeRefNull(value.type); default: @@ -825,6 +826,7 @@ class Builder { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: return ExpressionManipulator::refNull(curr, curr->type); case Type::none: return ExpressionManipulator::nop(curr); diff --git a/src/wasm-features.h b/src/wasm-features.h index c35ff0442dd..5d05b6284b7 100644 --- a/src/wasm-features.h +++ b/src/wasm-features.h @@ -36,7 +36,8 @@ struct FeatureSet { TailCall = 1 << 7, ReferenceTypes = 1 << 8, Multivalue = 1 << 9, - All = (1 << 10) - 1 + Anyref = 1 << 10, + All = (1 << 11) - 1 }; static std::string toString(Feature f) { @@ -61,6 +62,8 @@ struct FeatureSet { return "reference-types"; case Multivalue: return "multivalue"; + case Anyref: + return "anyref"; default: WASM_UNREACHABLE("unexpected feature"); } @@ -84,6 +87,7 @@ struct FeatureSet { bool hasTailCall() const { return (features & TailCall) != 0; } bool hasReferenceTypes() const { return (features & ReferenceTypes) != 0; } bool hasMultivalue() const { return (features & Multivalue) != 0; } + bool hasAnyref() const { return (features & Anyref) != 0; } bool hasAll() const { return (features & All) != 0; } void makeMVP() { features = MVP; } @@ -100,6 +104,7 @@ struct FeatureSet { void setTailCall(bool v = true) { set(TailCall, v); } void setReferenceTypes(bool v = true) { set(ReferenceTypes, v); } void setMultivalue(bool v = true) { set(Multivalue, v); } + void setAnyref(bool v = true) { set(Anyref, v); } void setAll(bool v = true) { features = v ? All : MVP; } void enable(const FeatureSet& other) { features |= other.features; } diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 44cac9d4960..361545a2ca2 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -1647,6 +1647,7 @@ template class ModuleInstanceBase { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -1703,6 +1704,7 @@ template class ModuleInstanceBase { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); diff --git a/src/wasm-type.h b/src/wasm-type.h index 384cc589fc1..f3973068f32 100644 --- a/src/wasm-type.h +++ b/src/wasm-type.h @@ -50,7 +50,8 @@ class Type { funcref, externref, exnref, - _last_basic_id = exnref + anyref, + _last_basic_id = anyref }; Type() = default; @@ -88,11 +89,11 @@ class Type { // │ v128 ║ x │ │ x │ x │ V │ ┘ // ├─ Aliases ───╫───┼───┼───┼───┤───────┤ // │ funcref ║ x │ │ x │ x │ f n │ ┐ Ref - // │ externref ║ x │ │ x │ x │ f? n │ │ f_unc, n_ullable - // │ anyref ║ x │ │ x │ x │ f? n │ │ ┐ - // │ eqref ║ x │ │ x │ x │ n │ │ │ TODO (GC) + // │ externref ║ x │ │ x │ x │ f? n │ │ f_unc + // │ exnref ║ x │ │ x │ x │ n │ │ n_ullable + // │ anyref ║ x │ │ x │ x │ f? n │ │ + // │ eqref ║ x │ │ x │ x │ n │ │ ┐ TODO (GC) // │ i31ref ║ x │ │ x │ x │ │ │ ┘ - // │ exnref ║ x │ │ x │ x │ n │ │ // ├─ Compound ──╫───┼───┼───┼───┤───────┤ │ // │ Ref ║ │ x │ x │ x │ f? n? │◄┘ // │ Tuple ║ │ x │ │ x │ │ @@ -330,11 +331,11 @@ struct HeapType { enum Kind { FuncKind, ExternKind, + ExnKind, AnyKind, EqKind, I31Kind, - ExnKind, - _last_basic_kind = ExnKind, + _last_basic_kind = I31Kind, SignatureKind, StructKind, ArrayKind, diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp index ec86428651e..eaf42869f9a 100644 --- a/src/wasm/literal.cpp +++ b/src/wasm/literal.cpp @@ -69,6 +69,7 @@ Literal::Literal(const Literal& other) : type(other.type) { case Type::none: break; case Type::externref: + case Type::anyref: break; // null case Type::funcref: case Type::exnref: @@ -221,6 +222,7 @@ void Literal::getBits(uint8_t (&buf)[16]) const { break; case Type::externref: case Type::exnref: + case Type::anyref: if (isNull()) { break; } @@ -384,6 +386,10 @@ std::ostream& operator<<(std::ostream& o, Literal literal) { o << "exnref(" << literal.getExceptionPackage() << ")"; } break; + case Type::anyref: + assert(literal.isNull() && "TODO: non-null anyref values"); + o << "anyref(null)"; + break; case Type::externref: assert(literal.isNull() && "TODO: non-null externref values"); o << "externref(null)"; @@ -612,6 +618,7 @@ Literal Literal::eqz() const { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -633,6 +640,7 @@ Literal Literal::neg() const { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -654,6 +662,7 @@ Literal Literal::abs() const { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -758,6 +767,7 @@ Literal Literal::add(const Literal& other) const { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -779,6 +789,7 @@ Literal Literal::sub(const Literal& other) const { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -871,6 +882,7 @@ Literal Literal::mul(const Literal& other) const { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -1124,6 +1136,7 @@ Literal Literal::eq(const Literal& other) const { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -1145,6 +1158,7 @@ Literal Literal::ne(const Literal& other) const { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index b78d6b86ba5..de82f065697 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -691,6 +691,8 @@ void WasmBinaryWriter::writeFeaturesSection() { return BinaryConsts::UserSections::ReferenceTypesFeature; case FeatureSet::Multivalue: return BinaryConsts::UserSections::MultivalueFeature; + case FeatureSet::Anyref: + return BinaryConsts::UserSections::AnyrefFeature; default: WASM_UNREACHABLE("unexpected feature flag"); } @@ -1138,6 +1140,8 @@ Type WasmBinaryBuilder::getType() { return Type::externref; case BinaryConsts::EncodedType::exnref: return Type::exnref; + case BinaryConsts::EncodedType::anyref: + return Type::anyref; default: throwError("invalid wasm type: " + std::to_string(type)); } @@ -1160,6 +1164,8 @@ HeapType WasmBinaryBuilder::getHeapType() { return HeapType::ExternKind; case BinaryConsts::EncodedHeapType::exn: return HeapType::ExnKind; + case BinaryConsts::EncodedHeapType::any: + return HeapType::AnyKind; default: throwError("invalid wasm heap type: " + std::to_string(type)); } @@ -2203,6 +2209,8 @@ void WasmBinaryBuilder::readFeatures(size_t payloadLen) { wasm.features.setReferenceTypes(); } else if (name == BinaryConsts::UserSections::MultivalueFeature) { wasm.features.setMultivalue(); + } else if (name == BinaryConsts::UserSections::AnyrefFeature) { + wasm.features.setAnyref(); } } } diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 0e4202a24d6..e8ef60fb86e 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -872,6 +872,9 @@ Type SExpressionWasmBuilder::stringToType(const char* str, if (strncmp(str, "exnref", 6) == 0 && (prefix || str[6] == 0)) { return Type::exnref; } + if (strncmp(str, "anyref", 6) == 0 && (prefix || str[6] == 0)) { + return Type::anyref; + } if (allowError) { return Type::none; } diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index aee5079c2e9..64622e81415 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -191,6 +191,7 @@ void BinaryInstWriter::visitLoad(Load* curr) { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: WASM_UNREACHABLE("unexpected type"); } @@ -292,6 +293,7 @@ void BinaryInstWriter::visitStore(Store* curr) { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -694,6 +696,7 @@ void BinaryInstWriter::visitConst(Const* curr) { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index 729cc88f5f7..368b8fe3a2c 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -256,12 +256,13 @@ std::unordered_map indices = { {TypeInfo(HeapType(HeapType::FuncKind), true), Type::funcref}, {TypeInfo({Type::externref}), Type::externref}, {TypeInfo(HeapType(HeapType::ExternKind), true), Type::externref}, + {TypeInfo({Type::exnref}), Type::exnref}, + {TypeInfo(HeapType(HeapType::ExnKind), true), Type::exnref}, + {TypeInfo({Type::anyref}), Type::anyref}, + {TypeInfo(HeapType(HeapType::AnyKind), true), Type::anyref}, // TODO (GC): Add canonical ids - // * `(ref null any) == anyref` // * `(ref null eq) == eqref` // * `(ref i31) == i31ref` - {TypeInfo({Type::exnref}), Type::exnref}, - {TypeInfo(HeapType(HeapType::ExnKind), true), Type::exnref}, }; } // anonymous namespace @@ -340,7 +341,7 @@ bool Type::isTuple() const { bool Type::isRef() const { if (isBasic()) { - return id >= funcref && id <= exnref; + return id >= funcref && id <= anyref; } else { return getTypeInfo(*this)->isRef(); } @@ -366,7 +367,7 @@ bool Type::isException() const { bool Type::isNullable() const { if (isBasic()) { - return id >= funcref && id <= exnref; + return id >= funcref && id <= anyref; } else { return getTypeInfo(*this)->isNullable(); } @@ -407,6 +408,7 @@ unsigned Type::getByteSize() const { case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: case Type::unreachable: break; @@ -451,6 +453,8 @@ FeatureSet Type::getFeatures() const { return FeatureSet::ReferenceTypes; case Type::exnref: return FeatureSet::ReferenceTypes | FeatureSet::ExceptionHandling; + case Type::anyref: + return FeatureSet::ReferenceTypes | FeatureSet::Anyref; default: return FeatureSet::MVP; } @@ -478,6 +482,8 @@ HeapType Type::getHeapType() const { return HeapType::ExternKind; case exnref: return HeapType::ExnKind; + case anyref: + return HeapType::AnyKind; default: break; } @@ -502,10 +508,12 @@ 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()) { + return right == Type::anyref; + } if (left.isTuple() && right.isTuple()) { if (left.size() != right.size()) { return false; @@ -533,6 +541,11 @@ Type Type::getLeastUpperBound(Type a, Type b) { if (a.size() != b.size()) { return Type::none; // a poison value that must not be consumed } + if (a.isRef()) { + // FIXME: `anyref` is only valid here if the `anyref` feature is enabled, + // but this information is not available within `Type` alone. + return b.isRef() ? Type::anyref : Type::none; + } if (a.isTuple()) { TypeList types; types.resize(a.size()); @@ -732,6 +745,9 @@ std::ostream& operator<<(std::ostream& os, Type type) { case Type::exnref: os << "exnref"; break; + case Type::anyref: + os << "anyref"; + break; } } else { os << *getTypeInfo(type); diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index b236f912024..c34d8265b47 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -1265,6 +1265,7 @@ void FunctionValidator::validateMemBytes(uint8_t bytes, case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: WASM_UNREACHABLE("unexpected type"); } @@ -2074,6 +2075,7 @@ void FunctionValidator::validateAlignment( case Type::funcref: case Type::externref: case Type::exnref: + case Type::anyref: case Type::none: WASM_UNREACHABLE("invalid type"); } diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index fe7c1b22983..31e05f42ec8 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -45,6 +45,7 @@ const char* SIMD128Feature = "simd128"; const char* TailCallFeature = "tail-call"; const char* ReferenceTypesFeature = "reference-types"; const char* MultivalueFeature = "multivalue"; +const char* AnyrefFeature = "anyref"; } // namespace UserSections } // namespace BinaryConsts diff --git a/test/binaryen.js/kitchen-sink.js b/test/binaryen.js/kitchen-sink.js index e820908581f..b9089046606 100644 --- a/test/binaryen.js/kitchen-sink.js +++ b/test/binaryen.js/kitchen-sink.js @@ -77,6 +77,9 @@ function test_types() { console.log(" // BinaryenTypeExnref: " + binaryen.exnref); console.log(" //", binaryen.expandType(binaryen.exnref).join(",")); + console.log(" // BinaryenTypeAnyref: " + binaryen.anyref); + console.log(" //", binaryen.expandType(binaryen.anyref).join(",")); + console.log(" // BinaryenTypeAuto: " + binaryen.auto); var i32_pair = binaryen.createType([binaryen.i32, binaryen.i32]); @@ -103,6 +106,7 @@ function test_features() { console.log("Features.TailCall: " + binaryen.Features.TailCall); console.log("Features.ReferenceTypes: " + binaryen.Features.ReferenceTypes); console.log("Features.Multivalue: " + binaryen.Features.Multivalue); + console.log("Features.Anyref: " + binaryen.Features.Anyref); console.log("Features.All: " + binaryen.Features.All); } diff --git a/test/binaryen.js/kitchen-sink.js.txt b/test/binaryen.js/kitchen-sink.js.txt index 917525eebcd..52b15f8ff34 100644 --- a/test/binaryen.js/kitchen-sink.js.txt +++ b/test/binaryen.js/kitchen-sink.js.txt @@ -18,6 +18,8 @@ // 8 // BinaryenTypeExnref: 9 // 9 + // BinaryenTypeAnyref: 10 + // 10 // BinaryenTypeAuto: -1 // 2,2 // 2,2 @@ -33,7 +35,8 @@ Features.ExceptionHandling: 64 Features.TailCall: 128 Features.ReferenceTypes: 256 Features.Multivalue: 512 -Features.All: 1023 +Features.Anyref: 1024 +Features.All: 2047 InvalidId: 0 BlockId: 1 IfId: 2 diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index b0a3ad30274..e242cfc8e02 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -211,6 +211,12 @@ void test_types() { BinaryenTypeExpand(exnref, &valueType); assert(valueType == exnref); + BinaryenType anyref = BinaryenTypeAnyref(); + printf(" // BinaryenTypeAnyref: %d\n", anyref); + assert(BinaryenTypeArity(anyref) == 1); + BinaryenTypeExpand(anyref, &valueType); + assert(valueType == anyref); + printf(" // BinaryenTypeAuto: %d\n", BinaryenTypeAuto()); BinaryenType pair[] = {i32, i32}; @@ -241,6 +247,7 @@ void test_features() { printf("BinaryenFeatureTailCall: %d\n", BinaryenFeatureTailCall()); printf("BinaryenFeatureReferenceTypes: %d\n", BinaryenFeatureReferenceTypes()); printf("BinaryenFeatureMultivalue: %d\n", BinaryenFeatureMultivalue()); + printf("BinaryenFeatureAnyref: %d\n", BinaryenFeatureAnyref()); printf("BinaryenFeatureAll: %d\n", BinaryenFeatureAll()); } diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt index 288174b9981..c5958ff1d87 100644 --- a/test/example/c-api-kitchen-sink.txt +++ b/test/example/c-api-kitchen-sink.txt @@ -8,6 +8,7 @@ // BinaryenTypeFuncref: 7 // BinaryenTypeExternref: 8 // BinaryenTypeExnref: 9 + // BinaryenTypeAnyref: 10 // BinaryenTypeAuto: -1 BinaryenFeatureMVP: 0 BinaryenFeatureAtomics: 1 @@ -20,7 +21,8 @@ BinaryenFeatureExceptionHandling: 64 BinaryenFeatureTailCall: 128 BinaryenFeatureReferenceTypes: 256 BinaryenFeatureMultivalue: 512 -BinaryenFeatureAll: 1023 +BinaryenFeatureAnyref: 1024 +BinaryenFeatureAll: 2047 (f32.neg (f32.const -33.61199951171875) ) diff --git a/test/example/typeinfo.cpp b/test/example/typeinfo.cpp index ac01c6a1b8c..345bc07887a 100644 --- a/test/example/typeinfo.cpp +++ b/test/example/typeinfo.cpp @@ -21,8 +21,15 @@ void test_compound() { HeapType sameExtern(HeapType::ExternKind); assert(Type(extern_, false).getID() == Type(sameExtern, false).getID()); + HeapType exn(HeapType::ExnKind); + assert(Type(exn, true).getID() == Type::exnref); + assert(Type(exn, false).getID() == Type(exn, false).getID()); + assert(Type(exn, false).getID() != Type(exn, true).getID()); + HeapType sameExn(HeapType::ExnKind); + assert(Type(exn, false).getID() == Type(sameExn, false).getID()); + HeapType any(HeapType::AnyKind); - // assert(Type(any, true).getID() == Type::anyref); + assert(Type(any, true).getID() == Type::anyref); assert(Type(any, false).getID() == Type(any, false).getID()); assert(Type(any, false).getID() != Type(any, true).getID()); HeapType sameAny(HeapType::AnyKind); @@ -41,13 +48,6 @@ void test_compound() { assert(Type(i31, false).getID() != Type(i31, true).getID()); HeapType sameI31(HeapType::I31Kind); assert(Type(i31, false).getID() == Type(sameI31, false).getID()); - - HeapType exn(HeapType::ExnKind); - assert(Type(exn, true).getID() == Type::exnref); - assert(Type(exn, false).getID() == Type(exn, false).getID()); - assert(Type(exn, false).getID() != Type(exn, true).getID()); - HeapType sameExn(HeapType::ExnKind); - assert(Type(exn, false).getID() == Type(sameExn, false).getID()); } { Signature signature(Type::i32, Type::none); diff --git a/test/example/typeinfo.txt b/test/example/typeinfo.txt index 95706d5e28b..539f305dbc4 100644 --- a/test/example/typeinfo.txt +++ b/test/example/typeinfo.txt @@ -6,7 +6,7 @@ extern externref (ref extern) any -(ref null any) +anyref (ref any) eq (ref null eq) diff --git a/test/passes/flatten_all-features.txt b/test/passes/flatten_all-features.txt index 896dc4ed019..e3d2ca55ed6 100644 --- a/test/passes/flatten_all-features.txt +++ b/test/passes/flatten_all-features.txt @@ -5,6 +5,7 @@ (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_=>_anyref (func (result anyref))) (memory $0 10) (table $0 1 1 funcref) (elem (i32.const 0) $call-me) @@ -2375,6 +2376,53 @@ ) (unreachable) ) + (func $subtype (result anyref) + (local $0 externref) + (local $1 anyref) + (local $2 externref) + (local $3 externref) + (local $4 externref) + (local $5 externref) + (local $6 externref) + (local $7 anyref) + (block $label0 + (block $block + (local.set $1 + (ref.null extern) + ) + (local.set $2 + (ref.null extern) + ) + (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 68bd7a64bf0..1eca29a126e 100644 --- a/test/passes/flatten_all-features.wast +++ b/test/passes/flatten_all-features.wast @@ -1028,19 +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 anyref) - ;; (block $label0 (result externref) - ;; (block (result anyref) - ;; (local.tee $0 - ;; (br_if $label0 - ;; (ref.null extern) - ;; (i32.const 0) - ;; ) - ;; ) - ;; ) - ;; ) - ;; ) + (func $subtype (result anyref) + (local $0 externref) + (block $label0 (result anyref) + (block (result externref) + (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 201a6f793d4..ad051c5e2dc 100644 --- a/test/passes/flatten_local-cse_all-features.txt +++ b/test/passes/flatten_local-cse_all-features.txt @@ -764,3 +764,52 @@ ) ) ) +(module + (type $none_=>_none (func)) + (type $none_=>_anyref (func (result anyref))) + (func $subtype-test (result anyref) + (local $0 funcref) + (local $1 funcref) + (local $2 anyref) + (local $3 anyref) + (block + (nop) + (loop $label$1 + (local.set $0 + (ref.null func) + ) + ) + (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 anyref) + (local $1 funcref) + (local $2 funcref) + (block $label$1 + (local.set $0 + (ref.null func) + ) + (local.set $1 + (ref.null func) + ) + ) + (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 05fbcb2ac64..da71122b14a 100644 --- a/test/passes/flatten_local-cse_all-features.wast +++ b/test/passes/flatten_local-cse_all-features.wast @@ -288,30 +288,29 @@ ) ) -;; 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) -;; ) -;; ) +(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 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) -;; ) -;; ) -;; ) -;; ) + (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/instrument-locals_all-features.txt b/test/passes/instrument-locals_all-features.txt index 91e71a48d11..cb46cb3efcb 100644 --- a/test/passes/instrument-locals_all-features.txt +++ b/test/passes/instrument-locals_all-features.txt @@ -7,6 +7,7 @@ (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_exnref_=>_exnref (func (param i32 i32 exnref) (result exnref))) + (type $i32_i32_anyref_=>_anyref (func (param i32 i32 anyref) (result anyref))) (type $none_=>_none (func)) (import "env" "get_i32" (func $get_i32 (param i32 i32 i32) (result i32))) (import "env" "get_i64" (func $get_i64 (param i32 i32 i64) (result i64))) @@ -22,6 +23,8 @@ (import "env" "set_externref" (func $set_externref (param i32 i32 externref) (result externref))) (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_anyref" (func $get_anyref (param i32 i32 anyref) (result anyref))) + (import "env" "set_anyref" (func $set_anyref (param i32 i32 anyref) (result anyref))) (import "env" "get_v128" (func $get_v128 (param i32 i32 v128) (result v128))) (import "env" "set_v128" (func $set_v128 (param i32 i32 v128) (result v128))) (func $test diff --git a/test/passes/merge-locals_all-features.txt b/test/passes/merge-locals_all-features.txt index 15039b4ce8e..0ba98f09a3d 100644 --- a/test/passes/merge-locals_all-features.txt +++ b/test/passes/merge-locals_all-features.txt @@ -1,6 +1,7 @@ (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)) @@ -456,4 +457,15 @@ ) ) ) + (func $subtype-test + (local $0 anyref) + (local $1 funcref) + (local $2 funcref) + (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 c12a02426be..1cdac26ec9c 100644 --- a/test/passes/merge-locals_all-features.wast +++ b/test/passes/merge-locals_all-features.wast @@ -375,18 +375,16 @@ ) ) ) - ;; 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) - ;; ) - ;; ) + (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 5677624cb83..6ff608ab77c 100644 --- a/test/passes/optimize-instructions_all-features.txt +++ b/test/passes/optimize-instructions_all-features.txt @@ -14,6 +14,7 @@ (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_=>_anyref (func (result anyref))) (memory $0 0) (export "load-off-2" (func $load-off-2)) (func $f (param $i1 i32) (param $i2 i64) @@ -3711,6 +3712,9 @@ (unreachable) ) ) + (func $if-arms-subtype (result anyref) + (ref.null extern) + ) (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 37d0d761858..aafb6c9d8b7 100644 --- a/test/passes/optimize-instructions_all-features.wast +++ b/test/passes/optimize-instructions_all-features.wast @@ -4207,15 +4207,14 @@ (unreachable) ) ) - ;; TODO (GC) ;; Tests when if arms are subtype of if's type - ;; (func $if-arms-subtype (result anyref) - ;; (if (result anyref) - ;; (i32.const 0) - ;; (ref.null extern) - ;; (ref.null func) - ;; ) - ;; ) + (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/simplify-locals_all-features.txt b/test/passes/simplify-locals_all-features.txt index f461a75804a..e04b8fb7a96 100644 --- a/test/passes/simplify-locals_all-features.txt +++ b/test/passes/simplify-locals_all-features.txt @@ -1881,6 +1881,19 @@ ) ) ) +(module + (type $none_=>_anyref (func (result anyref))) + (func $subtype-test (result anyref) + (local $0 externref) + (local $1 anyref) + (local $2 anyref) + (block $block + (nop) + ) + (nop) + (local.get $0) + ) +) (module (type $none_=>_none (func)) (type $i32_exnref_=>_none (func (param i32 exnref))) diff --git a/test/passes/simplify-locals_all-features.wast b/test/passes/simplify-locals_all-features.wast index b32da3df815..0a51e5371a2 100644 --- a/test/passes/simplify-locals_all-features.wast +++ b/test/passes/simplify-locals_all-features.wast @@ -1655,23 +1655,22 @@ ) ) ) -;; 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 + (func $subtype-test (result anyref) + (local $0 externref) + (local $1 anyref) + (local $2 anyref) + (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) 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 b01941639dc..7215bfadfd3 100644 --- a/test/passes/simplify-locals_all-features_disable-exception-handling.txt +++ b/test/passes/simplify-locals_all-features_disable-exception-handling.txt @@ -1875,3 +1875,16 @@ ) ) ) +(module + (type $none_=>_anyref (func (result anyref))) + (func $subtype-test (result anyref) + (local $0 funcref) + (local $1 anyref) + (local $2 anyref) + (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 c0f279cd0c8..f9806641c5c 100644 --- a/test/passes/simplify-locals_all-features_disable-exception-handling.wast +++ b/test/passes/simplify-locals_all-features_disable-exception-handling.wast @@ -1655,20 +1655,19 @@ ) ) ) -;; 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) -;; ) -;; ) +(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 d54c7bb4ef9..80e8d6bc79c 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 @@ -8,6 +8,7 @@ --enable-tail-call --enable-reference-types --enable-multivalue +--enable-anyref (module (type $none_=>_v128_externref (func (result v128 externref))) (func $foo (result v128 externref) diff --git a/test/passes/translate-to-fuzz_all-features.txt b/test/passes/translate-to-fuzz_all-features.txt index ab9a5b94634..4b7ec462a4f 100644 --- a/test/passes/translate-to-fuzz_all-features.txt +++ b/test/passes/translate-to-fuzz_all-features.txt @@ -1,20 +1,18 @@ (module (type $none_=>_none (func)) + (type $f32_=>_none (func (param f32))) + (type $exnref_=>_none (func (param exnref))) + (type $none_=>_i32_anyref_externref (func (result i32 anyref externref))) + (type $none_=>_externref_anyref_anyref_anyref (func (result externref anyref anyref anyref))) (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 $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 $anyref_funcref_externref_=>_f32 (func (param anyref funcref externref) (result f32))) (type $none_=>_v128 (func (result v128))) - (type $none_=>_funcref (func (result funcref))) + (type $none_=>_anyref (func (result anyref))) (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))) @@ -23,31 +21,29 @@ (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 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) + (table $0 2 funcref) + (elem (i32.const 0) $func_7 $func_11) + (global $global$5 (mut f32) (f32.const 74)) + (global $global$4 (mut exnref) (ref.null exn)) + (global $global$3 (mut i32) (i32.const 1263230471)) + (global $global$2 (mut i32) (i32.const -131072)) + (global $global$1 (mut (funcref exnref exnref externref anyref f64)) (tuple.make + (ref.null func) (ref.null exn) (ref.null exn) + (ref.null extern) + (ref.null any) + (f64.const 1.1754943508222875e-38) )) - (global $global$1 (mut exnref) (ref.null exn)) (global $hangLimit (mut i32) (i32.const 10)) - (event $event$0 (attr 0) (param i32)) + (event $event$0 (attr 0) (param exnref)) + (event $event$1 (attr 0) (param f32)) (export "hashMemory" (func $hashMemory)) (export "memory" (memory $0)) + (export "func_7" (func $func_7)) (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_16_invoker" (func $func_16_invoker)) - (export "func_19" (func $func_19)) + (export "func_10" (func $func_10)) + (export "func_11_invoker" (func $func_11_invoker)) (export "hangLimitInitializer" (func $hangLimitInitializer)) (func $hashMemory (result i32) (local $0 i32) @@ -280,14 +276,17 @@ ) (local.get $0) ) - (func $func_7 (param $0 i32) (param $1 v128) (param $2 f64) (param $3 i32) (result i32) + (func $func_7 (result anyref) + (local $0 i64) + (local $1 i64) + (local $2 anyref) (block (if (i32.eqz (global.get $hangLimit) ) (return - (i32.const 4883) + (ref.null any) ) ) (global.set $hangLimit @@ -297,65 +296,26 @@ ) ) ) - (local.tee $3 - (local.tee $0 - (local.get $3) - ) - ) + (ref.null any) ) (func $func_7_invoker (drop - (call $func_7 - (i32.const -119) - (v128.const i32x4 0x00000000 0x40410000 0x00000000 0x3ff00000) - (f64.const 3.433897990215153e-220) - (i32.const 255) - ) + (call $func_7) + ) + (drop + (call $func_7) ) (call $log-i32 (call $hashMemory) ) - ) - (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) - ) - ) + (drop + (call $func_7) ) - (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) - ) + (call $log-i32 + (call $hashMemory) ) ) - (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) + (func $func_9 (result externref anyref anyref anyref) (block (if (i32.eqz @@ -363,10 +323,10 @@ ) (return (tuple.make - (ref.func $func_10) - (ref.null exn) - (i32.const 0) (ref.null extern) + (ref.null any) + (ref.null any) + (ref.null any) ) ) ) @@ -378,22 +338,14 @@ ) ) (tuple.make - (ref.func $log-v128) - (ref.null exn) - (i32.const 26155) (ref.null extern) + (ref.null any) + (ref.null any) + (ref.null any) ) ) - (func $func_10_invoker - (drop - (call $func_10) - ) - (call $log-i32 - (call $hashMemory) - ) - ) - (func $func_12 - (local $0 exnref) + (func $func_10 (param $0 f64) (param $1 i32) (param $2 i64) (param $3 f64) (param $4 v128) + (local $5 exnref) (block (if (i32.eqz @@ -408,56 +360,478 @@ ) ) ) - (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) - ) + (block $label$0 + (call $log-i32 + (call $hashMemory) ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) + (call $log-f32 + (i32.load offset=4 align=2 + (i32.and + (local.tee $1 + (block $label$1 + (call $log-i32 + (block $label$2 (result i32) + (loop $label$3 + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block + (block $label$4 + (call $log-f32 + (global.get $global$5) + ) + (if + (local.tee $1 + (local.get $1) + ) + (block $label$5 + (call $log-f64 + (f64.reinterpret_i64 + (local.tee $2 + (block $label$6 + (call $log-f32 + (f32.min + (f32.const -1) + (f32.demote_f64 + (f64.copysign + (f64.const 28) + (local.get $3) + ) + ) + ) + ) + (br $label$5) + ) + ) + ) + ) + (call $log-i32 + (br_if $label$2 + (global.get $global$3) + (f64.lt + (f64.min + (tuple.extract 0 + (tuple.make + (f64.const 16240) + (ref.null any) + ) + ) + (f64.const -9223372036854775808) + ) + (f64x2.extract_lane 1 + (local.get $4) + ) + ) + ) + ) + ) + (block $label$7 + (local.set $0 + (loop $label$8 (result f64) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result f64) + (block $label$9 + (call $log-v128 + (local.get $4) + ) + (call $log-i32 + (call $hashMemory) + ) + ) + (br_if $label$8 + (i32.eqz + (local.tee $1 + (i32.const 977223545) + ) + ) + ) + (local.get $3) + ) + ) + ) + (call $log-f32 + (f32.const 2147483648) + ) + ) + ) + ) + (br_if $label$3 + (br_if $label$2 + (select + (i32.const 4612) + (local.get $1) + (local.get $1) + ) + (if + (i32.eqz + (i64.le_s + (local.get $2) + (local.get $2) + ) + ) + (block $label$10 + (br $label$3) + ) + (local.tee $1 + (if + (if (result i32) + (i32.const -16) + (block + (select + (if (result i32) + (i32.popcnt + (call $hashMemory) + ) + (block $label$15 (result i32) + (call $log-f32 + (f32.const 1291) + ) + (global.get $global$3) + ) + (block $label$16 + (call $log-i64 + (i64.const 1304720377604164420) + ) + (br $label$3) + ) + ) + (block $label$17 + (call $log-v128 + (i32x4.ne + (local.get $4) + (v128.const i32x4 0xffe3e76d 0x41dfffff 0xd70a3d70 0x3ffb70a3) + ) + ) + (br $label$3) + ) + (if (result i32) + (block $label$11 (result i32) + (nop) + (i32.const 127) + ) + (block $label$12 (result i32) + (call $log-v128 + (if (result v128) + (f32.ge + (f32.const -nan:0x7fffed) + (f32.mul + (f32.const -nan:0x7ffffc) + (f32.const -nan:0x7ffffc) + ) + ) + (v128.const i32x4 0x110b0c03 0x241c171e 0xffffffe9 0xffffffff) + (local.tee $4 + (local.tee $4 + (v128.const i32x4 0x00000000 0xfe000000 0xffffffff 0x00000fff) + ) + ) + ) + ) + (br_if $label$12 + (local.get $1) + (local.get $1) + ) + ) + (block $label$13 (result i32) + (v128.store offset=4 align=1 + (i32.and + (local.get $1) + (i32.const 15) + ) + (loop $label$14 (result v128) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (i64x2.splat + (i64.const 32767) + ) + ) + ) + (local.get $1) + ) + ) + ) + (drop + (i32.atomic.load offset=4 + (i32.and + (i64.lt_u + (local.get $2) + (local.tee $2 + (i64.extend_i32_u + (local.get $1) + ) + ) + ) + (i32.const 15) + ) + ) + ) + ) + (block $label$18 (result i32) + (call $log-i32 + (br_if $label$18 + (local.tee $1 + (br_if $label$18 + (ref.is_null + (ref.null exn) + ) + (i32.eqz + (i32.const 1997038858) + ) + ) + ) + (i32.eqz + (i8x16.extract_lane_u 3 + (tuple.extract 1 + (tuple.make + (f64.const 2) + (select + (local.get $4) + (v128.const i32x4 0x5b800000 0x4e800000 0x53000000 0x5f800000) + (i32.const -255) + ) + (ref.null any) + (ref.null func) + (f32x4.extract_lane 1 + (local.get $4) + ) + ) + ) + ) + ) + ) + ) + (br $label$3) + ) + ) + (block $label$19 + (loop $label$20 + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block $label$21 + (call $log-f64 + (local.tee $0 + (local.tee $0 + (local.get $3) + ) + ) + ) + (call $log-i32 + (local.get $1) + ) + ) + ) + (br $label$3) + ) + (block $label$22 + (call $log-v128 + (local.tee $4 + (loop $label$23 (result v128) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result v128) + (block $label$24 + (call $log-i64 + (local.tee $2 + (i64.const 576460752303423488) + ) + ) + (loop $label$25 + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block + (block $label$26 + (local.set $5 + (local.get $5) + ) + (call $log-v128 + (v128.const i32x4 0x00000014 0xffff8000 0x00000800 0xffffffe5) + ) + ) + (br_if $label$25 + (i32.eqz + (local.get $1) + ) + ) + (call $log-i32 + (call $hashMemory) + ) + ) + ) + ) + (br_if $label$23 + (i32.eqz + (loop $label$27 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result i32) + (call $log-f32 + (loop $label$28 (result f32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (f32.const 1) + ) + ) + (br_if $label$27 + (i32.eqz + (i32.atomic.load16_u offset=1 + (i32.and + (i32.const -11) + (i32.const 15) + ) + ) + ) + ) + (if (result i32) + (i32.const 358420504) + (local.get $1) + (block $label$29 (result i32) + (nop) + (local.get $1) + ) + ) + ) + ) + ) + ) + (local.get $4) + ) + ) + ) + ) + (br $label$3) + ) + ) + ) + ) + ) + ) + (v128.store offset=22 + (i32.and + (global.get $global$3) + (i32.const 15) + ) + (local.get $4) + ) + ) + ) + (block $label$31 + (return) + ) + ) + ) + (return) + ) + ) + (i32.const 15) + ) ) ) ) - (v128.const i32x4 0x1d00ff00 0x2a255500 0x01fbf800 0x0a000002) ) - (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) + (func $func_11 (param $0 anyref) (param $1 funcref) (param $2 externref) (result f32) (block (if (i32.eqz (global.get $hangLimit) ) (return - (i64.const -2097152) + (f32.const 510.8139953613281) ) ) (global.set $hangLimit @@ -467,27 +841,39 @@ ) ) ) - (block $label$0 - (nop) - (return - (i64.const -61) + (f32.const 4503599627370496) + ) + (func $func_11_invoker + (drop + (call $func_11 + (ref.null any) + (ref.func $func_7) + (ref.null extern) ) ) + (drop + (call $func_11 + (ref.null any) + (ref.func $log-f64) + (ref.null extern) + ) + ) + (call $log-i32 + (call $hashMemory) + ) ) - (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)) + (func $func_13 (result v128) + (local $0 i32) + (local $1 exnref) + (local $2 f64) (block (if (i32.eqz (global.get $hangLimit) ) - (return) + (return + (v128.const i32x4 0x016d0001 0x7a01017f 0x7901016d 0x00800056) + ) ) (global.set $hangLimit (i32.sub @@ -496,36 +882,27 @@ ) ) ) - (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) + (tuple.extract 0 + (tuple.make + (v128.const i32x4 0x41430000 0x00405556 0x2020ffdd 0x0005080a) + (i32.const 32768) + ) ) ) - (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) + (func $func_14 (result i32 anyref externref) + (local $0 i64) + (local $1 i32) (block (if (i32.eqz (global.get $hangLimit) ) (return - (f64.const -1073741824) + (tuple.make + (i32.const -91) + (ref.null any) + (ref.null extern) + ) ) ) (global.set $hangLimit @@ -535,45 +912,25 @@ ) ) ) - (select - (f64.const 35184372088832) - (f64x2.extract_lane 0 - (v128.const i32x4 0x55800000 0x4f800000 0x3def9db2 0x4e6dcc9d) - ) - (loop $label$0 (result i32) - (block + (block $label$0 + (f64.store offset=2 + (select + (local.get $1) + (local.get $1) (if (i32.eqz - (global.get $hangLimit) - ) - (return - (f64.const 4294967213) - ) - ) - (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) - ) - (nop) - ) - (br_if $label$0 - (i32.eqz - (loop $label$2 (result i32) + (loop $label$6 (result i32) (block (if (i32.eqz (global.get $hangLimit) ) (return - (f64.const 8589934591.815) + (tuple.make + (i32.const -16383) + (ref.null any) + (ref.null extern) + ) ) ) (global.set $hangLimit @@ -584,156 +941,257 @@ ) ) (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) + (nop) + (br_if $label$6 + (i32.eqz + (i32x4.extract_lane 0 + (v128.load offset=2 align=4 + (i16x8.extract_lane_u 5 + (if (result v128) + (local.get $1) + (block $label$7 (result v128) + (nop) + (v128.const i32x4 0xffff8001 0xffffffff 0x4d2b4835 0x00000000) + ) + (block $label$8 (result v128) + (block $label$9 + (call $log-i32 + (call $hashMemory) + ) + (nop) + ) + (v128.const i32x4 0x0d756b0d 0x0d0f0301 0x60626c7f 0x07092727) + ) + ) + ) ) - (i32.const 15) ) - (i32.atomic.rmw8.add_u offset=1 - (i32.and - (i32.const -93) - (i32.const 15) + ) + ) + (block $label$10 (result i32) + (loop $label$11 + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (tuple.make + (i32.const 622862719) + (ref.null any) + (ref.null extern) + ) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) ) - (i32.const 26) ) - ) - (br_if $label$15 - (i32.eqz - (i32.const 169416729) + (block + (br_if $label$6 + (loop $label$12 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (tuple.make + (i32.const 0) + (ref.null any) + (ref.null extern) + ) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block $label$13 (result i32) + (data.drop 0) + (i32.const 2) + ) + ) + ) + (br_if $label$11 + (local.get $1) + ) + (loop $label$14 + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (tuple.make + (i32.const 25948) + (ref.null any) + (ref.null extern) + ) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (f32.store offset=4 align=2 + (i32.and + (i32.atomic.rmw8.or_u offset=4 + (i32.and + (i32.const 13) + (i32.const 15) + ) + (atomic.notify offset=22 + (i32.and + (local.get $1) + (i32.const 15) + ) + (br_if $label$10 + (local.get $1) + (i32.eqz + (local.get $1) + ) + ) + ) + ) + (i32.const 15) + ) + (f32.const 18446744073709551615) + ) + ) ) ) - ) - (br_if $label$2 - (i32.const 1397565735) - ) - (tuple.extract 1 - (tuple.make - (f64.const -2.2250738585072014e-308) - (i32.const -86) - ) + (br $label$6) ) ) ) ) - ) - (if (result i32) - (if (result i32) - (i32.const -33) - (i32.trunc_f32_s - (f32.load offset=4 align=1 - (i32.const 1347440720) + (block $label$16 + (nop) + (return + (tuple.make + (i32.const 33554433) + (ref.null any) + (ref.null extern) ) ) - (i32.const -83) ) - (block $label$12 (result i32) - (nop) - (i32.const -5) + (block $label$17 + (call $log-i32 + (call $hashMemory) + ) + (return + (tuple.make + (i32.const 0) + (ref.null any) + (ref.null extern) + ) + ) ) - (if (result i32) - (i32.eqz - (i32.load offset=3 align=1 - (i32.and - (block $label$23 - (nop) + ) + ) + (f64x2.extract_lane 0 + (v128.const i32x4 0x14171109 0x0109440d 0x10031007 0x021d1401) + ) + ) + (if + (local.tee $1 + (local.tee $1 + (block $label$18 (result i32) + (call $log-f64 + (loop $label$19 (result f64) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) (return - (f64.const -1) + (tuple.make + (i32.const -10) + (ref.null any) + (ref.null extern) + ) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) ) ) - (i32.const 15) ) - ) - ) - (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) + (block (result f64) + (block $label$20 + (call $log-f32 + (block $label$21 + (call $log-i32 + (call $hashMemory) + ) + (br $label$19) ) - (return - (f64.const -2147483647.157) + ) + (call $log-i32 + (call $hashMemory) + ) + ) + (br_if $label$19 + (i32.eqz + (ref.is_null + (ref.null extern) ) ) ) + (f64.const 4294967278) ) ) - (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.atomic.load16_u offset=3 + (i32.and + (local.get $1) + (i32.const 15) ) ) - (i32.const 0) ) ) ) - ) - ) - ) - (func $func_19 (result f32) - (block - (if - (i32.eqz - (global.get $hangLimit) - ) - (return - (f32.const 8589934592) - ) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) + (block $label$1 + (return + (tuple.make + (i32.const -131072) + (ref.null any) + (ref.null extern) + ) + ) ) - ) - ) - (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 - (block $label$1 - (atomic.fence) - (return - (f32.const -512.8049926757812) - ) - ) - (i32.const 15) - ) - (i64.const -28) - (i64.const -524289) - ) - ) + (block $label$2 + (i32.atomic.store16 offset=4 + (i32.and + (local.tee $1 + (local.get $1) ) - (ref.null exn) + (i32.const 15) + ) + (local.tee $1 + (i32.const 843005738) + ) + ) + (return + (tuple.make + (i32.const -8388607) + (ref.null any) + (ref.null extern) ) ) ) - (i32.const 15) ) ) ) diff --git a/test/reference-types.wast b/test/reference-types.wast index 80755124ee9..ad0f908ce47 100644 --- a/test/reference-types.wast +++ b/test/reference-types.wast @@ -1,22 +1,24 @@ ;; reftype :: externref | funcref | exnref -;; 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. +;; NOTE: the subtyping relationship has been removed from the reference-types proposal but an +;; `--enable-anyref` feature flag is present in Binaryen that we use below to test subtyping. +;; +;; reftype :: reftype | anyref +;; reftype <: anyref (module (type $sig_externref (func (param externref))) (type $sig_funcref (func (param funcref))) (type $sig_exnref (func (param exnref))) - ;; (type $sig_anyref (func (param anyref))) + (type $sig_anyref (func (param anyref))) (func $take_externref (param externref)) (func $take_funcref (param funcref)) (func $take_exnref (param exnref)) - ;; (func $take_anyref (param anyref)) + (func $take_anyref (param anyref)) (func $foo) - (table funcref (elem $take_externref $take_funcref $take_exnref)) ;; $take_anyref + (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)) @@ -28,19 +30,19 @@ (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)) + (global $global_anyref (mut anyref) (ref.null any)) ;; Test subtype relationship in global initializer expressions - ;; (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)) + (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) + (local $local_anyref anyref) ;; Test types for local.get/set (local.set $local_externref (local.get $local_externref)) @@ -53,21 +55,21 @@ (local.set $local_exnref (local.get $local_exnref)) (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)) + (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 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)) + (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)) @@ -80,21 +82,21 @@ (global.set $global_exnref (global.get $global_exnref)) (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)) + (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)) + (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 function call params (call $take_externref (local.get $local_externref)) @@ -107,21 +109,21 @@ (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)) + (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)) + (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)) @@ -134,21 +136,21 @@ (call_indirect (type $sig_exnref) (local.get $local_exnref) (i32.const 2)) (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)) + (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 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)) + (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 @@ -201,58 +203,58 @@ (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)) - ;; ) - ;; ) + (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 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)) - ;; ) - ;; ) + (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 @@ -305,73 +307,73 @@ (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) - ;; ) - ;; ) + (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 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) - ;; ) - ;; ) + (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 @@ -395,64 +397,64 @@ (ref.null exn) ) ) - ;; (drop - ;; (if (result anyref) - ;; (i32.const 1) - ;; (local.get $local_anyref) - ;; (ref.null any) - ;; ) - ;; ) + (drop + (if (result anyref) + (i32.const 1) + (local.get $local_anyref) + (ref.null any) + ) + ) ;; 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) - ;; ) - ;; ) + (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 @@ -489,70 +491,70 @@ ) ;; 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) - ;; ) - ;; ) - ;; ) + (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 @@ -585,48 +587,48 @@ ) ;; 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) - ;; ) - ;; ) + (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))) @@ -639,9 +641,9 @@ (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))) + (drop (ref.is_null (local.get $local_anyref))) + (drop (ref.is_null (global.get $global_anyref))) + (drop (ref.is_null (ref.null any))) ) ;; Test function return type @@ -678,51 +680,51 @@ (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) - ;; ) + (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 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) - ;; ) + (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_exnref 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) @@ -744,27 +746,27 @@ (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)) - ;; ) + (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)) - ;; ) + (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 ac966053116..4e82da60d2f 100644 --- a/test/reference-types.wast.from-wast +++ b/test/reference-types.wast.from-wast @@ -1,4 +1,6 @@ (module + (type $none_=>_anyref (func (result anyref))) + (type $anyref_=>_none (func (param anyref))) (type $funcref_=>_none (func (param funcref))) (type $none_=>_funcref (func (result funcref))) (type $externref_=>_none (func (param externref))) @@ -9,12 +11,17 @@ (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 3 3 funcref) - (elem (i32.const 0) $take_externref $take_funcref $take_exnref) + (table $0 4 4 funcref) + (elem (i32.const 0) $take_externref $take_funcref $take_exnref $take_anyref) (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)) + (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)) (export "export_func" (func $import_func)) (export "export_global" (global $import_global)) (func $take_externref (param $0 externref) @@ -26,6 +33,9 @@ (func $take_exnref (param $0 exnref) (nop) ) + (func $take_anyref (param $0 anyref) + (nop) + ) (func $foo (nop) ) @@ -33,6 +43,7 @@ (local $local_externref externref) (local $local_funcref funcref) (local $local_exnref exnref) + (local $local_anyref anyref) (local.set $local_externref (local.get $local_externref) ) @@ -63,6 +74,45 @@ (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) + ) + (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) + ) (global.set $global_externref (global.get $global_externref) ) @@ -93,6 +143,45 @@ (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) + ) + (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) + ) (call $take_externref (local.get $local_externref) ) @@ -123,6 +212,45 @@ (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) + ) + (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) + ) (call_indirect (type $externref_=>_none) (local.get $local_externref) (i32.const 0) @@ -163,6 +291,58 @@ (ref.null exn) (i32.const 2) ) + (call_indirect (type $anyref_=>_none) + (local.get $local_anyref) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (global.get $global_anyref) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (ref.null any) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (local.get $local_externref) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (global.get $global_externref) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (ref.null extern) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (local.get $local_funcref) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (global.get $global_funcref) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (ref.null func) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (ref.func $foo) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (local.get $local_exnref) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (global.get $global_exnref) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (ref.null exn) + (i32.const 3) + ) (drop (block $block (result externref) (br_if $block @@ -243,53 +423,198 @@ ) ) ) + (drop + (block $block9 (result anyref) + (br_if $block9 + (local.get $local_anyref) + (i32.const 1) + ) + ) + ) + (drop + (block $block10 (result anyref) + (br_if $block10 + (global.get $global_anyref) + (i32.const 1) + ) + ) + ) + (drop + (block $block11 (result anyref) + (br_if $block11 + (ref.null any) + (i32.const 1) + ) + ) + ) + (drop + (block $block12 (result anyref) + (br_if $block12 + (local.get $local_externref) + (i32.const 1) + ) + ) + ) + (drop + (block $block13 (result anyref) + (br_if $block13 + (local.get $local_funcref) + (i32.const 1) + ) + ) + ) + (drop + (block $block14 (result anyref) + (br_if $block14 + (local.get $local_exnref) + (i32.const 1) + ) + ) + ) + (drop + (block $block15 (result anyref) + (br_if $block15 + (ref.null extern) + (i32.const 1) + ) + ) + ) + (drop + (block $block16 (result anyref) + (br_if $block16 + (ref.null func) + (i32.const 1) + ) + ) + ) + (drop + (block $block17 (result anyref) + (br_if $block17 + (ref.func $foo) + (i32.const 1) + ) + ) + ) + (drop + (block $block18 (result anyref) + (br_if $block18 + (ref.null exn) + (i32.const 1) + ) + ) + ) (drop (loop $loop-in (result externref) (local.get $local_externref) ) ) (drop - (loop $loop-in9 (result externref) + (loop $loop-in19 (result externref) (global.get $global_externref) ) ) (drop - (loop $loop-in10 (result externref) + (loop $loop-in20 (result externref) (ref.null extern) ) ) (drop - (loop $loop-in11 (result funcref) + (loop $loop-in21 (result funcref) (local.get $local_funcref) ) ) (drop - (loop $loop-in12 (result funcref) + (loop $loop-in22 (result funcref) (global.get $global_funcref) ) ) (drop - (loop $loop-in13 (result funcref) + (loop $loop-in23 (result funcref) (ref.null func) ) ) (drop - (loop $loop-in14 (result funcref) + (loop $loop-in24 (result funcref) (ref.func $foo) ) ) (drop - (loop $loop-in15 (result exnref) + (loop $loop-in25 (result exnref) (local.get $local_exnref) ) ) (drop - (loop $loop-in16 (result exnref) + (loop $loop-in26 (result exnref) (global.get $global_exnref) ) ) (drop - (loop $loop-in17 (result exnref) + (loop $loop-in27 (result exnref) + (ref.null exn) + ) + ) + (drop + (loop $loop-in28 (result anyref) + (local.get $local_anyref) + ) + ) + (drop + (loop $loop-in29 (result anyref) + (global.get $global_anyref) + ) + ) + (drop + (loop $loop-in30 (result anyref) + (ref.null any) + ) + ) + (drop + (loop $loop-in31 (result anyref) + (local.get $local_externref) + ) + ) + (drop + (loop $loop-in32 (result anyref) + (global.get $global_externref) + ) + ) + (drop + (loop $loop-in33 (result anyref) + (ref.null extern) + ) + ) + (drop + (loop $loop-in34 (result anyref) + (local.get $local_funcref) + ) + ) + (drop + (loop $loop-in35 (result anyref) + (global.get $global_funcref) + ) + ) + (drop + (loop $loop-in36 (result anyref) + (ref.null func) + ) + ) + (drop + (loop $loop-in37 (result anyref) + (ref.func $foo) + ) + ) + (drop + (loop $loop-in38 (result anyref) + (local.get $local_exnref) + ) + ) + (drop + (loop $loop-in39 (result anyref) + (global.get $global_exnref) + ) + ) + (drop + (loop $loop-in40 (result anyref) (ref.null exn) ) ) @@ -314,6 +639,62 @@ (ref.null exn) ) ) + (drop + (if (result anyref) + (i32.const 1) + (local.get $local_anyref) + (ref.null any) + ) + ) + (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) + ) + ) (drop (try (result externref) (do @@ -350,6 +731,78 @@ ) ) ) + (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) + ) + ) + ) (drop (select (result externref) (local.get $local_externref) @@ -378,6 +831,48 @@ (i32.const 1) ) ) + (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) + ) + ) (drop (ref.is_null (local.get $local_externref) @@ -428,6 +923,21 @@ (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) + ) + ) ) (func $return_externref_local (result externref) (local $local_externref externref) @@ -462,6 +972,49 @@ (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) + ) + (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_exnref exnref) + (local.get $local_exnref) + ) + (func $return_anyref10 (result anyref) + (global.get $global_exnref) + ) + (func $return_anyref11 (result anyref) + (ref.null exn) + ) (func $returns_externref (result externref) (local $local_externref externref) (return @@ -501,4 +1054,51 @@ (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) + ) + ) + (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.fromBinary b/test/reference-types.wast.fromBinary index f4a958d99ee..c266e725a74 100644 --- a/test/reference-types.wast.fromBinary +++ b/test/reference-types.wast.fromBinary @@ -1,4 +1,6 @@ (module + (type $none_=>_anyref (func (result anyref))) + (type $anyref_=>_none (func (param anyref))) (type $funcref_=>_none (func (param funcref))) (type $none_=>_funcref (func (result funcref))) (type $externref_=>_none (func (param externref))) @@ -9,12 +11,17 @@ (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 3 3 funcref) - (elem (i32.const 0) $take_externref $take_funcref $take_exnref) + (table $0 4 4 funcref) + (elem (i32.const 0) $take_externref $take_funcref $take_exnref $take_anyref) (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)) + (global $global$4 (mut anyref) (ref.null any)) + (global $global$5 (mut anyref) (ref.null extern)) + (global $global$6 (mut anyref) (ref.null func)) + (global $global$7 (mut anyref) (ref.func $foo)) + (global $global$8 (mut anyref) (ref.null exn)) (export "export_func" (func $import_func)) (export "export_global" (global $gimport$1)) (func $take_externref (param $0 externref) @@ -26,6 +33,9 @@ (func $take_exnref (param $0 exnref) (nop) ) + (func $take_anyref (param $0 anyref) + (nop) + ) (func $foo (nop) ) @@ -33,6 +43,7 @@ (local $0 funcref) (local $1 externref) (local $2 exnref) + (local $3 anyref) (local.set $1 (local.get $1) ) @@ -63,6 +74,45 @@ (local.set $2 (ref.null exn) ) + (local.set $3 + (local.get $3) + ) + (local.set $3 + (global.get $global$4) + ) + (local.set $3 + (ref.null any) + ) + (local.set $3 + (local.get $1) + ) + (local.set $3 + (global.get $global$0) + ) + (local.set $3 + (ref.null extern) + ) + (local.set $3 + (local.get $0) + ) + (local.set $3 + (global.get $global$1) + ) + (local.set $3 + (ref.null func) + ) + (local.set $3 + (ref.func $foo) + ) + (local.set $3 + (local.get $2) + ) + (local.set $3 + (global.get $global$3) + ) + (local.set $3 + (ref.null exn) + ) (global.set $global$0 (global.get $global$0) ) @@ -93,6 +143,45 @@ (global.set $global$3 (ref.null exn) ) + (global.set $global$4 + (global.get $global$4) + ) + (global.set $global$4 + (local.get $3) + ) + (global.set $global$4 + (ref.null any) + ) + (global.set $global$4 + (global.get $global$0) + ) + (global.set $global$4 + (local.get $1) + ) + (global.set $global$4 + (ref.null extern) + ) + (global.set $global$4 + (global.get $global$1) + ) + (global.set $global$4 + (local.get $0) + ) + (global.set $global$4 + (ref.null func) + ) + (global.set $global$4 + (ref.func $foo) + ) + (global.set $global$4 + (global.get $global$3) + ) + (global.set $global$4 + (local.get $2) + ) + (global.set $global$4 + (ref.null exn) + ) (call $take_externref (local.get $1) ) @@ -123,6 +212,45 @@ (call $take_exnref (ref.null exn) ) + (call $take_anyref + (local.get $3) + ) + (call $take_anyref + (global.get $global$4) + ) + (call $take_anyref + (ref.null any) + ) + (call $take_anyref + (local.get $1) + ) + (call $take_anyref + (global.get $global$0) + ) + (call $take_anyref + (ref.null extern) + ) + (call $take_anyref + (local.get $0) + ) + (call $take_anyref + (global.get $global$1) + ) + (call $take_anyref + (ref.null func) + ) + (call $take_anyref + (ref.func $foo) + ) + (call $take_anyref + (local.get $2) + ) + (call $take_anyref + (global.get $global$3) + ) + (call $take_anyref + (ref.null exn) + ) (call_indirect (type $externref_=>_none) (local.get $1) (i32.const 0) @@ -163,6 +291,58 @@ (ref.null exn) (i32.const 2) ) + (call_indirect (type $anyref_=>_none) + (local.get $3) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (global.get $global$4) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (ref.null any) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (local.get $1) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (global.get $global$0) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (ref.null extern) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (local.get $0) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (global.get $global$1) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (ref.null func) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (ref.func $foo) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (local.get $2) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (global.get $global$3) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (ref.null exn) + (i32.const 3) + ) (drop (block $label$1 (result externref) (br_if $label$1 @@ -244,52 +424,197 @@ ) ) (drop - (loop $label$11 (result externref) + (block $label$11 (result anyref) + (br_if $label$11 + (local.get $3) + (i32.const 1) + ) + ) + ) + (drop + (block $label$12 (result anyref) + (br_if $label$12 + (global.get $global$4) + (i32.const 1) + ) + ) + ) + (drop + (block $label$13 (result anyref) + (br_if $label$13 + (ref.null any) + (i32.const 1) + ) + ) + ) + (drop + (block $label$14 (result anyref) + (br_if $label$14 + (local.get $1) + (i32.const 1) + ) + ) + ) + (drop + (block $label$15 (result anyref) + (br_if $label$15 + (local.get $0) + (i32.const 1) + ) + ) + ) + (drop + (block $label$16 (result anyref) + (br_if $label$16 + (local.get $2) + (i32.const 1) + ) + ) + ) + (drop + (block $label$17 (result anyref) + (br_if $label$17 + (ref.null extern) + (i32.const 1) + ) + ) + ) + (drop + (block $label$18 (result anyref) + (br_if $label$18 + (ref.null func) + (i32.const 1) + ) + ) + ) + (drop + (block $label$19 (result anyref) + (br_if $label$19 + (ref.func $foo) + (i32.const 1) + ) + ) + ) + (drop + (block $label$20 (result anyref) + (br_if $label$20 + (ref.null exn) + (i32.const 1) + ) + ) + ) + (drop + (loop $label$21 (result externref) + (local.get $1) + ) + ) + (drop + (loop $label$22 (result externref) + (global.get $global$0) + ) + ) + (drop + (loop $label$23 (result externref) + (ref.null extern) + ) + ) + (drop + (loop $label$24 (result funcref) + (local.get $0) + ) + ) + (drop + (loop $label$25 (result funcref) + (global.get $global$1) + ) + ) + (drop + (loop $label$26 (result funcref) + (ref.null func) + ) + ) + (drop + (loop $label$27 (result funcref) + (ref.func $foo) + ) + ) + (drop + (loop $label$28 (result exnref) + (local.get $2) + ) + ) + (drop + (loop $label$29 (result exnref) + (global.get $global$3) + ) + ) + (drop + (loop $label$30 (result exnref) + (ref.null exn) + ) + ) + (drop + (loop $label$31 (result anyref) + (local.get $3) + ) + ) + (drop + (loop $label$32 (result anyref) + (global.get $global$4) + ) + ) + (drop + (loop $label$33 (result anyref) + (ref.null any) + ) + ) + (drop + (loop $label$34 (result anyref) (local.get $1) ) ) (drop - (loop $label$12 (result externref) + (loop $label$35 (result anyref) (global.get $global$0) ) ) (drop - (loop $label$13 (result externref) + (loop $label$36 (result anyref) (ref.null extern) ) ) (drop - (loop $label$14 (result funcref) + (loop $label$37 (result anyref) (local.get $0) ) ) (drop - (loop $label$15 (result funcref) + (loop $label$38 (result anyref) (global.get $global$1) ) ) (drop - (loop $label$16 (result funcref) + (loop $label$39 (result anyref) (ref.null func) ) ) (drop - (loop $label$17 (result funcref) + (loop $label$40 (result anyref) (ref.func $foo) ) ) (drop - (loop $label$18 (result exnref) + (loop $label$41 (result anyref) (local.get $2) ) ) (drop - (loop $label$19 (result exnref) + (loop $label$42 (result anyref) (global.get $global$3) ) ) (drop - (loop $label$20 (result exnref) + (loop $label$43 (result anyref) (ref.null exn) ) ) @@ -314,6 +639,62 @@ (ref.null exn) ) ) + (drop + (if (result anyref) + (i32.const 1) + (local.get $3) + (ref.null any) + ) + ) + (drop + (if (result anyref) + (i32.const 1) + (local.get $1) + (local.get $0) + ) + ) + (drop + (if (result anyref) + (i32.const 1) + (local.get $1) + (local.get $2) + ) + ) + (drop + (if (result anyref) + (i32.const 1) + (local.get $0) + (local.get $2) + ) + ) + (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) + ) + ) (drop (try (result externref) (do @@ -350,6 +731,78 @@ ) ) ) + (drop + (try (result anyref) + (do + (local.get $1) + ) + (catch + (drop + (exnref.pop) + ) + (ref.func $foo) + ) + ) + ) + (drop + (try (result anyref) + (do + (local.get $1) + ) + (catch + (exnref.pop) + ) + ) + ) + (drop + (try (result anyref) + (do + (ref.func $foo) + ) + (catch + (drop + (exnref.pop) + ) + (local.get $1) + ) + ) + ) + (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 $1) + ) + ) + ) + (drop + (try (result anyref) + (do + (ref.null exn) + ) + (catch + (drop + (exnref.pop) + ) + (ref.func $foo) + ) + ) + ) (drop (select (result externref) (local.get $1) @@ -378,6 +831,48 @@ (i32.const 1) ) ) + (drop + (select (result anyref) + (local.get $1) + (local.get $0) + (i32.const 1) + ) + ) + (drop + (select (result anyref) + (local.get $1) + (local.get $2) + (i32.const 1) + ) + ) + (drop + (select (result anyref) + (local.get $0) + (local.get $1) + (i32.const 1) + ) + ) + (drop + (select (result anyref) + (local.get $0) + (local.get $2) + (i32.const 1) + ) + ) + (drop + (select (result anyref) + (local.get $2) + (local.get $1) + (i32.const 1) + ) + ) + (drop + (select (result anyref) + (local.get $2) + (local.get $0) + (i32.const 1) + ) + ) (drop (ref.is_null (local.get $1) @@ -428,6 +923,21 @@ (ref.null exn) ) ) + (drop + (ref.is_null + (local.get $3) + ) + ) + (drop + (ref.is_null + (global.get $global$4) + ) + ) + (drop + (ref.is_null + (ref.null any) + ) + ) ) (func $return_externref_local (result externref) (local $0 externref) @@ -462,6 +972,49 @@ (func $return_exnref_null (result exnref) (ref.null exn) ) + (func $return_anyref_local (result anyref) + (local $0 anyref) + (local.get $0) + ) + (func $return_anyref_global (result anyref) + (global.get $global$4) + ) + (func $return_anyref_null (result anyref) + (ref.null any) + ) + (func $return_anyref2 (result anyref) + (local $0 externref) + (local.get $0) + ) + (func $return_anyref3 (result anyref) + (global.get $global$0) + ) + (func $return_anyref4 (result anyref) + (ref.null extern) + ) + (func $return_anyref5 (result anyref) + (local $0 funcref) + (local.get $0) + ) + (func $return_anyref6 (result anyref) + (global.get $global$1) + ) + (func $return_anyref7 (result anyref) + (ref.null func) + ) + (func $return_anyref8 (result anyref) + (ref.func $foo) + ) + (func $return_anyref9 (result anyref) + (local $0 exnref) + (local.get $0) + ) + (func $return_anyref10 (result anyref) + (global.get $global$3) + ) + (func $return_anyref11 (result anyref) + (ref.null exn) + ) (func $returns_externref (result externref) (local $0 externref) (return @@ -480,5 +1033,19 @@ (local.get $0) ) ) + (func $returns_anyref (result anyref) + (local $0 anyref) + (return + (local.get $0) + ) + ) + (func $returns_anyref2 (result anyref) + (local $0 funcref) + (local $1 externref) + (local $2 exnref) + (return + (local.get $1) + ) + ) ) diff --git a/test/reference-types.wast.fromBinary.noDebugInfo b/test/reference-types.wast.fromBinary.noDebugInfo index f0282f1e243..e1d18827ec0 100644 --- a/test/reference-types.wast.fromBinary.noDebugInfo +++ b/test/reference-types.wast.fromBinary.noDebugInfo @@ -1,4 +1,6 @@ (module + (type $none_=>_anyref (func (result anyref))) + (type $anyref_=>_none (func (param anyref))) (type $funcref_=>_none (func (param funcref))) (type $none_=>_funcref (func (result funcref))) (type $externref_=>_none (func (param externref))) @@ -9,12 +11,17 @@ (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 3 3 funcref) - (elem (i32.const 0) $0 $1 $2) + (table $0 4 4 funcref) + (elem (i32.const 0) $0 $1 $2 $3) (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$2 (mut funcref) (ref.func $4)) (global $global$3 (mut exnref) (ref.null exn)) + (global $global$4 (mut anyref) (ref.null any)) + (global $global$5 (mut anyref) (ref.null extern)) + (global $global$6 (mut anyref) (ref.null func)) + (global $global$7 (mut anyref) (ref.func $4)) + (global $global$8 (mut anyref) (ref.null exn)) (export "export_func" (func $fimport$0)) (export "export_global" (global $gimport$1)) (func $0 (param $0 externref) @@ -26,13 +33,17 @@ (func $2 (param $0 exnref) (nop) ) - (func $3 + (func $3 (param $0 anyref) (nop) ) (func $4 + (nop) + ) + (func $5 (local $0 funcref) (local $1 externref) (local $2 exnref) + (local $3 anyref) (local.set $1 (local.get $1) ) @@ -52,7 +63,7 @@ (ref.null func) ) (local.set $0 - (ref.func $3) + (ref.func $4) ) (local.set $2 (local.get $2) @@ -63,6 +74,45 @@ (local.set $2 (ref.null exn) ) + (local.set $3 + (local.get $3) + ) + (local.set $3 + (global.get $global$4) + ) + (local.set $3 + (ref.null any) + ) + (local.set $3 + (local.get $1) + ) + (local.set $3 + (global.get $global$0) + ) + (local.set $3 + (ref.null extern) + ) + (local.set $3 + (local.get $0) + ) + (local.set $3 + (global.get $global$1) + ) + (local.set $3 + (ref.null func) + ) + (local.set $3 + (ref.func $4) + ) + (local.set $3 + (local.get $2) + ) + (local.set $3 + (global.get $global$3) + ) + (local.set $3 + (ref.null exn) + ) (global.set $global$0 (global.get $global$0) ) @@ -82,7 +132,7 @@ (ref.null func) ) (global.set $global$1 - (ref.func $3) + (ref.func $4) ) (global.set $global$3 (global.get $global$3) @@ -93,6 +143,45 @@ (global.set $global$3 (ref.null exn) ) + (global.set $global$4 + (global.get $global$4) + ) + (global.set $global$4 + (local.get $3) + ) + (global.set $global$4 + (ref.null any) + ) + (global.set $global$4 + (global.get $global$0) + ) + (global.set $global$4 + (local.get $1) + ) + (global.set $global$4 + (ref.null extern) + ) + (global.set $global$4 + (global.get $global$1) + ) + (global.set $global$4 + (local.get $0) + ) + (global.set $global$4 + (ref.null func) + ) + (global.set $global$4 + (ref.func $4) + ) + (global.set $global$4 + (global.get $global$3) + ) + (global.set $global$4 + (local.get $2) + ) + (global.set $global$4 + (ref.null exn) + ) (call $0 (local.get $1) ) @@ -112,7 +201,7 @@ (ref.null func) ) (call $1 - (ref.func $3) + (ref.func $4) ) (call $2 (local.get $2) @@ -123,6 +212,45 @@ (call $2 (ref.null exn) ) + (call $3 + (local.get $3) + ) + (call $3 + (global.get $global$4) + ) + (call $3 + (ref.null any) + ) + (call $3 + (local.get $1) + ) + (call $3 + (global.get $global$0) + ) + (call $3 + (ref.null extern) + ) + (call $3 + (local.get $0) + ) + (call $3 + (global.get $global$1) + ) + (call $3 + (ref.null func) + ) + (call $3 + (ref.func $4) + ) + (call $3 + (local.get $2) + ) + (call $3 + (global.get $global$3) + ) + (call $3 + (ref.null exn) + ) (call_indirect (type $externref_=>_none) (local.get $1) (i32.const 0) @@ -148,7 +276,7 @@ (i32.const 1) ) (call_indirect (type $funcref_=>_none) - (ref.func $3) + (ref.func $4) (i32.const 1) ) (call_indirect (type $exnref_=>_none) @@ -163,6 +291,58 @@ (ref.null exn) (i32.const 2) ) + (call_indirect (type $anyref_=>_none) + (local.get $3) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (global.get $global$4) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (ref.null any) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (local.get $1) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (global.get $global$0) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (ref.null extern) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (local.get $0) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (global.get $global$1) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (ref.null func) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (ref.func $4) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (local.get $2) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (global.get $global$3) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (ref.null exn) + (i32.const 3) + ) (drop (block $label$1 (result externref) (br_if $label$1 @@ -214,7 +394,7 @@ (drop (block $label$7 (result funcref) (br_if $label$7 - (ref.func $3) + (ref.func $4) (i32.const 1) ) ) @@ -244,52 +424,197 @@ ) ) (drop - (loop $label$11 (result externref) + (block $label$11 (result anyref) + (br_if $label$11 + (local.get $3) + (i32.const 1) + ) + ) + ) + (drop + (block $label$12 (result anyref) + (br_if $label$12 + (global.get $global$4) + (i32.const 1) + ) + ) + ) + (drop + (block $label$13 (result anyref) + (br_if $label$13 + (ref.null any) + (i32.const 1) + ) + ) + ) + (drop + (block $label$14 (result anyref) + (br_if $label$14 + (local.get $1) + (i32.const 1) + ) + ) + ) + (drop + (block $label$15 (result anyref) + (br_if $label$15 + (local.get $0) + (i32.const 1) + ) + ) + ) + (drop + (block $label$16 (result anyref) + (br_if $label$16 + (local.get $2) + (i32.const 1) + ) + ) + ) + (drop + (block $label$17 (result anyref) + (br_if $label$17 + (ref.null extern) + (i32.const 1) + ) + ) + ) + (drop + (block $label$18 (result anyref) + (br_if $label$18 + (ref.null func) + (i32.const 1) + ) + ) + ) + (drop + (block $label$19 (result anyref) + (br_if $label$19 + (ref.func $4) + (i32.const 1) + ) + ) + ) + (drop + (block $label$20 (result anyref) + (br_if $label$20 + (ref.null exn) + (i32.const 1) + ) + ) + ) + (drop + (loop $label$21 (result externref) + (local.get $1) + ) + ) + (drop + (loop $label$22 (result externref) + (global.get $global$0) + ) + ) + (drop + (loop $label$23 (result externref) + (ref.null extern) + ) + ) + (drop + (loop $label$24 (result funcref) + (local.get $0) + ) + ) + (drop + (loop $label$25 (result funcref) + (global.get $global$1) + ) + ) + (drop + (loop $label$26 (result funcref) + (ref.null func) + ) + ) + (drop + (loop $label$27 (result funcref) + (ref.func $4) + ) + ) + (drop + (loop $label$28 (result exnref) + (local.get $2) + ) + ) + (drop + (loop $label$29 (result exnref) + (global.get $global$3) + ) + ) + (drop + (loop $label$30 (result exnref) + (ref.null exn) + ) + ) + (drop + (loop $label$31 (result anyref) + (local.get $3) + ) + ) + (drop + (loop $label$32 (result anyref) + (global.get $global$4) + ) + ) + (drop + (loop $label$33 (result anyref) + (ref.null any) + ) + ) + (drop + (loop $label$34 (result anyref) (local.get $1) ) ) (drop - (loop $label$12 (result externref) + (loop $label$35 (result anyref) (global.get $global$0) ) ) (drop - (loop $label$13 (result externref) + (loop $label$36 (result anyref) (ref.null extern) ) ) (drop - (loop $label$14 (result funcref) + (loop $label$37 (result anyref) (local.get $0) ) ) (drop - (loop $label$15 (result funcref) + (loop $label$38 (result anyref) (global.get $global$1) ) ) (drop - (loop $label$16 (result funcref) + (loop $label$39 (result anyref) (ref.null func) ) ) (drop - (loop $label$17 (result funcref) - (ref.func $3) + (loop $label$40 (result anyref) + (ref.func $4) ) ) (drop - (loop $label$18 (result exnref) + (loop $label$41 (result anyref) (local.get $2) ) ) (drop - (loop $label$19 (result exnref) + (loop $label$42 (result anyref) (global.get $global$3) ) ) (drop - (loop $label$20 (result exnref) + (loop $label$43 (result anyref) (ref.null exn) ) ) @@ -314,6 +639,62 @@ (ref.null exn) ) ) + (drop + (if (result anyref) + (i32.const 1) + (local.get $3) + (ref.null any) + ) + ) + (drop + (if (result anyref) + (i32.const 1) + (local.get $1) + (local.get $0) + ) + ) + (drop + (if (result anyref) + (i32.const 1) + (local.get $1) + (local.get $2) + ) + ) + (drop + (if (result anyref) + (i32.const 1) + (local.get $0) + (local.get $2) + ) + ) + (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 $4) + (ref.null extern) + ) + ) (drop (try (result externref) (do @@ -330,7 +711,7 @@ (drop (try (result funcref) (do - (ref.func $3) + (ref.func $4) ) (catch (drop @@ -350,6 +731,78 @@ ) ) ) + (drop + (try (result anyref) + (do + (local.get $1) + ) + (catch + (drop + (exnref.pop) + ) + (ref.func $4) + ) + ) + ) + (drop + (try (result anyref) + (do + (local.get $1) + ) + (catch + (exnref.pop) + ) + ) + ) + (drop + (try (result anyref) + (do + (ref.func $4) + ) + (catch + (drop + (exnref.pop) + ) + (local.get $1) + ) + ) + ) + (drop + (try (result anyref) + (do + (ref.func $4) + ) + (catch + (exnref.pop) + ) + ) + ) + (drop + (try (result anyref) + (do + (ref.null exn) + ) + (catch + (drop + (exnref.pop) + ) + (local.get $1) + ) + ) + ) + (drop + (try (result anyref) + (do + (ref.null exn) + ) + (catch + (drop + (exnref.pop) + ) + (ref.func $4) + ) + ) + ) (drop (select (result externref) (local.get $1) @@ -378,6 +831,48 @@ (i32.const 1) ) ) + (drop + (select (result anyref) + (local.get $1) + (local.get $0) + (i32.const 1) + ) + ) + (drop + (select (result anyref) + (local.get $1) + (local.get $2) + (i32.const 1) + ) + ) + (drop + (select (result anyref) + (local.get $0) + (local.get $1) + (i32.const 1) + ) + ) + (drop + (select (result anyref) + (local.get $0) + (local.get $2) + (i32.const 1) + ) + ) + (drop + (select (result anyref) + (local.get $2) + (local.get $1) + (i32.const 1) + ) + ) + (drop + (select (result anyref) + (local.get $2) + (local.get $0) + (i32.const 1) + ) + ) (drop (ref.is_null (local.get $1) @@ -410,7 +905,7 @@ ) (drop (ref.is_null - (ref.func $3) + (ref.func $4) ) ) (drop @@ -428,57 +923,129 @@ (ref.null exn) ) ) + (drop + (ref.is_null + (local.get $3) + ) + ) + (drop + (ref.is_null + (global.get $global$4) + ) + ) + (drop + (ref.is_null + (ref.null any) + ) + ) + ) + (func $6 (result externref) + (local $0 externref) + (local.get $0) + ) + (func $7 (result externref) + (global.get $global$0) + ) + (func $8 (result externref) + (ref.null extern) + ) + (func $9 (result funcref) + (local $0 funcref) + (local.get $0) + ) + (func $10 (result funcref) + (global.get $global$1) + ) + (func $11 (result funcref) + (ref.null func) + ) + (func $12 (result funcref) + (ref.func $4) + ) + (func $13 (result exnref) + (local $0 exnref) + (local.get $0) + ) + (func $14 (result exnref) + (global.get $global$3) + ) + (func $15 (result exnref) + (ref.null exn) + ) + (func $16 (result anyref) + (local $0 anyref) + (local.get $0) + ) + (func $17 (result anyref) + (global.get $global$4) + ) + (func $18 (result anyref) + (ref.null any) ) - (func $5 (result externref) + (func $19 (result anyref) (local $0 externref) (local.get $0) ) - (func $6 (result externref) + (func $20 (result anyref) (global.get $global$0) ) - (func $7 (result externref) + (func $21 (result anyref) (ref.null extern) ) - (func $8 (result funcref) + (func $22 (result anyref) (local $0 funcref) (local.get $0) ) - (func $9 (result funcref) + (func $23 (result anyref) (global.get $global$1) ) - (func $10 (result funcref) + (func $24 (result anyref) (ref.null func) ) - (func $11 (result funcref) - (ref.func $3) + (func $25 (result anyref) + (ref.func $4) ) - (func $12 (result exnref) + (func $26 (result anyref) (local $0 exnref) (local.get $0) ) - (func $13 (result exnref) + (func $27 (result anyref) (global.get $global$3) ) - (func $14 (result exnref) + (func $28 (result anyref) (ref.null exn) ) - (func $15 (result externref) + (func $29 (result externref) (local $0 externref) (return (local.get $0) ) ) - (func $16 (result funcref) + (func $30 (result funcref) (local $0 funcref) (return (local.get $0) ) ) - (func $17 (result exnref) + (func $31 (result exnref) (local $0 exnref) (return (local.get $0) ) ) + (func $32 (result anyref) + (local $0 anyref) + (return + (local.get $0) + ) + ) + (func $33 (result anyref) + (local $0 funcref) + (local $1 externref) + (local $2 exnref) + (return + (local.get $1) + ) + ) ) diff --git a/test/unit/input/anyref_target_feature.wasm b/test/unit/input/anyref_target_feature.wasm new file mode 100644 index 0000000000000000000000000000000000000000..88c61ebc2ab4f5be42ef6a1e5a9d8d79ba469f0e GIT binary patch literal 60 zcmZQbEY4+QU|?WlW6Wc`kjKrS#b1(Gl%84=pO%_fQd*Q+%%sg Date: Wed, 9 Sep 2020 05:11:58 +0200 Subject: [PATCH 02/14] remove a left-over comment --- test/passes/flatten_all-features.wast | 1 - 1 file changed, 1 deletion(-) diff --git a/test/passes/flatten_all-features.wast b/test/passes/flatten_all-features.wast index 1eca29a126e..14da24a74bc 100644 --- a/test/passes/flatten_all-features.wast +++ b/test/passes/flatten_all-features.wast @@ -1020,7 +1020,6 @@ (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 From add5e7d288dbf66119db670b05ea63f82541cac8 Mon Sep 17 00:00:00 2001 From: dcode Date: Wed, 9 Sep 2020 10:39:23 +0200 Subject: [PATCH 03/14] add implied feature validation, update unit tests accordingly --- src/wasm/wasm-validator.cpp | 15 +++++++ .../exception_handling_target_feature.wasm | Bin 89 -> 106 bytes test/unit/test_features.py | 37 ++++++++++++++++-- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index c34d8265b47..fed8d4d3bef 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -2375,6 +2375,20 @@ static void validateModule(Module& module, ValidationInfo& info) { } } +static void validateFeatures(Module& module, ValidationInfo& info) { + if (module.features.hasAnyref()) { + info.shouldBeTrue(module.features.hasReferenceTypes(), + module.features, + "--enable-anyref requires --enable-reference-types"); + } + if (module.features.hasExceptionHandling()) { // implies exnref + info.shouldBeTrue( + module.features.hasReferenceTypes(), + module.features, + "--enable-exception-handling requires --enable-reference-types"); + } +} + // TODO: If we want the validator to be part of libwasm rather than libpasses, // then Using PassRunner::getPassDebug causes a circular dependence. We should // fix that, perhaps by moving some of the pass infrastructure into libsupport. @@ -2395,6 +2409,7 @@ bool WasmValidator::validate(Module& module, Flags flags) { validateTable(module, info); validateEvents(module, info); validateModule(module, info); + validateFeatures(module, info); } // validate additional internal IR details when in pass-debug mode if (PassRunner::getPassDebug()) { diff --git a/test/unit/input/exception_handling_target_feature.wasm b/test/unit/input/exception_handling_target_feature.wasm index 487aaf679ae555e7015464fb28cbbdae586e3629..996cd2142786734370d437b2488963c039e1478d 100755 GIT binary patch delta 60 zcma#dnqX{h#$S?Hl%84=pO%_fQd*Q+%%m-pT9KSuP?DLSr<;+Omy(m2m#)oUl$w@W Pl$w{Es#{W7kXj4?l5`dm delta 43 ycmd0boM5b`%3qRLl%84=pO%_fQd*Q+%&0AtT9KSuP?DLSr<;+Omy(m2mkt0-zYnDV diff --git a/test/unit/test_features.py b/test/unit/test_features.py index 18e635ca807..b73674c43ee 100644 --- a/test/unit/test_features.py +++ b/test/unit/test_features.py @@ -42,8 +42,17 @@ def check_reference_types(self, module, error): self.check_feature(module, error, '--enable-reference-types') def check_multivalue(self, module, error): + self.check_feature(module, error, '--enable-multivalue') + + def check_multivalue_exception_handling(self, module, error): self.check_feature(module, error, '--enable-multivalue', - ['--enable-exception-handling']) + ['--enable-exception-handling', + '--enable-reference-types']) + + def check_anyref(self, module, error): + # Anyref handling implies reference types + self.check_feature(module, error, '--enable-anyref', + ['--enable-reference-types']) def test_v128_signature(self): module = ''' @@ -228,8 +237,8 @@ def test_multivalue_event(self): (event $foo (attr 0) (param i32 i64)) ) ''' - self.check_multivalue(module, 'Multivalue event type ' + - '(multivalue is not enabled)') + self.check_multivalue_exception_handling(module, + 'Multivalue event type (multivalue is not enabled)') def test_multivalue_block(self): module = ''' @@ -250,6 +259,26 @@ def test_multivalue_block(self): '(multivalue is not enabled)') + def test_anyref_global(self): + module = ''' + (module + (global $foo anyref (ref.null any)) + ) + ''' + self.check_anyref(module, 'all used types should be allowed') + + + def test_anyref_local(self): + module = ''' + (module + (func $foo + (local $0 anyref) + ) + ) + ''' + self.check_anyref(module, 'all used types should be allowed') + + class TargetFeaturesSectionTest(utils.BinaryenTestCase): def test_atomics(self): filename = 'atomics_target_feature.wasm' @@ -303,7 +332,7 @@ def test_reference_types(self): def test_exception_handling(self): filename = 'exception_handling_target_feature.wasm' self.roundtrip(filename) - self.check_features(filename, ['exception-handling']) + self.check_features(filename, ['exception-handling', 'reference-types']) self.assertIn('throw', self.disassemble(filename)) def test_anyref(self): From 67a139b12afda1e4d8641ae6412bd1855d7e3eee Mon Sep 17 00:00:00 2001 From: dcode Date: Wed, 9 Sep 2020 10:46:12 +0200 Subject: [PATCH 04/14] lint --- test/unit/test_features.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/unit/test_features.py b/test/unit/test_features.py index b73674c43ee..2b5b00469b7 100644 --- a/test/unit/test_features.py +++ b/test/unit/test_features.py @@ -237,8 +237,8 @@ def test_multivalue_event(self): (event $foo (attr 0) (param i32 i64)) ) ''' - self.check_multivalue_exception_handling(module, - 'Multivalue event type (multivalue is not enabled)') + self.check_multivalue_exception_handling(module, 'Multivalue event type ' + + '(multivalue is not enabled)') def test_multivalue_block(self): module = ''' @@ -258,7 +258,6 @@ def test_multivalue_block(self): self.check_multivalue(module, 'Multivalue block type ' + '(multivalue is not enabled)') - def test_anyref_global(self): module = ''' (module @@ -267,7 +266,6 @@ def test_anyref_global(self): ''' self.check_anyref(module, 'all used types should be allowed') - def test_anyref_local(self): module = ''' (module From 1b65a5ea3440ebab8e083733050a1a7645c0fd38 Mon Sep 17 00:00:00 2001 From: dcode Date: Wed, 9 Sep 2020 11:11:45 +0200 Subject: [PATCH 05/14] fix js event test --- test/binaryen.js/event.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/binaryen.js/event.js b/test/binaryen.js/event.js index 64d7659b815..f705edc3826 100644 --- a/test/binaryen.js/event.js +++ b/test/binaryen.js/event.js @@ -7,7 +7,9 @@ function cleanInfo(info) { } var module = new binaryen.Module(); -module.setFeatures(binaryen.Features.ExceptionHandling | binaryen.Features.Multivalue); +module.setFeatures(binaryen.Features.ReferenceTypes | + binaryen.Features.ExceptionHandling | + binaryen.Features.Multivalue); var pairType = binaryen.createType([binaryen.i32, binaryen.f32]); From fb1a789b0efdc88c6522e6986d34f2e101da77a4 Mon Sep 17 00:00:00 2001 From: dcode Date: Wed, 9 Sep 2020 11:34:13 +0200 Subject: [PATCH 06/14] teach the fuzzer about implied feature options --- scripts/fuzz_opt.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/scripts/fuzz_opt.py b/scripts/fuzz_opt.py index 49910349f29..898a4bbaabc 100755 --- a/scripts/fuzz_opt.py +++ b/scripts/fuzz_opt.py @@ -111,6 +111,9 @@ def randomize_feature_opts(): for possible in POSSIBLE_FEATURE_OPTS: if random.random() < 0.5: FEATURE_OPTS.append(possible) + if possible in IMPLIED_FEATURE_OPTS.keys(): + for implied in IMPLIED_FEATURE_OPTS[possible]: + FEATURE_OPTS.append(implied) print('randomized feature opts:', ' '.join(FEATURE_OPTS)) @@ -870,6 +873,12 @@ def randomize_opt_flags(): POSSIBLE_FEATURE_OPTS = run([in_bin('wasm-opt'), '--print-features', in_binaryen('test', 'hello_world.wat')] + CONSTANT_FEATURE_OPTS).replace('--enable', '--disable').strip().split('\n') print('POSSIBLE_FEATURE_OPTS:', POSSIBLE_FEATURE_OPTS) +# some features depend on other features, so if a required feature is +# disabled, its dependent features need to be disabled as well. +IMPLIED_FEATURE_OPTS = { + '--disable-reference-types': ['--disable-exception-handling', '--disable-anyref'] +} + if __name__ == '__main__': # if we are given a seed, run exactly that one testcase. otherwise, # run new ones until we fail From 1003b31b9ddef1d4423f90f42138c7b560f7a884 Mon Sep 17 00:00:00 2001 From: Daniel Wirtz Date: Wed, 9 Sep 2020 19:10:30 +0200 Subject: [PATCH 07/14] Update test/passes/flatten_local-cse_all-features.wast Co-authored-by: Heejin Ahn --- test/passes/flatten_local-cse_all-features.wast | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/passes/flatten_local-cse_all-features.wast b/test/passes/flatten_local-cse_all-features.wast index da71122b14a..660f56c1e9f 100644 --- a/test/passes/flatten_local-cse_all-features.wast +++ b/test/passes/flatten_local-cse_all-features.wast @@ -307,8 +307,8 @@ (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. + ;; --local-cse, even if we set (ref.null func) to local $0 above, this + ;; should not be replaced with $0, because it is of type anyref. (ref.null func) ) ) From 2809e6180be3937353f7c1d5221133984bc98918 Mon Sep 17 00:00:00 2001 From: Daniel Wirtz Date: Wed, 9 Sep 2020 20:45:13 +0200 Subject: [PATCH 08/14] Update scripts/fuzz_opt.py Co-authored-by: Thomas Lively <7121787+tlively@users.noreply.github.com> --- scripts/fuzz_opt.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/scripts/fuzz_opt.py b/scripts/fuzz_opt.py index 898a4bbaabc..4df552b993d 100755 --- a/scripts/fuzz_opt.py +++ b/scripts/fuzz_opt.py @@ -111,9 +111,8 @@ def randomize_feature_opts(): for possible in POSSIBLE_FEATURE_OPTS: if random.random() < 0.5: FEATURE_OPTS.append(possible) - if possible in IMPLIED_FEATURE_OPTS.keys(): - for implied in IMPLIED_FEATURE_OPTS[possible]: - FEATURE_OPTS.append(implied) + if possible in IMPLIED_FEATURE_OPTS: + FEATURE_OPTS.extend(IMPLIED_FEATURE_OPTS[possible]) print('randomized feature opts:', ' '.join(FEATURE_OPTS)) From bc2d52285f92310b3e776b3b4d9c947d5f03cd6d Mon Sep 17 00:00:00 2001 From: dcode Date: Thu, 10 Sep 2020 02:31:27 +0200 Subject: [PATCH 09/14] move hasY checks into hasX checks where Y requires X --- src/passes/InstrumentLocals.cpp | 24 ++++++++++++------------ src/tools/fuzzing.h | 7 ++----- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/passes/InstrumentLocals.cpp b/src/passes/InstrumentLocals.cpp index 2a8a02e690c..b1ce5f05e2f 100644 --- a/src/passes/InstrumentLocals.cpp +++ b/src/passes/InstrumentLocals.cpp @@ -192,18 +192,18 @@ struct InstrumentLocals : public WalkerPass> { set_externref, {Type::i32, Type::i32, Type::externref}, Type::externref); - } - if (curr->features.hasExceptionHandling()) { - addImport( - curr, get_exnref, {Type::i32, Type::i32, Type::exnref}, Type::exnref); - addImport( - curr, set_exnref, {Type::i32, Type::i32, Type::exnref}, Type::exnref); - } - if (curr->features.hasAnyref()) { - addImport( - curr, get_anyref, {Type::i32, Type::i32, Type::anyref}, Type::anyref); - addImport( - curr, set_anyref, {Type::i32, Type::i32, Type::anyref}, Type::anyref); + if (curr->features.hasExceptionHandling()) { + addImport( + curr, get_exnref, {Type::i32, Type::i32, Type::exnref}, Type::exnref); + addImport( + curr, set_exnref, {Type::i32, Type::i32, Type::exnref}, Type::exnref); + } + if (curr->features.hasAnyref()) { + addImport( + curr, get_anyref, {Type::i32, Type::i32, Type::anyref}, Type::anyref); + addImport( + curr, set_anyref, {Type::i32, Type::i32, Type::anyref}, Type::anyref); + } } if (curr->features.hasSIMD()) { addImport(curr, get_v128, {Type::i32, Type::i32, Type::v128}, Type::v128); diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h index 641a7583f11..1d542a46811 100644 --- a/src/tools/fuzzing.h +++ b/src/tools/fuzzing.h @@ -318,11 +318,8 @@ class TranslateToFuzzReader { TODO_SINGLE_COMPOUND(type); switch (type.getBasic()) { case Type::anyref: - assert(wasm.features.hasAnyref()); - if (wasm.features.hasReferenceTypes()) { - options.push_back(Type::funcref); - options.push_back(Type::externref); - } + options.push_back(Type::funcref); + options.push_back(Type::externref); if (wasm.features.hasExceptionHandling()) { options.push_back(Type::exnref); } From 4efa482c75aec9b5bb2a6701dfbbf11e154ef54c Mon Sep 17 00:00:00 2001 From: dcode Date: Thu, 10 Sep 2020 02:47:08 +0200 Subject: [PATCH 10/14] concretize comment on getLeastUpperBound returning anyref --- src/wasm/wasm-type.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index 368b8fe3a2c..41322770e3d 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -542,9 +542,16 @@ Type Type::getLeastUpperBound(Type a, Type b) { return Type::none; // a poison value that must not be consumed } if (a.isRef()) { - // FIXME: `anyref` is only valid here if the `anyref` feature is enabled, - // but this information is not available within `Type` alone. - return b.isRef() ? Type::anyref : Type::none; + if (b.isRef()) { + // Just returning `anyref` assumes that this method is never called with + // let's say `externref` and `funcref` where the anyref feature is not + // enabled, and that it would be a bug either in a pass or on the user's + // end during code generation if it did happen. If it turns out that it + // can happen otherwise, this method would need to take the enabled + // feature set as an additional argument at all call sites. + return Type::anyref; + } + return Type::none; } if (a.isTuple()) { TypeList types; From c2033c169ce5098f458afb2b4287e02d7bc95e4a Mon Sep 17 00:00:00 2001 From: dcode Date: Thu, 10 Sep 2020 02:53:40 +0200 Subject: [PATCH 11/14] add CHANGELOG entry --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 555fa70037d..8ef080c442a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,9 @@ Current Trunk ------------- - Remove asm2wasm, which supported Emscripten's fastcomp backend, after fastcomp was removed. +- Enabling the exception handling feature now requires enabling the reference + types feature as well since `exnref` depends on it. The same applies to the + new anyref feature where `anyref` depends on reference types. v96 --- From 6c76c1f8b439d711738ae1bffc7591c186b96f3f Mon Sep 17 00:00:00 2001 From: dcode Date: Thu, 10 Sep 2020 20:11:39 +0200 Subject: [PATCH 12/14] update getLeastUpperBound comment --- src/wasm/wasm-type.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index 41322770e3d..0c49e8dcc01 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -543,12 +543,11 @@ Type Type::getLeastUpperBound(Type a, Type b) { } if (a.isRef()) { if (b.isRef()) { - // Just returning `anyref` assumes that this method is never called with - // let's say `externref` and `funcref` where the anyref feature is not - // enabled, and that it would be a bug either in a pass or on the user's - // end during code generation if it did happen. If it turns out that it - // can happen otherwise, this method would need to take the enabled - // feature set as an additional argument at all call sites. + // The LUB of two different reference types is anyref, which may or may + // not be a valid type depending on whether the anyref feature is enabled. + // When anyref is disabled, it is possible for the finalization of invalid + // code to introduce a use of anyref via this function, but that is not a + // problem because it will be caught and rejected by validation. return Type::anyref; } return Type::none; From f877ef9915aae479cad1ce5eec72391fea8372e4 Mon Sep 17 00:00:00 2001 From: dcode Date: Thu, 10 Sep 2020 20:19:05 +0200 Subject: [PATCH 13/14] update CHANGELOG --- CHANGELOG.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ef080c442a..80534dab86e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,9 +16,10 @@ Current Trunk ------------- - Remove asm2wasm, which supported Emscripten's fastcomp backend, after fastcomp was removed. -- Enabling the exception handling feature now requires enabling the reference - types feature as well since `exnref` depends on it. The same applies to the - new anyref feature where `anyref` depends on reference types. +- The new feature flag `--enable-anyref` enables just the `anyref` type incl. + basic subtyping of `externref`, `funcref` and `exnref` (if enabled). +- Enabling the exception handling or anyref features without also enabling + reference types is a validation error now. v96 --- From 74be0b671092bf7c2905e8b742f5451467f98b45 Mon Sep 17 00:00:00 2001 From: dcode Date: Thu, 10 Sep 2020 20:22:29 +0200 Subject: [PATCH 14/14] restore condition in TranslateToFuzzReader::getSubType --- src/tools/fuzzing.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h index 1d542a46811..9768b63c48c 100644 --- a/src/tools/fuzzing.h +++ b/src/tools/fuzzing.h @@ -318,10 +318,12 @@ class TranslateToFuzzReader { TODO_SINGLE_COMPOUND(type); switch (type.getBasic()) { case Type::anyref: - options.push_back(Type::funcref); - options.push_back(Type::externref); - if (wasm.features.hasExceptionHandling()) { - options.push_back(Type::exnref); + if (wasm.features.hasReferenceTypes()) { + options.push_back(Type::funcref); + options.push_back(Type::externref); + if (wasm.features.hasExceptionHandling()) { + options.push_back(Type::exnref); + } } break; default: