From eb727a8faa08557d894506e2f95f2bfdc4996490 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Fri, 3 Feb 2017 03:36:32 +0200 Subject: [PATCH] Add TerminatorKind::if_ convenience constructor Constructs a TerminatorKind::SwitchInt for an equivalent conditional true-false branch. --- src/librustc/mir/mod.rs | 14 +++++-- .../borrowck/mir/elaborate_drops.rs | 9 +---- src/librustc_mir/build/expr/into.rs | 38 ++++++------------- src/librustc_mir/build/matches/mod.rs | 8 +--- src/librustc_mir/build/matches/test.rs | 31 ++++++--------- 5 files changed, 38 insertions(+), 62 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 98693d469ed..d8212807eb2 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -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 { diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs index 44b85c31d86..d7ffe538c24 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs @@ -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) } } } diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index f61b4a66077..35841c2cbdf 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -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 diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 812900b6bec..a28bc5d6ce3 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -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); diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index f268eda4c15..7e47e173c51 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -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 }