Remove unreachable and terminated from Block

This commit is contained in:
Mark-Simulacrum 2016-12-10 20:35:02 -07:00 committed by Mark Simulacrum
parent bf7d4534a7
commit 3f17ab9618
7 changed files with 17 additions and 93 deletions

View File

@ -566,7 +566,7 @@ fn struct_field_ptr<'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>,
ix: usize, needs_cast: bool) -> ValueRef {
let fty = fields[ix];
let ccx = bcx.ccx();
let ll_fty = type_of::in_memory_type_of(bcx.ccx(), fty);
let ll_fty = type_of::in_memory_type_of(ccx, fty);
let ptr_val = if needs_cast {
let fields = st.field_index_by_increasing_offset().map(|i| {

View File

@ -467,10 +467,6 @@ pub fn invoke<'blk, 'tcx>(bcx: BlockAndBuilder<'blk, 'tcx>,
debug_loc: DebugLoc)
-> (ValueRef, BlockAndBuilder<'blk, 'tcx>) {
let _icx = push_ctxt("invoke_");
if bcx.is_unreachable() {
return (C_null(Type::i8(bcx.ccx())), bcx);
}
if need_invoke(&bcx) {
debug!("invoking {:?} at {:?}", Value(llfn), bcx.llbb());
for &llarg in llargs {
@ -562,10 +558,6 @@ pub fn load_ty_builder<'a, 'tcx>(b: &Builder<'a, 'tcx>, ptr: ValueRef, t: Ty<'tc
/// Helper for storing values in memory. Does the necessary conversion if the in-memory type
/// differs from the type used for SSA values.
pub fn store_ty<'blk, 'tcx>(cx: &BlockAndBuilder<'blk, 'tcx>, v: ValueRef, dst: ValueRef, t: Ty<'tcx>) {
if cx.is_unreachable() {
return;
}
debug!("store_ty: {:?} : {:?} <- {:?}", Value(dst), t, Value(v));
if common::type_is_fat_ptr(cx.tcx(), t) {
@ -592,12 +584,6 @@ pub fn load_fat_ptr<'blk, 'tcx>(cx: &BlockAndBuilder<'blk, 'tcx>,
ty: Ty<'tcx>)
-> (ValueRef, ValueRef)
{
if cx.is_unreachable() {
// FIXME: remove me
return (Load(cx, get_dataptr(cx, src)),
Load(cx, get_meta(cx, src)));
}
load_fat_ptr_builder(cx, src, ty)
}
@ -644,7 +630,7 @@ pub fn with_cond<'blk, 'tcx, F>(
{
let _icx = push_ctxt("with_cond");
if bcx.is_unreachable() || common::const_to_opt_uint(val) == Some(0) {
if common::const_to_opt_uint(val) == Some(0) {
return bcx;
}
@ -704,15 +690,11 @@ impl Lifetime {
}
pub fn call_lifetime_start(bcx: &BlockAndBuilder, ptr: ValueRef) {
if !bcx.is_unreachable() {
Lifetime::Start.call(bcx, ptr);
}
Lifetime::Start.call(bcx, ptr);
}
pub fn call_lifetime_end(bcx: &BlockAndBuilder, ptr: ValueRef) {
if !bcx.is_unreachable() {
Lifetime::End.call(bcx, ptr);
}
Lifetime::End.call(bcx, ptr);
}
// Generates code for resumption of unwind at the end of a landing pad.
@ -747,7 +729,7 @@ pub fn memcpy_ty<'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>, dst: ValueRef, s
let _icx = push_ctxt("memcpy_ty");
let ccx = bcx.ccx();
if type_is_zero_size(ccx, t) || bcx.is_unreachable() {
if type_is_zero_size(ccx, t) {
return;
}
@ -765,9 +747,6 @@ pub fn memcpy_ty<'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>, dst: ValueRef, s
}
pub fn init_zero_mem<'blk, 'tcx>(cx: &BlockAndBuilder<'blk, 'tcx>, llptr: ValueRef, t: Ty<'tcx>) {
if cx.is_unreachable() {
return;
}
let _icx = push_ctxt("init_zero_mem");
let bcx = cx;
memfill(bcx, llptr, t, 0);
@ -926,8 +905,7 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> {
// Builds the return block for a function.
pub fn build_return_block(&self, ret_cx: &BlockAndBuilder<'blk, 'tcx>,
ret_debug_location: DebugLoc) {
if self.llretslotptr.get().is_none() || ret_cx.is_unreachable() ||
self.fn_ty.ret.is_indirect() {
if self.llretslotptr.get().is_none() || self.fn_ty.ret.is_indirect() {
return RetVoid(ret_cx, ret_debug_location);
}

View File

@ -24,22 +24,12 @@ use debuginfo::DebugLoc;
use libc::{c_uint, c_char};
// The difference between a block being unreachable and being terminated is
// somewhat obscure, and has to do with error checking. When a block is
// terminated, we're saying that trying to add any further statements in the
// block is an error. On the other hand, if something is unreachable, that
// means that the block was terminated in some way that we don't want to check
// for (panic/break/return statements, call to diverging functions, etc), and
// further instructions to the block should simply be ignored.
pub fn RetVoid(cx: &BlockAndBuilder, debug_loc: DebugLoc) {
cx.terminate();
debug_loc.apply(cx.fcx());
cx.ret_void();
}
pub fn Ret(cx: &BlockAndBuilder, v: ValueRef, debug_loc: DebugLoc) {
cx.terminate();
debug_loc.apply(cx.fcx());
cx.ret(v);
}
@ -47,13 +37,11 @@ pub fn Ret(cx: &BlockAndBuilder, v: ValueRef, debug_loc: DebugLoc) {
pub fn AggregateRet(cx: &BlockAndBuilder,
ret_vals: &[ValueRef],
debug_loc: DebugLoc) {
cx.terminate();
debug_loc.apply(cx.fcx());
cx.aggregate_ret(ret_vals);
}
pub fn Br(cx: &BlockAndBuilder, dest: BasicBlockRef, debug_loc: DebugLoc) {
cx.terminate();
debug_loc.apply(cx.fcx());
cx.br(dest);
}
@ -63,14 +51,12 @@ pub fn CondBr(cx: &BlockAndBuilder,
then: BasicBlockRef,
else_: BasicBlockRef,
debug_loc: DebugLoc) {
cx.terminate();
debug_loc.apply(cx.fcx());
cx.cond_br(if_, then, else_);
}
pub fn Switch(cx: &BlockAndBuilder, v: ValueRef, else_: BasicBlockRef, num_cases: usize)
-> ValueRef {
cx.terminate();
cx.switch(v, else_, num_cases)
}
@ -85,7 +71,6 @@ pub fn IndirectBr(cx: &BlockAndBuilder,
addr: ValueRef,
num_dests: usize,
debug_loc: DebugLoc) {
cx.terminate();
debug_loc.apply(cx.fcx());
cx.indirect_br(addr, num_dests);
}
@ -97,7 +82,6 @@ pub fn Invoke(cx: &BlockAndBuilder,
catch: BasicBlockRef,
debug_loc: DebugLoc)
-> ValueRef {
cx.terminate();
debug!("Invoke({:?} with arguments ({}))",
Value(fn_),
args.iter().map(|a| {
@ -687,7 +671,6 @@ pub fn Trap(cx: &BlockAndBuilder) {
pub fn LandingPad(cx: &BlockAndBuilder, ty: Type, pers_fn: ValueRef,
num_clauses: usize) -> ValueRef {
assert!(!cx.is_unreachable());
cx.landing_pad(ty, pers_fn, num_clauses, cx.fcx().llfn)
}
@ -720,26 +703,22 @@ pub fn AtomicRMW(cx: &BlockAndBuilder, op: AtomicRmwBinOp,
pub fn CleanupPad(cx: &BlockAndBuilder,
parent: Option<ValueRef>,
args: &[ValueRef]) -> ValueRef {
assert!(!cx.is_unreachable());
cx.cleanup_pad(parent, args)
}
pub fn CleanupRet(cx: &BlockAndBuilder,
cleanup: ValueRef,
unwind: Option<BasicBlockRef>) -> ValueRef {
cx.terminate();
cx.cleanup_ret(cleanup, unwind)
}
pub fn CatchPad(cx: &BlockAndBuilder,
parent: ValueRef,
args: &[ValueRef]) -> ValueRef {
assert!(!cx.is_unreachable());
cx.catch_pad(parent, args)
}
pub fn CatchRet(cx: &BlockAndBuilder, pad: ValueRef, unwind: BasicBlockRef) -> ValueRef {
cx.terminate();
cx.catch_ret(pad, unwind)
}
@ -747,7 +726,6 @@ pub fn CatchSwitch(cx: &BlockAndBuilder,
parent: Option<ValueRef>,
unwind: Option<BasicBlockRef>,
num_handlers: usize) -> ValueRef {
cx.terminate();
cx.catch_switch(parent, unwind, num_handlers)
}

View File

@ -712,24 +712,20 @@ fn trans_call_inner<'a, 'blk, 'tcx>(bcx: BlockAndBuilder<'blk, 'tcx>,
};
let (llret, bcx) = base::invoke(bcx, llfn, &llargs, debug_loc);
if !bcx.is_unreachable() {
fn_ty.apply_attrs_callsite(llret);
fn_ty.apply_attrs_callsite(llret);
// If the function we just called does not use an outpointer,
// store the result into the rust outpointer. Cast the outpointer
// type to match because some ABIs will use a different type than
// the Rust type. e.g., a {u32,u32} struct could be returned as
// u64.
if !fn_ty.ret.is_indirect() {
if let Some(llretslot) = opt_llretslot {
fn_ty.ret.store(&bcx, llret, llretslot);
}
// If the function we just called does not use an outpointer,
// store the result into the rust outpointer. Cast the outpointer
// type to match because some ABIs will use a different type than
// the Rust type. e.g., a {u32,u32} struct could be returned as
// u64.
if !fn_ty.ret.is_indirect() {
if let Some(llretslot) = opt_llretslot {
fn_ty.ret.store(&bcx, llret, llretslot);
}
}
if fn_ret.0.is_never() {
assert!(!bcx.is_terminated());
bcx.set_unreachable();
bcx.unreachable();
}

View File

@ -343,10 +343,8 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> {
scope: &CleanupScope<'tcx>) -> BlockAndBuilder<'blk, 'tcx> {
let mut bcx = bcx;
if !bcx.is_unreachable() {
for cleanup in scope.cleanups.iter().rev() {
bcx = cleanup.trans(bcx, scope.debug_loc);
}
for cleanup in scope.cleanups.iter().rev() {
bcx = cleanup.trans(bcx, scope.debug_loc);
}
bcx
}

View File

@ -449,8 +449,6 @@ pub struct BlockS<'blk, 'tcx: 'blk> {
// instructions into that block by way of this block context.
// The block pointing to this one in the function's digraph.
pub llbb: BasicBlockRef,
pub terminated: Cell<bool>,
pub unreachable: Cell<bool>,
// If this block part of a landing pad, then this is `Some` indicating what
// kind of landing pad its in, otherwise this is none.
@ -469,8 +467,6 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> {
-> Block<'blk, 'tcx> {
fcx.block_arena.alloc(BlockS {
llbb: llbb,
terminated: Cell::new(false),
unreachable: Cell::new(false),
lpad: Cell::new(None),
fcx: fcx
})
@ -599,24 +595,6 @@ impl<'blk, 'tcx> BlockAndBuilder<'blk, 'tcx> {
// Methods delegated to bcx
pub fn terminate(&self) {
debug!("terminate({})", self.bcx.to_str());
self.bcx.terminated.set(true);
}
pub fn set_unreachable(&self) {
debug!("set_unreachable({})", self.bcx.to_str());
self.bcx.unreachable.set(true);
}
pub fn is_unreachable(&self) -> bool {
self.bcx.unreachable.get()
}
pub fn is_terminated(&self) -> bool {
self.bcx.terminated.get()
}
pub fn ccx(&self) -> &'blk CrateContext<'blk, 'tcx> {
self.bcx.ccx()
}

View File

@ -321,10 +321,6 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>,
let align = C_uint(bcx.ccx(), align);
return (size, align);
}
if bcx.is_unreachable() {
let llty = Type::int(bcx.ccx());
return (C_undef(llty), C_undef(llty));
}
match t.sty {
ty::TyAdt(def, substs) => {
let ccx = bcx.ccx();