Skip to content

Commit 62c79fb

Browse files
committed
Sketch closure-forming logic for nontrivial bindings.
1 parent f3f63da commit 62c79fb

File tree

2 files changed

+79
-4
lines changed

2 files changed

+79
-4
lines changed

src/comp/back/abi.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ const int obj_body_elt_fields = 1;
4949
const int fn_field_code = 0;
5050
const int fn_field_box = 1;
5151

52+
const int closure_elt_tydesc = 0;
53+
const int closure_elt_target = 1;
54+
const int closure_elt_bindings = 2;
55+
const int closure_elt_ty_params = 3;
56+
57+
5258
const int worst_case_glue_call_args = 7;
5359

5460
const int n_upcall_glues = 7;

src/comp/middle/trans.rs

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1955,24 +1955,93 @@ impure fn trans_bind(@block_ctxt cx, @ast.expr f,
19551955
if (f_res.is_mem) {
19561956
cx.fcx.ccx.sess.unimpl("re-binding existing function");
19571957
} else {
1958-
let vec[@ty.t] bound = vec();
1958+
let vec[@ast.expr] bound = vec();
1959+
19591960
for (option.t[@ast.expr] argopt in args) {
19601961
alt (argopt) {
19611962
case (none[@ast.expr]) {
19621963
}
19631964
case (some[@ast.expr](?e)) {
1964-
append[@ty.t](bound, ty.expr_ty(e));
1965+
append[@ast.expr](bound, e);
19651966
}
19661967
}
19671968
}
1968-
if (_vec.len[@ty.t](bound) == 0u) {
1969+
if (_vec.len[@ast.expr](bound) == 0u) {
19691970
// Trivial 'binding': just return the static pair-ptr.
19701971
ret f_res.res;
19711972
} else {
19721973
auto bcx = f_res.res.bcx;
19731974
auto pair_t = node_type(cx.fcx.ccx, ann);
19741975
auto pair_v = bcx.build.Alloca(pair_t);
1975-
cx.fcx.ccx.sess.unimpl("nontrivial binding");
1976+
1977+
auto pair_box = bcx.build.GEP(pair_v,
1978+
vec(C_int(0),
1979+
C_int(abi.fn_field_box)));
1980+
1981+
// Translate the bound expressions.
1982+
let vec[@ty.t] bound_tys = vec();
1983+
let vec[ValueRef] bound_vals = vec();
1984+
for (@ast.expr e in bound) {
1985+
auto arg = trans_expr(bcx, e);
1986+
bcx = arg.bcx;
1987+
append[ValueRef](bound_vals, arg.val);
1988+
append[@ty.t](bound_tys, ty.expr_ty(e));
1989+
}
1990+
1991+
// Synthesize a closure type.
1992+
let @ty.t bindings_ty = ty.plain_ty(ty.ty_tup(bound_tys));
1993+
let TypeRef llbindings_ty = type_of(bcx.fcx.ccx,
1994+
bindings_ty);
1995+
let TypeRef llclosure_ty =
1996+
T_ptr(T_box(T_struct(vec(T_ptr(T_tydesc()),
1997+
type_of(bcx.fcx.ccx,
1998+
ty.expr_ty(f)),
1999+
llbindings_ty)
2000+
// FIXME: add captured typarams.
2001+
)));
2002+
2003+
// Malloc a box for the body.
2004+
auto r = trans_malloc_inner(bcx, llclosure_ty);
2005+
auto box = r.val;
2006+
bcx = r.bcx;
2007+
auto rc = bcx.build.GEP(box,
2008+
vec(C_int(0),
2009+
C_int(abi.box_rc_field_refcnt)));
2010+
auto closure =
2011+
bcx.build.GEP(box,
2012+
vec(C_int(0),
2013+
C_int(abi.box_rc_field_body)));
2014+
bcx.build.Store(C_int(1), rc);
2015+
2016+
2017+
// Store bindings tydesc.
2018+
auto bound_tydesc =
2019+
bcx.build.GEP(closure,
2020+
vec(C_int(0),
2021+
C_int(abi.closure_elt_tydesc)));
2022+
2023+
auto bindings_tydesc = get_tydesc(bcx, bindings_ty);
2024+
bcx.build.Store(bindings_tydesc, bound_tydesc);
2025+
2026+
// Copy args into body fields.
2027+
auto bindings =
2028+
bcx.build.GEP(closure,
2029+
vec(C_int(0),
2030+
C_int(abi.closure_elt_bindings)));
2031+
2032+
let int i = 0;
2033+
for (ValueRef v in bound_vals) {
2034+
auto bound = bcx.build.GEP(bindings,
2035+
vec(C_int(0),C_int(i)));
2036+
bcx = copy_ty(r.bcx, true, bound, v, bound_tys.(i)).bcx;
2037+
i += 1;
2038+
}
2039+
2040+
// Store box ptr in outer pair.
2041+
let TypeRef llbox_ty = T_ptr(T_box(T_nil()));
2042+
auto p = r.bcx.build.PointerCast(box, llbox_ty);
2043+
bcx.build.Store(p, pair_box);
2044+
19762045
ret res(bcx, pair_v);
19772046
}
19782047
}

0 commit comments

Comments
 (0)