diff options
author | Alon Zakai <azakai@google.com> | 2021-07-29 10:34:34 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-29 10:34:34 -0700 |
commit | be119e310624aa332fb476613a6e970fe214ec83 (patch) | |
tree | 8c75509a03af833b01bf10f5444042a52c409473 | |
parent | 518ec5e028f540af69c9a346c4232941d81367ac (diff) | |
download | binaryen-be119e310624aa332fb476613a6e970fe214ec83.tar.gz binaryen-be119e310624aa332fb476613a6e970fe214ec83.tar.bz2 binaryen-be119e310624aa332fb476613a6e970fe214ec83.zip |
[Wasm GC] Handle call_ref in DeadArgument return refinement (#4038)
-rw-r--r-- | src/passes/DeadArgumentElimination.cpp | 12 | ||||
-rw-r--r-- | test/lit/passes/dae-gc-refine-return.wast | 61 |
2 files changed, 73 insertions, 0 deletions
diff --git a/src/passes/DeadArgumentElimination.cpp b/src/passes/DeadArgumentElimination.cpp index 601acfc5c..419ae1aca 100644 --- a/src/passes/DeadArgumentElimination.cpp +++ b/src/passes/DeadArgumentElimination.cpp @@ -682,6 +682,18 @@ private: return false; } } + for (auto* call : FindAll<CallRef>(func->body).list) { + if (call->isReturn) { + auto targetType = call->target->type; + if (targetType == Type::unreachable) { + continue; + } + if (!processReturnType( + targetType.getHeapType().getSignature().results)) { + return false; + } + } + } assert(refinedType != originalType); // If the refined type is unreachable then nothing actually returns from diff --git a/test/lit/passes/dae-gc-refine-return.wast b/test/lit/passes/dae-gc-refine-return.wast index 9f945a5b3..128b5fbcf 100644 --- a/test/lit/passes/dae-gc-refine-return.wast +++ b/test/lit/passes/dae-gc-refine-return.wast @@ -382,4 +382,65 @@ (call $tail-caller-indirect-no) ) ) + + ;; As above, but with a tail call by function reference. + ;; CHECK: (func $tail-callee-call_ref (result (ref ${})) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + (func $tail-callee-call_ref (result (ref ${})) + (unreachable) + ) + ;; CHECK: (func $tail-caller-call_ref-yes (result (ref ${})) + ;; CHECK-NEXT: (return_call_ref + ;; CHECK-NEXT: (ref.null $return_{}) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $tail-caller-call_ref-yes (result anyref) + (return_call_ref (ref.null $return_{})) + ) + ;; CHECK: (func $tail-caller-call_ref-no (result anyref) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (ref.null any) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (return_call_ref + ;; CHECK-NEXT: (ref.null $return_{}) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $tail-caller-call_ref-no (result anyref) + (if (i32.const 1) + (return (ref.null any)) + ) + (return_call_ref (ref.null $return_{})) + ) + ;; CHECK: (func $tail-caller-call_ref-unreachable + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + (func $tail-caller-call_ref-unreachable (result anyref) + ;; An unreachable means there is no function signature to even look at. We + ;; should not hit an assertion on such things. + (return_call_ref (unreachable)) + ) + ;; CHECK: (func $tail-call-caller-call_ref + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $tail-caller-call_ref-yes) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $tail-caller-call_ref-no) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $tail-caller-call_ref-unreachable) + ;; CHECK-NEXT: ) + (func $tail-call-caller-call_ref + (drop + (call $tail-caller-call_ref-yes) + ) + (drop + (call $tail-caller-call_ref-no) + ) + (drop + (call $tail-caller-call_ref-unreachable) + ) + ) ) |