Clean up block_ctxt representation
This commit is contained in:
parent
54d7bffbb8
commit
9f4206cdc4
2 changed files with 131 additions and 140 deletions
|
@ -2108,7 +2108,7 @@ fn trans_for(cx: @block_ctxt, local: @ast::local, seq: @ast::expr,
|
||||||
body: ast::blk, outer_next_cx: @block_ctxt) -> @block_ctxt {
|
body: ast::blk, outer_next_cx: @block_ctxt) -> @block_ctxt {
|
||||||
let next_cx = new_sub_block_ctxt(bcx, "next");
|
let next_cx = new_sub_block_ctxt(bcx, "next");
|
||||||
let scope_cx =
|
let scope_cx =
|
||||||
new_loop_scope_block_ctxt(bcx, option::some(next_cx),
|
new_loop_scope_block_ctxt(bcx, cont_other(next_cx),
|
||||||
outer_next_cx, "for loop scope",
|
outer_next_cx, "for loop scope",
|
||||||
body.span);
|
body.span);
|
||||||
Br(bcx, scope_cx.llbb);
|
Br(bcx, scope_cx.llbb);
|
||||||
|
@ -2138,7 +2138,7 @@ fn trans_for(cx: @block_ctxt, local: @ast::local, seq: @ast::expr,
|
||||||
fn trans_while(cx: @block_ctxt, cond: @ast::expr, body: ast::blk)
|
fn trans_while(cx: @block_ctxt, cond: @ast::expr, body: ast::blk)
|
||||||
-> @block_ctxt {
|
-> @block_ctxt {
|
||||||
let next_cx = new_sub_block_ctxt(cx, "while next");
|
let next_cx = new_sub_block_ctxt(cx, "while next");
|
||||||
let cond_cx = new_loop_scope_block_ctxt(cx, none, next_cx,
|
let cond_cx = new_loop_scope_block_ctxt(cx, cont_self, next_cx,
|
||||||
"while cond", body.span);
|
"while cond", body.span);
|
||||||
let body_cx = new_scope_block_ctxt(cond_cx, "while loop body");
|
let body_cx = new_scope_block_ctxt(cond_cx, "while loop body");
|
||||||
Br(cx, cond_cx.llbb);
|
Br(cx, cond_cx.llbb);
|
||||||
|
@ -2154,7 +2154,7 @@ fn trans_do_while(cx: @block_ctxt, body: ast::blk, cond: @ast::expr) ->
|
||||||
@block_ctxt {
|
@block_ctxt {
|
||||||
let next_cx = new_sub_block_ctxt(cx, "next");
|
let next_cx = new_sub_block_ctxt(cx, "next");
|
||||||
let body_cx =
|
let body_cx =
|
||||||
new_loop_scope_block_ctxt(cx, option::none::<@block_ctxt>, next_cx,
|
new_loop_scope_block_ctxt(cx, cont_self, next_cx,
|
||||||
"do-while loop body", body.span);
|
"do-while loop body", body.span);
|
||||||
let body_end = trans_block(body_cx, body, ignore);
|
let body_end = trans_block(body_cx, body, ignore);
|
||||||
let cond_cx = new_scope_block_ctxt(body_cx, "do-while cond");
|
let cond_cx = new_scope_block_ctxt(body_cx, "do-while cond");
|
||||||
|
@ -2995,27 +2995,32 @@ fn invoke_(bcx: @block_ctxt, llfn: ValueRef, llargs: [ValueRef],
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_landing_pad(bcx: @block_ctxt) -> BasicBlockRef {
|
fn get_landing_pad(bcx: @block_ctxt) -> BasicBlockRef {
|
||||||
fn find_scope_for_lpad(bcx: @block_ctxt) -> @block_ctxt {
|
fn in_lpad_scope_cx(bcx: @block_ctxt, f: fn(scope_info)) {
|
||||||
let scope_bcx = bcx;
|
let bcx = bcx;
|
||||||
while true {
|
while true {
|
||||||
if vec::is_not_empty(scope_bcx.cleanups) { break; }
|
alt bcx.kind {
|
||||||
scope_bcx = alt scope_bcx.parent {
|
scope_block(info) {
|
||||||
parent_some(b) { b }
|
if info.cleanups.len() > 0u || bcx.parent == parent_none {
|
||||||
parent_none { break; }
|
f(info); ret;
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
_ {}
|
||||||
|
}
|
||||||
|
bcx = alt check bcx.parent { parent_some(b) { b } };
|
||||||
}
|
}
|
||||||
scope_bcx
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let scope_bcx = find_scope_for_lpad(bcx);
|
let cached = none, pad_bcx = bcx; // Guaranteed to be set below
|
||||||
|
in_lpad_scope_cx(bcx) {|info|
|
||||||
// If there is a valid landing pad still around, use it
|
// If there is a valid landing pad still around, use it
|
||||||
alt scope_bcx.landing_pad {
|
alt info.landing_pad {
|
||||||
some(target) { ret target; }
|
some(target) { cached = some(target); ret; }
|
||||||
none {}
|
none {}
|
||||||
}
|
}
|
||||||
|
pad_bcx = new_sub_block_ctxt(bcx, "unwind");
|
||||||
let pad_bcx = new_sub_block_ctxt(bcx, "unwind");
|
info.landing_pad = some(pad_bcx.llbb);
|
||||||
scope_bcx.landing_pad = some(pad_bcx.llbb);
|
}
|
||||||
|
alt cached { some(b) { ret b; } none {} } // Can't return from block above
|
||||||
// The landing pad return type (the type being propagated). Not sure what
|
// The landing pad return type (the type being propagated). Not sure what
|
||||||
// this represents but it's determined by the personality function and
|
// this represents but it's determined by the personality function and
|
||||||
// this is what the EH proposal example uses.
|
// this is what the EH proposal example uses.
|
||||||
|
@ -3573,13 +3578,13 @@ fn trans_break_cont(bcx: @block_ctxt, to_end: bool)
|
||||||
let unwind = bcx, target = bcx;
|
let unwind = bcx, target = bcx;
|
||||||
while true {
|
while true {
|
||||||
alt unwind.kind {
|
alt unwind.kind {
|
||||||
LOOP_SCOPE_BLOCK(_cont, _break) {
|
scope_block({is_loop: some({cnt, brk}), _}) {
|
||||||
target = if to_end {
|
target = if to_end {
|
||||||
_break
|
brk
|
||||||
} else {
|
} else {
|
||||||
alt _cont {
|
alt cnt {
|
||||||
option::some(_cont) { _cont }
|
cont_other(o) { o }
|
||||||
_ { unwind }
|
cont_self { unwind }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
@ -3738,16 +3743,14 @@ fn new_block_ctxt(cx: @fn_ctxt, parent: block_parent, kind: block_kind,
|
||||||
if cx.ccx.sess.opts.save_temps || cx.ccx.sess.opts.debuginfo {
|
if cx.ccx.sess.opts.save_temps || cx.ccx.sess.opts.debuginfo {
|
||||||
s = cx.ccx.names(name);
|
s = cx.ccx.names(name);
|
||||||
}
|
}
|
||||||
let llbb: BasicBlockRef =
|
let llbb: BasicBlockRef = str::as_buf(s, {|buf|
|
||||||
str::as_buf(s, {|buf| llvm::LLVMAppendBasicBlock(cx.llfn, buf) });
|
llvm::LLVMAppendBasicBlock(cx.llfn, buf)
|
||||||
|
});
|
||||||
let bcx = @{llbb: llbb,
|
let bcx = @{llbb: llbb,
|
||||||
mutable terminated: false,
|
mutable terminated: false,
|
||||||
mutable unreachable: false,
|
mutable unreachable: false,
|
||||||
parent: parent,
|
parent: parent,
|
||||||
kind: kind,
|
kind: kind,
|
||||||
mutable cleanups: [],
|
|
||||||
mutable cleanup_paths: [],
|
|
||||||
mutable landing_pad: none,
|
|
||||||
block_span: block_span,
|
block_span: block_span,
|
||||||
fcx: cx};
|
fcx: cx};
|
||||||
alt parent {
|
alt parent {
|
||||||
|
@ -3759,34 +3762,43 @@ fn new_block_ctxt(cx: @fn_ctxt, parent: block_parent, kind: block_kind,
|
||||||
ret bcx;
|
ret bcx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn simple_scope_block() -> block_kind {
|
||||||
|
scope_block({is_loop: none, mutable cleanups: [],
|
||||||
|
mutable cleanup_paths: [], mutable landing_pad: none})
|
||||||
|
}
|
||||||
|
|
||||||
// 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 new_top_block_ctxt(fcx: @fn_ctxt, sp: option<span>) -> @block_ctxt {
|
fn new_top_block_ctxt(fcx: @fn_ctxt, sp: option<span>) -> @block_ctxt {
|
||||||
ret new_block_ctxt(fcx, parent_none, SCOPE_BLOCK, "function top level",
|
ret new_block_ctxt(fcx, parent_none, simple_scope_block(),
|
||||||
sp);
|
"function top level", sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Use this when you're at a curly-brace or similar lexical scope.
|
// Use this when you're at a curly-brace or similar lexical scope.
|
||||||
fn new_scope_block_ctxt(bcx: @block_ctxt, n: str) -> @block_ctxt {
|
fn new_scope_block_ctxt(bcx: @block_ctxt, n: str) -> @block_ctxt {
|
||||||
ret new_block_ctxt(bcx.fcx, parent_some(bcx), SCOPE_BLOCK, n, none);
|
ret new_block_ctxt(bcx.fcx, parent_some(bcx), simple_scope_block(),
|
||||||
|
n, none);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_real_block_ctxt(bcx: @block_ctxt, n: str, sp: span) -> @block_ctxt {
|
fn new_real_block_ctxt(bcx: @block_ctxt, n: str, sp: span) -> @block_ctxt {
|
||||||
ret new_block_ctxt(bcx.fcx, parent_some(bcx), SCOPE_BLOCK, n, some(sp));
|
ret new_block_ctxt(bcx.fcx, parent_some(bcx), simple_scope_block(),
|
||||||
|
n, some(sp));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_loop_scope_block_ctxt(bcx: @block_ctxt, _cont: option<@block_ctxt>,
|
fn new_loop_scope_block_ctxt(bcx: @block_ctxt, _cont: loop_cont,
|
||||||
_break: @block_ctxt, n: str, sp: span)
|
_break: @block_ctxt, n: str, sp: span)
|
||||||
-> @block_ctxt {
|
-> @block_ctxt {
|
||||||
ret new_block_ctxt(bcx.fcx, parent_some(bcx),
|
ret new_block_ctxt(bcx.fcx, parent_some(bcx), scope_block({
|
||||||
LOOP_SCOPE_BLOCK(_cont, _break), n, some(sp));
|
is_loop: some({cnt: _cont, brk: _break}),
|
||||||
|
mutable cleanups: [],
|
||||||
|
mutable cleanup_paths: [],
|
||||||
|
mutable landing_pad: none
|
||||||
|
}), n, some(sp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 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 new_sub_block_ctxt(bcx: @block_ctxt, n: str) -> @block_ctxt {
|
fn new_sub_block_ctxt(bcx: @block_ctxt, n: str) -> @block_ctxt {
|
||||||
ret new_block_ctxt(bcx.fcx, parent_some(bcx), NON_SCOPE_BLOCK, n, none);
|
ret new_block_ctxt(bcx.fcx, parent_some(bcx), non_scope_block, n, none);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_raw_block_ctxt(fcx: @fn_ctxt, llbb: BasicBlockRef) -> @block_ctxt {
|
fn new_raw_block_ctxt(fcx: @fn_ctxt, llbb: BasicBlockRef) -> @block_ctxt {
|
||||||
|
@ -3794,10 +3806,7 @@ fn new_raw_block_ctxt(fcx: @fn_ctxt, llbb: BasicBlockRef) -> @block_ctxt {
|
||||||
mutable terminated: false,
|
mutable terminated: false,
|
||||||
mutable unreachable: false,
|
mutable unreachable: false,
|
||||||
parent: parent_none,
|
parent: parent_none,
|
||||||
kind: NON_SCOPE_BLOCK,
|
kind: non_scope_block,
|
||||||
mutable cleanups: [],
|
|
||||||
mutable cleanup_paths: [],
|
|
||||||
mutable landing_pad: none,
|
|
||||||
block_span: none,
|
block_span: none,
|
||||||
fcx: fcx};
|
fcx: fcx};
|
||||||
}
|
}
|
||||||
|
@ -3813,12 +3822,12 @@ fn new_raw_block_ctxt(fcx: @fn_ctxt, llbb: BasicBlockRef) -> @block_ctxt {
|
||||||
fn trans_block_cleanups(bcx: @block_ctxt, cleanup_cx: @block_ctxt) ->
|
fn trans_block_cleanups(bcx: @block_ctxt, cleanup_cx: @block_ctxt) ->
|
||||||
@block_ctxt {
|
@block_ctxt {
|
||||||
if bcx.unreachable { ret bcx; }
|
if bcx.unreachable { ret bcx; }
|
||||||
let i = cleanup_cx.cleanups.len(), bcx = bcx;
|
let bcx = bcx;
|
||||||
if cleanup_cx.kind == NON_SCOPE_BLOCK { assert i == 0u; }
|
alt check cleanup_cx.kind {
|
||||||
while i > 0u {
|
scope_block({cleanups, _}) {
|
||||||
i -= 1u;
|
vec::riter(cleanups) {|cu|
|
||||||
alt cleanup_cx.cleanups[i] {
|
alt cu { clean(cfn) | clean_temp(_, cfn) { bcx = cfn(bcx); } }
|
||||||
clean(cfn) | clean_temp(_, cfn) { bcx = cfn(bcx); }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret bcx;
|
ret bcx;
|
||||||
|
@ -3831,9 +3840,9 @@ fn cleanup_and_leave(bcx: @block_ctxt, upto: option<BasicBlockRef>,
|
||||||
leave: option<BasicBlockRef>) {
|
leave: option<BasicBlockRef>) {
|
||||||
let cur = bcx, bcx = bcx;
|
let cur = bcx, bcx = bcx;
|
||||||
while true {
|
while true {
|
||||||
if cur.cleanups.len() > 0u {
|
alt cur.kind {
|
||||||
assert cur.kind != NON_SCOPE_BLOCK;
|
scope_block(info) if info.cleanups.len() > 0u {
|
||||||
for exists in cur.cleanup_paths {
|
for exists in info.cleanup_paths {
|
||||||
if exists.target == leave {
|
if exists.target == leave {
|
||||||
Br(bcx, exists.dest);
|
Br(bcx, exists.dest);
|
||||||
ret;
|
ret;
|
||||||
|
@ -3841,9 +3850,11 @@ fn cleanup_and_leave(bcx: @block_ctxt, upto: option<BasicBlockRef>,
|
||||||
}
|
}
|
||||||
let sub_cx = new_sub_block_ctxt(bcx, "cleanup");
|
let sub_cx = new_sub_block_ctxt(bcx, "cleanup");
|
||||||
Br(bcx, sub_cx.llbb);
|
Br(bcx, sub_cx.llbb);
|
||||||
cur.cleanup_paths += [{target: leave, dest: sub_cx.llbb}];
|
info.cleanup_paths += [{target: leave, dest: sub_cx.llbb}];
|
||||||
bcx = trans_block_cleanups(sub_cx, cur);
|
bcx = trans_block_cleanups(sub_cx, cur);
|
||||||
}
|
}
|
||||||
|
_ {}
|
||||||
|
}
|
||||||
alt upto {
|
alt upto {
|
||||||
some(bb) { if cur.llbb == bb { break; } }
|
some(bb) { if cur.llbb == bb { break; } }
|
||||||
_ {}
|
_ {}
|
||||||
|
@ -3890,33 +3901,6 @@ fn block_locals(b: ast::blk, it: fn(@ast::local)) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn llstaticallocas_block_ctxt(fcx: @fn_ctxt) -> @block_ctxt {
|
|
||||||
ret @{llbb: fcx.llstaticallocas,
|
|
||||||
mutable terminated: false,
|
|
||||||
mutable unreachable: false,
|
|
||||||
parent: parent_none,
|
|
||||||
kind: SCOPE_BLOCK,
|
|
||||||
mutable cleanups: [],
|
|
||||||
mutable cleanup_paths: [],
|
|
||||||
mutable landing_pad: none,
|
|
||||||
block_span: none,
|
|
||||||
fcx: fcx};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn llderivedtydescs_block_ctxt(fcx: @fn_ctxt) -> @block_ctxt {
|
|
||||||
ret @{llbb: fcx.llderivedtydescs,
|
|
||||||
mutable terminated: false,
|
|
||||||
mutable unreachable: false,
|
|
||||||
parent: parent_none,
|
|
||||||
kind: SCOPE_BLOCK,
|
|
||||||
mutable cleanups: [],
|
|
||||||
mutable cleanup_paths: [],
|
|
||||||
mutable landing_pad: none,
|
|
||||||
block_span: none,
|
|
||||||
fcx: fcx};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn alloc_ty(cx: @block_ctxt, t: ty::t) -> result {
|
fn alloc_ty(cx: @block_ctxt, t: ty::t) -> result {
|
||||||
let bcx = cx, ccx = bcx_ccx(cx);
|
let bcx = cx, ccx = bcx_ccx(cx);
|
||||||
let llty = type_of(ccx, t);
|
let llty = type_of(ccx, t);
|
||||||
|
@ -3927,7 +3911,8 @@ fn alloc_ty(cx: @block_ctxt, t: ty::t) -> result {
|
||||||
// block_ctxt built on the llderivedtydescs block for the fn,
|
// block_ctxt built on the llderivedtydescs block for the fn,
|
||||||
// so that the size dominates the array_alloca that
|
// so that the size dominates the array_alloca that
|
||||||
// comes next.
|
// comes next.
|
||||||
let n = size_of(llderivedtydescs_block_ctxt(bcx.fcx), t);
|
let n = size_of(new_raw_block_ctxt(cx.fcx, cx.fcx.llderivedtydescs),
|
||||||
|
t);
|
||||||
bcx.fcx.llderivedtydescs = n.bcx.llbb;
|
bcx.fcx.llderivedtydescs = n.bcx.llbb;
|
||||||
PointerCast(bcx, dynastack_alloca(bcx, T_i8(), n.val, t), T_ptr(llty))
|
PointerCast(bcx, dynastack_alloca(bcx, T_i8(), n.val, t), T_ptr(llty))
|
||||||
};
|
};
|
||||||
|
|
|
@ -233,16 +233,17 @@ enum cleanup {
|
||||||
type cleanup_path = {target: option<BasicBlockRef>,
|
type cleanup_path = {target: option<BasicBlockRef>,
|
||||||
dest: BasicBlockRef};
|
dest: BasicBlockRef};
|
||||||
|
|
||||||
fn scope_clean_changed(cx: @block_ctxt) {
|
fn scope_clean_changed(info: scope_info) {
|
||||||
cx.cleanup_paths = [];
|
if info.cleanup_paths.len() > 0u { info.cleanup_paths = []; }
|
||||||
cx.landing_pad = none;
|
info.landing_pad = none;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_clean(cx: @block_ctxt, val: ValueRef, ty: ty::t) {
|
fn add_clean(cx: @block_ctxt, val: ValueRef, ty: ty::t) {
|
||||||
if !ty::type_needs_drop(bcx_tcx(cx), ty) { ret; }
|
if !ty::type_needs_drop(bcx_tcx(cx), ty) { ret; }
|
||||||
let scope_cx = find_scope_cx(cx);
|
in_scope_cx(cx) {|info|
|
||||||
scope_cx.cleanups += [clean(bind drop_ty(_, val, ty))];
|
info.cleanups += [clean(bind drop_ty(_, val, ty))];
|
||||||
scope_clean_changed(scope_cx);
|
scope_clean_changed(info);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fn add_clean_temp(cx: @block_ctxt, val: ValueRef, ty: ty::t) {
|
fn add_clean_temp(cx: @block_ctxt, val: ValueRef, ty: ty::t) {
|
||||||
if !ty::type_needs_drop(bcx_tcx(cx), ty) { ret; }
|
if !ty::type_needs_drop(bcx_tcx(cx), ty) { ret; }
|
||||||
|
@ -254,23 +255,25 @@ fn add_clean_temp(cx: @block_ctxt, val: ValueRef, ty: ty::t) {
|
||||||
ret drop_ty(bcx, val, ty);
|
ret drop_ty(bcx, val, ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let scope_cx = find_scope_cx(cx);
|
in_scope_cx(cx) {|info|
|
||||||
scope_cx.cleanups +=
|
info.cleanups += [clean_temp(val, bind do_drop(_, val, ty))];
|
||||||
[clean_temp(val, bind do_drop(_, val, ty))];
|
scope_clean_changed(info);
|
||||||
scope_clean_changed(scope_cx);
|
}
|
||||||
}
|
}
|
||||||
fn add_clean_temp_mem(cx: @block_ctxt, val: ValueRef, ty: ty::t) {
|
fn add_clean_temp_mem(cx: @block_ctxt, val: ValueRef, ty: ty::t) {
|
||||||
if !ty::type_needs_drop(bcx_tcx(cx), ty) { ret; }
|
if !ty::type_needs_drop(bcx_tcx(cx), ty) { ret; }
|
||||||
let scope_cx = find_scope_cx(cx);
|
in_scope_cx(cx) {|info|
|
||||||
scope_cx.cleanups += [clean_temp(val, bind drop_ty(_, val, ty))];
|
info.cleanups += [clean_temp(val, bind drop_ty(_, val, ty))];
|
||||||
scope_clean_changed(scope_cx);
|
scope_clean_changed(info);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fn add_clean_free(cx: @block_ctxt, ptr: ValueRef, shared: bool) {
|
fn add_clean_free(cx: @block_ctxt, ptr: ValueRef, shared: bool) {
|
||||||
let scope_cx = find_scope_cx(cx);
|
|
||||||
let free_fn = if shared { bind base::trans_shared_free(_, ptr) }
|
let free_fn = if shared { bind base::trans_shared_free(_, ptr) }
|
||||||
else { bind base::trans_free(_, ptr) };
|
else { bind base::trans_free(_, ptr) };
|
||||||
scope_cx.cleanups += [clean_temp(ptr, free_fn)];
|
in_scope_cx(cx) {|info|
|
||||||
scope_clean_changed(scope_cx);
|
info.cleanups += [clean_temp(ptr, free_fn)];
|
||||||
|
scope_clean_changed(info);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note that this only works for temporaries. We should, at some point, move
|
// Note that this only works for temporaries. We should, at some point, move
|
||||||
|
@ -278,27 +281,22 @@ fn add_clean_free(cx: @block_ctxt, ptr: ValueRef, shared: bool) {
|
||||||
// this will be more involved. For now, we simply zero out the local, and the
|
// this will be more involved. For now, we simply zero out the local, and the
|
||||||
// drop glue checks whether it is zero.
|
// drop glue checks whether it is zero.
|
||||||
fn revoke_clean(cx: @block_ctxt, val: ValueRef) {
|
fn revoke_clean(cx: @block_ctxt, val: ValueRef) {
|
||||||
let sc_cx = find_scope_cx(cx);
|
in_scope_cx(cx) {|info|
|
||||||
let found = -1;
|
let i = 0u;
|
||||||
let i = 0;
|
for cu in info.cleanups {
|
||||||
for c: cleanup in sc_cx.cleanups {
|
alt cu {
|
||||||
alt c {
|
clean_temp(v, _) if v == val {
|
||||||
clean_temp(v, _) {
|
info.cleanups =
|
||||||
if v as uint == val as uint { found = i; break; }
|
vec::slice(info.cleanups, 0u, i) +
|
||||||
|
vec::slice(info.cleanups, i + 1u, info.cleanups.len());
|
||||||
|
scope_clean_changed(info);
|
||||||
|
ret;
|
||||||
}
|
}
|
||||||
_ {}
|
_ {}
|
||||||
}
|
}
|
||||||
i += 1;
|
i += 1u;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// The value does not have a cleanup associated with it.
|
|
||||||
if found == -1 { ret; }
|
|
||||||
// We found the cleanup and remove it
|
|
||||||
sc_cx.cleanups =
|
|
||||||
vec::slice(sc_cx.cleanups, 0u, found as uint) +
|
|
||||||
vec::slice(sc_cx.cleanups, (found as uint) + 1u,
|
|
||||||
sc_cx.cleanups.len());
|
|
||||||
scope_clean_changed(sc_cx);
|
|
||||||
ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_res_dtor(ccx: @crate_ctxt, did: ast::def_id, inner_t: ty::t)
|
fn get_res_dtor(ccx: @crate_ctxt, did: ast::def_id, inner_t: ty::t)
|
||||||
|
@ -325,47 +323,53 @@ enum block_kind {
|
||||||
// cleaned up. May correspond to an actual block in the language, but also
|
// cleaned up. May correspond to an actual block in the language, but also
|
||||||
// to an implicit scope, for example, calls introduce an implicit scope in
|
// to an implicit scope, for example, calls introduce an implicit scope in
|
||||||
// which the arguments are evaluated and cleaned up.
|
// which the arguments are evaluated and cleaned up.
|
||||||
SCOPE_BLOCK,
|
scope_block(scope_info),
|
||||||
// A basic block created from the body of a loop. Contains pointers to
|
|
||||||
// which block to jump to in the case of "continue" or "break".
|
|
||||||
LOOP_SCOPE_BLOCK(option<@block_ctxt>, @block_ctxt),
|
|
||||||
// A non-scope block is a basic block created as a translation artifact
|
// A non-scope block is a basic block created as a translation artifact
|
||||||
// from translating code that expresses conditional logic rather than by
|
// from translating code that expresses conditional logic rather than by
|
||||||
// explicit { ... } block structure in the source language. It's called a
|
// explicit { ... } block structure in the source language. It's called a
|
||||||
// non-scope block because it doesn't introduce a new variable scope.
|
// non-scope block because it doesn't introduce a new variable scope.
|
||||||
NON_SCOPE_BLOCK
|
non_scope_block,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum loop_cont { cont_self, cont_other(@block_ctxt), }
|
||||||
|
|
||||||
|
type scope_info = {
|
||||||
|
is_loop: option<{cnt: loop_cont, brk: @block_ctxt}>,
|
||||||
|
// A list of functions that must be run at when leaving this
|
||||||
|
// block, cleaning up any variables that were introduced in the
|
||||||
|
// block.
|
||||||
|
mutable cleanups: [cleanup],
|
||||||
|
// Existing cleanup paths that may be reused, indexed by destination and
|
||||||
|
// cleared when the set of cleanups changes.
|
||||||
|
mutable cleanup_paths: [cleanup_path],
|
||||||
|
// Unwinding landing pad. Also cleared when cleanups change.
|
||||||
|
mutable landing_pad: option<BasicBlockRef>,
|
||||||
|
};
|
||||||
|
|
||||||
// Basic block context. We create a block context for each basic block
|
// Basic block context. We create a block context for each basic block
|
||||||
// (single-entry, single-exit sequence of instructions) we generate from Rust
|
// (single-entry, single-exit sequence of instructions) we generate from Rust
|
||||||
// code. Each basic block we generate is attached to a function, typically
|
// code. Each basic block we generate is attached to a function, typically
|
||||||
// with many basic blocks per function. All the basic blocks attached to a
|
// with many basic blocks per function. All the basic blocks attached to a
|
||||||
// function are organized as a directed graph.
|
// function are organized as a directed graph.
|
||||||
type block_ctxt =
|
type block_ctxt = {
|
||||||
// The BasicBlockRef returned from a call to
|
// The BasicBlockRef returned from a call to
|
||||||
// llvm::LLVMAppendBasicBlock(llfn, name), which adds a basic
|
// llvm::LLVMAppendBasicBlock(llfn, name), which adds a basic
|
||||||
// block to the function pointed to by llfn. We insert
|
// block to the function pointed to by llfn. We insert
|
||||||
// instructions into that block by way of this block context.
|
// instructions into that block by way of this block context.
|
||||||
// The block pointing to this one in the function's digraph.
|
// The block pointing to this one in the function's digraph.
|
||||||
// The 'kind' of basic block this is.
|
llbb: BasicBlockRef,
|
||||||
// A list of functions that run at the end of translating this
|
|
||||||
// block, cleaning up any variables that were introduced in the
|
|
||||||
// block and need to go out of scope at the end of it.
|
|
||||||
// The source span where this block comes from, for error
|
|
||||||
// reporting. FIXME this is not currently reliable
|
|
||||||
// The function context for the function to which this block is
|
|
||||||
// attached.
|
|
||||||
{llbb: BasicBlockRef,
|
|
||||||
mutable terminated: bool,
|
mutable terminated: bool,
|
||||||
mutable unreachable: bool,
|
mutable unreachable: bool,
|
||||||
parent: block_parent,
|
parent: block_parent,
|
||||||
|
// The 'kind' of basic block this is.
|
||||||
kind: block_kind,
|
kind: block_kind,
|
||||||
// FIXME the next five fields should probably only appear in scope blocks
|
// The source span where the block came from, if it is a block that
|
||||||
mutable cleanups: [cleanup],
|
// actually appears in the source code.
|
||||||
mutable cleanup_paths: [cleanup_path],
|
|
||||||
mutable landing_pad: option<BasicBlockRef>,
|
|
||||||
block_span: option<span>,
|
block_span: option<span>,
|
||||||
fcx: @fn_ctxt};
|
// The function context for the function to which this block is
|
||||||
|
// attached.
|
||||||
|
fcx: @fn_ctxt
|
||||||
|
};
|
||||||
|
|
||||||
// FIXME: we should be able to use option<@block_parent> here but
|
// FIXME: we should be able to use option<@block_parent> here but
|
||||||
// the infinite-enum check in rustboot gets upset.
|
// the infinite-enum check in rustboot gets upset.
|
||||||
|
@ -395,13 +399,15 @@ fn struct_elt(llstructty: TypeRef, n: uint) -> TypeRef unsafe {
|
||||||
ret llvm::LLVMGetElementType(elt_tys[n]);
|
ret llvm::LLVMGetElementType(elt_tys[n]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_scope_cx(cx: @block_ctxt) -> @block_ctxt {
|
fn in_scope_cx(cx: @block_ctxt, f: fn(scope_info)) {
|
||||||
let cur = cx;
|
let cur = cx;
|
||||||
while true {
|
while true {
|
||||||
if cur.kind != NON_SCOPE_BLOCK { break; }
|
alt cur.kind {
|
||||||
|
scope_block(info) { f(info); ret; }
|
||||||
|
_ {}
|
||||||
|
}
|
||||||
cur = alt check cur.parent { parent_some(b) { b } };
|
cur = alt check cur.parent { parent_some(b) { b } };
|
||||||
}
|
}
|
||||||
cur
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accessors
|
// Accessors
|
||||||
|
|
Loading…
Reference in a new issue