rust/src/librustc_mir/dataflow/mod.rs

89 lines
3.5 KiB
Rust
Raw Normal View History

2020-02-28 21:42:20 -08:00
use rustc::ty;
use rustc_ast::ast::{self, MetaItem};
2020-02-28 21:42:20 -08:00
use rustc_index::bit_set::BitSet;
use rustc_index::vec::Idx;
use rustc_span::symbol::{sym, Symbol};
Revised mir-dataflow. Incorporates many fixes contributed by arielb1. ---- revise borrowck::mir::dataflow code to allow varying domain for bitvectors. This particular code implements the `BitDenotation` trait for three analyses: * `MovingOutStatements`, which, like `borrowck::move_data`, maps each bit-index to a move instruction, and a 1 means "the effect of this move reaches this point" (and the assigned l-value, if a scoped declaration, is still in scope). * `MaybeInitializedLvals`, which maps each bit-index to an l-value. A 1 means "there exists a control flow path to this point that initializes the associated l-value." * `MaybeUninitializedLvals`, which maps each bit-index to an l-value A 1 means "there exists a control flow path to this point that de-initializes the associated l-value." ---- Revised `graphviz` dataflow-rendering support in `borrowck::mir`. One big difference is that this code is now parameterized over the `BitDenotation`, so that it can be used to render dataflow results independent of how the dataflow bitvectors are interpreted; see where reference to `MoveOut` is replaced by the type parameter `D`. ---- Factor out routine to query subattributes in `#[rustc_mir(..)]`. (Later commits build upon this for some unit testing and instrumentation.) ---- thread through a tcx so that I can query types of lvalues as part of analysis. ---- Revised `BitDenotation::Ctxt`, allowing variation beyond `MoveData`. The main motivation is to ease threading through a `TyCtxt`. (In hindsight it might have been better to instead attach the `TyCtxt` to each of the different dataflow implementations, but that would require e.g. switching away from having a `Default` impl, so I am leaving that experiment for another time.)
2016-05-02 15:50:27 +02:00
2019-12-22 17:42:04 -05:00
pub(crate) use self::drop_flag_effects::*;
pub use self::impls::borrows::Borrows;
2018-08-30 18:54:32 -03:00
pub use self::impls::DefinitelyInitializedPlaces;
pub use self::impls::EverInitializedPlaces;
pub use self::impls::{MaybeBorrowedLocals, MaybeMutBorrowedLocals};
2019-12-22 17:42:04 -05:00
pub use self::impls::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
pub use self::impls::{MaybeRequiresStorage, MaybeStorageLive};
use self::move_paths::MoveData;
2018-08-30 18:54:32 -03:00
pub mod drop_flag_effects;
2019-09-17 16:25:29 -07:00
pub mod generic;
mod impls;
pub mod move_paths;
pub(crate) mod indexes {
pub(crate) use super::{
impls::borrows::BorrowIndex,
2019-12-22 17:42:04 -05:00
move_paths::{InitIndex, MoveOutIndex, MovePathIndex},
};
}
pub(crate) fn has_rustc_mir_with(attrs: &[ast::Attribute], name: Symbol) -> Option<MetaItem> {
for attr in attrs {
if attr.check_name(sym::rustc_mir) {
let items = attr.meta_item_list();
for item in items.iter().flat_map(|l| l.iter()) {
match item.meta_item() {
Some(mi) if mi.check_name(name) => return Some(mi.clone()),
2019-12-22 17:42:04 -05:00
_ => continue,
}
}
}
}
None
}
2019-06-14 00:48:52 +03:00
pub struct MoveDataParamEnv<'tcx> {
pub(crate) move_data: MoveData<'tcx>,
2019-06-14 00:48:52 +03:00
pub(crate) param_env: ty::ParamEnv<'tcx>,
}
Revised mir-dataflow. Incorporates many fixes contributed by arielb1. ---- revise borrowck::mir::dataflow code to allow varying domain for bitvectors. This particular code implements the `BitDenotation` trait for three analyses: * `MovingOutStatements`, which, like `borrowck::move_data`, maps each bit-index to a move instruction, and a 1 means "the effect of this move reaches this point" (and the assigned l-value, if a scoped declaration, is still in scope). * `MaybeInitializedLvals`, which maps each bit-index to an l-value. A 1 means "there exists a control flow path to this point that initializes the associated l-value." * `MaybeUninitializedLvals`, which maps each bit-index to an l-value A 1 means "there exists a control flow path to this point that de-initializes the associated l-value." ---- Revised `graphviz` dataflow-rendering support in `borrowck::mir`. One big difference is that this code is now parameterized over the `BitDenotation`, so that it can be used to render dataflow results independent of how the dataflow bitvectors are interpreted; see where reference to `MoveOut` is replaced by the type parameter `D`. ---- Factor out routine to query subattributes in `#[rustc_mir(..)]`. (Later commits build upon this for some unit testing and instrumentation.) ---- thread through a tcx so that I can query types of lvalues as part of analysis. ---- Revised `BitDenotation::Ctxt`, allowing variation beyond `MoveData`. The main motivation is to ease threading through a `TyCtxt`. (In hindsight it might have been better to instead attach the `TyCtxt` to each of the different dataflow implementations, but that would require e.g. switching away from having a `Default` impl, so I am leaving that experiment for another time.)
2016-05-02 15:50:27 +02:00
/// Parameterization for the precise form of data flow that is used.
///
/// `BottomValue` determines whether the initial entry set for each basic block is empty or full.
/// This also determines the semantics of the lattice `join` operator used to merge dataflow
/// results, since dataflow works by starting at the bottom and moving monotonically to a fixed
/// point.
///
/// 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.
pub trait BottomValue {
/// Specifies the initial value for each bit in the entry set for each basic block.
const BOTTOM_VALUE: bool;
/// Merges `in_set` into `inout_set`, returning `true` if `inout_set` changed.
2019-12-15 09:42:09 +01:00
///
2019-12-20 19:46:38 +01:00
/// It is almost certainly wrong to override this, since it automatically applies
2019-12-15 09:42:09 +01:00
/// * `inout_set & in_set` if `BOTTOM_VALUE == true`
/// * `inout_set | in_set` if `BOTTOM_VALUE == false`
///
/// This means that if a bit is not `BOTTOM_VALUE`, it is propagated into all target blocks.
/// For clarity, the above statement again from a different perspective:
2019-12-20 19:46:38 +01:00
/// A bit in the block's entry set is `!BOTTOM_VALUE` if *any* predecessor block's bit value is
2019-12-15 09:42:09 +01:00
/// `!BOTTOM_VALUE`.
2019-12-20 19:46:38 +01:00
///
2019-12-15 09:42:09 +01:00
/// There are situations where you want the opposite behaviour: propagate only if *all*
2019-12-20 19:46:38 +01:00
/// predecessor blocks's value is `!BOTTOM_VALUE`.
/// E.g. if you want to know whether a bit is *definitely* set at a specific location. This
/// means that all code paths leading to the location must have set the bit, instead of any
/// code path leading there.
///
/// If you want this kind of "definitely set" analysis, you need to
2019-12-15 09:42:09 +01:00
/// 1. Invert `BOTTOM_VALUE`
/// 2. Reset the `entry_set` in `start_block_effect` to `!BOTTOM_VALUE`
/// 3. Override `join` to do the opposite from what it's doing now.
#[inline]
fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
if !Self::BOTTOM_VALUE { inout_set.union(in_set) } else { inout_set.intersect(in_set) }
}
Revised mir-dataflow. Incorporates many fixes contributed by arielb1. ---- revise borrowck::mir::dataflow code to allow varying domain for bitvectors. This particular code implements the `BitDenotation` trait for three analyses: * `MovingOutStatements`, which, like `borrowck::move_data`, maps each bit-index to a move instruction, and a 1 means "the effect of this move reaches this point" (and the assigned l-value, if a scoped declaration, is still in scope). * `MaybeInitializedLvals`, which maps each bit-index to an l-value. A 1 means "there exists a control flow path to this point that initializes the associated l-value." * `MaybeUninitializedLvals`, which maps each bit-index to an l-value A 1 means "there exists a control flow path to this point that de-initializes the associated l-value." ---- Revised `graphviz` dataflow-rendering support in `borrowck::mir`. One big difference is that this code is now parameterized over the `BitDenotation`, so that it can be used to render dataflow results independent of how the dataflow bitvectors are interpreted; see where reference to `MoveOut` is replaced by the type parameter `D`. ---- Factor out routine to query subattributes in `#[rustc_mir(..)]`. (Later commits build upon this for some unit testing and instrumentation.) ---- thread through a tcx so that I can query types of lvalues as part of analysis. ---- Revised `BitDenotation::Ctxt`, allowing variation beyond `MoveData`. The main motivation is to ease threading through a `TyCtxt`. (In hindsight it might have been better to instead attach the `TyCtxt` to each of the different dataflow implementations, but that would require e.g. switching away from having a `Default` impl, so I am leaving that experiment for another time.)
2016-05-02 15:50:27 +02:00
}