Rollup merge of #133938 - nnethercote:rustc_mir_dataflow-renamings, r=oli-obk
`rustc_mir_dataflow` cleanups, including some renamings Some opinionated commits in this collection, let's see how we go. r? `@cjgillot`
This commit is contained in:
@@ -179,15 +179,15 @@ where
|
||||
/// Advances the cursor to hold the dataflow state at `target` before its "primary" effect is
|
||||
/// applied.
|
||||
///
|
||||
/// The "before" effect at the target location *will be* applied.
|
||||
/// The "early" effect at the target location *will be* applied.
|
||||
pub fn seek_before_primary_effect(&mut self, target: Location) {
|
||||
self.seek_after(target, Effect::Before)
|
||||
self.seek_after(target, Effect::Early)
|
||||
}
|
||||
|
||||
/// Advances the cursor to hold the dataflow state at `target` after its "primary" effect is
|
||||
/// applied.
|
||||
///
|
||||
/// The "before" effect at the target location will be applied as well.
|
||||
/// The "early" effect at the target location will be applied as well.
|
||||
pub fn seek_after_primary_effect(&mut self, target: Location) {
|
||||
self.seek_after(target, Effect::Primary)
|
||||
}
|
||||
@@ -222,12 +222,12 @@ where
|
||||
#[rustfmt::skip]
|
||||
let next_effect = if A::Direction::IS_FORWARD {
|
||||
self.pos.curr_effect_index.map_or_else(
|
||||
|| Effect::Before.at_index(0),
|
||||
|| Effect::Early.at_index(0),
|
||||
EffectIndex::next_in_forward_order,
|
||||
)
|
||||
} else {
|
||||
self.pos.curr_effect_index.map_or_else(
|
||||
|| Effect::Before.at_index(block_data.statements.len()),
|
||||
|| Effect::Early.at_index(block_data.statements.len()),
|
||||
EffectIndex::next_in_backward_order,
|
||||
)
|
||||
};
|
||||
|
||||
@@ -66,12 +66,12 @@ impl Direction for Backward {
|
||||
{
|
||||
let terminator = block_data.terminator();
|
||||
let location = Location { block, statement_index: block_data.statements.len() };
|
||||
analysis.apply_before_terminator_effect(state, terminator, location);
|
||||
analysis.apply_terminator_effect(state, terminator, location);
|
||||
analysis.apply_early_terminator_effect(state, terminator, location);
|
||||
analysis.apply_primary_terminator_effect(state, terminator, location);
|
||||
for (statement_index, statement) in block_data.statements.iter().enumerate().rev() {
|
||||
let location = Location { block, statement_index };
|
||||
analysis.apply_before_statement_effect(state, statement, location);
|
||||
analysis.apply_statement_effect(state, statement, location);
|
||||
analysis.apply_early_statement_effect(state, statement, location);
|
||||
analysis.apply_primary_statement_effect(state, statement, location);
|
||||
}
|
||||
|
||||
let exit_state = state;
|
||||
@@ -159,14 +159,14 @@ impl Direction for Backward {
|
||||
let location = Location { block, statement_index: from.statement_index };
|
||||
let terminator = block_data.terminator();
|
||||
|
||||
if from.effect == Effect::Before {
|
||||
analysis.apply_before_terminator_effect(state, terminator, location);
|
||||
if to == Effect::Before.at_index(terminator_index) {
|
||||
if from.effect == Effect::Early {
|
||||
analysis.apply_early_terminator_effect(state, terminator, location);
|
||||
if to == Effect::Early.at_index(terminator_index) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
analysis.apply_terminator_effect(state, terminator, location);
|
||||
analysis.apply_primary_terminator_effect(state, terminator, location);
|
||||
if to == Effect::Primary.at_index(terminator_index) {
|
||||
return;
|
||||
}
|
||||
@@ -180,7 +180,7 @@ impl Direction for Backward {
|
||||
let location = Location { block, statement_index: from.statement_index };
|
||||
let statement = &block_data.statements[from.statement_index];
|
||||
|
||||
analysis.apply_statement_effect(state, statement, location);
|
||||
analysis.apply_primary_statement_effect(state, statement, location);
|
||||
if to == Effect::Primary.at_index(from.statement_index) {
|
||||
return;
|
||||
}
|
||||
@@ -188,7 +188,7 @@ impl Direction for Backward {
|
||||
from.statement_index - 1
|
||||
}
|
||||
|
||||
Effect::Before => from.statement_index,
|
||||
Effect::Early => from.statement_index,
|
||||
};
|
||||
|
||||
// Handle all statements between `first_unapplied_idx` and `to.statement_index`.
|
||||
@@ -196,21 +196,21 @@ impl Direction for Backward {
|
||||
for statement_index in (to.statement_index..next_effect).rev().map(|i| i + 1) {
|
||||
let location = Location { block, statement_index };
|
||||
let statement = &block_data.statements[statement_index];
|
||||
analysis.apply_before_statement_effect(state, statement, location);
|
||||
analysis.apply_statement_effect(state, statement, location);
|
||||
analysis.apply_early_statement_effect(state, statement, location);
|
||||
analysis.apply_primary_statement_effect(state, statement, location);
|
||||
}
|
||||
|
||||
// Handle the statement at `to`.
|
||||
|
||||
let location = Location { block, statement_index: to.statement_index };
|
||||
let statement = &block_data.statements[to.statement_index];
|
||||
analysis.apply_before_statement_effect(state, statement, location);
|
||||
analysis.apply_early_statement_effect(state, statement, location);
|
||||
|
||||
if to.effect == Effect::Before {
|
||||
if to.effect == Effect::Early {
|
||||
return;
|
||||
}
|
||||
|
||||
analysis.apply_statement_effect(state, statement, location);
|
||||
analysis.apply_primary_statement_effect(state, statement, location);
|
||||
}
|
||||
|
||||
fn visit_results_in_block<'mir, 'tcx, A>(
|
||||
@@ -228,17 +228,17 @@ impl Direction for Backward {
|
||||
|
||||
let loc = Location { block, statement_index: block_data.statements.len() };
|
||||
let term = block_data.terminator();
|
||||
results.analysis.apply_before_terminator_effect(state, term, loc);
|
||||
vis.visit_terminator_before_primary_effect(results, state, term, loc);
|
||||
results.analysis.apply_terminator_effect(state, term, loc);
|
||||
vis.visit_terminator_after_primary_effect(results, state, term, loc);
|
||||
results.analysis.apply_early_terminator_effect(state, term, loc);
|
||||
vis.visit_after_early_terminator_effect(results, state, term, loc);
|
||||
results.analysis.apply_primary_terminator_effect(state, term, loc);
|
||||
vis.visit_after_primary_terminator_effect(results, state, term, loc);
|
||||
|
||||
for (statement_index, stmt) in block_data.statements.iter().enumerate().rev() {
|
||||
let loc = Location { block, statement_index };
|
||||
results.analysis.apply_before_statement_effect(state, stmt, loc);
|
||||
vis.visit_statement_before_primary_effect(results, state, stmt, loc);
|
||||
results.analysis.apply_statement_effect(state, stmt, loc);
|
||||
vis.visit_statement_after_primary_effect(results, state, stmt, loc);
|
||||
results.analysis.apply_early_statement_effect(state, stmt, loc);
|
||||
vis.visit_after_early_statement_effect(results, state, stmt, loc);
|
||||
results.analysis.apply_primary_statement_effect(state, stmt, loc);
|
||||
vis.visit_after_primary_statement_effect(results, state, stmt, loc);
|
||||
}
|
||||
|
||||
vis.visit_block_start(state);
|
||||
@@ -294,13 +294,13 @@ impl Direction for Forward {
|
||||
{
|
||||
for (statement_index, statement) in block_data.statements.iter().enumerate() {
|
||||
let location = Location { block, statement_index };
|
||||
analysis.apply_before_statement_effect(state, statement, location);
|
||||
analysis.apply_statement_effect(state, statement, location);
|
||||
analysis.apply_early_statement_effect(state, statement, location);
|
||||
analysis.apply_primary_statement_effect(state, statement, location);
|
||||
}
|
||||
let terminator = block_data.terminator();
|
||||
let location = Location { block, statement_index: block_data.statements.len() };
|
||||
analysis.apply_before_terminator_effect(state, terminator, location);
|
||||
let edges = analysis.apply_terminator_effect(state, terminator, location);
|
||||
analysis.apply_early_terminator_effect(state, terminator, location);
|
||||
let edges = analysis.apply_primary_terminator_effect(state, terminator, location);
|
||||
|
||||
let exit_state = state;
|
||||
match edges {
|
||||
@@ -368,21 +368,21 @@ impl Direction for Forward {
|
||||
// after effect, do so now and start the loop below from the next statement.
|
||||
|
||||
let first_unapplied_index = match from.effect {
|
||||
Effect::Before => from.statement_index,
|
||||
Effect::Early => from.statement_index,
|
||||
|
||||
Effect::Primary if from.statement_index == terminator_index => {
|
||||
debug_assert_eq!(from, to);
|
||||
|
||||
let location = Location { block, statement_index: terminator_index };
|
||||
let terminator = block_data.terminator();
|
||||
analysis.apply_terminator_effect(state, terminator, location);
|
||||
analysis.apply_primary_terminator_effect(state, terminator, location);
|
||||
return;
|
||||
}
|
||||
|
||||
Effect::Primary => {
|
||||
let location = Location { block, statement_index: from.statement_index };
|
||||
let statement = &block_data.statements[from.statement_index];
|
||||
analysis.apply_statement_effect(state, statement, location);
|
||||
analysis.apply_primary_statement_effect(state, statement, location);
|
||||
|
||||
// If we only needed to apply the after effect of the statement at `idx`, we are
|
||||
// done.
|
||||
@@ -399,8 +399,8 @@ impl Direction for Forward {
|
||||
for statement_index in first_unapplied_index..to.statement_index {
|
||||
let location = Location { block, statement_index };
|
||||
let statement = &block_data.statements[statement_index];
|
||||
analysis.apply_before_statement_effect(state, statement, location);
|
||||
analysis.apply_statement_effect(state, statement, location);
|
||||
analysis.apply_early_statement_effect(state, statement, location);
|
||||
analysis.apply_primary_statement_effect(state, statement, location);
|
||||
}
|
||||
|
||||
// Handle the statement or terminator at `to`.
|
||||
@@ -408,17 +408,17 @@ impl Direction for Forward {
|
||||
let location = Location { block, statement_index: to.statement_index };
|
||||
if to.statement_index == terminator_index {
|
||||
let terminator = block_data.terminator();
|
||||
analysis.apply_before_terminator_effect(state, terminator, location);
|
||||
analysis.apply_early_terminator_effect(state, terminator, location);
|
||||
|
||||
if to.effect == Effect::Primary {
|
||||
analysis.apply_terminator_effect(state, terminator, location);
|
||||
analysis.apply_primary_terminator_effect(state, terminator, location);
|
||||
}
|
||||
} else {
|
||||
let statement = &block_data.statements[to.statement_index];
|
||||
analysis.apply_before_statement_effect(state, statement, location);
|
||||
analysis.apply_early_statement_effect(state, statement, location);
|
||||
|
||||
if to.effect == Effect::Primary {
|
||||
analysis.apply_statement_effect(state, statement, location);
|
||||
analysis.apply_primary_statement_effect(state, statement, location);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -438,18 +438,18 @@ impl Direction for Forward {
|
||||
|
||||
for (statement_index, stmt) in block_data.statements.iter().enumerate() {
|
||||
let loc = Location { block, statement_index };
|
||||
results.analysis.apply_before_statement_effect(state, stmt, loc);
|
||||
vis.visit_statement_before_primary_effect(results, state, stmt, loc);
|
||||
results.analysis.apply_statement_effect(state, stmt, loc);
|
||||
vis.visit_statement_after_primary_effect(results, state, stmt, loc);
|
||||
results.analysis.apply_early_statement_effect(state, stmt, loc);
|
||||
vis.visit_after_early_statement_effect(results, state, stmt, loc);
|
||||
results.analysis.apply_primary_statement_effect(state, stmt, loc);
|
||||
vis.visit_after_primary_statement_effect(results, state, stmt, loc);
|
||||
}
|
||||
|
||||
let loc = Location { block, statement_index: block_data.statements.len() };
|
||||
let term = block_data.terminator();
|
||||
results.analysis.apply_before_terminator_effect(state, term, loc);
|
||||
vis.visit_terminator_before_primary_effect(results, state, term, loc);
|
||||
results.analysis.apply_terminator_effect(state, term, loc);
|
||||
vis.visit_terminator_after_primary_effect(results, state, term, loc);
|
||||
results.analysis.apply_early_terminator_effect(state, term, loc);
|
||||
vis.visit_after_early_terminator_effect(results, state, term, loc);
|
||||
results.analysis.apply_primary_terminator_effect(state, term, loc);
|
||||
vis.visit_after_primary_terminator_effect(results, state, term, loc);
|
||||
|
||||
vis.visit_block_end(state);
|
||||
}
|
||||
|
||||
@@ -724,7 +724,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_statement_before_primary_effect(
|
||||
fn visit_after_early_statement_effect(
|
||||
&mut self,
|
||||
results: &mut Results<'tcx, A>,
|
||||
state: &A::Domain,
|
||||
@@ -737,7 +737,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_statement_after_primary_effect(
|
||||
fn visit_after_primary_statement_effect(
|
||||
&mut self,
|
||||
results: &mut Results<'tcx, A>,
|
||||
state: &A::Domain,
|
||||
@@ -748,7 +748,7 @@ where
|
||||
self.prev_state.clone_from(state)
|
||||
}
|
||||
|
||||
fn visit_terminator_before_primary_effect(
|
||||
fn visit_after_early_terminator_effect(
|
||||
&mut self,
|
||||
results: &mut Results<'tcx, A>,
|
||||
state: &A::Domain,
|
||||
@@ -761,7 +761,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_terminator_after_primary_effect(
|
||||
fn visit_after_primary_terminator_effect(
|
||||
&mut self,
|
||||
results: &mut Results<'tcx, A>,
|
||||
state: &A::Domain,
|
||||
|
||||
@@ -38,10 +38,8 @@
|
||||
//! [Hasse diagram]: https://en.wikipedia.org/wiki/Hasse_diagram
|
||||
//! [poset]: https://en.wikipedia.org/wiki/Partially_ordered_set
|
||||
|
||||
use std::iter;
|
||||
|
||||
use rustc_index::Idx;
|
||||
use rustc_index::bit_set::{BitSet, MixedBitSet};
|
||||
use rustc_index::{Idx, IndexVec};
|
||||
|
||||
use crate::framework::BitSetExt;
|
||||
|
||||
@@ -70,53 +68,6 @@ pub trait HasTop {
|
||||
const TOP: Self;
|
||||
}
|
||||
|
||||
/// A `bool` is a "two-point" lattice with `true` as the top element and `false` as the bottom:
|
||||
///
|
||||
/// ```text
|
||||
/// true
|
||||
/// |
|
||||
/// false
|
||||
/// ```
|
||||
impl JoinSemiLattice for bool {
|
||||
fn join(&mut self, other: &Self) -> bool {
|
||||
if let (false, true) = (*self, *other) {
|
||||
*self = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl HasBottom for bool {
|
||||
const BOTTOM: Self = false;
|
||||
|
||||
fn is_bottom(&self) -> bool {
|
||||
!self
|
||||
}
|
||||
}
|
||||
|
||||
impl HasTop for bool {
|
||||
const TOP: Self = true;
|
||||
}
|
||||
|
||||
/// A tuple (or list) of lattices is itself a lattice whose least upper bound is the concatenation
|
||||
/// of the least upper bounds of each element of the tuple (or list).
|
||||
///
|
||||
/// In other words:
|
||||
/// (A₀, A₁, ..., Aₙ) ∨ (B₀, B₁, ..., Bₙ) = (A₀∨B₀, A₁∨B₁, ..., Aₙ∨Bₙ)
|
||||
impl<I: Idx, T: JoinSemiLattice> JoinSemiLattice for IndexVec<I, T> {
|
||||
fn join(&mut self, other: &Self) -> bool {
|
||||
assert_eq!(self.len(), other.len());
|
||||
|
||||
let mut changed = false;
|
||||
for (a, b) in iter::zip(self, other) {
|
||||
changed |= a.join(b);
|
||||
}
|
||||
changed
|
||||
}
|
||||
}
|
||||
|
||||
/// A `BitSet` represents the lattice formed by the powerset of all possible values of
|
||||
/// the index type `T` ordered by inclusion. Equivalently, it is a tuple of "two-point" lattices,
|
||||
/// one for each possible value of `T`.
|
||||
@@ -197,18 +148,6 @@ impl<T> MaybeReachable<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> HasBottom for MaybeReachable<T> {
|
||||
const BOTTOM: Self = MaybeReachable::Unreachable;
|
||||
|
||||
fn is_bottom(&self) -> bool {
|
||||
matches!(self, Self::Unreachable)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: HasTop> HasTop for MaybeReachable<T> {
|
||||
const TOP: Self = MaybeReachable::Reachable(T::TOP);
|
||||
}
|
||||
|
||||
impl<S> MaybeReachable<S> {
|
||||
/// Return whether the current state contains the given element. If the state is unreachable,
|
||||
/// it does no contain anything.
|
||||
|
||||
@@ -56,7 +56,7 @@ mod visitor;
|
||||
pub use self::cursor::ResultsCursor;
|
||||
pub use self::direction::{Backward, Direction, Forward};
|
||||
pub use self::lattice::{JoinSemiLattice, MaybeReachable};
|
||||
pub use self::results::{EntrySets, Results};
|
||||
pub use self::results::{EntryStates, Results};
|
||||
pub use self::visitor::{ResultsVisitor, visit_results};
|
||||
|
||||
/// Analysis domains are all bitsets of various kinds. This trait holds
|
||||
@@ -122,8 +122,23 @@ pub trait Analysis<'tcx> {
|
||||
// `resume`). It's not obvious how to handle `yield` points in coroutines, however.
|
||||
fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut Self::Domain);
|
||||
|
||||
/// Updates the current dataflow state with an "early" effect, i.e. one
|
||||
/// that occurs immediately before the given statement.
|
||||
///
|
||||
/// This method is useful if the consumer of the results of this analysis only needs to observe
|
||||
/// *part* of the effect of a statement (e.g. for two-phase borrows). As a general rule,
|
||||
/// analyses should not implement this without also implementing
|
||||
/// `apply_primary_statement_effect`.
|
||||
fn apply_early_statement_effect(
|
||||
&mut self,
|
||||
_state: &mut Self::Domain,
|
||||
_statement: &mir::Statement<'tcx>,
|
||||
_location: Location,
|
||||
) {
|
||||
}
|
||||
|
||||
/// Updates the current dataflow state with the effect of evaluating a statement.
|
||||
fn apply_statement_effect(
|
||||
fn apply_primary_statement_effect(
|
||||
&mut self,
|
||||
state: &mut Self::Domain,
|
||||
statement: &mir::Statement<'tcx>,
|
||||
@@ -131,15 +146,16 @@ pub trait Analysis<'tcx> {
|
||||
);
|
||||
|
||||
/// Updates the current dataflow state with an effect that occurs immediately *before* the
|
||||
/// given statement.
|
||||
/// given terminator.
|
||||
///
|
||||
/// This method is useful if the consumer of the results of this analysis only needs to observe
|
||||
/// *part* of the effect of a statement (e.g. for two-phase borrows). As a general rule,
|
||||
/// analyses should not implement this without also implementing `apply_statement_effect`.
|
||||
fn apply_before_statement_effect(
|
||||
/// This method is useful if the consumer of the results of this analysis needs only to observe
|
||||
/// *part* of the effect of a terminator (e.g. for two-phase borrows). As a general rule,
|
||||
/// analyses should not implement this without also implementing
|
||||
/// `apply_primary_terminator_effect`.
|
||||
fn apply_early_terminator_effect(
|
||||
&mut self,
|
||||
_state: &mut Self::Domain,
|
||||
_statement: &mir::Statement<'tcx>,
|
||||
_terminator: &mir::Terminator<'tcx>,
|
||||
_location: Location,
|
||||
) {
|
||||
}
|
||||
@@ -150,7 +166,7 @@ pub trait Analysis<'tcx> {
|
||||
/// in this function. That should go in `apply_call_return_effect`. For example, in the
|
||||
/// `InitializedPlaces` analyses, the return place for a function call is not marked as
|
||||
/// initialized here.
|
||||
fn apply_terminator_effect<'mir>(
|
||||
fn apply_primary_terminator_effect<'mir>(
|
||||
&mut self,
|
||||
_state: &mut Self::Domain,
|
||||
terminator: &'mir mir::Terminator<'tcx>,
|
||||
@@ -159,27 +175,13 @@ pub trait Analysis<'tcx> {
|
||||
terminator.edges()
|
||||
}
|
||||
|
||||
/// Updates the current dataflow state with an effect that occurs immediately *before* the
|
||||
/// given terminator.
|
||||
///
|
||||
/// This method is useful if the consumer of the results of this analysis needs only to observe
|
||||
/// *part* of the effect of a terminator (e.g. for two-phase borrows). As a general rule,
|
||||
/// analyses should not implement this without also implementing `apply_terminator_effect`.
|
||||
fn apply_before_terminator_effect(
|
||||
&mut self,
|
||||
_state: &mut Self::Domain,
|
||||
_terminator: &mir::Terminator<'tcx>,
|
||||
_location: Location,
|
||||
) {
|
||||
}
|
||||
|
||||
/* Edge-specific effects */
|
||||
|
||||
/// Updates the current dataflow state with the effect of a successful return from a `Call`
|
||||
/// terminator.
|
||||
///
|
||||
/// This is separate from `apply_terminator_effect` to properly track state across unwind
|
||||
/// edges.
|
||||
/// This is separate from `apply_primary_terminator_effect` to properly track state across
|
||||
/// unwind edges.
|
||||
fn apply_call_return_effect(
|
||||
&mut self,
|
||||
_state: &mut Self::Domain,
|
||||
@@ -234,11 +236,12 @@ pub trait Analysis<'tcx> {
|
||||
Self: Sized,
|
||||
Self::Domain: DebugWithContext<Self>,
|
||||
{
|
||||
let mut entry_sets =
|
||||
let mut entry_states =
|
||||
IndexVec::from_fn_n(|_| self.bottom_value(body), body.basic_blocks.len());
|
||||
self.initialize_start_block(body, &mut entry_sets[mir::START_BLOCK]);
|
||||
self.initialize_start_block(body, &mut entry_states[mir::START_BLOCK]);
|
||||
|
||||
if Self::Direction::IS_BACKWARD && entry_sets[mir::START_BLOCK] != self.bottom_value(body) {
|
||||
if Self::Direction::IS_BACKWARD && entry_states[mir::START_BLOCK] != self.bottom_value(body)
|
||||
{
|
||||
bug!("`initialize_start_block` is not yet supported for backward dataflow analyses");
|
||||
}
|
||||
|
||||
@@ -262,9 +265,9 @@ pub trait Analysis<'tcx> {
|
||||
let mut state = self.bottom_value(body);
|
||||
while let Some(bb) = dirty_queue.pop() {
|
||||
// Set the state to the entry state of the block.
|
||||
// This is equivalent to `state = entry_sets[bb].clone()`,
|
||||
// This is equivalent to `state = entry_states[bb].clone()`,
|
||||
// but it saves an allocation, thus improving compile times.
|
||||
state.clone_from(&entry_sets[bb]);
|
||||
state.clone_from(&entry_states[bb]);
|
||||
|
||||
Self::Direction::apply_effects_in_block(
|
||||
&mut self,
|
||||
@@ -273,7 +276,7 @@ pub trait Analysis<'tcx> {
|
||||
bb,
|
||||
&body[bb],
|
||||
|target: BasicBlock, state: &Self::Domain| {
|
||||
let set_changed = entry_sets[target].join(state);
|
||||
let set_changed = entry_states[target].join(state);
|
||||
if set_changed {
|
||||
dirty_queue.insert(target);
|
||||
}
|
||||
@@ -281,7 +284,7 @@ pub trait Analysis<'tcx> {
|
||||
);
|
||||
}
|
||||
|
||||
let mut results = Results { analysis: self, entry_sets };
|
||||
let mut results = Results { analysis: self, entry_states };
|
||||
|
||||
if tcx.sess.opts.unstable_opts.dump_mir_dataflow {
|
||||
let res = write_graphviz_results(tcx, body, &mut results, pass_name);
|
||||
@@ -358,11 +361,10 @@ impl<T, S: GenKill<T>> GenKill<T> for MaybeReachable<S> {
|
||||
// NOTE: DO NOT CHANGE VARIANT ORDER. The derived `Ord` impls rely on the current order.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
enum Effect {
|
||||
/// The "before" effect (e.g., `apply_before_statement_effect`) for a statement (or
|
||||
/// terminator).
|
||||
Before,
|
||||
/// The "early" effect (e.g., `apply_early_statement_effect`) for a statement/terminator.
|
||||
Early,
|
||||
|
||||
/// The "primary" effect (e.g., `apply_statement_effect`) for a statement (or terminator).
|
||||
/// The "primary" effect (e.g., `apply_primary_statement_effect`) for a statement/terminator.
|
||||
Primary,
|
||||
}
|
||||
|
||||
@@ -381,15 +383,15 @@ pub struct EffectIndex {
|
||||
impl EffectIndex {
|
||||
fn next_in_forward_order(self) -> Self {
|
||||
match self.effect {
|
||||
Effect::Before => Effect::Primary.at_index(self.statement_index),
|
||||
Effect::Primary => Effect::Before.at_index(self.statement_index + 1),
|
||||
Effect::Early => Effect::Primary.at_index(self.statement_index),
|
||||
Effect::Primary => Effect::Early.at_index(self.statement_index + 1),
|
||||
}
|
||||
}
|
||||
|
||||
fn next_in_backward_order(self) -> Self {
|
||||
match self.effect {
|
||||
Effect::Before => Effect::Primary.at_index(self.statement_index),
|
||||
Effect::Primary => Effect::Before.at_index(self.statement_index - 1),
|
||||
Effect::Early => Effect::Primary.at_index(self.statement_index),
|
||||
Effect::Primary => Effect::Early.at_index(self.statement_index - 1),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use rustc_middle::mir::{BasicBlock, Body, traversal};
|
||||
use super::{Analysis, ResultsCursor, ResultsVisitor, visit_results};
|
||||
use crate::framework::cursor::ResultsHandle;
|
||||
|
||||
pub type EntrySets<'tcx, A> = IndexVec<BasicBlock, <A as Analysis<'tcx>>::Domain>;
|
||||
pub type EntryStates<'tcx, A> = IndexVec<BasicBlock, <A as Analysis<'tcx>>::Domain>;
|
||||
|
||||
/// A dataflow analysis that has converged to fixpoint. It only holds the domain values at the
|
||||
/// entry of each basic block. Domain values in other parts of the block are recomputed on the fly
|
||||
@@ -17,7 +17,7 @@ where
|
||||
A: Analysis<'tcx>,
|
||||
{
|
||||
pub analysis: A,
|
||||
pub entry_sets: EntrySets<'tcx, A>,
|
||||
pub entry_states: EntryStates<'tcx, A>,
|
||||
}
|
||||
|
||||
impl<'tcx, A> Results<'tcx, A>
|
||||
@@ -40,7 +40,7 @@ where
|
||||
|
||||
/// Gets the dataflow state for the given block.
|
||||
pub fn entry_set_for_block(&self, block: BasicBlock) -> &A::Domain {
|
||||
&self.entry_sets[block]
|
||||
&self.entry_states[block]
|
||||
}
|
||||
|
||||
pub fn visit_with<'mir>(
|
||||
|
||||
@@ -73,7 +73,7 @@ fn mock_body<'tcx>() -> mir::Body<'tcx> {
|
||||
///
|
||||
/// The `102` in the block's entry set is derived from the basic block index and ensures that the
|
||||
/// expected state is unique across all basic blocks. Remember, it is generated by
|
||||
/// `mock_entry_sets`, not from actually running `MockAnalysis` to fixpoint.
|
||||
/// `mock_entry_states`, not from actually running `MockAnalysis` to fixpoint.
|
||||
struct MockAnalysis<'tcx, D> {
|
||||
body: &'tcx mir::Body<'tcx>,
|
||||
dir: PhantomData<D>,
|
||||
@@ -90,7 +90,7 @@ impl<D: Direction> MockAnalysis<'_, D> {
|
||||
ret
|
||||
}
|
||||
|
||||
fn mock_entry_sets(&self) -> IndexVec<BasicBlock, BitSet<usize>> {
|
||||
fn mock_entry_states(&self) -> IndexVec<BasicBlock, BitSet<usize>> {
|
||||
let empty = self.bottom_value(self.body);
|
||||
let mut ret = IndexVec::from_elem(empty, &self.body.basic_blocks);
|
||||
|
||||
@@ -104,7 +104,7 @@ impl<D: Direction> MockAnalysis<'_, D> {
|
||||
/// Returns the index that should be added to the dataflow state at the given target.
|
||||
fn effect(&self, loc: EffectIndex) -> usize {
|
||||
let idx = match loc.effect {
|
||||
Effect::Before => loc.statement_index * 2,
|
||||
Effect::Early => loc.statement_index * 2,
|
||||
Effect::Primary => loc.statement_index * 2 + 1,
|
||||
};
|
||||
|
||||
@@ -128,14 +128,14 @@ impl<D: Direction> MockAnalysis<'_, D> {
|
||||
|
||||
let target = match target {
|
||||
SeekTarget::BlockEntry { .. } => return ret,
|
||||
SeekTarget::Before(loc) => Effect::Before.at_index(loc.statement_index),
|
||||
SeekTarget::Early(loc) => Effect::Early.at_index(loc.statement_index),
|
||||
SeekTarget::After(loc) => Effect::Primary.at_index(loc.statement_index),
|
||||
};
|
||||
|
||||
let mut pos = if D::IS_FORWARD {
|
||||
Effect::Before.at_index(0)
|
||||
Effect::Early.at_index(0)
|
||||
} else {
|
||||
Effect::Before.at_index(self.body[block].statements.len())
|
||||
Effect::Early.at_index(self.body[block].statements.len())
|
||||
};
|
||||
|
||||
loop {
|
||||
@@ -168,7 +168,17 @@ impl<'tcx, D: Direction> Analysis<'tcx> for MockAnalysis<'tcx, D> {
|
||||
unimplemented!("This is never called since `MockAnalysis` is never iterated to fixpoint");
|
||||
}
|
||||
|
||||
fn apply_statement_effect(
|
||||
fn apply_early_statement_effect(
|
||||
&mut self,
|
||||
state: &mut Self::Domain,
|
||||
_statement: &mir::Statement<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
let idx = self.effect(Effect::Early.at_index(location.statement_index));
|
||||
assert!(state.insert(idx));
|
||||
}
|
||||
|
||||
fn apply_primary_statement_effect(
|
||||
&mut self,
|
||||
state: &mut Self::Domain,
|
||||
_statement: &mir::Statement<'tcx>,
|
||||
@@ -178,17 +188,17 @@ impl<'tcx, D: Direction> Analysis<'tcx> for MockAnalysis<'tcx, D> {
|
||||
assert!(state.insert(idx));
|
||||
}
|
||||
|
||||
fn apply_before_statement_effect(
|
||||
fn apply_early_terminator_effect(
|
||||
&mut self,
|
||||
state: &mut Self::Domain,
|
||||
_statement: &mir::Statement<'tcx>,
|
||||
_terminator: &mir::Terminator<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
let idx = self.effect(Effect::Before.at_index(location.statement_index));
|
||||
let idx = self.effect(Effect::Early.at_index(location.statement_index));
|
||||
assert!(state.insert(idx));
|
||||
}
|
||||
|
||||
fn apply_terminator_effect<'mir>(
|
||||
fn apply_primary_terminator_effect<'mir>(
|
||||
&mut self,
|
||||
state: &mut Self::Domain,
|
||||
terminator: &'mir mir::Terminator<'tcx>,
|
||||
@@ -198,22 +208,12 @@ impl<'tcx, D: Direction> Analysis<'tcx> for MockAnalysis<'tcx, D> {
|
||||
assert!(state.insert(idx));
|
||||
terminator.edges()
|
||||
}
|
||||
|
||||
fn apply_before_terminator_effect(
|
||||
&mut self,
|
||||
state: &mut Self::Domain,
|
||||
_terminator: &mir::Terminator<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
let idx = self.effect(Effect::Before.at_index(location.statement_index));
|
||||
assert!(state.insert(idx));
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
enum SeekTarget {
|
||||
BlockEntry(BasicBlock),
|
||||
Before(Location),
|
||||
Early(Location),
|
||||
After(Location),
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ impl SeekTarget {
|
||||
|
||||
match *self {
|
||||
BlockEntry(block) => block,
|
||||
Before(loc) | After(loc) => loc.block,
|
||||
Early(loc) | After(loc) => loc.block,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,7 +235,7 @@ impl SeekTarget {
|
||||
.map(move |(i, kind)| {
|
||||
let loc = Location { block, statement_index: i };
|
||||
match kind {
|
||||
0 => SeekTarget::Before(loc),
|
||||
0 => SeekTarget::Early(loc),
|
||||
1 => SeekTarget::After(loc),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
@@ -249,7 +249,7 @@ fn test_cursor<D: Direction>(analysis: MockAnalysis<'_, D>) {
|
||||
let body = analysis.body;
|
||||
|
||||
let mut cursor =
|
||||
Results { entry_sets: analysis.mock_entry_sets(), analysis }.into_results_cursor(body);
|
||||
Results { entry_states: analysis.mock_entry_states(), analysis }.into_results_cursor(body);
|
||||
|
||||
cursor.allow_unreachable();
|
||||
|
||||
@@ -262,7 +262,7 @@ fn test_cursor<D: Direction>(analysis: MockAnalysis<'_, D>) {
|
||||
|
||||
match targ {
|
||||
BlockEntry(block) => cursor.seek_to_block_entry(block),
|
||||
Before(loc) => cursor.seek_before_primary_effect(loc),
|
||||
Early(loc) => cursor.seek_before_primary_effect(loc),
|
||||
After(loc) => cursor.seek_after_primary_effect(loc),
|
||||
}
|
||||
|
||||
|
||||
@@ -35,9 +35,9 @@ where
|
||||
{
|
||||
fn visit_block_start(&mut self, _state: &A::Domain) {}
|
||||
|
||||
/// Called with the `before_statement_effect` of the given statement applied to `state` but not
|
||||
/// its `statement_effect`.
|
||||
fn visit_statement_before_primary_effect(
|
||||
/// // njn: grep for "before", "primary", etc.
|
||||
/// Called after the "early" effect of the given statement is applied to `state`.
|
||||
fn visit_after_early_statement_effect(
|
||||
&mut self,
|
||||
_results: &mut Results<'tcx, A>,
|
||||
_state: &A::Domain,
|
||||
@@ -46,9 +46,8 @@ where
|
||||
) {
|
||||
}
|
||||
|
||||
/// Called with both the `before_statement_effect` and the `statement_effect` of the given
|
||||
/// statement applied to `state`.
|
||||
fn visit_statement_after_primary_effect(
|
||||
/// Called after the "primary" effect of the given statement is applied to `state`.
|
||||
fn visit_after_primary_statement_effect(
|
||||
&mut self,
|
||||
_results: &mut Results<'tcx, A>,
|
||||
_state: &A::Domain,
|
||||
@@ -57,9 +56,8 @@ where
|
||||
) {
|
||||
}
|
||||
|
||||
/// Called with the `before_terminator_effect` of the given terminator applied to `state` but
|
||||
/// not its `terminator_effect`.
|
||||
fn visit_terminator_before_primary_effect(
|
||||
/// Called after the "early" effect of the given terminator is applied to `state`.
|
||||
fn visit_after_early_terminator_effect(
|
||||
&mut self,
|
||||
_results: &mut Results<'tcx, A>,
|
||||
_state: &A::Domain,
|
||||
@@ -68,11 +66,10 @@ where
|
||||
) {
|
||||
}
|
||||
|
||||
/// Called with both the `before_terminator_effect` and the `terminator_effect` of the given
|
||||
/// terminator applied to `state`.
|
||||
/// Called after the "primary" effect of the given terminator is applied to `state`.
|
||||
///
|
||||
/// The `call_return_effect` (if one exists) will *not* be applied to `state`.
|
||||
fn visit_terminator_after_primary_effect(
|
||||
fn visit_after_primary_terminator_effect(
|
||||
&mut self,
|
||||
_results: &mut Results<'tcx, A>,
|
||||
_state: &A::Domain,
|
||||
|
||||
Reference in New Issue
Block a user