diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index c72bdd04011161166f6abe81f84cd68af64bb8d9..3be7c43cab9388c654b1355134a105b1002793e9 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -18,8 +18,6 @@ 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 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 9c980ddf08acef195b0e574c4aa858e4d83c7b1c..a2b1e3c26637dbd3876a7eccbb6bd3ce96ae9671 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 @@ 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 159fee6aa4c92167aeeac32440874a2f61410333..98278949d51fd43ebe6ed8dec2d0bd4ce4d7200a 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 similarity index 67% rename from src/librustc_borrowck/borrowck/mir/mod.rs rename to src/librustc_mir/dataflow/drop_flag_effects.rs index e3b99b9d4bd43f92ac16ad3e7559d3c998c9c0ba..daafbecc5dfa3ba0d96642d125ac6ba5bd081b1f 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 { +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 { 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 } 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, - print_postflow_to: Option, -} - -#[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>, - flow_uninits: DataflowResults> -} - -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>) { - 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 @@ -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 similarity index 97% rename from src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs rename to src/librustc_mir/dataflow/graphviz.rs index 7f95f07f48d4ab3d6f062abb33a4aff6046ba779..e6d77aa2686af345839169226078bdc7e9f3d0f5 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs +++ b/src/librustc_mir/dataflow/graphviz.rs @@ -15,7 +15,6 @@ 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::mem; use std::path::Path; -use super::super::MirBorrowckCtxtPreDataflow; +use util; + use super::{BitDenotation, DataflowState}; +use super::DataflowBuilder; impl DataflowState { fn each_bit(&self, words: &IdxSet, mut f: F) @@ -86,7 +87,7 @@ pub trait MirWithFlowState<'tcx> { fn flow_state(&self) -> &DataflowState; } -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 @@ fn chunked_present_left(w: &mut W, } 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 similarity index 96% rename from src/librustc_borrowck/borrowck/mir/dataflow/impls.rs rename to src/librustc_mir/dataflow/impls/mod.rs index 1a1ac7f9c74d3eab0f47b37342ece825f34449e9..97c996dea68f6c07cc6078cd1711111fe0557b71 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 similarity index 95% rename from src/librustc_borrowck/borrowck/mir/dataflow/mod.rs rename to src/librustc_mir/dataflow/mod.rs index f0f082a2561cca6f3814dd1acaf46b2ec4828805..d7ad9f9c09aef820ea7b5a0dcb48c1353bda1ac4 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::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, + print_postflow_to: Option, +} pub trait Dataflow { fn dataflow

(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug; } -impl<'a, 'tcx: 'a, BD> Dataflow for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD> +impl<'a, 'tcx: 'a, BD> Dataflow for DataflowBuilder<'a, 'tcx, BD> where BD: BitDenotation + DataflowOperator { fn dataflow

(&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

(&self, p: P) -> io::Result<()> @@ -195,7 +207,7 @@ pub fn results(self) -> DataflowResults { pub fn mir(&self) -> &'a Mir<'tcx> { self.mir } } -pub struct DataflowResults(DataflowState) where O: BitDenotation; +pub struct DataflowResults(pub(crate) DataflowState) where O: BitDenotation; impl DataflowResults { pub fn sets(&self) -> &AllSets { @@ -213,7 +225,7 @@ pub struct DataflowState pub sets: AllSets, /// operator used to initialize, combine, and interpret bits. - operator: O, + pub(crate) operator: O, } #[derive(Debug)] @@ -240,9 +252,9 @@ pub struct AllSets { } pub struct BlockSets<'a, E: Idx> { - on_entry: &'a mut IdxSet, - gen_set: &'a mut IdxSet, - kill_set: &'a mut IdxSet, + pub(crate) on_entry: &'a mut IdxSet, + pub(crate) gen_set: &'a mut IdxSet, + pub(crate) kill_set: &'a mut IdxSet, } 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 similarity index 100% rename from src/librustc_borrowck/borrowck/mir/abs_domain.rs rename to 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 similarity index 98% rename from src/librustc_borrowck/borrowck/mir/gather_moves.rs rename to src/librustc_mir/dataflow/move_paths/mod.rs index a0ecdcc8e2ff728d0b5ff2abe6f5e1f526d7433c..d7ed0938e886a00e0ed71dd3c4f46cb1c89e87d5 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::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 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 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 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 { /// Location-indexed (BasicBlock for outer index, index within BB /// for inner index) map. - map: IndexVec>, + pub(crate) map: IndexVec>, } impl Index for LocationMap { @@ -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 bfa31c052e4edeb3dbdf2a65c9c17ef189842997..71855d3805e139c2c8e3008e85273c83fe378a46 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -26,6 +26,7 @@ #![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_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 similarity index 94% rename from src/librustc_borrowck/borrowck/mir/elaborate_drops.rs rename to src/librustc_mir/transform/elaborate_drops.rs index 833697726089ea5d4fd3e54e12b33948bd16a12a..b158cb43ce7a922c4192bcad6ea79ae43367c733 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::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 @@ fn run_pass<'a, 'tcx>(&self, }; 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 @@ fn clear_drop_flag(&mut self, loc: Location, path: Self::Path, mode: DropFlagMod } fn field_subpath(&self, path: Self::Path, field: Field) -> Option { - 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 @@ fn field_subpath(&self, path: Self::Path, field: Field) -> Option { } fn deref_subpath(&self, path: Self::Path) -> Option { - 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 @@ fn deref_subpath(&self, path: Self::Path) -> Option { } fn downcast_subpath(&self, path: Self::Path, variant: usize) -> Option { - 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 @@ fn drop_flags_for_fn_rets(&mut self) { 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 @@ fn drop_flags_for_locs(&mut self) { } } 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 4594c611d596f6cf06de8ee054fdeca25969d5e9..1530ea8e0df0fad09cd0f61fd39f8e9a5ba26bb2 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -30,6 +30,8 @@ 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 similarity index 73% rename from src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs rename to src/librustc_mir/transform/rustc_peek.rs index 4bef191b113bd66816416df4614fe65146c6c794..5918de0c6881104a906c857f250c2f0853d40670 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -14,12 +14,67 @@ 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 };