summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeejin Ahn <aheejin@gmail.com>2024-04-23 17:37:11 +0900
committerGitHub <noreply@github.com>2024-04-23 17:37:11 +0900
commita3c789008726ccf891b5f5581c87194578c32af4 (patch)
treeba3d713d751ae2be0629d5f852abb38f187ed489
parente50a2ba8e85c274880898ef7c5d6efc186efcc17 (diff)
downloadbinaryen-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.cpp2
-rw-r--r--test/lit/passes/translate-to-new-eh.wast45
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)
+ )
+ )
)