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:
-> 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)?;
}
}
.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, "}}")?;
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 };
}
}
- 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,
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;
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(())
}
// 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))?;
}
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(())
}