allow dumping intermediate IR with -Z dump-mir

This commit is contained in:
Niko Matsakis 2016-03-22 16:05:28 -04:00
parent 0d93989cf5
commit a61c1759c7
5 changed files with 78 additions and 2 deletions

View File

@ -663,6 +663,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"print the result of the translation item collection pass"),
mir_opt_level: Option<usize> = (None, parse_opt_uint,
"set the MIR optimization level (0-3)"),
dump_mir: Option<String> = (None, parse_opt_string,
"dump MIR state at various points in translation"),
orbit: bool = (false, parse_bool,
"get MIR where it belongs - everywhere; most importantly, in orbit"),
}

View File

@ -173,6 +173,18 @@ pub fn construct<'a,'tcx>(hir: Cx<'a,'tcx>,
builder.cfg.terminate(END_BLOCK, arg_scope_id, span,
TerminatorKind::Return);
assert!(
builder.cfg.basic_blocks
.iter()
.enumerate()
.all(|(index, block)| {
if block.terminator.is_none() {
panic!("no terminator on block {:?} in {:?}",
index, argument_extent)
}
true
}));
MirPlusPlus {
mir: Mir {
basic_blocks: builder.cfg.basic_blocks,

View File

@ -22,6 +22,7 @@ extern crate rustc_front;
use build::{self, MirPlusPlus};
use rustc::dep_graph::DepNode;
use rustc::mir::repr::Mir;
use pretty;
use hair::cx::Cx;
use rustc::mir::mir_map::MirMap;
@ -182,7 +183,7 @@ fn build_mir<'a,'tcx:'a>(cx: Cx<'a,'tcx>,
let parameter_scope =
cx.tcx().region_maps.lookup_code_extent(
CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body.id });
let MirPlusPlus { mut mir, scope_auxiliary: _ } =
let MirPlusPlus { mut mir, scope_auxiliary } =
build::construct(cx,
span,
implicit_arg_tys,
@ -201,6 +202,13 @@ fn build_mir<'a,'tcx:'a>(cx: Cx<'a,'tcx>,
_ => {}
}
pretty::dump_mir(cx.tcx(),
"mir_map",
&0,
fn_id,
&mir,
Some(&scope_auxiliary));
Ok(mir)
}

View File

@ -12,12 +12,63 @@ use build::{Location, ScopeAuxiliary};
use rustc::mir::repr::*;
use rustc::middle::ty::{self, TyCtxt};
use rustc_data_structures::fnv::FnvHashMap;
use std::fmt::Display;
use std::fs;
use std::io::{self, Write};
use syntax::ast::NodeId;
use syntax::codemap::Span;
const INDENT: &'static str = " ";
/// If the session is properly configured, dumps a human-readable
/// representation of the mir into:
///
/// ```
/// rustc.node<node_id>.<pass_name>.<disambiguator>
/// ```
///
/// Output from this function is controlled by passing `-Z dump-mir=<filter>`,
/// where `<filter>` takes the following forms:
///
/// - `all` -- dump MIR for all fns, all passes, all everything
/// - `substring1&substring2,...` -- `&`-separated list of substrings
/// that can appear in the pass-name or the `item_path_str` for the given
/// node-id. If any one of the substrings match, the data is dumped out.
pub fn dump_mir<'a, 'tcx>(tcx: &TyCtxt<'tcx>,
pass_name: &str,
disambiguator: &Display,
node_id: NodeId,
mir: &Mir<'tcx>,
auxiliary: Option<&Vec<ScopeAuxiliary>>) {
let filters = match tcx.sess.opts.debugging_opts.dump_mir {
None => return,
Some(ref filters) => filters,
};
let node_path = tcx.item_path_str(tcx.map.local_def_id(node_id));
let is_matched =
filters.split("&")
.any(|filter| {
filter == "all" ||
pass_name.contains(filter) ||
node_path.contains(filter)
});
if !is_matched {
return;
}
let file_name = format!("rustc.node{}.{}.{}.mir",
node_id, pass_name, disambiguator);
let _ = fs::File::create(&file_name).and_then(|mut file| {
try!(writeln!(file, "// MIR for `{}`", node_path));
try!(writeln!(file, "// node_id = {}", node_id));
try!(writeln!(file, "// pass_name = {}", pass_name));
try!(writeln!(file, "// disambiguator = {}", disambiguator));
try!(writeln!(file, ""));
try!(write_mir_fn(tcx, node_id, mir, &mut file, auxiliary));
Ok(())
});
}
/// Write out a human-readable textual representation for the given MIR.
pub fn write_mir_pretty<'a, 'tcx, I>(tcx: &TyCtxt<'tcx>,
iter: I,
@ -117,7 +168,7 @@ fn write_basic_block(tcx: &TyCtxt,
// Terminator at the bottom.
writeln!(w, "{0}{0}{1:?}; // {2}",
INDENT,
data.terminator(),
data.terminator().kind,
comment(tcx, data.terminator().scope, data.terminator().span))?;
writeln!(w, "{}}}", INDENT)

View File

@ -30,6 +30,7 @@ impl SimplifyCfg {
let mut seen: Vec<BasicBlock> = Vec::with_capacity(8);
while mir.basic_block_data(target).statements.is_empty() {
debug!("final_target: target={:?}", target);
match mir.basic_block_data(target).terminator().kind {
TerminatorKind::Goto { target: next } => {
if seen.contains(&next) {
@ -51,6 +52,8 @@ impl SimplifyCfg {
let mut terminator = mir.basic_block_data_mut(bb).terminator.take()
.expect("invalid terminator state");
debug!("remove_goto_chains: bb={:?} terminator={:?}", bb, terminator);
for target in terminator.successors_mut() {
let new_target = match final_target(mir, *target) {
Some(new_target) => new_target,