---
title: Compiling by Proving
url: https://www.emergentmind.com/topics/compiling-by-proving
type: topic
---

# Compiling by Proving

Compiling by proving is used, across multiple research traditions, for compilation workflows in which proofs are not an external afterthought but an internal artifact of compilation itself. In some settings the compiler is defined inside a theorem prover and extracted as executable code; in others, compilation is certified pass by pass by translation relations, secure-compilation theorems, or proof-producing toolchains; and in more recent work verification proofs themselves are compiled into optimized execution rules. The common thread is that compilation correctness, security, provenance, or optimization is obtained by construction from formal semantics, machine-checked proofs, or verifier-generated certificates rather than by testing alone [1707.06901] [1601.05520] [2509.21793].

## 1. Conceptual scope and motivation

The motivating problem is longstanding: compiler correctness is difficult, yet compiler errors invalidate higher-level guarantees. In foundational verification, the assurance can be strong because guarantees are checked by a small trusted kernel, but the proof cost is high. The CompCert verified C compiler took about 6 person-years and roughly 100,000 lines of Coq, and seL4 took 22 person-years to verify [1907.07794]. For smart contracts, the problem is sharpened by immutability and adversarial deployment: users must trust not only that a compiler is faithful, but also that the deployed low-level code actually corresponds to the claimed source [2201.04919].

The literature uses the phrase in several distinct but related ways. One sense is constructive verified compilation: define a compiler inside Isabelle/HOL or Coq, prove it sound against formal semantics, and extract or generate executable code. A second sense is certificate-producing compilation: compile a specific artifact while simultaneously generating a proof object, translation certificate, or cryptographic receipt. A third sense is proof-driven optimization: instead of discarding verification proofs, compile their structure into faster execution rules. A fourth sense concerns proof techniques for secure compilation, where contextual equivalence, robust safety preservation, or information-flow security are established by machine-checked theorems rather than informal argument [1707.06901] [2501.15002] [2509.21793].

A recurrent misconception is that all such work verifies a compiler implementation in the same way. The surveyed systems differ substantially. Some verify a compiler definition once and for all; some certify each compilation result; some prove secure-preservation theorems for a compiler pass; and some use proof assistants or zkVMs to attach evidence to individual compiled artifacts. Another important distinction is that a translation relation is not itself a correctness proof: it specifies admissible compiler behavior, and correctness comes from the additional theorem that related terms preserve meaning [2201.04919].

## 2. Constructive verified compilers in theorem provers

A central form of compiling by proving defines the compiler inside a proof assistant and proves it sound against formal source and target semantics. In "A Verified Compiler for Probability Density Functions" [1707.06901], the compiler is formalized in Isabelle/HOL for a probabilistic functional language modeled after Bhat et al.'s Fun language. The core judgment is \(Y \vdash e \Rightarrow f\), where \(Y = (V, V', T, \delta)\) is a density context and the output is a density function. The proof uses a two-step refinement: first an abstract compiler producing HOL functions is defined and proved sound; then it is refined to a concrete compiler returning target-language expressions. With Isabelle code generation for inductive predicates, this yields a fully verified, executable density compiler [1707.06901].

COGENT presents a related but broader architecture. It is a self-certifying compiler for a restricted, polymorphic, higher-order, and purely functional language with linear types, no trusted runtime, and no garbage collector. For a well-typed COGENT program, the compiler produces C code, a high-level shallow embedding of its semantics in Isabelle/HOL, and a proof that the C code correctly implements this embedding. The certificate is a series of language-level meta proofs and per-program translation validation phases, composed into one top-level theorem. A key formal move is the proof that update semantics refines value semantics, justified by the linear type system and its non-aliasing discipline for writable references [1601.05520].

Choreographic programming gives a third instance. "Certifying Choreography Compilation" [2102.10698] formalizes a choreographic source language and a target process calculus in Coq, together with endpoint projection and a proof of the EPP theorem. The source language is a global choreography; the target is a distributed network of local behaviors. Correctness requires formalizing merging for conditional branches, pruning via the preorder `more_branches`, and operational correspondence in both directions. The result is presented as the first certified program for choreography compilation for a nontrivial choreographic language supporting recursion [2102.10698].

| System | Formal setting | Resulting artifact |
|---|---|---|
| PDF density compiler [1707.06901] | Isabelle/HOL, abstract compiler then refinement | Fully verified, executable density compiler |
| COGENT [1601.05520] | Isabelle/HOL, refinement chain from source to C | C code, shallow embedding, and proof |
| Choreography compilation [2102.10698] | Coq, endpoint projection with EPP theorem | Certified compiler from choreographies to process networks |

These systems share a constructive pattern. Compilation is not justified post hoc by testing or by an external proof about an opaque implementation; rather, the executable compiler or compiled code is derived inside a formal development whose theorems explicitly connect source and target semantics.

## 3. Translation certificates, proof-producing pipelines, and provenance

A second family of approaches attaches proof artifacts to concrete compilation runs. "Translation Certification for Smart Contracts" [2201.04919] models a compiler as a sequence of pure functions \(f_i : AST_i \to AST_{i+1}\), together with an inductively defined translation relation \(R_i \subseteq AST_i \times AST_{i+1}\) for each pass. For actual compiler output \(t_{i+1} = f_i(t_i)\), the certifier attempts to construct a derivation of \(R_i(t_i, t_{i+1})\). A whole compilation certificate contains the chain of intermediate ASTs and proofs of \(R_1(t_1,t_2) \wedge \dots \wedge R_{n-1}(t_{n-1},t_n)\). Semantic preservation is then proved separately by the schema \(R_i(t_i,t_{i+1}) \implies \llbracket t_i \rrbracket_i \sim_i \llbracket t_{i+1} \rrbracket_{i+1}\). This modular architecture is intended to be robust under an evolving compiler implementation [2201.04919].

"A Proof-Producing Compiler for Blockchain Applications" [2501.15002] develops this idea for CairoZero. The tooling augments the CairoZero compiler so that it produces compiled machine code, a naive autogenerated specification of what the source code does, and a Lean 3 proof that the machine code satisfies that autogenerated specification. Users then prove stronger application-specific specifications from the autogenerated one. The key predicate is `ensures`, a partial-correctness notion over halting traces:
```lean
def ensures (mem : F → F) (σ : register_state F) (P : ℕ → register_state F → Prop) : Prop :=
  ∀ n : ℕ, ∀ exec : fin (n+1) → register_state F,
  is_halting_trace mem exec → exec 0 = σ →
  ∃ i : fin (n+1), ∃ κ ≤ i, P κ (exec i)
```
The case studies include secp256k1 and secp256r1 arithmetic, ECDSA public-key recovery, and `squash_dict`, showing that compiled Cairo machine code can be proved to satisfy high-level functional specifications in Lean 3 [2501.15002].

"Verifiable Provenance of Software Artifacts with Zero-Knowledge Compilation" [2602.11887] replaces proof-assistant certificates with cryptographic ones. The compiler is executed inside a zkVM, producing the compiled output together with a proof that the compilation was performed on the claimed source code with the claimed compiler. The protocol separates a compiler handshake, proof-producing compilation, and verification against the agreed `ImageID`. The resulting receipt contains the cryptographic proof, the SHA-256 digest of the input source code, and the compiled assembly output. In the prototype, median zk-compilation time for random programs was 78.91 s, compared with 0.0092 s for standard compilation, and verification median was 49.88 s; all adversarial tests targeting compiler substitution, source tampering, output manipulation, and replay attacks were successfully blocked [2602.11887].

These systems refine the meaning of provenance and correctness. A verified compiler addresses semantic faithfulness in general. Translation certification and proof-producing compilation additionally bind a specific low-level artifact to a specific source artifact. zk-compilation goes further by making that binding cryptographically portable, without requiring every verifier to reproduce the build. The underlying paper explicitly notes that the zero-knowledge property itself is not the main requirement; the essential property is a succinct proof of correct execution [2602.11887].

## 4. Proving secure and fully abstract compilation

Compiling by proving also names a class of proof techniques for compiler security. "Modular, Fully-abstract Compilation by Approximate Back-translation" [1703.09988] addresses full abstraction when the source language is too weak to encode the target language directly, as in compilation from STLC to ULC. The central theorem has the standard shape
\[
t_1 \simeq_{ctx}^S t_2 \iff \llbracket t_1 \rrbracket \simeq_{ctx}^T \llbracket t_2 \rrbracket.
\]
The key technical move is approximate back-translation: the source context need only be accurate up to \(n\) steps and conservative afterward. This is formalized with asymmetric, step-indexed cross-language logical relations and the finite family \(UVal_n\), where \(UVal_0 = Unit\) and \(UVal_{n+1}\) unfolds a universal value type to depth \(n\). The proof was fully mechanized in Coq and reported as the first fully mechanized proof of compiler full abstraction for a non-trivial compiler pass [1703.09988].

"SecurePtrs" [2110.01439] targets robust safety preservation for partial programs compiled from a structured-control-flow source language to an unstructured-control-flow target language, both with safe pointers, components, and dynamic memory sharing. Standard trace-directed back-translation becomes problematic when shared pointers can be stashed in private memory, because the trace omits the path by which the pointer is recovered. The proposed solution is data-flow traces, which enrich interaction traces with internal events such as `Const`, `Mov`, `BinOp`, `Load`, `Store`, and `Alloc`. A second innovation is turn-taking simulation, whose invariant changes depending on which side currently executes, allowing a recomposition lemma in the presence of shared mutable memory. The proof is mechanized in Coq, and the paper states that it is the first mechanization of such a recomposition lemma in the presence of memory sharing [2110.01439].

"Verifying that a compiler preserves concurrent value-dependent information-flow security" [1907.00713] studies a stronger security property: Concurrent Value-Dependent Noninterference for shared-memory concurrent programs with locking primitives. Prior secure-refinement notions were cube-shaped and substantially more complex than standard refinement. The paper introduces a decomposition principle that separates the proof into a paced square-shaped refinement argument and side conditions on stopping behavior, pacing consistency, and invariant closure. The authors state that this can almost halve the complexity of proving secure refinement, and the development proves in Isabelle/HOL that a While-to-RISC compiler preserves value-dependent security. The case study compiles a While-language model of the Cross Domain Desktop Compositor, giving what the paper describes as the first use of a compiler verification result to carry an information-flow security property down to the assembly-level model of a non-trivial concurrent program [1907.00713].

Across these results, security is not reduced to ordinary semantics preservation. Full abstraction constrains observational power at the target; robust safety preservation quantifies over arbitrary contexts; concurrent value-dependent security requires preservation of source-level confidentiality arguments under compilation and interleaving. The proof methods are correspondingly more intricate than standard compiler-correctness arguments.

## 5. Proofs as optimization artifacts

A more literal sense of compiling by proving appears when proof objects are themselves compiled into executable optimizations. "Compiling by Proving: Language-Agnostic Automatic Optimization from Formal Semantics" [2509.21793] uses symbolic execution in the K framework to construct All-Path Reachability Proofs,
\[
\Pi = (V, E_s, E_c, E_b),
\]
with vertices as constrained terms and step, cover, and branch edges. A step edge \((v_1, v_2, n)\) means that \(v_2\) is reached from \(v_1\) by exactly \(n\) deterministic rewrite steps. The compiler turns such edges into single optimized semantic rules of the form `rule v1.state => v2.state requires v1.constraints`. The method also applies step compression and branch lifting. On EVM opcode semantics, program specifications were successfully built for 131 of 149 opcodes, giving 87.9% coverage, an average reduction of 89.6% in rewriting steps, a geometric mean speedup of 2.189× on 2756 concrete tests, and 1.442× on 70 symbolic verification tasks. For a Rust MIR whole-program example, execution time dropped from 2438.26 seconds to 4.668 seconds, about 522× [2509.21793].

"Accelerating Verified-Compiler Development with a Verified Rewriting Engine" [2205.00862] moves proof-driven compilation into the compiler-construction workflow itself. The framework treats compilers as collections of algebraic rewrite rules, proved separately as ordinary Coq theorems, and assembles them into efficient compilers with proofs via a generic verified rewriting engine. The paper emphasizes a `Make rewriter := Rewriter For (...)` command that packages reified rewrite rules, a compiled decision tree, and soundness proofs into an extraction-ready compiler artifact. Applied to Fiat Cryptography, the extracted command-line compiler was about 1000× faster while featuring simpler compiler-specific proofs [2205.00862].

A more specialized variant appears in "Recursive Variational Quantum Compiling" [2203.08514]. Standard VQC requires coherent execution of the full target circuit during optimization, making deep noisy circuits hard to compile. RVQC instead decomposes \(U = U_N \cdots U_1\) and optimizes one stage at a time, with effective depth approximately bounded by
\[
2K + \frac{L}{N},
\]
rather than by the full target depth \(L+K\). The paper interprets this recursively justified procedure as a form of compiling by proving: each stage certifies the next compiled prefix relative to the previous one. Under an IBM Santiago noise model, standard VQC did not converge within 500 iterations on randomly generated five-qubit circuits of approximate depth 1000, while RVQC with \(N = 5\) converged to a fidelity of \(0.90 \pm 0.05\) within a total of 500 iterations [2203.08514].

These works shift proofs from a retrospective role to an operational one. In K, the proof graph becomes an optimized interpreter rule set. In Coq rewriting, proved equalities become the compiler. In RVQC, recursive local correctness obligations justify a compilation strategy whose noise behavior is analyzed mathematically.

## 6. Reducing the proof burden in proof-centric compilation ecosystems

The practical obstacle to compiling by proving is often not expressivity but proof effort. "Generating Correctness Proofs with Neural Networks" [1907.07794] addresses this directly with Proverbot9001, a proof-search system trained on existing Coq proofs and evaluated on proof obligations from CompCert. The system predicts proof commands from proof states, using a tactic predictor and an argument predictor combined by multiplying their scores without normalization. On the CompCert test set of 501 theorem statements, Proverbot9001 solved 97 proofs on its own, or 19.36%, and 138/501 when combined with CoqHammer; the paper reports this as nearly a 4× improvement over prior solver-free Coq proof-generation models and notes that the model reproduces the correct tactic name 32% of the time, while predicting the correct argument 89% of the time when the tactic name is correct [1907.07794].

"LEAN-GitHub: Compiling GitHub LEAN repositories for a versatile LEAN prover" [2407.17227] targets the data bottleneck behind theorem-prover automation. The dataset is extracted from Lean 4 repositories by compiling with `leanc` and extending prior tooling to handle isolated files and greater parallelism. The final dataset contains 28,597 theorems, 218,866 tactics, 2,133 files, and 0.131B tokens in the comparison table, with intermediate proof states preserved. Fine-tuning on LEAN-GitHub, Mathlib, and private synthetic data yields a prover that attains 48.8% pass@1 and 54.5% cumulative accuracy at 64 passes on the Lean 4 miniF2F test, along with state-of-the-art results on ProofNet and Putnam among the reported systems in that paper [2407.17227].

"Compile to Compress: Boosting Formal Theorem Provers by Compiler Outputs" [2604.18587] reframes verifier feedback as a compressed representation of proof failure. The Lean compiler maps many incorrect proof attempts into a compact set of structured failure modes, and the paper uses that structure in a learning-to-refine framework with Markovian refinement and tree search. Under a main test-time sampling budget of 64, the method improves both Kimina-Prover-Distill-8B and Goedel-Prover-V2-32B on MiniF2F, ProofNet, MathOlympiadBench, and PutnamBench. On PutnamBench, the paper reports 110 solved problems with a 32B model at budget 256 and 25 solved with an 8B model at budget 256, claiming state-of-the-art among publicly reported \(\sim 8B\) and \(\sim 32B\) models under comparable budgets [2604.18587].

These systems do not compile source programs into machine code. Their relevance is infrastructural: proof-heavy verified compilation and proof-producing compilation depend on theorem provers, proof search, and large formal corpora. Automating correctness proofs, extracting proof-state supervision, and using compiler outputs as compressed failure signals all reduce the cost of the proving side of compiling by proving. A plausible implication is that the scalability of certified compilation will increasingly depend not only on proof theory and semantics, but also on learned proof guidance and verifier-guided refinement.

Compiling by proving therefore names not a single method but a family of proof-centered compilation paradigms. In constructive verified compilers, the compiler is derived inside a theorem prover. In translation certification and proof-producing pipelines, each compiled artifact carries a checkable proof or receipt. In secure compilation, proof techniques establish preservation of contextual equivalence, robust safety, or information-flow security. In proof-driven optimization, verification proofs become executable semantics. And in the surrounding ecosystem, learned and verifier-guided systems attack the proof bottleneck that has historically limited the practical spread of high-assurance compilation.

Source: https://www.emergentmind.com/topics/compiling-by-proving