Skip to content

[wasm-merge] Handle table initializer referring to imported global - #9167

Merged
kripken merged 2 commits into
WebAssembly:mainfrom
vouillon:wasm-merge-fix
Oct 1, 2026
Merged

kripken merged 2 commits into
WebAssembly:mainfrom
vouillon:wasm-merge-fix

Conversation

@vouillon

Copy link
Copy Markdown
Contributor

Unlike global initializers and element segments (which under GC may refer to preceding module-defined globals), a table initializer expression may only refer to imported globals. Fusing can turn an imported global that a table initializer refers to into a module-defined one, which would make the initializer invalid. When that happens, inline the referenced global's (immutable, constant) value so the initializer remains valid.

Unlike global initializers and element segments (which under GC may
refer to preceding module-defined globals), a table initializer
expression may only refer to imported globals. Fusing can turn an
imported global that a table initializer refers to into a module-defined
one, which would make the initializer invalid. When that happens, inline
the referenced global's (immutable, constant) value so the initializer
remains valid.
@vouillon
vouillon requested a review from a team as a code owner September 28, 2026 18:09
@vouillon
vouillon requested review from aheejin and removed request for a team September 28, 2026 18:09
Comment thread src/tools/wasm-merge.cpp Outdated
struct Inliner : public PostWalker<Inliner> {
bool inlined = false;
void visitGlobalGet(GlobalGet* curr) {
auto* global = getModule()->getGlobalOrNull(curr->name);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can the result here be null? I think we can use getGlobal()?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. Fixed.

Comment thread src/tools/wasm-merge.cpp
// global's initializer refers to another one), so iterate to a fixed point.
// Globals cannot form cycles, so this terminates. Any global.gets that
// remain refer to imported globals, which are valid in table initializers.
while (true) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a second testcase that adds coverage for the looping.

@kripken kripken left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm otherwise

@kripken
kripken merged commit d2a7cc3 into WebAssembly:main Oct 1, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants