@@ -10,6 +10,7 @@ use std::iter;
10
10
use std:: slice;
11
11
12
12
pub use super :: query:: * ;
13
+ use super :: * ;
13
14
14
15
#[ derive( Debug , Clone , TyEncodable , TyDecodable , Hash , HashStable , PartialEq ) ]
15
16
pub struct SwitchTargets {
@@ -430,3 +431,108 @@ impl<'tcx> TerminatorKind<'tcx> {
430
431
}
431
432
}
432
433
}
434
+
435
+ #[ derive( Copy , Clone , Debug ) ]
436
+ pub enum TerminatorEdges < ' mir , ' tcx > {
437
+ /// For terminators that have no successor, like `return`.
438
+ None ,
439
+ /// For terminators that a single successor, like `goto`, and `assert` without cleanup block.
440
+ Single ( BasicBlock ) ,
441
+ /// For terminators that two successors, `assert` with cleanup block and `falseEdge`.
442
+ Double ( BasicBlock , BasicBlock ) ,
443
+ /// Special action for `Yield`, `Call` and `InlineAsm` terminators.
444
+ AssignOnReturn {
445
+ return_ : Option < BasicBlock > ,
446
+ unwind : UnwindAction ,
447
+ place : CallReturnPlaces < ' mir , ' tcx > ,
448
+ } ,
449
+ /// Special edge for `SwitchInt`.
450
+ SwitchInt { targets : & ' mir SwitchTargets , discr : & ' mir Operand < ' tcx > } ,
451
+ }
452
+
453
+ /// List of places that are written to after a successful (non-unwind) return
454
+ /// from a `Call`, `Yield` or `InlineAsm`.
455
+ #[ derive( Copy , Clone , Debug ) ]
456
+ pub enum CallReturnPlaces < ' a , ' tcx > {
457
+ Call ( Place < ' tcx > ) ,
458
+ Yield ( Place < ' tcx > ) ,
459
+ InlineAsm ( & ' a [ InlineAsmOperand < ' tcx > ] ) ,
460
+ }
461
+
462
+ impl < ' tcx > CallReturnPlaces < ' _ , ' tcx > {
463
+ pub fn for_each ( & self , mut f : impl FnMut ( Place < ' tcx > ) ) {
464
+ match * self {
465
+ Self :: Call ( place) | Self :: Yield ( place) => f ( place) ,
466
+ Self :: InlineAsm ( operands) => {
467
+ for op in operands {
468
+ match * op {
469
+ InlineAsmOperand :: Out { place : Some ( place) , .. }
470
+ | InlineAsmOperand :: InOut { out_place : Some ( place) , .. } => f ( place) ,
471
+ _ => { }
472
+ }
473
+ }
474
+ }
475
+ }
476
+ }
477
+ }
478
+
479
+ impl < ' tcx > Terminator < ' tcx > {
480
+ pub fn edges ( & self ) -> TerminatorEdges < ' _ , ' tcx > {
481
+ self . kind . edges ( )
482
+ }
483
+ }
484
+
485
+ impl < ' tcx > TerminatorKind < ' tcx > {
486
+ pub fn edges ( & self ) -> TerminatorEdges < ' _ , ' tcx > {
487
+ use TerminatorKind :: * ;
488
+ match * self {
489
+ Return | Resume | Terminate | GeneratorDrop | Unreachable => TerminatorEdges :: None ,
490
+
491
+ Goto { target } => TerminatorEdges :: Single ( target) ,
492
+
493
+ Assert { target, unwind, expected : _, msg : _, cond : _ }
494
+ | Drop { target, unwind, place : _, replace : _ }
495
+ | FalseUnwind { real_target : target, unwind } => match unwind {
496
+ UnwindAction :: Cleanup ( unwind) => TerminatorEdges :: Double ( target, unwind) ,
497
+ UnwindAction :: Continue | UnwindAction :: Terminate | UnwindAction :: Unreachable => {
498
+ TerminatorEdges :: Single ( target)
499
+ }
500
+ } ,
501
+
502
+ FalseEdge { real_target, imaginary_target } => {
503
+ TerminatorEdges :: Double ( real_target, imaginary_target)
504
+ }
505
+
506
+ Yield { resume : target, drop, resume_arg, value : _ } => {
507
+ TerminatorEdges :: AssignOnReturn {
508
+ return_ : Some ( target) ,
509
+ unwind : drop. map_or ( UnwindAction :: Terminate , UnwindAction :: Cleanup ) ,
510
+ place : CallReturnPlaces :: Yield ( resume_arg) ,
511
+ }
512
+ }
513
+
514
+ Call { unwind, destination, target, func : _, args : _, fn_span : _, call_source : _ } => {
515
+ TerminatorEdges :: AssignOnReturn {
516
+ return_ : target,
517
+ unwind,
518
+ place : CallReturnPlaces :: Call ( destination) ,
519
+ }
520
+ }
521
+
522
+ InlineAsm {
523
+ template : _,
524
+ ref operands,
525
+ options : _,
526
+ line_spans : _,
527
+ destination,
528
+ unwind,
529
+ } => TerminatorEdges :: AssignOnReturn {
530
+ return_ : destination,
531
+ unwind,
532
+ place : CallReturnPlaces :: InlineAsm ( operands) ,
533
+ } ,
534
+
535
+ SwitchInt { ref targets, ref discr } => TerminatorEdges :: SwitchInt { targets, discr } ,
536
+ }
537
+ }
538
+ }
0 commit comments