feat(#851): aarch64 full control flow — if/else, loop, return#857
Open
avrabe wants to merge 5 commits into
Open
feat(#851): aarch64 full control flow — if/else, loop, return#857avrabe wants to merge 5 commits into
avrabe wants to merge 5 commits into
Conversation
if/else, loop back-edge, return execution differential — native arm64 (MAP_JIT fork) + unicorn vs wasmtime. RED before lowering: all 7 functions decline (If unsupported, loop declined by name). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
Extends the void-block-only #538 control flow (block/br/br_if) with: - if/else: kind-tagged frame; cbz cond -> else/end, unconditional b over the else arm, join at end. Void (0,0) only — value-if loud-declines. - loop: backward-branch target; br/br_if to a loop frame resolves a NEGATIVE offset eagerly (loop header known at push). Void (0,0) only. - return: early epilogue (funnel top -> x0/d0, restore SP, ret). Branch dispatch is on the TARGET frame's kind (Block/If = forward pending, patched at End; Loop = backward, resolved now), so loop back-edges and forward block exits coexist. patch_branch() centralizes b/cbnz/cbz re-encode so the new cbz can't be mis-patched as cbnz. Reachability flag: code after br/return/unreachable is stack-polymorphic (WASM); truncate the value stack unconditionally but gate the fall-through height debug_assert on reachability. block_arity ordinal now consumed by Loop and If (one entry each), keeping the arity-table lookup aligned. br_table still loud-declines (catch-all). Execution gate: aarch64_ctrlflow_851_differential.py — 25 cases, both branch edges + loop trip counts, native arm64 (MAP_JIT fork) + unicorn vs wasmtime, all GREEN (was RED: all 7 fns declined). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
Backend unit tests for the new lowerings: void-if cbz skip, void-if/else both-edge patch, loop back-edge negative offset, early-return epilogue. Update the old decline test to br_table-and-typed-loop/if only (loop/if now lowered for the void shape). Fix the countdown fixture to copy the param into a non-param local (param writes loud-decline). 70/70 backend tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
Address advisor tightening: - check_imm26/check_imm19 guard every branch displacement (eager backward Br/BrIf-to-loop + patched forward b/cbz/cbnz) against the A64 field width; over-range LOUD-DECLINES instead of wrapping silently (No silent miscompile). patch_branch is now fallible and propagated at all three call sites. - do_while_count fixture: br_if BACK to the loop header exercises the backward CONDITIONAL branch (cbnz-to-header) that br 0 + br_if 1 loops never hit. Differential now 28 cases, all GREEN. fmt clean, workspace clippy -D warnings clean, 70/70 backend tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Extends the
-b aarch64backend's void-block-only #538 control flow(
block/br/br_if) with the remaining structured constructs, part of laneL4 of the v0.51 hub. Closes the last major control-flow gap for the host-native
integer subset (#851).
Lowered (all execution-verified bit-identical vs wasmtime):
if/else—cbzcond → else/end, unconditionalbover the else arm,join at end (void
(0,0)only).loop— backward branch target: abr/br_ifto a loop frame resolves anegative offset eagerly at the loop header (void
(0,0)only).return— early epilogue (funnel top →x0/d0, restore SP,ret).Design
enum Kind { Block, Loop { entry }, If { else_fixup } }.Branch resolution dispatches on the target frame's kind — Block/If are
forward (recorded in
pending, patched atEnd), Loop is backward (resolvedon emission). This is what lets loop back-edges and forward block exits coexist.
patch_branchhelper centralizes theb/cbnz/cbzre-encode so the newcbzcan't be mis-patched as acbnz; it is fallible and range-checks everydisplacement.
br/return/unreachable: the value stack is truncated unconditionally(fixes the model) but the fall-through height
debug_assertis gated onreachability.
block_arityordinal is now consumed byLoopandIf(one entry each),keeping the arity-table lookup aligned.
check_imm26/check_imm19): displacements exceeding the A64field width LOUD-DECLINE rather than wrap silently.
Honest frontier (loud-decline, never silent)
if/loop(arity ≠(0,0)— both arms would need the resultin one register / the value stack live across the back-edge).
br_table(catch-all).Gate — RED-first execution differential
scripts/repro/aarch64_ctrlflow_851_differential.py(28 cases), native arm64(MAP_JIT fork) + unicorn vs wasmtime:
Ifunsupported,loopdeclined by name).do-while loops (the do-while drives the backward conditional
cbnz-to-headerpath), early-return, return-inside-loop. Both branch edges + a trap edge
exercised; non-vacuity-guarded (every function + both edges must run).
Verification
back-edge negative offset, early-return epilogue).
scripts/repro/aarch64_matrix.shPASS (32 ops accepted, 86 native checks).aarch64_cf_538/locals_851/mem_851differentials still GREEN.frozen_codegen_bytes10/10 untouched.cargo fmt --check+cargo clippy --workspace --all-targets -D warningsclean.Coordinator note
The new differential needs wiring into
.github/workflows/ci.ymlalongsideaarch64_cf_538_differential.py/aarch64_mem_851_differential.pyat assembly(this lane does not edit repo config).
🤖 Generated with Claude Code
https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L