Refactoring: pull bitvector initialization out from other parts of dataflow.

This is meant to ease development of multi-stage dataflow analyses
where the output from one analysis is used to initialize the state
for the next; in such a context, you cannot start with `bottom_value`
for all the bits.
This commit is contained in:
Felix S. Klock II 2017-11-27 15:08:11 +01:00
parent 171c2aeb25
commit d4add5d52a
4 changed files with 18 additions and 21 deletions

View file

@ -22,7 +22,7 @@ use rustc_data_structures::bitslice::{BitwiseOperator};
use rustc_data_structures::indexed_set::{IdxSet};
use rustc_data_structures::indexed_vec::{IndexVec};
use dataflow::{BitDenotation, BlockSets, DataflowOperator};
use dataflow::{BitDenotation, BlockSets, InitialFlow};
pub use dataflow::indexes::BorrowIndex;
use borrow_check::nll::region_infer::RegionInferenceContext;
use borrow_check::nll::ToRegionVid;
@ -339,7 +339,7 @@ impl<'a, 'gcx, 'tcx> BitwiseOperator for Borrows<'a, 'gcx, 'tcx> {
}
}
impl<'a, 'gcx, 'tcx> DataflowOperator for Borrows<'a, 'gcx, 'tcx> {
impl<'a, 'gcx, 'tcx> InitialFlow for Borrows<'a, 'gcx, 'tcx> {
#[inline]
fn bottom_value() -> bool {
false // bottom = no Rvalue::Refs are active by default

View file

@ -23,7 +23,7 @@ use util::elaborate_drops::DropFlagState;
use super::move_paths::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex, InitIndex};
use super::move_paths::{LookupResult, InitKind};
use super::{BitDenotation, BlockSets, DataflowOperator};
use super::{BitDenotation, BlockSets, InitialFlow};
use super::drop_flag_effects_for_function_entry;
use super::drop_flag_effects_for_location;
@ -702,35 +702,35 @@ impl<'a, 'gcx, 'tcx> BitwiseOperator for EverInitializedLvals<'a, 'gcx, 'tcx> {
// propagating, or you start at all-ones and then use Intersect as
// your merge when propagating.
impl<'a, 'gcx, 'tcx> DataflowOperator for MaybeInitializedLvals<'a, 'gcx, 'tcx> {
impl<'a, 'gcx, 'tcx> InitialFlow for MaybeInitializedLvals<'a, 'gcx, 'tcx> {
#[inline]
fn bottom_value() -> bool {
false // bottom = uninitialized
}
}
impl<'a, 'gcx, 'tcx> DataflowOperator for MaybeUninitializedLvals<'a, 'gcx, 'tcx> {
impl<'a, 'gcx, 'tcx> InitialFlow for MaybeUninitializedLvals<'a, 'gcx, 'tcx> {
#[inline]
fn bottom_value() -> bool {
false // bottom = initialized (start_block_effect counters this at outset)
}
}
impl<'a, 'gcx, 'tcx> DataflowOperator for DefinitelyInitializedLvals<'a, 'gcx, 'tcx> {
impl<'a, 'gcx, 'tcx> InitialFlow for DefinitelyInitializedLvals<'a, 'gcx, 'tcx> {
#[inline]
fn bottom_value() -> bool {
true // bottom = initialized (start_block_effect counters this at outset)
}
}
impl<'a, 'gcx, 'tcx> DataflowOperator for MovingOutStatements<'a, 'gcx, 'tcx> {
impl<'a, 'gcx, 'tcx> InitialFlow for MovingOutStatements<'a, 'gcx, 'tcx> {
#[inline]
fn bottom_value() -> bool {
false // bottom = no loans in scope by default
}
}
impl<'a, 'gcx, 'tcx> DataflowOperator for EverInitializedLvals<'a, 'gcx, 'tcx> {
impl<'a, 'gcx, 'tcx> InitialFlow for EverInitializedLvals<'a, 'gcx, 'tcx> {
#[inline]
fn bottom_value() -> bool {
false // bottom = no initialized variables by default

View file

@ -74,7 +74,7 @@ impl<'a, 'tcx> BitwiseOperator for MaybeStorageLive<'a, 'tcx> {
}
}
impl<'a, 'tcx> DataflowOperator for MaybeStorageLive<'a, 'tcx> {
impl<'a, 'tcx> InitialFlow for MaybeStorageLive<'a, 'tcx> {
#[inline]
fn bottom_value() -> bool {
false // bottom = dead

View file

@ -127,7 +127,7 @@ pub(crate) fn do_dataflow<'a, 'gcx, 'tcx, BD, P>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
bd: BD,
p: P)
-> DataflowResults<BD>
where BD: BitDenotation,
where BD: BitDenotation + InitialFlow,
P: Fn(&BD, BD::Idx) -> DebugFormatted
{
let name_found = |sess: &Session, attrs: &[ast::Attribute], name| -> Option<String> {
@ -176,7 +176,6 @@ impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitDenotation
};
while propcx.changed {
propcx.changed = false;
propcx.reset(&mut temp);
propcx.walk_cfg(&mut temp);
}
}
@ -212,13 +211,6 @@ impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitDenotation
impl<'b, 'a: 'b, 'tcx: 'a, BD> PropagationContext<'b, 'a, 'tcx, BD> where BD: BitDenotation
{
fn reset(&mut self, bits: &mut IdxSet<BD::Idx>) {
let e = if BD::bottom_value() {!0} else {0};
for b in bits.words_mut() {
*b = e;
}
}
fn walk_cfg(&mut self, in_out: &mut IdxSet<BD::Idx>) {
let mir = self.builder.mir;
for (bb_idx, bb_data) in mir.basic_blocks().iter().enumerate() {
@ -554,12 +546,17 @@ impl<E:Idx> AllSets<E> {
}
/// Parameterization for the precise form of data flow that is used.
pub trait DataflowOperator: BitwiseOperator {
/// `InitialFlow` handles initializing the bitvectors before any
/// code is inspected by the analysis. Analyses that need more nuanced
/// initialization (e.g. they need to consult the results of some other
/// dataflow analysis to set up the initial bitvectors) should not
/// implement this.
pub trait InitialFlow {
/// Specifies the initial value for each bit in the `on_entry` set
fn bottom_value() -> bool;
}
pub trait BitDenotation: DataflowOperator {
pub trait BitDenotation: BitwiseOperator {
/// Specifies what index type is used to access the bitvector.
type Idx: Idx;
@ -642,7 +639,7 @@ impl<'a, 'gcx, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
pub fn new(_tcx: TyCtxt<'a, 'gcx, 'tcx>,
mir: &'a Mir<'tcx>,
dead_unwinds: &'a IdxSet<mir::BasicBlock>,
denotation: D) -> Self {
denotation: D) -> Self where D: InitialFlow {
let bits_per_block = denotation.bits_per_block();
let usize_bits = mem::size_of::<usize>() * 8;
let words_per_block = (bits_per_block + usize_bits - 1) / usize_bits;