If is now always a SwitchInt in MIR

This commit is contained in:
Simonas Kazlauskas 2017-01-31 05:32:08 +02:00
parent 779c6b6cb8
commit 98d1db7fe3
18 changed files with 76 additions and 102 deletions

View File

@ -453,12 +453,6 @@ pub enum TerminatorKind<'tcx> {
target: BasicBlock,
},
/// jump to branch 0 if this lvalue evaluates to true
If {
cond: Operand<'tcx>,
targets: (BasicBlock, BasicBlock),
},
/// lvalue evaluates to some enum; jump depending on the branch
Switch {
discr: Lvalue<'tcx>,
@ -470,7 +464,7 @@ pub enum TerminatorKind<'tcx> {
/// to one of the targets, and otherwise fallback to `otherwise`
SwitchInt {
/// discriminant value being tested
discr: Lvalue<'tcx>,
discr: Operand<'tcx>,
/// type of value being tested
switch_ty: Ty<'tcx>,
@ -550,7 +544,6 @@ impl<'tcx> TerminatorKind<'tcx> {
use self::TerminatorKind::*;
match *self {
Goto { target: ref b } => slice::ref_slice(b).into_cow(),
If { targets: (b1, b2), .. } => vec![b1, b2].into_cow(),
Switch { targets: ref b, .. } => b[..].into_cow(),
SwitchInt { targets: ref b, .. } => b[..].into_cow(),
Resume => (&[]).into_cow(),
@ -580,7 +573,6 @@ impl<'tcx> TerminatorKind<'tcx> {
use self::TerminatorKind::*;
match *self {
Goto { target: ref mut b } => vec![b],
If { targets: (ref mut b1, ref mut b2), .. } => vec![b1, b2],
Switch { targets: ref mut b, .. } => b.iter_mut().collect(),
SwitchInt { targets: ref mut b, .. } => b.iter_mut().collect(),
Resume => Vec::new(),
@ -659,7 +651,6 @@ impl<'tcx> TerminatorKind<'tcx> {
use self::TerminatorKind::*;
match *self {
Goto { .. } => write!(fmt, "goto"),
If { cond: ref lv, .. } => write!(fmt, "if({:?})", lv),
Switch { discr: ref lv, .. } => write!(fmt, "switch({:?})", lv),
SwitchInt { discr: ref lv, .. } => write!(fmt, "switchInt({:?})", lv),
Return => write!(fmt, "return"),
@ -710,7 +701,6 @@ impl<'tcx> TerminatorKind<'tcx> {
match *self {
Return | Resume | Unreachable => vec![],
Goto { .. } => vec!["".into()],
If { .. } => vec!["true".into(), "false".into()],
Switch { ref adt_def, .. } => {
adt_def.variants
.iter()

View File

@ -14,7 +14,6 @@ use ty::subst::Substs;
use ty::{ClosureSubsts, Region, Ty};
use mir::*;
use rustc_const_math::ConstUsize;
use rustc_data_structures::tuple_slice::TupleSlice;
use rustc_data_structures::indexed_vec::Idx;
use syntax_pos::Span;
@ -363,14 +362,6 @@ macro_rules! make_mir_visitor {
self.visit_branch(block, target);
}
TerminatorKind::If { ref $($mutability)* cond,
ref $($mutability)* targets } => {
self.visit_operand(cond, source_location);
for &target in targets.as_slice() {
self.visit_branch(block, target);
}
}
TerminatorKind::Switch { ref $($mutability)* discr,
adt_def: _,
ref targets } => {
@ -384,7 +375,7 @@ macro_rules! make_mir_visitor {
ref $($mutability)* switch_ty,
ref $($mutability)* values,
ref targets } => {
self.visit_lvalue(discr, LvalueContext::Inspect, source_location);
self.visit_operand(discr, source_location);
self.visit_ty(switch_ty);
for value in values {
self.visit_const_val(value, source_location);

View File

@ -454,10 +454,6 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D>
self.propagate_bits_into_entry_set_for(in_out, changed, target);
self.propagate_bits_into_entry_set_for(in_out, changed, unwind);
}
mir::TerminatorKind::If { ref targets, .. } => {
self.propagate_bits_into_entry_set_for(in_out, changed, &targets.0);
self.propagate_bits_into_entry_set_for(in_out, changed, &targets.1);
}
mir::TerminatorKind::Switch { ref targets, .. } |
mir::TerminatorKind::SwitchInt { ref targets, .. } => {
for target in targets {

View File

@ -813,9 +813,12 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
(true, false) => on_set,
(true, true) => {
let flag = self.drop_flag(c.path).unwrap();
self.new_block(c, is_cleanup, TerminatorKind::If {
cond: Operand::Consume(flag),
targets: (on_set, on_unset)
let boolty = self.tcx.types.bool;
self.new_block(c, is_cleanup, TerminatorKind::SwitchInt {
discr: Operand::Consume(flag),
switch_ty: boolty,
values: vec![ConstVal::Bool(true)],
targets: vec![on_set, on_unset],
})
}
}

View File

@ -464,7 +464,6 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
self.gather_move(loc, &Lvalue::Local(RETURN_POINTER));
}
TerminatorKind::If { .. } |
TerminatorKind::Assert { .. } |
TerminatorKind::SwitchInt { .. } |
TerminatorKind::Switch { .. } => {

View File

@ -15,6 +15,7 @@ use build::expr::category::{Category, RvalueFunc};
use hair::*;
use rustc::ty;
use rustc::mir::*;
use rustc::middle::const_val::ConstVal;
impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
/// Compile `expr`, storing the result into `destination`, which
@ -69,9 +70,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
let mut then_block = this.cfg.start_new_block();
let mut else_block = this.cfg.start_new_block();
this.cfg.terminate(block, source_info, TerminatorKind::If {
cond: operand,
targets: (then_block, else_block)
this.cfg.terminate(block, source_info, TerminatorKind::SwitchInt {
discr: operand,
switch_ty: this.hir.bool_ty(),
values: vec![ConstVal::Bool(true)],
targets: vec![then_block, else_block],
});
unpack!(then_block = this.into(destination, then_block, then_expr));
@ -111,16 +114,22 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
let lhs = unpack!(block = this.as_operand(block, lhs));
let blocks = match op {
LogicalOp::And => (else_block, false_block),
LogicalOp::Or => (true_block, else_block),
LogicalOp::And => vec![else_block, false_block],
LogicalOp::Or => vec![true_block, else_block],
};
this.cfg.terminate(block, source_info,
TerminatorKind::If { cond: lhs, targets: blocks });
this.cfg.terminate(block, source_info, TerminatorKind::SwitchInt {
discr: lhs,
switch_ty: this.hir.bool_ty(),
values: vec![ConstVal::Bool(true)],
targets: blocks,
});
let rhs = unpack!(else_block = this.as_operand(else_block, rhs));
this.cfg.terminate(else_block, source_info, TerminatorKind::If {
cond: rhs,
targets: (true_block, false_block)
this.cfg.terminate(else_block, source_info, TerminatorKind::SwitchInt {
discr: rhs,
switch_ty: this.hir.bool_ty(),
values: vec![ConstVal::Bool(true)],
targets: vec![true_block, false_block],
});
this.cfg.push_assign_constant(
@ -180,9 +189,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
loop_block_end = this.as_operand(loop_block, cond_expr));
body_block = this.cfg.start_new_block();
this.cfg.terminate(loop_block_end, source_info,
TerminatorKind::If {
cond: cond,
targets: (body_block, exit_block)
TerminatorKind::SwitchInt {
discr: cond,
switch_ty: this.hir.bool_ty(),
values: vec![ConstVal::Bool(true)],
targets: vec![body_block, exit_block],
});
// if the test is false, there's no `break` to assign `destination`, so

View File

@ -672,9 +672,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
let source_info = self.source_info(guard.span);
let cond = unpack!(block = self.as_operand(block, guard));
let otherwise = self.cfg.start_new_block();
self.cfg.terminate(block, source_info,
TerminatorKind::If { cond: cond,
targets: (arm_block, otherwise)});
self.cfg.terminate(block, source_info, TerminatorKind::SwitchInt {
discr: cond,
switch_ty: self.hir.bool_ty(),
values: vec![ConstVal::Bool(true)],
targets: vec![arm_block, otherwise],
});
Some(otherwise)
} else {
let source_info = self.source_info(candidate.span);

View File

@ -221,10 +221,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
v => span_bug!(test.span, "expected boolean value but got {:?}", v)
};
(targets,
TerminatorKind::If {
cond: Operand::Consume(lvalue.clone()),
targets: (true_bb, else_bb)
(targets, TerminatorKind::SwitchInt {
discr: Operand::Consume(lvalue.clone()),
switch_ty: self.hir.bool_ty(),
values: vec![ConstVal::Bool(true)],
targets: vec![true_bb, else_bb]
})
}
@ -240,7 +241,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
(targets.clone(),
TerminatorKind::SwitchInt {
discr: lvalue.clone(),
discr: Operand::Consume(lvalue.clone()),
switch_ty: switch_ty,
values: options.clone(),
targets: targets
@ -314,9 +315,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
// check the result
let block = self.cfg.start_new_block();
self.cfg.terminate(eq_block, source_info, TerminatorKind::If {
cond: Operand::Consume(eq_result),
targets: (block, fail),
self.cfg.terminate(eq_block, source_info, TerminatorKind::SwitchInt {
discr: Operand::Consume(eq_result),
switch_ty: self.hir.bool_ty(),
values: vec![ConstVal::Bool(true)],
targets: vec![block, fail],
});
vec![block, fail]
@ -362,9 +365,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
// branch based on result
let target_blocks: Vec<_> = vec![self.cfg.start_new_block(),
self.cfg.start_new_block()];
self.cfg.terminate(block, source_info, TerminatorKind::If {
cond: Operand::Consume(result),
targets: (target_blocks[0], target_blocks[1])
self.cfg.terminate(block, source_info, TerminatorKind::SwitchInt {
discr: Operand::Consume(result),
switch_ty: self.hir.bool_ty(),
values: vec![ConstVal::Bool(true)],
targets: target_blocks.clone(),
});
target_blocks
@ -389,9 +394,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
// branch based on result
let target_block = self.cfg.start_new_block();
self.cfg.terminate(block, source_info, TerminatorKind::If {
cond: Operand::Consume(result),
targets: (target_block, fail_block)
self.cfg.terminate(block, source_info, TerminatorKind::SwitchInt {
discr: Operand::Consume(result),
switch_ty: self.hir.bool_ty(),
values: vec![ConstVal::Bool(true)],
targets: vec![target_block, fail_block]
});
target_block

View File

@ -134,7 +134,8 @@ pub enum ExprKind<'tcx> {
op: LogicalOp,
lhs: ExprRef<'tcx>,
rhs: ExprRef<'tcx>,
},
}, // NOT overloaded!
// LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands.
Unary {
op: UnOp,
arg: ExprRef<'tcx>,

View File

@ -28,7 +28,6 @@ impl<'tcx> MutVisitor<'tcx> for NoLandingPads {
TerminatorKind::Resume |
TerminatorKind::Return |
TerminatorKind::Unreachable |
TerminatorKind::If { .. } |
TerminatorKind::Switch { .. } |
TerminatorKind::SwitchInt { .. } => {
/* nothing to do */

View File

@ -394,7 +394,6 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
return Qualif::empty();
}
TerminatorKind::If {..} |
TerminatorKind::Switch {..} |
TerminatorKind::SwitchInt {..} |
TerminatorKind::DropAndReplace { .. } |

View File

@ -209,7 +209,6 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {
// turn a branch with all successors identical to a goto
fn simplify_branch(&mut self, terminator: &mut Terminator<'tcx>) -> bool {
match terminator.kind {
TerminatorKind::If { .. } |
TerminatorKind::Switch { .. } |
TerminatorKind::SwitchInt { .. } => {},
_ => return false

View File

@ -30,17 +30,17 @@ impl<'l, 'tcx> MirPass<'tcx> for SimplifyBranches<'l> {
for block in mir.basic_blocks_mut() {
let terminator = block.terminator_mut();
terminator.kind = match terminator.kind {
TerminatorKind::If { ref targets, cond: Operand::Constant(Constant {
literal: Literal::Value {
value: ConstVal::Bool(cond)
}, ..
}) } => {
if cond {
TerminatorKind::Goto { target: targets.0 }
} else {
TerminatorKind::Goto { target: targets.1 }
}
}
// TerminatorKind::If { ref targets, cond: Operand::Constant(Constant {
// literal: Literal::Value {
// value: ConstVal::Bool(cond)
// }, ..
// }) } => {
// if cond {
// TerminatorKind::Goto { target: targets.0 }
// } else {
// TerminatorKind::Goto { target: targets.1 }
// }
// }
TerminatorKind::Assert { target, cond: Operand::Constant(Constant {
literal: Literal::Value {

View File

@ -423,18 +423,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
lv_ty, rv_ty, terr);
}
}
TerminatorKind::If { ref cond, .. } => {
let cond_ty = cond.ty(mir, tcx);
match cond_ty.sty {
ty::TyBool => {}
_ => {
span_mirbug!(self, term, "bad If ({:?}, not bool", cond_ty);
}
}
}
TerminatorKind::SwitchInt { ref discr, switch_ty, .. } => {
let discr_ty = discr.ty(mir, tcx).to_ty(tcx);
let discr_ty = discr.ty(mir, tcx);
if let Err(terr) = self.sub_types(discr_ty, switch_ty) {
span_mirbug!(self, term, "bad SwitchInt ({:?} on {:?}): {:?}",
switch_ty, discr_ty, terr);
@ -603,10 +593,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
match block.terminator().kind {
TerminatorKind::Goto { target } =>
self.assert_iscleanup(mir, block, target, is_cleanup),
TerminatorKind::If { targets: (on_true, on_false), .. } => {
self.assert_iscleanup(mir, block, on_true, is_cleanup);
self.assert_iscleanup(mir, block, on_false, is_cleanup);
}
TerminatorKind::Switch { ref targets, .. } |
TerminatorKind::SwitchInt { ref targets, .. } => {
for target in targets {

View File

@ -148,7 +148,6 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
self.record("TerminatorKind", kind);
self.record(match *kind {
TerminatorKind::Goto { .. } => "TerminatorKind::Goto",
TerminatorKind::If { .. } => "TerminatorKind::If",
TerminatorKind::Switch { .. } => "TerminatorKind::Switch",
TerminatorKind::SwitchInt { .. } => "TerminatorKind::SwitchInt",
TerminatorKind::Resume => "TerminatorKind::Resume",

View File

@ -204,7 +204,6 @@ pub fn cleanup_kinds<'a, 'tcx>(mir: &mir::Mir<'tcx>) -> IndexVec<mir::BasicBlock
TerminatorKind::Resume |
TerminatorKind::Return |
TerminatorKind::Unreachable |
TerminatorKind::If { .. } |
TerminatorKind::Switch { .. } |
TerminatorKind::SwitchInt { .. } => {
/* nothing to do */

View File

@ -136,14 +136,6 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
funclet_br(self, bcx, target);
}
mir::TerminatorKind::If { ref cond, targets: (true_bb, false_bb) } => {
let cond = self.trans_operand(&bcx, cond);
let lltrue = llblock(self, true_bb);
let llfalse = llblock(self, false_bb);
bcx.cond_br(cond.immediate(), lltrue, llfalse);
}
mir::TerminatorKind::Switch { ref discr, ref adt_def, ref targets } => {
let discr_lvalue = self.trans_lvalue(&bcx, discr);
let ty = discr_lvalue.ty.to_ty(bcx.tcx());
@ -180,10 +172,9 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
}
mir::TerminatorKind::SwitchInt { ref discr, switch_ty, ref values, ref targets } => {
// TODO: cond_br if only 1 value
let (otherwise, targets) = targets.split_last().unwrap();
let lv = self.trans_lvalue(&bcx, discr);
let discr = bcx.load(lv.llval, lv.alignment.to_align());
let discr = base::to_immediate(&bcx, discr, switch_ty);
let discr = self.trans_operand(&bcx, discr).immediate();
let switch = bcx.switch(discr, llblock(self, *otherwise), values.len());
for (value, target) in values.iter().zip(targets) {
let val = Const::from_constval(bcx.ccx, value.clone(), switch_ty);

View File

@ -9,6 +9,7 @@
// except according to those terms.
// aux-build:plugin.rs
// ignore-stage1
#![feature(proc_macro)]