@@ -77,6 +77,7 @@ state type crate_ctxt = rec(session.session sess,
77
77
78
78
state type fn_ctxt = rec ( ValueRef llfn,
79
79
ValueRef lltaskptr ,
80
+ ValueRef llclosure ,
80
81
mutable option. t[ ValueRef ] llself ,
81
82
mutable option. t[ ValueRef ] llretptr ,
82
83
hashmap[ ast. def_id, ValueRef ] llargs ,
@@ -197,7 +198,7 @@ fn T_fn(vec[TypeRef] inputs, TypeRef output) -> TypeRef {
197
198
198
199
fn T_fn_pair ( TypeRef tfn) -> TypeRef {
199
200
ret T_struct ( vec ( T_ptr ( tfn) ,
200
- T_ptr ( T_box ( T_nil ( ) ) ) ) ) ;
201
+ T_opaque_closure_ptr ( ) ) ) ;
201
202
}
202
203
203
204
fn T_ptr ( TypeRef t) -> TypeRef {
@@ -287,6 +288,20 @@ fn T_taskptr() -> TypeRef {
287
288
ret T_ptr ( T_task ( ) ) ;
288
289
}
289
290
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
+
290
305
fn type_of ( @crate_ctxt cx , @ty. t t ) -> TypeRef {
291
306
let TypeRef llty = type_of_inner ( cx, t) ;
292
307
check ( llty as int != 0 ) ;
@@ -313,7 +328,9 @@ fn type_of_fn_full(@crate_ctxt cx,
313
328
check ( t as int != 0 ) ;
314
329
atys += t;
315
330
}
316
- case ( _) { }
331
+ case ( _) {
332
+ atys += T_opaque_closure_ptr ( ) ;
333
+ }
317
334
}
318
335
319
336
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 {
1880
1897
}
1881
1898
1882
1899
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,
1884
1902
& vec[ @ast. expr] es, @ty. t fn_ty)
1885
1903
-> tup( @block_ctxt, vec[ ValueRef ] ) {
1886
1904
let vec[ ValueRef ] vs = vec( cx. fcx. lltaskptr) ;
@@ -1899,7 +1917,9 @@ impure fn trans_args(@block_ctxt cx, option.t[ValueRef] llobj,
1899
1917
// doted method-call).
1900
1918
vs += cx. build. Load ( ob) ;
1901
1919
}
1902
- case ( _) { }
1920
+ case ( _) {
1921
+ vs += llclosure;
1922
+ }
1903
1923
}
1904
1924
1905
1925
auto i = 0 u;
@@ -1948,6 +1968,95 @@ impure fn trans_args(@block_ctxt cx, option.t[ValueRef] llobj,
1948
1968
ret tup( bcx, vs) ;
1949
1969
}
1950
1970
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 = 0 u;
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 += 1 u;
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
+
1951
2060
impure fn trans_bind( @block_ctxt cx, @ast. expr f,
1952
2061
vec[ option. t[ @ast. expr] ] args,
1953
2062
& ast. ann ann) -> result {
@@ -1974,10 +2083,6 @@ impure fn trans_bind(@block_ctxt cx, @ast.expr f,
1974
2083
auto pair_t = node_type( cx. fcx. ccx, ann) ;
1975
2084
auto pair_v = bcx. build. Alloca( pair_t) ;
1976
2085
1977
- auto pair_box = bcx. build. GEP ( pair_v,
1978
- vec( C_int ( 0 ) ,
1979
- C_int ( abi. fn_field_box) ) ) ;
1980
-
1981
2086
// Translate the bound expressions.
1982
2087
let vec[ @ty. t] bound_tys = vec( ) ;
1983
2088
let vec[ ValueRef ] bound_vals = vec( ) ;
@@ -1990,14 +2095,10 @@ impure fn trans_bind(@block_ctxt cx, @ast.expr f,
1990
2095
1991
2096
// Synthesize a closure type.
1992
2097
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) ) ;
1993
2099
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) ;
2001
2102
2002
2103
// Malloc a box for the body.
2003
2104
auto r = trans_malloc_inner( bcx, llclosure_ty) ;
@@ -2040,10 +2141,27 @@ impure fn trans_bind(@block_ctxt cx, @ast.expr f,
2040
2141
i += 1 ;
2041
2142
}
2042
2143
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) ;
2047
2165
2048
2166
ret res( bcx, pair_v) ;
2049
2167
}
@@ -2054,6 +2172,7 @@ impure fn trans_call(@block_ctxt cx, @ast.expr f,
2054
2172
vec[ @ast. expr] args, & ast. ann ann) -> result {
2055
2173
auto f_res = trans_lval( cx, f) ;
2056
2174
auto faddr = f_res. res. val;
2175
+ auto llclosure = C_null ( T_opaque_closure_ptr ( ) ) ;
2057
2176
2058
2177
alt ( f_res. llobj) {
2059
2178
case ( some[ ValueRef ] ( _) ) {
@@ -2063,14 +2182,20 @@ impure fn trans_call(@block_ctxt cx, @ast.expr f,
2063
2182
case ( none[ ValueRef ] ) {
2064
2183
// It's a closure.
2065
2184
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 ) ,
2067
2187
C_int ( abi. fn_field_code) ) ) ;
2068
2188
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) ;
2069
2193
}
2070
2194
}
2071
2195
auto fn_ty = ty. expr_ty( f) ;
2072
2196
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) ;
2074
2199
2075
2200
auto real_retval = args_res. _0. build. FastCall ( faddr, args_res. _1) ;
2076
2201
auto retval;
@@ -2569,6 +2694,7 @@ fn new_fn_ctxt(@crate_ctxt cx,
2569
2694
ValueRef llfndecl) -> @fn_ctxt {
2570
2695
2571
2696
let ValueRef lltaskptr = llvm. LLVMGetParam ( llfndecl, 0 u) ;
2697
+ let ValueRef llclosure = llvm. LLVMGetParam ( llfndecl, 1 u) ;
2572
2698
2573
2699
let hashmap[ ast. def_id , ValueRef ] llargs = new_def_hash[ ValueRef ] ( ) ;
2574
2700
let hashmap[ ast. def_id , ValueRef ] llobjfields = new_def_hash[ ValueRef ] ( ) ;
@@ -2577,6 +2703,7 @@ fn new_fn_ctxt(@crate_ctxt cx,
2577
2703
2578
2704
ret @rec( llfn=llfndecl,
2579
2705
lltaskptr=lltaskptr,
2706
+ llclosure=llclosure,
2580
2707
mutable llself=none[ ValueRef ] ,
2581
2708
mutable llretptr=none[ ValueRef ] ,
2582
2709
llargs=llargs,
@@ -2608,7 +2735,10 @@ fn create_llargs_for_fn_args(&@fn_ctxt cx,
2608
2735
cx. llself = some[ ValueRef ] ( llself) ;
2609
2736
arg_n += 1 u;
2610
2737
}
2611
- case ( _) { }
2738
+ case ( _) {
2739
+ // llclosure, we don't know what it is.
2740
+ arg_n += 1 u;
2741
+ }
2612
2742
}
2613
2743
2614
2744
if ( ty. type_has_dynamic_size( ret_ty) ) {
@@ -2677,15 +2807,20 @@ fn arg_tys_of_fn(ast.ann ann) -> vec[ty.arg] {
2677
2807
fail;
2678
2808
}
2679
2809
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 ) {
2682
2812
case ( ty. ty_fn ( _, ?ret_ty) ) {
2683
2813
ret ret_ty;
2684
2814
}
2685
2815
}
2686
2816
fail;
2687
2817
}
2688
2818
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
+
2689
2824
fn create_llobjfields_for_fields ( @block_ctxt cx , ValueRef llself) {
2690
2825
2691
2826
let vec[ TypeRef ] llfield_tys = vec ( ) ;
@@ -2996,18 +3131,22 @@ impure fn trans_mod(@crate_ctxt cx, &ast._mod m) {
2996
3131
}
2997
3132
}
2998
3133
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
+
2999
3142
fn decl_fn_and_pair( @crate_ctxt cx,
3000
3143
str kind,
3001
3144
str name,
3002
3145
& ast. ann ann,
3003
3146
ast. def_id id) {
3004
3147
3005
- // Bit of a kludge: pick the fn typeref out of the pair.
3006
3148
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) ;
3011
3150
3012
3151
// Declare the function itself.
3013
3152
let str s = cx. names. next( "_rust_" + kind) + "." + name;
@@ -3018,7 +3157,7 @@ fn decl_fn_and_pair(@crate_ctxt cx,
3018
3157
let ValueRef gvar = llvm. LLVMAddGlobal ( cx. llmod, llpairty,
3019
3158
_str. buf( ps) ) ;
3020
3159
auto pair = C_struct ( vec( llfn,
3021
- C_null ( T_ptr ( T_box ( T_nil ( ) ) ) ) ) ) ;
3160
+ C_null ( T_opaque_closure_ptr ( ) ) ) ) ;
3022
3161
3023
3162
llvm. LLVMSetInitializer ( gvar, pair) ;
3024
3163
llvm. LLVMSetGlobalConstant ( gvar, True ) ;
@@ -3252,6 +3391,7 @@ fn trans_exit_task_glue(@crate_ctxt cx) {
3252
3391
let ValueRef lltaskptr = llvm. LLVMGetParam ( llfn, 0 u) ;
3253
3392
auto fcx = @rec ( llfn=llfn,
3254
3393
lltaskptr=lltaskptr,
3394
+ llclosure=C_null ( T_opaque_closure_ptr ( ) ) ,
3255
3395
mutable llself=none[ ValueRef ] ,
3256
3396
mutable llretptr=none[ ValueRef ] ,
3257
3397
llargs=new_def_hash[ ValueRef ] ( ) ,
0 commit comments