Skip to content

Commit 101d55f

Browse files
Change kani-compiler to use -C llvm-args for Kani specific flags (rust-lang#2185)
Changed how `kani-driver` passess arguments to `kani-compiler`. We now have one option, `--kani-compiler`, that changes how we configure rustc, and all the other Kani specific arguments are added to `-C llvm-args`. We no longer need to keep the arguments in a certain order or need to use KANI_FLAGS environment variable. In the `kani-compiler` we no longer parse the arguments before invoking rustc, we initially detect whether users want to use the Kani flavour of the compiler by looking for a `--kani-compiler` flag. If `--kani-compiler` flag is found, we configure rustc's driver to use our custom backend and our custom callback. We then invoke the driver with the command line arguments excluding the `--kani-compiler` flag. During the callback configuration we initialize the Kani specific flags that are passed via `-C llvm-args`. If there isn't any `--kani-compiler` flag, we just invoke rustc with all the given arguments. Co-authored-by: Zyad Hassan <[email protected]>
1 parent 832bc67 commit 101d55f

File tree

20 files changed

+353
-328
lines changed

20 files changed

+353
-328
lines changed

kani-compiler/kani_queries/src/lib.rs

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,14 @@
11
// Copyright Kani Contributors
22
// SPDX-License-Identifier: Apache-2.0 OR MIT
33

4-
use std::sync::atomic::{AtomicBool, Ordering};
5-
#[cfg(not(feature = "unsound_experiments"))]
6-
use std::sync::Mutex;
4+
use std::sync::{Arc, Mutex};
75
use strum_macros::{AsRefStr, EnumString, EnumVariantNames};
86

97
#[cfg(feature = "unsound_experiments")]
108
mod unsound_experiments;
119

1210
#[cfg(feature = "unsound_experiments")]
13-
use {
14-
crate::unsound_experiments::UnsoundExperiments,
15-
std::sync::{Arc, Mutex},
16-
};
11+
use crate::unsound_experiments::UnsoundExperiments;
1712

1813
#[derive(Debug, Clone, Copy, AsRefStr, EnumString, EnumVariantNames, PartialEq, Eq)]
1914
#[strum(serialize_all = "snake_case")]
@@ -56,60 +51,78 @@ pub trait UserInput {
5651
fn get_stubbing_enabled(&self) -> bool;
5752

5853
#[cfg(feature = "unsound_experiments")]
59-
fn get_unsound_experiments(&self) -> Arc<Mutex<UnsoundExperiments>>;
54+
fn get_unsound_experiments(&self) -> UnsoundExperiments;
55+
#[cfg(feature = "unsound_experiments")]
56+
fn set_unsound_experiments(&mut self, experiments: UnsoundExperiments);
6057
}
6158

62-
#[derive(Debug, Default)]
59+
/// This structure should only be used behind a synchronized reference or a snapshot.
60+
#[derive(Debug, Clone)]
6361
pub struct QueryDb {
64-
check_assertion_reachability: AtomicBool,
65-
emit_vtable_restrictions: AtomicBool,
66-
json_pretty_print: AtomicBool,
67-
ignore_global_asm: AtomicBool,
68-
reachability_analysis: Mutex<ReachabilityType>,
62+
check_assertion_reachability: bool,
63+
emit_vtable_restrictions: bool,
64+
json_pretty_print: bool,
65+
ignore_global_asm: bool,
66+
reachability_analysis: ReachabilityType,
6967
stubbing_enabled: bool,
7068
#[cfg(feature = "unsound_experiments")]
71-
unsound_experiments: Arc<Mutex<UnsoundExperiments>>,
69+
unsound_experiments: UnsoundExperiments,
70+
}
71+
72+
impl QueryDb {
73+
pub fn new() -> Arc<Mutex<QueryDb>> {
74+
Arc::new(Mutex::new(QueryDb {
75+
check_assertion_reachability: false,
76+
emit_vtable_restrictions: false,
77+
json_pretty_print: false,
78+
ignore_global_asm: false,
79+
reachability_analysis: ReachabilityType::None,
80+
stubbing_enabled: false,
81+
#[cfg(feature = "unsound_experiments")]
82+
unsound_experiments: unsound_experiments::UnsoundExperiments { zero_init_vars: false },
83+
}))
84+
}
7285
}
7386

7487
impl UserInput for QueryDb {
7588
fn set_emit_vtable_restrictions(&mut self, restrictions: bool) {
76-
self.emit_vtable_restrictions.store(restrictions, Ordering::Relaxed);
89+
self.emit_vtable_restrictions = restrictions;
7790
}
7891

7992
fn get_emit_vtable_restrictions(&self) -> bool {
80-
self.emit_vtable_restrictions.load(Ordering::Relaxed)
93+
self.emit_vtable_restrictions
8194
}
8295

8396
fn set_check_assertion_reachability(&mut self, reachability: bool) {
84-
self.check_assertion_reachability.store(reachability, Ordering::Relaxed);
97+
self.check_assertion_reachability = reachability;
8598
}
8699

87100
fn get_check_assertion_reachability(&self) -> bool {
88-
self.check_assertion_reachability.load(Ordering::Relaxed)
101+
self.check_assertion_reachability
89102
}
90103

91104
fn set_output_pretty_json(&mut self, pretty_json: bool) {
92-
self.json_pretty_print.store(pretty_json, Ordering::Relaxed);
105+
self.json_pretty_print = pretty_json;
93106
}
94107

95108
fn get_output_pretty_json(&self) -> bool {
96-
self.json_pretty_print.load(Ordering::Relaxed)
109+
self.json_pretty_print
97110
}
98111

99112
fn set_ignore_global_asm(&mut self, global_asm: bool) {
100-
self.ignore_global_asm.store(global_asm, Ordering::Relaxed);
113+
self.ignore_global_asm = global_asm;
101114
}
102115

103116
fn get_ignore_global_asm(&self) -> bool {
104-
self.ignore_global_asm.load(Ordering::Relaxed)
117+
self.ignore_global_asm
105118
}
106119

107120
fn set_reachability_analysis(&mut self, reachability: ReachabilityType) {
108-
*self.reachability_analysis.get_mut().unwrap() = reachability;
121+
self.reachability_analysis = reachability;
109122
}
110123

111124
fn get_reachability_analysis(&self) -> ReachabilityType {
112-
*self.reachability_analysis.lock().unwrap()
125+
self.reachability_analysis
113126
}
114127

115128
fn set_stubbing_enabled(&mut self, stubbing_enabled: bool) {
@@ -121,7 +134,12 @@ impl UserInput for QueryDb {
121134
}
122135

123136
#[cfg(feature = "unsound_experiments")]
124-
fn get_unsound_experiments(&self) -> Arc<Mutex<UnsoundExperiments>> {
125-
self.unsound_experiments.clone()
137+
fn get_unsound_experiments(&self) -> UnsoundExperiments {
138+
self.unsound_experiments
139+
}
140+
141+
#[cfg(feature = "unsound_experiments")]
142+
fn set_unsound_experiments(&mut self, experiments: UnsoundExperiments) {
143+
self.unsound_experiments = experiments
126144
}
127145
}

kani-compiler/kani_queries/src/unsound_experiments.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
#![cfg(feature = "unsound_experiments")]
55

6-
#[derive(Debug, Default)]
6+
#[derive(Debug, Clone, Copy, Default)]
77
pub struct UnsoundExperiments {
88
/// Zero initilize variables.
99
/// This is useful for experiments to see whether assigning constant values produces better

kani-compiler/src/codegen_cprover_gotoc/compiler_interface.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,23 @@ use std::io::Write as IoWrite;
4545
use std::iter::FromIterator;
4646
use std::path::{Path, PathBuf};
4747
use std::process::Command;
48-
use std::rc::Rc;
48+
use std::sync::{Arc, Mutex};
4949
use std::time::Instant;
5050
use tempfile::Builder as TempFileBuilder;
5151
use tracing::{debug, error, info};
5252

5353
#[derive(Clone)]
5454
pub struct GotocCodegenBackend {
55-
queries: Rc<QueryDb>,
55+
/// The query is shared with `KaniCompiler` and it is initialized as part of `rustc`
56+
/// initialization, which may happen after this object is created.
57+
/// Since we don't have any guarantees on when the compiler creates the Backend object, neither
58+
/// in which thread it will be used, we prefer to explicitly synchronize any query access.
59+
queries: Arc<Mutex<QueryDb>>,
5660
}
5761

5862
impl GotocCodegenBackend {
59-
pub fn new(queries: &Rc<QueryDb>) -> Self {
60-
GotocCodegenBackend { queries: Rc::clone(queries) }
63+
pub fn new(queries: Arc<Mutex<QueryDb>>) -> Self {
64+
GotocCodegenBackend { queries }
6165
}
6266
}
6367

@@ -67,7 +71,7 @@ impl CodegenBackend for GotocCodegenBackend {
6771
}
6872

6973
fn provide(&self, providers: &mut Providers) {
70-
provide::provide(providers, &self.queries);
74+
provide::provide(providers, &self.queries.lock().unwrap());
7175
}
7276

7377
fn provide_extern(&self, providers: &mut ty::query::ExternProviders) {
@@ -84,7 +88,7 @@ impl CodegenBackend for GotocCodegenBackend {
8488

8589
// Follow rustc naming convention (cx is abbrev for context).
8690
// https://rustc-dev-guide.rust-lang.org/conventions.html#naming-conventions
87-
let mut gcx = GotocCtx::new(tcx, self.queries.clone());
91+
let mut gcx = GotocCtx::new(tcx, (*self.queries.lock().unwrap()).clone());
8892
check_target(tcx.sess);
8993
check_options(tcx.sess);
9094
check_crate_items(&gcx);
@@ -170,7 +174,7 @@ impl CodegenBackend for GotocCodegenBackend {
170174
if !tcx.sess.opts.unstable_opts.no_codegen && tcx.sess.opts.output_types.should_codegen() {
171175
let outputs = tcx.output_filenames(());
172176
let base_filename = outputs.output_path(OutputType::Object);
173-
let pretty = self.queries.get_output_pretty_json();
177+
let pretty = self.queries.lock().unwrap().get_output_pretty_json();
174178
write_file(&base_filename, ArtifactType::SymTab, &gcx.symbol_table, pretty);
175179
write_file(&base_filename, ArtifactType::TypeMap, &type_map, pretty);
176180
write_file(&base_filename, ArtifactType::Metadata, &metadata, pretty);

kani-compiler/src/codegen_cprover_gotoc/context/goto_ctx.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,13 @@ use rustc_target::abi::Endian;
4242
use rustc_target::abi::{HasDataLayout, TargetDataLayout};
4343
use rustc_target::spec::Target;
4444
use std::path::Path;
45-
use std::rc::Rc;
4645

4746
pub struct GotocCtx<'tcx> {
4847
/// the typing context
4948
pub tcx: TyCtxt<'tcx>,
50-
/// the query system for kani
51-
pub queries: Rc<QueryDb>,
49+
/// a snapshot of the query values. The queries shouldn't change at this point,
50+
/// so we just keep a copy.
51+
pub queries: QueryDb,
5252
/// the generated symbol table for gotoc
5353
pub symbol_table: SymbolTable,
5454
pub hooks: GotocHooks<'tcx>,
@@ -79,7 +79,7 @@ pub struct GotocCtx<'tcx> {
7979

8080
/// Constructor
8181
impl<'tcx> GotocCtx<'tcx> {
82-
pub fn new(tcx: TyCtxt<'tcx>, queries: Rc<QueryDb>) -> GotocCtx<'tcx> {
82+
pub fn new(tcx: TyCtxt<'tcx>, queries: QueryDb) -> GotocCtx<'tcx> {
8383
let fhks = fn_hooks();
8484
let mm = machine_model_from_session(tcx.sess);
8585
let symbol_table = SymbolTable::new(mm);

0 commit comments

Comments
 (0)