about summary refs log tree commit diff
diff options
context:
space:
mode:
authorScott Olson <scott@solson.me>2015-12-29 20:06:19 -0600
committerScott Olson <scott@solson.me>2016-01-04 16:11:32 -0600
commit661976cbd1ca3f9cd32d60cc0c48d9b291d7887f (patch)
tree7f7149d380c5c6ae2297b238c2b36864f80345b2
parentbadc23b6ad47c6b6d401a3ea1dc5163bdcd86cd7 (diff)
downloadrust-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.rs6
-rw-r--r--src/librustc_mir/mir_map.rs29
-rw-r--r--src/librustc_mir/pretty.rs85
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(())
+}