about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/librustc_borrowck/borrowck/mod.rs27
-rw-r--r--src/librustc_borrowck/lib.rs3
-rw-r--r--src/librustc_driver/driver.rs3
-rw-r--r--src/librustc_mir/dataflow/drop_flag_effects.rs (renamed from src/librustc_borrowck/borrowck/mir/mod.rs)148
-rw-r--r--src/librustc_mir/dataflow/graphviz.rs (renamed from src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs)13
-rw-r--r--src/librustc_mir/dataflow/impls/mod.rs (renamed from src/librustc_borrowck/borrowck/mir/dataflow/impls.rs)29
-rw-r--r--src/librustc_mir/dataflow/mod.rs (renamed from src/librustc_borrowck/borrowck/mir/dataflow/mod.rs)36
-rw-r--r--src/librustc_mir/dataflow/move_paths/abs_domain.rs (renamed from src/librustc_borrowck/borrowck/mir/abs_domain.rs)0
-rw-r--r--src/librustc_mir/dataflow/move_paths/mod.rs (renamed from src/librustc_borrowck/borrowck/mir/gather_moves.rs)12
-rw-r--r--src/librustc_mir/lib.rs3
-rw-r--r--src/librustc_mir/transform/elaborate_drops.rs (renamed from src/librustc_borrowck/borrowck/mir/elaborate_drops.rs)43
-rw-r--r--src/librustc_mir/transform/mod.rs2
-rw-r--r--src/librustc_mir/transform/rustc_peek.rs (renamed from src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs)65
13 files changed, 178 insertions, 206 deletions
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index c72bdd04011..3be7c43cab9 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -18,8 +18,6 @@ pub use self::bckerr_code::*;
 pub use self::AliasableViolationKind::*;
 pub use self::MovedValueUseKind::*;
 
-pub use self::mir::elaborate_drops::ElaborateDrops;
-
 use self::InteriorKind::*;
 
 use rustc::hir::map as hir_map;
@@ -55,8 +53,6 @@ pub mod gather_loans;
 
 pub mod move_data;
 
-mod mir;
-
 #[derive(Clone, Copy)]
 pub struct LoanDataFlowOperator;
 
@@ -100,26 +96,21 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) {
     }
 
     let body_id = tcx.hir.body_owned_by(owner_id);
-    let attributes = tcx.get_attrs(owner_def_id);
     let tables = tcx.typeck_tables_of(owner_def_id);
     let region_maps = tcx.region_maps(owner_def_id);
     let mut bccx = &mut BorrowckCtxt { tcx, tables, region_maps, owner_def_id };
 
     let body = bccx.tcx.hir.body(body_id);
 
-    if bccx.tcx.has_attr(owner_def_id, "rustc_mir_borrowck") {
-        mir::borrowck_mir(bccx, owner_id, &attributes);
-    } else {
-        // Eventually, borrowck will always read the MIR, but at the
-        // moment we do not. So, for now, we always force MIR to be
-        // constructed for a given fn, since this may result in errors
-        // being reported and we want that to happen.
-        //
-        // Note that `mir_validated` is a "stealable" result; the
-        // thief, `optimized_mir()`, forces borrowck, so we know that
-        // is not yet stolen.
-        tcx.mir_validated(owner_def_id).borrow();
-    }
+    // Eventually, borrowck will always read the MIR, but at the
+    // moment we do not. So, for now, we always force MIR to be
+    // constructed for a given fn, since this may result in errors
+    // being reported and we want that to happen.
+    //
+    // Note that `mir_validated` is a "stealable" result; the
+    // thief, `optimized_mir()`, forces borrowck, so we know that
+    // is not yet stolen.
+    tcx.mir_validated(owner_def_id).borrow();
 
     let cfg = cfg::CFG::new(bccx.tcx, &body);
     let AnalysisData { all_loans,
diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs
index 9c980ddf08a..a2b1e3c2663 100644
--- a/src/librustc_borrowck/lib.rs
+++ b/src/librustc_borrowck/lib.rs
@@ -21,7 +21,6 @@
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(associated_consts)]
-#![feature(nonzero)]
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
@@ -39,7 +38,7 @@ extern crate core; // for NonZero
 
 pub use borrowck::check_crate;
 pub use borrowck::build_borrowck_dataflow_data_for_fn;
-pub use borrowck::{AnalysisData, BorrowckCtxt, ElaborateDrops};
+pub use borrowck::{AnalysisData, BorrowckCtxt};
 
 // NB: This module needs to be declared first so diagnostics are
 // registered before they are used.
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 159fee6aa4c..98278949d51 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -920,6 +920,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
     // What we need to do constant evaluation.
     passes.push_pass(MIR_CONST, mir::transform::simplify::SimplifyCfg::new("initial"));
     passes.push_pass(MIR_CONST, mir::transform::type_check::TypeckMir);
+    passes.push_pass(MIR_CONST, mir::transform::rustc_peek::SanityCheck);
 
     // What we need to run borrowck etc.
     passes.push_pass(MIR_VALIDATED, mir::transform::qualify_consts::QualifyAndPromoteConstants);
@@ -934,7 +935,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
     // From here on out, regions are gone.
     passes.push_pass(MIR_OPTIMIZED, mir::transform::erase_regions::EraseRegions);
     passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::AddCallGuards);
-    passes.push_pass(MIR_OPTIMIZED, borrowck::ElaborateDrops);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::elaborate_drops::ElaborateDrops);
     passes.push_pass(MIR_OPTIMIZED, mir::transform::no_landing_pads::NoLandingPads);
     passes.push_pass(MIR_OPTIMIZED, mir::transform::simplify::SimplifyCfg::new("elaborate-drops"));
 
diff --git a/src/librustc_borrowck/borrowck/mir/mod.rs b/src/librustc_mir/dataflow/drop_flag_effects.rs
index e3b99b9d4bd..daafbecc5df 100644
--- a/src/librustc_borrowck/borrowck/mir/mod.rs
+++ b/src/librustc_mir/dataflow/drop_flag_effects.rs
@@ -1,4 +1,4 @@
-// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,33 +8,24 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use borrowck::BorrowckCtxt;
-
 use syntax::ast::{self, MetaItem};
 use syntax_pos::DUMMY_SP;
 
-use rustc::mir::{self, BasicBlock, BasicBlockData, Mir, Statement, Terminator, Location};
+
+use rustc::mir::{self, Mir, BasicBlock, Location};
 use rustc::session::Session;
 use rustc::ty::{self, TyCtxt};
-use rustc_mir::util::elaborate_drops::DropFlagState;
-use rustc_data_structures::indexed_set::{IdxSet, IdxSetBuf};
-
-mod abs_domain;
-pub mod elaborate_drops;
-mod dataflow;
-mod gather_moves;
-// mod graphviz;
-
-use self::dataflow::{BitDenotation};
-use self::dataflow::{DataflowOperator};
-use self::dataflow::{Dataflow, DataflowAnalysis, DataflowResults};
-use self::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals};
-use self::dataflow::{DefinitelyInitializedLvals};
-use self::gather_moves::{HasMoveData, MoveData, MovePathIndex, LookupResult};
+use util::elaborate_drops::DropFlagState;
+use rustc_data_structures::indexed_set::{IdxSet};
 
 use std::fmt;
 
-fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option<MetaItem> {
+use super::{Dataflow, DataflowBuilder, DataflowAnalysis};
+use super::{BitDenotation, DataflowOperator, DataflowResults};
+use super::indexes::MovePathIndex;
+use super::move_paths::{MoveData, LookupResult};
+
+pub(crate) fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option<MetaItem> {
     for attr in attrs {
         if attr.check_name("rustc_mir") {
             let items = attr.meta_item_list();
@@ -50,69 +41,11 @@ fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option<MetaItem>
 }
 
 pub struct MoveDataParamEnv<'tcx> {
-    move_data: MoveData<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    pub(crate) move_data: MoveData<'tcx>,
+    pub(crate) param_env: ty::ParamEnv<'tcx>,
 }
 
-pub fn borrowck_mir(bcx: &mut BorrowckCtxt,
-                    id: ast::NodeId,
-                    attributes: &[ast::Attribute]) {
-    let tcx = bcx.tcx;
-    let def_id = tcx.hir.local_def_id(id);
-    debug!("borrowck_mir({:?}) UNIMPLEMENTED", def_id);
-
-    // It is safe for us to borrow `mir_validated()`: `optimized_mir`
-    // steals it, but it forces the `borrowck` query.
-    let mir = &tcx.mir_validated(def_id).borrow();
-
-    let param_env = tcx.param_env(def_id);
-    let move_data = MoveData::gather_moves(mir, tcx, param_env);
-    let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
-    let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
-    let flow_inits =
-        do_dataflow(tcx, mir, id, attributes, &dead_unwinds,
-                    MaybeInitializedLvals::new(tcx, mir, &mdpe),
-                    |bd, i| &bd.move_data().move_paths[i]);
-    let flow_uninits =
-        do_dataflow(tcx, mir, id, attributes, &dead_unwinds,
-                    MaybeUninitializedLvals::new(tcx, mir, &mdpe),
-                    |bd, i| &bd.move_data().move_paths[i]);
-    let flow_def_inits =
-        do_dataflow(tcx, mir, id, attributes, &dead_unwinds,
-                    DefinitelyInitializedLvals::new(tcx, mir, &mdpe),
-                    |bd, i| &bd.move_data().move_paths[i]);
-
-    if has_rustc_mir_with(attributes, "rustc_peek_maybe_init").is_some() {
-        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &flow_inits);
-    }
-    if has_rustc_mir_with(attributes, "rustc_peek_maybe_uninit").is_some() {
-        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &flow_uninits);
-    }
-    if has_rustc_mir_with(attributes, "rustc_peek_definite_init").is_some() {
-        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &flow_def_inits);
-    }
-
-    if has_rustc_mir_with(attributes, "stop_after_dataflow").is_some() {
-        bcx.tcx.sess.fatal("stop_after_dataflow ended compilation");
-    }
-
-    let mut mbcx = MirBorrowckCtxt {
-        bcx: bcx,
-        mir: mir,
-        node_id: id,
-        move_data: &mdpe.move_data,
-        flow_inits: flow_inits,
-        flow_uninits: flow_uninits,
-    };
-
-    for bb in mir.basic_blocks().indices() {
-        mbcx.process_basic_block(bb);
-    }
-
-    debug!("borrowck_mir done");
-}
-
-fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub(crate) fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                 mir: &Mir<'tcx>,
                                 node_id: ast::NodeId,
                                 attributes: &[ast::Attribute],
@@ -142,7 +75,7 @@ fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let print_postflow_to =
         name_found(tcx.sess, attributes, "borrowck_graphviz_postflow");
 
-    let mut mbcx = MirBorrowckCtxtPreDataflow {
+    let mut mbcx = DataflowBuilder {
         node_id: node_id,
         print_preflow_to: print_preflow_to,
         print_postflow_to: print_postflow_to,
@@ -153,46 +86,7 @@ fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mbcx.flow_state.results()
 }
 
-
-pub struct MirBorrowckCtxtPreDataflow<'a, 'tcx: 'a, BD> where BD: BitDenotation
-{
-    node_id: ast::NodeId,
-    flow_state: DataflowAnalysis<'a, 'tcx, BD>,
-    print_preflow_to: Option<String>,
-    print_postflow_to: Option<String>,
-}
-
-#[allow(dead_code)]
-pub struct MirBorrowckCtxt<'b, 'a: 'b, 'tcx: 'a> {
-    bcx: &'b mut BorrowckCtxt<'a, 'tcx>,
-    mir: &'b Mir<'tcx>,
-    node_id: ast::NodeId,
-    move_data: &'b MoveData<'tcx>,
-    flow_inits: DataflowResults<MaybeInitializedLvals<'b, 'tcx>>,
-    flow_uninits: DataflowResults<MaybeUninitializedLvals<'b, 'tcx>>
-}
-
-impl<'b, 'a: 'b, 'tcx: 'a> MirBorrowckCtxt<'b, 'a, 'tcx> {
-    fn process_basic_block(&mut self, bb: BasicBlock) {
-        let BasicBlockData { ref statements, ref terminator, is_cleanup: _ } =
-            self.mir[bb];
-        for stmt in statements {
-            self.process_statement(bb, stmt);
-        }
-
-        self.process_terminator(bb, terminator);
-    }
-
-    fn process_statement(&mut self, bb: BasicBlock, stmt: &Statement<'tcx>) {
-        debug!("MirBorrowckCtxt::process_statement({:?}, {:?}", bb, stmt);
-    }
-
-    fn process_terminator(&mut self, bb: BasicBlock, term: &Option<Terminator<'tcx>>) {
-        debug!("MirBorrowckCtxt::process_terminator({:?}, {:?})", bb, term);
-    }
-}
-
-fn move_path_children_matching<'tcx, F>(move_data: &MoveData<'tcx>,
+pub fn move_path_children_matching<'tcx, F>(move_data: &MoveData<'tcx>,
                                         path: MovePathIndex,
                                         mut cond: F)
                                         -> Option<MovePathIndex>
@@ -253,7 +147,7 @@ fn lvalue_contents_drop_state_cannot_differ<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx
     }
 }
 
-fn on_lookup_result_bits<'a, 'tcx, F>(
+pub(crate) fn on_lookup_result_bits<'a, 'tcx, F>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir: &Mir<'tcx>,
     move_data: &MoveData<'tcx>,
@@ -271,7 +165,7 @@ fn on_lookup_result_bits<'a, 'tcx, F>(
     }
 }
 
-fn on_all_children_bits<'a, 'tcx, F>(
+pub(crate) fn on_all_children_bits<'a, 'tcx, F>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir: &Mir<'tcx>,
     move_data: &MoveData<'tcx>,
@@ -312,7 +206,7 @@ fn on_all_children_bits<'a, 'tcx, F>(
     on_all_children_bits(tcx, mir, move_data, move_path_index, &mut each_child);
 }
 
-fn on_all_drop_children_bits<'a, 'tcx, F>(
+pub(crate) fn on_all_drop_children_bits<'a, 'tcx, F>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir: &Mir<'tcx>,
     ctxt: &MoveDataParamEnv<'tcx>,
@@ -333,7 +227,7 @@ fn on_all_drop_children_bits<'a, 'tcx, F>(
     })
 }
 
-fn drop_flag_effects_for_function_entry<'a, 'tcx, F>(
+pub(crate) fn drop_flag_effects_for_function_entry<'a, 'tcx, F>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir: &Mir<'tcx>,
     ctxt: &MoveDataParamEnv<'tcx>,
@@ -350,7 +244,7 @@ fn drop_flag_effects_for_function_entry<'a, 'tcx, F>(
     }
 }
 
-fn drop_flag_effects_for_location<'a, 'tcx, F>(
+pub(crate) fn drop_flag_effects_for_location<'a, 'tcx, F>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir: &Mir<'tcx>,
     ctxt: &MoveDataParamEnv<'tcx>,
diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs b/src/librustc_mir/dataflow/graphviz.rs
index 7f95f07f48d..e6d77aa2686 100644
--- a/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs
+++ b/src/librustc_mir/dataflow/graphviz.rs
@@ -15,7 +15,6 @@ use rustc::mir::{BasicBlock, Mir};
 use rustc_data_structures::bitslice::bits_to_string;
 use rustc_data_structures::indexed_set::{IdxSet};
 use rustc_data_structures::indexed_vec::Idx;
-use rustc_mir::util as mir_util;
 
 use dot;
 use dot::IntoCow;
@@ -28,8 +27,10 @@ use std::marker::PhantomData;
 use std::mem;
 use std::path::Path;
 
-use super::super::MirBorrowckCtxtPreDataflow;
+use util;
+
 use super::{BitDenotation, DataflowState};
+use super::DataflowBuilder;
 
 impl<O: BitDenotation> DataflowState<O> {
     fn each_bit<F>(&self, words: &IdxSet<O::Idx>, mut f: F)
@@ -86,7 +87,7 @@ pub trait MirWithFlowState<'tcx> {
     fn flow_state(&self) -> &DataflowState<Self::BD>;
 }
 
-impl<'a, 'tcx: 'a, BD> MirWithFlowState<'tcx> for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>
+impl<'a, 'tcx: 'a, BD> MirWithFlowState<'tcx> for DataflowBuilder<'a, 'tcx, BD>
     where 'tcx: 'a, BD: BitDenotation
 {
     type BD = BD;
@@ -103,8 +104,8 @@ struct Graph<'a, 'tcx, MWF:'a, P> where
     render_idx: P,
 }
 
-pub fn print_borrowck_graph_to<'a, 'tcx, BD, P>(
-    mbcx: &MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>,
+pub(crate) fn print_borrowck_graph_to<'a, 'tcx, BD, P>(
+    mbcx: &DataflowBuilder<'a, 'tcx, BD>,
     path: &Path,
     render_idx: P)
     -> io::Result<()>
@@ -220,7 +221,7 @@ impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P>
             }
             Ok(())
         }
-        mir_util::write_graphviz_node_label(
+        util::write_graphviz_node_label(
             *n, self.mbcx.mir(), &mut v, 4,
             |w| {
                 let flow = self.mbcx.flow_state();
diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs b/src/librustc_mir/dataflow/impls/mod.rs
index 1a1ac7f9c74..97c996dea68 100644
--- a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs
+++ b/src/librustc_mir/dataflow/impls/mod.rs
@@ -8,25 +8,26 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+//! Dataflow analyses are built upon some interpretation of the
+//! bitvectors attached to each basic block, represented via a
+//! zero-sized structure.
+
 use rustc::ty::TyCtxt;
 use rustc::mir::{self, Mir, Location};
 use rustc_data_structures::bitslice::BitSlice; // adds set_bit/get_bit to &[usize] bitvector rep.
 use rustc_data_structures::bitslice::{BitwiseOperator};
 use rustc_data_structures::indexed_set::{IdxSet};
 use rustc_data_structures::indexed_vec::Idx;
-use rustc_mir::util::elaborate_drops::DropFlagState;
 
-use super::super::gather_moves::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex};
-use super::super::MoveDataParamEnv;
-use super::super::drop_flag_effects_for_function_entry;
-use super::super::drop_flag_effects_for_location;
-use super::super::on_lookup_result_bits;
+use super::MoveDataParamEnv;
+use util::elaborate_drops::DropFlagState;
 
+use super::move_paths::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex};
 use super::{BitDenotation, BlockSets, DataflowOperator};
 
-// Dataflow analyses are built upon some interpretation of the
-// bitvectors attached to each basic block, represented via a
-// zero-sized structure.
+use super::drop_flag_effects_for_function_entry;
+use super::drop_flag_effects_for_location;
+use super::on_lookup_result_bits;
 
 /// `MaybeInitializedLvals` tracks all l-values that might be
 /// initialized upon reaching a particular point in the control flow
@@ -219,6 +220,16 @@ pub struct MovingOutStatements<'a, 'tcx: 'a> {
     mdpe: &'a MoveDataParamEnv<'tcx>,
 }
 
+impl<'a, 'tcx: 'a> MovingOutStatements<'a, 'tcx> {
+    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+               mir: &'a Mir<'tcx>,
+               mdpe: &'a MoveDataParamEnv<'tcx>)
+               -> Self
+    {
+        MovingOutStatements { tcx: tcx, mir: mir, mdpe: mdpe }
+    }
+}
+
 impl<'a, 'tcx> HasMoveData<'tcx> for MovingOutStatements<'a, 'tcx> {
     fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data }
 }
diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs
index f0f082a2561..d7ad9f9c09a 100644
--- a/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs
+++ b/src/librustc_mir/dataflow/mod.rs
@@ -8,11 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use syntax::ast;
+
 use rustc_data_structures::indexed_set::{IdxSet, IdxSetBuf};
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::bitslice::{bitwise, BitwiseOperator};
 
-use rustc::ty::TyCtxt;
+use rustc::ty::{TyCtxt};
 use rustc::mir::{self, Mir};
 
 use std::fmt::Debug;
@@ -21,21 +23,31 @@ use std::mem;
 use std::path::PathBuf;
 use std::usize;
 
-use super::MirBorrowckCtxtPreDataflow;
-
-pub use self::sanity_check::sanity_check_via_rustc_peek;
 pub use self::impls::{MaybeInitializedLvals, MaybeUninitializedLvals};
 pub use self::impls::{DefinitelyInitializedLvals, MovingOutStatements};
 
+pub(crate) use self::drop_flag_effects::*;
+
+mod drop_flag_effects;
 mod graphviz;
-mod sanity_check;
 mod impls;
+pub mod move_paths;
+
+pub(crate) use self::move_paths::indexes;
+
+pub(crate) struct DataflowBuilder<'a, 'tcx: 'a, BD> where BD: BitDenotation
+{
+    node_id: ast::NodeId,
+    flow_state: DataflowAnalysis<'a, 'tcx, BD>,
+    print_preflow_to: Option<String>,
+    print_postflow_to: Option<String>,
+}
 
 pub trait Dataflow<BD: BitDenotation> {
     fn dataflow<P>(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug;
 }
 
-impl<'a, 'tcx: 'a, BD> Dataflow<BD> for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>
+impl<'a, 'tcx: 'a, BD> Dataflow<BD> for DataflowBuilder<'a, 'tcx, BD>
     where BD: BitDenotation + DataflowOperator
 {
     fn dataflow<P>(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug {
@@ -135,7 +147,7 @@ fn dataflow_path(context: &str, prepost: &str, path: &str) -> PathBuf {
     path
 }
 
-impl<'a, 'tcx: 'a, BD> MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>
+impl<'a, 'tcx: 'a, BD> DataflowBuilder<'a, 'tcx, BD>
     where BD: BitDenotation
 {
     fn pre_dataflow_instrumentation<P>(&self, p: P) -> io::Result<()>
@@ -195,7 +207,7 @@ impl<'a, 'tcx: 'a, O> DataflowAnalysis<'a, 'tcx, O>
     pub fn mir(&self) -> &'a Mir<'tcx> { self.mir }
 }
 
-pub struct DataflowResults<O>(DataflowState<O>) where O: BitDenotation;
+pub struct DataflowResults<O>(pub(crate) DataflowState<O>) where O: BitDenotation;
 
 impl<O: BitDenotation> DataflowResults<O> {
     pub fn sets(&self) -> &AllSets<O::Idx> {
@@ -213,7 +225,7 @@ pub struct DataflowState<O: BitDenotation>
     pub sets: AllSets<O::Idx>,
 
     /// operator used to initialize, combine, and interpret bits.
-    operator: O,
+    pub(crate) operator: O,
 }
 
 #[derive(Debug)]
@@ -240,9 +252,9 @@ pub struct AllSets<E: Idx> {
 }
 
 pub struct BlockSets<'a, E: Idx> {
-    on_entry: &'a mut IdxSet<E>,
-    gen_set: &'a mut IdxSet<E>,
-    kill_set: &'a mut IdxSet<E>,
+    pub(crate) on_entry: &'a mut IdxSet<E>,
+    pub(crate) gen_set: &'a mut IdxSet<E>,
+    pub(crate) kill_set: &'a mut IdxSet<E>,
 }
 
 impl<'a, E:Idx> BlockSets<'a, E> {
diff --git a/src/librustc_borrowck/borrowck/mir/abs_domain.rs b/src/librustc_mir/dataflow/move_paths/abs_domain.rs
index 5e61c2ec7a2..5e61c2ec7a2 100644
--- a/src/librustc_borrowck/borrowck/mir/abs_domain.rs
+++ b/src/librustc_mir/dataflow/move_paths/abs_domain.rs
diff --git a/src/librustc_borrowck/borrowck/mir/gather_moves.rs b/src/librustc_mir/dataflow/move_paths/mod.rs
index a0ecdcc8e2f..d7ed0938e88 100644
--- a/src/librustc_borrowck/borrowck/mir/gather_moves.rs
+++ b/src/librustc_mir/dataflow/move_paths/mod.rs
@@ -21,14 +21,16 @@ use std::fmt;
 use std::mem;
 use std::ops::{Index, IndexMut};
 
-use super::abs_domain::{AbstractElem, Lift};
+use self::abs_domain::{AbstractElem, Lift};
+
+mod abs_domain;
 
 // This submodule holds some newtype'd Index wrappers that are using
 // NonZero to ensure that Option<Index> occupies only a single word.
 // They are in a submodule to impose privacy restrictions; namely, to
 // ensure that other code does not accidentally access `index.0`
 // (which is likely to yield a subtle off-by-one error).
-mod indexes {
+pub(crate) mod indexes {
     use std::fmt;
     use core::nonzero::NonZero;
     use rustc_data_structures::indexed_vec::Idx;
@@ -65,7 +67,7 @@ mod indexes {
 pub use self::indexes::MovePathIndex;
 pub use self::indexes::MoveOutIndex;
 
-impl self::indexes::MoveOutIndex {
+impl MoveOutIndex {
     pub fn move_path_index(&self, move_data: &MoveData) -> MovePathIndex {
         move_data.moves[*self].path
     }
@@ -128,7 +130,7 @@ pub trait HasMoveData<'tcx> {
 pub struct LocationMap<T> {
     /// Location-indexed (BasicBlock for outer index, index within BB
     /// for inner index) map.
-    map: IndexVec<BasicBlock, Vec<T>>,
+    pub(crate) map: IndexVec<BasicBlock, Vec<T>>,
 }
 
 impl<T> Index<Location> for LocationMap<T> {
@@ -188,7 +190,7 @@ pub struct MovePathLookup<'tcx> {
     projections: FxHashMap<(MovePathIndex, AbstractElem<'tcx>), MovePathIndex>
 }
 
-struct MoveDataBuilder<'a, 'tcx: 'a> {
+pub(super) struct MoveDataBuilder<'a, 'tcx: 'a> {
     mir: &'a Mir<'tcx>,
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index bfa31c052e4..71855d3805e 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -26,6 +26,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 #![feature(rustc_diagnostic_macros)]
 #![feature(placement_in_syntax)]
 #![feature(collection_placement)]
+#![feature(nonzero)]
 
 #[macro_use] extern crate log;
 extern crate graphviz as dot;
@@ -40,10 +41,12 @@ extern crate syntax;
 extern crate syntax_pos;
 extern crate rustc_const_math;
 extern crate rustc_const_eval;
+extern crate core; // for NonZero
 
 pub mod diagnostics;
 
 mod build;
+pub mod dataflow;
 mod hair;
 mod shim;
 pub mod transform;
diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs
index 83369772608..b158cb43ce7 100644
--- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
+++ b/src/librustc_mir/transform/elaborate_drops.rs
@@ -8,12 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::gather_moves::{HasMoveData, MoveData, MovePathIndex, LookupResult};
-use super::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals};
-use super::dataflow::{DataflowResults};
-use super::{on_all_children_bits, on_all_drop_children_bits};
-use super::{drop_flag_effects_for_location, on_lookup_result_bits};
-use super::MoveDataParamEnv;
+use dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex, LookupResult};
+use dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals};
+use dataflow::{DataflowResults};
+use dataflow::{on_all_children_bits, on_all_drop_children_bits};
+use dataflow::{drop_flag_effects_for_location, on_lookup_result_bits};
+use dataflow::MoveDataParamEnv;
+use dataflow;
 use rustc::ty::{self, TyCtxt};
 use rustc::mir::*;
 use rustc::mir::transform::{MirPass, MirSource};
@@ -21,9 +22,9 @@ use rustc::middle::const_val::ConstVal;
 use rustc::util::nodemap::FxHashMap;
 use rustc_data_structures::indexed_set::IdxSetBuf;
 use rustc_data_structures::indexed_vec::Idx;
-use rustc_mir::util::patch::MirPatch;
-use rustc_mir::util::elaborate_drops::{DropFlagState, Unwind, elaborate_drop};
-use rustc_mir::util::elaborate_drops::{DropElaborator, DropStyle, DropFlagMode};
+use util::patch::MirPatch;
+use util::elaborate_drops::{DropFlagState, Unwind, elaborate_drop};
+use util::elaborate_drops::{DropElaborator, DropStyle, DropFlagMode};
 use syntax::ast;
 use syntax_pos::Span;
 
@@ -54,13 +55,13 @@ impl MirPass for ElaborateDrops {
             };
             let dead_unwinds = find_dead_unwinds(tcx, mir, id, &env);
             let flow_inits =
-                super::do_dataflow(tcx, mir, id, &[], &dead_unwinds,
-                                   MaybeInitializedLvals::new(tcx, mir, &env),
-                                   |bd, p| &bd.move_data().move_paths[p]);
+                dataflow::do_dataflow(tcx, mir, id, &[], &dead_unwinds,
+                                      MaybeInitializedLvals::new(tcx, mir, &env),
+                                      |bd, p| &bd.move_data().move_paths[p]);
             let flow_uninits =
-                super::do_dataflow(tcx, mir, id, &[], &dead_unwinds,
-                                   MaybeUninitializedLvals::new(tcx, mir, &env),
-                                   |bd, p| &bd.move_data().move_paths[p]);
+                dataflow::do_dataflow(tcx, mir, id, &[], &dead_unwinds,
+                                      MaybeUninitializedLvals::new(tcx, mir, &env),
+                                      |bd, p| &bd.move_data().move_paths[p]);
 
             ElaborateDropsCtxt {
                 tcx: tcx,
@@ -91,7 +92,7 @@ fn find_dead_unwinds<'a, 'tcx>(
     // reach cleanup blocks, which can't have unwind edges themselves.
     let mut dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
     let flow_inits =
-        super::do_dataflow(tcx, mir, id, &[], &dead_unwinds,
+        dataflow::do_dataflow(tcx, mir, id, &[], &dead_unwinds,
                            MaybeInitializedLvals::new(tcx, mir, &env),
                            |bd, p| &bd.move_data().move_paths[p]);
     for (bb, bb_data) in mir.basic_blocks().iter_enumerated() {
@@ -242,7 +243,7 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> {
     }
 
     fn field_subpath(&self, path: Self::Path, field: Field) -> Option<Self::Path> {
-        super::move_path_children_matching(self.ctxt.move_data(), path, |p| {
+        dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| {
             match p {
                 &Projection {
                     elem: ProjectionElem::Field(idx, _), ..
@@ -253,7 +254,7 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> {
     }
 
     fn deref_subpath(&self, path: Self::Path) -> Option<Self::Path> {
-        super::move_path_children_matching(self.ctxt.move_data(), path, |p| {
+        dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| {
             match p {
                 &Projection { elem: ProjectionElem::Deref, .. } => true,
                 _ => false
@@ -262,7 +263,7 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> {
     }
 
     fn downcast_subpath(&self, path: Self::Path, variant: usize) -> Option<Self::Path> {
-        super::move_path_children_matching(self.ctxt.move_data(), path, |p| {
+        dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| {
             match p {
                 &Projection {
                     elem: ProjectionElem::Downcast(_, idx), ..
@@ -560,7 +561,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
 
     fn drop_flags_for_args(&mut self) {
         let loc = Location { block: START_BLOCK, statement_index: 0 };
-        super::drop_flag_effects_for_function_entry(
+        dataflow::drop_flag_effects_for_function_entry(
             self.tcx, self.mir, self.env, |path, ds| {
                 self.set_drop_flag(loc, path, ds);
             }
@@ -605,7 +606,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
                     }
                 }
                 let loc = Location { block: bb, statement_index: i };
-                super::drop_flag_effects_for_location(
+                dataflow::drop_flag_effects_for_location(
                     self.tcx, self.mir, self.env, loc, |path, ds| {
                         if ds == DropFlagState::Absent || allow_initializations {
                             self.set_drop_flag(loc, path, ds)
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index 4594c611d59..1530ea8e0df 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -30,6 +30,8 @@ pub mod simplify;
 pub mod erase_regions;
 pub mod no_landing_pads;
 pub mod type_check;
+pub mod rustc_peek;
+pub mod elaborate_drops;
 pub mod add_call_guards;
 pub mod promote_consts;
 pub mod qualify_consts;
diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs b/src/librustc_mir/transform/rustc_peek.rs
index 4bef191b113..5918de0c688 100644
--- a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs
+++ b/src/librustc_mir/transform/rustc_peek.rs
@@ -14,12 +14,67 @@ use syntax_pos::Span;
 
 use rustc::ty::{self, TyCtxt};
 use rustc::mir::{self, Mir};
+use rustc::mir::transform::{MirPass, MirSource};
+use rustc_data_structures::indexed_set::IdxSetBuf;
 use rustc_data_structures::indexed_vec::Idx;
 
-use super::super::gather_moves::{MovePathIndex, LookupResult};
-use super::BitDenotation;
-use super::DataflowResults;
-use super::super::gather_moves::HasMoveData;
+use dataflow::do_dataflow;
+use dataflow::MoveDataParamEnv;
+use dataflow::BitDenotation;
+use dataflow::DataflowResults;
+use dataflow::{DefinitelyInitializedLvals, MaybeInitializedLvals, MaybeUninitializedLvals};
+use dataflow::move_paths::{MovePathIndex, LookupResult};
+use dataflow::move_paths::{HasMoveData, MoveData};
+use dataflow;
+
+use dataflow::has_rustc_mir_with;
+
+pub struct SanityCheck;
+
+impl MirPass for SanityCheck {
+    fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          src: MirSource, mir: &mut Mir<'tcx>) {
+        let id = src.item_id();
+        let def_id = tcx.hir.local_def_id(id);
+        if !tcx.has_attr(def_id, "rustc_mir_borrowck") {
+            debug!("skipping rustc_peek::SanityCheck on {}", tcx.item_path_str(def_id));
+            return;
+        } else {
+            debug!("running rustc_peek::SanityCheck on {}", tcx.item_path_str(def_id));
+        }
+
+        let attributes = tcx.get_attrs(def_id);
+        let param_env = tcx.param_env(def_id);
+        let move_data = MoveData::gather_moves(mir, tcx, param_env);
+        let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
+        let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
+        let flow_inits =
+            do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
+                        MaybeInitializedLvals::new(tcx, mir, &mdpe),
+                        |bd, i| &bd.move_data().move_paths[i]);
+        let flow_uninits =
+            do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
+                        MaybeUninitializedLvals::new(tcx, mir, &mdpe),
+                        |bd, i| &bd.move_data().move_paths[i]);
+        let flow_def_inits =
+            do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
+                        DefinitelyInitializedLvals::new(tcx, mir, &mdpe),
+                        |bd, i| &bd.move_data().move_paths[i]);
+
+        if has_rustc_mir_with(&attributes, "rustc_peek_maybe_init").is_some() {
+            sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_inits);
+        }
+        if has_rustc_mir_with(&attributes, "rustc_peek_maybe_uninit").is_some() {
+            sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_uninits);
+        }
+        if has_rustc_mir_with(&attributes, "rustc_peek_definite_init").is_some() {
+            sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_def_inits);
+        }
+        if has_rustc_mir_with(&attributes, "stop_after_dataflow").is_some() {
+            tcx.sess.fatal("stop_after_dataflow ended compilation");
+        }
+    }
+}
 
 /// This function scans `mir` for all calls to the intrinsic
 /// `rustc_peek` that have the expression form `rustc_peek(&expr)`.
@@ -92,7 +147,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // of the argument at time immediate preceding Call to
     // `rustc_peek`).
 
-    let mut sets = super::BlockSets { on_entry: &mut entry,
+    let mut sets = dataflow::BlockSets { on_entry: &mut entry,
                                       gen_set: &mut gen,
                                       kill_set: &mut kill };