Skip to content

Commit 141483a

Browse files
generic visitor WIP
1 parent d252816 commit 141483a

File tree

2 files changed

+253
-0
lines changed

2 files changed

+253
-0
lines changed

src/librustc_mir/dataflow/generic/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ use crate::dataflow::BottomValue;
4343
mod cursor;
4444
mod engine;
4545
mod graphviz;
46+
pub mod visitor;
4647

4748
pub use self::cursor::{ResultsCursor, ResultsRefCursor};
4849
pub use self::engine::Engine;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
use rustc::mir::{self, BasicBlock, Location};
2+
use rustc_index::bit_set::BitSet;
3+
4+
use super::{Analysis, Results};
5+
use crate::dataflow::impls::{borrows::Borrows, EverInitializedPlaces, MaybeUninitializedPlaces};
6+
7+
/// For every location in a `mir::Body`, calls the corresponding method in `ResultsVisitor` with
8+
/// the appropriate dataflow state in `Results`.
9+
pub fn visit_results<F>(
10+
body: &'mir mir::Body<'tcx>,
11+
blocks: impl IntoIterator<Item = BasicBlock>,
12+
results: &impl ResultsVisitable<'tcx, FlowState = F>,
13+
vis: &mut impl ResultsVisitor<'mir, 'tcx, FlowState = F>,
14+
) {
15+
let mut state = results.new_flow_state(body);
16+
17+
for block in blocks {
18+
let block_data = &body[block];
19+
results.reset_to_block_start(&mut state, block);
20+
21+
for (statement_index, stmt) in block_data.statements.iter().enumerate() {
22+
let loc = Location { block, statement_index };
23+
24+
results.reconstruct_before_statement_effect(&mut state, stmt, loc);
25+
vis.visit_statement(&mut state, stmt, loc);
26+
27+
results.reconstruct_statement_effect(&mut state, stmt, loc);
28+
vis.visit_statement_exit(&mut state, stmt, loc);
29+
}
30+
31+
let loc = body.terminator_loc(block);
32+
let term = block_data.terminator();
33+
34+
results.reconstruct_before_terminator_effect(&mut state, term, loc);
35+
vis.visit_terminator(&mut state, term, loc);
36+
37+
results.reconstruct_terminator_effect(&mut state, term, loc);
38+
vis.visit_terminator_exit(&mut state, term, loc);
39+
}
40+
}
41+
42+
pub trait ResultsVisitor<'mir, 'tcx> {
43+
type FlowState;
44+
45+
fn visit_statement(
46+
&mut self,
47+
_state: &Self::FlowState,
48+
_statement: &'mir mir::Statement<'tcx>,
49+
_location: Location,
50+
) {
51+
}
52+
53+
fn visit_statement_exit(
54+
&mut self,
55+
_state: &Self::FlowState,
56+
_statement: &'mir mir::Statement<'tcx>,
57+
_location: Location,
58+
) {
59+
}
60+
61+
fn visit_terminator(
62+
&mut self,
63+
_state: &Self::FlowState,
64+
_terminator: &'mir mir::Terminator<'tcx>,
65+
_location: Location,
66+
) {
67+
}
68+
69+
fn visit_terminator_exit(
70+
&mut self,
71+
_state: &Self::FlowState,
72+
_terminator: &'mir mir::Terminator<'tcx>,
73+
_location: Location,
74+
) {
75+
}
76+
}
77+
78+
/// Things that can be visited by a `ResultsVisitor`.
79+
///
80+
/// This trait exists so that we can visit the results of multiple dataflow analyses simultaneously.
81+
pub trait ResultsVisitable<'tcx> {
82+
type FlowState;
83+
84+
fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState;
85+
86+
fn reset_to_block_start(&self, state: &mut Self::FlowState, block: BasicBlock);
87+
88+
fn reconstruct_before_statement_effect(
89+
&self,
90+
state: &mut Self::FlowState,
91+
statement: &mir::Statement<'tcx>,
92+
location: Location,
93+
);
94+
95+
fn reconstruct_statement_effect(
96+
&self,
97+
state: &mut Self::FlowState,
98+
statement: &mir::Statement<'tcx>,
99+
location: Location,
100+
);
101+
102+
fn reconstruct_before_terminator_effect(
103+
&self,
104+
state: &mut Self::FlowState,
105+
terminator: &mir::Terminator<'tcx>,
106+
location: Location,
107+
);
108+
109+
fn reconstruct_terminator_effect(
110+
&self,
111+
state: &mut Self::FlowState,
112+
terminator: &mir::Terminator<'tcx>,
113+
location: Location,
114+
);
115+
}
116+
117+
impl<'tcx, A> ResultsVisitable<'tcx> for Results<'tcx, A>
118+
where
119+
A: Analysis<'tcx>,
120+
{
121+
type FlowState = BitSet<A::Idx>;
122+
123+
fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState {
124+
BitSet::new_empty(self.analysis.bits_per_block(body))
125+
}
126+
127+
fn reset_to_block_start(&self, state: &mut Self::FlowState, block: BasicBlock) {
128+
state.overwrite(&self.entry_set_for_block(block));
129+
}
130+
131+
fn reconstruct_before_statement_effect(
132+
&self,
133+
state: &mut Self::FlowState,
134+
stmt: &mir::Statement<'tcx>,
135+
loc: Location,
136+
) {
137+
self.analysis.apply_before_statement_effect(state, stmt, loc);
138+
}
139+
140+
fn reconstruct_statement_effect(
141+
&self,
142+
state: &mut Self::FlowState,
143+
stmt: &mir::Statement<'tcx>,
144+
loc: Location,
145+
) {
146+
self.analysis.apply_statement_effect(state, stmt, loc);
147+
}
148+
149+
fn reconstruct_before_terminator_effect(
150+
&self,
151+
state: &mut Self::FlowState,
152+
term: &mir::Terminator<'tcx>,
153+
loc: Location,
154+
) {
155+
self.analysis.apply_before_terminator_effect(state, term, loc);
156+
}
157+
158+
fn reconstruct_terminator_effect(
159+
&self,
160+
state: &mut Self::FlowState,
161+
term: &mir::Terminator<'tcx>,
162+
loc: Location,
163+
) {
164+
self.analysis.apply_terminator_effect(state, term, loc);
165+
}
166+
}
167+
168+
macro_rules! results_tuples {
169+
( $(
170+
$( #[$meta:meta] )*
171+
$T:ident { $( $field:ident : $A:ident ),* $(,)? }
172+
)* ) => { $(
173+
$( #[$meta] )*
174+
#[derive(Debug)]
175+
pub struct $T<$($A),*> {
176+
$( pub $field: $A, )*
177+
}
178+
179+
impl<'tcx, $( $A),*> ResultsVisitable<'tcx> for $T<$( Results<'tcx, $A> ),*>
180+
where
181+
$( $A: Analysis<'tcx>, )*
182+
{
183+
type FlowState = $T<$( BitSet<$A::Idx> ),*>;
184+
185+
fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState {
186+
$T {
187+
$( $field: BitSet::new_empty(self.$field.analysis.bits_per_block(body)) ),*
188+
}
189+
}
190+
191+
fn reset_to_block_start(
192+
&self,
193+
state: &mut Self::FlowState,
194+
block: BasicBlock,
195+
) {
196+
$( state.$field.overwrite(&self.$field.entry_sets[block]); )*
197+
}
198+
199+
fn reconstruct_before_statement_effect(
200+
&self,
201+
state: &mut Self::FlowState,
202+
stmt: &mir::Statement<'tcx>,
203+
loc: Location,
204+
) {
205+
$( self.$field.analysis
206+
.apply_before_statement_effect(&mut state.$field, stmt, loc); )*
207+
}
208+
209+
fn reconstruct_statement_effect(
210+
&self,
211+
state: &mut Self::FlowState,
212+
stmt: &mir::Statement<'tcx>,
213+
loc: Location,
214+
) {
215+
$( self.$field.analysis
216+
.apply_statement_effect(&mut state.$field, stmt, loc); )*
217+
}
218+
219+
fn reconstruct_before_terminator_effect(
220+
&self,
221+
state: &mut Self::FlowState,
222+
term: &mir::Terminator<'tcx>,
223+
loc: Location,
224+
) {
225+
$( self.$field.analysis
226+
.apply_before_terminator_effect(&mut state.$field, term, loc); )*
227+
}
228+
229+
fn reconstruct_terminator_effect(
230+
&self,
231+
state: &mut Self::FlowState,
232+
term: &mir::Terminator<'tcx>,
233+
loc: Location,
234+
) {
235+
$( self.$field.analysis
236+
.apply_terminator_effect(&mut state.$field, term, loc); )*
237+
}
238+
}
239+
)* }
240+
}
241+
242+
results_tuples!(
243+
/// A tuple with named fields to hold the results of the dataflow analyses used by the
244+
/// borrow checker.
245+
BorrowckAnalyses { borrows: B, uninits: U, ever_inits: E }
246+
);
247+
248+
pub type BorrowckResults<'mir, 'tcx> = BorrowckAnalyses<
249+
Results<'tcx, Borrows<'mir, 'tcx>>,
250+
Results<'tcx, MaybeUninitializedPlaces<'mir, 'tcx>>,
251+
Results<'tcx, EverInitializedPlaces<'mir, 'tcx>>,
252+
>;

0 commit comments

Comments
 (0)