diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2016-03-22 10:08:44 -0400 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2016-03-23 16:42:52 -0400 |
| commit | d32bde3311a035f2a0d7c26cf3170cf98860d701 (patch) | |
| tree | e6bada2a08585c31afb9628c1b93f3f4213d371e | |
| parent | caac0b969fd888014c3ff80238d8a00c6eae4feb (diff) | |
| download | rust-d32bde3311a035f2a0d7c26cf3170cf98860d701.tar.gz rust-d32bde3311a035f2a0d7c26cf3170cf98860d701.zip | |
augment MIR pretty printer to print scopes
| -rw-r--r-- | src/librustc/mir/repr.rs | 4 | ||||
| -rw-r--r-- | src/librustc_mir/build/mod.rs | 1 | ||||
| -rw-r--r-- | src/librustc_mir/pretty.rs | 98 |
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(¤t_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))?; |
