summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gen-s-parser.inc35
-rw-r--r--src/ir/ReFinalize.cpp1
-rw-r--r--src/ir/cost.h10
-rw-r--r--src/ir/effects.h4
-rw-r--r--src/ir/module-utils.cpp3
-rw-r--r--src/ir/possible-contents.cpp4
-rw-r--r--src/ir/subtype-exprs.h1
-rw-r--r--src/parser/contexts.h12
-rw-r--r--src/parser/parsers.h15
-rw-r--r--src/passes/Print.cpp7
-rw-r--r--src/passes/TypeGeneralizing.cpp1
-rw-r--r--src/wasm-binary.h2
-rw-r--r--src/wasm-builder.h12
-rw-r--r--src/wasm-delegations-fields.def9
-rw-r--r--src/wasm-delegations.def1
-rw-r--r--src/wasm-interpreter.h2
-rw-r--r--src/wasm-ir-builder.h3
-rw-r--r--src/wasm-s-parser.h1
-rw-r--r--src/wasm.h13
-rw-r--r--src/wasm/wasm-binary.cpp41
-rw-r--r--src/wasm/wasm-ir-builder.cpp42
-rw-r--r--src/wasm/wasm-s-parser.cpp23
-rw-r--r--src/wasm/wasm-stack.cpp6
-rw-r--r--src/wasm/wasm-validator.cpp19
-rw-r--r--src/wasm/wasm.cpp2
-rw-r--r--src/wasm2js.h4
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");