From d8947db3fd29eb1bd48b28a5b10779ffb8ba025c Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 3 Nov 2025 09:19:01 -0800 Subject: [PATCH 1/3] work --- src/tools/wasm-merge.cpp | 6 +++ test/lit/merge/func_subtyping_return.wat | 43 +++++++++++++++++++ .../merge/func_subtyping_return.wat.second | 26 +++++++++++ 3 files changed, 75 insertions(+) create mode 100644 test/lit/merge/func_subtyping_return.wat create mode 100644 test/lit/merge/func_subtyping_return.wat.second diff --git a/src/tools/wasm-merge.cpp b/src/tools/wasm-merge.cpp index 958c45fce3c..1c8ebe135b3 100644 --- a/src/tools/wasm-merge.cpp +++ b/src/tools/wasm-merge.cpp @@ -570,6 +570,12 @@ void updateTypes(Module& wasm) { return std::make_unique(); } + void visitCall(Call* curr) { + if (curr->type != Type::unreachable) { + curr->type = getModule()->getFunction(curr->target)->type.getHeapType().getSignature().results; + } + } + void visitRefFunc(RefFunc* curr) { curr->finalize(getModule()->getFunction(curr->func)->type.getHeapType()); } diff --git a/test/lit/merge/func_subtyping_return.wat b/test/lit/merge/func_subtyping_return.wat new file mode 100644 index 00000000000..2232f77a418 --- /dev/null +++ b/test/lit/merge/func_subtyping_return.wat @@ -0,0 +1,43 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. + +;; RUN: wasm-merge %s primary %s.second secondary --skip-export-conflicts -all -S -o - | filecheck %s + +;; Export a function with a subtype. It is imported using the supertype, and +;; after we merge, the refined return type must be updated - the call +;; instruction now returns something new. +(module + ;; CHECK: (type $0 (func (result anyref))) + + ;; CHECK: (type $super (sub (func (param i32) (result anyref)))) + (type $super (sub (func (param i32) (result anyref)))) + + ;; CHECK: (type $sub (sub final $super (func (param i32) (result (ref any))))) + (type $sub (sub final $super (func (param i32) (result (ref any))))) + + ;; CHECK: (export "sub" (func $sub)) + + ;; CHECK: (export "caller" (func $caller)) + + ;; CHECK: (export "caller-unreachable" (func $caller-unreachable)) + + ;; CHECK: (func $sub (type $sub) (param $0 i32) (result (ref any)) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + (func $sub (export "sub") (type $sub) + (unreachable) + ) +) + +;; CHECK: (func $caller (type $0) (result anyref) +;; CHECK-NEXT: (nop) +;; CHECK-NEXT: (call $sub +;; CHECK-NEXT: (i32.const 42) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) + +;; CHECK: (func $caller-unreachable (type $0) (result anyref) +;; CHECK-NEXT: (nop) +;; CHECK-NEXT: (call $sub +;; CHECK-NEXT: (unreachable) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) diff --git a/test/lit/merge/func_subtyping_return.wat.second b/test/lit/merge/func_subtyping_return.wat.second new file mode 100644 index 00000000000..e6611c2ca7f --- /dev/null +++ b/test/lit/merge/func_subtyping_return.wat.second @@ -0,0 +1,26 @@ +(module + (type $second-super (sub (func (param i32) (result anyref)))) + + (import "primary" "sub" (func $import (type $second-super))) + + (func $caller (export "caller") (result anyref) + ;; This will get refined from anyref to non-nullable. + (block (result anyref) + (nop) ;; keep the block non-trivial + (call $import + (i32.const 42) + ) + ) + ) + + (func $caller-unreachable (export "caller-unreachable") (result anyref) + ;; Unreachable code is not modified. + (block (result anyref) + (nop) + (call $import + (unreachable) + ) + ) + ) +) + From efff8f249d0c31786ee94015a2b5b54b2021b35e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 3 Nov 2025 09:20:13 -0800 Subject: [PATCH 2/3] fix --- test/lit/merge/func_subtyping_return.wat | 14 ++++++++------ test/lit/merge/func_subtyping_return.wat.second | 6 ++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/test/lit/merge/func_subtyping_return.wat b/test/lit/merge/func_subtyping_return.wat index 2232f77a418..9e32ad2a98f 100644 --- a/test/lit/merge/func_subtyping_return.wat +++ b/test/lit/merge/func_subtyping_return.wat @@ -29,15 +29,17 @@ ) ;; CHECK: (func $caller (type $0) (result anyref) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (call $sub -;; CHECK-NEXT: (i32.const 42) +;; CHECK-NEXT: (block $block (result (ref any)) +;; CHECK-NEXT: (call $sub +;; CHECK-NEXT: (i32.const 42) +;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK: (func $caller-unreachable (type $0) (result anyref) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (call $sub -;; CHECK-NEXT: (unreachable) +;; CHECK-NEXT: (block $block +;; CHECK-NEXT: (call $sub +;; CHECK-NEXT: (unreachable) +;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) diff --git a/test/lit/merge/func_subtyping_return.wat.second b/test/lit/merge/func_subtyping_return.wat.second index e6611c2ca7f..d5bc5f5e94d 100644 --- a/test/lit/merge/func_subtyping_return.wat.second +++ b/test/lit/merge/func_subtyping_return.wat.second @@ -5,8 +5,7 @@ (func $caller (export "caller") (result anyref) ;; This will get refined from anyref to non-nullable. - (block (result anyref) - (nop) ;; keep the block non-trivial + (block $block (result anyref) (call $import (i32.const 42) ) @@ -15,8 +14,7 @@ (func $caller-unreachable (export "caller-unreachable") (result anyref) ;; Unreachable code is not modified. - (block (result anyref) - (nop) + (block $block (result anyref) (call $import (unreachable) ) From 4be64f875d9fe6d2e32601de39bceeb8ccbe46f2 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 3 Nov 2025 09:20:20 -0800 Subject: [PATCH 3/3] fomr --- src/tools/wasm-merge.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/tools/wasm-merge.cpp b/src/tools/wasm-merge.cpp index 1c8ebe135b3..5fb1ff71619 100644 --- a/src/tools/wasm-merge.cpp +++ b/src/tools/wasm-merge.cpp @@ -572,7 +572,11 @@ void updateTypes(Module& wasm) { void visitCall(Call* curr) { if (curr->type != Type::unreachable) { - curr->type = getModule()->getFunction(curr->target)->type.getHeapType().getSignature().results; + curr->type = getModule() + ->getFunction(curr->target) + ->type.getHeapType() + .getSignature() + .results; } }