about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2016-03-22 10:08:44 -0400
committerNiko Matsakis <niko@alum.mit.edu>2016-03-23 16:42:52 -0400
commitd32bde3311a035f2a0d7c26cf3170cf98860d701 (patch)
treee6bada2a08585c31afb9628c1b93f3f4213d371e
parentcaac0b969fd888014c3ff80238d8a00c6eae4feb (diff)
downloadrust-d32bde3311a035f2a0d7c26cf3170cf98860d701.tar.gz
rust-d32bde3311a035f2a0d7c26cf3170cf98860d701.zip
augment MIR pretty printer to print scopes
-rw-r--r--src/librustc/mir/repr.rs4
-rw-r--r--src/librustc_mir/build/mod.rs1
-rw-r--r--src/librustc_mir/pretty.rs98
3 files changed, 91 insertions, 12 deletions
diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs
index cc95d5946a8..a1688e1464c 100644
--- a/src/librustc/mir/repr.rs
+++ b/src/librustc/mir/repr.rs
@@ -197,7 +197,7 @@ pub struct ArgDecl<'tcx> {
 /// list of the `Mir`.
 ///
 /// (We use a `u32` internally just to save memory.)
-#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
 pub struct BasicBlock(u32);
 
 impl BasicBlock {
@@ -668,7 +668,7 @@ impl IndexMut<ScopeId> for ScopeDataVec {
     }
 }
 
-#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, RustcEncodable, RustcDecodable)]
 pub struct ScopeId(u32);
 
 impl ScopeId {
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index 416c078f4a9..f2def53d4ea 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -73,6 +73,7 @@ pub struct ScopeAuxiliary {
     pub postdoms: Vec<Location>,
 }
 
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
 pub struct Location {
     /// the location is within this block
     pub block: BasicBlock,
diff --git a/src/librustc_mir/pretty.rs b/src/librustc_mir/pretty.rs
index 0f1891bf37b..813766d60c6 100644
--- a/src/librustc_mir/pretty.rs
+++ b/src/librustc_mir/pretty.rs
@@ -8,60 +8,138 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use build::Location;
 use rustc::mir::repr::*;
-use rustc::middle::ty;
+use rustc::middle::ty::{self, TyCtxt};
+use rustc_data_structures::fnv::FnvHashMap;
 use std::io::{self, Write};
 use syntax::ast::NodeId;
+use syntax::codemap::Span;
 
 const INDENT: &'static str = "    ";
 
 /// Write out a human-readable textual representation for the given MIR.
-pub fn write_mir_pretty<'a, 'tcx, I>(tcx: &ty::TyCtxt<'tcx>,
+pub fn write_mir_pretty<'a, 'tcx, I>(tcx: &TyCtxt<'tcx>,
                                      iter: I,
                                      w: &mut Write)
                                      -> io::Result<()>
     where I: Iterator<Item=(&'a NodeId, &'a Mir<'tcx>)>, 'tcx: 'a
 {
+    let no_annotations = FnvHashMap();
     for (&node_id, mir) in iter {
-        write_mir_fn(tcx, node_id, mir, w)?;
+        write_mir_fn(tcx, node_id, mir, w, &no_annotations)?;
     }
     Ok(())
 }
 
-pub fn write_mir_fn<'tcx>(tcx: &ty::TyCtxt<'tcx>,
+pub enum Annotation {
+    EnterScope(ScopeId),
+    ExitScope(ScopeId),
+}
+
+pub fn write_mir_fn<'tcx>(tcx: &TyCtxt<'tcx>,
                           node_id: NodeId,
                           mir: &Mir<'tcx>,
-                          w: &mut Write)
+                          w: &mut Write,
+                          annotations: &FnvHashMap<Location, Vec<Annotation>>)
                           -> io::Result<()> {
     write_mir_intro(tcx, node_id, mir, w)?;
     for block in mir.all_basic_blocks() {
-        write_basic_block(block, mir, w)?;
+        write_basic_block(tcx, block, mir, w, annotations)?;
+    }
+
+    // construct a scope tree
+    let mut scope_tree: FnvHashMap<Option<ScopeId>, Vec<ScopeId>> = FnvHashMap();
+    for (index, scope_data) in mir.scopes.vec.iter().enumerate() {
+        scope_tree.entry(scope_data.parent_scope)
+                  .or_insert(vec![])
+                  .push(ScopeId::new(index));
     }
+    write_scope_tree(tcx, mir, &scope_tree, w, None, 1)?;
+
     writeln!(w, "}}")?;
     Ok(())
 }
 
 /// Write out a human-readable textual representation for the given basic block.
-fn write_basic_block(block: BasicBlock, mir: &Mir, w: &mut Write) -> io::Result<()> {
+fn write_basic_block(tcx: &TyCtxt,
+                     block: BasicBlock,
+                     mir: &Mir,
+                     w: &mut Write,
+                     annotations: &FnvHashMap<Location, Vec<Annotation>>)
+                     -> io::Result<()> {
     let data = mir.basic_block_data(block);
 
     // Basic block label at the top.
     writeln!(w, "\n{}{:?}: {{", INDENT, block)?;
 
     // List of statements in the middle.
+    let mut current_location = Location { block: block, statement_index: 0 };
     for statement in &data.statements {
-        writeln!(w, "{0}{0}{1:?};", INDENT, statement)?;
+        if let Some(ref annotations) = annotations.get(&current_location) {
+            for annotation in annotations.iter() {
+                match *annotation {
+                    Annotation::EnterScope(id) =>
+                        writeln!(w, "{0}{0}// Enter Scope({1})",
+                                 INDENT, id.index())?,
+                    Annotation::ExitScope(id) =>
+                        writeln!(w, "{0}{0}// Exit Scope({1})",
+                                 INDENT, id.index())?,
+                }
+            }
+        }
+
+        writeln!(w, "{0}{0}{1:?}; // {2}",
+                 INDENT,
+                 statement,
+                 comment(tcx, statement.scope, statement.span))?;
+
+        current_location.statement_index += 1;
     }
 
     // Terminator at the bottom.
-    writeln!(w, "{0}{0}{1:?};", INDENT, data.terminator())?;
+    writeln!(w, "{0}{0}{1:?}; // {2}",
+             INDENT,
+             data.terminator(),
+             comment(tcx, data.terminator().scope, data.terminator().span))?;
 
     writeln!(w, "{}}}", INDENT)
 }
 
+fn comment(tcx: &TyCtxt,
+           scope: ScopeId,
+           span: Span)
+           -> String {
+    format!("Scope({}) at {}", scope.index(), tcx.sess.codemap().span_to_string(span))
+}
+
+fn write_scope_tree(tcx: &TyCtxt,
+                    mir: &Mir,
+                    scope_tree: &FnvHashMap<Option<ScopeId>, Vec<ScopeId>>,
+                    w: &mut Write,
+                    parent: Option<ScopeId>,
+                    depth: usize)
+                    -> io::Result<()> {
+    for &child in scope_tree.get(&parent).unwrap_or(&vec![]) {
+        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())?;
+        let indent = indent + INDENT.len();
+        if let Some(parent) = parent {
+            writeln!(w, "{0:1$}Parent: Scope({2})", "", indent, parent.index())?;
+        }
+        writeln!(w, "{0:1$}Extent: {2:?}",
+                 "", indent,
+                 tcx.region_maps.code_extent_data(data.extent))?;
+        write_scope_tree(tcx, mir, scope_tree, w, Some(child), depth + 1)?;
+    }
+    Ok(())
+}
+
 /// Write out a human-readable textual representation of the MIR's `fn` type and the types of its
 /// local variables (both user-defined bindings and compiler temporaries).
-fn write_mir_intro(tcx: &ty::TyCtxt, nid: NodeId, mir: &Mir, w: &mut Write)
+fn write_mir_intro(tcx: &TyCtxt, nid: NodeId, mir: &Mir, w: &mut Write)
                    -> io::Result<()> {
     write!(w, "fn {}(", tcx.map.path_to_string(nid))?;