Skip to content

[Heap2Local] Handle array init uses in Array2Struct - #9381

Open
tlively wants to merge 1 commit into
mainfrom
heap2local-array-init-uses
Open

tlively wants to merge 1 commit into
mainfrom
heap2local-array-init-uses

Conversation

@tlively

@tlively tlively commented Nov 11, 2026

Copy link
Copy Markdown
Member

Previously, Array2Struct constructed structNew and arrayNewReplacement in its constructor before walking the function body. This captured the allocation's init or values children prior to the post-order walk. However, when an array.new or array.new_fixed inside an unreachable loop read from itself (via the loop backedge) inside its own initializer operands, Array2Struct replaced those inner uses during the walk while arrayNewReplacement retained stale pointers to the unreplaced array.get expressions. Fix this by constructing structNew and arrayNewReplacement inside visitArrayNew and visitArrayNewFixed after child operands have been visited.

Also keep structNew->type as the concrete struct reference type even when an operand becomes unreachable, and defer ReFinalize until the end of Struct2Local so unreachability inside an operand does not propagate to structNew->type before Struct2Local runs. StructNew does not store its heap type separately from type, so Struct2Local depends on structNew->type remaining a concrete struct reference to look up the struct's fields when allocating locals and to construct the replacement ref.null.

Previously, `Array2Struct` constructed `structNew` and `arrayNewReplacement` in its constructor before walking the function body. This captured the allocation's `init` or `values` children prior to the post-order walk. However, when an `array.new` or `array.new_fixed` inside an unreachable loop read from itself (via the loop backedge) inside its own initializer operands, `Array2Struct` replaced those inner uses during the walk while `arrayNewReplacement` retained stale pointers to the unreplaced `array.get` expressions. Fix this by constructing `structNew` and `arrayNewReplacement` inside `visitArrayNew` and `visitArrayNewFixed` after child operands have been visited.

Also keep `structNew->type` as the concrete struct reference type even when an operand becomes `unreachable`, and defer `ReFinalize` until the end of `Struct2Local` so unreachability inside an operand does not propagate to `structNew->type` before `Struct2Local` runs. `StructNew` does not store its heap type separately from `type`, so `Struct2Local` depends on `structNew->type` remaining a concrete struct reference to look up the struct's fields when allocating locals and to construct the replacement `ref.null`.
@tlively
tlively requested a review from kripken November 11, 2026 01:58

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant