Skip to content

bugc: keep an inlined body's control flow inside the body - #356

Merged
gnidan merged 1 commit into
mainfrom
bugc-inline-membership
Oct 7, 2026
Merged

gnidan merged 1 commit into
mainfrom
bugc-inline-membership

Conversation

@gnidan

@gnidan gnidan commented Oct 7, 2026

Copy link
Copy Markdown
Member

At O2 and O3, the inliner marks each inlined instruction with transform: ["inline"], but not the body's terminators. A debugger counts the inline markers on each step to decide which virtual frames are still open, so at the first branch of an inlined if the frame closed, long before the body's return.

These parts of an inlined body did not have the marker:

  • the body's own terminators: an if's branch and the jumps between the body's blocks
  • the JUMPDEST at the entry of each of the body's blocks (its debug came only from the variables pass)
  • the jump that carries the return when the body's return block has no instruction to carry it (as when the returned value is a phi). That jump is the body's exit, as a real call's exit JUMP is the callee's. This is not the case that bugc: leave the jump past an inlined return out of the inlined body #347 took the marker off: there the return is on an instruction, and the jump after it is the caller's code
  • the empty block that splitPhiBranchEdges puts on a branch edge into a block with phis. It had an empty debug, so it also had no source range and no variables, at every level

The inliner now marks the body's terminators, and the jump that carries the return. A block's entry JUMPDEST gets one inline marker for each inlined body that its first operation is in, except for a body whose invoke that operation carries. An edge block takes its branch's context, without the branch's invoke or return, and also its inline sites and origin. The variables pass then lists the variables in scope there, as it does for the branch.

The new test in inline-bracket.test.ts runs a function with an if and a phi, inlined, on both paths at O2 and O3. It checks that each step from the invoke through the return has the marker and lists variables.

One known limit: the PUSH before the return-carrying jump still lists the caller's variables, because that jump keeps the caller's placement. A terminator has no returned debug that would split the variables between its operations, as an instruction has.

@gnidan
gnidan force-pushed the bugc-inline-membership branch from 7a13c7e to ba22dca Compare October 7, 2026 01:35
@github-actions

github-actions Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-10-07 02:03 UTC

@gnidan
gnidan merged commit 46585fd into main Oct 7, 2026
7 checks passed
@gnidan
gnidan deleted the bugc-inline-membership branch October 7, 2026 01:58
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.

1 participant