@@ -248,6 +248,7 @@ impl Direction for Backward {
248
248
) ;
249
249
propagate ( pred, & tmp) ;
250
250
}
251
+
251
252
mir:: TerminatorKind :: InlineAsm {
252
253
destination : Some ( dest) , ref operands, ..
253
254
} if dest == bb => {
@@ -266,6 +267,25 @@ impl Direction for Backward {
266
267
propagate ( pred, & tmp) ;
267
268
}
268
269
270
+ mir:: TerminatorKind :: SwitchInt { ref targets, ref discr, switch_ty : _ } => {
271
+ let mut applier = BackwardSwitchIntEdgeEffectsApplier {
272
+ pred,
273
+ exit_state,
274
+ targets,
275
+ bb,
276
+ propagate : & mut propagate,
277
+ effects_applied : false ,
278
+ } ;
279
+
280
+ analysis. apply_switch_int_edge_effects ( pred, discr, & mut applier) ;
281
+
282
+ let BackwardSwitchIntEdgeEffectsApplier { effects_applied, .. } = applier;
283
+
284
+ if !effects_applied {
285
+ propagate ( pred, exit_state)
286
+ }
287
+ }
288
+
269
289
// Ignore dead unwinds.
270
290
mir:: TerminatorKind :: Call { cleanup : Some ( unwind) , .. }
271
291
| mir:: TerminatorKind :: Assert { cleanup : Some ( unwind) , .. }
@@ -286,6 +306,33 @@ impl Direction for Backward {
286
306
}
287
307
}
288
308
309
+ struct BackwardSwitchIntEdgeEffectsApplier < ' a , D , F > {
310
+ pred : BasicBlock ,
311
+ exit_state : & ' a mut D ,
312
+ targets : & ' a SwitchTargets ,
313
+ bb : BasicBlock ,
314
+ propagate : & ' a mut F ,
315
+
316
+ effects_applied : bool ,
317
+ }
318
+
319
+ impl < D , F > super :: SwitchIntEdgeEffects < D > for BackwardSwitchIntEdgeEffectsApplier < ' _ , D , F >
320
+ where
321
+ D : Clone ,
322
+ F : FnMut ( BasicBlock , & D ) ,
323
+ {
324
+ fn apply ( & mut self , mut apply_edge_effect : impl FnMut ( & mut D , SwitchIntTarget ) ) {
325
+ assert ! ( !self . effects_applied) ;
326
+
327
+ let value =
328
+ self . targets . iter ( ) . find_map ( |( value, target) | ( target == self . bb ) . then_some ( value) ) ;
329
+ apply_edge_effect ( self . exit_state , SwitchIntTarget { value, target : self . bb } ) ;
330
+ ( self . propagate ) ( self . pred , self . exit_state ) ;
331
+
332
+ self . effects_applied = true ;
333
+ }
334
+ }
335
+
289
336
/// Dataflow that runs from the entry of a block (the first statement), to its exit (terminator).
290
337
pub struct Forward ;
291
338
@@ -528,7 +575,7 @@ impl Direction for Forward {
528
575
}
529
576
530
577
SwitchInt { ref targets, ref discr, switch_ty : _ } => {
531
- let mut applier = SwitchIntEdgeEffectApplier {
578
+ let mut applier = ForwardSwitchIntEdgeEffectsApplier {
532
579
exit_state,
533
580
targets,
534
581
propagate,
@@ -537,8 +584,11 @@ impl Direction for Forward {
537
584
538
585
analysis. apply_switch_int_edge_effects ( bb, discr, & mut applier) ;
539
586
540
- let SwitchIntEdgeEffectApplier {
541
- exit_state, mut propagate, effects_applied, ..
587
+ let ForwardSwitchIntEdgeEffectsApplier {
588
+ exit_state,
589
+ mut propagate,
590
+ effects_applied,
591
+ ..
542
592
} = applier;
543
593
544
594
if !effects_applied {
@@ -551,15 +601,15 @@ impl Direction for Forward {
551
601
}
552
602
}
553
603
554
- struct SwitchIntEdgeEffectApplier < ' a , D , F > {
604
+ struct ForwardSwitchIntEdgeEffectsApplier < ' a , D , F > {
555
605
exit_state : & ' a mut D ,
556
606
targets : & ' a SwitchTargets ,
557
607
propagate : F ,
558
608
559
609
effects_applied : bool ,
560
610
}
561
611
562
- impl < D , F > super :: SwitchIntEdgeEffects < D > for SwitchIntEdgeEffectApplier < ' _ , D , F >
612
+ impl < D , F > super :: SwitchIntEdgeEffects < D > for ForwardSwitchIntEdgeEffectsApplier < ' _ , D , F >
563
613
where
564
614
D : Clone ,
565
615
F : FnMut ( BasicBlock , & D ) ,
0 commit comments