Skip to content

Commit

Permalink
[Parser] Parse rethrow
Browse files Browse the repository at this point in the history
Like `delegate`, rethrow takes a `Try` label. Refactor the delegate handling so
that `Try` can share its logic.
  • Loading branch information
tlively committed Dec 8, 2023
1 parent d76f1d8 commit f73773b
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 17 deletions.
5 changes: 5 additions & 0 deletions src/parser/contexts.h
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@ struct NullInstrParserCtx {
Result<> makeTableFill(Index, TableIdxT*) { return Ok{}; }
Result<> makeTableCopy(Index, TableIdxT*, TableIdxT*) { return Ok{}; }
Result<> makeThrow(Index, TagIdxT) { return Ok{}; }
Result<> makeRethrow(Index, LabelIdxT) { return Ok{}; }
template<typename HeapTypeT> Result<> makeCallRef(Index, HeapTypeT, bool) {
return Ok{};
}
Expand Down Expand Up @@ -1572,6 +1573,10 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
return withLoc(pos, irBuilder.makeThrow(tag));
}

Result<> makeRethrow(Index pos, Index label) {
return withLoc(pos, irBuilder.makeRethrow(label));
}

Result<> makeCallRef(Index pos, HeapType type, bool isReturn) {
return withLoc(pos, irBuilder.makeCallRef(type, isReturn));
}
Expand Down
4 changes: 3 additions & 1 deletion src/parser/parsers.h
Original file line number Diff line number Diff line change
Expand Up @@ -1479,7 +1479,9 @@ template<typename Ctx> Result<> makeThrow(Ctx& ctx, Index pos) {
}

template<typename Ctx> Result<> makeRethrow(Ctx& ctx, Index pos) {
return ctx.in.err("unimplemented instruction");
auto label = labelidx(ctx);
CHECK_ERR(label);
return ctx.makeRethrow(pos, *label);
}

template<typename Ctx> Result<> makeTupleMake(Ctx& ctx, Index pos) {
Expand Down
3 changes: 2 additions & 1 deletion src/wasm-ir-builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
[[nodiscard]] Result<> makeTableCopy(Name destTable, Name srcTable);
[[nodiscard]] Result<> makeTry(Name label, Type type);
[[nodiscard]] Result<> makeThrow(Name tag);
// [[nodiscard]] Result<> makeRethrow();
[[nodiscard]] Result<> makeRethrow(Index label);
// [[nodiscard]] Result<> makeTupleMake();
// [[nodiscard]] Result<> makeTupleExtract();
[[nodiscard]] Result<> makeRefI31();
Expand Down Expand Up @@ -459,6 +459,7 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
Result<Expression*> finishScope(Block* block = nullptr);

[[nodiscard]] Result<Name> getLabelName(Index label);
[[nodiscard]] Result<Name> getDelegateLabelName(Index label);
[[nodiscard]] Result<Index> addScratchLocal(Type);
[[nodiscard]] Result<Expression*> pop();

Expand Down
54 changes: 40 additions & 14 deletions src/wasm/wasm-ir-builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -499,8 +499,8 @@ Result<> IRBuilder::visitLoopStart(Loop* loop) {
}

Result<> IRBuilder::visitTryStart(Try* tryy, Name label) {
// The delegate label will be regenerated if we need it. See `visitDelegate`
// for details.
// The delegate label will be regenerated if we need it. See
// `getDelegateLabelName` for details.
tryy->name = Name();
pushScope(ScopeCtx::makeTry(tryy, label));
return Ok{};
Expand Down Expand Up @@ -663,6 +663,33 @@ Result<> IRBuilder::visitCatchAll() {
return Ok{};
}

Result<Name> IRBuilder::getDelegateLabelName(Index label) {
if (label >= scopeStack.size()) {
return Err{"invalid label: " + std::to_string(label)};
}
auto& scope = scopeStack[scopeStack.size() - label - 1];
auto* delegateTry = scope.getTry();
if (!delegateTry) {
delegateTry = scope.getCatch();
}
if (!delegateTry) {
delegateTry = scope.getCatchAll();
}
if (!delegateTry) {
return Err{"expected try scope at label " + std::to_string(label)};
}
// Only delegate and rethrow can reference the try name in Binaryen IR, so
// trys might need two labels: one for delegate/rethrow and one for all
// other control flow. These labels must be different to satisfy the
// Binaryen validator. To keep this complexity contained within the
// handling of trys and delegates, pretend there is just the single normal
// label and add a prefix to it to generate the delegate label.
auto delegateName =
Name(std::string("__delegate__") + getLabelName(label)->toString());
delegateTry->name = delegateName;
return delegateName;
}

Result<> IRBuilder::visitDelegate(Index label) {
auto& scope = getScope();
auto* tryy = scope.getTry();
Expand All @@ -676,17 +703,10 @@ Result<> IRBuilder::visitDelegate(Index label) {
++label;
for (size_t size = scopeStack.size(); label < size; ++label) {
auto& delegateScope = scopeStack[size - label - 1];
if (auto* delegateTry = delegateScope.getTry()) {
// Only delegates can reference the try name in Binaryen IR, so trys might
// need two labels: one for delegates and one for all other control flow.
// These labels must be different to satisfy the Binaryen validator. To
// keep this complexity contained within the handling of trys and
// delegates, pretend there is just the single normal label and add a
// prefix to it to generate the delegate label.
auto delegateName =
Name(std::string("__delegate__") + getLabelName(label)->toString());
delegateTry->name = delegateName;
tryy->delegateTarget = delegateName;
if (delegateScope.getTry()) {
auto delegateName = getDelegateLabelName(label);
CHECK_ERR(delegateName);
tryy->delegateTarget = *delegateName;
break;
} else if (delegateScope.getFunction()) {
tryy->delegateTarget = DELEGATE_CALLER_TARGET;
Expand Down Expand Up @@ -1215,7 +1235,13 @@ Result<> IRBuilder::makeThrow(Name tag) {
return Ok{};
}

// Result<> IRBuilder::makeRethrow() {}
Result<> IRBuilder::makeRethrow(Index label) {
// Rethrow references `Try` labels directly, just like `delegate`.
auto name = getDelegateLabelName(label);
CHECK_ERR(name);
push(builder.makeRethrow(*name));
return Ok{};
}

// Result<> IRBuilder::makeTupleMake() {}

Expand Down
102 changes: 101 additions & 1 deletion test/lit/wat-kitchen-sink.wast
Original file line number Diff line number Diff line change
Expand Up @@ -2024,6 +2024,106 @@
)
)

;; CHECK: (func $rethrow (type $void)
;; CHECK-NEXT: (block $label
;; CHECK-NEXT: (try $__delegate__label
;; CHECK-NEXT: (do
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
;; CHECK-NEXT: (catch $empty
;; CHECK-NEXT: (rethrow $__delegate__label)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $rethrow
try
catch $empty
rethrow 0
end
)

;; CHECK: (func $rethrow-named (type $void)
;; CHECK-NEXT: (block $l
;; CHECK-NEXT: (try $__delegate__l
;; CHECK-NEXT: (do
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
;; CHECK-NEXT: (catch $empty
;; CHECK-NEXT: (rethrow $__delegate__l)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $rethrow-named
try $l
catch $empty
rethrow $l
end
)

;; CHECK: (func $rethrow-nested (type $void)
;; CHECK-NEXT: (block $label
;; CHECK-NEXT: (try $__delegate__label
;; CHECK-NEXT: (do
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
;; CHECK-NEXT: (catch $empty
;; CHECK-NEXT: (try
;; CHECK-NEXT: (do
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
;; CHECK-NEXT: (catch $empty
;; CHECK-NEXT: (rethrow $__delegate__label)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $rethrow-nested
try
catch $empty
block
try
catch $empty
rethrow 2
end
end
end
)

;; CHECK: (func $rethrow-nested-named (type $void)
;; CHECK-NEXT: (block $l
;; CHECK-NEXT: (try $__delegate__l
;; CHECK-NEXT: (do
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
;; CHECK-NEXT: (catch $empty
;; CHECK-NEXT: (try
;; CHECK-NEXT: (do
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
;; CHECK-NEXT: (catch $empty
;; CHECK-NEXT: (rethrow $__delegate__l)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $rethrow-nested-named
try $l
catch $empty
block
try
catch $empty
rethrow $l
end
end
end
)

;; CHECK: (func $label-siblings (type $void)
;; CHECK-NEXT: (block $l
;; CHECK-NEXT: (br $l)
Expand Down Expand Up @@ -2922,7 +3022,7 @@
(func $ref-func
ref.func $ref-func
drop
ref.func 129
ref.func 133
drop
)

Expand Down

0 comments on commit f73773b

Please sign in to comment.