diff --git a/src/tools/wasm-merge.cpp b/src/tools/wasm-merge.cpp index 01614e19cec..a6215974b73 100644 --- a/src/tools/wasm-merge.cpp +++ b/src/tools/wasm-merge.cpp @@ -574,6 +574,16 @@ void updateTypes(Module& wasm) { curr->type = getModule()->getGlobal(curr->name)->type; } + 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..9e32ad2a98f --- /dev/null +++ b/test/lit/merge/func_subtyping_return.wat @@ -0,0 +1,45 @@ +;; 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: (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: (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 new file mode 100644 index 00000000000..d5bc5f5e94d --- /dev/null +++ b/test/lit/merge/func_subtyping_return.wat.second @@ -0,0 +1,24 @@ +(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 $block (result anyref) + (call $import + (i32.const 42) + ) + ) + ) + + (func $caller-unreachable (export "caller-unreachable") (result anyref) + ;; Unreachable code is not modified. + (block $block (result anyref) + (call $import + (unreachable) + ) + ) + ) +) +