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    analysis: &mut A,
11    results: &Results<A::Domain>,
12    vis: &mut impl ResultsVisitor<'tcx, A>,
13) where
14    A: Analysis<'tcx>,
15{
16    let mut state = analysis.bottom_value(body);
17
18    #[cfg(debug_assertions)]
19    let reachable_blocks = mir::traversal::reachable_as_bitset(body);
20
21    for block in blocks {
22        #[cfg(debug_assertions)]
23        assert!(reachable_blocks.contains(block));
24
25        let block_data = &body[block];
26        state.clone_from(&results[block]);
27        A::Direction::visit_results_in_block(&mut state, block, block_data, analysis, vis);
28    }
29}
30
31/// Like `visit_results`, but only for reachable blocks.
32pub fn visit_reachable_results<'mir, 'tcx, A>(
33    body: &'mir mir::Body<'tcx>,
34    analysis: &mut A,
35    results: &Results<A::Domain>,
36    vis: &mut impl ResultsVisitor<'tcx, A>,
37) where
38    A: Analysis<'tcx>,
39{
40    let blocks = traversal::reachable(body).map(|(bb, _)| bb);
41    visit_results(body, blocks, analysis, results, vis)
42}
43
44/// A visitor over the results of an `Analysis`. Use this when you want to inspect domain values in
45/// many or all locations; use `ResultsCursor` if you want to inspect domain values only in certain
46/// locations.
47pub trait ResultsVisitor<'tcx, A>
48where
49    A: Analysis<'tcx>,
50{
51    fn visit_block_start(&mut self, _state: &A::Domain) {}
52
53    /// Called after the "early" effect of the given statement is applied to `state`.
54    fn visit_after_early_statement_effect(
55        &mut self,
56        _analysis: &mut A,
57        _state: &A::Domain,
58        _statement: &mir::Statement<'tcx>,
59        _location: Location,
60    ) {
61    }
62
63    /// Called after the "primary" effect of the given statement is applied to `state`.
64    fn visit_after_primary_statement_effect(
65        &mut self,
66        _analysis: &mut A,
67        _state: &A::Domain,
68        _statement: &mir::Statement<'tcx>,
69        _location: Location,
70    ) {
71    }
72
73    /// Called after the "early" effect of the given terminator is applied to `state`.
74    fn visit_after_early_terminator_effect(
75        &mut self,
76        _analysis: &mut A,
77        _state: &A::Domain,
78        _terminator: &mir::Terminator<'tcx>,
79        _location: Location,
80    ) {
81    }
82
83    /// Called after the "primary" effect of the given terminator is applied to `state`.
84    ///
85    /// The `call_return_effect` (if one exists) will *not* be applied to `state`.
86    fn visit_after_primary_terminator_effect(
87        &mut self,
88        _analysis: &mut A,
89        _state: &A::Domain,
90        _terminator: &mir::Terminator<'tcx>,
91        _location: Location,
92    ) {
93    }
94
95    fn visit_block_end(&mut self, _state: &A::Domain) {}
96}