Skip to main content

rustc_mir_dataflow/framework/
visitor.rs

1use rustc_middle::mir::{self, BasicBlock, Location};
2
3use super::{Analysis, Direction, Results};
4
5/// Calls the visitor methods in `vis` for every location in every block in `blocks`. Note that
6/// every block in `blocks` must be reachable, and a `debug_assert` checks this.
7pub fn visit_results<'mir, 'tcx, A>(
8    body: &'mir mir::Body<'tcx>,
9    blocks: impl IntoIterator<Item = BasicBlock>,
10    results: &Results<'tcx, A>,
11    vis: &mut impl ResultsVisitor<'tcx, A>,
12) where
13    A: Analysis<'tcx>,
14{
15    let mut state = results.analysis.bottom_value(body);
16
17    #[cfg(debug_assertions)]
18    let reachable_blocks = mir::traversal::reachable_as_bitset(body);
19
20    for block in blocks {
21        #[cfg(debug_assertions)]
22        if !reachable_blocks.contains(block) {
    ::core::panicking::panic("assertion failed: reachable_blocks.contains(block)")
};assert!(reachable_blocks.contains(block));
23
24        let block_data = &body[block];
25        state.clone_from(&results.entry_states[block]);
26        A::Direction::visit_results_in_block(&results.analysis, &mut state, block, block_data, vis);
27    }
28}
29
30/// A visitor over the results of an `Analysis`. Use this when you want to inspect domain values in
31/// many or all locations; use `ResultsCursor` if you want to inspect domain values only in certain
32/// locations.
33pub trait ResultsVisitor<'tcx, A>
34where
35    A: Analysis<'tcx>,
36{
37    /// Called after all effects in a block have been applied in the direction
38    /// of the analysis.
39    ///
40    /// In a forwards analysis, `state` is from the block's end. In a backwards
41    /// analysis, `state` is from the block's start.
42    fn visit_block_exit(&mut self, _state: &A::Domain, _block: BasicBlock) {}
43
44    /// Called after the "early" effect of the given statement is applied to `state`.
45    fn visit_after_early_statement_effect(
46        &mut self,
47        _state: &A::Domain,
48        _statement: &mir::Statement<'tcx>,
49        _location: Location,
50    ) {
51    }
52
53    /// Called after the "primary" effect of the given statement is applied to `state`.
54    fn visit_after_primary_statement_effect(
55        &mut self,
56        _state: &A::Domain,
57        _statement: &mir::Statement<'tcx>,
58        _location: Location,
59    ) {
60    }
61
62    /// Called after the "early" effect of the given terminator is applied to `state`.
63    fn visit_after_early_terminator_effect(
64        &mut self,
65        _state: &A::Domain,
66        _terminator: &mir::Terminator<'tcx>,
67        _location: Location,
68    ) {
69    }
70
71    /// Called after the "primary" effect of the given terminator is applied to `state`.
72    ///
73    /// The `call_return_effect` (if one exists) will *not* be applied to `state`.
74    fn visit_after_primary_terminator_effect(
75        &mut self,
76        _state: &A::Domain,
77        _terminator: &mir::Terminator<'tcx>,
78        _location: Location,
79    ) {
80    }
81}