rustc_mir_dataflow/framework/
visitor.rs

1use rustc_middle::mir::{self, BasicBlock, Location, traversal};
2
3use super::{Analysis, Direction, Results};
4
5/// Calls the corresponding method in `ResultsVisitor` for every location in a `mir::Body` with the
6/// dataflow state at that location.
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        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/// Like `visit_results`, but only for reachable blocks.
31pub fn visit_reachable_results<'mir, 'tcx, A>(
32    body: &'mir mir::Body<'tcx>,
33    results: &Results<'tcx, A>,
34    vis: &mut impl ResultsVisitor<'tcx, A>,
35) where
36    A: Analysis<'tcx>,
37{
38    let blocks = traversal::reachable(body).map(|(bb, _)| bb);
39    visit_results(body, blocks, results, vis)
40}
41
42/// A visitor over the results of an `Analysis`. Use this when you want to inspect domain values in
43/// many or all locations; use `ResultsCursor` if you want to inspect domain values only in certain
44/// locations.
45pub trait ResultsVisitor<'tcx, A>
46where
47    A: Analysis<'tcx>,
48{
49    fn visit_block_start(&mut self, _state: &A::Domain) {}
50
51    /// Called after the "early" effect of the given statement is applied to `state`.
52    fn visit_after_early_statement_effect(
53        &mut self,
54        _analysis: &A,
55        _state: &A::Domain,
56        _statement: &mir::Statement<'tcx>,
57        _location: Location,
58    ) {
59    }
60
61    /// Called after the "primary" effect of the given statement is applied to `state`.
62    fn visit_after_primary_statement_effect(
63        &mut self,
64        _analysis: &A,
65        _state: &A::Domain,
66        _statement: &mir::Statement<'tcx>,
67        _location: Location,
68    ) {
69    }
70
71    /// Called after the "early" effect of the given terminator is applied to `state`.
72    fn visit_after_early_terminator_effect(
73        &mut self,
74        _analysis: &A,
75        _state: &A::Domain,
76        _terminator: &mir::Terminator<'tcx>,
77        _location: Location,
78    ) {
79    }
80
81    /// Called after the "primary" effect of the given terminator is applied to `state`.
82    ///
83    /// The `call_return_effect` (if one exists) will *not* be applied to `state`.
84    fn visit_after_primary_terminator_effect(
85        &mut self,
86        _analysis: &A,
87        _state: &A::Domain,
88        _terminator: &mir::Terminator<'tcx>,
89        _location: Location,
90    ) {
91    }
92
93    fn visit_block_end(&mut self, _state: &A::Domain) {}
94}