@@ -453,36 +453,30 @@ pub enum TerminatorKind<'tcx> {
453
453
target : BasicBlock ,
454
454
} ,
455
455
456
- /// jump to branch 0 if this lvalue evaluates to true
457
- If {
458
- cond : Operand < ' tcx > ,
459
- targets : ( BasicBlock , BasicBlock ) ,
460
- } ,
461
-
462
- /// lvalue evaluates to some enum; jump depending on the branch
463
- Switch {
464
- discr : Lvalue < ' tcx > ,
465
- adt_def : & ' tcx AdtDef ,
466
- targets : Vec < BasicBlock > ,
467
- } ,
468
-
469
456
/// operand evaluates to an integer; jump depending on its value
470
457
/// to one of the targets, and otherwise fallback to `otherwise`
471
458
SwitchInt {
472
459
/// discriminant value being tested
473
- discr : Lvalue < ' tcx > ,
460
+ discr : Operand < ' tcx > ,
474
461
475
462
/// type of value being tested
476
463
switch_ty : Ty < ' tcx > ,
477
464
478
465
/// Possible values. The locations to branch to in each case
479
466
/// are found in the corresponding indices from the `targets` vector.
480
- values : Vec < ConstVal > ,
481
-
482
- /// Possible branch sites. The length of this vector should be
483
- /// equal to the length of the `values` vector plus 1 -- the
484
- /// extra item is the block to branch to if none of the values
485
- /// fit.
467
+ values : Cow < ' tcx , [ ConstInt ] > ,
468
+
469
+ /// Possible branch sites. The last element of this vector is used
470
+ /// for the otherwise branch, so values.len() == targets.len() + 1
471
+ /// should hold.
472
+ // This invariant is quite non-obvious and also could be improved.
473
+ // One way to make this invariant is to have something like this instead:
474
+ //
475
+ // branches: Vec<(ConstInt, BasicBlock)>,
476
+ // otherwise: Option<BasicBlock> // exhaustive if None
477
+ //
478
+ // However we’ve decided to keep this as-is until we figure a case
479
+ // where some other approach seems to be strictly better than other.
486
480
targets : Vec < BasicBlock > ,
487
481
} ,
488
482
@@ -546,12 +540,21 @@ impl<'tcx> Terminator<'tcx> {
546
540
}
547
541
548
542
impl < ' tcx > TerminatorKind < ' tcx > {
543
+ pub fn if_ < ' a , ' gcx > ( tcx : ty:: TyCtxt < ' a , ' gcx , ' tcx > , cond : Operand < ' tcx > ,
544
+ t : BasicBlock , f : BasicBlock ) -> TerminatorKind < ' tcx > {
545
+ static BOOL_SWITCH_FALSE : & ' static [ ConstInt ] = & [ ConstInt :: Infer ( 0 ) ] ;
546
+ TerminatorKind :: SwitchInt {
547
+ discr : cond,
548
+ switch_ty : tcx. types . bool ,
549
+ values : From :: from ( BOOL_SWITCH_FALSE ) ,
550
+ targets : vec ! [ f, t] ,
551
+ }
552
+ }
553
+
549
554
pub fn successors ( & self ) -> Cow < [ BasicBlock ] > {
550
555
use self :: TerminatorKind :: * ;
551
556
match * self {
552
557
Goto { target : ref b } => slice:: ref_slice ( b) . into_cow ( ) ,
553
- If { targets : ( b1, b2) , .. } => vec ! [ b1, b2] . into_cow ( ) ,
554
- Switch { targets : ref b, .. } => b[ ..] . into_cow ( ) ,
555
558
SwitchInt { targets : ref b, .. } => b[ ..] . into_cow ( ) ,
556
559
Resume => ( & [ ] ) . into_cow ( ) ,
557
560
Return => ( & [ ] ) . into_cow ( ) ,
@@ -580,8 +583,6 @@ impl<'tcx> TerminatorKind<'tcx> {
580
583
use self :: TerminatorKind :: * ;
581
584
match * self {
582
585
Goto { target : ref mut b } => vec ! [ b] ,
583
- If { targets : ( ref mut b1, ref mut b2) , .. } => vec ! [ b1, b2] ,
584
- Switch { targets : ref mut b, .. } => b. iter_mut ( ) . collect ( ) ,
585
586
SwitchInt { targets : ref mut b, .. } => b. iter_mut ( ) . collect ( ) ,
586
587
Resume => Vec :: new ( ) ,
587
588
Return => Vec :: new ( ) ,
@@ -659,8 +660,6 @@ impl<'tcx> TerminatorKind<'tcx> {
659
660
use self :: TerminatorKind :: * ;
660
661
match * self {
661
662
Goto { .. } => write ! ( fmt, "goto" ) ,
662
- If { cond : ref lv, .. } => write ! ( fmt, "if({:?})" , lv) ,
663
- Switch { discr : ref lv, .. } => write ! ( fmt, "switch({:?})" , lv) ,
664
663
SwitchInt { discr : ref lv, .. } => write ! ( fmt, "switchInt({:?})" , lv) ,
665
664
Return => write ! ( fmt, "return" ) ,
666
665
Resume => write ! ( fmt, "resume" ) ,
@@ -710,18 +709,11 @@ impl<'tcx> TerminatorKind<'tcx> {
710
709
match * self {
711
710
Return | Resume | Unreachable => vec ! [ ] ,
712
711
Goto { .. } => vec ! [ "" . into( ) ] ,
713
- If { .. } => vec ! [ "true" . into( ) , "false" . into( ) ] ,
714
- Switch { ref adt_def, .. } => {
715
- adt_def. variants
716
- . iter ( )
717
- . map ( |variant| variant. name . to_string ( ) . into ( ) )
718
- . collect ( )
719
- }
720
712
SwitchInt { ref values, .. } => {
721
713
values. iter ( )
722
714
. map ( |const_val| {
723
715
let mut buf = String :: new ( ) ;
724
- fmt_const_val ( & mut buf, const_val) . unwrap ( ) ;
716
+ fmt_const_val ( & mut buf, & ConstVal :: Integral ( * const_val) ) . unwrap ( ) ;
725
717
buf. into ( )
726
718
} )
727
719
. chain ( iter:: once ( String :: from ( "otherwise" ) . into ( ) ) )
@@ -997,6 +989,12 @@ pub enum Rvalue<'tcx> {
997
989
998
990
UnaryOp ( UnOp , Operand < ' tcx > ) ,
999
991
992
+ /// Read the discriminant of an ADT.
993
+ ///
994
+ /// Undefined (i.e. no effort is made to make it defined, but there’s no reason why it cannot
995
+ /// be defined to return, say, a 0) if ADT is not an enum.
996
+ Discriminant ( Lvalue < ' tcx > ) ,
997
+
1000
998
/// Creates an *uninitialized* Box
1001
999
Box ( Ty < ' tcx > ) ,
1002
1000
@@ -1111,6 +1109,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
1111
1109
write ! ( fmt, "Checked{:?}({:?}, {:?})" , op, a, b)
1112
1110
}
1113
1111
UnaryOp ( ref op, ref a) => write ! ( fmt, "{:?}({:?})" , op, a) ,
1112
+ Discriminant ( ref lval) => write ! ( fmt, "discriminant({:?})" , lval) ,
1114
1113
Box ( ref t) => write ! ( fmt, "Box({:?})" , t) ,
1115
1114
InlineAsm { ref asm, ref outputs, ref inputs } => {
1116
1115
write ! ( fmt, "asm!({:?} : {:?} : {:?})" , asm, outputs, inputs)
0 commit comments