Skip to content

Commit f8275a5

Browse files
authored
wasm-merge: Handle imported functions that use supertypes (#7957)
In such a case we must update (refine) the type after merging, to avoid validation errors.
1 parent 959d522 commit f8275a5

3 files changed

Lines changed: 72 additions & 0 deletions

File tree

src/tools/wasm-merge.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@
9999

100100
#include "ir/module-utils.h"
101101
#include "ir/names.h"
102+
#include "ir/utils.h"
102103
#include "support/colors.h"
103104
#include "support/file.h"
104105
#include "wasm-builder.h"
@@ -557,6 +558,30 @@ void fuseImportsAndExports(const PassOptions& options) {
557558
updateNames(merged, kindNameUpdates);
558559
}
559560

561+
// Things may have been imported using supertypes, which means they can get
562+
// refined after merging.
563+
void updateTypes(Module& wasm) {
564+
struct Updater : public WalkerPass<PostWalker<Updater>> {
565+
bool isFunctionParallel() override { return true; }
566+
567+
std::unique_ptr<Pass> create() override {
568+
return std::make_unique<Updater>();
569+
}
570+
571+
void visitRefFunc(RefFunc* curr) {
572+
curr->finalize(getModule()->getFunction(curr->func)->type);
573+
}
574+
575+
void visitFunction(Function* curr) {
576+
ReFinalize().walkFunctionInModule(curr, getModule());
577+
}
578+
} updater;
579+
580+
PassRunner runner(&wasm);
581+
updater.run(&runner, &wasm);
582+
updater.runOnModuleCode(&runner, &wasm);
583+
}
584+
560585
// Merges an input module into an existing target module. The input module can
561586
// be modified, as it will no longer be needed (so it is intentionally not
562587
// marked as const here).
@@ -765,6 +790,9 @@ Input source maps can be specified by adding an -ism option right after the modu
765790
// module.
766791
fuseImportsAndExports(options.passOptions);
767792

793+
// Update types after combing and linking everything.
794+
updateTypes(merged);
795+
768796
{
769797
PassRunner passRunner(&merged);
770798
// We might have made some globals read from others that now appear after

test/lit/merge/func_subtyping.wat

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
2+
3+
;; RUN: wasm-merge %s primary %s.second secondary --skip-export-conflicts -all -S -o - | filecheck %s
4+
5+
;; Export a function with a subtype. It is imported using the supertype, and
6+
;; after we merge, the type must be updated. That update will then propagate to
7+
;; the call_ref.
8+
(module
9+
;; CHECK: (type $super (sub (func)))
10+
(type $super (sub (func)))
11+
;; CHECK: (type $sub (sub final $super (func)))
12+
(type $sub (sub final $super (func)))
13+
14+
;; CHECK: (type $2 (func))
15+
16+
;; CHECK: (elem declare func $sub)
17+
18+
;; CHECK: (export "sub" (func $sub))
19+
20+
;; CHECK: (export "caller" (func $caller))
21+
22+
;; CHECK: (func $sub (type $sub)
23+
;; CHECK-NEXT: )
24+
(func $sub (export "sub") (type $sub)
25+
)
26+
)
27+
28+
;; CHECK: (func $caller (type $2)
29+
;; CHECK-NEXT: (call_ref $sub
30+
;; CHECK-NEXT: (ref.func $sub)
31+
;; CHECK-NEXT: )
32+
;; CHECK-NEXT: )
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
(module
2+
(type $second-super (sub (func)))
3+
4+
(import "primary" "sub" (func $import (type $second-super)))
5+
6+
(func $caller (export "caller")
7+
(call_ref $second-super
8+
(ref.func $import)
9+
)
10+
)
11+
)
12+

0 commit comments

Comments
 (0)