Remove the Panic block terminator

This commit is contained in:
Simonas Kazlauskas 2015-12-18 23:19:29 +02:00
parent ecf4d0e3ad
commit 5b34690842
8 changed files with 107 additions and 32 deletions

View File

@ -204,12 +204,6 @@ pub enum Terminator<'tcx> {
target: BasicBlock,
},
/// block should initiate unwinding; should be one successor
/// that does cleanup and branches to DIVERGE_BLOCK
Panic {
target: BasicBlock,
},
/// jump to branch 0 if this lvalue evaluates to true
If {
cond: Operand<'tcx>,
@ -320,7 +314,6 @@ impl<'tcx> Terminator<'tcx> {
use self::Terminator::*;
match *self {
Goto { target: ref b } => slice::ref_slice(b),
Panic { target: ref b } => slice::ref_slice(b),
If { targets: ref b, .. } => b.as_slice(),
Switch { targets: ref b, .. } => b,
SwitchInt { targets: ref b, .. } => b,
@ -340,7 +333,6 @@ impl<'tcx> Terminator<'tcx> {
use self::Terminator::*;
match *self {
Goto { target: ref mut b } => slice::mut_ref_slice(b),
Panic { target: ref mut b } => slice::mut_ref_slice(b),
If { targets: ref mut b, .. } => b.as_mut_slice(),
Switch { targets: ref mut b, .. } => b,
SwitchInt { targets: ref mut b, .. } => b,
@ -401,7 +393,6 @@ impl<'tcx> Terminator<'tcx> {
use self::Terminator::*;
match *self {
Goto { .. } => write!(fmt, "goto"),
Panic { .. } => write!(fmt, "panic"),
If { cond: ref lv, .. } => write!(fmt, "if({:?})", lv),
Switch { discr: ref lv, .. } => write!(fmt, "switch({:?})", lv),
SwitchInt { discr: ref lv, .. } => write!(fmt, "switchInt({:?})", lv),
@ -424,7 +415,7 @@ impl<'tcx> Terminator<'tcx> {
use self::Terminator::*;
match *self {
Diverge | Return | Resume => vec![],
Goto { .. } | Panic { .. } => vec!["".into_cow()],
Goto { .. } => vec!["".into_cow()],
If { .. } => vec!["true".into_cow(), "false".into_cow()],
Call { .. } => vec!["return".into_cow(), "unwind".into_cow()],
DivergingCall { .. } => vec!["unwind".into_cow()],

View File

@ -107,8 +107,7 @@ pub trait Visitor<'tcx> {
fn super_terminator(&mut self, block: BasicBlock, terminator: &Terminator<'tcx>) {
match *terminator {
Terminator::Goto { target } |
Terminator::Panic { target } => {
Terminator::Goto { target } => {
self.visit_branch(block, target);
}
@ -405,8 +404,7 @@ pub trait MutVisitor<'tcx> {
block: BasicBlock,
terminator: &mut Terminator<'tcx>) {
match *terminator {
Terminator::Goto { target } |
Terminator::Panic { target } => {
Terminator::Goto { target } => {
self.visit_branch(block, target);
}

View File

@ -63,7 +63,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
this.cfg.push_assign(block, expr_span, // lt = idx < len
&lt, Rvalue::BinaryOp(BinOp::Lt,
idx.clone(),
Operand::Consume(len)));
Operand::Consume(len.clone())));
let (success, failure) = (this.cfg.start_new_block(), this.cfg.start_new_block());
this.cfg.terminate(block,
@ -71,7 +71,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
cond: Operand::Consume(lt),
targets: (success, failure),
});
this.panic(failure);
this.panic_bound_check(failure, idx.clone(), Operand::Consume(len), expr_span);
success.and(slice.index(idx))
}
ExprKind::SelfRef => {

View File

@ -89,7 +89,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
// not entirely precise
if !otherwise.is_empty() {
let join_block = self.join_otherwise_blocks(otherwise);
self.panic(join_block);
self.panic(join_block, "something about matches algorithm not being precise", span);
}
// all the arm blocks will rejoin here

View File

@ -88,9 +88,12 @@ should go to.
use build::{BlockAnd, BlockAndExtension, Builder};
use rustc::middle::region::CodeExtent;
use rustc::middle::ty::Ty;
use rustc::middle::lang_items;
use rustc::middle::subst::Substs;
use rustc::middle::ty::{Ty, Region};
use rustc::mir::repr::*;
use syntax::codemap::Span;
use syntax::codemap::{Span, DUMMY_SP};
use syntax::parse::token::intern_and_get_ident;
pub struct Scope<'tcx> {
extent: CodeExtent,
@ -261,13 +264,6 @@ impl<'a,'tcx> Builder<'a,'tcx> {
self.scopes.iter().rev().flat_map(|b| b.cached_block).next()
}
/// Create diverge cleanup and branch to it from `block`.
pub fn panic(&mut self, block: BasicBlock) {
// FIXME: panic terminator should also have conditional cleanup?
let cleanup = self.diverge_cleanup().unwrap_or(DIVERGE_BLOCK);
self.cfg.terminate(block, Terminator::Panic { target: cleanup });
}
/// Indicates that `lvalue` should be dropped on exit from
/// `extent`.
pub fn schedule_drop(&mut self,
@ -299,4 +295,94 @@ impl<'a,'tcx> Builder<'a,'tcx> {
pub fn extent_of_outermost_scope(&self) -> CodeExtent {
self.scopes.first().map(|scope| scope.extent).unwrap()
}
pub fn panic_bound_check(&mut self,
block: BasicBlock,
index: Operand<'tcx>,
len: Operand<'tcx>,
span: Span) {
let cleanup = self.diverge_cleanup();
let func = self.lang_function(lang_items::PanicBoundsCheckFnLangItem);
let str_ty = self.hir.tcx().mk_static_str();
let tup_ty = self.hir.tcx().mk_tup(vec![str_ty, self.hir.tcx().types.u32]);
// FIXME: ReStatic might be wrong here?
let ref_region = self.hir.tcx().mk_region(Region::ReStatic);
let ref_ty = self.hir.tcx().mk_imm_ref(ref_region, tup_ty.clone());
let (file_arg, line_arg) = self.span_to_fileline_args(span);
let (tuple, tuple_ref) = (self.temp(tup_ty), self.temp(ref_ty));
self.cfg.push_assign(block, DUMMY_SP, &tuple, // tuple = (message_arg, file_arg, line_arg);
Rvalue::Aggregate(AggregateKind::Tuple, vec![file_arg, line_arg]));
// FIXME: ReStatic might be wrong here?
self.cfg.push_assign(block, DUMMY_SP, &tuple_ref, // tuple_ref = &tuple;
Rvalue::Ref(*ref_region, BorrowKind::Unique, tuple));
self.cfg.terminate(block, Terminator::DivergingCall {
func: func,
args: vec![Operand::Consume(tuple_ref), index, len],
cleanup: cleanup,
});
}
/// Create diverge cleanup and branch to it from `block`.
pub fn panic(&mut self, block: BasicBlock, msg: &'static str, span: Span) {
let cleanup = self.diverge_cleanup();
let func = self.lang_function(lang_items::PanicFnLangItem);
let str_ty = self.hir.tcx().mk_static_str();
let tup_ty = self.hir.tcx().mk_tup(vec![str_ty, str_ty, self.hir.tcx().types.u32]);
// FIXME: ReStatic might be wrong here?
let ref_region = self.hir.tcx().mk_region(Region::ReStatic);
let ref_ty = self.hir.tcx().mk_imm_ref(ref_region, tup_ty.clone());
let message_arg = Operand::Constant(Constant {
span: DUMMY_SP,
ty: str_ty,
literal: self.hir.str_literal(intern_and_get_ident(msg))
});
let (file_arg, line_arg) = self.span_to_fileline_args(span);
let tuple = self.temp(tup_ty);
let tuple_ref = self.temp(ref_ty);
self.cfg.push_assign(block, DUMMY_SP, &tuple, // tuple = (message_arg, file_arg, line_arg);
Rvalue::Aggregate(AggregateKind::Tuple,
vec![message_arg, file_arg, line_arg])
);
// FIXME: ReStatic might be wrong here?
self.cfg.push_assign(block, DUMMY_SP, &tuple_ref, // tuple_ref = &tuple;
Rvalue::Ref(*ref_region, BorrowKind::Unique, tuple));
self.cfg.terminate(block, Terminator::DivergingCall {
func: func,
args: vec![Operand::Consume(tuple_ref)],
cleanup: cleanup,
});
}
fn lang_function(&mut self, lang_item: lang_items::LangItem) -> Operand<'tcx> {
let funcdid = match self.hir.tcx().lang_items.require(lang_item) {
Ok(d) => d,
Err(m) => {
self.hir.tcx().sess.fatal(&*m)
}
};
Operand::Constant(Constant {
span: DUMMY_SP,
ty: self.hir.tcx().lookup_item_type(funcdid).ty,
literal: Literal::Item {
def_id: funcdid,
kind: ItemKind::Function,
substs: self.hir.tcx().mk_substs(Substs::empty())
}
})
}
fn span_to_fileline_args(&mut self, span: Span) -> (Operand<'tcx>, Operand<'tcx>) {
let span_lines = self.hir.tcx().sess.codemap().lookup_char_pos(span.lo);
(Operand::Constant(Constant {
span: DUMMY_SP,
ty: self.hir.tcx().mk_static_str(),
literal: self.hir.str_literal(intern_and_get_ident(&span_lines.file.name))
}), Operand::Constant(Constant {
span: DUMMY_SP,
ty: self.hir.tcx().types.u32,
literal: self.hir.usize_literal(span_lines.line)
}))
}
}

View File

@ -22,6 +22,7 @@ use rustc::middle::const_eval::{self, ConstVal};
use rustc::middle::infer::InferCtxt;
use rustc::middle::ty::{self, Ty};
use syntax::codemap::Span;
use syntax::parse::token;
use rustc_front::hir;
#[derive(Copy, Clone)]
@ -61,6 +62,10 @@ impl<'a,'tcx:'a> Cx<'a, 'tcx> {
self.tcx.types.bool
}
pub fn str_literal(&mut self, value: token::InternedString) -> Literal<'tcx> {
Literal::Value { value: ConstVal::Str(value) }
}
pub fn true_literal(&mut self) -> Literal<'tcx> {
Literal::Value { value: ConstVal::Bool(true) }
}

View File

@ -81,8 +81,7 @@ impl<'a, 'tcx> EraseRegions<'a, 'tcx> {
Terminator::Goto { .. } |
Terminator::Diverge |
Terminator::Resume |
Terminator::Return |
Terminator::Panic { .. } => {
Terminator::Return => {
/* nothing to do */
}
Terminator::If { ref mut cond, .. } => {

View File

@ -40,10 +40,6 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
build::Br(bcx, self.llblock(target), DebugLoc::None)
}
mir::Terminator::Panic { .. } => {
unimplemented!()
}
mir::Terminator::If { ref cond, targets: (true_bb, false_bb) } => {
let cond = self.trans_operand(bcx, cond);
let lltrue = self.llblock(true_bb);