Skip to content

Don't emit invoke instructions inside landing pads. #3003

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 24, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/libcore/rt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ fn rt_exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
ret rustrt::rust_upcall_exchange_malloc(td, size);
}

// NB: Calls to free CANNOT be allowed to fail, as throwing an exception from
// inside a landing pad may corrupt the state of the exception handler. If a
// problem occurs, call exit instead.
#[rt(exchange_free)]
fn rt_exchange_free(ptr: *c_char) {
rustrt::rust_upcall_exchange_free(ptr);
Expand All @@ -47,6 +50,9 @@ fn rt_malloc(td: *c_char, size: uintptr_t) -> *c_char {
ret rustrt::rust_upcall_malloc(td, size);
}

// NB: Calls to free CANNOT be allowed to fail, as throwing an exception from
// inside a landing pad may corrupt the state of the exception handler. If a
// problem occurs, call exit instead.
#[rt(free)]
fn rt_free(ptr: *c_char) {
rustrt::rust_upcall_free(ptr);
Expand Down
38 changes: 24 additions & 14 deletions src/rustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ fn alloca_zeroed(cx: block, t: TypeRef) -> ValueRef {
fn alloca_maybe_zeroed(cx: block, t: TypeRef, zero: bool) -> ValueRef {
let _icx = cx.insn_ctxt(~"alloca");
if cx.unreachable { ret llvm::LLVMGetUndef(t); }
let initcx = raw_block(cx.fcx, cx.fcx.llstaticallocas);
let initcx = raw_block(cx.fcx, false, cx.fcx.llstaticallocas);
let p = Alloca(initcx, t);
if zero { Store(initcx, C_null(t), p); }
ret p;
Expand All @@ -294,7 +294,7 @@ fn zero_mem(cx: block, llptr: ValueRef, t: ty::t) -> block {
fn arrayalloca(cx: block, t: TypeRef, v: ValueRef) -> ValueRef {
let _icx = cx.insn_ctxt(~"arrayalloca");
if cx.unreachable { ret llvm::LLVMGetUndef(t); }
ret ArrayAlloca(raw_block(cx.fcx, cx.fcx.llstaticallocas), t, v);
ret ArrayAlloca(raw_block(cx.fcx, false, cx.fcx.llstaticallocas), t, v);
}

// Given a pointer p, returns a pointer sz(p) (i.e., inc'd by sz bytes).
Expand Down Expand Up @@ -3228,6 +3228,11 @@ fn need_invoke(bcx: block) -> bool {
ret false;
}

// Avoid using invoke if we are already inside a landing pad.
if bcx.is_lpad {
ret false;
}

if have_cached_lpad(bcx) {
ret true;
}
Expand Down Expand Up @@ -3291,7 +3296,7 @@ fn get_landing_pad(bcx: block) -> BasicBlockRef {
alt copy inf.landing_pad {
some(target) { cached = some(target); }
none {
pad_bcx = sub_block(bcx, ~"unwind");
pad_bcx = lpad_block(bcx, ~"unwind");
inf.landing_pad = some(pad_bcx.llbb);
}
}
Expand Down Expand Up @@ -4107,15 +4112,16 @@ fn trans_stmt(cx: block, s: ast::stmt) -> block {
// You probably don't want to use this one. See the
// next three functions instead.
fn new_block(cx: fn_ctxt, parent: option<block>, +kind: block_kind,
name: ~str, opt_node_info: option<node_info>) -> block {
is_lpad: bool, name: ~str, opt_node_info: option<node_info>)
-> block {

let s = if cx.ccx.sess.opts.save_temps || cx.ccx.sess.opts.debuginfo {
cx.ccx.names(name)
} else { ~"" };
let llbb: BasicBlockRef = str::as_c_str(s, |buf| {
llvm::LLVMAppendBasicBlock(cx.llfn, buf)
});
let bcx = mk_block(llbb, parent, kind, opt_node_info, cx);
let bcx = mk_block(llbb, parent, kind, is_lpad, opt_node_info, cx);
do option::iter(parent) |cx| {
if cx.unreachable { Unreachable(bcx); }
};
Expand All @@ -4129,14 +4135,14 @@ fn simple_block_scope() -> block_kind {

// Use this when you're at the top block of a function or the like.
fn top_scope_block(fcx: fn_ctxt, opt_node_info: option<node_info>) -> block {
ret new_block(fcx, none, simple_block_scope(),
ret new_block(fcx, none, simple_block_scope(), false,
~"function top level", opt_node_info);
}

fn scope_block(bcx: block,
opt_node_info: option<node_info>,
n: ~str) -> block {
ret new_block(bcx.fcx, some(bcx), simple_block_scope(),
ret new_block(bcx.fcx, some(bcx), simple_block_scope(), bcx.is_lpad,
n, opt_node_info);
}

Expand All @@ -4147,17 +4153,21 @@ fn loop_scope_block(bcx: block, loop_break: block, n: ~str,
mut cleanups: ~[],
mut cleanup_paths: ~[],
mut landing_pad: none
}), n, opt_node_info);
}), bcx.is_lpad, n, opt_node_info);
}

// Use this when creating a block for the inside of a landing pad.
fn lpad_block(bcx: block, n: ~str) -> block {
new_block(bcx.fcx, some(bcx), block_non_scope, true, n, none)
}

// Use this when you're making a general CFG BB within a scope.
fn sub_block(bcx: block, n: ~str) -> block {
new_block(bcx.fcx, some(bcx), block_non_scope, n, none)
new_block(bcx.fcx, some(bcx), block_non_scope, bcx.is_lpad, n, none)
}

fn raw_block(fcx: fn_ctxt, llbb: BasicBlockRef) -> block {
mk_block(llbb, none, block_non_scope, none, fcx)
fn raw_block(fcx: fn_ctxt, is_lpad: bool, llbb: BasicBlockRef) -> block {
mk_block(llbb, none, block_non_scope, is_lpad, none, fcx)
}


Expand Down Expand Up @@ -4475,14 +4485,14 @@ fn copy_args_to_allocas(fcx: fn_ctxt, bcx: block, args: ~[ast::arg],
fn finish_fn(fcx: fn_ctxt, lltop: BasicBlockRef) {
let _icx = fcx.insn_ctxt(~"finish_fn");
tie_up_header_blocks(fcx, lltop);
let ret_cx = raw_block(fcx, fcx.llreturn);
let ret_cx = raw_block(fcx, false, fcx.llreturn);
RetVoid(ret_cx);
}

fn tie_up_header_blocks(fcx: fn_ctxt, lltop: BasicBlockRef) {
let _icx = fcx.insn_ctxt(~"tie_up_header_blocks");
Br(raw_block(fcx, fcx.llstaticallocas), fcx.llloadenv);
Br(raw_block(fcx, fcx.llloadenv), lltop);
Br(raw_block(fcx, false, fcx.llstaticallocas), fcx.llloadenv);
Br(raw_block(fcx, false, fcx.llloadenv), lltop);
}

enum self_arg { impl_self(ty::t), no_self, }
Expand Down
2 changes: 1 addition & 1 deletion src/rustc/middle/trans/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ fn load_environment(fcx: fn_ctxt,
load_ret_handle: bool,
ck: ty::closure_kind) {
let _icx = fcx.insn_ctxt(~"closure::load_environment");
let bcx = raw_block(fcx, fcx.llloadenv);
let bcx = raw_block(fcx, false, fcx.llloadenv);

// Load a pointer to the closure data, skipping over the box header:
let llcdata = base::opaque_box_body(bcx, cdata_ty, fcx.llenv);
Expand Down
13 changes: 8 additions & 5 deletions src/rustc/middle/trans/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -393,17 +393,19 @@ class block_ {
let parent: option<block>;
// The 'kind' of basic block this is.
let kind: block_kind;
// Is this block part of a landing pad?
let is_lpad: bool;
// info about the AST node this block originated from, if any
let node_info: option<node_info>;
// The function context for the function to which this block is
// attached.
let fcx: fn_ctxt;
new(llbb: BasicBlockRef, parent: option<block>, -kind: block_kind,
node_info: option<node_info>, fcx: fn_ctxt) {
is_lpad: bool, node_info: option<node_info>, fcx: fn_ctxt) {
// sigh
self.llbb = llbb; self.terminated = false; self.unreachable = false;
self.parent = parent; self.kind = kind; self.node_info = node_info;
self.fcx = fcx;
self.parent = parent; self.kind = kind; self.is_lpad = is_lpad;
self.node_info = node_info; self.fcx = fcx;
}
}

Expand All @@ -412,8 +414,9 @@ class block_ {
enum block = @block_;

fn mk_block(llbb: BasicBlockRef, parent: option<block>, -kind: block_kind,
node_info: option<node_info>, fcx: fn_ctxt) -> block {
block(@block_(llbb, parent, kind, node_info, fcx))
is_lpad: bool, node_info: option<node_info>, fcx: fn_ctxt)
-> block {
block(@block_(llbb, parent, kind, is_lpad, node_info, fcx))
}

// First two args are retptr, env
Expand Down
2 changes: 1 addition & 1 deletion src/rustc/middle/trans/foreign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ fn build_wrap_fn_(ccx: @crate_ctxt,
tie_up_header_blocks(fcx, lltop);

// Make sure our standard return block (that we didn't use) is terminated
let ret_cx = raw_block(fcx, fcx.llreturn);
let ret_cx = raw_block(fcx, false, fcx.llreturn);
Unreachable(ret_cx);
}

Expand Down