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
5 changed files with 38 additions and 62 deletions
|
@ -446,9 +446,6 @@ pub struct Terminator<'tcx> {
|
||||||
pub kind: TerminatorKind<'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)]
|
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
||||||
pub enum TerminatorKind<'tcx> {
|
pub enum TerminatorKind<'tcx> {
|
||||||
/// block should have one successor in the graph; we jump there
|
/// block should have one successor in the graph; we jump there
|
||||||
|
@ -543,6 +540,17 @@ impl<'tcx> Terminator<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TerminatorKind<'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]> {
|
pub fn successors(&self) -> Cow<[BasicBlock]> {
|
||||||
use self::TerminatorKind::*;
|
use self::TerminatorKind::*;
|
||||||
match *self {
|
match *self {
|
||||||
|
|
|
@ -842,13 +842,8 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
||||||
(true, false) => on_set,
|
(true, false) => on_set,
|
||||||
(true, true) => {
|
(true, true) => {
|
||||||
let flag = self.drop_flag(c.path).unwrap();
|
let flag = self.drop_flag(c.path).unwrap();
|
||||||
let boolty = self.tcx.types.bool;
|
let term = TerminatorKind::if_(self.tcx, Operand::Consume(flag), on_set, on_unset);
|
||||||
self.new_block(c, is_cleanup, TerminatorKind::SwitchInt {
|
self.new_block(c, is_cleanup, term)
|
||||||
discr: Operand::Consume(flag),
|
|
||||||
switch_ty: boolty,
|
|
||||||
values: BOOL_SWITCH_FALSE.clone(),
|
|
||||||
targets: vec![on_unset, on_set],
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,12 +69,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
let mut then_block = this.cfg.start_new_block();
|
let mut then_block = this.cfg.start_new_block();
|
||||||
let mut else_block = this.cfg.start_new_block();
|
let mut else_block = this.cfg.start_new_block();
|
||||||
this.cfg.terminate(block, source_info, TerminatorKind::SwitchInt {
|
let term = TerminatorKind::if_(this.hir.tcx(), operand, then_block, else_block);
|
||||||
discr: operand,
|
this.cfg.terminate(block, source_info, term);
|
||||||
switch_ty: this.hir.bool_ty(),
|
|
||||||
values: BOOL_SWITCH_FALSE.clone(),
|
|
||||||
targets: vec![else_block, then_block],
|
|
||||||
});
|
|
||||||
|
|
||||||
unpack!(then_block = this.into(destination, then_block, then_expr));
|
unpack!(then_block = this.into(destination, then_block, then_expr));
|
||||||
else_block = if let Some(else_expr) = else_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 lhs = unpack!(block = this.as_operand(block, lhs));
|
||||||
let blocks = match op {
|
let blocks = match op {
|
||||||
LogicalOp::And => vec![false_block, else_block],
|
LogicalOp::And => (else_block, false_block),
|
||||||
LogicalOp::Or => vec![else_block, true_block],
|
LogicalOp::Or => (true_block, else_block),
|
||||||
};
|
};
|
||||||
this.cfg.terminate(block, source_info, TerminatorKind::SwitchInt {
|
let term = TerminatorKind::if_(this.hir.tcx(), lhs, blocks.0, blocks.1);
|
||||||
discr: lhs,
|
this.cfg.terminate(block, source_info, term);
|
||||||
switch_ty: this.hir.bool_ty(),
|
|
||||||
values: BOOL_SWITCH_FALSE.clone(),
|
|
||||||
targets: blocks,
|
|
||||||
});
|
|
||||||
|
|
||||||
let rhs = unpack!(else_block = this.as_operand(else_block, rhs));
|
let rhs = unpack!(else_block = this.as_operand(else_block, rhs));
|
||||||
this.cfg.terminate(else_block, source_info, TerminatorKind::SwitchInt {
|
let term = TerminatorKind::if_(this.hir.tcx(), rhs, true_block, false_block);
|
||||||
discr: rhs,
|
this.cfg.terminate(else_block, source_info, term);
|
||||||
switch_ty: this.hir.bool_ty(),
|
|
||||||
values: BOOL_SWITCH_FALSE.clone(),
|
|
||||||
targets: vec![false_block, true_block],
|
|
||||||
});
|
|
||||||
|
|
||||||
this.cfg.push_assign_constant(
|
this.cfg.push_assign_constant(
|
||||||
true_block, source_info, destination,
|
true_block, source_info, destination,
|
||||||
|
@ -187,13 +175,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
let cond = unpack!(
|
let cond = unpack!(
|
||||||
loop_block_end = this.as_operand(loop_block, cond_expr));
|
loop_block_end = this.as_operand(loop_block, cond_expr));
|
||||||
body_block = this.cfg.start_new_block();
|
body_block = this.cfg.start_new_block();
|
||||||
this.cfg.terminate(loop_block_end, source_info,
|
let term = TerminatorKind::if_(this.hir.tcx(), cond,
|
||||||
TerminatorKind::SwitchInt {
|
body_block, exit_block);
|
||||||
discr: cond,
|
this.cfg.terminate(loop_block_end, source_info, term);
|
||||||
switch_ty: this.hir.bool_ty(),
|
|
||||||
values: BOOL_SWITCH_FALSE.clone(),
|
|
||||||
targets: vec![exit_block, body_block],
|
|
||||||
});
|
|
||||||
|
|
||||||
// if the test is false, there's no `break` to assign `destination`, so
|
// 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
|
// 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 source_info = self.source_info(guard.span);
|
||||||
let cond = unpack!(block = self.as_operand(block, guard));
|
let cond = unpack!(block = self.as_operand(block, guard));
|
||||||
let otherwise = self.cfg.start_new_block();
|
let otherwise = self.cfg.start_new_block();
|
||||||
self.cfg.terminate(block, source_info, TerminatorKind::SwitchInt {
|
self.cfg.terminate(block, source_info,
|
||||||
discr: cond,
|
TerminatorKind::if_(self.hir.tcx(), cond, arm_block, otherwise));
|
||||||
switch_ty: self.hir.bool_ty(),
|
|
||||||
values: BOOL_SWITCH_FALSE.clone(),
|
|
||||||
targets: vec![otherwise, arm_block],
|
|
||||||
});
|
|
||||||
Some(otherwise)
|
Some(otherwise)
|
||||||
} else {
|
} else {
|
||||||
let source_info = self.source_info(candidate.span);
|
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: _ } => {
|
TestKind::SwitchInt { switch_ty, ref options, indices: _ } => {
|
||||||
let (values, targets, ret) = if switch_ty.sty == ty::TyBool {
|
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);
|
assert!(options.len() > 0 && options.len() <= 2);
|
||||||
let (true_bb, false_bb) = (self.cfg.start_new_block(),
|
let (true_bb, false_bb) = (self.cfg.start_new_block(),
|
||||||
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],
|
&ConstVal::Bool(false) => vec![false_bb, true_bb],
|
||||||
v => span_bug!(test.span, "expected boolean value but got {:?}", v)
|
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 {
|
} else {
|
||||||
// The switch may be inexhaustive so we
|
// The switch may be inexhaustive so we
|
||||||
// add a catch all block
|
// add a catch all block
|
||||||
|
@ -323,12 +324,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
// check the result
|
// check the result
|
||||||
let block = self.cfg.start_new_block();
|
let block = self.cfg.start_new_block();
|
||||||
self.cfg.terminate(eq_block, source_info, TerminatorKind::SwitchInt {
|
self.cfg.terminate(eq_block, source_info,
|
||||||
discr: Operand::Consume(eq_result),
|
TerminatorKind::if_(self.hir.tcx(),
|
||||||
switch_ty: self.hir.bool_ty(),
|
Operand::Consume(eq_result),
|
||||||
values: BOOL_SWITCH_FALSE.clone(),
|
block, fail));
|
||||||
targets: vec![fail, block],
|
|
||||||
});
|
|
||||||
vec![block, fail]
|
vec![block, fail]
|
||||||
} else {
|
} else {
|
||||||
let block = self.compare(block, fail, test.span, BinOp::Eq, expect, val);
|
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
|
// branch based on result
|
||||||
let (false_bb, true_bb) = (self.cfg.start_new_block(),
|
let (false_bb, true_bb) = (self.cfg.start_new_block(),
|
||||||
self.cfg.start_new_block());
|
self.cfg.start_new_block());
|
||||||
self.cfg.terminate(block, source_info, TerminatorKind::SwitchInt {
|
self.cfg.terminate(block, source_info,
|
||||||
discr: Operand::Consume(result),
|
TerminatorKind::if_(self.hir.tcx(), Operand::Consume(result),
|
||||||
switch_ty: self.hir.bool_ty(),
|
true_bb, false_bb));
|
||||||
values: BOOL_SWITCH_FALSE.clone(),
|
|
||||||
targets: vec![false_bb, true_bb],
|
|
||||||
});
|
|
||||||
vec![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
|
// branch based on result
|
||||||
let target_block = self.cfg.start_new_block();
|
let target_block = self.cfg.start_new_block();
|
||||||
self.cfg.terminate(block, source_info, TerminatorKind::SwitchInt {
|
self.cfg.terminate(block, source_info,
|
||||||
discr: Operand::Consume(result),
|
TerminatorKind::if_(self.hir.tcx(), Operand::Consume(result),
|
||||||
switch_ty: self.hir.bool_ty(),
|
target_block, fail_block));
|
||||||
values: BOOL_SWITCH_FALSE.clone(),
|
|
||||||
targets: vec![fail_block, target_block]
|
|
||||||
});
|
|
||||||
target_block
|
target_block
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue