From 661a8fece52bdf4f1369651ba2663625633ab19e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 16 Oct 2025 09:14:15 -0700 Subject: [PATCH 1/2] Directize: Refine results --- src/passes/Directize.cpp | 9 +++++++- test/lit/passes/directize-gc.wast | 37 +++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/passes/Directize.cpp b/src/passes/Directize.cpp index 519049456cb..9be89ba8b21 100644 --- a/src/passes/Directize.cpp +++ b/src/passes/Directize.cpp @@ -189,9 +189,16 @@ struct FunctionDirectizer : public WalkerPass> { // Everything looks good! auto name = std::get(info).target; + auto results = getModule()->getFunction(name)->getResults(); replaceCurrent( Builder(*getModule()) - .makeCall(name, operands, original->type, original->isReturn)); + .makeCall(name, operands, results, original->isReturn)); + + // When we call a function of a subtype of the call_indirect's call type, we + // may be refining results. + if (results != original->type) { + changedTypes = true; + } } }; diff --git a/test/lit/passes/directize-gc.wast b/test/lit/passes/directize-gc.wast index fcf5c98116f..20f5ac1f9a4 100644 --- a/test/lit/passes/directize-gc.wast +++ b/test/lit/passes/directize-gc.wast @@ -112,3 +112,40 @@ ) ) +;; call_indirect using the supertype. The direct call has a more refined type, +;; which we must update the IR to. +(module + (rec + ;; CHECK: (rec + ;; CHECK-NEXT: (type $super (sub (func (result (ref any))))) + (type $super (sub (func (result (ref any))))) + ;; CHECK: (type $sub (sub $super (func (result (ref none))))) + (type $sub (sub $super (func (result (ref none))))) + ) + + ;; CHECK: (table $table 42 funcref) + (table $table 42 funcref) + ;; CHECK: (elem $elem (i32.const 0) $sub) + (elem $elem (i32.const 0) $sub) + + ;; CHECK: (func $super (type $super) (result (ref any)) + ;; CHECK-NEXT: (block $show-type (result (ref none)) + ;; CHECK-NEXT: (call $sub) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $super (type $super) (result (ref any)) + (block $show-type (result (ref any)) + (call_indirect $table (type $super) + (i32.const 0) + ) + ) + ) + + ;; CHECK: (func $sub (type $sub) (result (ref none)) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + (func $sub (type $sub) (result (ref none)) + (unreachable) + ) +) + From c696b94e30e5cd2852f860658b6f6a208019d569 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 16 Oct 2025 09:14:30 -0700 Subject: [PATCH 2/2] format --- src/passes/Directize.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/passes/Directize.cpp b/src/passes/Directize.cpp index 9be89ba8b21..3a458772467 100644 --- a/src/passes/Directize.cpp +++ b/src/passes/Directize.cpp @@ -190,9 +190,8 @@ struct FunctionDirectizer : public WalkerPass> { // Everything looks good! auto name = std::get(info).target; auto results = getModule()->getFunction(name)->getResults(); - replaceCurrent( - Builder(*getModule()) - .makeCall(name, operands, results, original->isReturn)); + replaceCurrent(Builder(*getModule()) + .makeCall(name, operands, results, original->isReturn)); // When we call a function of a subtype of the call_indirect's call type, we // may be refining results.