Add llvm_verify_fixpoint / llvm_verify_fixpoint_chc for LLVM-bitcode loop fixpoint proofs#3285
Open
AmeliaRose802 wants to merge 2 commits into
Open
Add llvm_verify_fixpoint / llvm_verify_fixpoint_chc for LLVM-bitcode loop fixpoint proofs#3285AmeliaRose802 wants to merge 2 commits into
AmeliaRose802 wants to merge 2 commits into
Conversation
added 2 commits
May 26, 2026 20:53
The Haskell implementations of `llvm_verify_fixpoint` and `llvm_verify_fixpoint_chc` have lived in `saw-central/src/SAWCentral/Crucible/LLVM/Builtins.hs` since the loop-fixpoint commit (9a0906b), but neither was ever registered as a `prim` entry in `saw-script/src/SAWScript/Interpreter.hs`. Only the `_x86` variants were exposed, so from a user's SAWScript these names resolved to "unbound variable" and the LLVM-bitcode fixpoint feature was unreachable. Changes: * `saw-script/src/SAWScript/Interpreter.hs`: Add `prim` entries for `llvm_verify_fixpoint` and `llvm_verify_fixpoint_chc` directly wrapping the SAWCentral functions via `pureVal` (no `do_*` wrapper needed -- the underlying functions already accept `Text` for the function name). * `examples/loop-fixpoint/loop_fixpoint_demo.saw`: Un-gate the demo; remove the "not yet implemented" comments and uncomment the three worked examples (`sum_upto` user-supplied fixpoint, `sum_upto` CHC, `zero_fill` memory-loop). * `doc/developer/loop-fixpoint-llvm-verify.md`: Flip status from "Proposed -- April 2026" to "Implemented (Phase 1) -- May 2026". * `intTests/test_llvm_loop_fixpoint/`: New binding-existence regression test that asserts both names resolve and have the documented type. Risk: minimal. The change is purely interpreter wiring; no `saw-central` code is modified. The exposed implementation already runs in production via the `_x86` variants, which share the same `Crucible.LLVM.SimpleLoopFixpoint(.simpleLoopFixpoint)` / `Crucible.LLVM.SimpleLoopFixpointCHC.simpleLoopFixpoint` machinery.
Contributor
|
For clarity, is this LLM-generated? It looks like it. It seems to have rather a lot of cutpaste as it is... |
Contributor
|
Thanks for the PR, @AmeliaRose802! I largely echo @sauclovian-g's sentiments here: this is something that would be nice to have, but I would want to make sure that we aren't blatantly duplicating large parts of |
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
Adds
llvm_verify_fixpointandllvm_verify_fixpoint_chc— the LLVM-bitcode counterparts of the existingllvm_verify_fixpoint_x86/llvm_verify_fixpoint_chc_x86primitives. They exposeLang.Crucible.LLVM.SimpleLoopFixpoint(.simpleLoopFixpoint)andLang.Crucible.LLVM.SimpleLoopFixpointCHC.simpleLoopFixpointfor LLVM-bitcode verification, removing the requirement to drop down to the x86 machine-code path (with its ELF-object detour) when a function contains a loop with a symbolic bound.Motivation
llvm_verifytoday can only handle loops with concrete bounds; users must either bound the loop in the spec or switch tollvm_verify_fixpoint_x86. The x86 path requires producing an ELF object, which is a significant detour on non-ELF targets (e.g. Windows /x86_64-pc-windows-msvc), and forces machine-code verification of optimized code — a heavier obligation than verifying the LLVM IR of the same function.Concrete motivating example: a length-prefixed canonicalizer with two byte-copy loops
for (uint8_t i = 0; i < nm; ++i) ...andfor (uint8_t i = 0; i < nb; ++i) .... Wall-clock numbers for boundedllvm_verifyagainst Z3 (otherwise identical script):MAX_LENThis is exactly the use case
SimpleLoopFixpointexists for.Changes
Two commits:
Add loop fixpoint support for llvm_verify— adds the SAWCentral plumbing:saw-central/src/SAWCentral/Crucible/LLVM/Builtins.hs:FixpointSelect = NoFixpoint | SimpleFixpoint TypedTerm | SimpleFixpointCHC TypedTermllvm_verify_fixpointandllvm_verify_fixpoint_chctop-level entry pointsverifyMethodSpecWithFixpointthreadingFixpointSelectintoverifySimulate, which constructs and installs the fixpoint execution feature viaCrucible.LLVM.Fixpoint.simpleLoopFixpoint/Crucible.LLVM.FixpointCHC.simpleLoopFixpointdoc/developer/loop-fixpoint-llvm-verify.md: design docexamples/loop-fixpoint/:simple_loop.cand demo.sawRegister llvm_verify_fixpoint{,_chc} as SAWScript primitives— wires the two functions into the interpreter:saw-script/src/SAWScript/Interpreter.hs: twoprimentries (Experimental) wrapping the SAWCentral functions directly viapureVal(nodo_*wrapper needed since the underlying functions already takeTextfor the function name)examples/loop-fixpoint/loop_fixpoint_demo.saw: un-gated (the three worked examples now compile and run)doc/developer/loop-fixpoint-llvm-verify.md: status flipped to Implemented (Phase 1). Phase 2 (SimpleInvariantfor LLVM bitcode) remains future work — it needs a different loop-identification mechanism (block labels rather than ELF symbol addresses) and is intentionally not exposed here.intTests/test_llvm_loop_fixpoint/: binding-existence regression testSAWScript types
The
Termargument is the loop's next-state function (or, for the CHC variant, an optional hint that Z3's constrained horn-clause engine can use to synthesize the loop invariant).Validation
cabal build sawclean.intTests/test_llvm_loop_fixpoint/smoke test (binding existence + type check)._x86tests untouched and continue to use the sameCrucible.LLVM.SimpleLoopFixpointmachinery.Risk
Low. The new primitives sit alongside the existing
_x86variants and call into the same crucible-llvm libraries those variants already exercise. MarkedExperimental.