allow dumping intermediate IR with -Z dump-mir
This commit is contained in:
parent
0d93989cf5
commit
a61c1759c7
|
@ -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"),
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue