Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
1 change: 1 addition & 0 deletions kani-compiler/src/kani_compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ impl Callbacks for KaniCompiler {
let queries = self.queries.clone();
move |_cfg| backend(queries)
}));
// `kani-driver` passes the `kani-compiler` specific arguments through llvm-args, so extract them here.
args.extend(config.opts.cg.llvm_args.iter().cloned());
let args = Arguments::parse_from(args);
init_session(&args, matches!(config.opts.error_format, ErrorOutputType::Json { .. }));
Expand Down
9 changes: 7 additions & 2 deletions kani-compiler/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,15 @@ fn main() {

/// Return whether we should run our flavour of the compiler, and which arguments to pass to rustc.
///
/// We add a `--kani-compiler` argument to run the Kani version of the compiler, which needs to be
/// `kani-driver` adds a `--kani-compiler` argument to run the Kani version of the compiler, which needs to be
/// filtered out before passing the arguments to rustc.
///
/// All other Kani arguments are today located inside `--llvm-args`.
///
/// This function returns `true` for rustc invocations that originate from our rustc / cargo rustc invocations in `kani-driver`.
/// It returns `false` for rustc invocations that cargo adds in the process of executing the `kani-driver` rustc command.
/// For example, if we are compiling a crate that has a build.rs file, cargo will compile and run that build script
/// (c.f. https://doc.rust-lang.org/cargo/reference/build-scripts.html#life-cycle-of-a-build-script).
/// The build script should be compiled with normal rustc, not the Kani compiler.
pub fn is_kani_compiler(args: Vec<String>) -> (bool, Vec<String>) {
assert!(!args.is_empty(), "Arguments should always include executable name");
const KANI_COMPILER: &str = "--kani-compiler";
Expand Down
2 changes: 2 additions & 0 deletions kani-driver/src/autoharness/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ impl KaniSession {
}

/// Add the compiler arguments specific to the `autoharness` subcommand.
/// TODO: this should really be appending onto the `kani_compiler_flags()` output instead of `pkg_args`.
/// It doesn't affect functionality since autoharness doesn't examine dependencies, but would still be better practice.
pub fn add_auto_harness_args(&mut self, included: &[String], excluded: &[String]) {
for func in included {
self.pkg_args
Expand Down
19 changes: 12 additions & 7 deletions kani-driver/src/call_cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,14 +182,19 @@ crate-type = ["lib"]
cargo_args.push("-v".into());
}

// Arguments that will only be passed to the target package.
// Arguments that will only be passed to the target crate (the crate under verification)
// and not its dependencies, c.f. https://doc.rust-lang.org/cargo/commands/cargo-rustc.html.
// The difference between pkg_args and rustc_args is that rustc_args are also provided when
// we invoke rustc on the target crate's dependencies.
// We do not provide the `--reachability` argument to dependencies so that it has the default value `None`
// (c.f. kani-compiler::args::ReachabilityType) and we skip codegen for the dependency.
// This is the desired behavior because we only want to construct `CodegenUnits` for the target crate;
// i.e., if some dependency has harnesses, we don't want to run them.

// If you are adding a new `kani-compiler` argument, you likely want to put it `kani_compiler_flags()` instead,
// unless there a reason it shouldn't be passed to dependencies.
// (Note that at the time of writing, passing the other compiler args to dependencies is a no-op, since `--reachability=None` skips codegen anyway.)
self.pkg_args.push(self.reachability_arg());
if let Some(backend_arg) = self.backend_arg() {
self.pkg_args.push(backend_arg);
}
if self.args.no_assert_contracts {
self.pkg_args.push("--no-assert-contracts".into());
}

let mut found_target = false;
let packages = self.packages_to_verify(&self.args, &metadata)?;
Expand Down
15 changes: 4 additions & 11 deletions kani-driver/src/call_single_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,6 @@ impl KaniSession {
) -> Result<()> {
let mut kani_args = self.kani_compiler_flags();
kani_args.push(format!("--reachability={}", self.reachability_mode()));
if self.args.common_args.unstable_features.contains(UnstableFeature::Lean) {
kani_args.push("--backend=llbc".into());
}

let lib_path = lib_folder().unwrap();
let mut rustc_args = self.kani_rustc_flags(LibConfig::new(lib_path));
Expand Down Expand Up @@ -100,14 +97,6 @@ impl KaniSession {
to_rustc_arg(vec![format!("--reachability={}", self.reachability_mode())])
}

pub fn backend_arg(&self) -> Option<String> {
if self.args.common_args.unstable_features.contains(UnstableFeature::Lean) {
Some(to_rustc_arg(vec!["--backend=llbc".into()]))
} else {
None
}
}

/// These arguments are arguments passed to kani-compiler that are `kani` compiler specific.
pub fn kani_compiler_flags(&self) -> Vec<String> {
let mut flags = vec![check_version()];
Expand Down Expand Up @@ -150,6 +139,10 @@ impl KaniSession {
flags.push("--ub-check=uninit".into());
}

if self.args.common_args.unstable_features.contains(UnstableFeature::Lean) {
flags.push("--backend=llbc".into());
}

if self.args.print_llbc {
flags.push("--print-llbc".into());
}
Expand Down
2 changes: 1 addition & 1 deletion kani-driver/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub struct KaniSession {
/// Automatically verify functions in the crate, in addition to running manual harnesses.
pub auto_harness: bool,

/// The arguments that will be passed to the target package, i.e. kani_compiler.
/// The arguments that will be passed only to the target package, not its dependencies.
pub pkg_args: Vec<String>,

/// Include all publicly-visible symbols in the generated goto binary, not just those reachable from
Expand Down
Loading