Skip to content

Commit 84cc9fa

Browse files
authored
Typed continuations: suspend instructions (#6393)
This PR is part of a series that adds basic support for the [typed continuations/wasmfx proposal](https://github.com/wasmfx/specfx). This particular PR adds support for the `suspend` instruction for suspending with a given tag, documented [here](https://github.com/wasmfx/specfx/blob/main/proposals/continuations/Overview.md#instructions). These instructions are of the form `(suspend $tag)`. Assuming that `$tag` is defined with _n_ `param` types `t_1` to `t_n`, the instruction consumes _n_ arguments of types `t_1` to `t_n`. Its result type is the same as the `result` type of the tag. Thus, the folded textual representation looks like `(suspend $tag arg1 ... argn)`. Support for the instruction is implemented in both the old and the new wat parser. Note that this PR does not implement validation of the new instruction. This PR also fixes finalization of `cont.new`, `cont.bind` and `resume` nodes in those cases where any of their children are unreachable.
1 parent 63db13b commit 84cc9fa

29 files changed

+281
-22
lines changed

scripts/fuzz_opt.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ def is_git_repo():
328328
'typed_continuations_resume.wast',
329329
'typed_continuations_contnew.wast',
330330
'typed_continuations_contbind.wast',
331+
'typed_continuations_suspend.wast',
331332
# New EH implementation is in progress
332333
'exception-handling.wast',
333334
'translate-eh-old-to-new.wast',

scripts/gen-s-parser.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,7 @@
570570
("cont.new", "makeContNew(s)"),
571571
("cont.bind", "makeContBind(s)"),
572572
("resume", "makeResume(s)"),
573+
("suspend", "makeSuspend(s)"),
573574
# GC
574575
("i31.new", "makeRefI31(s)"), # deprecated
575576
("ref.i31", "makeRefI31(s)"),

src/gen-s-parser.inc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3369,6 +3369,9 @@ switch (buf[0]) {
33693369
default: goto parse_error;
33703370
}
33713371
}
3372+
case 'u':
3373+
if (op == "suspend"sv) { return makeSuspend(s); }
3374+
goto parse_error;
33723375
default: goto parse_error;
33733376
}
33743377
}
@@ -8653,6 +8656,12 @@ switch (buf[0]) {
86538656
default: goto parse_error;
86548657
}
86558658
}
8659+
case 'u':
8660+
if (op == "suspend"sv) {
8661+
CHECK_ERR(makeSuspend(ctx, pos, annotations));
8662+
return Ok{};
8663+
}
8664+
goto parse_error;
86568665
default: goto parse_error;
86578666
}
86588667
}

src/ir/ReFinalize.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ void ReFinalize::visitStringSliceIter(StringSliceIter* curr) {
185185
void ReFinalize::visitContNew(ContNew* curr) { curr->finalize(); }
186186
void ReFinalize::visitContBind(ContBind* curr) { curr->finalize(); }
187187
void ReFinalize::visitResume(Resume* curr) { curr->finalize(); }
188+
void ReFinalize::visitSuspend(Suspend* curr) { curr->finalize(getModule()); }
188189

189190
void ReFinalize::visitExport(Export* curr) { WASM_UNREACHABLE("unimp"); }
190191
void ReFinalize::visitGlobal(Global* curr) { WASM_UNREACHABLE("unimp"); }

src/ir/cost.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,18 @@ struct CostAnalyzer : public OverriddenVisitor<CostAnalyzer, CostType> {
742742
}
743743
CostType visitResume(Resume* curr) {
744744
// Inspired by indirect calls, but twice the cost.
745-
return 12 + visit(curr->cont);
745+
CostType ret = 12 + visit(curr->cont);
746+
for (auto* arg : curr->operands) {
747+
ret += visit(arg);
748+
}
749+
return ret;
750+
}
751+
CostType visitSuspend(Suspend* curr) {
752+
CostType ret = 12;
753+
for (auto* arg : curr->operands) {
754+
ret += visit(arg);
755+
}
756+
return ret;
746757
}
747758

748759
private:

src/ir/effects.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -994,6 +994,14 @@ class EffectAnalyzer {
994994
parent.throws_ = true;
995995
}
996996
}
997+
void visitSuspend(Suspend* curr) {
998+
// Similar to resume/call: Suspending means that we execute arbitrary
999+
// other code before we may resume here.
1000+
parent.calls = true;
1001+
if (parent.features.hasExceptionHandling() && parent.tryDepth == 0) {
1002+
parent.throws_ = true;
1003+
}
1004+
}
9971005
};
9981006

9991007
public:

src/ir/possible-contents.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,6 +1212,10 @@ struct InfoCollector
12121212
// TODO: optimize when possible
12131213
addRoot(curr);
12141214
}
1215+
void visitSuspend(Suspend* curr) {
1216+
// TODO: optimize when possible
1217+
addRoot(curr);
1218+
}
12151219

12161220
void visitFunction(Function* func) {
12171221
// Functions with a result can flow a value out from their body.

src/ir/subtype-exprs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,7 @@ struct SubtypingDiscoverer : public OverriddenVisitor<SubType> {
394394
void visitContBind(ContBind* curr) { WASM_UNREACHABLE("not implemented"); }
395395
void visitContNew(ContNew* curr) { WASM_UNREACHABLE("not implemented"); }
396396
void visitResume(Resume* curr) { WASM_UNREACHABLE("not implemented"); }
397+
void visitSuspend(Suspend* curr) { WASM_UNREACHABLE("not implemented"); }
397398
};
398399

399400
} // namespace wasm

src/parser/contexts.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,9 @@ struct NullInstrParserCtx {
824824
const TagLabelListT&) {
825825
return Ok{};
826826
}
827+
Result<> makeSuspend(Index, const std::vector<Annotation>&, TagIdxT) {
828+
return Ok{};
829+
}
827830
};
828831

829832
struct NullCtx : NullTypeParserCtx, NullInstrParserCtx {
@@ -2594,6 +2597,11 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
25942597
}
25952598
return withLoc(pos, irBuilder.makeResume(type, tags, labels));
25962599
}
2600+
2601+
Result<>
2602+
makeSuspend(Index pos, const std::vector<Annotation>& annotations, Name tag) {
2603+
return withLoc(pos, irBuilder.makeSuspend(tag));
2604+
}
25972605
};
25982606

25992607
} // namespace wasm::WATParser

src/parser/parsers.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,8 @@ template<typename Ctx>
309309
Result<> makeContNew(Ctx*, Index, const std::vector<Annotation>&);
310310
template<typename Ctx>
311311
Result<> makeResume(Ctx&, Index, const std::vector<Annotation>&);
312+
template<typename Ctx>
313+
Result<> makeSuspend(Ctx&, Index, const std::vector<Annotation>&);
312314

313315
// Modules
314316
template<typename Ctx> MaybeResult<Index> maybeTypeidx(Ctx& ctx);
@@ -2498,6 +2500,15 @@ makeResume(Ctx& ctx, Index pos, const std::vector<Annotation>& annotations) {
24982500
return ctx.makeResume(pos, annotations, *type, tagLabels);
24992501
}
25002502

2503+
template<typename Ctx>
2504+
Result<>
2505+
makeSuspend(Ctx& ctx, Index pos, const std::vector<Annotation>& annotations) {
2506+
auto tag = tagidx(ctx);
2507+
CHECK_ERR(tag);
2508+
2509+
return ctx.makeSuspend(pos, annotations, *tag);
2510+
}
2511+
25012512
// =======
25022513
// Modules
25032514
// =======

0 commit comments

Comments
 (0)