Skip to content

Commit

Permalink
Add TerminatorKind::if_ convenience constructor
Browse files Browse the repository at this point in the history
Constructs a TerminatorKind::SwitchInt for an equivalent conditional true-false branch.
  • Loading branch information
nagisa committed Feb 10, 2017
1 parent a8b7b62 commit eb727a8
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 62 deletions.
14 changes: 11 additions & 3 deletions src/librustc/mir/mod.rs
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
9 changes: 2 additions & 7 deletions src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
Expand Up @@ -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)
}
}
}
Expand Down
38 changes: 11 additions & 27 deletions src/librustc_mir/build/expr/into.rs
Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down
8 changes: 2 additions & 6 deletions src/librustc_mir/build/matches/mod.rs
Expand Up @@ -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);
Expand Down
31 changes: 12 additions & 19 deletions src/librustc_mir/build/matches/test.rs
Expand Up @@ -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());
Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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]
}
}
Expand All @@ -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
}

Expand Down

0 comments on commit eb727a8

Please sign in to comment.