Skip to content

Commit 539a160

Browse files
committed
Merge pull request #3003 from elliottslaughter/free-cant-fail
Don't emit invoke instructions inside landing pads.
2 parents 8868b22 + c341eb9 commit 539a160

File tree

5 files changed

+40
-21
lines changed

5 files changed

+40
-21
lines changed

Diff for: src/libcore/rt.rs

+6
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ fn rt_exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
3737
ret rustrt::rust_upcall_exchange_malloc(td, size);
3838
}
3939

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

53+
// NB: Calls to free CANNOT be allowed to fail, as throwing an exception from
54+
// inside a landing pad may corrupt the state of the exception handler. If a
55+
// problem occurs, call exit instead.
5056
#[rt(free)]
5157
fn rt_free(ptr: *c_char) {
5258
rustrt::rust_upcall_free(ptr);

Diff for: src/rustc/middle/trans/base.rs

+24-14
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ fn alloca_zeroed(cx: block, t: TypeRef) -> ValueRef {
276276
fn alloca_maybe_zeroed(cx: block, t: TypeRef, zero: bool) -> ValueRef {
277277
let _icx = cx.insn_ctxt(~"alloca");
278278
if cx.unreachable { ret llvm::LLVMGetUndef(t); }
279-
let initcx = raw_block(cx.fcx, cx.fcx.llstaticallocas);
279+
let initcx = raw_block(cx.fcx, false, cx.fcx.llstaticallocas);
280280
let p = Alloca(initcx, t);
281281
if zero { Store(initcx, C_null(t), p); }
282282
ret p;
@@ -294,7 +294,7 @@ fn zero_mem(cx: block, llptr: ValueRef, t: ty::t) -> block {
294294
fn arrayalloca(cx: block, t: TypeRef, v: ValueRef) -> ValueRef {
295295
let _icx = cx.insn_ctxt(~"arrayalloca");
296296
if cx.unreachable { ret llvm::LLVMGetUndef(t); }
297-
ret ArrayAlloca(raw_block(cx.fcx, cx.fcx.llstaticallocas), t, v);
297+
ret ArrayAlloca(raw_block(cx.fcx, false, cx.fcx.llstaticallocas), t, v);
298298
}
299299

300300
// 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 {
32283228
ret false;
32293229
}
32303230

3231+
// Avoid using invoke if we are already inside a landing pad.
3232+
if bcx.is_lpad {
3233+
ret false;
3234+
}
3235+
32313236
if have_cached_lpad(bcx) {
32323237
ret true;
32333238
}
@@ -3291,7 +3296,7 @@ fn get_landing_pad(bcx: block) -> BasicBlockRef {
32913296
alt copy inf.landing_pad {
32923297
some(target) { cached = some(target); }
32933298
none {
3294-
pad_bcx = sub_block(bcx, ~"unwind");
3299+
pad_bcx = lpad_block(bcx, ~"unwind");
32953300
inf.landing_pad = some(pad_bcx.llbb);
32963301
}
32973302
}
@@ -4107,15 +4112,16 @@ fn trans_stmt(cx: block, s: ast::stmt) -> block {
41074112
// You probably don't want to use this one. See the
41084113
// next three functions instead.
41094114
fn new_block(cx: fn_ctxt, parent: option<block>, +kind: block_kind,
4110-
name: ~str, opt_node_info: option<node_info>) -> block {
4115+
is_lpad: bool, name: ~str, opt_node_info: option<node_info>)
4116+
-> block {
41114117

41124118
let s = if cx.ccx.sess.opts.save_temps || cx.ccx.sess.opts.debuginfo {
41134119
cx.ccx.names(name)
41144120
} else { ~"" };
41154121
let llbb: BasicBlockRef = str::as_c_str(s, |buf| {
41164122
llvm::LLVMAppendBasicBlock(cx.llfn, buf)
41174123
});
4118-
let bcx = mk_block(llbb, parent, kind, opt_node_info, cx);
4124+
let bcx = mk_block(llbb, parent, kind, is_lpad, opt_node_info, cx);
41194125
do option::iter(parent) |cx| {
41204126
if cx.unreachable { Unreachable(bcx); }
41214127
};
@@ -4129,14 +4135,14 @@ fn simple_block_scope() -> block_kind {
41294135

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

41364142
fn scope_block(bcx: block,
41374143
opt_node_info: option<node_info>,
41384144
n: ~str) -> block {
4139-
ret new_block(bcx.fcx, some(bcx), simple_block_scope(),
4145+
ret new_block(bcx.fcx, some(bcx), simple_block_scope(), bcx.is_lpad,
41404146
n, opt_node_info);
41414147
}
41424148

@@ -4147,17 +4153,21 @@ fn loop_scope_block(bcx: block, loop_break: block, n: ~str,
41474153
mut cleanups: ~[],
41484154
mut cleanup_paths: ~[],
41494155
mut landing_pad: none
4150-
}), n, opt_node_info);
4156+
}), bcx.is_lpad, n, opt_node_info);
41514157
}
41524158

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

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

4159-
fn raw_block(fcx: fn_ctxt, llbb: BasicBlockRef) -> block {
4160-
mk_block(llbb, none, block_non_scope, none, fcx)
4169+
fn raw_block(fcx: fn_ctxt, is_lpad: bool, llbb: BasicBlockRef) -> block {
4170+
mk_block(llbb, none, block_non_scope, is_lpad, none, fcx)
41614171
}
41624172

41634173

@@ -4475,14 +4485,14 @@ fn copy_args_to_allocas(fcx: fn_ctxt, bcx: block, args: ~[ast::arg],
44754485
fn finish_fn(fcx: fn_ctxt, lltop: BasicBlockRef) {
44764486
let _icx = fcx.insn_ctxt(~"finish_fn");
44774487
tie_up_header_blocks(fcx, lltop);
4478-
let ret_cx = raw_block(fcx, fcx.llreturn);
4488+
let ret_cx = raw_block(fcx, false, fcx.llreturn);
44794489
RetVoid(ret_cx);
44804490
}
44814491

44824492
fn tie_up_header_blocks(fcx: fn_ctxt, lltop: BasicBlockRef) {
44834493
let _icx = fcx.insn_ctxt(~"tie_up_header_blocks");
4484-
Br(raw_block(fcx, fcx.llstaticallocas), fcx.llloadenv);
4485-
Br(raw_block(fcx, fcx.llloadenv), lltop);
4494+
Br(raw_block(fcx, false, fcx.llstaticallocas), fcx.llloadenv);
4495+
Br(raw_block(fcx, false, fcx.llloadenv), lltop);
44864496
}
44874497

44884498
enum self_arg { impl_self(ty::t), no_self, }

Diff for: src/rustc/middle/trans/closure.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ fn load_environment(fcx: fn_ctxt,
319319
load_ret_handle: bool,
320320
ck: ty::closure_kind) {
321321
let _icx = fcx.insn_ctxt(~"closure::load_environment");
322-
let bcx = raw_block(fcx, fcx.llloadenv);
322+
let bcx = raw_block(fcx, false, fcx.llloadenv);
323323

324324
// Load a pointer to the closure data, skipping over the box header:
325325
let llcdata = base::opaque_box_body(bcx, cdata_ty, fcx.llenv);

Diff for: src/rustc/middle/trans/common.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -393,17 +393,19 @@ class block_ {
393393
let parent: option<block>;
394394
// The 'kind' of basic block this is.
395395
let kind: block_kind;
396+
// Is this block part of a landing pad?
397+
let is_lpad: bool;
396398
// info about the AST node this block originated from, if any
397399
let node_info: option<node_info>;
398400
// The function context for the function to which this block is
399401
// attached.
400402
let fcx: fn_ctxt;
401403
new(llbb: BasicBlockRef, parent: option<block>, -kind: block_kind,
402-
node_info: option<node_info>, fcx: fn_ctxt) {
404+
is_lpad: bool, node_info: option<node_info>, fcx: fn_ctxt) {
403405
// sigh
404406
self.llbb = llbb; self.terminated = false; self.unreachable = false;
405-
self.parent = parent; self.kind = kind; self.node_info = node_info;
406-
self.fcx = fcx;
407+
self.parent = parent; self.kind = kind; self.is_lpad = is_lpad;
408+
self.node_info = node_info; self.fcx = fcx;
407409
}
408410
}
409411

@@ -412,8 +414,9 @@ class block_ {
412414
enum block = @block_;
413415

414416
fn mk_block(llbb: BasicBlockRef, parent: option<block>, -kind: block_kind,
415-
node_info: option<node_info>, fcx: fn_ctxt) -> block {
416-
block(@block_(llbb, parent, kind, node_info, fcx))
417+
is_lpad: bool, node_info: option<node_info>, fcx: fn_ctxt)
418+
-> block {
419+
block(@block_(llbb, parent, kind, is_lpad, node_info, fcx))
417420
}
418421

419422
// First two args are retptr, env

Diff for: src/rustc/middle/trans/foreign.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ fn build_wrap_fn_(ccx: @crate_ctxt,
537537
tie_up_header_blocks(fcx, lltop);
538538

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

0 commit comments

Comments
 (0)