Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
32 changes: 32 additions & 0 deletions kani-driver/src/args/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,12 @@ impl NumThreads {
}

impl VerificationArgs {
/// Whether the LLBC backend (`-Z lean`) replaces the CBMC one. It writes no goto program, so
/// there is nothing to link or verify: Kani stops once the compiler has run.
pub fn uses_llbc_backend(&self) -> bool {
self.common_args.unstable_features.contains(UnstableFeature::Lean)
Comment thread
tautschnig marked this conversation as resolved.
}

pub fn restrict_vtable(&self) -> bool {
self.common_args.unstable_features.contains(UnstableFeature::RestrictVtable)
&& !self.no_restrict_vtable
Expand Down Expand Up @@ -879,6 +885,24 @@ impl ValidateArgs for VerificationArgs {
"Conflicting options: --sarif isn't compatible with --only-codegen.",
));
}
// The LLBC backend stops after codegen too (see `uses_llbc_backend`), so the same
// holds for it: nothing would write the requested file.
if self.uses_llbc_backend() {
for (requested, option) in [
(self.sarif.is_some(), "--sarif"),
(self.export_json.is_some(), "--export-json"),
] {
if requested {
return Err(Error::raw(
ErrorKind::ArgumentConflict,
format!(
"Conflicting options: {option} isn't compatible with {}.",
UnstableFeature::Lean.as_argument_string()
),
));
}
}
}
// Neither code-generation-only mode runs verification, so there is nothing to export.
// `--only-codegen` would otherwise succeed without writing the file the user asked for,
// and `--no-codegen` would write a document describing a run that never happened.
Expand Down Expand Up @@ -1260,6 +1284,10 @@ mod tests {
"kani file.rs -Z unstable-options --export-json out.json --no-codegen",
ErrorKind::ArgumentConflict,
);
expect_validation_error(
"kani file.rs -Z unstable-options -Z lean --export-json out.json",
ErrorKind::ArgumentConflict,
);
}

#[test]
Expand Down Expand Up @@ -1358,6 +1386,10 @@ mod tests {
"kani file.rs --sarif out.sarif --only-codegen",
ErrorKind::ArgumentConflict,
);
expect_validation_error(
"kani file.rs -Z lean --sarif out.sarif",
ErrorKind::ArgumentConflict,
);
}

#[test]
Expand Down
10 changes: 8 additions & 2 deletions kani-driver/src/autoharness/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::list::output::output_list_results;
use crate::project::{Project, standalone_project, std_project};
use crate::session::KaniSession;
use crate::util::warning;
use crate::{InvocationType, print_kani_version, project, verify_project};
use crate::{InvocationType, codegen_llbc_only, print_kani_version, project, verify_project};
use anyhow::Result;
use comfy_table::Table as PrettyTable;
use kani_metadata::{AutoHarnessSkipReason, HarnessMetadata, KaniMetadata};
Expand Down Expand Up @@ -114,7 +114,13 @@ fn postprocess_project(
session.args.common_args.quiet,
);
}
if session.args.only_codegen { Ok(()) } else { verify_project(project, session) }
if session.args.only_codegen {
Ok(())
} else if session.args.uses_llbc_backend() {
codegen_llbc_only(&project, &session)
} else {
verify_project(project, session)
}
}

/// Print automatic harness metadata to the terminal.
Expand Down
24 changes: 22 additions & 2 deletions kani-driver/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,13 @@ fn cargokani_main(input_args: Vec<OsString>) -> Result<()> {
}

let project = project::cargo_project(&mut session, false)?;
if session.args.only_codegen { Ok(()) } else { verify_project(project, session) }
if session.args.only_codegen {
Ok(())
} else if session.args.uses_llbc_backend() {
codegen_llbc_only(&project, &session)
} else {
verify_project(project, session)
}
}

/// The main function for the `kani` command.
Expand Down Expand Up @@ -164,7 +170,21 @@ fn standalone_main() -> Result<()> {
(session, project)
}
};
if session.args.only_codegen { Ok(()) } else { verify_project(project, session) }
if session.args.only_codegen {
Ok(())
} else if session.args.uses_llbc_backend() {
codegen_llbc_only(&project, &session)
} else {
verify_project(project, session)
}
}

/// Finish a run of the LLBC backend (`-Z lean`), which stops after codegen: there is nothing to
/// link or verify. Still reject `--harness` filters that match nothing, as `verify_project` does:
/// the compiler only filters its metadata and would silently translate no harness.
pub(crate) fn codegen_llbc_only(project: &Project, session: &KaniSession) -> Result<()> {
session.determine_targets(project.get_all_harnesses())?;
Ok(())
}

/// Run verification on the given project.
Expand Down
38 changes: 23 additions & 15 deletions kani-driver/src/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,21 +122,29 @@ impl Project {
cargo_metadata: Option<cargo_metadata::Metadata>,
) -> Result<Self> {
// For each harness (test or proof) from each metadata, read the path for the goto
// SymTabGoto file. Use that path to find all the other artifacts.
let link_jobs = metadata
.iter()
.flat_map(|crate_metadata| {
crate_metadata.test_harnesses.iter().chain(crate_metadata.proof_harnesses.iter())
})
.map(|harness| {
let model_path = harness.goto_file.as_ref().expect("Expected a model file");
let input = model_path.canonicalize().with_context(|| {
format!("Failed to canonicalize harness model {}", model_path.display())
})?;
let output = convert_type(&input, SymTabGoto, Goto);
Ok(LinkJob { input, output })
})
.collect::<Result<Vec<_>>>()?;
// SymTabGoto file. Use that path to find all the other artifacts. The LLBC backend writes
// no goto files, so there is nothing to link.
let link_jobs = if session.args.uses_llbc_backend() {
vec![]
} else {
metadata
.iter()
.flat_map(|crate_metadata| {
crate_metadata
.test_harnesses
.iter()
.chain(crate_metadata.proof_harnesses.iter())
})
.map(|harness| {
let model_path = harness.goto_file.as_ref().expect("Expected a model file");
let input = model_path.canonicalize().with_context(|| {
format!("Failed to canonicalize harness model {}", model_path.display())
})?;
let output = convert_type(&input, SymTabGoto, Goto);
Ok(LinkJob { input, output })
})
.collect::<Result<Vec<_>>>()?
};

let build_artifacts = |link_job: &LinkJob| -> Result<Vec<Artifact>> {
let symtab_out = Artifact { path: link_job.input.clone(), typ: SymTabGoto };
Expand Down
Loading