]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_mir_dataflow/src/framework/visitor.rs
Rollup merge of #99516 - m-ou-se:proc-macro-tracked-tracking-issue, r=Mark-Simulacrum
[rust.git] / compiler / rustc_mir_dataflow / src / framework / visitor.rs
1 use rustc_middle::mir::{self, BasicBlock, Location};
2
3 use 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.
7 pub fn visit_results<'mir, 'tcx, F, V>(
8     body: &'mir mir::Body<'tcx>,
9     blocks: impl IntoIterator<Item = BasicBlock>,
10     results: &V,
11     vis: &mut impl ResultsVisitor<'mir, 'tcx, FlowState = F>,
12 ) where
13     V: ResultsVisitable<'tcx, FlowState = F>,
14 {
15     let mut state = results.new_flow_state(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         V::Direction::visit_results_in_block(&mut state, block, block_data, results, vis);
26     }
27 }
28
29 pub trait ResultsVisitor<'mir, 'tcx> {
30     type FlowState;
31
32     fn visit_block_start(
33         &mut self,
34         _state: &Self::FlowState,
35         _block_data: &'mir mir::BasicBlockData<'tcx>,
36         _block: BasicBlock,
37     ) {
38     }
39
40     /// Called with the `before_statement_effect` of the given statement applied to `state` but not
41     /// its `statement_effect`.
42     fn visit_statement_before_primary_effect(
43         &mut self,
44         _state: &Self::FlowState,
45         _statement: &'mir mir::Statement<'tcx>,
46         _location: Location,
47     ) {
48     }
49
50     /// Called with both the `before_statement_effect` and the `statement_effect` of the given
51     /// statement applied to `state`.
52     fn visit_statement_after_primary_effect(
53         &mut self,
54         _state: &Self::FlowState,
55         _statement: &'mir mir::Statement<'tcx>,
56         _location: Location,
57     ) {
58     }
59
60     /// Called with the `before_terminator_effect` of the given terminator applied to `state` but not
61     /// its `terminator_effect`.
62     fn visit_terminator_before_primary_effect(
63         &mut self,
64         _state: &Self::FlowState,
65         _terminator: &'mir mir::Terminator<'tcx>,
66         _location: Location,
67     ) {
68     }
69
70     /// Called with both the `before_terminator_effect` and the `terminator_effect` of the given
71     /// terminator applied to `state`.
72     ///
73     /// The `call_return_effect` (if one exists) will *not* be applied to `state`.
74     fn visit_terminator_after_primary_effect(
75         &mut self,
76         _state: &Self::FlowState,
77         _terminator: &'mir mir::Terminator<'tcx>,
78         _location: Location,
79     ) {
80     }
81
82     fn visit_block_end(
83         &mut self,
84         _state: &Self::FlowState,
85         _block_data: &'mir mir::BasicBlockData<'tcx>,
86         _block: BasicBlock,
87     ) {
88     }
89 }
90
91 /// Things that can be visited by a `ResultsVisitor`.
92 ///
93 /// This trait exists so that we can visit the results of multiple dataflow analyses simultaneously.
94 /// DO NOT IMPLEMENT MANUALLY. Instead, use the `impl_visitable` macro below.
95 pub trait ResultsVisitable<'tcx> {
96     type Direction: Direction;
97     type FlowState;
98
99     /// Creates an empty `FlowState` to hold the transient state for these dataflow results.
100     ///
101     /// The value of the newly created `FlowState` will be overwritten by `reset_to_block_entry`
102     /// before it can be observed by a `ResultsVisitor`.
103     fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState;
104
105     fn reset_to_block_entry(&self, state: &mut Self::FlowState, block: BasicBlock);
106
107     fn reconstruct_before_statement_effect(
108         &self,
109         state: &mut Self::FlowState,
110         statement: &mir::Statement<'tcx>,
111         location: Location,
112     );
113
114     fn reconstruct_statement_effect(
115         &self,
116         state: &mut Self::FlowState,
117         statement: &mir::Statement<'tcx>,
118         location: Location,
119     );
120
121     fn reconstruct_before_terminator_effect(
122         &self,
123         state: &mut Self::FlowState,
124         terminator: &mir::Terminator<'tcx>,
125         location: Location,
126     );
127
128     fn reconstruct_terminator_effect(
129         &self,
130         state: &mut Self::FlowState,
131         terminator: &mir::Terminator<'tcx>,
132         location: Location,
133     );
134 }
135
136 impl<'tcx, A> ResultsVisitable<'tcx> for Results<'tcx, A>
137 where
138     A: Analysis<'tcx>,
139 {
140     type FlowState = A::Domain;
141
142     type Direction = A::Direction;
143
144     fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState {
145         self.analysis.bottom_value(body)
146     }
147
148     fn reset_to_block_entry(&self, state: &mut Self::FlowState, block: BasicBlock) {
149         state.clone_from(&self.entry_set_for_block(block));
150     }
151
152     fn reconstruct_before_statement_effect(
153         &self,
154         state: &mut Self::FlowState,
155         stmt: &mir::Statement<'tcx>,
156         loc: Location,
157     ) {
158         self.analysis.apply_before_statement_effect(state, stmt, loc);
159     }
160
161     fn reconstruct_statement_effect(
162         &self,
163         state: &mut Self::FlowState,
164         stmt: &mir::Statement<'tcx>,
165         loc: Location,
166     ) {
167         self.analysis.apply_statement_effect(state, stmt, loc);
168     }
169
170     fn reconstruct_before_terminator_effect(
171         &self,
172         state: &mut Self::FlowState,
173         term: &mir::Terminator<'tcx>,
174         loc: Location,
175     ) {
176         self.analysis.apply_before_terminator_effect(state, term, loc);
177     }
178
179     fn reconstruct_terminator_effect(
180         &self,
181         state: &mut Self::FlowState,
182         term: &mir::Terminator<'tcx>,
183         loc: Location,
184     ) {
185         self.analysis.apply_terminator_effect(state, term, loc);
186     }
187 }