-
Notifications
You must be signed in to change notification settings - Fork 793
[EH] Fix missing outer block for catchless try #6519
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
When translating a `try` expression, we may need an 'outer' block that wraps the newly generated `try_table` so we can jump out of the expression when an exception does not occur. (The condition we use is when the `try` has any catches or if the `try` is a target of any inner `try-delegate`s: https://github.com/WebAssembly/binaryen/blob/219e668e87b012c0634043ed702534b8be31231f/src/passes/TranslateEH.cpp#L677) In case the `try` has either of `catch` or `delegate`, when we have the 'outer' block, we add the newly created `try_table` in the 'outer' block and replace the whole expression with the block: https://github.com/WebAssembly/binaryen/blob/219e668e87b012c0634043ed702534b8be31231f/src/passes/TranslateEH.cpp#L670 https://github.com/WebAssembly/binaryen/blob/219e668e87b012c0634043ed702534b8be31231f/src/passes/TranslateEH.cpp#L332-L340 But in case of a catchless `try`, we forgot to do that: https://github.com/WebAssembly/binaryen/blob/219e668e87b012c0634043ed702534b8be31231f/src/passes/TranslateEH.cpp#L388 So this PR fixes it.
;; CHECK-NEXT: (block $l00 (result exnref) | ||
;; CHECK-NEXT: (try_table (catch_all_ref $l00) | ||
;; CHECK-NEXT: (call $foo) | ||
;; CHECK-NEXT: (block $outer1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why was this outer block needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before we go into actually processing catch
es and delegate
s, we create an outer block in this condition:
binaryen/src/passes/TranslateEH.cpp
Line 677 in 219e668
if (it != delegateTargetToBrTarget.end() || curr->isCatch()) { |
Because
-
In case of a
delegate
, it will be translated into athrow_ref
to the delegate target. But when an exception does not occur, we have to bail out of thatthrow_ref
. And this outer block is that bail-out destination. It is explained here:
binaryen/src/passes/TranslateEH.cpp
Line 251 in e50a2ba
// (br $outer)
binaryen/src/passes/TranslateEH.cpp
Line 267 in e50a2ba
// (br $outer ;; Now has the try_table as a child. -
In case of
catch
es, we proceed into catch handler parts unless we bail out in case an exception does not occur. It is explained here:
binaryen/src/passes/TranslateEH.cpp
Line 415 in e50a2ba
// (br $outer)
binaryen/src/passes/TranslateEH.cpp
Line 436 in e50a2ba
// (br $outer
But this test does not need a br
because the body's type is unreachable due to a return
. We omit that br
here:
binaryen/src/passes/TranslateEH.cpp
Lines 298 to 300 in e50a2ba
auto* brToOuter = curr->body->type == Type::unreachable | |
? nullptr | |
: builder.makeBreak(outerBlock->name); |
It is hard to check this condition before creating an outer block. We can run BranchSeeker
to find out if the block is actually used as a destination for a branch afterwards to remove this unnecessary block. Do you want me to do that? It is not hard, but I didn't end up doing that because we might be adding too much optimization in this pass which should ideally be done by other passes later. Currently we run this pass at the end and don't run any other optimization passes after this, I already baked some amount of optimization into it though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tried removing it without using BranchSeeker
: 8c8fcc5
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great!
When translating a
try
expression, we may need an 'outer' block that wraps the newly generatedtry_table
so we can jump out of the expression when an exception does not occur. (The condition we use is when thetry
has any catches or if thetry
is a target of any innertry-delegate
s:binaryen/src/passes/TranslateEH.cpp
Line 677 in 219e668
In case the
try
has either ofcatch
ordelegate
, when we have the 'outer' block, we add the newly createdtry_table
in the 'outer' block and replace the whole expression with the block:binaryen/src/passes/TranslateEH.cpp
Line 670 in 219e668
binaryen/src/passes/TranslateEH.cpp
Lines 332 to 340 in 219e668
But in case of a catchless
try
, we forgot to do that:binaryen/src/passes/TranslateEH.cpp
Line 388 in 219e668
So this PR fixes it.