summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/DeadArgumentElimination.cpp12
-rw-r--r--test/lit/passes/dae-gc-refine-return.wast61
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)
+ )
+ )
)