Skip to content

rustc_mir: Hide initial block state when defining transfer functions #61787

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 24, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions src/librustc_data_structures/bit_set.rs
Original file line number Diff line number Diff line change
@@ -273,11 +273,6 @@ impl<'a, T: Idx> Iterator for BitIter<'a, T> {
}
}

pub trait BitSetOperator {
/// Combine one bitset into another.
fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool;
}

#[inline]
fn bitwise<Op>(out_vec: &mut [Word], in_vec: &[Word], op: Op) -> bool
where Op: Fn(Word, Word) -> Word
77 changes: 23 additions & 54 deletions src/librustc_mir/dataflow/at_location.rs
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@
use rustc::mir::{BasicBlock, Location};
use rustc_data_structures::bit_set::{BitIter, BitSet, HybridBitSet};

use crate::dataflow::{BitDenotation, BlockSets, DataflowResults};
use crate::dataflow::{BitDenotation, DataflowResults, GenKillSet};
use crate::dataflow::move_paths::{HasMoveData, MovePathIndex};

use std::iter;
@@ -66,8 +66,7 @@ where
{
base_results: DataflowResults<'tcx, BD>,
curr_state: BitSet<BD::Idx>,
stmt_gen: HybridBitSet<BD::Idx>,
stmt_kill: HybridBitSet<BD::Idx>,
stmt_trans: GenKillSet<BD::Idx>,
}

impl<'tcx, BD> FlowAtLocation<'tcx, BD>
@@ -89,19 +88,17 @@ where
where
F: FnMut(BD::Idx),
{
self.stmt_gen.iter().for_each(f)
self.stmt_trans.gen_set.iter().for_each(f)
}

pub fn new(results: DataflowResults<'tcx, BD>) -> Self {
let bits_per_block = results.sets().bits_per_block();
let curr_state = BitSet::new_empty(bits_per_block);
let stmt_gen = HybridBitSet::new_empty(bits_per_block);
let stmt_kill = HybridBitSet::new_empty(bits_per_block);
let stmt_trans = GenKillSet::from_elem(HybridBitSet::new_empty(bits_per_block));
FlowAtLocation {
base_results: results,
curr_state: curr_state,
stmt_gen: stmt_gen,
stmt_kill: stmt_kill,
curr_state,
stmt_trans,
}
}

@@ -127,8 +124,7 @@ where
F: FnOnce(BitIter<'_, BD::Idx>),
{
let mut curr_state = self.curr_state.clone();
curr_state.union(&self.stmt_gen);
curr_state.subtract(&self.stmt_kill);
self.stmt_trans.apply(&mut curr_state);
f(curr_state.iter());
}

@@ -142,68 +138,41 @@ impl<'tcx, BD> FlowsAtLocation for FlowAtLocation<'tcx, BD>
where BD: BitDenotation<'tcx>
{
fn reset_to_entry_of(&mut self, bb: BasicBlock) {
self.curr_state.overwrite(self.base_results.sets().on_entry_set_for(bb.index()));
self.curr_state.overwrite(self.base_results.sets().entry_set_for(bb.index()));
}

fn reset_to_exit_of(&mut self, bb: BasicBlock) {
self.reset_to_entry_of(bb);
self.curr_state.union(self.base_results.sets().gen_set_for(bb.index()));
self.curr_state.subtract(self.base_results.sets().kill_set_for(bb.index()));
let trans = self.base_results.sets().trans_for(bb.index());
trans.apply(&mut self.curr_state)
}

fn reconstruct_statement_effect(&mut self, loc: Location) {
self.stmt_gen.clear();
self.stmt_kill.clear();
{
let mut sets = BlockSets {
on_entry: &mut self.curr_state,
gen_set: &mut self.stmt_gen,
kill_set: &mut self.stmt_kill,
};
self.base_results
.operator()
.before_statement_effect(&mut sets, loc);
}
self.apply_local_effect(loc);
self.stmt_trans.clear();
self.base_results
.operator()
.before_statement_effect(&mut self.stmt_trans, loc);
self.stmt_trans.apply(&mut self.curr_state);

let mut sets = BlockSets {
on_entry: &mut self.curr_state,
gen_set: &mut self.stmt_gen,
kill_set: &mut self.stmt_kill,
};
self.base_results
.operator()
.statement_effect(&mut sets, loc);
.statement_effect(&mut self.stmt_trans, loc);
}

fn reconstruct_terminator_effect(&mut self, loc: Location) {
self.stmt_gen.clear();
self.stmt_kill.clear();
{
let mut sets = BlockSets {
on_entry: &mut self.curr_state,
gen_set: &mut self.stmt_gen,
kill_set: &mut self.stmt_kill,
};
self.base_results
.operator()
.before_terminator_effect(&mut sets, loc);
}
self.apply_local_effect(loc);
self.stmt_trans.clear();
self.base_results
.operator()
.before_terminator_effect(&mut self.stmt_trans, loc);
self.stmt_trans.apply(&mut self.curr_state);

let mut sets = BlockSets {
on_entry: &mut self.curr_state,
gen_set: &mut self.stmt_gen,
kill_set: &mut self.stmt_kill,
};
self.base_results
.operator()
.terminator_effect(&mut sets, loc);
.terminator_effect(&mut self.stmt_trans, loc);
}

fn apply_local_effect(&mut self, _loc: Location) {
self.curr_state.union(&self.stmt_gen);
self.curr_state.subtract(&self.stmt_kill);
self.stmt_trans.apply(&mut self.curr_state)
}
}

15 changes: 6 additions & 9 deletions src/librustc_mir/dataflow/graphviz.rs
Original file line number Diff line number Diff line change
@@ -170,7 +170,7 @@ where MWF: MirWithFlowState<'tcx>,

write!(w, "<tr>")?;
// Entry
dump_set_for!(on_entry_set_for, interpret_set);
dump_set_for!(entry_set_for, interpret_set);

// MIR statements
write!(w, "<td>")?;
@@ -208,7 +208,7 @@ where MWF: MirWithFlowState<'tcx>,
write!(w, "<tr>")?;

// Entry
let set = flow.sets.on_entry_set_for(i);
let set = flow.sets.entry_set_for(i);
write!(w, "<td>{:?}</td>", dot::escape_html(&set.to_string()))?;

// Terminator
@@ -221,13 +221,10 @@ where MWF: MirWithFlowState<'tcx>,
}
write!(w, "</td>")?;

// Gen
let set = flow.sets.gen_set_for(i);
write!(w, "<td>{:?}</td>", dot::escape_html(&format!("{:?}", set)))?;

// Kill
let set = flow.sets.kill_set_for(i);
write!(w, "<td>{:?}</td>", dot::escape_html(&format!("{:?}", set)))?;
// Gen/Kill
let trans = flow.sets.trans_for(i);
write!(w, "<td>{:?}</td>", dot::escape_html(&format!("{:?}", trans.gen_set)))?;
write!(w, "<td>{:?}</td>", dot::escape_html(&format!("{:?}", trans.kill_set)))?;

write!(w, "</tr>")?;

39 changes: 15 additions & 24 deletions src/librustc_mir/dataflow/impls/borrowed_locals.rs
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ pub use super::*;

use rustc::mir::*;
use rustc::mir::visit::Visitor;
use crate::dataflow::BitDenotation;
use crate::dataflow::{BitDenotation, GenKillSet};

/// This calculates if any part of a MIR local could have previously been borrowed.
/// This means that once a local has been borrowed, its bit will be set
@@ -33,39 +33,39 @@ impl<'a, 'tcx> BitDenotation<'tcx> for HaveBeenBorrowedLocals<'a, 'tcx> {
self.body.local_decls.len()
}

fn start_block_effect(&self, _sets: &mut BitSet<Local>) {
fn start_block_effect(&self, _on_entry: &mut BitSet<Local>) {
// Nothing is borrowed on function entry
}

fn statement_effect(&self,
sets: &mut BlockSets<'_, Local>,
trans: &mut GenKillSet<Local>,
loc: Location) {
let stmt = &self.body[loc.block].statements[loc.statement_index];

BorrowedLocalsVisitor {
sets,
trans,
}.visit_statement(stmt, loc);

// StorageDead invalidates all borrows and raw pointers to a local
match stmt.kind {
StatementKind::StorageDead(l) => sets.kill(l),
StatementKind::StorageDead(l) => trans.kill(l),
_ => (),
}
}

fn terminator_effect(&self,
sets: &mut BlockSets<'_, Local>,
trans: &mut GenKillSet<Local>,
loc: Location) {
let terminator = self.body[loc.block].terminator();
BorrowedLocalsVisitor {
sets,
trans,
}.visit_terminator(terminator, loc);
match &terminator.kind {
// Drop terminators borrows the location
TerminatorKind::Drop { location, .. } |
TerminatorKind::DropAndReplace { location, .. } => {
if let Some(local) = find_local(location) {
sets.gen(local);
trans.gen(local);
}
}
_ => (),
@@ -83,22 +83,13 @@ impl<'a, 'tcx> BitDenotation<'tcx> for HaveBeenBorrowedLocals<'a, 'tcx> {
}
}

impl<'a, 'tcx> BitSetOperator for HaveBeenBorrowedLocals<'a, 'tcx> {
#[inline]
fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
inout_set.union(in_set) // "maybe" means we union effects of both preds
}
}

impl<'a, 'tcx> InitialFlow for HaveBeenBorrowedLocals<'a, 'tcx> {
#[inline]
fn bottom_value() -> bool {
false // bottom = unborrowed
}
impl<'a, 'tcx> BottomValue for HaveBeenBorrowedLocals<'a, 'tcx> {
// bottom = unborrowed
const BOTTOM_VALUE: bool = false;
}

struct BorrowedLocalsVisitor<'b, 'c> {
sets: &'b mut BlockSets<'c, Local>,
struct BorrowedLocalsVisitor<'gk> {
trans: &'gk mut GenKillSet<Local>,
}

fn find_local<'tcx>(place: &Place<'tcx>) -> Option<Local> {
@@ -117,13 +108,13 @@ fn find_local<'tcx>(place: &Place<'tcx>) -> Option<Local> {
})
}

impl<'tcx, 'b, 'c> Visitor<'tcx> for BorrowedLocalsVisitor<'b, 'c> {
impl<'tcx> Visitor<'tcx> for BorrowedLocalsVisitor<'_> {
fn visit_rvalue(&mut self,
rvalue: &Rvalue<'tcx>,
location: Location) {
if let Rvalue::Ref(_, _, ref place) = *rvalue {
if let Some(local) = find_local(place) {
self.sets.gen(local);
self.trans.gen(local);
}
}

67 changes: 32 additions & 35 deletions src/librustc_mir/dataflow/impls/borrows.rs
Original file line number Diff line number Diff line change
@@ -5,11 +5,11 @@ use rustc::mir::{self, Location, Place, PlaceBase, Body};
use rustc::ty::TyCtxt;
use rustc::ty::RegionVid;

use rustc_data_structures::bit_set::{BitSet, BitSetOperator};
use rustc_data_structures::bit_set::BitSet;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::indexed_vec::{Idx, IndexVec};

use crate::dataflow::{BitDenotation, BlockSets, InitialFlow};
use crate::dataflow::{BitDenotation, BottomValue, GenKillSet};
use crate::borrow_check::nll::region_infer::RegionInferenceContext;
use crate::borrow_check::nll::ToRegionVid;
use crate::borrow_check::places_conflict;
@@ -168,7 +168,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
/// Add all borrows to the kill set, if those borrows are out of scope at `location`.
/// That means they went out of a nonlexical scope
fn kill_loans_out_of_scope_at_location(&self,
sets: &mut BlockSets<'_, BorrowIndex>,
trans: &mut GenKillSet<BorrowIndex>,
location: Location) {
// NOTE: The state associated with a given `location`
// reflects the dataflow on entry to the statement.
@@ -182,14 +182,14 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
// region, then setting that gen-bit will override any
// potential kill introduced here.
if let Some(indices) = self.borrows_out_of_scope_at_location.get(&location) {
sets.kill_all(indices);
trans.kill_all(indices);
}
}

/// Kill any borrows that conflict with `place`.
fn kill_borrows_on_place(
&self,
sets: &mut BlockSets<'_, BorrowIndex>,
trans: &mut GenKillSet<BorrowIndex>,
place: &Place<'tcx>
) {
debug!("kill_borrows_on_place: place={:?}", place);
@@ -206,7 +206,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
// local must conflict. This is purely an optimization so we don't have to call
// `places_conflict` for every borrow.
if let Place::Base(PlaceBase::Local(_)) = place {
sets.kill_all(other_borrows_of_local);
trans.kill_all(other_borrows_of_local);
return;
}

@@ -224,7 +224,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
places_conflict::PlaceConflictBias::NoOverlap)
});

sets.kill_all(definitely_conflicting_borrows);
trans.kill_all(definitely_conflicting_borrows);
}
}
}
@@ -236,21 +236,24 @@ impl<'a, 'tcx> BitDenotation<'tcx> for Borrows<'a, 'tcx> {
self.borrow_set.borrows.len() * 2
}

fn start_block_effect(&self, _entry_set: &mut BitSet<BorrowIndex>) {
fn start_block_effect(&self, _entry_set: &mut BitSet<Self::Idx>) {
// no borrows of code region_scopes have been taken prior to
// function execution, so this method has no effect on
// `_sets`.
// function execution, so this method has no effect.
}

fn before_statement_effect(&self,
sets: &mut BlockSets<'_, BorrowIndex>,
trans: &mut GenKillSet<Self::Idx>,
location: Location) {
debug!("Borrows::before_statement_effect sets: {:?} location: {:?}", sets, location);
self.kill_loans_out_of_scope_at_location(sets, location);
debug!("Borrows::before_statement_effect trans: {:?} location: {:?}",
trans, location);
self.kill_loans_out_of_scope_at_location(trans, location);
}

fn statement_effect(&self, sets: &mut BlockSets<'_, BorrowIndex>, location: Location) {
debug!("Borrows::statement_effect: sets={:?} location={:?}", sets, location);
fn statement_effect(&self,
trans: &mut GenKillSet<Self::Idx>,
location: Location) {
debug!("Borrows::statement_effect: trans={:?} location={:?}",
trans, location);

let block = &self.body.basic_blocks().get(location.block).unwrap_or_else(|| {
panic!("could not find block at location {:?}", location);
@@ -264,7 +267,7 @@ impl<'a, 'tcx> BitDenotation<'tcx> for Borrows<'a, 'tcx> {
mir::StatementKind::Assign(ref lhs, ref rhs) => {
// Make sure there are no remaining borrows for variables
// that are assigned over.
self.kill_borrows_on_place(sets, lhs);
self.kill_borrows_on_place(trans, lhs);

if let mir::Rvalue::Ref(_, _, ref place) = **rhs {
if place.ignore_borrow(
@@ -278,20 +281,20 @@ impl<'a, 'tcx> BitDenotation<'tcx> for Borrows<'a, 'tcx> {
panic!("could not find BorrowIndex for location {:?}", location);
});

sets.gen(*index);
trans.gen(*index);
}
}

mir::StatementKind::StorageDead(local) => {
// Make sure there are no remaining borrows for locals that
// are gone out of scope.
self.kill_borrows_on_place(sets, &Place::Base(PlaceBase::Local(local)));
self.kill_borrows_on_place(trans, &Place::Base(PlaceBase::Local(local)));
}

mir::StatementKind::InlineAsm(ref asm) => {
for (output, kind) in asm.outputs.iter().zip(&asm.asm.outputs) {
if !kind.is_indirect && !kind.is_rw {
self.kill_borrows_on_place(sets, output);
self.kill_borrows_on_place(trans, output);
}
}
}
@@ -307,13 +310,16 @@ impl<'a, 'tcx> BitDenotation<'tcx> for Borrows<'a, 'tcx> {
}

fn before_terminator_effect(&self,
sets: &mut BlockSets<'_, BorrowIndex>,
trans: &mut GenKillSet<Self::Idx>,
location: Location) {
debug!("Borrows::before_terminator_effect sets: {:?} location: {:?}", sets, location);
self.kill_loans_out_of_scope_at_location(sets, location);
debug!("Borrows::before_terminator_effect: trans={:?} location={:?}",
trans, location);
self.kill_loans_out_of_scope_at_location(trans, location);
}

fn terminator_effect(&self, _: &mut BlockSets<'_, BorrowIndex>, _: Location) {}
fn terminator_effect(&self,
_: &mut GenKillSet<Self::Idx>,
_: Location) {}

fn propagate_call_return(
&self,
@@ -325,16 +331,7 @@ impl<'a, 'tcx> BitDenotation<'tcx> for Borrows<'a, 'tcx> {
}
}

impl<'a, 'tcx> BitSetOperator for Borrows<'a, 'tcx> {
#[inline]
fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
inout_set.union(in_set) // "maybe" means we union effects of both preds
}
}

impl<'a, 'tcx> InitialFlow for Borrows<'a, 'tcx> {
#[inline]
fn bottom_value() -> bool {
false // bottom = nothing is reserved or activated yet
}
impl<'a, 'tcx> BottomValue for Borrows<'a, 'tcx> {
/// bottom = nothing is reserved or activated yet;
const BOTTOM_VALUE: bool = false;
}
129 changes: 43 additions & 86 deletions src/librustc_mir/dataflow/impls/mod.rs
Original file line number Diff line number Diff line change
@@ -4,15 +4,15 @@
use rustc::ty::TyCtxt;
use rustc::mir::{self, Body, Location};
use rustc_data_structures::bit_set::{BitSet, BitSetOperator};
use rustc_data_structures::bit_set::BitSet;
use rustc_data_structures::indexed_vec::Idx;

use super::MoveDataParamEnv;

use crate::util::elaborate_drops::DropFlagState;

use super::move_paths::{HasMoveData, MoveData, MovePathIndex, InitIndex, InitKind};
use super::{BitDenotation, BlockSets, InitialFlow};
use super::{BitDenotation, BottomValue, GenKillSet};

use super::drop_flag_effects_for_function_entry;
use super::drop_flag_effects_for_location;
@@ -226,34 +226,37 @@ impl<'a, 'tcx> HasMoveData<'tcx> for EverInitializedPlaces<'a, 'tcx> {
}

impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> {
fn update_bits(sets: &mut BlockSets<'_, MovePathIndex>, path: MovePathIndex,
fn update_bits(trans: &mut GenKillSet<MovePathIndex>,
path: MovePathIndex,
state: DropFlagState)
{
match state {
DropFlagState::Absent => sets.kill(path),
DropFlagState::Present => sets.gen(path),
DropFlagState::Absent => trans.kill(path),
DropFlagState::Present => trans.gen(path),
}
}
}

impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> {
fn update_bits(sets: &mut BlockSets<'_, MovePathIndex>, path: MovePathIndex,
fn update_bits(trans: &mut GenKillSet<MovePathIndex>,
path: MovePathIndex,
state: DropFlagState)
{
match state {
DropFlagState::Absent => sets.gen(path),
DropFlagState::Present => sets.kill(path),
DropFlagState::Absent => trans.gen(path),
DropFlagState::Present => trans.kill(path),
}
}
}

impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> {
fn update_bits(sets: &mut BlockSets<'_, MovePathIndex>, path: MovePathIndex,
fn update_bits(trans: &mut GenKillSet<MovePathIndex>,
path: MovePathIndex,
state: DropFlagState)
{
match state {
DropFlagState::Absent => sets.kill(path),
DropFlagState::Present => sets.gen(path),
DropFlagState::Absent => trans.kill(path),
DropFlagState::Present => trans.gen(path),
}
}
}
@@ -275,24 +278,24 @@ impl<'a, 'tcx> BitDenotation<'tcx> for MaybeInitializedPlaces<'a, 'tcx> {
}

fn statement_effect(&self,
sets: &mut BlockSets<'_, MovePathIndex>,
trans: &mut GenKillSet<Self::Idx>,
location: Location)
{
drop_flag_effects_for_location(
self.tcx, self.body, self.mdpe,
location,
|path, s| Self::update_bits(sets, path, s)
|path, s| Self::update_bits(trans, path, s)
)
}

fn terminator_effect(&self,
sets: &mut BlockSets<'_, MovePathIndex>,
trans: &mut GenKillSet<Self::Idx>,
location: Location)
{
drop_flag_effects_for_location(
self.tcx, self.body, self.mdpe,
location,
|path, s| Self::update_bits(sets, path, s)
|path, s| Self::update_bits(trans, path, s)
)
}

@@ -333,24 +336,24 @@ impl<'a, 'tcx> BitDenotation<'tcx> for MaybeUninitializedPlaces<'a, 'tcx> {
}

fn statement_effect(&self,
sets: &mut BlockSets<'_, MovePathIndex>,
trans: &mut GenKillSet<Self::Idx>,
location: Location)
{
drop_flag_effects_for_location(
self.tcx, self.body, self.mdpe,
location,
|path, s| Self::update_bits(sets, path, s)
|path, s| Self::update_bits(trans, path, s)
)
}

fn terminator_effect(&self,
sets: &mut BlockSets<'_, MovePathIndex>,
trans: &mut GenKillSet<Self::Idx>,
location: Location)
{
drop_flag_effects_for_location(
self.tcx, self.body, self.mdpe,
location,
|path, s| Self::update_bits(sets, path, s)
|path, s| Self::update_bits(trans, path, s)
)
}

@@ -389,24 +392,24 @@ impl<'a, 'tcx> BitDenotation<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> {
}

fn statement_effect(&self,
sets: &mut BlockSets<'_, MovePathIndex>,
trans: &mut GenKillSet<Self::Idx>,
location: Location)
{
drop_flag_effects_for_location(
self.tcx, self.body, self.mdpe,
location,
|path, s| Self::update_bits(sets, path, s)
|path, s| Self::update_bits(trans, path, s)
)
}

fn terminator_effect(&self,
sets: &mut BlockSets<'_, MovePathIndex>,
trans: &mut GenKillSet<Self::Idx>,
location: Location)
{
drop_flag_effects_for_location(
self.tcx, self.body, self.mdpe,
location,
|path, s| Self::update_bits(sets, path, s)
|path, s| Self::update_bits(trans, path, s)
)
}

@@ -439,7 +442,7 @@ impl<'a, 'tcx> BitDenotation<'tcx> for EverInitializedPlaces<'a, 'tcx> {
}

fn statement_effect(&self,
sets: &mut BlockSets<'_, InitIndex>,
trans: &mut GenKillSet<Self::Idx>,
location: Location) {
let (_, body, move_data) = (self.tcx, self.body, self.move_data());
let stmt = &body[location.block].statements[location.statement_index];
@@ -449,7 +452,7 @@ impl<'a, 'tcx> BitDenotation<'tcx> for EverInitializedPlaces<'a, 'tcx> {

debug!("statement {:?} at loc {:?} initializes move_indexes {:?}",
stmt, location, &init_loc_map[location]);
sets.gen_all(&init_loc_map[location]);
trans.gen_all(&init_loc_map[location]);

match stmt.kind {
mir::StatementKind::StorageDead(local) => {
@@ -458,22 +461,22 @@ impl<'a, 'tcx> BitDenotation<'tcx> for EverInitializedPlaces<'a, 'tcx> {
let move_path_index = rev_lookup.find_local(local);
debug!("stmt {:?} at loc {:?} clears the ever initialized status of {:?}",
stmt, location, &init_path_map[move_path_index]);
sets.kill_all(&init_path_map[move_path_index]);
trans.kill_all(&init_path_map[move_path_index]);
}
_ => {}
}
}

fn terminator_effect(&self,
sets: &mut BlockSets<'_, InitIndex>,
trans: &mut GenKillSet<Self::Idx>,
location: Location)
{
let (body, move_data) = (self.body, self.move_data());
let term = body[location.block].terminator();
let init_loc_map = &move_data.init_loc_map;
debug!("terminator {:?} at loc {:?} initializes move_indexes {:?}",
term, location, &init_loc_map[location]);
sets.gen_all(
trans.gen_all(
init_loc_map[location].iter().filter(|init_index| {
move_data.inits[**init_index].kind != InitKind::NonPanicPathOnly
})
@@ -502,68 +505,22 @@ impl<'a, 'tcx> BitDenotation<'tcx> for EverInitializedPlaces<'a, 'tcx> {
}
}

impl<'a, 'tcx> BitSetOperator for MaybeInitializedPlaces<'a, 'tcx> {
#[inline]
fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
inout_set.union(in_set) // "maybe" means we union effects of both preds
}
}

impl<'a, 'tcx> BitSetOperator for MaybeUninitializedPlaces<'a, 'tcx> {
#[inline]
fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
inout_set.union(in_set) // "maybe" means we union effects of both preds
}
}

impl<'a, 'tcx> BitSetOperator for DefinitelyInitializedPlaces<'a, 'tcx> {
#[inline]
fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
inout_set.intersect(in_set) // "definitely" means we intersect effects of both preds
}
}

impl<'a, 'tcx> BitSetOperator for EverInitializedPlaces<'a, 'tcx> {
#[inline]
fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
inout_set.union(in_set) // inits from both preds are in scope
}
}

// The way that dataflow fixed point iteration works, you want to
// start at bottom and work your way to a fixed point. Control-flow
// merges will apply the `join` operator to each block entry's current
// state (which starts at that bottom value).
//
// This means, for propagation across the graph, that you either want
// to start at all-zeroes and then use Union as your merge when
// propagating, or you start at all-ones and then use Intersect as
// your merge when propagating.

impl<'a, 'tcx> InitialFlow for MaybeInitializedPlaces<'a, 'tcx> {
#[inline]
fn bottom_value() -> bool {
false // bottom = uninitialized
}
impl<'a, 'tcx> BottomValue for MaybeInitializedPlaces<'a, 'tcx> {
/// bottom = uninitialized
const BOTTOM_VALUE: bool = false;
}

impl<'a, 'tcx> InitialFlow for MaybeUninitializedPlaces<'a, 'tcx> {
#[inline]
fn bottom_value() -> bool {
false // bottom = initialized (start_block_effect counters this at outset)
}
impl<'a, 'tcx> BottomValue for MaybeUninitializedPlaces<'a, 'tcx> {
/// bottom = initialized (start_block_effect counters this at outset)
const BOTTOM_VALUE: bool = false;
}

impl<'a, 'tcx> InitialFlow for DefinitelyInitializedPlaces<'a, 'tcx> {
#[inline]
fn bottom_value() -> bool {
true // bottom = initialized (start_block_effect counters this at outset)
}
impl<'a, 'tcx> BottomValue for DefinitelyInitializedPlaces<'a, 'tcx> {
/// bottom = initialized (start_block_effect counters this at outset)
const BOTTOM_VALUE: bool = true;
}

impl<'a, 'tcx> InitialFlow for EverInitializedPlaces<'a, 'tcx> {
#[inline]
fn bottom_value() -> bool {
false // bottom = no initialized variables by default
}
impl<'a, 'tcx> BottomValue for EverInitializedPlaces<'a, 'tcx> {
/// bottom = no initialized variables by default
const BOTTOM_VALUE: bool = false;
}
25 changes: 8 additions & 17 deletions src/librustc_mir/dataflow/impls/storage_liveness.rs
Original file line number Diff line number Diff line change
@@ -26,24 +26,24 @@ impl<'a, 'tcx> BitDenotation<'tcx> for MaybeStorageLive<'a, 'tcx> {
self.body.local_decls.len()
}

fn start_block_effect(&self, _sets: &mut BitSet<Local>) {
fn start_block_effect(&self, _on_entry: &mut BitSet<Local>) {
// Nothing is live on function entry
}

fn statement_effect(&self,
sets: &mut BlockSets<'_, Local>,
trans: &mut GenKillSet<Local>,
loc: Location) {
let stmt = &self.body[loc.block].statements[loc.statement_index];

match stmt.kind {
StatementKind::StorageLive(l) => sets.gen(l),
StatementKind::StorageDead(l) => sets.kill(l),
StatementKind::StorageLive(l) => trans.gen(l),
StatementKind::StorageDead(l) => trans.kill(l),
_ => (),
}
}

fn terminator_effect(&self,
_sets: &mut BlockSets<'_, Local>,
_trans: &mut GenKillSet<Local>,
_loc: Location) {
// Terminators have no effect
}
@@ -59,16 +59,7 @@ impl<'a, 'tcx> BitDenotation<'tcx> for MaybeStorageLive<'a, 'tcx> {
}
}

impl<'a, 'tcx> BitSetOperator for MaybeStorageLive<'a, 'tcx> {
#[inline]
fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
inout_set.union(in_set) // "maybe" means we union effects of both preds
}
}

impl<'a, 'tcx> InitialFlow for MaybeStorageLive<'a, 'tcx> {
#[inline]
fn bottom_value() -> bool {
false // bottom = dead
}
impl<'a, 'tcx> BottomValue for MaybeStorageLive<'a, 'tcx> {
/// bottom = dead
const BOTTOM_VALUE: bool = false;
}
292 changes: 135 additions & 157 deletions src/librustc_mir/dataflow/mod.rs

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions src/librustc_mir/transform/elaborate_drops.rs
Original file line number Diff line number Diff line change
@@ -95,7 +95,7 @@ fn find_dead_unwinds<'tcx>(
};

let mut init_data = InitializationData {
live: flow_inits.sets().on_entry_set_for(bb.index()).to_owned(),
live: flow_inits.sets().entry_set_for(bb.index()).to_owned(),
dead: BitSet::new_empty(env.move_data.move_paths.len()),
};
debug!("find_dead_unwinds @ {:?}: {:?}; init_data={:?}",
@@ -304,9 +304,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {

fn initialization_data_at(&self, loc: Location) -> InitializationData {
let mut data = InitializationData {
live: self.flow_inits.sets().on_entry_set_for(loc.block.index())
live: self.flow_inits.sets().entry_set_for(loc.block.index())
.to_owned(),
dead: self.flow_uninits.sets().on_entry_set_for(loc.block.index())
dead: self.flow_uninits.sets().entry_set_for(loc.block.index())
.to_owned(),
};
for stmt in 0..loc.statement_index {
26 changes: 10 additions & 16 deletions src/librustc_mir/transform/rustc_peek.rs
Original file line number Diff line number Diff line change
@@ -18,7 +18,6 @@ use crate::dataflow::{
};
use crate::dataflow::move_paths::{MovePathIndex, LookupResult};
use crate::dataflow::move_paths::{HasMoveData, MoveData};
use crate::dataflow;

use crate::dataflow::has_rustc_mir_with;

@@ -133,20 +132,15 @@ fn each_block<'tcx, O>(
}
};

let mut on_entry = results.0.sets.on_entry_set_for(bb.index()).to_owned();
let mut gen_set = results.0.sets.gen_set_for(bb.index()).clone();
let mut kill_set = results.0.sets.kill_set_for(bb.index()).clone();
let mut on_entry = results.0.sets.entry_set_for(bb.index()).to_owned();
let mut trans = results.0.sets.trans_for(bb.index()).clone();

// Emulate effect of all statements in the block up to (but not
// including) the borrow within `peek_arg_place`. Do *not* include
// call to `peek_arg_place` itself (since we are peeking the state
// of the argument at time immediate preceding Call to
// `rustc_peek`).

let mut sets = dataflow::BlockSets { on_entry: &mut on_entry,
gen_set: &mut gen_set,
kill_set: &mut kill_set };

for (j, stmt) in statements.iter().enumerate() {
debug!("rustc_peek: ({:?},{}) {:?}", bb, j, stmt);
let (place, rvalue) = match stmt.kind {
@@ -170,7 +164,7 @@ fn each_block<'tcx, O>(
// Okay, our search is over.
match move_data.rev_lookup.find(peeking_at_place) {
LookupResult::Exact(peek_mpi) => {
let bit_state = sets.on_entry.contains(peek_mpi);
let bit_state = on_entry.contains(peek_mpi);
debug!("rustc_peek({:?} = &{:?}) bit_state: {}",
place, peeking_at_place, bit_state);
if !bit_state {
@@ -197,18 +191,18 @@ fn each_block<'tcx, O>(
debug!("rustc_peek: computing effect on place: {:?} ({:?}) in stmt: {:?}",
place, lhs_mpi, stmt);
// reset GEN and KILL sets before emulating their effect.
sets.gen_set.clear();
sets.kill_set.clear();
trans.clear();
results.0.operator.before_statement_effect(
&mut sets, Location { block: bb, statement_index: j });
&mut trans,
Location { block: bb, statement_index: j });
results.0.operator.statement_effect(
&mut sets, Location { block: bb, statement_index: j });
sets.on_entry.union(sets.gen_set);
sets.on_entry.subtract(sets.kill_set);
&mut trans,
Location { block: bb, statement_index: j });
trans.apply(&mut on_entry);
}

results.0.operator.before_terminator_effect(
&mut sets,
&mut trans,
Location { block: bb, statement_index: statements.len() });

tcx.sess.span_err(span, &format!("rustc_peek: MIR did not match \