@@ -373,11 +373,12 @@ fn T_typaram_ptr(type_names tn) -> TypeRef {
373
373
374
374
fn T_closure_ptr ( type_names tn,
375
375
TypeRef lltarget_ty ,
376
- TypeRef llbindings_ty ) -> TypeRef {
376
+ TypeRef llbindings_ty ,
377
+ uint n_ty_params ) -> TypeRef {
377
378
ret T_ptr ( T_box ( T_struct ( vec ( T_ptr ( T_tydesc ( tn) ) ,
378
379
lltarget_ty,
379
- llbindings_ty)
380
- // FIXME: add captured typarams.
380
+ llbindings_ty,
381
+ T_captured_tydescs ( tn , n_ty_params ) )
381
382
) ) ) ;
382
383
}
383
384
@@ -388,7 +389,8 @@ fn T_opaque_closure_ptr(type_names tn) -> TypeRef {
388
389
}
389
390
auto t = T_closure_ptr ( tn, T_struct ( vec ( T_ptr ( T_nil ( ) ) ,
390
391
T_ptr ( T_nil ( ) ) ) ) ,
391
- T_nil ( ) ) ;
392
+ T_nil ( ) ,
393
+ 0 u) ;
392
394
tn. associate ( s, t) ;
393
395
ret t;
394
396
}
@@ -2747,17 +2749,15 @@ fn trans_bind_thunk(@crate_ctxt cx,
2747
2749
@ty. t outgoing_fty ,
2748
2750
vec[ option. t[ @ast. expr] ] args ,
2749
2751
TypeRef llclosure_ty ,
2750
- vec[ @ty. t] bound_tys) -> ValueRef {
2752
+ vec[ @ty. t] bound_tys,
2753
+ uint ty_param_count ) -> ValueRef {
2751
2754
// Construct a thunk-call with signature incoming_fty, and that copies
2752
2755
// args forward into a call to outgoing_fty.
2753
2756
2754
2757
let str s = cx. names . next ( "_rust_thunk" ) + sep ( ) + cx. path ;
2755
2758
let TypeRef llthunk_ty = get_pair_fn_ty ( type_of ( cx, incoming_fty) ) ;
2756
2759
let ValueRef llthunk = decl_fastcall_fn ( cx. llmod , s, llthunk_ty) ;
2757
2760
2758
- // FIXME: handle ty params properly.
2759
- let vec[ ast. ty_param ] ty_params = vec ( ) ;
2760
-
2761
2761
auto fcx = new_fn_ctxt ( cx, s, llthunk) ;
2762
2762
auto bcx = new_top_block_ctxt ( fcx) ;
2763
2763
@@ -2779,11 +2779,33 @@ fn trans_bind_thunk(@crate_ctxt cx,
2779
2779
vec ( C_int ( 0 ) ,
2780
2780
C_int ( abi. fn_field_box ) ) ) ;
2781
2781
lltargetclosure = bcx. build . Load ( lltargetclosure) ;
2782
- let vec[ ValueRef ] llargs = vec ( fcx. llretptr ,
2782
+
2783
+ auto outgoing_ret_ty = ty. ty_fn_ret ( outgoing_fty) ;
2784
+ auto outgoing_arg_tys = ty. ty_fn_args ( outgoing_fty) ;
2785
+
2786
+ auto llretptr = fcx. llretptr ;
2787
+ if ( ty. type_has_dynamic_size ( outgoing_ret_ty) ) {
2788
+ llretptr = bcx. build . PointerCast ( llretptr, T_typaram_ptr ( cx. tn ) ) ;
2789
+ }
2790
+
2791
+ let vec[ ValueRef ] llargs = vec ( llretptr,
2783
2792
fcx. lltaskptr ,
2784
2793
lltargetclosure) ;
2785
- let uint a = 0 u;
2794
+
2795
+ // Copy in the type parameters.
2796
+ let uint i = 0 u;
2797
+ while ( i < ty_param_count) {
2798
+ auto lltyparam_ptr =
2799
+ bcx. build . GEP ( llbody, vec ( C_int ( 0 ) ,
2800
+ C_int ( abi. closure_elt_ty_params ) ,
2801
+ C_int ( i as int ) ) ) ;
2802
+ llargs += vec ( bcx. build . Load ( lltyparam_ptr) ) ;
2803
+ i += 1 u;
2804
+ }
2805
+
2806
+ let uint a = 2 u + i; // retptr, task ptr, env come first
2786
2807
let int b = 0 ;
2808
+ let uint outgoing_arg_index = 0 u;
2787
2809
for ( option. t[ @ast. expr] arg in args) {
2788
2810
alt ( arg) {
2789
2811
@@ -2800,17 +2822,27 @@ fn trans_bind_thunk(@crate_ctxt cx,
2800
2822
// Arg will be provided when the thunk is invoked.
2801
2823
case ( none[ @ast. expr] ) {
2802
2824
let ValueRef passed_arg = llvm. LLVMGetParam ( llthunk, a) ;
2825
+ if ( ty. type_has_dynamic_size( outgoing_arg_tys.
2826
+ ( outgoing_arg_index) . ty) ) {
2827
+ // Cast to a generic typaram pointer in order to make a
2828
+ // type-compatible call.
2829
+ passed_arg = bcx. build. PointerCast ( passed_arg,
2830
+ T_typaram_ptr ( cx. tn) ) ;
2831
+ }
2803
2832
llargs += passed_arg;
2804
2833
a += 1 u;
2805
2834
}
2806
2835
}
2836
+
2837
+ outgoing_arg_index += 0 u;
2807
2838
}
2808
2839
2809
2840
// FIXME: turn this call + ret into a tail call.
2810
2841
auto lltargetfn = bcx. build. GEP ( lltarget,
2811
2842
vec( C_int ( 0 ) ,
2812
2843
C_int ( abi. fn_field_code) ) ) ;
2813
2844
lltargetfn = bcx. build. Load ( lltargetfn) ;
2845
+
2814
2846
auto r = bcx. build. FastCall ( lltargetfn, llargs) ;
2815
2847
bcx. build. RetVoid ( ) ;
2816
2848
@@ -2835,7 +2867,23 @@ fn trans_bind(@block_ctxt cx, @ast.expr f,
2835
2867
}
2836
2868
}
2837
2869
}
2838
- if ( _vec. len[ @ast. expr] ( bound) == 0 u) {
2870
+
2871
+ // Figure out which tydescs we need to pass, if any.
2872
+ // FIXME: typestate botch
2873
+ let @ty. t outgoing_fty = ty. plain_ty( ty. ty_nil) ;
2874
+ let vec[ ValueRef ] lltydescs = vec( ) ;
2875
+ alt ( f_res. generic) {
2876
+ case ( none[ generic_info] ) {
2877
+ outgoing_fty = ty. expr_ty( f) ;
2878
+ }
2879
+ case ( some[ generic_info] ( ?ginfo) ) {
2880
+ outgoing_fty = ginfo. item_type;
2881
+ lltydescs = ginfo. tydescs;
2882
+ }
2883
+ }
2884
+ auto ty_param_count = _vec. len[ ValueRef ] ( lltydescs) ;
2885
+
2886
+ if ( _vec. len[ @ast. expr] ( bound) == 0 u && ty_param_count == 0 u) {
2839
2887
// Trivial 'binding': just return the static pair-ptr.
2840
2888
ret f_res. res;
2841
2889
} else {
@@ -2846,20 +2894,27 @@ fn trans_bind(@block_ctxt cx, @ast.expr f,
2846
2894
// Translate the bound expressions.
2847
2895
let vec[ @ty. t] bound_tys = vec( ) ;
2848
2896
let vec[ ValueRef ] bound_vals = vec( ) ;
2897
+ auto i = 0 u;
2849
2898
for ( @ast. expr e in bound) {
2850
2899
auto arg = trans_expr( bcx, e) ;
2851
2900
bcx = arg. bcx;
2901
+
2852
2902
append[ ValueRef ] ( bound_vals, arg. val) ;
2853
2903
append[ @ty. t] ( bound_tys, ty. expr_ty( e) ) ;
2904
+
2905
+ i += 1 u;
2854
2906
}
2855
2907
2908
+ // Get the type of the bound function.
2909
+ let TypeRef lltarget_ty = type_of( bcx. fcx. ccx, outgoing_fty) ;
2910
+
2856
2911
// Synthesize a closure type.
2857
2912
let @ty. t bindings_ty = plain_ty( ty. ty_tup( bound_tys) ) ;
2858
- let TypeRef lltarget_ty = type_of( bcx. fcx. ccx, ty. expr_ty( f) ) ;
2859
2913
let TypeRef llbindings_ty = type_of( bcx. fcx. ccx, bindings_ty) ;
2860
2914
let TypeRef llclosure_ty = T_closure_ptr ( cx. fcx. ccx. tn,
2861
2915
lltarget_ty,
2862
- llbindings_ty) ;
2916
+ llbindings_ty,
2917
+ ty_param_count) ;
2863
2918
2864
2919
// Malloc a box for the body.
2865
2920
auto r = trans_malloc_inner( bcx, llclosure_ty) ;
@@ -2888,19 +2943,40 @@ fn trans_bind(@block_ctxt cx, @ast.expr f,
2888
2943
bcx. build. GEP ( closure,
2889
2944
vec( C_int ( 0 ) ,
2890
2945
C_int ( abi. closure_elt_target) ) ) ;
2891
- bcx. build. Store ( bcx. build. Load ( f_res. res. val) , bound_target) ;
2946
+ auto src = bcx. build. Load ( f_res. res. val) ;
2947
+ bcx. build. Store ( src, bound_target) ;
2892
2948
2893
2949
// Copy expr values into boxed bindings.
2894
- let int i = 0 ;
2950
+ i = 0 u ;
2895
2951
auto bindings =
2896
2952
bcx. build. GEP ( closure,
2897
2953
vec( C_int ( 0 ) ,
2898
2954
C_int ( abi. closure_elt_bindings) ) ) ;
2899
2955
for ( ValueRef v in bound_vals) {
2900
2956
auto bound = bcx. build. GEP ( bindings,
2901
- vec( C_int ( 0 ) , C_int ( i) ) ) ;
2957
+ vec( C_int ( 0 ) , C_int ( i as int ) ) ) ;
2902
2958
bcx = copy_ty( r. bcx, INIT , bound, v, bound_tys. ( i) ) . bcx;
2903
- i += 1 ;
2959
+ i += 1 u;
2960
+ }
2961
+
2962
+ // If necessary, copy tydescs describing type parameters into the
2963
+ // appropriate slot in the closure.
2964
+ alt ( f_res. generic) {
2965
+ case ( none[ generic_info] ) { /* nothing to do */ }
2966
+ case ( some[ generic_info] ( ?ginfo) ) {
2967
+ auto ty_params_slot =
2968
+ bcx. build. GEP ( closure,
2969
+ vec( C_int ( 0 ) ,
2970
+ C_int ( abi. closure_elt_ty_params) ) ) ;
2971
+ auto i = 0 ;
2972
+ for ( ValueRef td in ginfo. tydescs) {
2973
+ auto ty_param_slot = bcx. build. GEP ( ty_params_slot,
2974
+ vec( C_int ( 0 ) ,
2975
+ C_int ( i) ) ) ;
2976
+ bcx. build. Store ( td, ty_param_slot) ;
2977
+ i += 1 ;
2978
+ }
2979
+ }
2904
2980
}
2905
2981
2906
2982
// Make thunk and store thunk-ptr in outer pair's code slot.
@@ -2910,8 +2986,9 @@ fn trans_bind(@block_ctxt cx, @ast.expr f,
2910
2986
2911
2987
let @ty. t pair_ty = node_ann_type( cx. fcx. ccx, ann) ;
2912
2988
let ValueRef llthunk =
2913
- trans_bind_thunk( cx. fcx. ccx, pair_ty, ty. expr_ty( f) ,
2914
- args, llclosure_ty, bound_tys) ;
2989
+ trans_bind_thunk( cx. fcx. ccx, pair_ty, outgoing_fty,
2990
+ args, llclosure_ty, bound_tys,
2991
+ ty_param_count) ;
2915
2992
2916
2993
bcx. build. Store ( llthunk, pair_code) ;
2917
2994
0 commit comments