diff options
| author | Scott Olson <scott@solson.me> | 2015-12-29 20:06:19 -0600 |
|---|---|---|
| committer | Scott Olson <scott@solson.me> | 2016-01-04 16:11:32 -0600 |
| commit | 661976cbd1ca3f9cd32d60cc0c48d9b291d7887f (patch) | |
| tree | 7f7149d380c5c6ae2297b238c2b36864f80345b2 | |
| parent | badc23b6ad47c6b6d401a3ea1dc5163bdcd86cd7 (diff) | |
| download | rust-661976cbd1ca3f9cd32d60cc0c48d9b291d7887f.tar.gz rust-661976cbd1ca3f9cd32d60cc0c48d9b291d7887f.zip | |
Add a human-readable textual form for MIR.
This can be dumped for a particular `fn` with the attribute `#![rustc_mir(pretty = "filename.mir"]`.
| -rw-r--r-- | src/librustc_mir/lib.rs | 6 | ||||
| -rw-r--r-- | src/librustc_mir/mir_map.rs | 29 | ||||
| -rw-r--r-- | src/librustc_mir/pretty.rs | 85 |
3 files changed, 103 insertions, 17 deletions
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 6a1134385d9..9cc40bbc383 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -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; - diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs index 5c9399ebdad..a3ca4c05456 100644 --- a/src/librustc_mir/mir_map.rs +++ b/src/librustc_mir/mir_map.rs @@ -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())); } } } diff --git a/src/librustc_mir/pretty.rs b/src/librustc_mir/pretty.rs new file mode 100644 index 00000000000..1251154891b --- /dev/null +++ b/src/librustc_mir/pretty.rs @@ -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(()) +} |
