Some simple improvements to MIR pretty printing

In short, this PR changes the MIR printer so that it:

* places an empty line between the MIR for each item
* does *not* write an empty line before the first BB when there are no
  var decls
* aligns the "// Scope" comments 50 chars in (makes the output more
  readable)
* prints the scope comments as "// scope N at ..." instead of "//
  Scope(N) at ..."
* prints a prettier scope tree:
 * no more unbalanced delimiters!
 * no more "Parent" entry (these convey no useful information)
 * drop the "Scope()" and just print scope IDs
 * no braces when the scope is empty
This commit is contained in:
Jonas Schievink 2016-05-13 00:20:59 +02:00
parent e88defe718
commit 96b178b131

View file

@ -21,6 +21,8 @@ use syntax::ast::NodeId;
use syntax::codemap::Span;
const INDENT: &'static str = " ";
/// Alignment for lining up comments following MIR statements
const ALIGN: usize = 50;
/// If the session is properly configured, dumps a human-readable
/// representation of the mir into:
@ -79,11 +81,20 @@ pub fn write_mir_pretty<'a, 'b, 'tcx, I>(tcx: TyCtxt<'b, 'tcx, 'tcx>,
-> io::Result<()>
where I: Iterator<Item=(&'a NodeId, &'a Mir<'tcx>)>, 'tcx: 'a
{
let mut first = true;
for (&id, mir) in iter {
if first {
first = false;
} else {
// Put empty lines between all items
writeln!(w, "")?;
}
let src = MirSource::from_node(tcx, id);
write_mir_fn(tcx, src, mir, w, None)?;
for (i, mir) in mir.promoted.iter().enumerate() {
writeln!(w, "")?;
write_mir_fn(tcx, MirSource::Promoted(id, i), mir, w, None)?;
}
}
@ -131,6 +142,8 @@ pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
.or_insert(vec![])
.push(ScopeId::new(index));
}
writeln!(w, "{}scope tree:", INDENT)?;
write_scope_tree(tcx, mir, auxiliary, &scope_tree, w, None, 1)?;
writeln!(w, "}}")?;
@ -147,7 +160,7 @@ fn write_basic_block(tcx: TyCtxt,
let data = mir.basic_block_data(block);
// Basic block label at the top.
writeln!(w, "\n{}{:?}: {{", INDENT, block)?;
writeln!(w, "{}{:?}: {{", INDENT, block)?;
// List of statements in the middle.
let mut current_location = Location { block: block, statement_index: 0 };
@ -165,25 +178,27 @@ fn write_basic_block(tcx: TyCtxt,
}
}
writeln!(w, "{0}{0}{1:?}; // {2}",
INDENT,
statement,
let indented_mir = format!("{0}{0}{1:?};", INDENT, statement);
writeln!(w, "{0:1$} // {2}",
indented_mir,
ALIGN,
comment(tcx, statement.scope, statement.span))?;
current_location.statement_index += 1;
}
// Terminator at the bottom.
writeln!(w, "{0}{0}{1:?}; // {2}",
INDENT,
data.terminator().kind,
let indented_terminator = format!("{0}{0}{1:?};", INDENT, data.terminator().kind);
writeln!(w, "{0:1$} // {2}",
indented_terminator,
ALIGN,
comment(tcx, data.terminator().scope, data.terminator().span))?;
writeln!(w, "{}}}", INDENT)
writeln!(w, "{}}}\n", INDENT)
}
fn comment(tcx: TyCtxt, scope: ScopeId, span: Span) -> String {
format!("Scope({}) at {}", scope.index(), tcx.sess.codemap().span_to_string(span))
format!("scope {} at {}", scope.index(), tcx.sess.codemap().span_to_string(span))
}
fn write_scope_tree(tcx: TyCtxt,
@ -198,12 +213,9 @@ fn write_scope_tree(tcx: TyCtxt,
let indent = depth * INDENT.len();
let data = &mir.scopes[child];
assert_eq!(data.parent_scope, parent);
writeln!(w, "{0:1$}Scope({2}) {{", "", indent, child.index())?;
write!(w, "{0:1$}{2}", "", indent, child.index())?;
let indent = indent + INDENT.len();
if let Some(parent) = parent {
writeln!(w, "{0:1$}Parent: Scope({2})", "", indent, parent.index())?;
}
if let Some(auxiliary) = auxiliary {
let extent = auxiliary[child].extent;
@ -211,9 +223,18 @@ fn write_scope_tree(tcx: TyCtxt,
writeln!(w, "{0:1$}Extent: {2:?}", "", indent, data)?;
}
write_scope_tree(tcx, mir, auxiliary, scope_tree, w,
Some(child), depth + 1)?;
if scope_tree.get(&Some(child)).map(Vec::is_empty).unwrap_or(true) {
// No child scopes, skip the braces
writeln!(w, "")?;
} else {
writeln!(w, " {{")?;
write_scope_tree(tcx, mir, auxiliary, scope_tree, w,
Some(child), depth + 1)?;
writeln!(w, "{0:1$}}}", "", indent - INDENT.len())?;
}
}
Ok(())
}
@ -261,13 +282,20 @@ fn write_mir_intro<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// User variable types (including the user's name in a comment).
for (i, var) in mir.var_decls.iter().enumerate() {
write!(w, "{}let ", INDENT)?;
if var.mutability == Mutability::Mut {
write!(w, "mut ")?;
}
writeln!(w, "{:?}: {}; // {} in {}",
Lvalue::Var(i as u32),
var.ty,
let mut_str = if var.mutability == Mutability::Mut {
"mut "
} else {
""
};
let indented_var = format!("{}let {}{:?}: {};",
INDENT,
mut_str,
Lvalue::Var(i as u32),
var.ty);
writeln!(w, "{0:1$} // \"{2}\" in {3}",
indented_var,
ALIGN,
var.name,
comment(tcx, var.scope, var.span))?;
}
@ -277,5 +305,10 @@ fn write_mir_intro<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
writeln!(w, "{}let mut {:?}: {};", INDENT, Lvalue::Temp(i as u32), temp.ty)?;
}
// Wrote any declaration? Add an empty line before the first block is printed.
if !mir.var_decls.is_empty() || !mir.temp_decls.is_empty() {
writeln!(w, "")?;
}
Ok(())
}