Merge pull request #3003 from elliottslaughter/free-cant-fail
Don't emit invoke instructions inside landing pads.
This commit is contained in:
commit
539a160bb7
5 changed files with 40 additions and 21 deletions
|
@ -37,6 +37,9 @@ fn rt_exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
|
||||||
ret rustrt::rust_upcall_exchange_malloc(td, size);
|
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)]
|
#[rt(exchange_free)]
|
||||||
fn rt_exchange_free(ptr: *c_char) {
|
fn rt_exchange_free(ptr: *c_char) {
|
||||||
rustrt::rust_upcall_exchange_free(ptr);
|
rustrt::rust_upcall_exchange_free(ptr);
|
||||||
|
@ -47,6 +50,9 @@ fn rt_malloc(td: *c_char, size: uintptr_t) -> *c_char {
|
||||||
ret rustrt::rust_upcall_malloc(td, size);
|
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)]
|
#[rt(free)]
|
||||||
fn rt_free(ptr: *c_char) {
|
fn rt_free(ptr: *c_char) {
|
||||||
rustrt::rust_upcall_free(ptr);
|
rustrt::rust_upcall_free(ptr);
|
||||||
|
|
|
@ -276,7 +276,7 @@ fn alloca_zeroed(cx: block, t: TypeRef) -> ValueRef {
|
||||||
fn alloca_maybe_zeroed(cx: block, t: TypeRef, zero: bool) -> ValueRef {
|
fn alloca_maybe_zeroed(cx: block, t: TypeRef, zero: bool) -> ValueRef {
|
||||||
let _icx = cx.insn_ctxt(~"alloca");
|
let _icx = cx.insn_ctxt(~"alloca");
|
||||||
if cx.unreachable { ret llvm::LLVMGetUndef(t); }
|
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);
|
let p = Alloca(initcx, t);
|
||||||
if zero { Store(initcx, C_null(t), p); }
|
if zero { Store(initcx, C_null(t), p); }
|
||||||
ret p;
|
ret p;
|
||||||
|
@ -294,7 +294,7 @@ fn zero_mem(cx: block, llptr: ValueRef, t: ty::t) -> block {
|
||||||
fn arrayalloca(cx: block, t: TypeRef, v: ValueRef) -> ValueRef {
|
fn arrayalloca(cx: block, t: TypeRef, v: ValueRef) -> ValueRef {
|
||||||
let _icx = cx.insn_ctxt(~"arrayalloca");
|
let _icx = cx.insn_ctxt(~"arrayalloca");
|
||||||
if cx.unreachable { ret llvm::LLVMGetUndef(t); }
|
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).
|
// Given a pointer p, returns a pointer sz(p) (i.e., inc'd by sz bytes).
|
||||||
|
@ -3228,6 +3228,11 @@ fn need_invoke(bcx: block) -> bool {
|
||||||
ret false;
|
ret false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Avoid using invoke if we are already inside a landing pad.
|
||||||
|
if bcx.is_lpad {
|
||||||
|
ret false;
|
||||||
|
}
|
||||||
|
|
||||||
if have_cached_lpad(bcx) {
|
if have_cached_lpad(bcx) {
|
||||||
ret true;
|
ret true;
|
||||||
}
|
}
|
||||||
|
@ -3291,7 +3296,7 @@ fn get_landing_pad(bcx: block) -> BasicBlockRef {
|
||||||
alt copy inf.landing_pad {
|
alt copy inf.landing_pad {
|
||||||
some(target) { cached = some(target); }
|
some(target) { cached = some(target); }
|
||||||
none {
|
none {
|
||||||
pad_bcx = sub_block(bcx, ~"unwind");
|
pad_bcx = lpad_block(bcx, ~"unwind");
|
||||||
inf.landing_pad = some(pad_bcx.llbb);
|
inf.landing_pad = some(pad_bcx.llbb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4107,7 +4112,8 @@ fn trans_stmt(cx: block, s: ast::stmt) -> block {
|
||||||
// You probably don't want to use this one. See the
|
// You probably don't want to use this one. See the
|
||||||
// next three functions instead.
|
// next three functions instead.
|
||||||
fn new_block(cx: fn_ctxt, parent: option<block>, +kind: block_kind,
|
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 {
|
let s = if cx.ccx.sess.opts.save_temps || cx.ccx.sess.opts.debuginfo {
|
||||||
cx.ccx.names(name)
|
cx.ccx.names(name)
|
||||||
|
@ -4115,7 +4121,7 @@ fn new_block(cx: fn_ctxt, parent: option<block>, +kind: block_kind,
|
||||||
let llbb: BasicBlockRef = str::as_c_str(s, |buf| {
|
let llbb: BasicBlockRef = str::as_c_str(s, |buf| {
|
||||||
llvm::LLVMAppendBasicBlock(cx.llfn, 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| {
|
do option::iter(parent) |cx| {
|
||||||
if cx.unreachable { Unreachable(bcx); }
|
if cx.unreachable { Unreachable(bcx); }
|
||||||
};
|
};
|
||||||
|
@ -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.
|
// 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 {
|
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);
|
~"function top level", opt_node_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scope_block(bcx: block,
|
fn scope_block(bcx: block,
|
||||||
opt_node_info: option<node_info>,
|
opt_node_info: option<node_info>,
|
||||||
n: ~str) -> block {
|
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);
|
n, opt_node_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4147,17 +4153,21 @@ fn loop_scope_block(bcx: block, loop_break: block, n: ~str,
|
||||||
mut cleanups: ~[],
|
mut cleanups: ~[],
|
||||||
mut cleanup_paths: ~[],
|
mut cleanup_paths: ~[],
|
||||||
mut landing_pad: none
|
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.
|
// Use this when you're making a general CFG BB within a scope.
|
||||||
fn sub_block(bcx: block, n: ~str) -> block {
|
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 {
|
fn raw_block(fcx: fn_ctxt, is_lpad: bool, llbb: BasicBlockRef) -> block {
|
||||||
mk_block(llbb, none, block_non_scope, none, fcx)
|
mk_block(llbb, none, block_non_scope, is_lpad, none, fcx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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) {
|
fn finish_fn(fcx: fn_ctxt, lltop: BasicBlockRef) {
|
||||||
let _icx = fcx.insn_ctxt(~"finish_fn");
|
let _icx = fcx.insn_ctxt(~"finish_fn");
|
||||||
tie_up_header_blocks(fcx, lltop);
|
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);
|
RetVoid(ret_cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tie_up_header_blocks(fcx: fn_ctxt, lltop: BasicBlockRef) {
|
fn tie_up_header_blocks(fcx: fn_ctxt, lltop: BasicBlockRef) {
|
||||||
let _icx = fcx.insn_ctxt(~"tie_up_header_blocks");
|
let _icx = fcx.insn_ctxt(~"tie_up_header_blocks");
|
||||||
Br(raw_block(fcx, fcx.llstaticallocas), fcx.llloadenv);
|
Br(raw_block(fcx, false, fcx.llstaticallocas), fcx.llloadenv);
|
||||||
Br(raw_block(fcx, fcx.llloadenv), lltop);
|
Br(raw_block(fcx, false, fcx.llloadenv), lltop);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum self_arg { impl_self(ty::t), no_self, }
|
enum self_arg { impl_self(ty::t), no_self, }
|
||||||
|
|
|
@ -319,7 +319,7 @@ fn load_environment(fcx: fn_ctxt,
|
||||||
load_ret_handle: bool,
|
load_ret_handle: bool,
|
||||||
ck: ty::closure_kind) {
|
ck: ty::closure_kind) {
|
||||||
let _icx = fcx.insn_ctxt(~"closure::load_environment");
|
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:
|
// Load a pointer to the closure data, skipping over the box header:
|
||||||
let llcdata = base::opaque_box_body(bcx, cdata_ty, fcx.llenv);
|
let llcdata = base::opaque_box_body(bcx, cdata_ty, fcx.llenv);
|
||||||
|
|
|
@ -393,17 +393,19 @@ class block_ {
|
||||||
let parent: option<block>;
|
let parent: option<block>;
|
||||||
// The 'kind' of basic block this is.
|
// The 'kind' of basic block this is.
|
||||||
let kind: block_kind;
|
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
|
// info about the AST node this block originated from, if any
|
||||||
let node_info: option<node_info>;
|
let node_info: option<node_info>;
|
||||||
// The function context for the function to which this block is
|
// The function context for the function to which this block is
|
||||||
// attached.
|
// attached.
|
||||||
let fcx: fn_ctxt;
|
let fcx: fn_ctxt;
|
||||||
new(llbb: BasicBlockRef, parent: option<block>, -kind: block_kind,
|
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
|
// sigh
|
||||||
self.llbb = llbb; self.terminated = false; self.unreachable = false;
|
self.llbb = llbb; self.terminated = false; self.unreachable = false;
|
||||||
self.parent = parent; self.kind = kind; self.node_info = node_info;
|
self.parent = parent; self.kind = kind; self.is_lpad = is_lpad;
|
||||||
self.fcx = fcx;
|
self.node_info = node_info; self.fcx = fcx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,8 +414,9 @@ class block_ {
|
||||||
enum block = @block_;
|
enum block = @block_;
|
||||||
|
|
||||||
fn mk_block(llbb: BasicBlockRef, parent: option<block>, -kind: block_kind,
|
fn mk_block(llbb: BasicBlockRef, parent: option<block>, -kind: block_kind,
|
||||||
node_info: option<node_info>, fcx: fn_ctxt) -> block {
|
is_lpad: bool, node_info: option<node_info>, fcx: fn_ctxt)
|
||||||
block(@block_(llbb, parent, kind, node_info, fcx))
|
-> block {
|
||||||
|
block(@block_(llbb, parent, kind, is_lpad, node_info, fcx))
|
||||||
}
|
}
|
||||||
|
|
||||||
// First two args are retptr, env
|
// First two args are retptr, env
|
||||||
|
|
|
@ -537,7 +537,7 @@ fn build_wrap_fn_(ccx: @crate_ctxt,
|
||||||
tie_up_header_blocks(fcx, lltop);
|
tie_up_header_blocks(fcx, lltop);
|
||||||
|
|
||||||
// Make sure our standard return block (that we didn't use) is terminated
|
// 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);
|
Unreachable(ret_cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue