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:
parent
171c2aeb25
commit
d4add5d52a
4 changed files with 18 additions and 21 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue