feat(coq): i64 bit-manip T1 lifts (v0.9.0 PR 5 — final lift batch)#157
feat(coq): i64 bit-manip T1 lifts (v0.9.0 PR 5 — final lift batch)#157avrabe wants to merge 1 commit into
Conversation
Lifts the 3 i64 bit-manipulation T2 (existence-only) theorems in
CorrectnessI64.v to T1 (result-correspondence) using the
i64_{clz,ctz,popcnt}_bits_spec axioms shipped in v0.9.0 PR 1 (#153).
Each theorem is restated with:
- **I64-typed hypotheses**: operand pinned via lo/hi halves in (R0:R1).
The combined 64-bit operand is `combine_i32 lo hi`.
- **Single-register post-condition**:
`get_reg astate' R0 = i64_to_i32 (I64.<op> (combine_i32 lo hi))`
(clz/ctz/popcnt of an i64 fit in 32 bits, so the codegen produces
just R0; `i64_to_i32` captures the 32-bit return convention of the
pseudo-op).
- **No `exec_wasm_instr` hypothesis** (per the PR-1..PR-4 pattern —
the lifted theorems give a direct value-level correspondence to the
WASM-spec function `I64.{clz,ctz,popcnt}` without routing through
`exec_wasm_instr`).
| Theorem | Spec axiom | Outcome |
|-----------------------|-------------------------|---------|
| `i64_clz_correct` | `i64_clz_bits_spec` | Qed |
| `i64_ctz_correct` | `i64_ctz_bits_spec` | Qed |
| `i64_popcnt_correct` | `i64_popcnt_bits_spec` | Qed |
All three discharge via the mechanical
intros; unfold compile_wasm_to_arm; simpl; rewrite Hregs;
rewrite <op>_bits_spec; eexists; split;
[reflexivity | apply get_set_reg_eq]
template — same shape as `i64_eqz_correct` (#155) for the
single-register unary case. No new spec axioms, no new Admitted proofs.
## Net T1 count for clz/ctz/popcnt in CorrectnessI64.v
| Before (T2) | After (T1) |
|-------------|------------|
| 0 T1 / 3 T2 | 3 T1 / 0 T2 |
Project-wide Qed count is unchanged at 233 (the 3 existence Qeds
become 3 result-correspondence Qeds).
## v0.9.0 lift queue
This PR completes the v0.9.0 lift queue for the i64 op surface. With
this and the in-flight #156 (shifts/rotates), every i64 op in
CorrectnessI64.v and CorrectnessI64Comparisons.v is now T1
result-correspondence (modulo the 5 Admitted carry-/borrow-/halves-
distribute gaps documented in PR #154, which have explicit follow-up
plans against existing infrastructure — no new axioms needed).
## Bazel/Nix availability
Full `bazel test //coq:verify_proofs` is gated on `nix-build`, which
is not available on this dev host (`nix-build not found in PATH`).
Local `rocq`/`coqc` likewise unavailable. The proofs follow the exact
mechanical template proven by `i64_eqz_correct` (#155) and the div/rem
proofs already on `main`. CI on Linux (with the Nix-provisioned Rocq
toolchain) will verify.
Refs: #152 (umbrella), #153 (precursor spec axioms — used),
#154 (v0.9.0 PR 2 arith+bitwise pattern),
#155 (v0.9.0 PR 4 comparison pattern — single-register unary
template via `i64_eqz_correct`)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Automated review for PR #157pulseengine/synth: Verdict: 💬 Comment Summary: The patch is a significant update to the Wasm interpreter in Coq, particularly focusing on the implementation of bit manipulation operations (Clz, Ctz, Popcnt) for the I64 type. The changes include restating these operations with I64-typed hypotheses and a single-register post-condition, which aligns with the pattern observed in previous PRs. The code is well-documented and follows Coq's style and Findings: 0 mechanical (rivet) · 1 from local AI model. Findings (1):
Generated by a local AI model and post-validated against a strict JSON contract. Each finding includes the verbatim line being criticised — verify by reading the file at the cited location. Reviewed at |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Summary
Lifts the 3 i64 bit-manipulation T2 (existence-only) theorems in
coq/Synth/Synth/CorrectnessI64.vto T1 (result-correspondence) using thei64_{clz,ctz,popcnt}_bits_specaxioms shipped in v0.9.0 PR 1 (#153).Refs umbrella #152. The original falsification was:
i64 bit-manipulation proofs use `solve_single_arm` existence — they assert only that the ARM program returns `Some _`, not that R0 holds the right count. This PR closes that gap for clz/ctz/popcnt by replacing the existence-only statements (with a vacuous-thenVI64 I64.zeropost-stack placeholder) with single-register value-level correspondence and discharging via the spec axioms.Per-theorem outcome
i64_clz_correcti64_clz_bits_speci64_ctz_correcti64_ctz_bits_speci64_popcnt_correcti64_popcnt_bits_specAll three discharge via the mechanical
intros; unfold compile_wasm_to_arm; simpl; rewrite Hregs; rewrite <op>_bits_spec; eexists; split; [reflexivity | apply get_set_reg_eq]template — same shape asi64_eqz_correct(#155) for the single-register unary case. No new spec axioms, no new Admitted proofs.Theorem shape (new T1)
Theorem i64_clz_correct : forall astate lo hi, get_reg astate R0 = lo -> get_reg astate R1 = hi -> exists astate', exec_program (compile_wasm_to_arm I64Clz) astate = Some astate' /\ get_reg astate' R0 = i64_to_i32 (I64.clz (combine_i32 lo hi)).Compilation.v(I64{Clz,Ctz,Popcnt}Pseudo R0 R0 R1: rd=R0, rnlo=R0, rnhi=R1).i64_to_i32truncates the 64-bit count to its low 32 bits (always lossless because the count is bounded by 64 — seeI64.{clz,ctz,popcnt}_rangeaxioms in Integers.v). This cast captures the 32-bit return convention of the pseudo-op (clz/ctz/popcnt of an i64 fit in 32 bits, so the codegen produces just R0).Net T1 count for clz/ctz/popcnt in
CorrectnessI64.vProject-wide Qed count is unchanged at 233 (the 3 existence Qeds become 3 result-correspondence Qeds).
v0.9.0 lift queue: complete
This PR is the final lift batch of the v0.9.0 milestone. With this and #156 (shifts/rotates, in flight), every i64 op in
CorrectnessI64.vandCorrectnessI64Comparisons.vis now T1 result-correspondence, modulo the 5 Admitted gaps (Add/Sub/And/Or/Xor) documented in PR #154 with explicit follow-up plans against existing infrastructure — no new axioms needed for any of them.WasmSemantics findings
WasmSemantics.vdoes model i64 clz/ctz/popcnt (lines 458-481, pushingVI64 (I64.<op> v)afterpop_i64). Despite this, the new T1 shape drops theexec_wasm_instrhypothesis — matching every prior v0.9.0 PR (#153/#154/#155/#156). The new theorem gives a direct value-level correspondence between the WASM-spec functionI64.{clz,ctz,popcnt}and the ARM execution result; the WasmSemantics plumbing is a redundant layer over an equivalent value-level statement.One sound architectural note: WasmSemantics pushes the result as a
VI64, whereas the actual WASM spec (and the ARM codegen) yields an i32. Thei64_to_i32cast in our spec axioms captures the spec/codegen behavior; the WasmSemantics modeling choice is independent of the proved property.Bazel/Nix availability
Full
bazel test //coq:verify_proofsis gated onnix-build, which is not available on this dev host (analysis fails:nix-build not found in PATH). Localrocq/coqclikewise unavailable. The proofs follow the exact mechanical template proven byi64_eqz_correct(#155) and the div/rem proofs already onmain. CI on Linux (with the Nix-provisioned Rocq toolchain) will verify.Test plan
//coq:verify_proofspasses on Linux (Nix Rocq 9 toolchain) — all 3 lifted theorems discharge via the_specaxioms.Axiomdeclarations introduced —git diff origin/main -- coq/Synth/ARM/ArmSemantics.vis empty (onlyCorrectnessI64.vchanged).Admittedproofs —grep Admitted coq/Synth/Synth/CorrectnessI64.vcount unchanged at 5 (Add/Sub/And/Or/Xor).exec_wasm_instrhypothesis.Refs: #152 (umbrella), #153 (precursor spec axioms — used), #154 (v0.9.0 PR 2 arith+bitwise pattern), #155 (v0.9.0 PR 4 single-register unary template via
i64_eqz_correct), #156 (v0.9.0 PR 3 shifts/rotates — parallel/independent).Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>