@@ -884,7 +884,7 @@ fn trans_malloc_boxed(cx: &@block_ctxt, t: ty::t) ->
884
884
fn field_of_tydesc ( cx : & @block_ctxt , t : ty:: t , escapes : bool , field : int ) ->
885
885
result {
886
886
let ti = none :: < @tydesc_info > ;
887
- let tydesc = get_tydesc ( cx, t, escapes, ti) . result ;
887
+ let tydesc = get_tydesc ( cx, t, escapes, tps_normal , ti) . result ;
888
888
ret rslt( tydesc. bcx ,
889
889
bld:: GEP ( tydesc. bcx , tydesc. val , [ C_int ( 0 ) , C_int ( field) ] ) ) ;
890
890
}
@@ -919,16 +919,16 @@ fn linearize_ty_params(cx: &@block_ctxt, t: ty::t) ->
919
919
920
920
fn trans_stack_local_derived_tydesc ( cx : & @block_ctxt , llsz : ValueRef ,
921
921
llalign : ValueRef , llroottydesc : ValueRef ,
922
- llparamtydescs : ValueRef , n_params : uint )
922
+ llfirstparam : ValueRef , n_params : uint ,
923
+ obj_params : uint )
923
924
-> ValueRef {
924
925
let llmyroottydesc = alloca ( cx, bcx_ccx ( cx) . tydesc_type ) ;
925
- // By convention, desc 0 is the root descriptor.
926
926
927
+ // By convention, desc 0 is the root descriptor.
927
928
llroottydesc = bld:: Load ( cx, llroottydesc) ;
928
929
bld:: Store ( cx, llroottydesc, llmyroottydesc) ;
929
- // Store a pointer to the rest of the descriptors.
930
930
931
- let llfirstparam = bld :: GEP ( cx , llparamtydescs , [ C_int ( 0 ) , C_int ( 0 ) ] ) ;
931
+ // Store a pointer to the rest of the descriptors.
932
932
store_inbounds ( cx, llfirstparam, llmyroottydesc,
933
933
[ C_int ( 0 ) , C_int ( abi:: tydesc_field_first_param) ] ) ;
934
934
store_inbounds ( cx, C_uint ( n_params) , llmyroottydesc,
@@ -937,10 +937,20 @@ fn trans_stack_local_derived_tydesc(cx: &@block_ctxt, llsz: ValueRef,
937
937
[ C_int ( 0 ) , C_int ( abi:: tydesc_field_size) ] ) ;
938
938
store_inbounds ( cx, llalign, llmyroottydesc,
939
939
[ C_int ( 0 ) , C_int ( abi:: tydesc_field_align) ] ) ;
940
+ store_inbounds ( cx, C_uint ( obj_params) , llmyroottydesc,
941
+ [ C_int ( 0 ) , C_int ( abi:: tydesc_field_obj_params) ] ) ;
940
942
ret llmyroottydesc;
941
943
}
942
944
945
+ // Objects store their type parameters differently (in the object itself
946
+ // rather than in the type descriptor).
947
+ tag ty_param_storage {
948
+ tps_normal;
949
+ tps_obj ( uint) ;
950
+ }
951
+
943
952
fn get_derived_tydesc ( cx : & @block_ctxt , t : ty:: t , escapes : bool ,
953
+ storage : ty_param_storage ,
944
954
static_ti : & mutable option:: t < @tydesc_info > ) -> result {
945
955
alt cx. fcx . derived_tydescs . find ( t) {
946
956
some ( info) {
@@ -954,10 +964,7 @@ fn get_derived_tydesc(cx: &@block_ctxt, t: ty::t, escapes: bool,
954
964
}
955
965
bcx_ccx ( cx) . stats . n_derived_tydescs += 1 u;
956
966
let bcx = new_raw_block_ctxt ( cx. fcx , cx. fcx . llderivedtydescs ) ;
957
- let n_params: uint = ty:: count_ty_params ( bcx_tcx ( bcx) , t) ;
958
967
let tys = linearize_ty_params ( bcx, t) ;
959
- assert ( n_params == std:: vec:: len :: < uint > ( tys. params ) ) ;
960
- assert ( n_params == std:: vec:: len :: < ValueRef > ( tys. descs ) ) ;
961
968
let root_ti = get_static_tydesc ( bcx, t, tys. params ) ;
962
969
static_ti = some :: < @tydesc_info > ( root_ti) ;
963
970
lazily_emit_all_tydesc_glue ( cx, static_ti) ;
@@ -966,43 +973,52 @@ fn get_derived_tydesc(cx: &@block_ctxt, t: ty::t, escapes: bool,
966
973
bcx = sz. bcx ;
967
974
let align = align_of ( bcx, t) ;
968
975
bcx = align. bcx ;
969
- let v;
976
+
977
+ // Store the captured type descriptors in an alloca if the caller isn't
978
+ // promising to do so itself.
979
+ let n_params = ty:: count_ty_params ( bcx_tcx ( bcx) , t) ;
980
+
981
+ assert ( n_params == std:: vec:: len :: < uint > ( tys. params ) ) ;
982
+ assert ( n_params == std:: vec:: len :: < ValueRef > ( tys. descs ) ) ;
983
+
984
+ let llparamtydescs =
985
+ alloca ( bcx, T_array ( T_ptr ( bcx_ccx ( bcx) . tydesc_type ) , n_params + 1 u) ) ;
986
+ let i = 0 ;
987
+
988
+ // If the type descriptor escapes, we need to add in the root as
989
+ // the first parameter, because upcall_get_type_desc() expects it.
970
990
if escapes {
971
- /* for root*/
972
- let tydescs =
973
- alloca ( bcx,
974
- T_array ( T_ptr ( bcx_ccx ( bcx) . tydesc_type ) , 1 u + n_params) ) ;
975
- let i = 0 ;
976
- let tdp = bld:: GEP ( bcx, tydescs, [ C_int ( 0 ) , C_int ( i) ] ) ;
977
- bld:: Store ( bcx, root, tdp) ;
991
+ bld:: Store ( bcx, root, GEPi ( bcx, llparamtydescs, [ 0 , 0 ] ) ) ;
978
992
i += 1 ;
979
- for td: ValueRef in tys. descs {
980
- let tdp = bld:: GEP ( bcx, tydescs, [ C_int ( 0 ) , C_int ( i) ] ) ;
981
- bld:: Store ( bcx, td, tdp) ;
982
- i += 1 ;
983
- }
984
- let lltydescsptr =
985
- bld:: PointerCast ( bcx, tydescs,
986
- T_ptr ( T_ptr ( bcx_ccx ( bcx) . tydesc_type ) ) ) ;
993
+ }
994
+
995
+ for td: ValueRef in tys. descs {
996
+ bld:: Store ( bcx, td, GEPi ( bcx, llparamtydescs, [ 0 , i] ) ) ;
997
+ i += 1 ;
998
+ }
999
+
1000
+ let llfirstparam =
1001
+ bld:: PointerCast ( bcx, llparamtydescs,
1002
+ T_ptr ( T_ptr ( bcx_ccx ( bcx) . tydesc_type ) ) ) ;
1003
+
1004
+ let obj_params;
1005
+ alt storage {
1006
+ tps_normal. { obj_params = 0 u; }
1007
+ tps_obj ( np) { obj_params = np; }
1008
+ }
1009
+
1010
+ let v;
1011
+ if escapes {
987
1012
let td_val =
988
1013
bld:: Call ( bcx, bcx_ccx ( bcx) . upcalls . get_type_desc ,
989
1014
[ bcx. fcx . lltaskptr , C_null ( T_ptr ( T_nil ( ) ) ) , sz. val ,
990
- align. val , C_int ( 1 u + n_params as int ) ,
991
- lltydescsptr ] ) ;
1015
+ align. val , C_uint ( 1 u + n_params) ,
1016
+ llfirstparam , C_uint ( obj_params ) ] ) ;
992
1017
v = td_val;
993
1018
} else {
994
- let llparamtydescs =
995
- alloca ( bcx,
996
- T_array ( T_ptr ( bcx_ccx ( bcx) . tydesc_type ) , n_params + 1 u) ) ;
997
- let i = 0 ;
998
- for td: ValueRef in tys. descs {
999
- let tdp = bld:: GEP ( bcx, llparamtydescs, [ C_int ( 0 ) , C_int ( i) ] ) ;
1000
- bld:: Store ( bcx, td, tdp) ;
1001
- i += 1 ;
1002
- }
1003
- v =
1004
- trans_stack_local_derived_tydesc ( bcx, sz. val , align. val , root,
1005
- llparamtydescs, n_params) ;
1019
+ v = trans_stack_local_derived_tydesc ( bcx, sz. val , align. val , root,
1020
+ llfirstparam, n_params,
1021
+ obj_params) ;
1006
1022
}
1007
1023
bcx. fcx . derived_tydescs . insert ( t, { lltydesc: v, escapes: escapes} ) ;
1008
1024
ret rslt( cx, v) ;
@@ -1011,6 +1027,7 @@ fn get_derived_tydesc(cx: &@block_ctxt, t: ty::t, escapes: bool,
1011
1027
type get_tydesc_result = { kind: tydesc_kind, result: result} ;
1012
1028
1013
1029
fn get_tydesc ( cx : & @block_ctxt , orig_t : ty:: t , escapes : bool ,
1030
+ storage : ty_param_storage ,
1014
1031
static_ti : & mutable option:: t < @tydesc_info > ) ->
1015
1032
get_tydesc_result {
1016
1033
@@ -1036,7 +1053,7 @@ fn get_tydesc(cx: &@block_ctxt, orig_t: ty::t, escapes: bool,
1036
1053
// Does it contain a type param? If so, generate a derived tydesc.
1037
1054
if ty:: type_contains_params ( bcx_tcx ( cx) , t) {
1038
1055
ret { kind : tk_derived,
1039
- result : get_derived_tydesc ( cx, t, escapes, static_ti) } ;
1056
+ result : get_derived_tydesc ( cx, t, escapes, storage , static_ti) } ;
1040
1057
}
1041
1058
1042
1059
// Otherwise, generate a tydesc if necessary, and return it.
@@ -1264,7 +1281,8 @@ fn emit_tydescs(ccx: &@crate_ctxt) {
1264
1281
cmp_glue, // cmp_glue
1265
1282
C_shape ( ccx, shape) , // shape
1266
1283
shape_tables, // shape_tables
1267
- C_int ( 0 ) ] ) ; // n_params
1284
+ C_int ( 0 ) , // n_params
1285
+ C_int ( 0 ) ] ) ; // n_obj_params
1268
1286
1269
1287
let gvar = ti. tydesc ;
1270
1288
llvm:: LLVMSetInitializer ( gvar, tydesc) ;
@@ -1483,7 +1501,7 @@ fn trans_res_drop(cx: @block_ctxt, rs: ValueRef, did: &ast::def_id,
1483
1501
let args = [ cx. fcx . llretptr , cx. fcx . lltaskptr , dtor_env] ;
1484
1502
for tp: ty:: t in tps {
1485
1503
let ti: option:: t < @tydesc_info > = none;
1486
- let td = get_tydesc ( cx, tp, false , ti) . result ;
1504
+ let td = get_tydesc ( cx, tp, false , tps_normal , ti) . result ;
1487
1505
args += [ td. val ] ;
1488
1506
cx = td. bcx ;
1489
1507
}
@@ -2143,7 +2161,7 @@ fn call_tydesc_glue_full(cx: &@block_ctxt, v: ValueRef, tydesc: ValueRef,
2143
2161
fn call_tydesc_glue ( cx : & @block_ctxt , v : ValueRef , t : ty:: t , field : int ) ->
2144
2162
result {
2145
2163
let ti: option:: t < @tydesc_info > = none :: < @tydesc_info > ;
2146
- let td = get_tydesc ( cx, t, false , ti) . result ;
2164
+ let td = get_tydesc ( cx, t, false , tps_normal , ti) . result ;
2147
2165
call_tydesc_glue_full ( td. bcx , spill_if_immediate ( td. bcx , v, t) , td. val ,
2148
2166
field, ti) ;
2149
2167
ret rslt( td. bcx , C_nil ( ) ) ;
@@ -2159,7 +2177,7 @@ fn call_cmp_glue(cx: &@block_ctxt, lhs: ValueRef, rhs: ValueRef, t: ty::t,
2159
2177
let llrawlhsptr = bld:: BitCast ( cx, lllhs, T_ptr ( T_i8 ( ) ) ) ;
2160
2178
let llrawrhsptr = bld:: BitCast ( cx, llrhs, T_ptr ( T_i8 ( ) ) ) ;
2161
2179
let ti = none :: < @tydesc_info > ;
2162
- let r = get_tydesc ( cx, t, false , ti) . result ;
2180
+ let r = get_tydesc ( cx, t, false , tps_normal , ti) . result ;
2163
2181
lazily_emit_tydesc_glue ( cx, abi:: tydesc_field_cmp_glue, ti) ;
2164
2182
let lltydesc = r. val ;
2165
2183
let lltydescs =
@@ -2194,7 +2212,8 @@ fn call_copy_glue(cx: &@block_ctxt, dst: ValueRef, src: ValueRef, t: ty::t,
2194
2212
let srcptr = bld:: BitCast ( cx, src, T_ptr ( T_i8 ( ) ) ) ;
2195
2213
let dstptr = bld:: BitCast ( cx, dst, T_ptr ( T_i8 ( ) ) ) ;
2196
2214
let ti = none;
2197
- let { bcx, val: lltydesc } = get_tydesc ( cx, t, false , ti) . result ;
2215
+ let { bcx, val: lltydesc } =
2216
+ get_tydesc ( cx, t, false , tps_normal, ti) . result ;
2198
2217
lazily_emit_tydesc_glue ( cx, abi:: tydesc_field_copy_glue, ti) ;
2199
2218
let lltydescs = bld:: GEP
2200
2219
( bcx, lltydesc, [ C_int ( 0 ) , C_int ( abi:: tydesc_field_first_param) ] ) ;
@@ -2594,10 +2613,10 @@ fn trans_evec_append(cx: &@block_ctxt, t: ty::t, lhs: ValueRef,
2594
2613
}
2595
2614
let bcx = cx;
2596
2615
let ti = none :: < @tydesc_info > ;
2597
- let llvec_tydesc = get_tydesc ( bcx, t, false , ti) . result ;
2616
+ let llvec_tydesc = get_tydesc ( bcx, t, false , tps_normal , ti) . result ;
2598
2617
bcx = llvec_tydesc. bcx ;
2599
2618
ti = none :: < @tydesc_info > ;
2600
- let llelt_tydesc = get_tydesc ( bcx, elt_ty, false , ti) . result ;
2619
+ let llelt_tydesc = get_tydesc ( bcx, elt_ty, false , tps_normal , ti) . result ;
2601
2620
lazily_emit_tydesc_glue ( cx, abi:: tydesc_field_take_glue, ti) ;
2602
2621
lazily_emit_tydesc_glue ( cx, abi:: tydesc_field_drop_glue, ti) ;
2603
2622
lazily_emit_tydesc_glue ( cx, abi:: tydesc_field_free_glue, ti) ;
@@ -2956,7 +2975,8 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
2956
2975
if copying {
2957
2976
let bound_tydesc = GEPi ( bcx, closure, [ 0 , abi:: closure_elt_tydesc] ) ;
2958
2977
let ti = none;
2959
- let bindings_tydesc = get_tydesc ( bcx, bindings_ty, true , ti) . result ;
2978
+ let bindings_tydesc =
2979
+ get_tydesc ( bcx, bindings_ty, true , tps_normal, ti) . result ;
2960
2980
lazily_emit_tydesc_glue ( bcx, abi:: tydesc_field_drop_glue, ti) ;
2961
2981
lazily_emit_tydesc_glue ( bcx, abi:: tydesc_field_free_glue, ti) ;
2962
2982
bcx = bindings_tydesc. bcx ;
@@ -3273,7 +3293,7 @@ fn lval_generic_fn(cx: &@block_ctxt, tpt: &ty::ty_param_kinds_and_ty,
3273
3293
// TODO: Doesn't always escape.
3274
3294
3275
3295
let ti = none :: < @tydesc_info > ;
3276
- let td = get_tydesc ( bcx, t, true , ti) . result ;
3296
+ let td = get_tydesc ( bcx, t, true , tps_normal , ti) . result ;
3277
3297
tis += [ ti] ;
3278
3298
bcx = td. bcx ;
3279
3299
tydescs += [ td. val ] ;
@@ -4526,7 +4546,7 @@ fn trans_log(lvl: int, cx: &@block_ctxt, e: &@ast::expr) -> result {
4526
4546
let log_bcx = sub. bcx ;
4527
4547
4528
4548
let ti = none :: < @tydesc_info > ;
4529
- let r = get_tydesc ( log_bcx, e_ty, false , ti) . result ;
4549
+ let r = get_tydesc ( log_bcx, e_ty, false , tps_normal , ti) . result ;
4530
4550
log_bcx = r. bcx ;
4531
4551
4532
4552
// Call the polymorphic log function.
0 commit comments