Skip to content

Commit 3b3c43e

Browse files
committed
Migrate compiler interface to use StableMIR
1 parent e1502e7 commit 3b3c43e

File tree

11 files changed

+140
-151
lines changed

11 files changed

+140
-151
lines changed

kani-compiler/src/codegen_cprover_gotoc/codegen/intrinsic.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1331,7 +1331,7 @@ impl<'tcx> GotocCtx<'tcx> {
13311331
TyKind::RigidTy(RigidTy::Slice(_)) | TyKind::RigidTy(RigidTy::Str) => {
13321332
let unit_t = match ty.kind() {
13331333
TyKind::RigidTy(RigidTy::Slice(et)) => et,
1334-
TyKind::RigidTy(RigidTy::Str) => rustc_internal::stable(self.tcx.types.u8),
1334+
TyKind::RigidTy(RigidTy::Str) => Ty::unsigned_ty(UintTy::U8),
13351335
_ => unreachable!(),
13361336
};
13371337
let unit = self.layout_of_stable(unit_t);

kani-compiler/src/codegen_cprover_gotoc/compiler_interface.rs

Lines changed: 30 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::kani_middle::{check_reachable_items, dump_mir_items};
1616
use crate::kani_queries::QueryDb;
1717
use cbmc::goto_program::Location;
1818
use cbmc::irep::goto_binary_serde::write_goto_binary_file;
19-
use cbmc::RoundingMode;
19+
use cbmc::{InternString, RoundingMode};
2020
use cbmc::{InternedString, MachineModel};
2121
use kani_metadata::artifact::convert_type;
2222
use kani_metadata::CompilerArtifactStub;
@@ -32,12 +32,10 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
3232
use rustc_data_structures::temp_dir::MaybeTempDir;
3333
use rustc_errors::{ErrorGuaranteed, DEFAULT_LOCALE_RESOURCE};
3434
use rustc_hir::def_id::LOCAL_CRATE;
35-
use rustc_hir::definitions::DefPathHash;
3635
use rustc_metadata::creader::MetadataLoaderDyn;
3736
use rustc_metadata::fs::{emit_wrapper_file, METADATA_FILENAME};
3837
use rustc_metadata::EncodedMetadata;
3938
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
40-
use rustc_middle::mir::mono::MonoItem;
4139
use rustc_middle::ty::TyCtxt;
4240
use rustc_middle::util::Providers;
4341
use rustc_session::config::{CrateType, OutputFilenames, OutputType};
@@ -46,7 +44,7 @@ use rustc_session::Session;
4644
use rustc_smir::rustc_internal;
4745
use rustc_target::abi::Endian;
4846
use rustc_target::spec::PanicStrategy;
49-
use stable_mir::mir::mono::MonoItem as MonoItemStable;
47+
use stable_mir::mir::mono::MonoItem;
5048
use stable_mir::CrateDef;
5149
use std::any::Any;
5250
use std::collections::BTreeMap;
@@ -82,10 +80,10 @@ impl GotocCodegenBackend {
8280
fn codegen_items<'tcx>(
8381
&self,
8482
tcx: TyCtxt<'tcx>,
85-
starting_items: &[MonoItem<'tcx>],
83+
starting_items: &[MonoItem],
8684
symtab_goto: &Path,
8785
machine_model: &MachineModel,
88-
) -> (GotocCtx<'tcx>, Vec<MonoItem<'tcx>>) {
86+
) -> (GotocCtx<'tcx>, Vec<MonoItem>) {
8987
let items = with_timer(
9088
|| collect_reachable_items(tcx, starting_items),
9189
"codegen reachability analysis",
@@ -103,17 +101,13 @@ impl GotocCodegenBackend {
103101
for item in &items {
104102
match *item {
105103
MonoItem::Fn(instance) => {
106-
let instance = rustc_internal::stable(instance);
107104
gcx.call_with_panic_debug_info(
108105
|ctx| ctx.declare_function(instance),
109106
format!("declare_function: {}", instance.name()),
110107
instance.def,
111108
);
112109
}
113-
MonoItem::Static(_) => {
114-
let MonoItemStable::Static(def) = rustc_internal::stable(item) else {
115-
unreachable!()
116-
};
110+
MonoItem::Static(def) => {
117111
gcx.call_with_panic_debug_info(
118112
|ctx| ctx.declare_static(def),
119113
format!("declare_static: {}", def.name()),
@@ -128,7 +122,6 @@ impl GotocCodegenBackend {
128122
for item in &items {
129123
match *item {
130124
MonoItem::Fn(instance) => {
131-
let instance = rustc_internal::stable(instance);
132125
gcx.call_with_panic_debug_info(
133126
|ctx| ctx.codegen_function(instance),
134127
format!(
@@ -139,10 +132,7 @@ impl GotocCodegenBackend {
139132
instance.def,
140133
);
141134
}
142-
MonoItem::Static(_) => {
143-
let MonoItemStable::Static(def) = rustc_internal::stable(item) else {
144-
unreachable!()
145-
};
135+
MonoItem::Static(def) => {
146136
gcx.call_with_panic_debug_info(
147137
|ctx| ctx.codegen_static(def),
148138
format!("codegen_static: {}", def.name()),
@@ -237,28 +227,30 @@ impl CodegenBackend for GotocCodegenBackend {
237227
ReachabilityType::Harnesses => {
238228
// Cross-crate collecting of all items that are reachable from the crate harnesses.
239229
let harnesses = queries.target_harnesses();
240-
let mut items: HashSet<DefPathHash> = HashSet::with_capacity(harnesses.len());
230+
let mut items: HashSet<_> = HashSet::with_capacity(harnesses.len());
241231
items.extend(harnesses);
242-
let harnesses = filter_crate_items(tcx, |_, def_id| {
243-
items.contains(&tcx.def_path_hash(def_id))
232+
let harnesses = filter_crate_items(tcx, |_, instance| {
233+
items.contains(&instance.name().intern())
244234
});
245235
for harness in harnesses {
246-
let model_path = queries
247-
.harness_model_path(&tcx.def_path_hash(harness.def_id()))
248-
.unwrap();
249-
let (gcx, items) =
250-
self.codegen_items(tcx, &[harness], model_path, &results.machine_model);
251-
results.extend(gcx, items, None);
236+
let model_path = queries.harness_model_path(&harness.name()).unwrap();
237+
let (gcx, mono_items) = self.codegen_items(
238+
tcx,
239+
&[MonoItem::Fn(harness)],
240+
model_path,
241+
&results.machine_model,
242+
);
243+
results.extend(gcx, mono_items, None);
252244
}
253245
}
254246
ReachabilityType::Tests => {
255247
// We're iterating over crate items here, so what we have to codegen is the "test description" containing the
256248
// test closure that we want to execute
257249
// TODO: Refactor this code so we can guarantee that the pair (test_fn, test_desc) actually match.
258250
let mut descriptions = vec![];
259-
let harnesses = filter_const_crate_items(tcx, |_, def_id| {
260-
if is_test_harness_description(tcx, def_id) {
261-
descriptions.push(def_id);
251+
let harnesses = filter_const_crate_items(tcx, |_, item| {
252+
if is_test_harness_description(tcx, item.def) {
253+
descriptions.push(item.def);
262254
true
263255
} else {
264256
false
@@ -289,11 +281,10 @@ impl CodegenBackend for GotocCodegenBackend {
289281
}
290282
ReachabilityType::None => {}
291283
ReachabilityType::PubFns => {
292-
let entry_fn = tcx.entry_fn(()).map(|(id, _)| id);
293-
let local_reachable = filter_crate_items(tcx, |_, def_id| {
294-
(tcx.is_reachable_non_generic(def_id) && tcx.def_kind(def_id).is_fn_like())
295-
|| entry_fn == Some(def_id)
296-
});
284+
let local_reachable = filter_crate_items(tcx, |_, _| true)
285+
.into_iter()
286+
.map(MonoItem::Fn)
287+
.collect::<Vec<_>>();
297288
let model_path = base_filename.with_extension(ArtifactType::SymTabGoto);
298289
let (gcx, items) = self.codegen_items(
299290
tcx,
@@ -527,17 +518,17 @@ where
527518
}
528519
}
529520

530-
struct GotoCodegenResults<'tcx> {
521+
struct GotoCodegenResults {
531522
reachability: ReachabilityType,
532523
harnesses: Vec<HarnessMetadata>,
533524
unsupported_constructs: UnsupportedConstructs,
534525
concurrent_constructs: UnsupportedConstructs,
535-
items: Vec<MonoItem<'tcx>>,
526+
items: Vec<MonoItem>,
536527
crate_name: InternedString,
537528
machine_model: MachineModel,
538529
}
539530

540-
impl<'tcx> GotoCodegenResults<'tcx> {
531+
impl GotoCodegenResults {
541532
pub fn new(tcx: TyCtxt, reachability: ReachabilityType) -> Self {
542533
GotoCodegenResults {
543534
reachability,
@@ -585,12 +576,7 @@ impl<'tcx> GotoCodegenResults<'tcx> {
585576
}
586577
}
587578

588-
fn extend(
589-
&mut self,
590-
gcx: GotocCtx,
591-
items: Vec<MonoItem<'tcx>>,
592-
metadata: Option<HarnessMetadata>,
593-
) {
579+
fn extend(&mut self, gcx: GotocCtx, items: Vec<MonoItem>, metadata: Option<HarnessMetadata>) {
594580
let mut items = items;
595581
self.harnesses.extend(metadata);
596582
self.concurrent_constructs.extend(gcx.concurrent_constructs);
@@ -599,7 +585,7 @@ impl<'tcx> GotoCodegenResults<'tcx> {
599585
}
600586

601587
/// Prints a report at the end of the compilation.
602-
fn print_report(&self, tcx: TyCtxt<'tcx>) {
588+
fn print_report(&self, tcx: TyCtxt) {
603589
// Print all unsupported constructs.
604590
if !self.unsupported_constructs.is_empty() {
605591
// Sort alphabetically.
@@ -631,7 +617,7 @@ impl<'tcx> GotoCodegenResults<'tcx> {
631617

632618
// Print some compilation stats.
633619
if tracing::enabled!(tracing::Level::INFO) {
634-
analysis::print_stats(tcx, &self.items);
620+
analysis::print_stats(&self.items);
635621
}
636622
}
637623
}

kani-compiler/src/kani_compiler.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use crate::kani_middle::reachability::filter_crate_items;
2525
use crate::kani_middle::stubbing::{self, harness_stub_map};
2626
use crate::kani_queries::QueryDb;
2727
use crate::session::init_session;
28+
use cbmc::{InternString, InternedString};
2829
use clap::Parser;
2930
use kani_metadata::{ArtifactType, HarnessMetadata, KaniMetadata};
3031
use rustc_codegen_ssa::traits::CodegenBackend;
@@ -68,7 +69,7 @@ fn backend(queries: Arc<Mutex<QueryDb>>) -> Box<CodegenBackend> {
6869
}
6970

7071
/// A stable (across compilation sessions) identifier for the harness function.
71-
type HarnessId = DefPathHash;
72+
type HarnessId = InternedString;
7273

7374
/// A set of stubs.
7475
type Stubs = BTreeMap<DefPathHash, DefPathHash>;
@@ -280,14 +281,13 @@ impl KaniCompiler {
280281
if self.queries.lock().unwrap().args().reachability_analysis == ReachabilityType::Harnesses
281282
{
282283
let base_filename = tcx.output_filenames(()).output_path(OutputType::Object);
283-
let harnesses = filter_crate_items(tcx, |_, def_id| is_proof_harness(tcx, def_id));
284+
let harnesses = filter_crate_items(tcx, |_, instance| is_proof_harness(tcx, instance));
284285
let all_harnesses = harnesses
285286
.into_iter()
286287
.map(|harness| {
287-
let def_id = harness.def_id();
288-
let def_path = tcx.def_path_hash(def_id);
289-
let metadata = gen_proof_metadata(tcx, def_id, &base_filename);
290-
let stub_map = harness_stub_map(tcx, def_id, &metadata);
288+
let def_path = harness.name().intern();
289+
let metadata = gen_proof_metadata(tcx, harness, &base_filename);
290+
let stub_map = harness_stub_map(tcx, harness, &metadata);
291291
(def_path, HarnessInfo { metadata, stub_map })
292292
})
293293
.collect::<HashMap<_, _>>();

kani-compiler/src/kani_middle/analysis.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@
77
//! This module will perform all the analyses requested. Callers are responsible for selecting
88
//! when the cost of these analyses are worth it.
99
10-
use rustc_middle::mir::mono::MonoItem as InternalMonoItem;
11-
use rustc_middle::ty::TyCtxt;
12-
use rustc_smir::rustc_internal;
1310
use stable_mir::mir::mono::MonoItem;
1411
use stable_mir::mir::{
1512
visit::Location, MirVisitor, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
@@ -23,8 +20,7 @@ use std::fmt::Display;
2320
/// - Number of items per type (Function / Constant / Shims)
2421
/// - Number of instructions per type.
2522
/// - Total number of MIR instructions.
26-
pub fn print_stats<'tcx>(_tcx: TyCtxt<'tcx>, items: &[InternalMonoItem<'tcx>]) {
27-
let items: Vec<MonoItem> = items.iter().map(rustc_internal::stable).collect();
23+
pub fn print_stats(items: &[MonoItem]) {
2824
let item_types = items.iter().collect::<Counter>();
2925
let visitor = items
3026
.iter()

kani-compiler/src/kani_middle/attributes.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ use rustc_errors::ErrorGuaranteed;
1313
use rustc_hir::{def::DefKind, def_id::DefId};
1414
use rustc_middle::ty::{Instance, TyCtxt, TyKind};
1515
use rustc_session::Session;
16+
use rustc_smir::rustc_internal;
1617
use rustc_span::{Span, Symbol};
18+
use stable_mir::mir::mono::Instance as InstanceStable;
19+
use stable_mir::CrateDef;
1720
use std::str::FromStr;
1821
use strum_macros::{AsRefStr, EnumString};
1922

@@ -111,6 +114,10 @@ impl<'tcx> std::fmt::Debug for KaniAttributes<'tcx> {
111114
impl<'tcx> KaniAttributes<'tcx> {
112115
/// Perform preliminary parsing and checking for the attributes on this
113116
/// function
117+
pub fn for_instance(tcx: TyCtxt<'tcx>, instance: InstanceStable) -> Self {
118+
KaniAttributes::for_item(tcx, rustc_internal::internal(instance.def.def_id()))
119+
}
120+
114121
pub fn for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> Self {
115122
let all_attributes = tcx.get_attrs_unchecked(def_id);
116123
let map = all_attributes.iter().fold(
@@ -511,20 +518,23 @@ pub fn is_function_contract_generated(tcx: TyCtxt, def_id: DefId) -> bool {
511518

512519
/// Same as [`KaniAttributes::is_harness`] but more efficient because less
513520
/// attribute parsing is performed.
514-
pub fn is_proof_harness(tcx: TyCtxt, def_id: DefId) -> bool {
521+
pub fn is_proof_harness(tcx: TyCtxt, instance: InstanceStable) -> bool {
522+
let def_id = rustc_internal::internal(instance.def.def_id());
515523
has_kani_attribute(tcx, def_id, |a| {
516524
matches!(a, KaniAttributeKind::Proof | KaniAttributeKind::ProofForContract)
517525
})
518526
}
519527

520528
/// Does this `def_id` have `#[rustc_test_marker]`?
521-
pub fn is_test_harness_description(tcx: TyCtxt, def_id: DefId) -> bool {
529+
pub fn is_test_harness_description(tcx: TyCtxt, item: impl CrateDef) -> bool {
530+
let def_id = rustc_internal::internal(item.def_id());
522531
let attrs = tcx.get_attrs_unchecked(def_id);
523532
attr::contains_name(attrs, rustc_span::symbol::sym::rustc_test_marker)
524533
}
525534

526535
/// Extract the test harness name from the `#[rustc_test_maker]`
527-
pub fn test_harness_name(tcx: TyCtxt, def_id: DefId) -> String {
536+
pub fn test_harness_name(tcx: TyCtxt, def: &impl CrateDef) -> String {
537+
let def_id = rustc_internal::internal(def.def_id());
528538
let attrs = tcx.get_attrs_unchecked(def_id);
529539
let marker = attr::find_by_name(attrs, rustc_span::symbol::sym::rustc_test_marker).unwrap();
530540
parse_str_value(&marker).unwrap()

kani-compiler/src/kani_middle/metadata.rs

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,30 @@ use std::path::Path;
77

88
use crate::kani_middle::attributes::test_harness_name;
99
use kani_metadata::{ArtifactType, HarnessAttributes, HarnessMetadata};
10-
use rustc_hir::def_id::DefId;
11-
use rustc_middle::ty::{Instance, InstanceDef, TyCtxt};
10+
use rustc_middle::ty::TyCtxt;
11+
use stable_mir::mir::mono::Instance;
12+
use stable_mir::CrateDef;
1213

1314
use super::{attributes::KaniAttributes, SourceLocation};
1415

1516
/// Create the harness metadata for a proof harness for a given function.
16-
pub fn gen_proof_metadata(tcx: TyCtxt, def_id: DefId, base_name: &Path) -> HarnessMetadata {
17-
let attributes = KaniAttributes::for_item(tcx, def_id).harness_attributes();
18-
let pretty_name = tcx.def_path_str(def_id);
17+
pub fn gen_proof_metadata(tcx: TyCtxt, instance: Instance, base_name: &Path) -> HarnessMetadata {
18+
let def = instance.def;
19+
let attributes = KaniAttributes::for_instance(tcx, instance).harness_attributes();
20+
let pretty_name = instance.name();
1921
// Main function a special case in order to support `--function main`
2022
// TODO: Get rid of this: https://github.com/model-checking/kani/issues/2129
21-
let mangled_name = if pretty_name == "main" {
22-
pretty_name.clone()
23-
} else {
24-
tcx.symbol_name(Instance::mono(tcx, def_id)).to_string()
25-
};
23+
let mangled_name =
24+
if pretty_name == "main" { pretty_name.clone() } else { instance.mangled_name() };
2625

27-
let body = tcx.instance_mir(InstanceDef::Item(def_id));
28-
let loc = SourceLocation::new(tcx, &body.span);
26+
let loc = SourceLocation::new(&instance.def.span());
2927
let file_stem = format!("{}_{mangled_name}", base_name.file_stem().unwrap().to_str().unwrap());
3028
let model_file = base_name.with_file_name(file_stem).with_extension(ArtifactType::SymTabGoto);
3129

3230
HarnessMetadata {
3331
pretty_name,
3432
mangled_name,
35-
crate_name: tcx.crate_name(def_id.krate).to_string(),
33+
crate_name: def.krate().name,
3634
original_file: loc.filename,
3735
original_start_line: loc.start_line,
3836
original_end_line: loc.end_line,
@@ -44,23 +42,22 @@ pub fn gen_proof_metadata(tcx: TyCtxt, def_id: DefId, base_name: &Path) -> Harne
4442

4543
/// Create the harness metadata for a test description.
4644
#[allow(dead_code)]
47-
pub fn gen_test_metadata<'tcx>(
48-
tcx: TyCtxt<'tcx>,
49-
test_desc: DefId,
50-
test_fn: Instance<'tcx>,
45+
pub fn gen_test_metadata(
46+
tcx: TyCtxt,
47+
test_desc: impl CrateDef,
48+
test_fn: Instance,
5149
base_name: &Path,
5250
) -> HarnessMetadata {
53-
let pretty_name = test_harness_name(tcx, test_desc);
54-
let mangled_name = tcx.symbol_name(test_fn).to_string();
55-
let body = tcx.instance_mir(InstanceDef::Item(test_desc));
56-
let loc = SourceLocation::new(tcx, &body.span);
51+
let pretty_name = test_harness_name(tcx, &test_desc);
52+
let mangled_name = test_fn.mangled_name();
53+
let loc = SourceLocation::new(&test_desc.span());
5754
let file_stem = format!("{}_{mangled_name}", base_name.file_stem().unwrap().to_str().unwrap());
5855
let model_file = base_name.with_file_name(file_stem).with_extension(ArtifactType::SymTabGoto);
5956

6057
HarnessMetadata {
6158
pretty_name,
6259
mangled_name,
63-
crate_name: tcx.crate_name(test_desc.krate).to_string(),
60+
crate_name: test_desc.krate().name,
6461
original_file: loc.filename,
6562
original_start_line: loc.start_line,
6663
original_end_line: loc.end_line,

0 commit comments

Comments
 (0)