aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGraydon Hoare <[email protected]>2011-01-07 16:26:30 -0800
committerGraydon Hoare <[email protected]>2011-01-07 16:26:30 -0800
commit3b0e207109ba135e94264cef17bac989574ccb0b (patch)
tree3a3f388b4b37bd34233ba3f721d42da08747e923 /src
parentAdd sufficient import support to compile some simple single-crate programs. (diff)
downloadrust-3b0e207109ba135e94264cef17bac989574ccb0b.tar.xz
rust-3b0e207109ba135e94264cef17bac989574ccb0b.zip
Drop closures. Un-XFAIL bind-interior.rs.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile1
-rw-r--r--src/comp/middle/trans.rs61
2 files changed, 55 insertions, 7 deletions
diff --git a/src/Makefile b/src/Makefile
index 60f87e8e..c9c7b6b0 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -418,6 +418,7 @@ TEST_XFAILS_RUSTC := $(filter-out \
arith-0.rs \
arith-1.rs \
arith-2.rs \
+ bind-interior.rs \
bind-thunk.rs \
bind-trivial.rs \
bitwise.rs \
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index f81c2bb4..50571879 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -298,7 +298,9 @@ fn T_closure_ptr(TypeRef lltarget_ty,
}
fn T_opaque_closure_ptr() -> TypeRef {
- ret T_ptr(T_box(T_nil()));
+ ret T_closure_ptr(T_struct(vec(T_ptr(T_nil()),
+ T_ptr(T_nil()))),
+ T_nil());
}
@@ -849,6 +851,50 @@ fn make_drop_glue(@block_ctxt cx, ValueRef v, @ty.t t) -> result {
T_int(), C_int(0));
}
+ case (ty.ty_fn(_,_)) {
+ fn hit_zero(@block_ctxt cx, ValueRef v) -> result {
+
+ // Call through the closure's own fields-drop glue first.
+ auto body =
+ cx.build.GEP(v,
+ vec(C_int(0),
+ C_int(abi.box_rc_field_body)));
+
+ auto bindings =
+ cx.build.GEP(body,
+ vec(C_int(0),
+ C_int(abi.closure_elt_bindings)));
+ auto llrawptr = cx.build.BitCast(bindings, T_ptr(T_i8()));
+
+ auto tydescptr =
+ cx.build.GEP(body,
+ vec(C_int(0),
+ C_int(abi.closure_elt_tydesc)));
+ auto tydesc = cx.build.Load(tydescptr);
+ auto llfnptr =
+ cx.build.GEP(tydesc,
+ vec(C_int(0),
+ C_int(abi.tydesc_field_drop_glue_off)));
+ auto llfn = cx.build.Load(llfnptr);
+ cx.build.FastCall(llfn, vec(cx.fcx.lltaskptr, llrawptr));
+
+ // Then free the body.
+ // FIXME: switch gc/non-gc on layer of the type.
+ ret trans_non_gc_free(cx, v);
+ }
+ auto box_cell =
+ cx.build.GEP(v,
+ vec(C_int(0),
+ C_int(abi.fn_field_box)));
+
+ auto boxptr = cx.build.Load(box_cell);
+
+ ret decr_refcnt_and_if_zero(cx, boxptr,
+ bind hit_zero(_, boxptr),
+ "free fn",
+ T_int(), C_int(0));
+ }
+
case (_) {
if (ty.type_is_structural(t)) {
ret iter_structural_ty(cx, v, t,
@@ -2145,13 +2191,11 @@ impure fn trans_bind(@block_ctxt cx, @ast.expr f,
auto pair_code = bcx.build.GEP(pair_v,
vec(C_int(0),
C_int(abi.fn_field_code)));
+
+ let @ty.t pair_ty = node_ann_type(cx.fcx.ccx, ann);
let ValueRef llthunk =
- trans_bind_thunk(cx.fcx.ccx,
- node_ann_type(cx.fcx.ccx, ann),
- ty.expr_ty(f),
- args,
- llclosure_ty,
- bound_tys);
+ trans_bind_thunk(cx.fcx.ccx, pair_ty, ty.expr_ty(f),
+ args, llclosure_ty, bound_tys);
bcx.build.Store(llthunk, pair_code);
@@ -2163,6 +2207,9 @@ impure fn trans_bind(@block_ctxt cx, @ast.expr f,
T_opaque_closure_ptr()),
pair_box);
+ find_scope_cx(cx).cleanups +=
+ clean(bind drop_slot(_, pair_v, pair_ty));
+
ret res(bcx, pair_v);
}
}