1 use rustc_middle::mir::{self, BasicBlock, Location};
3 use super::{Analysis, Direction, Results};
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>,
11 vis: &mut impl ResultsVisitor<'mir, 'tcx, FlowState = F>,
13 V: ResultsVisitable<'tcx, FlowState = F>,
15 let mut state = results.new_flow_state(body);
17 #[cfg(debug_assertions)]
18 let reachable_blocks = mir::traversal::reachable_as_bitset(body);
21 #[cfg(debug_assertions)]
22 assert!(reachable_blocks.contains(block));
24 let block_data = &body[block];
25 V::Direction::visit_results_in_block(&mut state, block, block_data, results, vis);
29 pub trait ResultsVisitor<'mir, 'tcx> {
34 _state: &Self::FlowState,
35 _block_data: &'mir mir::BasicBlockData<'tcx>,
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(
44 _state: &Self::FlowState,
45 _statement: &'mir mir::Statement<'tcx>,
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(
54 _state: &Self::FlowState,
55 _statement: &'mir mir::Statement<'tcx>,
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(
64 _state: &Self::FlowState,
65 _terminator: &'mir mir::Terminator<'tcx>,
70 /// Called with both the `before_terminator_effect` and the `terminator_effect` of the given
71 /// terminator applied to `state`.
73 /// The `call_return_effect` (if one exists) will *not* be applied to `state`.
74 fn visit_terminator_after_primary_effect(
76 _state: &Self::FlowState,
77 _terminator: &'mir mir::Terminator<'tcx>,
84 _state: &Self::FlowState,
85 _block_data: &'mir mir::BasicBlockData<'tcx>,
91 /// Things that can be visited by a `ResultsVisitor`.
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;
99 /// Creates an empty `FlowState` to hold the transient state for these dataflow results.
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;
105 fn reset_to_block_entry(&self, state: &mut Self::FlowState, block: BasicBlock);
107 fn reconstruct_before_statement_effect(
109 state: &mut Self::FlowState,
110 statement: &mir::Statement<'tcx>,
114 fn reconstruct_statement_effect(
116 state: &mut Self::FlowState,
117 statement: &mir::Statement<'tcx>,
121 fn reconstruct_before_terminator_effect(
123 state: &mut Self::FlowState,
124 terminator: &mir::Terminator<'tcx>,
128 fn reconstruct_terminator_effect(
130 state: &mut Self::FlowState,
131 terminator: &mir::Terminator<'tcx>,
136 impl<'tcx, A> ResultsVisitable<'tcx> for Results<'tcx, A>
140 type FlowState = A::Domain;
142 type Direction = A::Direction;
144 fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState {
145 self.analysis.bottom_value(body)
148 fn reset_to_block_entry(&self, state: &mut Self::FlowState, block: BasicBlock) {
149 state.clone_from(&self.entry_set_for_block(block));
152 fn reconstruct_before_statement_effect(
154 state: &mut Self::FlowState,
155 stmt: &mir::Statement<'tcx>,
158 self.analysis.apply_before_statement_effect(state, stmt, loc);
161 fn reconstruct_statement_effect(
163 state: &mut Self::FlowState,
164 stmt: &mir::Statement<'tcx>,
167 self.analysis.apply_statement_effect(state, stmt, loc);
170 fn reconstruct_before_terminator_effect(
172 state: &mut Self::FlowState,
173 term: &mir::Terminator<'tcx>,
176 self.analysis.apply_before_terminator_effect(state, term, loc);
179 fn reconstruct_terminator_effect(
181 state: &mut Self::FlowState,
182 term: &mir::Terminator<'tcx>,
185 self.analysis.apply_terminator_effect(state, term, loc);