diff options
author | Heejin Ahn <aheejin@gmail.com> | 2024-04-23 17:37:11 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-23 17:37:11 +0900 |
commit | a3c789008726ccf891b5f5581c87194578c32af4 (patch) | |
tree | ba3d713d751ae2be0629d5f852abb38f187ed489 | |
parent | e50a2ba8e85c274880898ef7c5d6efc186efcc17 (diff) | |
download | binaryen-a3c789008726ccf891b5f5581c87194578c32af4.tar.gz binaryen-a3c789008726ccf891b5f5581c87194578c32af4.tar.bz2 binaryen-a3c789008726ccf891b5f5581c87194578c32af4.zip |
[EH] Fix delegating to caller when func result is concrete (#6518)
hen the function return type is concrete, the translation result of a
`try`-`delegate` that targets the caller includes a `return` that
returns the whole function body:
https://github.com/WebAssembly/binaryen/blob/219e668e87b012c0634043ed702534b8be31231f/src/passes/TranslateEH.cpp#L751-L763
We should do that based on the function's return type, not the function
body's return type. The previous code didn't handle the case where the
function's return type is concrete but the function body's return type
is unreachable.
-rw-r--r-- | src/passes/TranslateEH.cpp | 2 | ||||
-rw-r--r-- | test/lit/passes/translate-to-new-eh.wast | 45 |
2 files changed, 46 insertions, 1 deletions
diff --git a/src/passes/TranslateEH.cpp b/src/passes/TranslateEH.cpp index 760c4b656..33fa4689d 100644 --- a/src/passes/TranslateEH.cpp +++ b/src/passes/TranslateEH.cpp @@ -762,7 +762,7 @@ struct TranslateToNewEH : public WalkerPass<PostWalker<TranslateToNewEH>> { // ) // ) Expression* innerBody = nullptr; - if (func->body->type.isConcrete()) { + if (func->getResults().isConcrete()) { auto* ret = builder.makeReturn(func->body); innerBody = builder.blockifyWithName( ret, callerDelegateBrTarget, nullptr, Type(HeapType::exn, Nullable)); diff --git a/test/lit/passes/translate-to-new-eh.wast b/test/lit/passes/translate-to-new-eh.wast index 3837ebf28..b1bbb4b98 100644 --- a/test/lit/passes/translate-to-new-eh.wast +++ b/test/lit/passes/translate-to-new-eh.wast @@ -2125,4 +2125,49 @@ (delegate 0) ) ) + + ;; CHECK: (func $throw_ref-in-resultless-block (type $2) (result i32) + ;; CHECK-NEXT: (throw_ref + ;; CHECK-NEXT: (block $__binaryen_delegate_caller_target0 (result exnref) + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (try_table (catch_all_ref $__binaryen_delegate_caller_target0) + ;; CHECK-NEXT: (call $foo) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; STACKIR-OPT: (func $throw_ref-in-resultless-block (type $2) (result i32) + ;; STACKIR-OPT-NEXT: block $__binaryen_delegate_caller_target0 (result exnref) + ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $__binaryen_delegate_caller_target0) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: unreachable + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: ) + (func $throw_ref-in-resultless-block (result i32) + ;; When the function return type is concrete, try-delegate that targets the + ;; caller is translated to + ;; (throw_ref + ;; (block $__binaryen_delegate_caller_target (result exnref) + ;; (return + ;; function body + ;; ) + ;; ) + ;; ) + ;; We should do that even if the function body's type is not concrete. + (block ;; This block doesn't have concrete result type + (try + (do + (call $foo) + ) + (delegate 1) + ) + (unreachable) + ) + ) ) |