Skip to content

Commit 9bfaacf

Browse files
authored
Dump the reachable MIR (rust-lang#1750)
* Enable option to dump MIR after reachability analysis For now, we just tag along the `--emit mir` option that can be provided to rustc. We use the extension `.kani.mir` to avoid conflict with the one generated from rustc.
1 parent 3a99a1e commit 9bfaacf

File tree

2 files changed

+49
-3
lines changed

2 files changed

+49
-3
lines changed

docs/src/cheat-sheets.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ kani --keep-temps file.rs
6868
kani --gen-c file.rs
6969
```
7070

71+
```bash
72+
# Generate a ${INPUT}.kani.mir file with a human friendly MIR dump
73+
# for all items that are compiled to the respective goto-program.
74+
RUSTFLAGS="--emit mir" kani ${INPUT}.rs
75+
```
76+
7177
## CBMC
7278

7379
```bash

kani-compiler/src/codegen_cprover_gotoc/compiler_interface.rs

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,20 @@ use rustc_hir::def::DefKind;
1818
use rustc_metadata::EncodedMetadata;
1919
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
2020
use rustc_middle::mir::mono::{CodegenUnit, MonoItem};
21+
use rustc_middle::mir::write_mir_pretty;
2122
use rustc_middle::ty::query::Providers;
22-
use rustc_middle::ty::{self, TyCtxt};
23+
use rustc_middle::ty::{self, InstanceDef, TyCtxt};
2324
use rustc_session::config::{OutputFilenames, OutputType};
2425
use rustc_session::cstore::MetadataLoaderDyn;
2526
use rustc_session::Session;
27+
use rustc_span::def_id::DefId;
2628
use rustc_target::abi::Endian;
2729
use rustc_target::spec::PanicStrategy;
2830
use std::collections::BTreeMap;
2931
use std::fmt::Write;
32+
use std::fs::File;
3033
use std::io::BufWriter;
34+
use std::io::Write as IoWrite;
3135
use std::iter::FromIterator;
3236
use std::path::Path;
3337
use std::process::Command;
@@ -74,6 +78,7 @@ impl CodegenBackend for GotocCodegenBackend {
7478
// There's nothing to do.
7579
return codegen_results(tcx, rustc_metadata, gcx.symbol_table.machine_model());
7680
}
81+
dump_mir_items(tcx, &items);
7782

7883
// we first declare all items
7984
for item in &items {
@@ -299,7 +304,7 @@ where
299304
{
300305
let filename = base_filename.with_extension(extension);
301306
debug!("output to {:?}", filename);
302-
let out_file = ::std::fs::File::create(&filename).unwrap();
307+
let out_file = File::create(&filename).unwrap();
303308
let writer = BufWriter::new(out_file);
304309
if pretty {
305310
serde_json::to_writer_pretty(writer, &source).unwrap();
@@ -357,7 +362,6 @@ fn codegen_results(
357362
///
358363
/// To be implemented:
359364
/// - PubFns: Cross-crate reachability analysis that use the local public fns as starting point.
360-
361365
fn collect_codegen_items<'tcx>(gcx: &GotocCtx<'tcx>) -> Vec<MonoItem<'tcx>> {
362366
let tcx = gcx.tcx;
363367
let reach = gcx.queries.get_reachability_analysis();
@@ -419,3 +423,39 @@ fn symbol_table_to_gotoc(tcx: &TyCtxt, file: &Path) {
419423
tcx.sess.abort_if_errors();
420424
}
421425
}
426+
427+
/// Print MIR for the reachable items if the `--emit mir` option was provided to rustc.
428+
fn dump_mir_items(tcx: TyCtxt, items: &[MonoItem]) {
429+
/// Convert MonoItem into a DefId.
430+
/// Skip stuff that we cannot generate the MIR items.
431+
fn visible_item<'tcx>(item: &MonoItem<'tcx>) -> Option<(MonoItem<'tcx>, DefId)> {
432+
match item {
433+
// Exclude FnShims and others that cannot be dumped.
434+
MonoItem::Fn(instance)
435+
if matches!(
436+
instance.def,
437+
InstanceDef::FnPtrShim(..) | InstanceDef::ClosureOnceShim { .. }
438+
) =>
439+
{
440+
None
441+
}
442+
MonoItem::Fn(instance) => Some((*item, instance.def_id())),
443+
MonoItem::Static(def_id) => Some((*item, *def_id)),
444+
MonoItem::GlobalAsm(_) => None,
445+
}
446+
}
447+
448+
if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) {
449+
// Create output buffer.
450+
let outputs = tcx.output_filenames(());
451+
let path = outputs.output_path(OutputType::Mir).with_extension("kani.mir");
452+
let out_file = File::create(&path).unwrap();
453+
let mut writer = BufWriter::new(out_file);
454+
455+
// For each def_id, dump their MIR
456+
for (item, def_id) in items.iter().filter_map(visible_item) {
457+
writeln!(writer, "// Item: {:?}", item).unwrap();
458+
write_mir_pretty(tcx, Some(def_id), &mut writer).unwrap();
459+
}
460+
}
461+
}

0 commit comments

Comments
 (0)