diff options
30 files changed, 511 insertions, 132 deletions
diff --git a/scripts/fuzz_opt.py b/scripts/fuzz_opt.py index 1f79b2e07..448a00705 100755 --- a/scripts/fuzz_opt.py +++ b/scripts/fuzz_opt.py @@ -327,6 +327,7 @@ INITIAL_CONTENTS_IGNORE = [ 'typed_continuations.wast', 'typed_continuations_resume.wast', 'typed_continuations_contnew.wast', + 'typed_continuations_contbind.wast', # New EH implementation is in progress 'exception-handling.wast', 'translate-eh-old-to-new.wast', diff --git a/scripts/gen-s-parser.py b/scripts/gen-s-parser.py index 2e3c0a8f1..b2cac2b89 100755 --- a/scripts/gen-s-parser.py +++ b/scripts/gen-s-parser.py @@ -568,6 +568,7 @@ instructions = [ ("return_call_ref", "makeCallRef(s, /*isReturn=*/true)"), # Typed continuations instructions ("cont.new", "makeContNew(s)"), + ("cont.bind", "makeContBind(s)"), ("resume", "makeResume(s)"), # GC ("i31.new", "makeRefI31(s)"), # deprecated diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc index 01f138cc0..8f13750d4 100644 --- a/src/gen-s-parser.inc +++ b/src/gen-s-parser.inc @@ -169,9 +169,17 @@ switch (buf[0]) { default: goto parse_error; } } - case 'o': - if (op == "cont.new"sv) { return makeContNew(s); } - goto parse_error; + case 'o': { + switch (buf[5]) { + case 'b': + if (op == "cont.bind"sv) { return makeContBind(s); } + goto parse_error; + case 'n': + if (op == "cont.new"sv) { return makeContNew(s); } + goto parse_error; + default: goto parse_error; + } + } default: goto parse_error; } } @@ -3853,12 +3861,23 @@ switch (buf[0]) { default: goto parse_error; } } - case 'o': - if (op == "cont.new"sv) { - CHECK_ERR(makeContNew(ctx, pos, annotations)); - return Ok{}; + case 'o': { + switch (buf[5]) { + case 'b': + if (op == "cont.bind"sv) { + CHECK_ERR(makeContBind(ctx, pos, annotations)); + return Ok{}; + } + goto parse_error; + case 'n': + if (op == "cont.new"sv) { + CHECK_ERR(makeContNew(ctx, pos, annotations)); + return Ok{}; + } + goto parse_error; + default: goto parse_error; } - goto parse_error; + } default: goto parse_error; } } diff --git a/src/ir/ReFinalize.cpp b/src/ir/ReFinalize.cpp index 7c81b0d0d..6d872056a 100644 --- a/src/ir/ReFinalize.cpp +++ b/src/ir/ReFinalize.cpp @@ -183,6 +183,7 @@ void ReFinalize::visitStringSliceIter(StringSliceIter* curr) { } void ReFinalize::visitContNew(ContNew* curr) { curr->finalize(); } +void ReFinalize::visitContBind(ContBind* curr) { curr->finalize(); } void ReFinalize::visitResume(Resume* curr) { curr->finalize(); } void ReFinalize::visitExport(Export* curr) { WASM_UNREACHABLE("unimp"); } diff --git a/src/ir/cost.h b/src/ir/cost.h index 7a8776c00..d66c97282 100644 --- a/src/ir/cost.h +++ b/src/ir/cost.h @@ -726,6 +726,16 @@ struct CostAnalyzer : public OverriddenVisitor<CostAnalyzer, CostType> { return 8 + visit(curr->ref) + visit(curr->num); } + CostType visitContBind(ContBind* curr) { + // Inspired by struct.new: The only cost of cont.bind is that it may need to + // allocate a buffer to hold the arguments. + CostType ret = 4; + ret += visit(curr->cont); + for (auto* arg : curr->operands) { + ret += visit(arg); + } + return ret; + } CostType visitContNew(ContNew* curr) { // Some arbitrary "high" value, reflecting that this may allocate a stack return 14 + visit(curr->func); diff --git a/src/ir/effects.h b/src/ir/effects.h index d0af932bd..0b3d2a4af 100644 --- a/src/ir/effects.h +++ b/src/ir/effects.h @@ -974,6 +974,10 @@ private: parent.implicitTrap = true; } + void visitContBind(ContBind* curr) { + // traps when curr->cont is null ref. + parent.implicitTrap = true; + } void visitContNew(ContNew* curr) { // traps when curr->func is null ref. parent.implicitTrap = true; diff --git a/src/ir/module-utils.cpp b/src/ir/module-utils.cpp index b61fddd8b..c2f48eec8 100644 --- a/src/ir/module-utils.cpp +++ b/src/ir/module-utils.cpp @@ -341,6 +341,9 @@ struct CodeScanner counts.include(get->type); } else if (auto* set = curr->dynCast<ArraySet>()) { counts.note(set->ref->type); + } else if (auto* contBind = curr->dynCast<ContBind>()) { + counts.note(contBind->contTypeBefore); + counts.note(contBind->contTypeAfter); } else if (auto* contNew = curr->dynCast<ContNew>()) { counts.note(contNew->contType); } else if (auto* resume = curr->dynCast<Resume>()) { diff --git a/src/ir/possible-contents.cpp b/src/ir/possible-contents.cpp index d0b0ea3ae..44015c113 100644 --- a/src/ir/possible-contents.cpp +++ b/src/ir/possible-contents.cpp @@ -1200,6 +1200,10 @@ struct InfoCollector void visitReturn(Return* curr) { addResult(curr->value); } + void visitContBind(ContBind* curr) { + // TODO: optimize when possible + addRoot(curr); + } void visitContNew(ContNew* curr) { // TODO: optimize when possible addRoot(curr); diff --git a/src/ir/subtype-exprs.h b/src/ir/subtype-exprs.h index ab0ace53d..553c1497b 100644 --- a/src/ir/subtype-exprs.h +++ b/src/ir/subtype-exprs.h @@ -391,6 +391,7 @@ struct SubtypingDiscoverer : public OverriddenVisitor<SubType> { void visitStringSliceWTF(StringSliceWTF* curr) {} void visitStringSliceIter(StringSliceIter* curr) {} + void visitContBind(ContBind* curr) { WASM_UNREACHABLE("not implemented"); } void visitContNew(ContNew* curr) { WASM_UNREACHABLE("not implemented"); } void visitResume(Resume* curr) { WASM_UNREACHABLE("not implemented"); } }; diff --git a/src/parser/contexts.h b/src/parser/contexts.h index 4c15c0308..08cebe33b 100644 --- a/src/parser/contexts.h +++ b/src/parser/contexts.h @@ -808,6 +808,11 @@ struct NullInstrParserCtx { return Ok{}; } template<typename HeapTypeT> + Result<> + makeContBind(Index, const std::vector<Annotation>&, HeapTypeT, HeapTypeT) { + return Ok{}; + } + template<typename HeapTypeT> Result<> makeContNew(Index, const std::vector<Annotation>&, HeapTypeT) { return Ok{}; } @@ -2547,6 +2552,13 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> { return withLoc(pos, irBuilder.makeStringSliceIter()); } + Result<> makeContBind(Index pos, + const std::vector<Annotation>& annotations, + HeapType contTypeBefore, + HeapType contTypeAfter) { + return withLoc(pos, irBuilder.makeContBind(contTypeBefore, contTypeAfter)); + } + Result<> makeContNew(Index pos, const std::vector<Annotation>& annotations, HeapType type) { diff --git a/src/parser/parsers.h b/src/parser/parsers.h index 4a2b99d84..0dde4b765 100644 --- a/src/parser/parsers.h +++ b/src/parser/parsers.h @@ -304,6 +304,8 @@ Result<> makeStringSliceWTF(Ctx&, template<typename Ctx> Result<> makeStringSliceIter(Ctx&, Index, const std::vector<Annotation>&); template<typename Ctx> +Result<> makeContBind(Ctx&, Index, const std::vector<Annotation>&); +template<typename Ctx> Result<> makeContNew(Ctx*, Index, const std::vector<Annotation>&); template<typename Ctx> Result<> makeResume(Ctx&, Index, const std::vector<Annotation>&); @@ -2459,6 +2461,19 @@ Result<> makeStringSliceIter(Ctx& ctx, return ctx.makeStringSliceIter(pos, annotations); } +// contbind ::= 'cont.bind' typeidx typeidx +template<typename Ctx> +Result<> +makeContBind(Ctx& ctx, Index pos, const std::vector<Annotation>& annotations) { + auto typeBefore = typeidx(ctx); + CHECK_ERR(typeBefore); + + auto typeAfter = typeidx(ctx); + CHECK_ERR(typeAfter); + + return ctx.makeContBind(pos, annotations, *typeBefore, *typeAfter); +} + template<typename Ctx> Result<> makeContNew(Ctx& ctx, Index pos, const std::vector<Annotation>& annotations) { diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index abe68f13d..3f0cfbabb 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -2378,7 +2378,12 @@ struct PrintExpressionContents void visitStringSliceIter(StringSliceIter* curr) { printMedium(o, "stringview_iter.slice"); } - + void visitContBind(ContBind* curr) { + printMedium(o, "cont.bind "); + printHeapType(curr->contTypeBefore); + o << ' '; + printHeapType(curr->contTypeAfter); + } void visitContNew(ContNew* curr) { printMedium(o, "cont.new "); printHeapType(curr->contType); diff --git a/src/passes/TypeGeneralizing.cpp b/src/passes/TypeGeneralizing.cpp index c19766ae3..10dfe8737 100644 --- a/src/passes/TypeGeneralizing.cpp +++ b/src/passes/TypeGeneralizing.cpp @@ -875,6 +875,7 @@ struct TransferFn : OverriddenVisitor<TransferFn> { void visitStringSliceWTF(StringSliceWTF* curr) { WASM_UNREACHABLE("TODO"); } void visitStringSliceIter(StringSliceIter* curr) { WASM_UNREACHABLE("TODO"); } + void visitContBind(ContBind* curr) { WASM_UNREACHABLE("TODO"); } void visitContNew(ContNew* curr) { WASM_UNREACHABLE("TODO"); } void visitResume(Resume* curr) { WASM_UNREACHABLE("TODO"); } }; diff --git a/src/wasm-binary.h b/src/wasm-binary.h index c1d79ec2a..082b711d7 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1299,6 +1299,7 @@ enum ASTNodes { // typed continuation opcodes ContNew = 0xe0, + ContBind = 0xe1, Resume = 0xe3, }; @@ -1928,6 +1929,7 @@ public: void visitRefAsCast(RefCast* curr, uint32_t code); void visitRefAs(RefAs* curr, uint8_t code); void visitContNew(ContNew* curr); + void visitContBind(ContBind* curr); void visitResume(Resume* curr); [[noreturn]] void throwError(std::string text); diff --git a/src/wasm-builder.h b/src/wasm-builder.h index 03fddb178..eb1874c3b 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -1198,6 +1198,18 @@ public: return ret; } + ContBind* makeContBind(HeapType contTypeBefore, + HeapType contTypeAfter, + const std::vector<Expression*>& operands, + Expression* cont) { + auto* ret = wasm.allocator.alloc<ContBind>(); + ret->contTypeBefore = contTypeBefore; + ret->contTypeAfter = contTypeAfter; + ret->operands.set(operands); + ret->cont = cont; + ret->finalize(); + return ret; + } ContNew* makeContNew(HeapType contType, Expression* func) { auto* ret = wasm.allocator.alloc<ContNew>(); ret->contType = contType; diff --git a/src/wasm-delegations-fields.def b/src/wasm-delegations-fields.def index c895c31dd..ac0256cf2 100644 --- a/src/wasm-delegations-fields.def +++ b/src/wasm-delegations-fields.def @@ -946,6 +946,15 @@ switch (DELEGATE_ID) { break; } + case Expression::Id::ContBindId: { + DELEGATE_START(ContBind); + DELEGATE_FIELD_CHILD(ContBind, cont); + DELEGATE_FIELD_CHILD_VECTOR(ContBind, operands); + DELEGATE_FIELD_HEAPTYPE(ContBind, contTypeAfter); + DELEGATE_FIELD_HEAPTYPE(ContBind, contTypeBefore); + DELEGATE_END(ContBind); + break; + } case Expression::Id::ContNewId: { DELEGATE_START(ContNew); DELEGATE_FIELD_CHILD(ContNew, func); diff --git a/src/wasm-delegations.def b/src/wasm-delegations.def index 5a57e399b..c07a78f8b 100644 --- a/src/wasm-delegations.def +++ b/src/wasm-delegations.def @@ -105,6 +105,7 @@ DELEGATE(StringIterNext); DELEGATE(StringIterMove); DELEGATE(StringSliceWTF); DELEGATE(StringSliceIter); +DELEGATE(ContBind); DELEGATE(ContNew); DELEGATE(Resume); diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index f1b081e51..47b8d5eb5 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -2401,6 +2401,7 @@ public: } return ExpressionRunner<SubType>::visitRefAs(curr); } + Flow visitContBind(ContBind* curr) { WASM_UNREACHABLE("unimplemented"); } Flow visitContNew(ContNew* curr) { WASM_UNREACHABLE("unimplemented"); } Flow visitResume(Resume* curr) { WASM_UNREACHABLE("unimplemented"); } @@ -3976,6 +3977,7 @@ public: multiValues.pop_back(); return ret; } + Flow visitContBind(ContBind* curr) { return Flow(NONCONSTANT_FLOW); } Flow visitContNew(ContNew* curr) { return Flow(NONCONSTANT_FLOW); } Flow visitResume(Resume* curr) { return Flow(NONCONSTANT_FLOW); } diff --git a/src/wasm-ir-builder.h b/src/wasm-ir-builder.h index d31a532a7..917080fc4 100644 --- a/src/wasm-ir-builder.h +++ b/src/wasm-ir-builder.h @@ -210,6 +210,8 @@ public: [[nodiscard]] Result<> makeStringIterMove(StringIterMoveOp op); [[nodiscard]] Result<> makeStringSliceWTF(StringSliceWTFOp op); [[nodiscard]] Result<> makeStringSliceIter(); + [[nodiscard]] Result<> makeContBind(HeapType contTypeBefore, + HeapType contTypeAfter); [[nodiscard]] Result<> makeContNew(HeapType ct); [[nodiscard]] Result<> makeResume(HeapType ct, const std::vector<Name>& tags, @@ -252,6 +254,7 @@ public: [[nodiscard]] Result<> visitThrow(Throw*); [[nodiscard]] Result<> visitStringNew(StringNew*); [[nodiscard]] Result<> visitStringEncode(StringEncode*); + [[nodiscard]] Result<> visitContBind(ContBind*); [[nodiscard]] Result<> visitResume(Resume*); [[nodiscard]] Result<> visitTupleMake(TupleMake*); [[nodiscard]] Result<> diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index 953599a1e..e1d9dab47 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -328,6 +328,7 @@ private: Expression* makeStringIterMove(Element& s, StringIterMoveOp op); Expression* makeStringSliceWTF(Element& s, StringSliceWTFOp op); Expression* makeStringSliceIter(Element& s); + Expression* makeContBind(Element& s); Expression* makeContNew(Element& s); Expression* makeResume(Element& s); diff --git a/src/wasm.h b/src/wasm.h index 3da245547..ad7ccb3ad 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -743,6 +743,7 @@ public: StringIterMoveId, StringSliceWTFId, StringSliceIterId, + ContBindId, ContNewId, ResumeId, NumExpressionIds @@ -1998,6 +1999,18 @@ public: void finalize(); }; +class ContBind : public SpecificExpression<Expression::ContBindId> { +public: + ContBind(MixedArena& allocator) : operands(allocator) {} + + HeapType contTypeBefore; + HeapType contTypeAfter; + ExpressionList operands; + Expression* cont; + + void finalize(); +}; + class ContNew : public SpecificExpression<Expression::ContNewId> { public: ContNew() = default; diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 6f41c3c87..efb65bb50 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -4046,6 +4046,10 @@ BinaryConsts::ASTNodes WasmBinaryReader::readExpression(Expression*& curr) { visitCallRef(call); break; } + case BinaryConsts::ContBind: { + visitContBind((curr = allocator.alloc<ContBind>())->cast<ContBind>()); + break; + } case BinaryConsts::ContNew: { auto contNew = allocator.alloc<ContNew>(); curr = contNew; @@ -7768,6 +7772,43 @@ void WasmBinaryReader::visitRefAs(RefAs* curr, uint8_t code) { curr->finalize(); } +void WasmBinaryReader::visitContBind(ContBind* curr) { + BYN_TRACE("zz node: ContBind\n"); + + auto contTypeBeforeIndex = getU32LEB(); + curr->contTypeBefore = getTypeByIndex(contTypeBeforeIndex); + + auto contTypeAfterIndex = getU32LEB(); + curr->contTypeAfter = getTypeByIndex(contTypeAfterIndex); + + for (auto& ct : {curr->contTypeBefore, curr->contTypeAfter}) { + if (!ct.isContinuation()) { + throwError("non-continuation type in cont.bind instruction " + + ct.toString()); + } + } + + curr->cont = popNonVoidExpression(); + + size_t paramsBefore = + curr->contTypeBefore.getContinuation().type.getSignature().params.size(); + size_t paramsAfter = + curr->contTypeAfter.getContinuation().type.getSignature().params.size(); + if (paramsBefore < paramsAfter) { + throwError("incompatible continuation types in cont.bind: source type " + + curr->contTypeBefore.toString() + + " has fewer parameters than destination " + + curr->contTypeAfter.toString()); + } + size_t numArgs = paramsBefore - paramsAfter; + curr->operands.resize(numArgs); + for (size_t i = 0; i < numArgs; i++) { + curr->operands[numArgs - i - 1] = popNonVoidExpression(); + } + + curr->finalize(); +} + void WasmBinaryReader::visitContNew(ContNew* curr) { BYN_TRACE("zz node: ContNew\n"); diff --git a/src/wasm/wasm-ir-builder.cpp b/src/wasm/wasm-ir-builder.cpp index 8d87d0f33..628a257c7 100644 --- a/src/wasm/wasm-ir-builder.cpp +++ b/src/wasm/wasm-ir-builder.cpp @@ -619,6 +619,32 @@ Result<> IRBuilder::visitStringEncode(StringEncode* curr) { WASM_UNREACHABLE("unexpected op"); } +Result<> IRBuilder::visitContBind(ContBind* curr) { + auto cont = pop(); + CHECK_ERR(cont); + curr->cont = *cont; + + size_t paramsBefore = + curr->contTypeBefore.getContinuation().type.getSignature().params.size(); + size_t paramsAfter = + curr->contTypeAfter.getContinuation().type.getSignature().params.size(); + if (paramsBefore < paramsAfter) { + return Err{"incompatible continuation types in cont.bind: source type " + + curr->contTypeBefore.toString() + + " has fewer parameters than destination " + + curr->contTypeAfter.toString()}; + } + size_t numArgs = paramsBefore - paramsAfter; + + curr->operands.resize(numArgs); + for (size_t i = 0; i < numArgs; ++i) { + auto val = pop(); + CHECK_ERR(val); + curr->operands[numArgs - i - 1] = *val; + } + return Ok{}; +} + Result<> IRBuilder::visitResume(Resume* curr) { auto cont = pop(); CHECK_ERR(cont); @@ -1833,6 +1859,22 @@ Result<> IRBuilder::makeStringSliceIter() { return Ok{}; } +Result<> IRBuilder::makeContBind(HeapType contTypeBefore, + HeapType contTypeAfter) { + if (!contTypeBefore.isContinuation() || !contTypeAfter.isContinuation()) { + return Err{"expected continuation types"}; + } + ContBind curr(wasm.allocator); + curr.contTypeBefore = contTypeBefore; + curr.contTypeAfter = contTypeAfter; + CHECK_ERR(visitContBind(&curr)); + + std::vector<Expression*> operands(curr.operands.begin(), curr.operands.end()); + push( + builder.makeContBind(contTypeBefore, contTypeAfter, operands, curr.cont)); + return Ok{}; +} + Result<> IRBuilder::makeContNew(HeapType ct) { if (!ct.isContinuation()) { return Err{"expected continuation type"}; diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index b7113d2b2..44ba84351 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -2990,6 +2990,29 @@ Expression* SExpressionWasmBuilder::makeCallRef(Element& s, bool isReturn) { target, operands, sigType.getSignature().results, isReturn); } +Expression* SExpressionWasmBuilder::makeContBind(Element& s) { + auto ret = allocator.alloc<ContBind>(); + + ret->contTypeBefore = parseHeapType(*s[1]); + if (!ret->contTypeBefore.isContinuation()) { + throw ParseException("expected continuation type", s[1]->line, s[1]->col); + } + ret->contTypeAfter = parseHeapType(*s[2]); + if (!ret->contTypeAfter.isContinuation()) { + throw ParseException("expected continuation type", s[2]->line, s[2]->col); + } + + Index i = 3; + while (i < s.size() - 1) { + ret->operands.push_back(parseExpression(s[i++])); + } + + ret->cont = parseExpression(s[i]); + + ret->finalize(); + return ret; +} + Expression* SExpressionWasmBuilder::makeContNew(Element& s) { auto ret = allocator.alloc<ContNew>(); diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 0857e9a0d..90d5a3768 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -2489,6 +2489,12 @@ void BinaryInstWriter::visitStringSliceIter(StringSliceIter* curr) { << U32LEB(BinaryConsts::StringViewIterSlice); } +void BinaryInstWriter::visitContBind(ContBind* curr) { + o << int8_t(BinaryConsts::ContBind); + parent.writeIndexedHeapType(curr->contTypeBefore); + parent.writeIndexedHeapType(curr->contTypeAfter); +} + void BinaryInstWriter::visitContNew(ContNew* curr) { o << int8_t(BinaryConsts::ContNew); parent.writeIndexedHeapType(curr->contType); diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index d745585e5..4bb556160 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -487,6 +487,7 @@ public: void visitStringIterMove(StringIterMove* curr); void visitStringSliceWTF(StringSliceWTF* curr); void visitStringSliceIter(StringSliceIter* curr); + void visitContBind(ContBind* curr); void visitContNew(ContNew* curr); void visitResume(Resume* curr); @@ -3295,6 +3296,24 @@ void FunctionValidator::visitStringSliceIter(StringSliceIter* curr) { "string operations require reference-types [--enable-strings]"); } +void FunctionValidator::visitContBind(ContBind* curr) { + // TODO implement actual type-checking + shouldBeTrue( + !getModule() || getModule()->features.hasTypedContinuations(), + curr, + "cont.bind requires typed-continuatons [--enable-typed-continuations]"); + + shouldBeTrue((curr->contTypeBefore.isContinuation() && + curr->contTypeBefore.getContinuation().type.isSignature()), + curr, + "invalid first type in ContBind expression"); + + shouldBeTrue((curr->contTypeAfter.isContinuation() && + curr->contTypeAfter.getContinuation().type.isSignature()), + curr, + "invalid second type in ContBind expression"); +} + void FunctionValidator::visitContNew(ContNew* curr) { // TODO implement actual type-checking shouldBeTrue( diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index ce5fd7006..374a97e19 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -1352,6 +1352,8 @@ void StringSliceIter::finalize() { } } +void ContBind::finalize() { type = Type(contTypeAfter, NonNullable); } + void ContNew::finalize() { type = Type(contType, NonNullable); } static void populateResumeSentTypes(Resume* curr, Module* wasm) { diff --git a/src/wasm2js.h b/src/wasm2js.h index 92ba397be..5f0305877 100644 --- a/src/wasm2js.h +++ b/src/wasm2js.h @@ -2428,6 +2428,10 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, WASM_UNREACHABLE("unimp"); } + Ref visitContBind(ContBind* curr) { + unimplemented(curr); + WASM_UNREACHABLE("unimp"); + } Ref visitContNew(ContNew* curr) { unimplemented(curr); WASM_UNREACHABLE("unimp"); diff --git a/test/lit/basic/typed_continuations_contbind.wast b/test/lit/basic/typed_continuations_contbind.wast new file mode 100644 index 000000000..065d4a796 --- /dev/null +++ b/test/lit/basic/typed_continuations_contbind.wast @@ -0,0 +1,98 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. + +;; RUN: wasm-opt %s -all -o %t.text.wast -g -S +;; RUN: wasm-as %s -all -g -o %t.wasm +;; RUN: wasm-dis %t.wasm -all -o %t.bin.wast +;; RUN: wasm-as %s -all -o %t.nodebug.wasm +;; RUN: wasm-dis %t.nodebug.wasm -all -o %t.bin.nodebug.wast +;; RUN: cat %t.text.wast | filecheck %s --check-prefix=CHECK-TEXT +;; RUN: cat %t.bin.wast | filecheck %s --check-prefix=CHECK-BIN +;; RUN: cat %t.bin.nodebug.wast | filecheck %s --check-prefix=CHECK-BIN-NODEBUG + +(module + ;; CHECK-TEXT: (type $ft1 (func (param i32 i64 i32) (result i32))) + ;; CHECK-BIN: (type $ft1 (func (param i32 i64 i32) (result i32))) + (type $ft1 (func (param i32 i64 i32) (result i32))) + ;; CHECK-TEXT: (type $ct1 (cont $ft1)) + + ;; CHECK-TEXT: (type $ft2 (func (param i32) (result i32))) + ;; CHECK-BIN: (type $ct1 (cont $ft1)) + + ;; CHECK-BIN: (type $ft2 (func (param i32) (result i32))) + (type $ft2 (func (param i32) (result i32))) + (type $ct1 (cont $ft1)) + ;; CHECK-TEXT: (type $ct2 (cont $ft2)) + ;; CHECK-BIN: (type $ct2 (cont $ft2)) + (type $ct2 (cont $ft2)) + + ;; CHECK-TEXT: (type $4 (func (param (ref $ct1)) (result (ref $ct2)))) + + ;; CHECK-TEXT: (type $5 (func (param (ref $ct1)) (result (ref $ct1)))) + + ;; CHECK-TEXT: (func $f (type $4) (param $x (ref $ct1)) (result (ref $ct2)) + ;; CHECK-TEXT-NEXT: (cont.bind $ct1 $ct2 + ;; CHECK-TEXT-NEXT: (i32.const 123) + ;; CHECK-TEXT-NEXT: (i64.const 456) + ;; CHECK-TEXT-NEXT: (local.get $x) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-BIN: (type $4 (func (param (ref $ct1)) (result (ref $ct2)))) + + ;; CHECK-BIN: (type $5 (func (param (ref $ct1)) (result (ref $ct1)))) + + ;; CHECK-BIN: (func $f (type $4) (param $x (ref $ct1)) (result (ref $ct2)) + ;; CHECK-BIN-NEXT: (cont.bind $ct1 $ct2 + ;; CHECK-BIN-NEXT: (i32.const 123) + ;; CHECK-BIN-NEXT: (i64.const 456) + ;; CHECK-BIN-NEXT: (local.get $x) + ;; CHECK-BIN-NEXT: ) + ;; CHECK-BIN-NEXT: ) + (func $f (param $x (ref $ct1)) (result (ref $ct2)) + (cont.bind $ct1 $ct2 + (i32.const 123) + (i64.const 456) + (local.get $x) + ) + ) + + ;; CHECK-TEXT: (func $g (type $5) (param $x (ref $ct1)) (result (ref $ct1)) + ;; CHECK-TEXT-NEXT: (cont.bind $ct1 $ct1 + ;; CHECK-TEXT-NEXT: (local.get $x) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-BIN: (func $g (type $5) (param $x (ref $ct1)) (result (ref $ct1)) + ;; CHECK-BIN-NEXT: (cont.bind $ct1 $ct1 + ;; CHECK-BIN-NEXT: (local.get $x) + ;; CHECK-BIN-NEXT: ) + ;; CHECK-BIN-NEXT: ) + (func $g (param $x (ref $ct1)) (result (ref $ct1)) + (cont.bind $ct1 $ct1 + (local.get $x) + ) + ) +) +;; CHECK-BIN-NODEBUG: (type $0 (func (param i32 i64 i32) (result i32))) + +;; CHECK-BIN-NODEBUG: (type $1 (cont $0)) + +;; CHECK-BIN-NODEBUG: (type $2 (func (param i32) (result i32))) + +;; CHECK-BIN-NODEBUG: (type $3 (cont $2)) + +;; CHECK-BIN-NODEBUG: (type $4 (func (param (ref $1)) (result (ref $3)))) + +;; CHECK-BIN-NODEBUG: (type $5 (func (param (ref $1)) (result (ref $1)))) + +;; CHECK-BIN-NODEBUG: (func $0 (type $4) (param $0 (ref $1)) (result (ref $3)) +;; CHECK-BIN-NODEBUG-NEXT: (cont.bind $1 $3 +;; CHECK-BIN-NODEBUG-NEXT: (i32.const 123) +;; CHECK-BIN-NODEBUG-NEXT: (i64.const 456) +;; CHECK-BIN-NODEBUG-NEXT: (local.get $0) +;; CHECK-BIN-NODEBUG-NEXT: ) +;; CHECK-BIN-NODEBUG-NEXT: ) + +;; CHECK-BIN-NODEBUG: (func $1 (type $5) (param $0 (ref $1)) (result (ref $1)) +;; CHECK-BIN-NODEBUG-NEXT: (cont.bind $1 $1 +;; CHECK-BIN-NODEBUG-NEXT: (local.get $0) +;; CHECK-BIN-NODEBUG-NEXT: ) +;; CHECK-BIN-NODEBUG-NEXT: ) diff --git a/test/lit/wat-kitchen-sink.wast b/test/lit/wat-kitchen-sink.wast index 3476195fd..55bd87f2e 100644 --- a/test/lit/wat-kitchen-sink.wast +++ b/test/lit/wat-kitchen-sink.wast @@ -25,12 +25,12 @@ ;; CHECK: (type $8 (func (param anyref))) - ;; CHECK: (type $9 (func (param i32 i64 v128))) - ;; CHECK: (type $simple (func (param i32 i64) (result f32))) ;; CHECK: (type $simple-cont (cont $simple)) + ;; CHECK: (type $11 (func (param i32 i64 v128))) + ;; CHECK: (rec ;; CHECK-NEXT: (type $s0 (struct )) (type $s0 (struct)) @@ -74,123 +74,129 @@ ;; CHECK: (type $30 (func (param i64 v128))) - ;; CHECK: (type $31 (func (result i32 i64 (ref null $simple-cont)))) + ;; CHECK: (type $cont-bind-before-func (func (param i32 i64 i32 i64) (result f32))) + + ;; CHECK: (type $cont-bind-before (cont $cont-bind-before-func)) - ;; CHECK: (type $32 (func (param i32 i32))) + ;; CHECK: (type $33 (func (result i32 i64 (ref null $simple-cont)))) - ;; CHECK: (type $33 (func (param exnref))) + ;; CHECK: (type $34 (func (param i32 i32))) - ;; CHECK: (type $34 (func (param i32 i32 f64 f64))) + ;; CHECK: (type $35 (func (param exnref))) - ;; CHECK: (type $35 (func (param i64))) + ;; CHECK: (type $36 (func (param i32 i32 f64 f64))) - ;; CHECK: (type $36 (func (param v128) (result i32))) + ;; CHECK: (type $37 (func (param i64))) - ;; CHECK: (type $37 (func (param v128 v128) (result v128))) + ;; CHECK: (type $38 (func (param v128) (result i32))) - ;; CHECK: (type $38 (func (param v128 v128 v128) (result v128))) + ;; CHECK: (type $39 (func (param v128 v128) (result v128))) - ;; CHECK: (type $39 (func (param i32 i32 i64 i64))) + ;; CHECK: (type $40 (func (param v128 v128 v128) (result v128))) - ;; CHECK: (type $40 (func (param i32) (result i32))) + ;; CHECK: (type $41 (func (param i32 i32 i64 i64))) - ;; CHECK: (type $41 (func (param i64) (result i32 i64))) + ;; CHECK: (type $42 (func (param i32) (result i32))) - ;; CHECK: (type $42 (func (param i32) (result i32 i64))) + ;; CHECK: (type $43 (func (param i64) (result i32 i64))) - ;; CHECK: (type $43 (func (param anyref) (result i32))) + ;; CHECK: (type $44 (func (param i32) (result i32 i64))) - ;; CHECK: (type $44 (func (param eqref eqref) (result i32))) + ;; CHECK: (type $45 (func (param anyref) (result i32))) - ;; CHECK: (type $45 (func (param i32) (result i31ref))) + ;; CHECK: (type $46 (func (param eqref eqref) (result i32))) - ;; CHECK: (type $46 (func (param i31ref))) + ;; CHECK: (type $47 (func (param i32) (result i31ref))) - ;; CHECK: (type $47 (func (param i32 i64) (result (ref $pair)))) + ;; CHECK: (type $48 (func (param i31ref))) - ;; CHECK: (type $48 (func (result (ref $pair)))) + ;; CHECK: (type $49 (func (param i32 i64) (result (ref $pair)))) - ;; CHECK: (type $49 (func (param (ref $pair)) (result i32))) + ;; CHECK: (type $50 (func (result (ref $pair)))) - ;; CHECK: (type $50 (func (param (ref $pair)) (result i64))) + ;; CHECK: (type $51 (func (param (ref $pair)) (result i32))) - ;; CHECK: (type $51 (func (param (ref null $pair)) (result i32))) + ;; CHECK: (type $52 (func (param (ref $pair)) (result i64))) - ;; CHECK: (type $52 (func (param (ref $pair) i32))) + ;; CHECK: (type $53 (func (param (ref null $pair)) (result i32))) - ;; CHECK: (type $53 (func (param (ref $pair) i64))) + ;; CHECK: (type $54 (func (param (ref $pair) i32))) - ;; CHECK: (type $54 (func (param (ref null $pair) i64))) + ;; CHECK: (type $55 (func (param (ref $pair) i64))) - ;; CHECK: (type $55 (func (param i64 i32) (result (ref $a1)))) + ;; CHECK: (type $56 (func (param (ref null $pair) i64))) - ;; CHECK: (type $56 (func (param i32) (result (ref $a1)))) + ;; CHECK: (type $57 (func (param i64 i32) (result (ref $a1)))) - ;; CHECK: (type $57 (func (param i32 i32) (result (ref $a1)))) + ;; CHECK: (type $58 (func (param i32) (result (ref $a1)))) - ;; CHECK: (type $58 (func (param (ref $a1) i32) (result i64))) + ;; CHECK: (type $59 (func (param i32 i32) (result (ref $a1)))) - ;; CHECK: (type $59 (func (param (ref $packed-i8) i32) (result i32))) + ;; CHECK: (type $60 (func (param (ref $a1) i32) (result i64))) - ;; CHECK: (type $60 (func (param (ref $packed-i16) i32) (result i32))) + ;; CHECK: (type $61 (func (param (ref $packed-i8) i32) (result i32))) - ;; CHECK: (type $61 (func (param (ref $a2) i32 f32))) + ;; CHECK: (type $62 (func (param (ref $packed-i16) i32) (result i32))) - ;; CHECK: (type $62 (func (param arrayref) (result i32))) + ;; CHECK: (type $63 (func (param (ref $a2) i32 f32))) - ;; CHECK: (type $63 (func (param (ref $a2) i32 (ref $a2) i32 i32))) + ;; CHECK: (type $64 (func (param arrayref) (result i32))) - ;; CHECK: (type $64 (func (param (ref $a2) i32 f32 i32))) + ;; CHECK: (type $65 (func (param (ref $a2) i32 (ref $a2) i32 i32))) - ;; CHECK: (type $65 (func (param (ref $a2) i32 i32 i32))) + ;; CHECK: (type $66 (func (param (ref $a2) i32 f32 i32))) - ;; CHECK: (type $66 (func (param (ref $any-array) i32 i32 i32))) + ;; CHECK: (type $67 (func (param (ref $a2) i32 i32 i32))) - ;; CHECK: (type $67 (func (param externref))) + ;; CHECK: (type $68 (func (param (ref $any-array) i32 i32 i32))) - ;; CHECK: (type $68 (func (param i32 i32) (result stringref))) + ;; CHECK: (type $69 (func (param externref))) - ;; CHECK: (type $69 (func (param (ref $packed-i8) i32 i32) (result stringref))) + ;; CHECK: (type $70 (func (param i32 i32) (result stringref))) - ;; CHECK: (type $70 (func (param i32) (result stringref))) + ;; CHECK: (type $71 (func (param (ref $packed-i8) i32 i32) (result stringref))) - ;; CHECK: (type $71 (func (result (ref string)))) + ;; CHECK: (type $72 (func (param i32) (result stringref))) - ;; CHECK: (type $72 (func (param stringref) (result i32))) + ;; CHECK: (type $73 (func (result (ref string)))) - ;; CHECK: (type $73 (func (param stringview_wtf16) (result i32))) + ;; CHECK: (type $74 (func (param stringref) (result i32))) - ;; CHECK: (type $74 (func (param stringref (ref $packed-i8) i32) (result i32))) + ;; CHECK: (type $75 (func (param stringview_wtf16) (result i32))) - ;; CHECK: (type $75 (func (param stringref stringref) (result (ref string)))) + ;; CHECK: (type $76 (func (param stringref (ref $packed-i8) i32) (result i32))) - ;; CHECK: (type $76 (func (param stringref) (result stringview_wtf8))) + ;; CHECK: (type $77 (func (param stringref stringref) (result (ref string)))) - ;; CHECK: (type $77 (func (param stringref) (result (ref stringview_wtf16)))) + ;; CHECK: (type $78 (func (param stringref) (result stringview_wtf8))) - ;; CHECK: (type $78 (func (param stringref) (result stringview_iter))) + ;; CHECK: (type $79 (func (param stringref) (result (ref stringview_wtf16)))) - ;; CHECK: (type $79 (func (param (ref stringview_wtf8) i32 i32) (result i32))) + ;; CHECK: (type $80 (func (param stringref) (result stringview_iter))) - ;; CHECK: (type $80 (func (param stringview_wtf16 i32) (result i32))) + ;; CHECK: (type $81 (func (param (ref stringview_wtf8) i32 i32) (result i32))) - ;; CHECK: (type $81 (func (param stringview_iter) (result i32))) + ;; CHECK: (type $82 (func (param stringview_wtf16 i32) (result i32))) - ;; CHECK: (type $82 (func (param stringview_iter i32) (result i32))) + ;; CHECK: (type $83 (func (param stringview_iter) (result i32))) - ;; CHECK: (type $83 (func (param (ref stringview_iter) i32) (result i32))) + ;; CHECK: (type $84 (func (param stringview_iter i32) (result i32))) - ;; CHECK: (type $84 (func (param stringview_wtf8 stringview_wtf16 i32 i32))) + ;; CHECK: (type $85 (func (param (ref stringview_iter) i32) (result i32))) - ;; CHECK: (type $85 (func (param stringview_iter i32) (result (ref string)))) + ;; CHECK: (type $86 (func (param stringview_wtf8 stringview_wtf16 i32 i32))) - ;; CHECK: (type $86 (func (param (ref $simple-cont)))) + ;; CHECK: (type $87 (func (param stringview_iter i32) (result (ref string)))) + + ;; CHECK: (type $88 (func (param (ref $simple-cont)))) ;; CHECK: (type $to-f32 (func (result f32))) ;; CHECK: (type $to-f32-cont (cont $to-f32)) - ;; CHECK: (type $89 (func (param (ref $simple)) (result (ref $simple-cont)))) + ;; CHECK: (type $91 (func (param (ref $simple)) (result (ref $simple-cont)))) + + ;; CHECK: (type $92 (func (param (ref $cont-bind-before)) (result (ref $simple-cont)))) ;; CHECK: (type $s2 (struct (field i32))) (type $s2 (struct i32)) @@ -240,6 +246,10 @@ (type $simple-cont (cont $simple)) (type $to-f32-cont (cont $to-f32)) + + (type $cont-bind-before-func (func (param i32) (param i64) (param i32) (param i64) (result f32))) + (type $cont-bind-before (cont $cont-bind-before-func)) + ;; CHECK: (type $all-types (struct (field externref) (field (ref extern)) (field funcref) (field (ref func)) (field anyref) (field (ref any)) (field eqref) (field (ref eq)) (field i31ref) (field (ref i31)) (field structref) (field (ref struct)) (field arrayref) (field (ref array)) (field exnref) (field (ref exn)) (field stringref) (field (ref string)) (field stringview_wtf8) (field (ref stringview_wtf8)) (field stringview_wtf16) (field (ref stringview_wtf16)) (field stringview_iter) (field (ref stringview_iter)) (field nullref) (field (ref none)) (field nullexternref) (field (ref noextern)) (field nullfuncref) (field (ref nofunc)) (field nullexnref) (field (ref noexn)))) (type $all-types (struct externref (ref extern) funcref (ref func) @@ -260,7 +270,7 @@ ;; imported memories (memory (export "mem") (export "mem2") (import "" "mem") 0) - ;; CHECK: (type $101 (func (param (ref $s0) (ref $s1) (ref $s2) (ref $s3) (ref $s4) (ref $s5) (ref $s6) (ref $s7) (ref $s8) (ref $a0) (ref $a1) (ref $a2) (ref $a3) (ref $subvoid) (ref $submany) (ref $all-types)))) + ;; CHECK: (type $104 (func (param (ref $s0) (ref $s1) (ref $s2) (ref $s3) (ref $s4) (ref $s5) (ref $s6) (ref $s7) (ref $s8) (ref $a0) (ref $a1) (ref $a2) (ref $a3) (ref $subvoid) (ref $submany) (ref $all-types)))) ;; CHECK: (import "" "mem" (memory $mimport$0 0)) @@ -937,7 +947,7 @@ drop ) - ;; CHECK: (func $locals (type $32) (param $0 i32) (param $x i32) + ;; CHECK: (func $locals (type $34) (param $0 i32) (param $x i32) ;; CHECK-NEXT: (local $2 i32) ;; CHECK-NEXT: (local $y i32) ;; CHECK-NEXT: (drop @@ -2590,7 +2600,7 @@ ) ) - ;; CHECK: (func $try-table-throw-ref (type $33) (param $0 exnref) + ;; CHECK: (func $try-table-throw-ref (type $35) (param $0 exnref) ;; CHECK-NEXT: (throw_ref ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -3008,7 +3018,7 @@ end ) - ;; CHECK: (func $binary (type $34) (param $0 i32) (param $1 i32) (param $2 f64) (param $3 f64) + ;; CHECK: (func $binary (type $36) (param $0 i32) (param $1 i32) (param $2 f64) (param $3 f64) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (local.get $0) @@ -3033,7 +3043,7 @@ drop ) - ;; CHECK: (func $unary (type $35) (param $0 i64) + ;; CHECK: (func $unary (type $37) (param $0 i64) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i64.eqz ;; CHECK-NEXT: (local.get $0) @@ -3382,7 +3392,7 @@ drop ) - ;; CHECK: (func $simd-extract (type $36) (param $0 v128) (result i32) + ;; CHECK: (func $simd-extract (type $38) (param $0 v128) (result i32) ;; CHECK-NEXT: (i32x4.extract_lane 3 ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -3404,7 +3414,7 @@ i32x4.replace_lane 2 ) - ;; CHECK: (func $simd-shuffle (type $37) (param $0 v128) (param $1 v128) (result v128) + ;; CHECK: (func $simd-shuffle (type $39) (param $0 v128) (param $1 v128) (result v128) ;; CHECK-NEXT: (i8x16.shuffle 0 1 2 3 4 5 6 7 16 17 18 19 20 21 22 23 ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -3416,7 +3426,7 @@ i8x16.shuffle 0 1 2 3 4 5 6 7 16 17 18 19 20 21 22 23 ) - ;; CHECK: (func $simd-ternary (type $38) (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + ;; CHECK: (func $simd-ternary (type $40) (param $0 v128) (param $1 v128) (param $2 v128) (result v128) ;; CHECK-NEXT: (v128.bitselect ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -3463,7 +3473,7 @@ drop ) - ;; CHECK: (func $simd-load-store-lane (type $9) (param $0 i32) (param $1 i64) (param $2 v128) + ;; CHECK: (func $simd-load-store-lane (type $11) (param $0 i32) (param $1 i64) (param $2 v128) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (v128.load16_lane $mimport$0 7 ;; CHECK-NEXT: (local.get $0) @@ -3526,7 +3536,7 @@ data.drop $passive ) - ;; CHECK: (func $memory-copy (type $39) (param $0 i32) (param $1 i32) (param $2 i64) (param $3 i64) + ;; CHECK: (func $memory-copy (type $41) (param $0 i32) (param $1 i32) (param $2 i64) (param $3 i64) ;; CHECK-NEXT: (memory.copy $mimport$0 $mimport$0 ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -3597,7 +3607,7 @@ return ) - ;; CHECK: (func $return-one (type $40) (param $0 i32) (result i32) + ;; CHECK: (func $return-one (type $42) (param $0 i32) (result i32) ;; CHECK-NEXT: (return ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -3621,7 +3631,7 @@ return ) - ;; CHECK: (func $return-two-first-unreachable (type $41) (param $0 i64) (result i32 i64) + ;; CHECK: (func $return-two-first-unreachable (type $43) (param $0 i64) (result i32 i64) ;; CHECK-NEXT: (return ;; CHECK-NEXT: (tuple.make 2 ;; CHECK-NEXT: (unreachable) @@ -3635,7 +3645,7 @@ return ) - ;; CHECK: (func $return-two-second-unreachable (type $42) (param $0 i32) (result i32 i64) + ;; CHECK: (func $return-two-second-unreachable (type $44) (param $0 i32) (result i32 i64) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -3652,7 +3662,7 @@ return ) - ;; CHECK: (func $ref-is-null (type $43) (param $0 anyref) (result i32) + ;; CHECK: (func $ref-is-null (type $45) (param $0 anyref) (result i32) ;; CHECK-NEXT: (ref.is_null ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -3696,7 +3706,7 @@ throw $tag-pair ) - ;; CHECK: (func $ref-eq (type $44) (param $0 eqref) (param $1 eqref) (result i32) + ;; CHECK: (func $ref-eq (type $46) (param $0 eqref) (param $1 eqref) (result i32) ;; CHECK-NEXT: (ref.eq ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -3873,7 +3883,7 @@ table.copy 2 $funcs ) - ;; CHECK: (func $i31-new (type $45) (param $0 i32) (result i31ref) + ;; CHECK: (func $i31-new (type $47) (param $0 i32) (result i31ref) ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -3883,7 +3893,7 @@ ref.i31 ) - ;; CHECK: (func $i31-get (type $46) (param $0 i31ref) + ;; CHECK: (func $i31-get (type $48) (param $0 i31ref) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i31.get_s ;; CHECK-NEXT: (local.get $0) @@ -4102,7 +4112,7 @@ drop ) - ;; CHECK: (func $struct-new (type $47) (param $0 i32) (param $1 i64) (result (ref $pair)) + ;; CHECK: (func $struct-new (type $49) (param $0 i32) (param $1 i64) (result (ref $pair)) ;; CHECK-NEXT: (struct.new $pair ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -4114,14 +4124,14 @@ struct.new $pair ) - ;; CHECK: (func $struct-new-default (type $48) (result (ref $pair)) + ;; CHECK: (func $struct-new-default (type $50) (result (ref $pair)) ;; CHECK-NEXT: (struct.new_default $pair) ;; CHECK-NEXT: ) (func $struct-new-default (result (ref $pair)) struct.new_default 14 ) - ;; CHECK: (func $struct-get-0 (type $49) (param $0 (ref $pair)) (result i32) + ;; CHECK: (func $struct-get-0 (type $51) (param $0 (ref $pair)) (result i32) ;; CHECK-NEXT: (struct.get $pair $first ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -4131,7 +4141,7 @@ struct.get 14 0 ) - ;; CHECK: (func $struct-get-1 (type $50) (param $0 (ref $pair)) (result i64) + ;; CHECK: (func $struct-get-1 (type $52) (param $0 (ref $pair)) (result i64) ;; CHECK-NEXT: (struct.get $pair $second ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -4141,7 +4151,7 @@ struct.get $pair 1 ) - ;; CHECK: (func $struct-get-named (type $51) (param $0 (ref null $pair)) (result i32) + ;; CHECK: (func $struct-get-named (type $53) (param $0 (ref null $pair)) (result i32) ;; CHECK-NEXT: (struct.get $pair $first ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -4151,7 +4161,7 @@ struct.get $pair $first ) - ;; CHECK: (func $struct-set-0 (type $52) (param $0 (ref $pair)) (param $1 i32) + ;; CHECK: (func $struct-set-0 (type $54) (param $0 (ref $pair)) (param $1 i32) ;; CHECK-NEXT: (struct.set $pair $first ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -4163,7 +4173,7 @@ struct.set $pair 0 ) - ;; CHECK: (func $struct-set-1 (type $53) (param $0 (ref $pair)) (param $1 i64) + ;; CHECK: (func $struct-set-1 (type $55) (param $0 (ref $pair)) (param $1 i64) ;; CHECK-NEXT: (struct.set $pair $second ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -4175,7 +4185,7 @@ struct.set 14 1 ) - ;; CHECK: (func $struct-set-named (type $54) (param $0 (ref null $pair)) (param $1 i64) + ;; CHECK: (func $struct-set-named (type $56) (param $0 (ref null $pair)) (param $1 i64) ;; CHECK-NEXT: (struct.set $pair $second ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -4187,7 +4197,7 @@ struct.set 14 $second ) - ;; CHECK: (func $array-new (type $55) (param $0 i64) (param $1 i32) (result (ref $a1)) + ;; CHECK: (func $array-new (type $57) (param $0 i64) (param $1 i32) (result (ref $a1)) ;; CHECK-NEXT: (array.new $a1 ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -4199,7 +4209,7 @@ array.new $a1 ) - ;; CHECK: (func $array-new-default (type $56) (param $0 i32) (result (ref $a1)) + ;; CHECK: (func $array-new-default (type $58) (param $0 i32) (result (ref $a1)) ;; CHECK-NEXT: (array.new_default $a1 ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -4209,7 +4219,7 @@ array.new_default 11 ) - ;; CHECK: (func $array-new-data (type $57) (param $0 i32) (param $1 i32) (result (ref $a1)) + ;; CHECK: (func $array-new-data (type $59) (param $0 i32) (param $1 i32) (result (ref $a1)) ;; CHECK-NEXT: (array.new_data $a1 $implicit-data ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -4243,7 +4253,7 @@ drop ) - ;; CHECK: (func $array-get (type $58) (param $0 (ref $a1)) (param $1 i32) (result i64) + ;; CHECK: (func $array-get (type $60) (param $0 (ref $a1)) (param $1 i32) (result i64) ;; CHECK-NEXT: (array.get $a1 ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -4255,7 +4265,7 @@ array.get $a1 ) - ;; CHECK: (func $array-get-s (type $59) (param $0 (ref $packed-i8)) (param $1 i32) (result i32) + ;; CHECK: (func $array-get-s (type $61) (param $0 (ref $packed-i8)) (param $1 i32) (result i32) ;; CHECK-NEXT: (array.get_s $packed-i8 ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -4267,7 +4277,7 @@ array.get_s 15 ) - ;; CHECK: (func $array-get-u (type $60) (param $0 (ref $packed-i16)) (param $1 i32) (result i32) + ;; CHECK: (func $array-get-u (type $62) (param $0 (ref $packed-i16)) (param $1 i32) (result i32) ;; CHECK-NEXT: (array.get_u $packed-i16 ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -4279,7 +4289,7 @@ array.get_u $packed-i16 ) - ;; CHECK: (func $array-set (type $61) (param $0 (ref $a2)) (param $1 i32) (param $2 f32) + ;; CHECK: (func $array-set (type $63) (param $0 (ref $a2)) (param $1 i32) (param $2 f32) ;; CHECK-NEXT: (array.set $a2 ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -4293,7 +4303,7 @@ array.set $a2 ) - ;; CHECK: (func $array-len (type $62) (param $0 arrayref) (result i32) + ;; CHECK: (func $array-len (type $64) (param $0 arrayref) (result i32) ;; CHECK-NEXT: (array.len ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -4303,7 +4313,7 @@ array.len ) - ;; CHECK: (func $array-copy (type $63) (param $0 (ref $a2)) (param $1 i32) (param $2 (ref $a2)) (param $3 i32) (param $4 i32) + ;; CHECK: (func $array-copy (type $65) (param $0 (ref $a2)) (param $1 i32) (param $2 (ref $a2)) (param $3 i32) (param $4 i32) ;; CHECK-NEXT: (array.copy $a2 $a2 ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -4321,7 +4331,7 @@ array.copy $a2 $a2 ) - ;; CHECK: (func $array-fill (type $64) (param $0 (ref $a2)) (param $1 i32) (param $2 f32) (param $3 i32) + ;; CHECK: (func $array-fill (type $66) (param $0 (ref $a2)) (param $1 i32) (param $2 f32) (param $3 i32) ;; CHECK-NEXT: (array.fill $a2 ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -4337,7 +4347,7 @@ array.fill $a2 ) - ;; CHECK: (func $array-init-data (type $65) (param $0 (ref $a2)) (param $1 i32) (param $2 i32) (param $3 i32) + ;; CHECK: (func $array-init-data (type $67) (param $0 (ref $a2)) (param $1 i32) (param $2 i32) (param $3 i32) ;; CHECK-NEXT: (array.init_data $a2 $implicit-data ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -4353,7 +4363,7 @@ array.init_data $a2 0 ) - ;; CHECK: (func $array-init-elem (type $66) (param $0 (ref $any-array)) (param $1 i32) (param $2 i32) (param $3 i32) + ;; CHECK: (func $array-init-elem (type $68) (param $0 (ref $any-array)) (param $1 i32) (param $2 i32) (param $3 i32) ;; CHECK-NEXT: (array.init_elem $any-array $passive-2 ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -4382,7 +4392,7 @@ drop ) - ;; CHECK: (func $any-convert-extern (type $67) (param $0 externref) + ;; CHECK: (func $any-convert-extern (type $69) (param $0 externref) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (extern.internalize ;; CHECK-NEXT: (local.get $0) @@ -4408,7 +4418,7 @@ drop ) - ;; CHECK: (func $string-new (type $68) (param $0 i32) (param $1 i32) (result stringref) + ;; CHECK: (func $string-new (type $70) (param $0 i32) (param $1 i32) (result stringref) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (string.new_utf8_try ;; CHECK-NEXT: (local.get $0) @@ -4450,7 +4460,7 @@ string.new_wtf16 ) - ;; CHECK: (func $string-new-gc (type $69) (param $0 (ref $packed-i8)) (param $1 i32) (param $2 i32) (result stringref) + ;; CHECK: (func $string-new-gc (type $71) (param $0 (ref $packed-i8)) (param $1 i32) (param $2 i32) (result stringref) ;; CHECK-NEXT: (string.new_utf8_array ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -4464,7 +4474,7 @@ string.new_utf8_array ) - ;; CHECK: (func $string-new-code-point (type $70) (param $0 i32) (result stringref) + ;; CHECK: (func $string-new-code-point (type $72) (param $0 i32) (result stringref) ;; CHECK-NEXT: (string.from_code_point ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -4474,7 +4484,7 @@ string.from_code_point ) - ;; CHECK: (func $string-const (type $71) (result (ref string)) + ;; CHECK: (func $string-const (type $73) (result (ref string)) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (string.const "foobar") ;; CHECK-NEXT: ) @@ -4523,7 +4533,7 @@ drop ) - ;; CHECK: (func $string-hash (type $72) (param $0 stringref) (result i32) + ;; CHECK: (func $string-hash (type $74) (param $0 stringref) (result i32) ;; CHECK-NEXT: (string.hash ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -4533,7 +4543,7 @@ string.hash ) - ;; CHECK: (func $stringview-length (type $73) (param $0 stringview_wtf16) (result i32) + ;; CHECK: (func $stringview-length (type $75) (param $0 stringview_wtf16) (result i32) ;; CHECK-NEXT: (stringview_wtf16.length ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -4588,7 +4598,7 @@ drop ) - ;; CHECK: (func $string-encode-gc (type $74) (param $0 stringref) (param $1 (ref $packed-i8)) (param $2 i32) (result i32) + ;; CHECK: (func $string-encode-gc (type $76) (param $0 stringref) (param $1 (ref $packed-i8)) (param $2 i32) (result i32) ;; CHECK-NEXT: (string.encode_wtf8_array ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -4602,7 +4612,7 @@ string.encode_wtf8_array ) - ;; CHECK: (func $string-concat (type $75) (param $0 stringref) (param $1 stringref) (result (ref string)) + ;; CHECK: (func $string-concat (type $77) (param $0 stringref) (param $1 stringref) (result (ref string)) ;; CHECK-NEXT: (string.concat ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -4638,7 +4648,7 @@ string.compare ) - ;; CHECK: (func $string-as-wtf8 (type $76) (param $0 stringref) (result stringview_wtf8) + ;; CHECK: (func $string-as-wtf8 (type $78) (param $0 stringref) (result stringview_wtf8) ;; CHECK-NEXT: (string.as_wtf8 ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -4648,7 +4658,7 @@ string.as_wtf8 ) - ;; CHECK: (func $string-as-wtf16 (type $77) (param $0 stringref) (result (ref stringview_wtf16)) + ;; CHECK: (func $string-as-wtf16 (type $79) (param $0 stringref) (result (ref stringview_wtf16)) ;; CHECK-NEXT: (string.as_wtf16 ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -4658,7 +4668,7 @@ string.as_wtf16 ) - ;; CHECK: (func $string-as-iter (type $78) (param $0 stringref) (result stringview_iter) + ;; CHECK: (func $string-as-iter (type $80) (param $0 stringref) (result stringview_iter) ;; CHECK-NEXT: (string.as_iter ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -4668,7 +4678,7 @@ string.as_iter ) - ;; CHECK: (func $string-advance (type $79) (param $0 (ref stringview_wtf8)) (param $1 i32) (param $2 i32) (result i32) + ;; CHECK: (func $string-advance (type $81) (param $0 (ref stringview_wtf8)) (param $1 i32) (param $2 i32) (result i32) ;; CHECK-NEXT: (stringview_wtf8.advance ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -4682,7 +4692,7 @@ stringview_wtf8.advance ) - ;; CHECK: (func $string-get (type $80) (param $0 stringview_wtf16) (param $1 i32) (result i32) + ;; CHECK: (func $string-get (type $82) (param $0 stringview_wtf16) (param $1 i32) (result i32) ;; CHECK-NEXT: (stringview_wtf16.get_codeunit ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -4694,7 +4704,7 @@ stringview_wtf16.get_codeunit ) - ;; CHECK: (func $string-iter-next (type $81) (param $0 stringview_iter) (result i32) + ;; CHECK: (func $string-iter-next (type $83) (param $0 stringview_iter) (result i32) ;; CHECK-NEXT: (stringview_iter.next ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -4704,7 +4714,7 @@ stringview_iter.next ) - ;; CHECK: (func $string-iter-advance (type $82) (param $0 stringview_iter) (param $1 i32) (result i32) + ;; CHECK: (func $string-iter-advance (type $84) (param $0 stringview_iter) (param $1 i32) (result i32) ;; CHECK-NEXT: (stringview_iter.advance ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -4716,7 +4726,7 @@ stringview_iter.advance ) - ;; CHECK: (func $string-iter-rewind (type $83) (param $0 (ref stringview_iter)) (param $1 i32) (result i32) + ;; CHECK: (func $string-iter-rewind (type $85) (param $0 (ref stringview_iter)) (param $1 i32) (result i32) ;; CHECK-NEXT: (stringview_iter.rewind ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -4728,7 +4738,7 @@ stringview_iter.rewind ) - ;; CHECK: (func $string-slice (type $84) (param $0 stringview_wtf8) (param $1 stringview_wtf16) (param $2 i32) (param $3 i32) + ;; CHECK: (func $string-slice (type $86) (param $0 stringview_wtf8) (param $1 stringview_wtf16) (param $2 i32) (param $3 i32) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (stringview_wtf8.slice ;; CHECK-NEXT: (local.get $0) @@ -4757,7 +4767,7 @@ drop ) - ;; CHECK: (func $string-iter-slice (type $85) (param $0 stringview_iter) (param $1 i32) (result (ref string)) + ;; CHECK: (func $string-iter-slice (type $87) (param $0 stringview_iter) (param $1 i32) (result (ref string)) ;; CHECK-NEXT: (stringview_iter.slice ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -4793,7 +4803,7 @@ return_call $return_call ) - ;; CHECK: (func $call-indirect (type $9) (param $0 i32) (param $1 i64) (param $2 v128) + ;; CHECK: (func $call-indirect (type $11) (param $0 i32) (param $1 i64) (param $2 v128) ;; CHECK-NEXT: (call_indirect $timport$0 (type $void) ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -4855,7 +4865,7 @@ drop ) - ;; CHECK: (func $call-indirect-folded (type $9) (param $0 i32) (param $1 i64) (param $2 v128) + ;; CHECK: (func $call-indirect-folded (type $11) (param $0 i32) (param $1 i64) (param $2 v128) ;; CHECK-NEXT: (call_indirect $timport$0 (type $void) ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -4928,7 +4938,7 @@ ) ) - ;; CHECK: (func $return-call-indirect (type $9) (param $0 i32) (param $1 i64) (param $2 v128) + ;; CHECK: (func $return-call-indirect (type $11) (param $0 i32) (param $1 i64) (param $2 v128) ;; CHECK-NEXT: (return_call_indirect $timport$0 (type $void) ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -4987,7 +4997,7 @@ return_call_indirect (param i64 v128) ) - ;; CHECK: (func $return-call-indirect-folded (type $9) (param $0 i32) (param $1 i64) (param $2 v128) + ;; CHECK: (func $return-call-indirect-folded (type $11) (param $0 i32) (param $1 i64) (param $2 v128) ;; CHECK-NEXT: (return_call_indirect $timport$0 (type $void) ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -5056,14 +5066,14 @@ ) ) - ;; CHECK: (func $resume (type $86) (param $ct (ref $simple-cont)) + ;; CHECK: (func $resume (type $88) (param $ct (ref $simple-cont)) ;; CHECK-NEXT: (local $f f32) ;; CHECK-NEXT: (block $label_1 ;; CHECK-NEXT: (block ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (block $label (result (ref $to-f32-cont)) ;; CHECK-NEXT: (tuple.drop 3 - ;; CHECK-NEXT: (block $label_0 (type $31) (result i32 i64 (ref null $simple-cont)) + ;; CHECK-NEXT: (block $label_0 (type $33) (result i32 i64 (ref null $simple-cont)) ;; CHECK-NEXT: (local.set $f ;; CHECK-NEXT: (resume $simple-cont (tag $empty $label) (tag $tag-pair-to-pair $label_0) ;; CHECK-NEXT: (i32.const 0) @@ -5097,7 +5107,7 @@ br 0 ) - ;; CHECK: (func $contnew (type $89) (param $f (ref $simple)) (result (ref $simple-cont)) + ;; CHECK: (func $contnew (type $91) (param $f (ref $simple)) (result (ref $simple-cont)) ;; CHECK-NEXT: (cont.new $simple-cont ;; CHECK-NEXT: (local.get $f) ;; CHECK-NEXT: ) @@ -5107,6 +5117,20 @@ cont.new $simple-cont ) + ;; CHECK: (func $contbind (type $92) (param $c (ref $cont-bind-before)) (result (ref $simple-cont)) + ;; CHECK-NEXT: (cont.bind $cont-bind-before $simple-cont + ;; CHECK-NEXT: (i32.const 123) + ;; CHECK-NEXT: (i64.const 123) + ;; CHECK-NEXT: (local.get $c) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $contbind (param $c (ref $cont-bind-before)) (result (ref $simple-cont)) + i32.const 123 + i64.const 123 + local.get $c + cont.bind $cont-bind-before $simple-cont + ) + ;; CHECK: (func $source-maps (type $void) ;; CHECK-NEXT: ;;@ src.cpp:40:1 ;; CHECK-NEXT: (drop @@ -5168,7 +5192,7 @@ end ) - ;; CHECK: (func $use-types (type $101) (param $0 (ref $s0)) (param $1 (ref $s1)) (param $2 (ref $s2)) (param $3 (ref $s3)) (param $4 (ref $s4)) (param $5 (ref $s5)) (param $6 (ref $s6)) (param $7 (ref $s7)) (param $8 (ref $s8)) (param $9 (ref $a0)) (param $10 (ref $a1)) (param $11 (ref $a2)) (param $12 (ref $a3)) (param $13 (ref $subvoid)) (param $14 (ref $submany)) (param $15 (ref $all-types)) + ;; CHECK: (func $use-types (type $104) (param $0 (ref $s0)) (param $1 (ref $s1)) (param $2 (ref $s2)) (param $3 (ref $s3)) (param $4 (ref $s4)) (param $5 (ref $s5)) (param $6 (ref $s6)) (param $7 (ref $s7)) (param $8 (ref $s8)) (param $9 (ref $a0)) (param $10 (ref $a1)) (param $11 (ref $a2)) (param $12 (ref $a3)) (param $13 (ref $subvoid)) (param $14 (ref $submany)) (param $15 (ref $all-types)) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) (func $use-types |