Skip to content

Commit a61c175

Browse files
committed
allow dumping intermediate IR with -Z dump-mir
1 parent 0d93989 commit a61c175

File tree

5 files changed

+78
-2
lines changed

5 files changed

+78
-2
lines changed

src/librustc/session/config.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
663663
"print the result of the translation item collection pass"),
664664
mir_opt_level: Option<usize> = (None, parse_opt_uint,
665665
"set the MIR optimization level (0-3)"),
666+
dump_mir: Option<String> = (None, parse_opt_string,
667+
"dump MIR state at various points in translation"),
666668
orbit: bool = (false, parse_bool,
667669
"get MIR where it belongs - everywhere; most importantly, in orbit"),
668670
}

src/librustc_mir/build/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,18 @@ pub fn construct<'a,'tcx>(hir: Cx<'a,'tcx>,
173173
builder.cfg.terminate(END_BLOCK, arg_scope_id, span,
174174
TerminatorKind::Return);
175175

176+
assert!(
177+
builder.cfg.basic_blocks
178+
.iter()
179+
.enumerate()
180+
.all(|(index, block)| {
181+
if block.terminator.is_none() {
182+
panic!("no terminator on block {:?} in {:?}",
183+
index, argument_extent)
184+
}
185+
true
186+
}));
187+
176188
MirPlusPlus {
177189
mir: Mir {
178190
basic_blocks: builder.cfg.basic_blocks,

src/librustc_mir/mir_map.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ extern crate rustc_front;
2222
use build::{self, MirPlusPlus};
2323
use rustc::dep_graph::DepNode;
2424
use rustc::mir::repr::Mir;
25+
use pretty;
2526
use hair::cx::Cx;
2627

2728
use rustc::mir::mir_map::MirMap;
@@ -182,7 +183,7 @@ fn build_mir<'a,'tcx:'a>(cx: Cx<'a,'tcx>,
182183
let parameter_scope =
183184
cx.tcx().region_maps.lookup_code_extent(
184185
CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body.id });
185-
let MirPlusPlus { mut mir, scope_auxiliary: _ } =
186+
let MirPlusPlus { mut mir, scope_auxiliary } =
186187
build::construct(cx,
187188
span,
188189
implicit_arg_tys,
@@ -201,6 +202,13 @@ fn build_mir<'a,'tcx:'a>(cx: Cx<'a,'tcx>,
201202
_ => {}
202203
}
203204

205+
pretty::dump_mir(cx.tcx(),
206+
"mir_map",
207+
&0,
208+
fn_id,
209+
&mir,
210+
Some(&scope_auxiliary));
211+
204212
Ok(mir)
205213
}
206214

src/librustc_mir/pretty.rs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,63 @@ use build::{Location, ScopeAuxiliary};
1212
use rustc::mir::repr::*;
1313
use rustc::middle::ty::{self, TyCtxt};
1414
use rustc_data_structures::fnv::FnvHashMap;
15+
use std::fmt::Display;
16+
use std::fs;
1517
use std::io::{self, Write};
1618
use syntax::ast::NodeId;
1719
use syntax::codemap::Span;
1820

1921
const INDENT: &'static str = " ";
2022

23+
/// If the session is properly configured, dumps a human-readable
24+
/// representation of the mir into:
25+
///
26+
/// ```
27+
/// rustc.node<node_id>.<pass_name>.<disambiguator>
28+
/// ```
29+
///
30+
/// Output from this function is controlled by passing `-Z dump-mir=<filter>`,
31+
/// where `<filter>` takes the following forms:
32+
///
33+
/// - `all` -- dump MIR for all fns, all passes, all everything
34+
/// - `substring1&substring2,...` -- `&`-separated list of substrings
35+
/// that can appear in the pass-name or the `item_path_str` for the given
36+
/// node-id. If any one of the substrings match, the data is dumped out.
37+
pub fn dump_mir<'a, 'tcx>(tcx: &TyCtxt<'tcx>,
38+
pass_name: &str,
39+
disambiguator: &Display,
40+
node_id: NodeId,
41+
mir: &Mir<'tcx>,
42+
auxiliary: Option<&Vec<ScopeAuxiliary>>) {
43+
let filters = match tcx.sess.opts.debugging_opts.dump_mir {
44+
None => return,
45+
Some(ref filters) => filters,
46+
};
47+
let node_path = tcx.item_path_str(tcx.map.local_def_id(node_id));
48+
let is_matched =
49+
filters.split("&")
50+
.any(|filter| {
51+
filter == "all" ||
52+
pass_name.contains(filter) ||
53+
node_path.contains(filter)
54+
});
55+
if !is_matched {
56+
return;
57+
}
58+
59+
let file_name = format!("rustc.node{}.{}.{}.mir",
60+
node_id, pass_name, disambiguator);
61+
let _ = fs::File::create(&file_name).and_then(|mut file| {
62+
try!(writeln!(file, "// MIR for `{}`", node_path));
63+
try!(writeln!(file, "// node_id = {}", node_id));
64+
try!(writeln!(file, "// pass_name = {}", pass_name));
65+
try!(writeln!(file, "// disambiguator = {}", disambiguator));
66+
try!(writeln!(file, ""));
67+
try!(write_mir_fn(tcx, node_id, mir, &mut file, auxiliary));
68+
Ok(())
69+
});
70+
}
71+
2172
/// Write out a human-readable textual representation for the given MIR.
2273
pub fn write_mir_pretty<'a, 'tcx, I>(tcx: &TyCtxt<'tcx>,
2374
iter: I,
@@ -117,7 +168,7 @@ fn write_basic_block(tcx: &TyCtxt,
117168
// Terminator at the bottom.
118169
writeln!(w, "{0}{0}{1:?}; // {2}",
119170
INDENT,
120-
data.terminator(),
171+
data.terminator().kind,
121172
comment(tcx, data.terminator().scope, data.terminator().span))?;
122173

123174
writeln!(w, "{}}}", INDENT)

src/librustc_mir/transform/simplify_cfg.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ impl SimplifyCfg {
3030
let mut seen: Vec<BasicBlock> = Vec::with_capacity(8);
3131

3232
while mir.basic_block_data(target).statements.is_empty() {
33+
debug!("final_target: target={:?}", target);
3334
match mir.basic_block_data(target).terminator().kind {
3435
TerminatorKind::Goto { target: next } => {
3536
if seen.contains(&next) {
@@ -51,6 +52,8 @@ impl SimplifyCfg {
5152
let mut terminator = mir.basic_block_data_mut(bb).terminator.take()
5253
.expect("invalid terminator state");
5354

55+
debug!("remove_goto_chains: bb={:?} terminator={:?}", bb, terminator);
56+
5457
for target in terminator.successors_mut() {
5558
let new_target = match final_target(mir, *target) {
5659
Some(new_target) => new_target,

0 commit comments

Comments
 (0)