Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions src/cfg/cfg-traversal.h
Original file line number Diff line number Diff line change
Expand Up @@ -292,11 +292,12 @@ struct CFGWalker : public PostWalker<SubType, VisitorType> {
// and the target try.
[[maybe_unused]] bool found = false;
for (int j = i - 1; j >= 0; j--) {
if (self->tryStack[j]->template cast<Try>()->name ==
tryy->delegateTarget) {
i = j;
found = true;
break;
if (auto* outerTry = self->tryStack[j]->template dynCast<Try>()) {
if (outerTry->name == tryy->delegateTarget) {
i = j;
found = true;
break;
}
}
}
assert(found);
Expand Down
3 changes: 2 additions & 1 deletion src/passes/Print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2999,11 +2999,11 @@ void PrintSExpression::visitBlock(Block* curr) {
}

void PrintSExpression::visitIf(If* curr) {
controlFlowDepth++;
o << '(';
printExpressionContents(curr);
incIndent();
printFullLine(curr->condition);
controlFlowDepth++;
doIndent(o, indent);
o << "(then";
incIndent();
Expand Down Expand Up @@ -3955,6 +3955,7 @@ static std::ostream& printStackIR(StackIR* ir, PrintSExpression& printer) {
} else {
curr->delegateTarget.print(o);
}
catchIndexStack.pop_back();
break;
}
default:
Expand Down
1 change: 1 addition & 0 deletions src/tools/fuzzing.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ class TranslateToFuzzReader {
TranslateToFuzzReader& parent;
Function* func;
std::vector<Expression*> breakableStack; // things we can break to
std::vector<Name> tryStack; // tries we can delegate to
Index labelIndex = 0;

// a list of things relevant to computing the odds of an infinite loop,
Expand Down
18 changes: 15 additions & 3 deletions src/tools/fuzzing/fuzzing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2358,7 +2358,7 @@ void TranslateToFuzzReader::fixAfterChanges(Function* func) {
}
});
BranchUtils::operateOnScopeNameUses(curr, [&](Name& name) {
if (name.is()) {
if (name.is() && name != DELEGATE_CALLER_TARGET) {
replaceIfInvalid(name);
}
});
Expand Down Expand Up @@ -2418,6 +2418,9 @@ void TranslateToFuzzReader::fixAfterChanges(Function* func) {

// Check if a reference to a try is valid.
bool isValidTryRef(Name target, Expression* curr) {
if (curr->is<Try>() && target == DELEGATE_CALLER_TARGET) {
return true;
}
// The rethrow or try must be on top.
assert(!expressionStack.empty());
assert(expressionStack.back() == curr);
Expand Down Expand Up @@ -3204,7 +3207,17 @@ Expression* TranslateToFuzzReader::makeIf(Type type) {
}

Expression* TranslateToFuzzReader::makeTry(Type type) {
auto name = makeLabel();
funcContext->tryStack.push_back(name);
auto* body = make(type);
funcContext->tryStack.pop_back();
if (oneIn(3)) {
Name delegateTarget = DELEGATE_CALLER_TARGET;
if (!funcContext->tryStack.empty() && !oneIn(4)) {
delegateTarget = pick(funcContext->tryStack);
}
return builder.makeTry(name, body, delegateTarget);
}
std::vector<Name> catchTags;
std::vector<Expression*> catchBodies;
auto numTags = upTo(fuzzParams->MAX_TRY_CATCHES);
Expand Down Expand Up @@ -3247,8 +3260,7 @@ Expression* TranslateToFuzzReader::makeTry(Type type) {
}
catchBodies.push_back(catchBody);
}
// TODO: delegate stuff
return builder.makeTry(body, catchTags, catchBodies);
return builder.makeTry(name, body, catchTags, catchBodies);
}

Expression* TranslateToFuzzReader::makeTryTable(Type type) {
Expand Down
2 changes: 1 addition & 1 deletion src/wasm/wasm-stack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3681,7 +3681,7 @@ StackInst* StackIRGenerator::makeStackInst(StackInst::Op op,
stackType = Type::none;
} else if (op != StackInst::BlockEnd && op != StackInst::IfEnd &&
op != StackInst::LoopEnd && op != StackInst::TryEnd &&
op != StackInst::TryTableEnd) {
op != StackInst::Delegate && op != StackInst::TryTableEnd) {
// If a concrete type is returned, we mark the end of the construct has
// having that type (as it is pushed to the value stack at that point),
// other parts are marked as none).
Expand Down
56 changes: 56 additions & 0 deletions test/lit/basic/exception-handling-legacy.wast
Original file line number Diff line number Diff line change
Expand Up @@ -1301,6 +1301,48 @@
)
(nop)
)

;; CHECK-TEXT: (func $delegate-within-if-condition (type $0)
;; CHECK-TEXT-NEXT: (if
;; CHECK-TEXT-NEXT: (try (result i32)
;; CHECK-TEXT-NEXT: (do
;; CHECK-TEXT-NEXT: (i32.const 1)
;; CHECK-TEXT-NEXT: )
;; CHECK-TEXT-NEXT: (delegate 0)
;; CHECK-TEXT-NEXT: )
;; CHECK-TEXT-NEXT: (then
;; CHECK-TEXT-NEXT: (nop)
;; CHECK-TEXT-NEXT: )
;; CHECK-TEXT-NEXT: )
;; CHECK-TEXT-NEXT: )
;; CHECK-BIN: (func $delegate-within-if-condition (type $0)
;; CHECK-BIN-NEXT: (if
;; CHECK-BIN-NEXT: (try (result i32)
;; CHECK-BIN-NEXT: (do
;; CHECK-BIN-NEXT: (i32.const 1)
;; CHECK-BIN-NEXT: )
;; CHECK-BIN-NEXT: (delegate 0)
;; CHECK-BIN-NEXT: )
;; CHECK-BIN-NEXT: (then
;; CHECK-BIN-NEXT: (nop)
;; CHECK-BIN-NEXT: )
;; CHECK-BIN-NEXT: )
;; CHECK-BIN-NEXT: )
(func $delegate-within-if-condition
;; An 'if' condition is outside the 'if' control flow scope, so a delegate
;; to the caller inside the condition should have depth 0.
(if
(try (result i32)
(do
(i32.const 1)
)
(delegate 0)
)
(then
(nop)
)
)
)
)
;; CHECK-BIN-NODEBUG: (type $0 (func))

Expand Down Expand Up @@ -1790,3 +1832,17 @@
;; CHECK-BIN-NODEBUG-NEXT: )
;; CHECK-BIN-NODEBUG-NEXT: (nop)
;; CHECK-BIN-NODEBUG-NEXT: )

;; CHECK-BIN-NODEBUG: (func $25 (type $0)
;; CHECK-BIN-NODEBUG-NEXT: (if
;; CHECK-BIN-NODEBUG-NEXT: (try (result i32)
;; CHECK-BIN-NODEBUG-NEXT: (do
;; CHECK-BIN-NODEBUG-NEXT: (i32.const 1)
;; CHECK-BIN-NODEBUG-NEXT: )
;; CHECK-BIN-NODEBUG-NEXT: (delegate 0)
;; CHECK-BIN-NODEBUG-NEXT: )
;; CHECK-BIN-NODEBUG-NEXT: (then
;; CHECK-BIN-NODEBUG-NEXT: (nop)
;; CHECK-BIN-NODEBUG-NEXT: )
;; CHECK-BIN-NODEBUG-NEXT: )
;; CHECK-BIN-NODEBUG-NEXT: )
52 changes: 52 additions & 0 deletions test/lit/passes/rse-eh-legacy.wast
Original file line number Diff line number Diff line change
Expand Up @@ -798,4 +798,56 @@
;; catch_all runs the same local.set. So this can be dropped.
(local.set $x (i32.const 1))
)

;; CHECK: (func $try-delegate-across-try-table (type $0)
;; CHECK-NEXT: (local $x i32)
;; CHECK-NEXT: (try $l0
;; CHECK-NEXT: (do
;; CHECK-NEXT: (block $catch
;; CHECK-NEXT: (try_table (catch_all $catch)
;; CHECK-NEXT: (try
;; CHECK-NEXT: (do
;; CHECK-NEXT: (throw $e
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (delegate $l0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (catch_all
;; CHECK-NEXT: (local.set $x
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $try-delegate-across-try-table
(local $x i32)
(try $l0
(do
(block $catch
(try_table (catch_all $catch)
(try
(do
(throw $e (i32.const 0))
)
(delegate $l0)
)
)
)
)
(catch_all
(local.set $x (i32.const 1))
)
)
;; The innermost try delegates to $l0 across a try_table, so the exception
;; is caught by $l0's catch_all, which sets $x to 1. Thus this redundant set
;; can be dropped.
(local.set $x (i32.const 1))
)
)
56 changes: 55 additions & 1 deletion test/lit/passes/stack-ir-eh-legacy.wast
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
;; RUN: wasm-opt %s --generate-stack-ir --optimize-stack-ir \
;; RUN: wasm-opt %s --generate-stack-ir --optimize-stack-ir --optimize-level=3 \
;; RUN: -all --print-stack-ir | filecheck %s

(module
;; CHECK: (tag $e0 (type $0) (param i32))
(tag $e0 (param i32))
;; CHECK: (tag $e1 (type $0) (param i32))
(tag $e1 (param i32))

;; CHECK: (func $eh (type $1)
;; CHECK-NEXT: try $l0
Expand Down Expand Up @@ -56,4 +58,56 @@
(delegate 0) ;; delegate to caller
)
)

;; CHECK: (func $concrete-delegate (type $2) (result i32)
;; CHECK-NEXT: (local $x i32)
;; CHECK-NEXT: try (result i32)
;; CHECK-NEXT: i32.const 42
;; CHECK-NEXT: delegate 0
;; CHECK-NEXT: )
(func $concrete-delegate (result i32)
;; A concrete-typed try-delegate whose result is consumed after local2Stack.
(local $x i32)
(local.set $x
(try (result i32)
(do
(i32.const 42)
)
(delegate 0)
)
)
(local.get $x)
)

;; CHECK: (func $delegate-in-catch (type $1)
;; CHECK-NEXT: try
;; CHECK-NEXT: i32.const 0
;; CHECK-NEXT: throw $e0
;; CHECK-NEXT: catch $e0
;; CHECK-NEXT: drop
;; CHECK-NEXT: try
;; CHECK-NEXT: delegate 1
;; CHECK-NEXT: catch $e1
;; CHECK-NEXT: drop
;; CHECK-NEXT: end
;; CHECK-NEXT: )
(func $delegate-in-catch
;; A try-delegate inside a catch block should properly pop catchIndexStack
;; when printing StackIR so subsequent catches print the right tag.
(try
(do
(throw $e0 (i32.const 0))
)
(catch $e0
(drop (pop i32))
(try
(do)
(delegate 0)
)
)
(catch $e1
(drop (pop i32))
)
)
)
)
Loading
Loading