about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-05-15 01:14:10 -0700
committerbors <bors@rust-lang.org>2016-05-15 01:14:10 -0700
commit1a26d2364f9da1667ca0098d3cc4a213d131f481 (patch)
tree2b3314160aaced7d8bc0c7bbb7ed34cd3016e1dc
parent088d4178522d4e9464c6beac70b14724670ee735 (diff)
parent2c7e398935fe10aa2adea453ca0a2251b3c387e8 (diff)
Auto merge of #33607 - jonas-schievink:prettier-mir, r=eddyb
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

In action: https://gist.github.com/jonas-schievink/1c11226cbb112892a9470ce0f9870b65
-rw-r--r--src/librustc_mir/pretty.rs110
1 files changed, 84 insertions, 26 deletions
diff --git a/src/librustc_mir/pretty.rs b/src/librustc_mir/pretty.rs
index bf6689de236..fb29cbd5fa8 100644
--- a/src/librustc_mir/pretty.rs
+++ b/src/librustc_mir/pretty.rs
@@ -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 = 40;
 
 /// 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,7 +142,10 @@ pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                   .or_insert(vec![])
                   .push(ScopeId::new(index));
     }
-    write_scope_tree(tcx, mir, auxiliary, &scope_tree, w, None, 1)?;
+
+    writeln!(w, "{}scope tree:", INDENT)?;
+    write_scope_tree(tcx, mir, auxiliary, &scope_tree, w, None, 1, false)?;
+    writeln!(w, "")?;
 
     writeln!(w, "}}")?;
     Ok(())
@@ -147,7 +161,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 +179,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,
@@ -192,18 +208,32 @@ fn write_scope_tree(tcx: TyCtxt,
                     scope_tree: &FnvHashMap<Option<ScopeId>, Vec<ScopeId>>,
                     w: &mut Write,
                     parent: Option<ScopeId>,
-                    depth: usize)
+                    depth: usize,
+                    same_line: bool)
                     -> io::Result<()> {
-    for &child in scope_tree.get(&parent).unwrap_or(&vec![]) {
-        let indent = depth * INDENT.len();
+    let indent = if same_line {
+        0
+    } else {
+        depth * INDENT.len()
+    };
+
+    let children = match scope_tree.get(&parent) {
+        Some(childs) => childs,
+        None => return Ok(()),
+    };
+
+    for (index, &child) in children.iter().enumerate() {
+        if index == 0 && same_line {
+            // We know we're going to output a scope, so prefix it with a space to separate it from
+            // the previous scopes on this line
+            write!(w, " ")?;
+        }
+
         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 +241,25 @@ 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)?;
+        let child_count = scope_tree.get(&Some(child)).map(Vec::len).unwrap_or(0);
+        if child_count < 2 {
+            // Skip the braces when there's no or only a single subscope
+            write_scope_tree(tcx, mir, auxiliary, scope_tree, w,
+                             Some(child), depth, true)?;
+        } else {
+            // 2 or more child scopes? Put them in braces and on new lines.
+            writeln!(w, " {{")?;
+            write_scope_tree(tcx, mir, auxiliary, scope_tree, w,
+                             Some(child), depth + 1, false)?;
+
+            write!(w, "\n{0:1$}}}", "", depth * INDENT.len())?;
+        }
+
+        if !same_line && index + 1 < children.len() {
+            writeln!(w, "")?;
+        }
     }
+
     Ok(())
 }
 
@@ -261,13 +307,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 +330,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(())
 }