Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
98 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
5683c25
verify: Let the Lean backend export goals over spec collections.
SwayamInSync Oct 23, 2026
d5c8a51
verify: State the spec collections in Lean with core types, prelude o…
SwayamInSync Oct 23, 2026
91bcccc
verify: Add machine equalities, collection extensionality, and spec u…
SwayamInSync Oct 23, 2026
dc6e821
test: Check that Lean evaluates every collection operation as the cer…
SwayamInSync Oct 23, 2026
e6287c9
test: Add the functions over each spec collection of the Lean collect…
SwayamInSync Oct 23, 2026
6dac71e
test: Add a proof by hand over a sequence for the Lean collections test.
SwayamInSync Oct 23, 2026
ce1c27c
test: Check the export, automation, and certification of goals over s…
SwayamInSync Oct 23, 2026
5a1bcfc
test: Expect revision 2 of cppverify_auto in the proof headers.
SwayamInSync Oct 23, 2026
fb9d7ee
test: Expect cppverify_auto to prove the goals over tri, and the proo…
SwayamInSync Oct 23, 2026
106cd5e
test: Say that the proofs over tri are also written by hand.
SwayamInSync Oct 23, 2026
511d17d
test: Expect cppverify_auto to certify fibo_step, and fibo_six to nee…
SwayamInSync Oct 23, 2026
1bbf954
docs: Explain collections in Lean and revision 2 of cppverify_auto in…
SwayamInSync Oct 23, 2026
98dfdd9
docs: Say in chapter 13 that a Lean project states the spec collections.
SwayamInSync Oct 23, 2026
20b4f96
docs: Drop the limitation that Lean lacks the spec collections.
SwayamInSync Oct 23, 2026
64bc948
docs: Show revision 2 of cppverify_auto in the tooling reference.
SwayamInSync Oct 23, 2026
5cc1e02
docs: Note collections in Lean and revision 2 of cppverify_auto in th…
SwayamInSync Oct 23, 2026
0d71ea4
docs: Describe the spec collections in Lean and the new automation st…
SwayamInSync Oct 23, 2026
a734035
docs: Describe the Lean collection prelude and revision 2 of cppverif…
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
483 changes: 432 additions & 51 deletions clang/lib/Verify/Backend/LeanBackend.cpp

Large diffs are not rendered by default.

33 changes: 26 additions & 7 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,12 +82,13 @@ 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.
return {allLogicFeatures() & ~logicFeature(LogicFeature::Sequences) &
~logicFeature(LogicFeature::Collections),
false};
return {allLogicFeatures(), false};
}
/// Restrict later exports to these internal obligation IDs.
void selectObligations(std::optional<std::set<std::string>> Ids) {
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
68 changes: 63 additions & 5 deletions clang/lib/Verify/Driver/LeanAutomation.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,28 @@ namespace verify {

/// Names this module's tactics: a stub or automatic proof that an earlier
/// revision wrote is tried again.
inline constexpr llvm::StringLiteral LeanAutomationRevision = "1";
inline constexpr llvm::StringLiteral LeanAutomationRevision = "2";

/// The steps of cppverify_auto, each the whole proof of a goal it proves.
inline constexpr llvm::StringLiteral LeanAutomationSteps[] = {
"cppverify_auto_grind", "cppverify_auto_heap", "cppverify_auto_bv",
"cppverify_auto_decide", "cppverify_auto_simp"};
"cppverify_auto_grind", "cppverify_auto_heap", "cppverify_auto_bv",
"cppverify_auto_decide", "cppverify_auto_simp", "cppverify_auto_bveq",
"cppverify_auto_ext", "cppverify_auto_unfold"};

/// CppVerify/Auto.lean, written with every export. Its steps were chosen by
/// what proves the goals of the test suite (heap stores as the functions
/// they define, machine arithmetic as integers, then grind; stating toInt
/// ranges and removing Int.bmod first proved nothing more, the latter less),
/// each with a heartbeat budget of its own, as Vermilion's discharger ladder.
/// Revision 2 adds the last three, after the others, so that every goal an
/// earlier step proves keeps its proof: machine equalities and sign
/// extensions as integer facts, collection equality element by element, and
/// the definition instances a goal states, by the bodies they name.
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 Expand Up @@ -82,6 +87,29 @@ elab "cppverify_unfold_readable" : tactic => withMainContext do
let unfolded ← deltaExpand target (· == name)
replaceMainGoal [← (← getMainGoal).change unfolded]

open Lean Elab Tactic Meta in
/-- Unfolds the definitions of spec bodies that a goal and its hypotheses
name, so that each definition instance a goal states says what the body
does. A body names only lower levels of its definition, so this ends. -/
elab "cppverify_unfold_bodies" : tactic => withMainContext do
let isBody : Name → Bool := fun
| .str _ s => s.startsWith "cppSpecBody_"
| _ => false
let rec expand (e : Expr) : Nat → MetaM Expr
| 0 => return e
| fuel + 1 => do
let e' ← deltaExpand e isBody
if e' == e then return e else expand e' fuel
let mut goal ← getMainGoal
goal ← goal.change (← expand (← instantiateMVars (← goal.getType)) 64)
for d in ← goal.withContext getLCtx do
if d.isImplementationDetail then continue
let t ← instantiateMVars d.type
let t' ← expand t 64
if t' != t then
goal ← goal.changeLocalDecl d.fvarId t'
replaceMainGoal [goal]

/-- Machine comparisons, constants, and overflow conditions as facts about
integers. -/
macro "cppverify_norm" : tactic => `(tactic| (try simp only [cppBvSlt, cppBvSle,
Expand Down Expand Up @@ -118,6 +146,33 @@ macro "cppverify_auto_decide" : tactic =>
macro "cppverify_auto_simp" : tactic =>
`(tactic| (cppverify_unfold_readable; simp_all))

/-- Machine equalities, as of `x ≠ y` for distinct keys, and sign extensions
as facts about integers. -/
macro "cppverify_bveq" : tactic => `(tactic| (try simp (disch := omega) only
[ne_eq, ← BitVec.toInt_inj, BitVec.toInt_signExtend_of_le] at *))
macro "cppverify_auto_bveq" : tactic => `(tactic| (
cppverify_unfold_readable
intros
cppverify_bveq
cppverify_norm
all_goals grind))
/-- Two collections are equal when they agree at every element: equal
lengths and reads for sequences, membership for sets, counts for
multisets, and keys and values for maps. -/
macro "cppverify_auto_ext" : tactic => `(tactic| (
cppverify_unfold_readable
intros
(first | apply cppSeq_ext | apply cppSet_ext | apply cppMultiset_ext
| apply cppMap_ext)
all_goals (intros; cppverify_norm; all_goals grind)))
macro "cppverify_auto_unfold" : tactic => `(tactic| (
cppverify_unfold_readable
intros
cppverify_unfold_bodies
cppverify_bveq
cppverify_norm
all_goals grind))

open Lean Elab Tactic in
/-- Tries each step on the goal, each with `cppverify.autoBudget` heartbeats
of its own, and keeps the first that proves it. A step that runs out of
Expand All @@ -132,7 +187,10 @@ elab "cppverify_auto" : tactic => do
("cppverify_auto_heap", ← `(tactic| cppverify_auto_heap)),
("cppverify_auto_bv", ← `(tactic| cppverify_auto_bv)),
("cppverify_auto_decide", ← `(tactic| cppverify_auto_decide)),
("cppverify_auto_simp", ← `(tactic| cppverify_auto_simp))]
("cppverify_auto_simp", ← `(tactic| cppverify_auto_simp)),
("cppverify_auto_bveq", ← `(tactic| cppverify_auto_bveq)),
("cppverify_auto_ext", ← `(tactic| cppverify_auto_ext)),
("cppverify_auto_unfold", ← `(tactic| cppverify_auto_unfold))]
for (name, step) in steps do
let attempt : TacticM Unit := do
let heartbeats ← IO.getNumHeartbeats
Expand Down
Loading
Loading