"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"),
}
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;
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,
_ => {}
}
+ pretty::dump_mir(cx.tcx(),
+ "mir_map",
+ &0,
+ fn_id,
+ &mir,
+ Some(&scope_auxiliary));
+
Ok(mir)
}
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,
// 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)
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) {
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,