]>
Commit | Line | Data |
---|---|---|
ba9703b0 | 1 | use rustc_middle::mir::{self, BasicBlock, Location}; |
74b04a01 | 2 | |
f9f354fc | 3 | use super::{Analysis, Direction, Results}; |
74b04a01 XL |
4 | |
5 | /// Calls the corresponding method in `ResultsVisitor` for every location in a `mir::Body` with the | |
6 | /// dataflow state at that location. | |
f9f354fc | 7 | pub fn visit_results<F, V>( |
74b04a01 XL |
8 | body: &'mir mir::Body<'tcx>, |
9 | blocks: impl IntoIterator<Item = BasicBlock>, | |
f9f354fc | 10 | results: &V, |
74b04a01 | 11 | vis: &mut impl ResultsVisitor<'mir, 'tcx, FlowState = F>, |
f9f354fc XL |
12 | ) where |
13 | V: ResultsVisitable<'tcx, FlowState = F>, | |
14 | { | |
74b04a01 XL |
15 | let mut state = results.new_flow_state(body); |
16 | ||
3dfed10e XL |
17 | #[cfg(debug_assertions)] |
18 | let reachable_blocks = mir::traversal::reachable_as_bitset(body); | |
19 | ||
74b04a01 | 20 | for block in blocks { |
3dfed10e XL |
21 | #[cfg(debug_assertions)] |
22 | assert!(reachable_blocks.contains(block)); | |
23 | ||
74b04a01 | 24 | let block_data = &body[block]; |
f9f354fc | 25 | V::Direction::visit_results_in_block(&mut state, block, block_data, results, vis); |
74b04a01 XL |
26 | } |
27 | } | |
28 | ||
29 | pub trait ResultsVisitor<'mir, 'tcx> { | |
30 | type FlowState; | |
31 | ||
f9f354fc XL |
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 | ||
74b04a01 XL |
40 | /// Called with the `before_statement_effect` of the given statement applied to `state` but not |
41 | /// its `statement_effect`. | |
f9f354fc | 42 | fn visit_statement_before_primary_effect( |
74b04a01 XL |
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`. | |
f9f354fc | 52 | fn visit_statement_after_primary_effect( |
74b04a01 XL |
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`. | |
f9f354fc | 62 | fn visit_terminator_before_primary_effect( |
74b04a01 XL |
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`. | |
f9f354fc | 74 | fn visit_terminator_after_primary_effect( |
74b04a01 XL |
75 | &mut self, |
76 | _state: &Self::FlowState, | |
77 | _terminator: &'mir mir::Terminator<'tcx>, | |
78 | _location: Location, | |
79 | ) { | |
80 | } | |
f9f354fc XL |
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 | } | |
74b04a01 XL |
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> { | |
f9f354fc | 96 | type Direction: Direction; |
74b04a01 XL |
97 | type FlowState; |
98 | ||
99 | /// Creates an empty `FlowState` to hold the transient state for these dataflow results. | |
100 | /// | |
f9f354fc | 101 | /// The value of the newly created `FlowState` will be overwritten by `reset_to_block_entry` |
74b04a01 XL |
102 | /// before it can be observed by a `ResultsVisitor`. |
103 | fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState; | |
104 | ||
f9f354fc | 105 | fn reset_to_block_entry(&self, state: &mut Self::FlowState, block: BasicBlock); |
74b04a01 XL |
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 | { | |
1b1a35ee | 140 | type FlowState = A::Domain; |
74b04a01 | 141 | |
f9f354fc XL |
142 | type Direction = A::Direction; |
143 | ||
74b04a01 | 144 | fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState { |
1b1a35ee | 145 | self.analysis.bottom_value(body) |
74b04a01 XL |
146 | } |
147 | ||
f9f354fc | 148 | fn reset_to_block_entry(&self, state: &mut Self::FlowState, block: BasicBlock) { |
1b1a35ee | 149 | state.clone_from(&self.entry_set_for_block(block)); |
74b04a01 XL |
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 | } |