提交 98d1db7f 编写于 作者: S Simonas Kazlauskas

If is now always a SwitchInt in MIR

上级 779c6b6c
......@@ -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 @@ pub fn successors(&self) -> Cow<[BasicBlock]> {
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 @@ pub fn successors_mut(&mut self) -> Vec<&mut BasicBlock> {
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 @@ pub fn fmt_head<W: Write>(&self, fmt: &mut W) -> fmt::Result {
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 @@ pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
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::{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 @@ fn super_terminator_kind(&mut self,
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 @@ fn super_terminator_kind(&mut self,
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 @@ fn propagate_bits_into_graph_successors_of(
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 @@ fn drop_flag_test_block_with_succ<'a>(&mut self,
(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 @@ fn gather_terminator(&mut self, loc: Location, term: &Terminator<'tcx>) {
self.gather_move(loc, &Lvalue::Local(RETURN_POINTER));
}
TerminatorKind::If { .. } |
TerminatorKind::Assert { .. } |
TerminatorKind::SwitchInt { .. } |
TerminatorKind::Switch { .. } => {
......
......@@ -15,6 +15,7 @@
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 @@ pub fn into_expr(&mut self,
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 @@ pub fn into_expr(&mut self,
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 @@ pub fn into_expr(&mut self,
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 @@ fn bind_and_guard_matched_candidate<'pat>(&mut self,
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 @@ pub fn perform_test(&mut self,
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 @@ pub fn perform_test(&mut self,
(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 @@ pub fn perform_test(&mut self,
// 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 @@ pub fn perform_test(&mut self,
// 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 @@ fn compare(&mut self,
// 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 @@ fn visit_terminator(&mut self,
TerminatorKind::Resume |
TerminatorKind::Return |
TerminatorKind::Unreachable |
TerminatorKind::If { .. } |
TerminatorKind::Switch { .. } |
TerminatorKind::SwitchInt { .. } => {
/* nothing to do */
......
......@@ -394,7 +394,6 @@ fn qualify_const(&mut self) -> Qualif {
return Qualif::empty();
}
TerminatorKind::If {..} |
TerminatorKind::Switch {..} |
TerminatorKind::SwitchInt {..} |
TerminatorKind::DropAndReplace { .. } |
......
......@@ -209,7 +209,6 @@ fn merge_successor(&mut self,
// 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 @@ fn run_pass<'a>(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, _src: MirSource, mir: &
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 @@ fn check_terminator(&mut self,
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 @@ fn check_iscleanup(&mut self, mir: &Mir<'tcx>, block: &BasicBlockData<'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 @@ fn visit_terminator_kind(&mut self,
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 @@ fn discover_masters<'tcx>(result: &mut IndexVec<mir::BasicBlock, CleanupKind>,
TerminatorKind::Resume |
TerminatorKind::Return |
TerminatorKind::Unreachable |
TerminatorKind::If { .. } |
TerminatorKind::Switch { .. } |
TerminatorKind::SwitchInt { .. } => {
/* nothing to do */
......
......@@ -136,14 +136,6 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock,
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 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock,
}
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)]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册