@@ -12,6 +12,16 @@ pub trait Direction {
1212
1313 const IS_BACKWARD : bool = !Self :: IS_FORWARD ;
1414
15+ fn apply_effects_in_block < ' mir , ' tcx , A > (
16+ analysis : & mut A ,
17+ body : & mir:: Body < ' tcx > ,
18+ state : & mut A :: Domain ,
19+ block : BasicBlock ,
20+ block_data : & ' mir mir:: BasicBlockData < ' tcx > ,
21+ propagate : impl FnMut ( BasicBlock , & A :: Domain ) ,
22+ ) where
23+ A : Analysis < ' tcx > ;
24+
1525 /// Applies all effects between the given `EffectIndex`s.
1626 ///
1727 /// `effects.start()` must precede or equal `effects.end()` in this direction.
@@ -24,15 +34,6 @@ pub trait Direction {
2434 ) where
2535 A : Analysis < ' tcx > ;
2636
27- fn apply_effects_in_block < ' mir , ' tcx , A > (
28- analysis : & mut A ,
29- state : & mut A :: Domain ,
30- block : BasicBlock ,
31- block_data : & ' mir mir:: BasicBlockData < ' tcx > ,
32- ) -> TerminatorEdges < ' mir , ' tcx >
33- where
34- A : Analysis < ' tcx > ;
35-
3637 fn visit_results_in_block < ' mir , ' tcx , A > (
3738 state : & mut A :: Domain ,
3839 block : BasicBlock ,
@@ -41,16 +42,6 @@ pub trait Direction {
4142 vis : & mut impl ResultsVisitor < ' mir , ' tcx , A > ,
4243 ) where
4344 A : Analysis < ' tcx > ;
44-
45- fn join_state_into_successors_of < ' tcx , A > (
46- analysis : & mut A ,
47- body : & mir:: Body < ' tcx > ,
48- exit_state : & mut A :: Domain ,
49- block : BasicBlock ,
50- edges : TerminatorEdges < ' _ , ' tcx > ,
51- propagate : impl FnMut ( BasicBlock , & A :: Domain ) ,
52- ) where
53- A : Analysis < ' tcx > ;
5445}
5546
5647/// Dataflow that runs from the exit of a block (terminator), to its entry (the first statement).
@@ -61,23 +52,84 @@ impl Direction for Backward {
6152
6253 fn apply_effects_in_block < ' mir , ' tcx , A > (
6354 analysis : & mut A ,
55+ body : & mir:: Body < ' tcx > ,
6456 state : & mut A :: Domain ,
6557 block : BasicBlock ,
6658 block_data : & ' mir mir:: BasicBlockData < ' tcx > ,
67- ) -> TerminatorEdges < ' mir , ' tcx >
68- where
59+ mut propagate : impl FnMut ( BasicBlock , & A :: Domain ) ,
60+ ) where
6961 A : Analysis < ' tcx > ,
7062 {
7163 let terminator = block_data. terminator ( ) ;
7264 let location = Location { block, statement_index : block_data. statements . len ( ) } ;
7365 analysis. apply_before_terminator_effect ( state, terminator, location) ;
74- let edges = analysis. apply_terminator_effect ( state, terminator, location) ;
66+ analysis. apply_terminator_effect ( state, terminator, location) ;
7567 for ( statement_index, statement) in block_data. statements . iter ( ) . enumerate ( ) . rev ( ) {
7668 let location = Location { block, statement_index } ;
7769 analysis. apply_before_statement_effect ( state, statement, location) ;
7870 analysis. apply_statement_effect ( state, statement, location) ;
7971 }
80- edges
72+
73+ let exit_state = state;
74+ for pred in body. basic_blocks . predecessors ( ) [ block] . iter ( ) . copied ( ) {
75+ match body[ pred] . terminator ( ) . kind {
76+ // Apply terminator-specific edge effects.
77+ //
78+ // FIXME(ecstaticmorse): Avoid cloning the exit state unconditionally.
79+ mir:: TerminatorKind :: Call { destination, target : Some ( dest) , .. }
80+ if dest == block =>
81+ {
82+ let mut tmp = exit_state. clone ( ) ;
83+ analysis. apply_call_return_effect (
84+ & mut tmp,
85+ pred,
86+ CallReturnPlaces :: Call ( destination) ,
87+ ) ;
88+ propagate ( pred, & tmp) ;
89+ }
90+
91+ mir:: TerminatorKind :: InlineAsm { ref targets, ref operands, .. }
92+ if targets. contains ( & block) =>
93+ {
94+ let mut tmp = exit_state. clone ( ) ;
95+ analysis. apply_call_return_effect (
96+ & mut tmp,
97+ pred,
98+ CallReturnPlaces :: InlineAsm ( operands) ,
99+ ) ;
100+ propagate ( pred, & tmp) ;
101+ }
102+
103+ mir:: TerminatorKind :: Yield { resume, resume_arg, .. } if resume == block => {
104+ let mut tmp = exit_state. clone ( ) ;
105+ analysis. apply_call_return_effect (
106+ & mut tmp,
107+ resume,
108+ CallReturnPlaces :: Yield ( resume_arg) ,
109+ ) ;
110+ propagate ( pred, & tmp) ;
111+ }
112+
113+ mir:: TerminatorKind :: SwitchInt { targets : _, ref discr } => {
114+ let mut applier = BackwardSwitchIntEdgeEffectsApplier {
115+ body,
116+ pred,
117+ exit_state,
118+ block,
119+ propagate : & mut propagate,
120+ effects_applied : false ,
121+ } ;
122+
123+ analysis. apply_switch_int_edge_effects ( pred, discr, & mut applier) ;
124+
125+ if !applier. effects_applied {
126+ propagate ( pred, exit_state)
127+ }
128+ }
129+
130+ _ => propagate ( pred, exit_state) ,
131+ }
132+ }
81133 }
82134
83135 fn apply_effects_in_range < ' tcx , A > (
@@ -188,82 +240,13 @@ impl Direction for Backward {
188240
189241 vis. visit_block_start ( state) ;
190242 }
191-
192- fn join_state_into_successors_of < ' tcx , A > (
193- analysis : & mut A ,
194- body : & mir:: Body < ' tcx > ,
195- exit_state : & mut A :: Domain ,
196- bb : BasicBlock ,
197- _edges : TerminatorEdges < ' _ , ' tcx > ,
198- mut propagate : impl FnMut ( BasicBlock , & A :: Domain ) ,
199- ) where
200- A : Analysis < ' tcx > ,
201- {
202- for pred in body. basic_blocks . predecessors ( ) [ bb] . iter ( ) . copied ( ) {
203- match body[ pred] . terminator ( ) . kind {
204- // Apply terminator-specific edge effects.
205- //
206- // FIXME(ecstaticmorse): Avoid cloning the exit state unconditionally.
207- mir:: TerminatorKind :: Call { destination, target : Some ( dest) , .. } if dest == bb => {
208- let mut tmp = exit_state. clone ( ) ;
209- analysis. apply_call_return_effect (
210- & mut tmp,
211- pred,
212- CallReturnPlaces :: Call ( destination) ,
213- ) ;
214- propagate ( pred, & tmp) ;
215- }
216-
217- mir:: TerminatorKind :: InlineAsm { ref targets, ref operands, .. }
218- if targets. contains ( & bb) =>
219- {
220- let mut tmp = exit_state. clone ( ) ;
221- analysis. apply_call_return_effect (
222- & mut tmp,
223- pred,
224- CallReturnPlaces :: InlineAsm ( operands) ,
225- ) ;
226- propagate ( pred, & tmp) ;
227- }
228-
229- mir:: TerminatorKind :: Yield { resume, resume_arg, .. } if resume == bb => {
230- let mut tmp = exit_state. clone ( ) ;
231- analysis. apply_call_return_effect (
232- & mut tmp,
233- resume,
234- CallReturnPlaces :: Yield ( resume_arg) ,
235- ) ;
236- propagate ( pred, & tmp) ;
237- }
238-
239- mir:: TerminatorKind :: SwitchInt { targets : _, ref discr } => {
240- let mut applier = BackwardSwitchIntEdgeEffectsApplier {
241- body,
242- pred,
243- exit_state,
244- bb,
245- propagate : & mut propagate,
246- effects_applied : false ,
247- } ;
248-
249- analysis. apply_switch_int_edge_effects ( pred, discr, & mut applier) ;
250-
251- if !applier. effects_applied {
252- propagate ( pred, exit_state)
253- }
254- }
255-
256- _ => propagate ( pred, exit_state) ,
257- }
258- }
259- }
260243}
261244
262245struct BackwardSwitchIntEdgeEffectsApplier < ' mir , ' tcx , D , F > {
263246 body : & ' mir mir:: Body < ' tcx > ,
264247 pred : BasicBlock ,
265248 exit_state : & ' mir mut D ,
266- bb : BasicBlock ,
249+ block : BasicBlock ,
267250 propagate : & ' mir mut F ,
268251 effects_applied : bool ,
269252}
@@ -276,8 +259,8 @@ where
276259 fn apply ( & mut self , mut apply_edge_effect : impl FnMut ( & mut D , SwitchIntTarget ) ) {
277260 assert ! ( !self . effects_applied) ;
278261
279- let values = & self . body . basic_blocks . switch_sources ( ) [ & ( self . bb , self . pred ) ] ;
280- let targets = values. iter ( ) . map ( |& value| SwitchIntTarget { value, target : self . bb } ) ;
262+ let values = & self . body . basic_blocks . switch_sources ( ) [ & ( self . block , self . pred ) ] ;
263+ let targets = values. iter ( ) . map ( |& value| SwitchIntTarget { value, target : self . block } ) ;
281264
282265 let mut tmp = None ;
283266 for target in targets {
@@ -298,11 +281,12 @@ impl Direction for Forward {
298281
299282 fn apply_effects_in_block < ' mir , ' tcx , A > (
300283 analysis : & mut A ,
284+ _body : & mir:: Body < ' tcx > ,
301285 state : & mut A :: Domain ,
302286 block : BasicBlock ,
303287 block_data : & ' mir mir:: BasicBlockData < ' tcx > ,
304- ) -> TerminatorEdges < ' mir , ' tcx >
305- where
288+ mut propagate : impl FnMut ( BasicBlock , & A :: Domain ) ,
289+ ) where
306290 A : Analysis < ' tcx > ,
307291 {
308292 for ( statement_index, statement) in block_data. statements . iter ( ) . enumerate ( ) {
@@ -313,7 +297,53 @@ impl Direction for Forward {
313297 let terminator = block_data. terminator ( ) ;
314298 let location = Location { block, statement_index : block_data. statements . len ( ) } ;
315299 analysis. apply_before_terminator_effect ( state, terminator, location) ;
316- analysis. apply_terminator_effect ( state, terminator, location)
300+ let edges = analysis. apply_terminator_effect ( state, terminator, location) ;
301+
302+ let exit_state = state;
303+ match edges {
304+ TerminatorEdges :: None => { }
305+ TerminatorEdges :: Single ( target) => propagate ( target, exit_state) ,
306+ TerminatorEdges :: Double ( target, unwind) => {
307+ propagate ( target, exit_state) ;
308+ propagate ( unwind, exit_state) ;
309+ }
310+ TerminatorEdges :: AssignOnReturn { return_, cleanup, place } => {
311+ // This must be done *first*, otherwise the unwind path will see the assignments.
312+ if let Some ( cleanup) = cleanup {
313+ propagate ( cleanup, exit_state) ;
314+ }
315+
316+ if !return_. is_empty ( ) {
317+ analysis. apply_call_return_effect ( exit_state, block, place) ;
318+ for & target in return_ {
319+ propagate ( target, exit_state) ;
320+ }
321+ }
322+ }
323+ TerminatorEdges :: SwitchInt { targets, discr } => {
324+ let mut applier = ForwardSwitchIntEdgeEffectsApplier {
325+ exit_state,
326+ targets,
327+ propagate,
328+ effects_applied : false ,
329+ } ;
330+
331+ analysis. apply_switch_int_edge_effects ( block, discr, & mut applier) ;
332+
333+ let ForwardSwitchIntEdgeEffectsApplier {
334+ exit_state,
335+ mut propagate,
336+ effects_applied,
337+ ..
338+ } = applier;
339+
340+ if !effects_applied {
341+ for target in targets. all_targets ( ) {
342+ propagate ( * target, exit_state) ;
343+ }
344+ }
345+ }
346+ }
317347 }
318348
319349 fn apply_effects_in_range < ' tcx , A > (
@@ -351,7 +381,8 @@ impl Direction for Forward {
351381 let statement = & block_data. statements [ from. statement_index ] ;
352382 analysis. apply_statement_effect ( state, statement, location) ;
353383
354- // If we only needed to apply the after effect of the statement at `idx`, we are done.
384+ // If we only needed to apply the after effect of the statement at `idx`, we are
385+ // done.
355386 if from == to {
356387 return ;
357388 }
@@ -419,62 +450,6 @@ impl Direction for Forward {
419450
420451 vis. visit_block_end ( state) ;
421452 }
422-
423- fn join_state_into_successors_of < ' tcx , A > (
424- analysis : & mut A ,
425- _body : & mir:: Body < ' tcx > ,
426- exit_state : & mut A :: Domain ,
427- bb : BasicBlock ,
428- edges : TerminatorEdges < ' _ , ' tcx > ,
429- mut propagate : impl FnMut ( BasicBlock , & A :: Domain ) ,
430- ) where
431- A : Analysis < ' tcx > ,
432- {
433- match edges {
434- TerminatorEdges :: None => { }
435- TerminatorEdges :: Single ( target) => propagate ( target, exit_state) ,
436- TerminatorEdges :: Double ( target, unwind) => {
437- propagate ( target, exit_state) ;
438- propagate ( unwind, exit_state) ;
439- }
440- TerminatorEdges :: AssignOnReturn { return_, cleanup, place } => {
441- // This must be done *first*, otherwise the unwind path will see the assignments.
442- if let Some ( cleanup) = cleanup {
443- propagate ( cleanup, exit_state) ;
444- }
445-
446- if !return_. is_empty ( ) {
447- analysis. apply_call_return_effect ( exit_state, bb, place) ;
448- for & target in return_ {
449- propagate ( target, exit_state) ;
450- }
451- }
452- }
453- TerminatorEdges :: SwitchInt { targets, discr } => {
454- let mut applier = ForwardSwitchIntEdgeEffectsApplier {
455- exit_state,
456- targets,
457- propagate,
458- effects_applied : false ,
459- } ;
460-
461- analysis. apply_switch_int_edge_effects ( bb, discr, & mut applier) ;
462-
463- let ForwardSwitchIntEdgeEffectsApplier {
464- exit_state,
465- mut propagate,
466- effects_applied,
467- ..
468- } = applier;
469-
470- if !effects_applied {
471- for target in targets. all_targets ( ) {
472- propagate ( * target, exit_state) ;
473- }
474- }
475- }
476- }
477- }
478453}
479454
480455struct ForwardSwitchIntEdgeEffectsApplier < ' mir , D , F > {
0 commit comments