2020-02-28 21:42:20 -08:00
|
|
|
use rustc::ty;
|
2020-02-29 20:37:32 +03:00
|
|
|
use rustc_ast::ast::{self, MetaItem};
|
2020-02-28 21:42:20 -08:00
|
|
|
use rustc_index::bit_set::BitSet;
|
2019-09-26 05:38:33 +00:00
|
|
|
use rustc_index::vec::Idx;
|
2020-03-11 12:49:08 +01:00
|
|
|
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;
|
2018-01-29 01:49:29 +02:00
|
|
|
pub use self::impls::EverInitializedPlaces;
|
2020-02-12 13:36:47 -08:00
|
|
|
pub use self::impls::{MaybeBorrowedLocals, MaybeMutBorrowedLocals};
|
2019-12-22 17:42:04 -05:00
|
|
|
pub use self::impls::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
|
2020-02-18 10:35:16 -08:00
|
|
|
pub use self::impls::{MaybeRequiresStorage, MaybeStorageLive};
|
2017-06-26 14:57:26 +02:00
|
|
|
|
2017-07-04 12:38:48 +02:00
|
|
|
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;
|
2016-05-24 13:26:54 +02:00
|
|
|
mod impls;
|
2017-06-26 14:57:26 +02:00
|
|
|
pub mod move_paths;
|
|
|
|
|
2019-04-01 19:38:00 +01:00
|
|
|
pub(crate) mod indexes {
|
|
|
|
pub(crate) use super::{
|
|
|
|
impls::borrows::BorrowIndex,
|
2019-12-22 17:42:04 -05:00
|
|
|
move_paths::{InitIndex, MoveOutIndex, MovePathIndex},
|
2019-04-01 19:38:00 +01:00
|
|
|
};
|
|
|
|
}
|
2017-06-26 14:57:26 +02:00
|
|
|
|
2019-05-08 13:21:18 +10:00
|
|
|
pub(crate) fn has_rustc_mir_with(attrs: &[ast::Attribute], name: Symbol) -> Option<MetaItem> {
|
2017-07-04 12:38:48 +02:00
|
|
|
for attr in attrs {
|
2019-05-08 13:21:18 +10:00
|
|
|
if attr.check_name(sym::rustc_mir) {
|
2017-07-04 12:38:48 +02:00
|
|
|
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,
|
2017-07-04 12:38:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-03-20 15:03:11 +01:00
|
|
|
None
|
2017-07-04 12:38:48 +02:00
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
pub struct MoveDataParamEnv<'tcx> {
|
2017-07-04 12:38:48 +02:00
|
|
|
pub(crate) move_data: MoveData<'tcx>,
|
2019-06-14 00:48:52 +03:00
|
|
|
pub(crate) param_env: ty::ParamEnv<'tcx>,
|
2017-07-04 12:38:48 +02:00
|
|
|
}
|
|
|
|
|
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.
|
2019-06-21 12:39:01 -07:00
|
|
|
///
|
|
|
|
/// `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.
|
2019-06-21 12:39:01 -07:00
|
|
|
#[inline]
|
|
|
|
fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
|
2020-02-28 13:36:45 +01:00
|
|
|
if !Self::BOTTOM_VALUE { inout_set.union(in_set) } else { inout_set.intersect(in_set) }
|
2019-06-21 12:39:01 -07:00
|
|
|
}
|
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
|
|
|
}
|