@@ -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,23 @@ impl Direction for Backward {
266
267
propagate ( pred, & tmp) ;
267
268
}
268
269
270
+ mir:: TerminatorKind :: SwitchInt { targets : _, ref discr, switch_ty : _ } => {
271
+ let mut applier = BackwardSwitchIntEdgeEffectsApplier {
272
+ pred,
273
+ exit_state,
274
+ values : & body. switch_sources ( ) [ bb] [ pred] ,
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
+ if !applier. effects_applied {
283
+ propagate ( pred, exit_state)
284
+ }
285
+ }
286
+
269
287
// Ignore dead unwinds.
270
288
mir:: TerminatorKind :: Call { cleanup : Some ( unwind) , .. }
271
289
| mir:: TerminatorKind :: Assert { cleanup : Some ( unwind) , .. }
@@ -286,6 +304,37 @@ impl Direction for Backward {
286
304
}
287
305
}
288
306
307
+ struct BackwardSwitchIntEdgeEffectsApplier < ' a , D , F > {
308
+ pred : BasicBlock ,
309
+ exit_state : & ' a mut D ,
310
+ values : & ' a [ Option < u128 > ] ,
311
+ bb : BasicBlock ,
312
+ propagate : & ' a mut F ,
313
+
314
+ effects_applied : bool ,
315
+ }
316
+
317
+ impl < D , F > super :: SwitchIntEdgeEffects < D > for BackwardSwitchIntEdgeEffectsApplier < ' _ , D , F >
318
+ where
319
+ D : Clone ,
320
+ F : FnMut ( BasicBlock , & D ) ,
321
+ {
322
+ fn apply ( & mut self , mut apply_edge_effect : impl FnMut ( & mut D , SwitchIntTarget ) ) {
323
+ assert ! ( !self . effects_applied) ;
324
+
325
+ let targets = self . values . iter ( ) . map ( |& value| SwitchIntTarget { value, target : self . bb } ) ;
326
+
327
+ let mut tmp = None ;
328
+ for target in targets {
329
+ let tmp = opt_clone_from_or_clone ( & mut tmp, self . exit_state ) ;
330
+ apply_edge_effect ( tmp, target) ;
331
+ ( self . propagate ) ( self . pred , tmp) ;
332
+ }
333
+
334
+ self . effects_applied = true ;
335
+ }
336
+ }
337
+
289
338
/// Dataflow that runs from the entry of a block (the first statement), to its exit (terminator).
290
339
pub struct Forward ;
291
340
@@ -528,7 +577,7 @@ impl Direction for Forward {
528
577
}
529
578
530
579
SwitchInt { ref targets, ref discr, switch_ty : _ } => {
531
- let mut applier = SwitchIntEdgeEffectApplier {
580
+ let mut applier = ForwardSwitchIntEdgeEffectsApplier {
532
581
exit_state,
533
582
targets,
534
583
propagate,
@@ -537,8 +586,11 @@ impl Direction for Forward {
537
586
538
587
analysis. apply_switch_int_edge_effects ( bb, discr, & mut applier) ;
539
588
540
- let SwitchIntEdgeEffectApplier {
541
- exit_state, mut propagate, effects_applied, ..
589
+ let ForwardSwitchIntEdgeEffectsApplier {
590
+ exit_state,
591
+ mut propagate,
592
+ effects_applied,
593
+ ..
542
594
} = applier;
543
595
544
596
if !effects_applied {
@@ -551,15 +603,15 @@ impl Direction for Forward {
551
603
}
552
604
}
553
605
554
- struct SwitchIntEdgeEffectApplier < ' a , D , F > {
606
+ struct ForwardSwitchIntEdgeEffectsApplier < ' a , D , F > {
555
607
exit_state : & ' a mut D ,
556
608
targets : & ' a SwitchTargets ,
557
609
propagate : F ,
558
610
559
611
effects_applied : bool ,
560
612
}
561
613
562
- impl < D , F > super :: SwitchIntEdgeEffects < D > for SwitchIntEdgeEffectApplier < ' _ , D , F >
614
+ impl < D , F > super :: SwitchIntEdgeEffects < D > for ForwardSwitchIntEdgeEffectsApplier < ' _ , D , F >
563
615
where
564
616
D : Clone ,
565
617
F : FnMut ( BasicBlock , & D ) ,
0 commit comments