@@ -18,16 +18,20 @@ use rustc_hir::def::DefKind;
18
18
use rustc_metadata:: EncodedMetadata ;
19
19
use rustc_middle:: dep_graph:: { WorkProduct , WorkProductId } ;
20
20
use rustc_middle:: mir:: mono:: { CodegenUnit , MonoItem } ;
21
+ use rustc_middle:: mir:: write_mir_pretty;
21
22
use rustc_middle:: ty:: query:: Providers ;
22
- use rustc_middle:: ty:: { self , TyCtxt } ;
23
+ use rustc_middle:: ty:: { self , InstanceDef , TyCtxt } ;
23
24
use rustc_session:: config:: { OutputFilenames , OutputType } ;
24
25
use rustc_session:: cstore:: MetadataLoaderDyn ;
25
26
use rustc_session:: Session ;
27
+ use rustc_span:: def_id:: DefId ;
26
28
use rustc_target:: abi:: Endian ;
27
29
use rustc_target:: spec:: PanicStrategy ;
28
30
use std:: collections:: BTreeMap ;
29
31
use std:: fmt:: Write ;
32
+ use std:: fs:: File ;
30
33
use std:: io:: BufWriter ;
34
+ use std:: io:: Write as IoWrite ;
31
35
use std:: iter:: FromIterator ;
32
36
use std:: path:: Path ;
33
37
use std:: process:: Command ;
@@ -74,6 +78,7 @@ impl CodegenBackend for GotocCodegenBackend {
74
78
// There's nothing to do.
75
79
return codegen_results ( tcx, rustc_metadata, gcx. symbol_table . machine_model ( ) ) ;
76
80
}
81
+ dump_mir_items ( tcx, & items) ;
77
82
78
83
// we first declare all items
79
84
for item in & items {
@@ -299,7 +304,7 @@ where
299
304
{
300
305
let filename = base_filename. with_extension ( extension) ;
301
306
debug ! ( "output to {:?}" , filename) ;
302
- let out_file = :: std :: fs :: File :: create ( & filename) . unwrap ( ) ;
307
+ let out_file = File :: create ( & filename) . unwrap ( ) ;
303
308
let writer = BufWriter :: new ( out_file) ;
304
309
if pretty {
305
310
serde_json:: to_writer_pretty ( writer, & source) . unwrap ( ) ;
@@ -357,7 +362,6 @@ fn codegen_results(
357
362
///
358
363
/// To be implemented:
359
364
/// - PubFns: Cross-crate reachability analysis that use the local public fns as starting point.
360
-
361
365
fn collect_codegen_items < ' tcx > ( gcx : & GotocCtx < ' tcx > ) -> Vec < MonoItem < ' tcx > > {
362
366
let tcx = gcx. tcx ;
363
367
let reach = gcx. queries . get_reachability_analysis ( ) ;
@@ -419,3 +423,39 @@ fn symbol_table_to_gotoc(tcx: &TyCtxt, file: &Path) {
419
423
tcx. sess . abort_if_errors ( ) ;
420
424
}
421
425
}
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