Add some useful comments.
Describing some things that took me a long time to understand.
This commit is contained in:
parent
0066acf753
commit
7e704afc2d
5 changed files with 24 additions and 12 deletions
|
@ -8,12 +8,16 @@ use rustc_middle::mir::{self, BasicBlock, Location};
|
|||
|
||||
use super::{Analysis, Direction, Effect, EffectIndex, Results};
|
||||
|
||||
/// Allows random access inspection of the results of a dataflow analysis.
|
||||
/// Allows random access inspection of the results of a dataflow analysis. Use this when you want
|
||||
/// to inspect domain values only in certain locations; use `ResultsVisitor` if you want to inspect
|
||||
/// domain values in many or all locations.
|
||||
///
|
||||
/// This cursor only has linear performance within a basic block when its statements are visited in
|
||||
/// the same order as the `DIRECTION` of the analysis. In the worst case—when statements are
|
||||
/// visited in *reverse* order—performance will be quadratic in the number of statements in the
|
||||
/// block. The order in which basic blocks are inspected has no impact on performance.
|
||||
/// Because `Results` only has domain values for the entry of each basic block, these inspections
|
||||
/// involve some amount of domain value recomputations. This cursor only has linear performance
|
||||
/// within a basic block when its statements are visited in the same order as the `DIRECTION` of
|
||||
/// the analysis. In the worst case—when statements are visited in *reverse* order—performance will
|
||||
/// be quadratic in the number of statements in the block. The order in which basic blocks are
|
||||
/// inspected has no impact on performance.
|
||||
pub struct ResultsCursor<'mir, 'tcx, A>
|
||||
where
|
||||
A: Analysis<'tcx>,
|
||||
|
|
|
@ -9,9 +9,9 @@ use super::{Analysis, Effect, EffectIndex, Results, SwitchIntTarget};
|
|||
|
||||
pub trait Direction {
|
||||
const IS_FORWARD: bool;
|
||||
|
||||
const IS_BACKWARD: bool = !Self::IS_FORWARD;
|
||||
|
||||
/// Called by `iterate_to_fixpoint` during initial analysis computation.
|
||||
fn apply_effects_in_block<'mir, 'tcx, A>(
|
||||
analysis: &mut A,
|
||||
body: &mir::Body<'tcx>,
|
||||
|
@ -22,7 +22,8 @@ pub trait Direction {
|
|||
) where
|
||||
A: Analysis<'tcx>;
|
||||
|
||||
/// Applies all effects between the given `EffectIndex`s.
|
||||
/// Called by `ResultsCursor` to recompute the domain value for a location
|
||||
/// in a basic block. Applies all effects between the given `EffectIndex`s.
|
||||
///
|
||||
/// `effects.start()` must precede or equal `effects.end()` in this direction.
|
||||
fn apply_effects_in_range<'tcx, A>(
|
||||
|
@ -34,6 +35,9 @@ pub trait Direction {
|
|||
) where
|
||||
A: Analysis<'tcx>;
|
||||
|
||||
/// Called by `ResultsVisitor` to recompute the analysis domain values for
|
||||
/// all locations in a basic block (starting from the entry value stored
|
||||
/// in `Results`) and to visit them with `vis`.
|
||||
fn visit_results_in_block<'mir, 'tcx, A>(
|
||||
state: &mut A::Domain,
|
||||
block: BasicBlock,
|
||||
|
@ -222,7 +226,6 @@ impl Direction for Backward {
|
|||
|
||||
vis.visit_block_end(state);
|
||||
|
||||
// Terminator
|
||||
let loc = Location { block, statement_index: block_data.statements.len() };
|
||||
let term = block_data.terminator();
|
||||
results.analysis.apply_before_terminator_effect(state, term, loc);
|
||||
|
|
|
@ -8,8 +8,9 @@
|
|||
//! The `impls` module contains several examples of dataflow analyses.
|
||||
//!
|
||||
//! Then call `iterate_to_fixpoint` on your type that impls `Analysis` to get a `Results`. From
|
||||
//! there, you can use a `ResultsCursor` to inspect the fixpoint solution to your dataflow problem,
|
||||
//! or implement the `ResultsVisitor` interface and use `visit_results`. The following example uses
|
||||
//! there, you can use a `ResultsCursor` to inspect the fixpoint solution to your dataflow problem
|
||||
//! (good for inspecting a small number of locations), or implement the `ResultsVisitor` interface
|
||||
//! and use `visit_results` (good for inspecting many or all locations). The following example uses
|
||||
//! the `ResultsCursor` approach.
|
||||
//!
|
||||
//! ```ignore (cross-crate-imports)
|
||||
|
|
|
@ -20,7 +20,9 @@ use crate::errors::{
|
|||
|
||||
pub type EntrySets<'tcx, A> = IndexVec<BasicBlock, <A as Analysis<'tcx>>::Domain>;
|
||||
|
||||
/// A dataflow analysis that has converged to fixpoint.
|
||||
/// 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
|
||||
/// by visitors (i.e. `ResultsCursor`, or `ResultsVisitor` impls).
|
||||
#[derive(Clone)]
|
||||
pub struct Results<'tcx, A>
|
||||
where
|
||||
|
|
|
@ -26,7 +26,9 @@ pub fn visit_results<'mir, 'tcx, A>(
|
|||
}
|
||||
}
|
||||
|
||||
/// A visitor over the results of an `Analysis`.
|
||||
/// A visitor over the results of an `Analysis`. Use this when you want to inspect domain values in
|
||||
/// many or all locations; use `ResultsCursor` if you want to inspect domain values only in certain
|
||||
/// locations.
|
||||
pub trait ResultsVisitor<'mir, 'tcx, A>
|
||||
where
|
||||
A: Analysis<'tcx>,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue