Skip to content

Commit b145a46

Browse files
committed
---
yaml --- r: 1207 b: refs/heads/master c: 3c61793 h: refs/heads/master i: 1205: e8bb871 1203: 53088a8 1199: 434a7bc v: v3
1 parent 078ce96 commit b145a46

File tree

2 files changed

+171
-31
lines changed

2 files changed

+171
-31
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: a9994a29634cc8d1ce330bdbb41fb1941c41f778
2+
refs/heads/master: 3c61793b5aeef3ab3e8fe876fb94dd9c8c4410c6

trunk/src/comp/middle/trans.rs

Lines changed: 170 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ state type crate_ctxt = rec(session.session sess,
7777

7878
state type fn_ctxt = rec(ValueRef llfn,
7979
ValueRef lltaskptr,
80+
ValueRef llclosure,
8081
mutable option.t[ValueRef] llself,
8182
mutable option.t[ValueRef] llretptr,
8283
hashmap[ast.def_id, ValueRef] llargs,
@@ -197,7 +198,7 @@ fn T_fn(vec[TypeRef] inputs, TypeRef output) -> TypeRef {
197198

198199
fn T_fn_pair(TypeRef tfn) -> TypeRef {
199200
ret T_struct(vec(T_ptr(tfn),
200-
T_ptr(T_box(T_nil()))));
201+
T_opaque_closure_ptr()));
201202
}
202203

203204
fn T_ptr(TypeRef t) -> TypeRef {
@@ -287,6 +288,20 @@ fn T_taskptr() -> TypeRef {
287288
ret T_ptr(T_task());
288289
}
289290

291+
fn T_closure_ptr(TypeRef lltarget_ty,
292+
TypeRef llbindings_ty) -> TypeRef {
293+
ret T_ptr(T_box(T_struct(vec(T_ptr(T_tydesc()),
294+
lltarget_ty,
295+
llbindings_ty)
296+
// FIXME: add captured typarams.
297+
)));
298+
}
299+
300+
fn T_opaque_closure_ptr() -> TypeRef {
301+
ret T_ptr(T_box(T_nil()));
302+
}
303+
304+
290305
fn type_of(@crate_ctxt cx, @ty.t t) -> TypeRef {
291306
let TypeRef llty = type_of_inner(cx, t);
292307
check (llty as int != 0);
@@ -313,7 +328,9 @@ fn type_of_fn_full(@crate_ctxt cx,
313328
check (t as int != 0);
314329
atys += t;
315330
}
316-
case (_) { }
331+
case (_) {
332+
atys += T_opaque_closure_ptr();
333+
}
317334
}
318335

319336
if (ty.type_has_dynamic_size(output)) {
@@ -1880,7 +1897,8 @@ impure fn trans_cast(@block_ctxt cx, @ast.expr e, &ast.ann ann) -> result {
18801897
}
18811898

18821899

1883-
impure fn trans_args(@block_ctxt cx, option.t[ValueRef] llobj,
1900+
impure fn trans_args(@block_ctxt cx, ValueRef llclosure,
1901+
option.t[ValueRef] llobj,
18841902
&vec[@ast.expr] es, @ty.t fn_ty)
18851903
-> tup(@block_ctxt, vec[ValueRef]) {
18861904
let vec[ValueRef] vs = vec(cx.fcx.lltaskptr);
@@ -1899,7 +1917,9 @@ impure fn trans_args(@block_ctxt cx, option.t[ValueRef] llobj,
18991917
// doted method-call).
19001918
vs += cx.build.Load(ob);
19011919
}
1902-
case (_) { }
1920+
case (_) {
1921+
vs += llclosure;
1922+
}
19031923
}
19041924

19051925
auto i = 0u;
@@ -1948,6 +1968,95 @@ impure fn trans_args(@block_ctxt cx, option.t[ValueRef] llobj,
19481968
ret tup(bcx, vs);
19491969
}
19501970

1971+
impure fn trans_bind_thunk(@crate_ctxt cx,
1972+
@ty.t incoming_fty,
1973+
@ty.t outgoing_fty,
1974+
vec[option.t[@ast.expr]] args,
1975+
TypeRef llclosure_ty,
1976+
vec[@ty.t] bound_tys) -> ValueRef {
1977+
// Construct a thunk-call with signature incoming_fty, and that copies
1978+
// args forward into a call to outgoing_fty.
1979+
1980+
let str s = cx.names.next("_rust_thunk") + "." + cx.path;
1981+
let TypeRef llthunk_ty = get_pair_fn_ty(type_of(cx, incoming_fty));
1982+
let ValueRef llthunk = decl_fastcall_fn(cx.llmod, s, llthunk_ty);
1983+
1984+
let @ty.t rty = ret_ty_of_fn_ty(incoming_fty);
1985+
1986+
// FIXME: handle ty params properly.
1987+
let vec[ast.ty_param] ty_params = vec();
1988+
1989+
auto fcx = new_fn_ctxt(cx, s, llthunk);
1990+
auto bcx = new_top_block_ctxt(fcx);
1991+
1992+
auto llclosure = bcx.build.PointerCast(fcx.llclosure, llclosure_ty);
1993+
1994+
auto llbody = bcx.build.GEP(llclosure,
1995+
vec(C_int(0),
1996+
C_int(abi.box_rc_field_body)));
1997+
1998+
auto lltarget = bcx.build.GEP(llbody,
1999+
vec(C_int(0),
2000+
C_int(abi.closure_elt_target)));
2001+
2002+
auto llbound = bcx.build.GEP(llbody,
2003+
vec(C_int(0),
2004+
C_int(abi.closure_elt_bindings)));
2005+
2006+
auto lltargetclosure = bcx.build.GEP(lltarget,
2007+
vec(C_int(0),
2008+
C_int(abi.fn_field_box)));
2009+
lltargetclosure = bcx.build.Load(lltargetclosure);
2010+
let vec[ValueRef] llargs = vec(fcx.lltaskptr,
2011+
lltargetclosure);
2012+
let uint a = 0u;
2013+
let int b = 0;
2014+
for (option.t[@ast.expr] arg in args) {
2015+
alt (arg) {
2016+
2017+
// Arg provided at binding time; thunk copies it from closure.
2018+
case (some[@ast.expr](_)) {
2019+
let ValueRef bound_arg = bcx.build.GEP(llbound,
2020+
vec(C_int(0),
2021+
C_int(b)));
2022+
// FIXME: possibly support passing aliases someday.
2023+
llargs += bcx.build.Load(bound_arg);
2024+
b += 1;
2025+
}
2026+
2027+
// Arg will be provided when the thunk is invoked.
2028+
case (none[@ast.expr]) {
2029+
let ValueRef passed_arg = llvm.LLVMGetParam(llthunk, a);
2030+
llargs += passed_arg;
2031+
a += 1u;
2032+
}
2033+
}
2034+
}
2035+
2036+
// FIXME: turn this call + ret into a tail call.
2037+
auto lltargetfn = bcx.build.GEP(lltarget,
2038+
vec(C_int(0),
2039+
C_int(abi.fn_field_code)));
2040+
lltargetfn = bcx.build.Load(lltargetfn);
2041+
auto r = bcx.build.FastCall(lltargetfn, llargs);
2042+
2043+
alt (fcx.llretptr) {
2044+
case (some[ValueRef](?llptr)) {
2045+
bcx.build.Store(bcx.build.Load(r), llptr);
2046+
bcx.build.RetVoid();
2047+
}
2048+
case (none[ValueRef]) {
2049+
if (ty.type_is_nil(rty)) {
2050+
bcx.build.RetVoid();
2051+
} else {
2052+
bcx.build.Ret(r);
2053+
}
2054+
}
2055+
}
2056+
2057+
ret llthunk;
2058+
}
2059+
19512060
impure fn trans_bind(@block_ctxt cx, @ast.expr f,
19522061
vec[option.t[@ast.expr]] args,
19532062
&ast.ann ann) -> result {
@@ -1974,10 +2083,6 @@ impure fn trans_bind(@block_ctxt cx, @ast.expr f,
19742083
auto pair_t = node_type(cx.fcx.ccx, ann);
19752084
auto pair_v = bcx.build.Alloca(pair_t);
19762085

1977-
auto pair_box = bcx.build.GEP(pair_v,
1978-
vec(C_int(0),
1979-
C_int(abi.fn_field_box)));
1980-
19812086
// Translate the bound expressions.
19822087
let vec[@ty.t] bound_tys = vec();
19832088
let vec[ValueRef] bound_vals = vec();
@@ -1990,14 +2095,10 @@ impure fn trans_bind(@block_ctxt cx, @ast.expr f,
19902095

19912096
// Synthesize a closure type.
19922097
let @ty.t bindings_ty = ty.plain_ty(ty.ty_tup(bound_tys));
2098+
let TypeRef lltarget_ty = type_of(bcx.fcx.ccx, ty.expr_ty(f));
19932099
let TypeRef llbindings_ty = type_of(bcx.fcx.ccx, bindings_ty);
1994-
let TypeRef llclosure_ty =
1995-
T_ptr(T_box(T_struct(vec(T_ptr(T_tydesc()),
1996-
type_of(bcx.fcx.ccx,
1997-
ty.expr_ty(f)),
1998-
llbindings_ty)
1999-
// FIXME: add captured typarams.
2000-
)));
2100+
let TypeRef llclosure_ty = T_closure_ptr(lltarget_ty,
2101+
llbindings_ty);
20012102

20022103
// Malloc a box for the body.
20032104
auto r = trans_malloc_inner(bcx, llclosure_ty);
@@ -2040,10 +2141,27 @@ impure fn trans_bind(@block_ctxt cx, @ast.expr f,
20402141
i += 1;
20412142
}
20422143

2043-
// Store box ptr in outer pair.
2044-
let TypeRef llbox_ty = T_ptr(T_box(T_nil()));
2045-
auto p = r.bcx.build.PointerCast(box, llbox_ty);
2046-
bcx.build.Store(p, pair_box);
2144+
// Make thunk and store thunk-ptr in outer pair's code slot.
2145+
auto pair_code = bcx.build.GEP(pair_v,
2146+
vec(C_int(0),
2147+
C_int(abi.fn_field_code)));
2148+
let ValueRef llthunk =
2149+
trans_bind_thunk(cx.fcx.ccx,
2150+
node_ann_type(cx.fcx.ccx, ann),
2151+
ty.expr_ty(f),
2152+
args,
2153+
llclosure_ty,
2154+
bound_tys);
2155+
2156+
bcx.build.Store(llthunk, pair_code);
2157+
2158+
// Store box ptr in outer pair's box slot.
2159+
auto pair_box = bcx.build.GEP(pair_v,
2160+
vec(C_int(0),
2161+
C_int(abi.fn_field_box)));
2162+
bcx.build.Store(bcx.build.PointerCast(box,
2163+
T_opaque_closure_ptr()),
2164+
pair_box);
20472165

20482166
ret res(bcx, pair_v);
20492167
}
@@ -2054,6 +2172,7 @@ impure fn trans_call(@block_ctxt cx, @ast.expr f,
20542172
vec[@ast.expr] args, &ast.ann ann) -> result {
20552173
auto f_res = trans_lval(cx, f);
20562174
auto faddr = f_res.res.val;
2175+
auto llclosure = C_null(T_opaque_closure_ptr());
20572176

20582177
alt (f_res.llobj) {
20592178
case (some[ValueRef](_)) {
@@ -2063,14 +2182,20 @@ impure fn trans_call(@block_ctxt cx, @ast.expr f,
20632182
case (none[ValueRef]) {
20642183
// It's a closure.
20652184
auto bcx = f_res.res.bcx;
2066-
faddr = bcx.build.GEP(faddr, vec(C_int(0),
2185+
auto pair = faddr;
2186+
faddr = bcx.build.GEP(pair, vec(C_int(0),
20672187
C_int(abi.fn_field_code)));
20682188
faddr = bcx.build.Load(faddr);
2189+
2190+
llclosure = bcx.build.GEP(pair, vec(C_int(0),
2191+
C_int(abi.fn_field_box)));
2192+
llclosure = bcx.build.Load(llclosure);
20692193
}
20702194
}
20712195
auto fn_ty = ty.expr_ty(f);
20722196
auto ret_ty = ty.ann_to_type(ann);
2073-
auto args_res = trans_args(f_res.res.bcx, f_res.llobj, args, fn_ty);
2197+
auto args_res = trans_args(f_res.res.bcx, llclosure, f_res.llobj,
2198+
args, fn_ty);
20742199

20752200
auto real_retval = args_res._0.build.FastCall(faddr, args_res._1);
20762201
auto retval;
@@ -2569,6 +2694,7 @@ fn new_fn_ctxt(@crate_ctxt cx,
25692694
ValueRef llfndecl) -> @fn_ctxt {
25702695

25712696
let ValueRef lltaskptr = llvm.LLVMGetParam(llfndecl, 0u);
2697+
let ValueRef llclosure = llvm.LLVMGetParam(llfndecl, 1u);
25722698

25732699
let hashmap[ast.def_id, ValueRef] llargs = new_def_hash[ValueRef]();
25742700
let hashmap[ast.def_id, ValueRef] llobjfields = new_def_hash[ValueRef]();
@@ -2577,6 +2703,7 @@ fn new_fn_ctxt(@crate_ctxt cx,
25772703

25782704
ret @rec(llfn=llfndecl,
25792705
lltaskptr=lltaskptr,
2706+
llclosure=llclosure,
25802707
mutable llself=none[ValueRef],
25812708
mutable llretptr=none[ValueRef],
25822709
llargs=llargs,
@@ -2608,7 +2735,10 @@ fn create_llargs_for_fn_args(&@fn_ctxt cx,
26082735
cx.llself = some[ValueRef](llself);
26092736
arg_n += 1u;
26102737
}
2611-
case (_) { }
2738+
case (_) {
2739+
// llclosure, we don't know what it is.
2740+
arg_n += 1u;
2741+
}
26122742
}
26132743

26142744
if (ty.type_has_dynamic_size(ret_ty)) {
@@ -2677,15 +2807,20 @@ fn arg_tys_of_fn(ast.ann ann) -> vec[ty.arg] {
26772807
fail;
26782808
}
26792809

2680-
fn ret_ty_of_fn(ast.ann ann) -> @ty.t {
2681-
alt (ty.ann_to_type(ann).struct) {
2810+
fn ret_ty_of_fn_ty(@ty.t t) -> @ty.t {
2811+
alt (t.struct) {
26822812
case (ty.ty_fn(_, ?ret_ty)) {
26832813
ret ret_ty;
26842814
}
26852815
}
26862816
fail;
26872817
}
26882818

2819+
2820+
fn ret_ty_of_fn(ast.ann ann) -> @ty.t {
2821+
ret ret_ty_of_fn_ty(ty.ann_to_type(ann));
2822+
}
2823+
26892824
fn create_llobjfields_for_fields(@block_ctxt cx, ValueRef llself) {
26902825

26912826
let vec[TypeRef] llfield_tys = vec();
@@ -2996,18 +3131,22 @@ impure fn trans_mod(@crate_ctxt cx, &ast._mod m) {
29963131
}
29973132
}
29983133

3134+
fn get_pair_fn_ty(TypeRef llpairty) -> TypeRef {
3135+
// Bit of a kludge: pick the fn typeref out of the pair.
3136+
let vec[TypeRef] pair_tys = vec(T_nil(), T_nil());
3137+
llvm.LLVMGetStructElementTypes(llpairty,
3138+
_vec.buf[TypeRef](pair_tys));
3139+
ret llvm.LLVMGetElementType(pair_tys.(0));
3140+
}
3141+
29993142
fn decl_fn_and_pair(@crate_ctxt cx,
30003143
str kind,
30013144
str name,
30023145
&ast.ann ann,
30033146
ast.def_id id) {
30043147

3005-
// Bit of a kludge: pick the fn typeref out of the pair.
30063148
auto llpairty = node_type(cx, ann);
3007-
let vec[TypeRef] pair_tys = vec(T_nil(), T_nil());
3008-
llvm.LLVMGetStructElementTypes(llpairty,
3009-
_vec.buf[TypeRef](pair_tys));
3010-
auto llfty = llvm.LLVMGetElementType(pair_tys.(0));
3149+
auto llfty = get_pair_fn_ty(llpairty);
30113150

30123151
// Declare the function itself.
30133152
let str s = cx.names.next("_rust_" + kind) + "." + name;
@@ -3018,7 +3157,7 @@ fn decl_fn_and_pair(@crate_ctxt cx,
30183157
let ValueRef gvar = llvm.LLVMAddGlobal(cx.llmod, llpairty,
30193158
_str.buf(ps));
30203159
auto pair = C_struct(vec(llfn,
3021-
C_null(T_ptr(T_box(T_nil())))));
3160+
C_null(T_opaque_closure_ptr())));
30223161

30233162
llvm.LLVMSetInitializer(gvar, pair);
30243163
llvm.LLVMSetGlobalConstant(gvar, True);
@@ -3252,6 +3391,7 @@ fn trans_exit_task_glue(@crate_ctxt cx) {
32523391
let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 0u);
32533392
auto fcx = @rec(llfn=llfn,
32543393
lltaskptr=lltaskptr,
3394+
llclosure=C_null(T_opaque_closure_ptr()),
32553395
mutable llself=none[ValueRef],
32563396
mutable llretptr=none[ValueRef],
32573397
llargs=new_def_hash[ValueRef](),

0 commit comments

Comments
 (0)