augment MIR pretty printer to print scopes
This commit is contained in:
parent
caac0b969f
commit
d32bde3311
3 changed files with 91 additions and 12 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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))?;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue