Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
128a6cb
verify: Replay a Lean project into one kernel environment, importing …
SwayamInSync Oct 23, 2026
62cac8d
test: Add a program whose first goal sorts before the other function'…
SwayamInSync Oct 23, 2026
9d85f6e
test: Add a proof of the first goal that defines a goal of its own un…
SwayamInSync Oct 23, 2026
fe6fc92
test: Expect a proof file that redeclares its goal to be the module l…
SwayamInSync Oct 23, 2026
f716cd7
test: Add a wrapper that bounds the peak memory of the processes a co…
SwayamInSync Oct 23, 2026
a9098e0
test: Bound the Lean checker's memory where a proof imports Lean thro…
SwayamInSync Oct 23, 2026
f814f9f
docs: Say that certification imports the toolchain once and rejects a…
SwayamInSync Oct 23, 2026
ed50d74
docs: Say in the release notes that the checker replays into one envi…
SwayamInSync Oct 23, 2026
e918963
docs: Describe the checker's single kernel environment in the design.
SwayamInSync Oct 23, 2026
c55de5b
docs: Describe the checker's single kernel environment and its memory…
SwayamInSync Oct 23, 2026
51a9a6a
verify: Declare a Lean project's generated modules and the prelude's …
SwayamInSync Oct 23, 2026
34ef6d0
verify: Emit a project's spec declarations apart from its goals, and …
SwayamInSync Oct 23, 2026
cdcaec5
verify: Let the Lean backend write the modules of a project.
SwayamInSync Oct 23, 2026
505cf15
verify: Write each function's Lean goals to its module and the specs …
SwayamInSync Oct 23, 2026
86e4a9d
verify: Import only the prelude in the module of cppverify_auto.
SwayamInSync Oct 23, 2026
c23e58c
verify: Check each goal against its own module, and fail every goal w…
SwayamInSync Oct 23, 2026
2ef7e14
verify: Give each function's Lean goals a module, and compile a proof…
SwayamInSync Oct 23, 2026
da1845a
test: Add a helper that prints a Lean project's generated text in imp…
SwayamInSync Oct 23, 2026
548094c
test: Read a Lean project's goals from its modules in the fidelity gate.
SwayamInSync Oct 23, 2026
2c9de79
test: Add the five functions of the Lean modules test.
SwayamInSync Oct 23, 2026
28af37d
test: Add the proof of tri_zero's postcondition for the Lean modules …
SwayamInSync Oct 23, 2026
901c3ca
test: Add the proof of plus_tri_zero's postcondition for the Lean mod…
SwayamInSync Oct 23, 2026
adf19a3
test: Check the module of each function's Lean goals and incremental …
SwayamInSync Oct 23, 2026
0350c69
test: Expect the goal module among the imports of an automatic proof.
SwayamInSync Oct 23, 2026
56a9fb0
test: Expect the goal module in the message for a shadowed goal.
SwayamInSync Oct 23, 2026
9f9fbb2
test: Expect an admitted User lemma to fail every goal through the ch…
SwayamInSync Oct 23, 2026
e261a4d
test: Read the fallback project's generated text from its modules.
SwayamInSync Oct 23, 2026
4cbeefd
test: Find spec bodies in their goal module and the goal module in a …
SwayamInSync Oct 23, 2026
accb2c9
test: Read the Lean projects' generated text from their modules.
SwayamInSync Oct 23, 2026
66be53e
test: Read the Lean project's generated text from its modules.
SwayamInSync Oct 23, 2026
97f3776
test: Read and edit the readable goals in their function's module.
SwayamInSync Oct 23, 2026
6ae6209
test: Read the exported Lean semantics from the project's modules.
SwayamInSync Oct 23, 2026
7e119a1
test: Expect the trial of cppverify_auto to build the goal modules too.
SwayamInSync Oct 23, 2026
71ce0e1
docs: Explain the module of each function's Lean goals and incrementa…
SwayamInSync Oct 23, 2026
e406b75
docs: Describe the modules of a Lean project in the tooling reference.
SwayamInSync Oct 23, 2026
0c43c5c
docs: Note the Lean module per function in the release notes.
SwayamInSync Oct 23, 2026
f2558ec
docs: Describe a Lean project's modules in the design.
SwayamInSync Oct 23, 2026
a989960
docs: Describe a Lean project's modules and proof keys in the archite…
SwayamInSync Oct 23, 2026
f178db1
test: Import its function's goal module in the proof cppverify_fine_5…
SwayamInSync Oct 23, 2026
b138c4b
test: Import its function's goal module in the proof cppverify_fine_5…
SwayamInSync Oct 23, 2026
1bf5460
test: Import its function's goal module in the proof cppverify_one_99…
SwayamInSync Oct 23, 2026
77bdebb
test: Import its function's goal module in the proof cppverify_one_99…
SwayamInSync Oct 23, 2026
e0d4296
test: Import its function's goal module in the proof Lemmas.lean.
SwayamInSync Oct 23, 2026
98d82b0
test: Import its function's goal module in the proof cppverify_one_99…
SwayamInSync Oct 23, 2026
71886e0
test: Import its function's goal module in the proof cppverify_one_99…
SwayamInSync Oct 23, 2026
aaf0ec7
test: Import its function's goal module in the proof lean_dependencie…
SwayamInSync Oct 23, 2026
910acbe
test: Import its function's goal module in the proof lean_dependencie…
SwayamInSync Oct 23, 2026
69d1177
test: Import its function's goal module in the proof lean_dependencie…
SwayamInSync Oct 23, 2026
6ce1435
test: Import its function's goal module in the proof lean_dependencie…
SwayamInSync Oct 23, 2026
d69832d
test: Import its function's goal module in the proof lean_dependencie…
SwayamInSync Oct 23, 2026
1d6af47
test: Import its function's goal module in the proof lean_dependencie…
SwayamInSync Oct 23, 2026
fad7045
test: Import its function's goal module in the proof lean_dependencie…
SwayamInSync Oct 23, 2026
49a0e1f
test: Import its function's goal module in the proof lean_dependencie…
SwayamInSync Oct 23, 2026
23e010b
test: Import its function's goal module in the proof lean_fallback_go…
SwayamInSync Oct 23, 2026
64c6570
test: Import its function's goal module in the proof lean_fallback_go…
SwayamInSync Oct 23, 2026
cc18009
test: Import its function's goal module in the proof lean_fallback_go…
SwayamInSync Oct 23, 2026
ce46518
test: Import its function's goal module in the proof lean_fallback_go…
SwayamInSync Oct 23, 2026
8d1523b
test: Import its function's goal module in the proof lean_fallback_pa…
SwayamInSync Oct 23, 2026
df33419
test: Import its function's goal module in the proof lean_fallback_pa…
SwayamInSync Oct 23, 2026
2f1a006
test: Import its function's goal module in the proof cppverify_bump_c…
SwayamInSync Oct 23, 2026
5daf121
test: Import its function's goal module in the proof cppverify_one_99…
SwayamInSync Oct 23, 2026
16a8c93
test: Import its function's goal module in the proof cppverify_one_99…
SwayamInSync Oct 23, 2026
6be02b0
test: Import its function's goal module in the proof cppverify_one_99…
SwayamInSync Oct 23, 2026
ca6c465
test: Import its function's goal module in the proof cppverify_one_99…
SwayamInSync Oct 23, 2026
7b861cb
test: Import its function's goal module in the proof cppverify_six_6a…
SwayamInSync Oct 23, 2026
5eedfdf
test: Import its function's goal module in the proof cppverify_six_6a…
SwayamInSync Oct 23, 2026
c318e4c
test: Import its function's goal module in the proof cppverify_tri_de…
SwayamInSync Oct 23, 2026
201ea08
test: Import its function's goal module in the proof cppverify_twice_…
SwayamInSync Oct 23, 2026
9bacf87
test: Import its function's goal module in the proof cppverify_twice_…
SwayamInSync Oct 23, 2026
451f38f
test: Import its function's goal module in the proof cppverify_twice_…
SwayamInSync Oct 23, 2026
05003b5
test: Import its function's goal module in the proof cppverify_twice_…
SwayamInSync Oct 23, 2026
93b75ad
test: Import its function's goal module in the proof lean_semantics_c…
SwayamInSync Oct 23, 2026
d49e8f9
test: Import its function's goal module in the proof lean_semantics_m…
SwayamInSync Oct 23, 2026
1136d88
test: Import its function's goal module in the proof lean_semantics_n…
SwayamInSync Oct 23, 2026
9359c25
test: Import its function's goal module in the proof cppverify_readin…
SwayamInSync Oct 23, 2026
cf3fc2c
test: Import its function's goal module in the proof cppverify_readin…
SwayamInSync Oct 23, 2026
1e8a0a1
test: Import its function's goal module in the proof cppverify_readin…
SwayamInSync Oct 23, 2026
4eb310f
test: Import its function's goal module in the proof cppverify_readin…
SwayamInSync Oct 23, 2026
9b346cc
test: Import its function's goal module in the proof cppverify_readin…
SwayamInSync Oct 23, 2026
04706a9
test: Import its function's goal module in the proof cppverify_sensor…
SwayamInSync Oct 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 55 additions & 47 deletions clang/lib/Verify/Backend/LeanBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1087,12 +1087,63 @@ static void emitLeanFunctionBodies(const ObligationModule &Module,
}
}

// The definitions every exported goal is stated with: the heap model, the
// machine comparisons, and C++ division; a project's goals also have the
// lemmas their readable forms' bridges use.
void verify::emitLeanPrelude(llvm::raw_ostream &OS, bool Project) {
OS << "noncomputable section\n\n";
OS << "set_option maxRecDepth 100000\n";
OS << "set_option maxHeartbeats 0\n\n";
OS << "local instance cppVerifyPropDecidable (p : Prop) : Decidable p :=\n";
OS << " Classical.propDecidable p\n\n";
OS << "abbrev CppHeap := Int -> Int\n\n";
OS << "def heapSelectInt (h : CppHeap) (p : Int) : Int := h p\n";
OS << "abbrev heapSelectBool (h : CppHeap) (p : Int) : Prop := h p ≠ 0\n";
OS << "def heapSelectBv (w : Nat) (h : CppHeap) (p : Int) : BitVec w :=\n";
OS << " BitVec.ofInt w (h p)\n\n";
OS << "def heapStoreInt (h : CppHeap) (p v : Int) (h' : CppHeap) : "
"Prop :=\n";
OS << " h' = fun q => if q = p then v else h q\n";
OS << "def heapStoreBool (h : CppHeap) (p : Int) (v : Prop)\n";
OS << " (h' : CppHeap) : Prop :=\n";
OS << " h' = fun q => if q = p then\n";
OS << " @ite Int v (Classical.propDecidable v) 1 0 else h q\n";
OS << "def heapStoreBv {w : Nat} (h : CppHeap) (p : Int) (v : BitVec w)\n";
OS << " (h' : CppHeap) : Prop :=\n";
OS << " h' = fun q => if q = p then Int.ofNat v.toNat else h q\n\n";
OS << "opaque validPtr : Int -> Prop\n\n";
// Reducible, so instance search sees the Bool comparison and decides it.
OS << "abbrev cppBvUlt {w : Nat} (x y : BitVec w) : Prop := x.ult y = "
"true\n";
OS << "abbrev cppBvUle {w : Nat} (x y : BitVec w) : Prop := x.ule y = "
"true\n";
OS << "abbrev cppBvSlt {w : Nat} (x y : BitVec w) : Prop := x.slt y = "
"true\n";
OS << "abbrev cppBvSle {w : Nat} (x y : BitVec w) : Prop := x.sle y = "
"true\n\n";
OS << "def cppIntDiv (x y : Int) : Int :=\n";
OS << " if y = 0 then 0 else\n";
OS << " let q := (if x < 0 then -x else x) / "
"(if y < 0 then -y else y)\n";
OS << " if (x < 0) ≠ (y < 0) then -q else q\n";
OS << "def cppIntRem (x y : Int) : Int :=\n";
OS << " if y = 0 then x else x - cppIntDiv x y * y\n\n";
if (Project) {
// What the bridges from readable goals use.
OS << "theorem cppverify_imp_or {a b : Prop} (h : a → b) : ¬a ∨ b :=\n";
OS << " (Classical.em a).elim (fun ha => Or.inr (h ha)) Or.inl\n";
OS << "theorem cppverify_not_imp_or {a b : Prop} (h : ¬a → b) : a ∨ b "
":=\n";
OS << " (Classical.em a).elim Or.inl (fun ha => Or.inr (h ha))\n\n";
}
}

VerifyResult verify::exportLeanScratchPad(
const ObligationModule &Module, llvm::raw_ostream &OS, bool EmitPreamble,
std::set<std::string> &EmittedFunctions,
std::set<std::string> &EmittedTheorems, unsigned ModuleIndex,
std::vector<LeanProjectGoal> *ProjectGoals,
const std::set<std::string> *Selection) {
const std::set<std::string> *Selection, llvm::raw_ostream *Declarations) {
VerifyResult Result;
if (!Module.CorrectnessGoal || !Module.CounterexampleQuery) {
Result.Status = VerifyStatus::Unresolved;
Expand Down Expand Up @@ -1130,54 +1181,11 @@ VerifyResult verify::exportLeanScratchPad(
OS << " This file exports canonical obligations but does not certify "
"them. -/\n\n";
}
OS << "noncomputable section\n\n";
OS << "set_option maxRecDepth 100000\n";
OS << "set_option maxHeartbeats 0\n\n";
OS << "local instance cppVerifyPropDecidable (p : Prop) : Decidable p :=\n";
OS << " Classical.propDecidable p\n\n";
OS << "abbrev CppHeap := Int -> Int\n\n";
OS << "def heapSelectInt (h : CppHeap) (p : Int) : Int := h p\n";
OS << "abbrev heapSelectBool (h : CppHeap) (p : Int) : Prop := h p ≠ 0\n";
OS << "def heapSelectBv (w : Nat) (h : CppHeap) (p : Int) : BitVec w :=\n";
OS << " BitVec.ofInt w (h p)\n\n";
OS << "def heapStoreInt (h : CppHeap) (p v : Int) (h' : CppHeap) : "
"Prop :=\n";
OS << " h' = fun q => if q = p then v else h q\n";
OS << "def heapStoreBool (h : CppHeap) (p : Int) (v : Prop)\n";
OS << " (h' : CppHeap) : Prop :=\n";
OS << " h' = fun q => if q = p then\n";
OS << " @ite Int v (Classical.propDecidable v) 1 0 else h q\n";
OS << "def heapStoreBv {w : Nat} (h : CppHeap) (p : Int) (v : BitVec w)\n";
OS << " (h' : CppHeap) : Prop :=\n";
OS << " h' = fun q => if q = p then Int.ofNat v.toNat else h q\n\n";
OS << "opaque validPtr : Int -> Prop\n\n";
// Reducible, so instance search sees the Bool comparison and decides it.
OS << "abbrev cppBvUlt {w : Nat} (x y : BitVec w) : Prop := x.ult y = "
"true\n";
OS << "abbrev cppBvUle {w : Nat} (x y : BitVec w) : Prop := x.ule y = "
"true\n";
OS << "abbrev cppBvSlt {w : Nat} (x y : BitVec w) : Prop := x.slt y = "
"true\n";
OS << "abbrev cppBvSle {w : Nat} (x y : BitVec w) : Prop := x.sle y = "
"true\n\n";
OS << "def cppIntDiv (x y : Int) : Int :=\n";
OS << " if y = 0 then 0 else\n";
OS << " let q := (if x < 0 then -x else x) / "
"(if y < 0 then -y else y)\n";
OS << " if (x < 0) ≠ (y < 0) then -q else q\n";
OS << "def cppIntRem (x y : Int) : Int :=\n";
OS << " if y = 0 then x else x - cppIntDiv x y * y\n\n";
if (ProjectGoals) {
// What the bridges from readable goals use.
OS << "theorem cppverify_imp_or {a b : Prop} (h : a → b) : ¬a ∨ b :=\n";
OS << " (Classical.em a).elim (fun ha => Or.inr (h ha)) Or.inl\n";
OS << "theorem cppverify_not_imp_or {a b : Prop} (h : ¬a → b) : a ∨ b "
":=\n";
OS << " (Classical.em a).elim Or.inl (fun ha => Or.inr (h ha))\n\n";
}
emitLeanPrelude(OS, ProjectGoals != nullptr);
}

emitLeanFunctionDeclarations(Module, OS, EmittedFunctions);
emitLeanFunctionDeclarations(Module, Declarations ? *Declarations : OS,
EmittedFunctions);
emitLeanFunctionBodies(Module, OS);
OS << "/- function: ";
printLeanCommentText(Module.FunctionName, OS);
Expand Down
28 changes: 25 additions & 3 deletions clang/lib/Verify/Backend/LeanBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

#include "VerifyBackend.h"
#include "llvm/Support/raw_ostream.h"
#include <map>
#include <optional>
#include <set>
#include <string>
#include <vector>

namespace clang {
Expand Down Expand Up @@ -38,21 +40,37 @@ struct LeanProjectGoal {
/// The group of a module's goals in a project: its function's directory.
std::string leanProjectGroup(const ObligationModule &Module);

/// The generated modules of a Lean project: the declarations of the specs
/// its goals apply, which every goal module imports, and each group's spec
/// definitions and goals.
struct LeanProjectModules {
std::string Specs;
std::map<std::string, std::string> Goals;
/// The groups in the order their functions were exported: the source's.
std::vector<std::string> Order;
};

/// The definitions every exported goal is stated with.
void emitLeanPrelude(llvm::raw_ostream &OS, bool Project);

/// Selection names the internal IDs to export; a project goal is named by
/// its function and semantic hash, so it keeps its name whatever else is
/// exported, and a scratch-pad goal keeps the positional name it has when
/// every obligation is exported. A project records every goal of the module,
/// the ones left out as not exported.
/// the ones left out as not exported. Declarations, when given, receives
/// the declarations of the specs, each once.
VerifyResult
exportLeanScratchPad(const ObligationModule &Module, llvm::raw_ostream &OS,
bool EmitPreamble, std::set<std::string> &EmittedFunctions,
std::set<std::string> &EmittedTheorems,
unsigned ModuleIndex,
std::vector<LeanProjectGoal> *ProjectGoals,
const std::set<std::string> *Selection = nullptr);
const std::set<std::string> *Selection = nullptr,
llvm::raw_ostream *Declarations = nullptr);

class LeanVerifyBackend : public VerifyBackend {
llvm::raw_ostream *Out;
llvm::raw_ostream *Out = nullptr;
LeanProjectModules *Modules = nullptr;
bool PreambleEmitted = false;
std::set<std::string> EmittedFunctions;
std::set<std::string> EmittedTheorems;
Expand All @@ -64,6 +82,10 @@ class LeanVerifyBackend : public VerifyBackend {
LeanVerifyBackend(llvm::raw_ostream *OS,
std::vector<LeanProjectGoal> *ProjectGoals)
: Out(OS), ProjectGoals(ProjectGoals) {}
/// A project's export, into its modules.
LeanVerifyBackend(LeanProjectModules *Modules,
std::vector<LeanProjectGoal> *ProjectGoals)
: Modules(Modules), ProjectGoals(ProjectGoals) {}
llvm::StringRef getName() const override { return "lean"; }
BackendCapabilities getCapabilities() const override {
// Collections have no Lean semantics yet.
Expand Down
30 changes: 24 additions & 6 deletions clang/lib/Verify/Backend/VerifyBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,32 @@ using namespace verify;

VerifyResult LeanVerifyBackend::verifyModule(const ObligationModule &Module) {
VerifyResult R;
if (!Out) {
if (!Out && !Modules) {
R.Status = VerifyStatus::Unresolved;
R.Reason = VerifyReason::LeanExportFailure;
R.Message = "no lean output stream";
return R;
}
const size_t Before = ProjectGoals ? ProjectGoals->size() : 0;
VerifyResult Result = exportLeanScratchPad(
Module, *Out, !PreambleEmitted, EmittedFunctions, EmittedTheorems,
++ModuleIndex, ProjectGoals, Selection ? &*Selection : nullptr);
PreambleEmitted = true;
VerifyResult Result;
if (Modules) {
// A project's goals go to their function's module, and the specs they
// apply are declared once, in the module every goal module imports.
const std::string Group = leanProjectGroup(Module);
if (!Modules->Goals.count(Group))
Modules->Order.push_back(Group);
llvm::raw_string_ostream Goals(Modules->Goals[Group]);
llvm::raw_string_ostream Specs(Modules->Specs);
Result = exportLeanScratchPad(Module, Goals, /*EmitPreamble=*/false,
EmittedFunctions, EmittedTheorems,
++ModuleIndex, ProjectGoals,
Selection ? &*Selection : nullptr, &Specs);
} else {
Result = exportLeanScratchPad(
Module, *Out, !PreambleEmitted, EmittedFunctions, EmittedTheorems,
++ModuleIndex, ProjectGoals, Selection ? &*Selection : nullptr);
PreambleEmitted = true;
}
if (ProjectGoals)
for (size_t I = Before; I < ProjectGoals->size(); ++I)
if ((*ProjectGoals)[I].Exported)
Expand Down Expand Up @@ -754,11 +769,14 @@ std::unique_ptr<VerifyBackend>
verify::createVerifyBackend(BackendKind K, llvm::raw_ostream *LeanOut,
unsigned BMCUnroll,
const BackendExecutionOptions &Execution,
std::vector<LeanProjectGoal> *LeanProjectGoals) {
std::vector<LeanProjectGoal> *LeanProjectGoals,
LeanProjectModules *LeanModules) {
switch (K) {
case BackendKind::Z3:
return std::make_unique<Z3VerifyBackend>(Execution, "z3");
case BackendKind::Lean:
if (LeanModules)
return std::make_unique<LeanVerifyBackend>(LeanModules, LeanProjectGoals);
return std::make_unique<LeanVerifyBackend>(LeanOut, LeanProjectGoals);
case BackendKind::BMC:
return std::make_unique<BMCVerifyBackend>(BMCUnroll, Execution);
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/Verify/Backend/VerifyBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,12 +307,14 @@ inline unsigned moduleTimeoutMs(const ObligationModule &Module,
}

struct LeanProjectGoal;
struct LeanProjectModules;

std::unique_ptr<VerifyBackend>
createVerifyBackend(BackendKind K, llvm::raw_ostream *LeanOut = nullptr,
unsigned BMCUnroll = 10,
const BackendExecutionOptions &Execution = {},
std::vector<LeanProjectGoal> *LeanProjectGoals = nullptr);
std::vector<LeanProjectGoal> *LeanProjectGoals = nullptr,
LeanProjectModules *LeanModules = nullptr);

VerifyResult
lowerObligationModule(const ObligationModule &Module,
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Verify/Driver/LeanAutomation.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ inline constexpr llvm::StringLiteral LeanAutomationSource =
R"lean(/- Generated by CppVerify: the tactics of its automatic proofs, which proof
files may use too. Regeneration replaces this file. -/
import Lean
import CppVerify.Generated
import CppVerify.Prelude

register_option cppverify.autoBudget : Nat := {
defValue := 50000
Expand Down
Loading
Loading