Skip to content

ci(vcr-oracle): CI-gate the RV32 immediate-shift-fold execution oracle (#472, #242)#489

Merged
avrabe merged 2 commits into
mainfrom
ci/rv32-shift-fold-oracle-472
Jun 25, 2026
Merged

ci(vcr-oracle): CI-gate the RV32 immediate-shift-fold execution oracle (#472, #242)#489
avrabe merged 2 commits into
mainfrom
ci/rv32-shift-fold-oracle-472

Conversation

@avrabe

@avrabe avrabe commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

What

CI-gates the RV32 immediate-shift-fold differential oracle. VCR-ORACLE-001's deliverable is CI-gating the differentials, not shipping them as dev-time scripts you have to remember to run.

The RV32 immediate-shift-fold lever (#487, landed flag-off behind SYNTH_RV_SHIFT_FOLD) came with a unicorn UC_ARCH_RISCV differential (shift_fold_riscv_differential.py) that only ran by hand. Because the lever sits flag-off awaiting the on-silicon flip, nothing else exercises the flag-on path — the exact gap the cmp-select two-move oracle was added to close for that lever.

How

Adds an isolated rv32-shift-fold-oracle CI job that mirrors the existing cmp-select-oracle job:

  • build synth, pip-install wasmtime/unicorn/pyelftools in that job only (the main cargo test gate is not taxed with the C-library build graph);
  • run the differential, which executes every fixture function in both flag states under unicorn and asserts bit-identical-to-wasmtime.

It continuously validates the slli/srli/srai folds, the & 31 mask on >=32 and negative shift amounts, and the variable-shift non-fold, plus non-vacuity (.text 168B→148B, 5 folds). The differential now honors a SYNTH env override (default release for local dev; CI points it at the debug build for speed, exactly like cmp-select).

Frozen-safe

No codegen change, no emitted-bytes change — this wires an already-written, already-passing oracle into CI. Verified locally with the exact CI invocation:

$ cargo build -p synth-cli
$ SYNTH=./target/debug/synth python scripts/repro/shift_fold_riscv_differential.py
.text 168B -> 148B (-20B): 5 const shift(s) folded
ORACLE: PASS

ci.yml parses (yaml.safe_load); the new job is well-formed.

Part of epic #242 (VCR-*), closing the CI-gate loop on the #472 lever-1 oracle.

🤖 Generated with Claude Code

#472, #242)

VCR-ORACLE-001's deliverable is CI-gating the differential oracles, not just
shipping them as dev-time scripts. The RV32 immediate-shift-fold lever (#487,
PR landed flag-off behind SYNTH_RV_SHIFT_FOLD) came with a unicorn UC_ARCH_RISCV
differential (shift_fold_riscv_differential.py) but it only ran by hand. Since
the lever sits flag-off awaiting the on-silicon flip, nothing else exercises the
flag-on path — exactly the gap the cmp-select two-move oracle was added to close.

Adds an isolated `rv32-shift-fold-oracle` CI job mirroring the existing
`cmp-select-oracle` job: build synth, pip-install wasmtime+unicorn+pyelftools in
that job ONLY (the main `cargo test` gate is not taxed with the C-library build
graph), and run the differential. It executes every fixture function in BOTH flag
states under unicorn and asserts bit-identical-to-wasmtime — continuously
validating the slli/srli/srai folds, the `& 31` mask on >=32 and negative shift
amounts, and the variable-shift non-fold, plus non-vacuity (.text 168B->148B, 5
folds). The differential now honors a SYNTH env override (default release for
local dev; CI points it at the debug build for speed, like cmp-select).

Frozen-safe: no codegen change, no emitted bytes change — wires an
already-written, already-passing oracle into CI. Verified locally with the exact
CI invocation (debug binary via SYNTH=./target/debug/synth): ORACLE PASS. ci.yml
parses; new job well-formed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@codecov

codecov Bot commented Jun 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

…h disasm` text

The CI oracle job failed with `SYMBOL MISSING` on the fresh runner while passing
locally: the harness scraped function addresses out of `synth disasm` stdout with
a regex, and that text is host-dependent (the disasm backend even decodes RISC-V
bytes with an ARM decoder, and on the bare runner the symbol-line format differs
so the regex matched nothing). Read the addresses straight from the ELF symbol
table via pyelftools instead — the same backend-independent approach
base_cse_differential.py uses. synth emits the symtab with an empty section name,
so it's found by sh_type (SHT_SYMTAB), and addresses are made .text-relative by
subtracting sh_addr. Re-verified with the exact CI invocation (debug binary via
SYNTH env): ORACLE PASS, 5 folds, all 6 functions matched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@avrabe avrabe merged commit b371731 into main Jun 25, 2026
12 checks passed
@avrabe avrabe deleted the ci/rv32-shift-fold-oracle-472 branch June 25, 2026 12:18
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