If is now always a SwitchInt in MIR
This commit is contained in:
parent
779c6b6cb8
commit
98d1db7fe3
@ -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()
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -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 { .. } => {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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>,
|
||||
|
@ -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 */
|
||||
|
@ -394,7 +394,6 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
|
||||
return Qualif::empty();
|
||||
}
|
||||
|
||||
TerminatorKind::If {..} |
|
||||
TerminatorKind::Switch {..} |
|
||||
TerminatorKind::SwitchInt {..} |
|
||||
TerminatorKind::DropAndReplace { .. } |
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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",
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -9,6 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
// aux-build:plugin.rs
|
||||
// ignore-stage1
|
||||
|
||||
#![feature(proc_macro)]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user