Skip to content

Commit

Permalink
Auto merge of #65672 - ecstatic-morse:unified-dataflow-proto, r=<try>
Browse files Browse the repository at this point in the history
[WIP] A single framework for gen-kill and generic dataflow problems

This is the prototype implementation discussed in rust-lang/compiler-team#202. You can read a high-level description of it in [the proposal](https://hackmd.io/@39Qr_z9cQhasi25sGjmFnA/Skvd9rztS) for that design meeting. This would eventually supersede the existing `BitDenotation` interface.

r? @ghost

cc @rust-lang/compiler (esp. @eddyb and @pnkfelix)
  • Loading branch information
bors committed Nov 15, 2019
2 parents cefcc20 + dceb654 commit 43d649e
Show file tree
Hide file tree
Showing 24 changed files with 1,945 additions and 826 deletions.
25 changes: 25 additions & 0 deletions src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,31 @@ impl<'tcx> Body<'tcx> {
}
}

/// Returns a partially initialized MIR body containing only a list of basic blocks.
///
/// The returned MIR contains no `LocalDecl`s (even for the return place) or source scopes. It
/// is only useful for testing but cannot be `#[cfg(test)]` because it is used in a different
/// crate.
pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self {
Body {
phase: MirPhase::Build,
basic_blocks,
source_scopes: IndexVec::new(),
source_scope_local_data: ClearCrossCrate::Clear,
yield_ty: None,
generator_drop: None,
generator_layout: None,
local_decls: IndexVec::new(),
user_type_annotations: IndexVec::new(),
arg_count: 0,
__upvar_debuginfo_codegen_only_do_not_use: Vec::new(),
spread_arg: None,
span: syntax_pos::DUMMY_SP,
cache: cache::Cache::new(),
control_flow_destroyed: Vec::new(),
}
}

#[inline]
pub fn basic_blocks(&self) -> &IndexVec<BasicBlock, BasicBlockData<'tcx>> {
&self.basic_blocks
Expand Down
17 changes: 6 additions & 11 deletions src/librustc_mir/borrow_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use crate::dataflow::Borrows;
use crate::dataflow::DataflowResultsConsumer;
use crate::dataflow::FlowAtLocation;
use crate::dataflow::MoveDataParamEnv;
use crate::dataflow::{do_dataflow, DebugFormatted};
use crate::dataflow::{self, do_dataflow, DebugFormatted};
use crate::dataflow::EverInitializedPlaces;
use crate::dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces};

Expand Down Expand Up @@ -167,16 +167,10 @@ fn do_mir_borrowck<'a, 'tcx>(
param_env,
};

let dead_unwinds = BitSet::new_empty(body.basic_blocks().len());
let mut flow_inits = FlowAtLocation::new(do_dataflow(
tcx,
body,
def_id,
&attributes,
&dead_unwinds,
MaybeInitializedPlaces::new(tcx, body, &mdpe),
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]),
));
let flow_inits = MaybeInitializedPlaces::new(tcx, body, &mdpe);
let mut flow_inits = dataflow::generic::Engine::new_gen_kill(tcx, body, def_id, flow_inits)
.iterate_to_fixpoint()
.into_cursor(body);

let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(id).is_fn_or_closure();
let borrow_set = Rc::new(BorrowSet::build(
Expand Down Expand Up @@ -205,6 +199,7 @@ fn do_mir_borrowck<'a, 'tcx>(

let regioncx = Rc::new(regioncx);

let dead_unwinds = BitSet::new_empty(body.basic_blocks().len());
let flow_borrows = FlowAtLocation::new(do_dataflow(
tcx,
body,
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_mir/borrow_check/nll/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ use crate::borrow_check::location::{LocationIndex, LocationTable};
use crate::borrow_check::nll::facts::AllFactsExt;
use crate::borrow_check::nll::type_check::{MirTypeckResults, MirTypeckRegionConstraints};
use crate::borrow_check::nll::region_infer::values::RegionValueElements;
use crate::dataflow::generic::ResultsCursor;
use crate::dataflow::indexes::BorrowIndex;
use crate::dataflow::move_paths::{InitLocation, MoveData, MovePathIndex, InitKind};
use crate::dataflow::FlowAtLocation;
use crate::dataflow::MaybeInitializedPlaces;
use crate::transform::MirSource;
use crate::borrow_check::Upvar;
Expand Down Expand Up @@ -161,7 +161,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
upvars: &[Upvar],
location_table: &LocationTable,
param_env: ty::ParamEnv<'tcx>,
flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'cx, 'tcx>>,
flow_inits: &mut ResultsCursor<'cx, 'tcx, MaybeInitializedPlaces<'cx, 'tcx>>,
move_data: &MoveData<'tcx>,
borrow_set: &BorrowSet<'tcx>,
errors_buffer: &mut Vec<Diagnostic>,
Expand Down
6 changes: 3 additions & 3 deletions src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use crate::borrow_check::nll::facts::{AllFacts, AllFactsExt};
use crate::borrow_check::nll::region_infer::values::RegionValueElements;
use crate::borrow_check::nll::universal_regions::UniversalRegions;
use crate::borrow_check::nll::ToRegionVid;
use crate::dataflow::generic::ResultsCursor;
use crate::dataflow::move_paths::MoveData;
use crate::dataflow::FlowAtLocation;
use crate::dataflow::MaybeInitializedPlaces;
use rustc::mir::{Body, Local};
use rustc::ty::{RegionVid, TyCtxt};
Expand All @@ -26,11 +26,11 @@ mod trace;
///
/// N.B., this computation requires normalization; therefore, it must be
/// performed before
pub(super) fn generate<'tcx>(
pub(super) fn generate<'mir, 'tcx>(
typeck: &mut TypeChecker<'_, 'tcx>,
body: &Body<'tcx>,
elements: &Rc<RegionValueElements>,
flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>,
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
move_data: &MoveData<'tcx>,
location_table: &LocationTable,
) {
Expand Down
40 changes: 22 additions & 18 deletions src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ use crate::borrow_check::nll::type_check::liveness::local_use_map::LocalUseMap;
use crate::borrow_check::nll::type_check::liveness::polonius;
use crate::borrow_check::nll::type_check::NormalizeLocation;
use crate::borrow_check::nll::type_check::TypeChecker;
use crate::dataflow::generic::ResultsCursor;
use crate::dataflow::indexes::MovePathIndex;
use crate::dataflow::move_paths::MoveData;
use crate::dataflow::{FlowAtLocation, FlowsAtLocation, MaybeInitializedPlaces};
use crate::dataflow::move_paths::{HasMoveData, MoveData};
use crate::dataflow::MaybeInitializedPlaces;
use rustc::infer::canonical::QueryRegionConstraints;
use rustc::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
use rustc::traits::query::dropck_outlives::DropckOutlivesResult;
Expand Down Expand Up @@ -34,7 +35,7 @@ pub(super) fn trace(
typeck: &mut TypeChecker<'_, 'tcx>,
body: &Body<'tcx>,
elements: &Rc<RegionValueElements>,
flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>,
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
move_data: &MoveData<'tcx>,
live_locals: Vec<Local>,
polonius_drop_used: Option<Vec<(Local, Location)>>,
Expand Down Expand Up @@ -81,7 +82,7 @@ struct LivenessContext<'me, 'typeck, 'flow, 'tcx> {

/// Results of dataflow tracking which variables (and paths) have been
/// initialized.
flow_inits: &'me mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'flow, 'tcx>>,
flow_inits: &'me mut ResultsCursor<'flow, 'tcx, MaybeInitializedPlaces<'flow, 'tcx>>,

/// Index indicating where each variable is assigned, used, or
/// dropped.
Expand Down Expand Up @@ -389,23 +390,26 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
}

impl LivenessContext<'_, '_, '_, 'tcx> {
/// Returns `true` if the local variable (or some part of it) is initialized at the current
/// cursor position. Callers should call one of the `seek` methods immediately before to point
/// the cursor to the desired location.
fn initialized_at_curr_loc(&self, mpi: MovePathIndex) -> bool {
let state = self.flow_inits.get();
if state.contains(mpi) {
return true;
}

let move_paths = &self.flow_inits.analysis().move_data().move_paths;
move_paths[mpi].find_child(&move_paths, |mpi| state.contains(mpi)).is_some()
}

/// Returns `true` if the local variable (or some part of it) is initialized in
/// the terminator of `block`. We need to check this to determine if a
/// DROP of some local variable will have an effect -- note that
/// drops, as they may unwind, are always terminators.
fn initialized_at_terminator(&mut self, block: BasicBlock, mpi: MovePathIndex) -> bool {
// Compute the set of initialized paths at terminator of block
// by resetting to the start of the block and then applying
// the effects of all statements. This is the only way to get
// "just ahead" of a terminator.
self.flow_inits.reset_to_entry_of(block);
for statement_index in 0..self.body[block].statements.len() {
let location = Location { block, statement_index };
self.flow_inits.reconstruct_statement_effect(location);
self.flow_inits.apply_local_effect(location);
}

self.flow_inits.has_any_child_of(mpi).is_some()
self.flow_inits.seek_before(self.body.terminator_loc(block));
self.initialized_at_curr_loc(mpi)
}

/// Returns `true` if the path `mpi` (or some part of it) is initialized at
Expand All @@ -414,8 +418,8 @@ impl LivenessContext<'_, '_, '_, 'tcx> {
/// **Warning:** Does not account for the result of `Call`
/// instructions.
fn initialized_at_exit(&mut self, block: BasicBlock, mpi: MovePathIndex) -> bool {
self.flow_inits.reset_to_exit_of(block);
self.flow_inits.has_any_child_of(mpi).is_some()
self.flow_inits.seek_after(self.body.terminator_loc(block));
self.initialized_at_curr_loc(mpi)
}

/// Stores the result that all regions in `value` are live for the
Expand Down
6 changes: 3 additions & 3 deletions src/librustc_mir/borrow_check/nll/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ use crate::borrow_check::nll::type_check::free_region_relations::{
use crate::borrow_check::nll::universal_regions::{DefiningTy, UniversalRegions};
use crate::borrow_check::nll::ToRegionVid;
use crate::transform::promote_consts::should_suggest_const_in_array_repeat_expressions_attribute;
use crate::dataflow::generic::ResultsCursor;
use crate::dataflow::move_paths::MoveData;
use crate::dataflow::FlowAtLocation;
use crate::dataflow::MaybeInitializedPlaces;
use either::Either;
use rustc::hir;
Expand Down Expand Up @@ -112,7 +112,7 @@ mod relate_tys;
/// constraints for the regions in the types of variables
/// - `flow_inits` -- results of a maybe-init dataflow analysis
/// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis
pub(crate) fn type_check<'tcx>(
pub(crate) fn type_check<'mir, 'tcx>(
infcx: &InferCtxt<'_, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>,
Expand All @@ -122,7 +122,7 @@ pub(crate) fn type_check<'tcx>(
location_table: &LocationTable,
borrow_set: &BorrowSet<'tcx>,
all_facts: &mut Option<AllFacts>,
flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>,
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
move_data: &MoveData<'tcx>,
elements: &Rc<RegionValueElements>,
) -> MirTypeckResults<'tcx> {
Expand Down
Loading

0 comments on commit 43d649e

Please sign in to comment.