Add TerminatorKind::if_ convenience constructor
Constructs a TerminatorKind::SwitchInt for an equivalent conditional true-false branch.
This commit is contained in:
parent
a8b7b62185
commit
eb727a8faa
@ -446,9 +446,6 @@ pub struct Terminator<'tcx> {
|
||||
pub kind: TerminatorKind<'tcx>
|
||||
}
|
||||
|
||||
/// For use in SwitchInt, for switching on bools.
|
||||
pub static BOOL_SWITCH_FALSE: Cow<'static, [ConstInt]> = Cow::Borrowed(&[ConstInt::Infer(0)]);
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
||||
pub enum TerminatorKind<'tcx> {
|
||||
/// block should have one successor in the graph; we jump there
|
||||
@ -543,6 +540,17 @@ impl<'tcx> Terminator<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> TerminatorKind<'tcx> {
|
||||
pub fn if_<'a, 'gcx>(tcx: ty::TyCtxt<'a, 'gcx, 'tcx>, cond: Operand<'tcx>,
|
||||
t: BasicBlock, f: BasicBlock) -> TerminatorKind<'tcx> {
|
||||
static BOOL_SWITCH_FALSE: &'static [ConstInt] = &[ConstInt::Infer(0)];
|
||||
TerminatorKind::SwitchInt {
|
||||
discr: cond,
|
||||
switch_ty: tcx.types.bool,
|
||||
values: From::from(BOOL_SWITCH_FALSE),
|
||||
targets: vec![f, t],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn successors(&self) -> Cow<[BasicBlock]> {
|
||||
use self::TerminatorKind::*;
|
||||
match *self {
|
||||
|
@ -842,13 +842,8 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
||||
(true, false) => on_set,
|
||||
(true, true) => {
|
||||
let flag = self.drop_flag(c.path).unwrap();
|
||||
let boolty = self.tcx.types.bool;
|
||||
self.new_block(c, is_cleanup, TerminatorKind::SwitchInt {
|
||||
discr: Operand::Consume(flag),
|
||||
switch_ty: boolty,
|
||||
values: BOOL_SWITCH_FALSE.clone(),
|
||||
targets: vec![on_unset, on_set],
|
||||
})
|
||||
let term = TerminatorKind::if_(self.tcx, Operand::Consume(flag), on_set, on_unset);
|
||||
self.new_block(c, is_cleanup, term)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,12 +69,8 @@ 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::SwitchInt {
|
||||
discr: operand,
|
||||
switch_ty: this.hir.bool_ty(),
|
||||
values: BOOL_SWITCH_FALSE.clone(),
|
||||
targets: vec![else_block, then_block],
|
||||
});
|
||||
let term = TerminatorKind::if_(this.hir.tcx(), operand, then_block, else_block);
|
||||
this.cfg.terminate(block, source_info, term);
|
||||
|
||||
unpack!(then_block = this.into(destination, then_block, then_expr));
|
||||
else_block = if let Some(else_expr) = else_expr {
|
||||
@ -113,23 +109,15 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
|
||||
let lhs = unpack!(block = this.as_operand(block, lhs));
|
||||
let blocks = match op {
|
||||
LogicalOp::And => vec![false_block, else_block],
|
||||
LogicalOp::Or => vec![else_block, true_block],
|
||||
LogicalOp::And => (else_block, false_block),
|
||||
LogicalOp::Or => (true_block, else_block),
|
||||
};
|
||||
this.cfg.terminate(block, source_info, TerminatorKind::SwitchInt {
|
||||
discr: lhs,
|
||||
switch_ty: this.hir.bool_ty(),
|
||||
values: BOOL_SWITCH_FALSE.clone(),
|
||||
targets: blocks,
|
||||
});
|
||||
let term = TerminatorKind::if_(this.hir.tcx(), lhs, blocks.0, blocks.1);
|
||||
this.cfg.terminate(block, source_info, term);
|
||||
|
||||
let rhs = unpack!(else_block = this.as_operand(else_block, rhs));
|
||||
this.cfg.terminate(else_block, source_info, TerminatorKind::SwitchInt {
|
||||
discr: rhs,
|
||||
switch_ty: this.hir.bool_ty(),
|
||||
values: BOOL_SWITCH_FALSE.clone(),
|
||||
targets: vec![false_block, true_block],
|
||||
});
|
||||
let term = TerminatorKind::if_(this.hir.tcx(), rhs, true_block, false_block);
|
||||
this.cfg.terminate(else_block, source_info, term);
|
||||
|
||||
this.cfg.push_assign_constant(
|
||||
true_block, source_info, destination,
|
||||
@ -187,13 +175,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
let cond = unpack!(
|
||||
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::SwitchInt {
|
||||
discr: cond,
|
||||
switch_ty: this.hir.bool_ty(),
|
||||
values: BOOL_SWITCH_FALSE.clone(),
|
||||
targets: vec![exit_block, body_block],
|
||||
});
|
||||
let term = TerminatorKind::if_(this.hir.tcx(), cond,
|
||||
body_block, exit_block);
|
||||
this.cfg.terminate(loop_block_end, source_info, term);
|
||||
|
||||
// if the test is false, there's no `break` to assign `destination`, so
|
||||
// we have to do it; this overwrites any `break`-assigned value but it's
|
||||
|
@ -672,12 +672,8 @@ 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::SwitchInt {
|
||||
discr: cond,
|
||||
switch_ty: self.hir.bool_ty(),
|
||||
values: BOOL_SWITCH_FALSE.clone(),
|
||||
targets: vec![otherwise, arm_block],
|
||||
});
|
||||
self.cfg.terminate(block, source_info,
|
||||
TerminatorKind::if_(self.hir.tcx(), cond, arm_block, otherwise));
|
||||
Some(otherwise)
|
||||
} else {
|
||||
let source_info = self.source_info(candidate.span);
|
||||
|
@ -228,6 +228,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
|
||||
TestKind::SwitchInt { switch_ty, ref options, indices: _ } => {
|
||||
let (values, targets, ret) = if switch_ty.sty == ty::TyBool {
|
||||
static BOOL_SWITCH_FALSE: &'static [ConstInt] = &[ConstInt::Infer(0)];
|
||||
assert!(options.len() > 0 && options.len() <= 2);
|
||||
let (true_bb, false_bb) = (self.cfg.start_new_block(),
|
||||
self.cfg.start_new_block());
|
||||
@ -236,7 +237,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
&ConstVal::Bool(false) => vec![false_bb, true_bb],
|
||||
v => span_bug!(test.span, "expected boolean value but got {:?}", v)
|
||||
};
|
||||
(BOOL_SWITCH_FALSE.clone(), vec![false_bb, true_bb], ret)
|
||||
(From::from(BOOL_SWITCH_FALSE), vec![false_bb, true_bb], ret)
|
||||
} else {
|
||||
// The switch may be inexhaustive so we
|
||||
// add a catch all block
|
||||
@ -323,12 +324,10 @@ 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::SwitchInt {
|
||||
discr: Operand::Consume(eq_result),
|
||||
switch_ty: self.hir.bool_ty(),
|
||||
values: BOOL_SWITCH_FALSE.clone(),
|
||||
targets: vec![fail, block],
|
||||
});
|
||||
self.cfg.terminate(eq_block, source_info,
|
||||
TerminatorKind::if_(self.hir.tcx(),
|
||||
Operand::Consume(eq_result),
|
||||
block, fail));
|
||||
vec![block, fail]
|
||||
} else {
|
||||
let block = self.compare(block, fail, test.span, BinOp::Eq, expect, val);
|
||||
@ -372,12 +371,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
// branch based on result
|
||||
let (false_bb, true_bb) = (self.cfg.start_new_block(),
|
||||
self.cfg.start_new_block());
|
||||
self.cfg.terminate(block, source_info, TerminatorKind::SwitchInt {
|
||||
discr: Operand::Consume(result),
|
||||
switch_ty: self.hir.bool_ty(),
|
||||
values: BOOL_SWITCH_FALSE.clone(),
|
||||
targets: vec![false_bb, true_bb],
|
||||
});
|
||||
self.cfg.terminate(block, source_info,
|
||||
TerminatorKind::if_(self.hir.tcx(), Operand::Consume(result),
|
||||
true_bb, false_bb));
|
||||
vec![true_bb, false_bb]
|
||||
}
|
||||
}
|
||||
@ -400,12 +396,9 @@ 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::SwitchInt {
|
||||
discr: Operand::Consume(result),
|
||||
switch_ty: self.hir.bool_ty(),
|
||||
values: BOOL_SWITCH_FALSE.clone(),
|
||||
targets: vec![fail_block, target_block]
|
||||
});
|
||||
self.cfg.terminate(block, source_info,
|
||||
TerminatorKind::if_(self.hir.tcx(), Operand::Consume(result),
|
||||
target_block, fail_block));
|
||||
target_block
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user