diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gen-s-parser.inc | 35 | ||||
-rw-r--r-- | src/ir/ReFinalize.cpp | 1 | ||||
-rw-r--r-- | src/ir/cost.h | 10 | ||||
-rw-r--r-- | src/ir/effects.h | 4 | ||||
-rw-r--r-- | src/ir/module-utils.cpp | 3 | ||||
-rw-r--r-- | src/ir/possible-contents.cpp | 4 | ||||
-rw-r--r-- | src/ir/subtype-exprs.h | 1 | ||||
-rw-r--r-- | src/parser/contexts.h | 12 | ||||
-rw-r--r-- | src/parser/parsers.h | 15 | ||||
-rw-r--r-- | src/passes/Print.cpp | 7 | ||||
-rw-r--r-- | src/passes/TypeGeneralizing.cpp | 1 | ||||
-rw-r--r-- | src/wasm-binary.h | 2 | ||||
-rw-r--r-- | src/wasm-builder.h | 12 | ||||
-rw-r--r-- | src/wasm-delegations-fields.def | 9 | ||||
-rw-r--r-- | src/wasm-delegations.def | 1 | ||||
-rw-r--r-- | src/wasm-interpreter.h | 2 | ||||
-rw-r--r-- | src/wasm-ir-builder.h | 3 | ||||
-rw-r--r-- | src/wasm-s-parser.h | 1 | ||||
-rw-r--r-- | src/wasm.h | 13 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 41 | ||||
-rw-r--r-- | src/wasm/wasm-ir-builder.cpp | 42 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 23 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 6 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 19 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 2 | ||||
-rw-r--r-- | src/wasm2js.h | 4 |
26 files changed, 264 insertions, 9 deletions
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"); |