From 9218f9772a6e7b8f55a1dbb6a347ee72d0c6eac9 Mon Sep 17 00:00:00 2001
From: Jake Goulding <jake.goulding@gmail.com>
Date: Thu, 16 Feb 2017 16:59:09 -0500
Subject: [PATCH 1/2] Teach rustc --emit=mir

---
 src/librustc/session/config.rs         |  6 ++++++
 src/librustc_driver/driver.rs          |  7 +++++++
 src/librustc_mir/transform/dump_mir.rs | 14 ++++++++++++++
 src/librustc_trans/back/write.rs       |  2 ++
 4 files changed, 29 insertions(+)

diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index d7a765fb82215..a0603c5795247 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -82,6 +82,7 @@ pub enum OutputType {
     Bitcode,
     Assembly,
     LlvmAssembly,
+    Mir,
     Metadata,
     Object,
     Exe,
@@ -96,6 +97,7 @@ impl OutputType {
             OutputType::Bitcode |
             OutputType::Assembly |
             OutputType::LlvmAssembly |
+            OutputType::Mir |
             OutputType::Object |
             OutputType::Metadata => false,
         }
@@ -106,6 +108,7 @@ impl OutputType {
             OutputType::Bitcode => "llvm-bc",
             OutputType::Assembly => "asm",
             OutputType::LlvmAssembly => "llvm-ir",
+            OutputType::Mir => "mir",
             OutputType::Object => "obj",
             OutputType::Metadata => "metadata",
             OutputType::Exe => "link",
@@ -118,6 +121,7 @@ impl OutputType {
             OutputType::Bitcode => "bc",
             OutputType::Assembly => "s",
             OutputType::LlvmAssembly => "ll",
+            OutputType::Mir => "mir",
             OutputType::Object => "o",
             OutputType::Metadata => "rmeta",
             OutputType::DepInfo => "d",
@@ -172,6 +176,7 @@ impl OutputTypes {
             OutputType::Bitcode |
             OutputType::Assembly |
             OutputType::LlvmAssembly |
+            OutputType::Mir |
             OutputType::Object |
             OutputType::Exe => true,
             OutputType::Metadata |
@@ -1370,6 +1375,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
                 let output_type = match parts.next().unwrap() {
                     "asm" => OutputType::Assembly,
                     "llvm-ir" => OutputType::LlvmAssembly,
+                    "mir" => OutputType::Mir,
                     "llvm-bc" => OutputType::Bitcode,
                     "obj" => OutputType::Object,
                     "metadata" => OutputType::Metadata,
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 2126a5a7c71bd..c1ea2b9ce41a9 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -209,6 +209,13 @@ pub fn compile_input(sess: &Session,
                 tcx.print_debug_stats();
             }
 
+            if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) {
+                if let Err(e) = mir::transform::dump_mir::emit_mir(tcx, &outputs) {
+                    sess.err(&format!("could not emit MIR: {}", e));
+                    sess.abort_if_errors();
+                }
+            }
+
             Ok((outputs, trans))
         })??
     };
diff --git a/src/librustc_mir/transform/dump_mir.rs b/src/librustc_mir/transform/dump_mir.rs
index f22a71636a98e..5b3113f962b2e 100644
--- a/src/librustc_mir/transform/dump_mir.rs
+++ b/src/librustc_mir/transform/dump_mir.rs
@@ -11,7 +11,10 @@
 //! This pass just dumps MIR at a specified point.
 
 use std::fmt;
+use std::fs::File;
+use std::io;
 
+use rustc::session::config::{OutputFilenames, OutputType};
 use rustc::ty::TyCtxt;
 use rustc::mir::*;
 use rustc::mir::transform::{Pass, MirPass, MirPassHook, MirSource};
@@ -70,3 +73,14 @@ impl<'tcx> MirPassHook<'tcx> for DumpMir {
 }
 
 impl<'b> Pass for DumpMir {}
+
+pub fn emit_mir<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    outputs: &OutputFilenames)
+    -> io::Result<()>
+{
+    let path = outputs.path(OutputType::Mir);
+    let mut f = File::create(&path)?;
+    mir_util::write_mir_pretty(tcx, tcx.maps.mir.borrow().keys().into_iter(), &mut f)?;
+    Ok(())
+}
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index 40a69721495b8..377ff34cb7e0d 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -741,6 +741,7 @@ pub fn run_passes(sess: &Session,
                 modules_config.emit_obj = true;
                 metadata_config.emit_obj = true;
             },
+            OutputType::Mir => {}
             OutputType::DepInfo => {}
         }
     }
@@ -880,6 +881,7 @@ pub fn run_passes(sess: &Session,
                 user_wants_objects = true;
                 copy_if_one_unit(OutputType::Object, true);
             }
+            OutputType::Mir |
             OutputType::Metadata |
             OutputType::Exe |
             OutputType::DepInfo => {}

From 4ddedf7246128c7f0dce4a836a0f375f2b12c7c3 Mon Sep 17 00:00:00 2001
From: Jake Goulding <jake.goulding@gmail.com>
Date: Fri, 3 Mar 2017 22:42:49 -0500
Subject: [PATCH 2/2] Add warning about volatility of MIR output

---
 src/librustc_mir/util/pretty.rs | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index 35734dcce2beb..ef2bf6e543420 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -91,6 +91,9 @@ pub fn write_mir_pretty<'a, 'b, 'tcx, I>(tcx: TyCtxt<'b, 'tcx, 'tcx>,
                                          -> io::Result<()>
     where I: Iterator<Item=DefId>, 'tcx: 'a
 {
+    writeln!(w, "// WARNING: This output format is intended for human consumers only")?;
+    writeln!(w, "// and is subject to change without notice. Knock yourself out.")?;
+
     let mut first = true;
     for def_id in iter.filter(DefId::is_local) {
         let mir = &tcx.item_mir(def_id);