Add a human-readable textual form for MIR.
This can be dumped for a particular `fn` with the attribute `#![rustc_mir(pretty = "filename.mir"]`.
This commit is contained in:
parent
badc23b6ad
commit
661976cbd1
3 changed files with 103 additions and 17 deletions
|
|
@ -29,8 +29,8 @@ extern crate rustc_back;
|
|||
extern crate syntax;
|
||||
|
||||
pub mod build;
|
||||
pub mod mir_map;
|
||||
pub mod graphviz;
|
||||
mod hair;
|
||||
mod graphviz;
|
||||
pub mod mir_map;
|
||||
pub mod pretty;
|
||||
pub mod transform;
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ extern crate rustc_front;
|
|||
|
||||
use build;
|
||||
use graphviz;
|
||||
use pretty;
|
||||
use transform::*;
|
||||
use rustc::mir::repr::Mir;
|
||||
use hair::cx::Cx;
|
||||
|
|
@ -152,29 +153,29 @@ impl<'a, 'm, 'tcx> Visitor<'tcx> for InnerDump<'a,'m,'tcx> {
|
|||
.flat_map(|a| a.meta_item_list())
|
||||
.flat_map(|l| l.iter());
|
||||
for item in meta_item_list {
|
||||
if item.check_name("graphviz") {
|
||||
if item.check_name("graphviz") || item.check_name("pretty") {
|
||||
match item.value_str() {
|
||||
Some(s) => {
|
||||
match
|
||||
File::create(format!("{}{}", prefix, s))
|
||||
.and_then(|ref mut output| {
|
||||
let filename = format!("{}{}", prefix, s);
|
||||
let result = File::create(&filename).and_then(|ref mut output| {
|
||||
if item.check_name("graphviz") {
|
||||
graphviz::write_mir_graphviz(&mir, output)
|
||||
})
|
||||
{
|
||||
Ok(()) => { }
|
||||
Err(e) => {
|
||||
self.tcx.sess.span_fatal(
|
||||
item.span,
|
||||
&format!("Error writing graphviz \
|
||||
results to `{}`: {}",
|
||||
s, e));
|
||||
} else {
|
||||
pretty::write_mir_pretty(&mir, output)
|
||||
}
|
||||
});
|
||||
|
||||
if let Err(e) = result {
|
||||
self.tcx.sess.span_fatal(
|
||||
item.span,
|
||||
&format!("Error writing MIR {} results to `{}`: {}",
|
||||
item.name(), filename, e));
|
||||
}
|
||||
}
|
||||
None => {
|
||||
self.tcx.sess.span_err(
|
||||
item.span,
|
||||
"graphviz attribute requires a path");
|
||||
&format!("{} attribute requires a path", item.name()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
85
src/librustc_mir/pretty.rs
Normal file
85
src/librustc_mir/pretty.rs
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use rustc::mir::repr::*;
|
||||
use rustc::middle::ty;
|
||||
use std::io::{self, Write};
|
||||
|
||||
const INDENT: &'static str = " ";
|
||||
|
||||
/// Write out a human-readable textual representation for the given MIR.
|
||||
pub fn write_mir_pretty<W: Write>(mir: &Mir, w: &mut W) -> io::Result<()> {
|
||||
try!(write_mir_intro(mir, w));
|
||||
|
||||
// Nodes
|
||||
for block in mir.all_basic_blocks() {
|
||||
try!(write_basic_block(block, mir, w));
|
||||
}
|
||||
|
||||
writeln!(w, "}}")
|
||||
}
|
||||
|
||||
/// Write out a human-readable textual representation for the given basic block.
|
||||
fn write_basic_block<W: Write>(block: BasicBlock, mir: &Mir, w: &mut W) -> io::Result<()> {
|
||||
let data = mir.basic_block_data(block);
|
||||
|
||||
// Basic block label at the top.
|
||||
try!(writeln!(w, "\n{}{:?}: {{", INDENT, block));
|
||||
|
||||
// List of statements in the middle.
|
||||
for statement in &data.statements {
|
||||
try!(writeln!(w, "{0}{0}{1:?};", INDENT, statement));
|
||||
}
|
||||
|
||||
// Terminator at the bottom.
|
||||
try!(writeln!(w, "{0}{0}{1:?};", INDENT, data.terminator));
|
||||
|
||||
writeln!(w, "{}}}", INDENT)
|
||||
}
|
||||
|
||||
/// 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<W: Write>(mir: &Mir, w: &mut W) -> io::Result<()> {
|
||||
try!(write!(w, "fn("));
|
||||
|
||||
// fn argument types.
|
||||
for (i, arg) in mir.arg_decls.iter().enumerate() {
|
||||
if i > 0 {
|
||||
try!(write!(w, ", "));
|
||||
}
|
||||
try!(write!(w, "{:?}: {}", Lvalue::Arg(i as u32), arg.ty));
|
||||
}
|
||||
|
||||
try!(write!(w, ") -> "));
|
||||
|
||||
// fn return type.
|
||||
match mir.return_ty {
|
||||
ty::FnOutput::FnConverging(ty) => try!(write!(w, "{}", ty)),
|
||||
ty::FnOutput::FnDiverging => try!(write!(w, "!")),
|
||||
}
|
||||
|
||||
try!(writeln!(w, " {{"));
|
||||
|
||||
// User variable types (including the user's name in a comment).
|
||||
for (i, var) in mir.var_decls.iter().enumerate() {
|
||||
try!(write!(w, "{}let ", INDENT));
|
||||
if var.mutability == Mutability::Mut {
|
||||
try!(write!(w, "mut "));
|
||||
}
|
||||
try!(writeln!(w, "{:?}: {}; // {}", Lvalue::Var(i as u32), var.ty, var.name));
|
||||
}
|
||||
|
||||
// Compiler-introduced temporary types.
|
||||
for (i, temp) in mir.temp_decls.iter().enumerate() {
|
||||
try!(writeln!(w, "{}let {:?}: {};", INDENT, Lvalue::Temp(i as u32), temp.ty));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue