Skip to content

bugc: fix -O2/-O3 codegen for call arguments and continuations - #388

Merged
gnidan merged 4 commits into
mainfrom
bugc-token-registry
Oct 15, 2026
Merged

gnidan merged 4 commits into
mainfrom
bugc-token-registry

Conversation

@gnidan

@gnidan gnidan commented Oct 15, 2026 •

Copy link
Copy Markdown
Member

examples/advanced/token-registry.bug compiled at -O0 and -O1 but failed at -O2 ("Cannot load value t107 - not in stack or memory") and, after that was fixed, at -O3 ("Jump target call_cont_14 not found"). Two optimizer steps forgot about call terminators:

  • Common subexpression elimination rewrote eliminated temps in instructions, phis, branch conditions and return values, but not in a call's arguments. A second msg.sender passed straight to a call was removed, and the call kept using the removed temp. The step now rewrites call arguments, too.
  • Return merging deleted an empty return block and redirected jumps and branches to the kept one, but left a call's continuation pointing at the deleted block. Redirecting the continuation would not be right either: evmgen enters a continuation only from its call, with the callee's return value on the stack. Continuation blocks now stay out of return merging, both as the block removed and as the block kept. This is also why the blog's arcade contract has failed at -O3 since bugc: string and bytes calldata parameters #383 (call play() -> call_cont_6, followed by a bare return;).

Each fix has a small regression test next to the step's other tests. The CSE test runs a program at -O2/-O3. The return-merging test runs at -O3 with the continuation before and after the other return;, and with a callee that returns a value or nothing. It checks that every call's continuation still exists and that no jump or branch enters it, and it runs both paths. All four cases fail on main. Of all the examples, only token-registry's bytecode changes (it now compiles at -O2 and -O3; the activation-pairing snapshot is updated for that). Its storage after a sequence of 18 calls is the same at every level.

The example keeps @wip: its dispatch never matches a selector, because bytes == bytes compares the two memory pointers, not the contents (let s: bytes = msg.data[0:4] vs. keccak256("pause()")[0:4] gives eq %t13, %t30 on the allocations). That is a separate irgen issue.

Closes #389

@github-actions

github-actions Bot commented Oct 15, 2026 •

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

@gnidan
gnidan merged commit 57044ae into main Oct 15, 2026
8 checks passed
@gnidan
gnidan deleted the bugc-token-registry branch October 15, 2026 02:14
gnidan added a commit that referenced this pull request Oct 15, 2026
Now that #388 and #391 are in, the example compiles and runs the same at O0-O3, so drop its @wip marker. Also note in constantBytes and foldCast that a string constant's bytes follow its type.
gnidan added a commit that referenced this pull request Oct 15, 2026
Now that #388 and #391 are in, the example compiles and runs the same at O0-O3, so drop its @wip marker. Also note in constantBytes and foldCast that a string constant's bytes follow its type.
gnidan added a commit that referenced this pull request Oct 15, 2026
Now that #388 and #391 are in, the example compiles and runs the same at O0-O3, so drop its @wip marker. Also note in constantBytes and foldCast that a string constant's bytes follow its type.
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.

bugc: jump target not found at -O 3 since #383

1 participant