@@ -546,18 +546,18 @@ fn make_generic_glue_inner(ccx: @crate_ctxt, t: ty::t,
546
546
let fcx = new_fn_ctxt ( ccx, ~[ ] , llfn, none) ;
547
547
lib:: llvm:: SetLinkage ( llfn, lib:: llvm:: InternalLinkage ) ;
548
548
ccx. stats . n_glues_created += 1 u;
549
- // Any nontrivial glue is with values passed *by alias*; this is a
549
+ // All glue functions take values passed *by alias*; this is a
550
550
// requirement since in many contexts glue is invoked indirectly and
551
551
// the caller has no idea if it's dealing with something that can be
552
552
// passed by value.
553
-
554
- let llty = T_ptr ( type_of ( ccx, t) ) ;
553
+ //
554
+ // llfn is expected be declared to take a parameter of the appropriate
555
+ // type, so we don't need to explicitly cast the function parameter.
555
556
556
557
let bcx = top_scope_block ( fcx, none) ;
557
558
let lltop = bcx. llbb ;
558
559
let llrawptr0 = llvm:: LLVMGetParam ( llfn, 3 u as c_uint ) ;
559
- let llval0 = BitCast ( bcx, llrawptr0, llty) ;
560
- helper ( bcx, llval0, t) ;
560
+ helper ( bcx, llrawptr0, t) ;
561
561
finish_fn ( fcx, lltop) ;
562
562
return llfn;
563
563
}
@@ -581,28 +581,44 @@ fn make_generic_glue(ccx: @crate_ctxt, t: ty::t, llfn: ValueRef,
581
581
fn emit_tydescs(ccx: @crate_ctxt) {
582
582
let _icx = ccx.insn_ctxt(~" emit_tydescs") ;
583
583
for ccx. tydescs. each |key, val| {
584
- let glue_fn_ty = T_ptr ( T_glue_fn ( ccx) ) ;
584
+ let glue_fn_ty = T_ptr ( T_generic_glue_fn ( ccx) ) ;
585
585
let ti = val;
586
586
587
+ // Each of the glue functions needs to be cast to a generic type
588
+ // before being put into the tydesc because we only have a singleton
589
+ // tydesc type. Then we'll recast each function to its real type when
590
+ // calling it.
587
591
let take_glue =
588
592
match copy ti. take_glue {
589
593
none => { ccx. stats . n_null_glues += 1 u; C_null ( glue_fn_ty) }
590
- some( v) => { ccx. stats . n_real_glues += 1 u; v }
594
+ some( v) => {
595
+ ccx. stats . n_real_glues += 1 u;
596
+ llvm:: LLVMConstPointerCast ( v, glue_fn_ty)
597
+ }
591
598
} ;
592
599
let drop_glue =
593
600
match copy ti. drop_glue {
594
601
none => { ccx. stats . n_null_glues += 1 u; C_null ( glue_fn_ty) }
595
- some( v) => { ccx. stats . n_real_glues += 1 u; v }
602
+ some( v) => {
603
+ ccx. stats . n_real_glues += 1 u;
604
+ llvm:: LLVMConstPointerCast ( v, glue_fn_ty)
605
+ }
596
606
} ;
597
607
let free_glue =
598
608
match copy ti. free_glue {
599
609
none => { ccx. stats . n_null_glues += 1 u; C_null ( glue_fn_ty) }
600
- some( v) => { ccx. stats . n_real_glues += 1 u; v }
610
+ some( v) => {
611
+ ccx. stats . n_real_glues += 1 u;
612
+ llvm:: LLVMConstPointerCast ( v, glue_fn_ty)
613
+ }
601
614
} ;
602
615
let visit_glue =
603
616
match copy ti. visit_glue {
604
617
none => { ccx. stats . n_null_glues += 1 u; C_null ( glue_fn_ty) }
605
- some( v) => { ccx. stats . n_real_glues += 1 u; v }
618
+ some( v) => {
619
+ ccx. stats . n_real_glues += 1 u;
620
+ llvm:: LLVMConstPointerCast ( v, glue_fn_ty)
621
+ }
606
622
} ;
607
623
608
624
let shape = shape_of ( ccx, key) ;
@@ -692,20 +708,20 @@ fn make_visit_glue(bcx: block, v: ValueRef, t: ty::t) {
692
708
693
709
694
710
fn make_free_glue ( bcx : block , v : ValueRef , t : ty:: t ) {
695
- // v is a pointer to the actual box component of the type here. The
696
- // ValueRef will have the wrong type here (make_generic_glue is casting
697
- // everything to a pointer to the type that the glue acts on).
711
+ // NB: v0 is an *alias* of type t here, not a direct value.
698
712
let _icx = bcx. insn_ctxt ( ~"make_free_glue") ;
699
713
let ccx = bcx. ccx ( ) ;
700
714
let bcx = match ty:: get ( t) . struct {
701
715
ty:: ty_box( body_mt) => {
702
- let v = PointerCast ( bcx, v, type_of ( ccx , t ) ) ;
716
+ let v = Load ( bcx, v) ;
703
717
let body = GEPi ( bcx, v, ~[ 0 u, abi:: box_field_body] ) ;
718
+ // Cast away the addrspace of the box pointer.
719
+ let body = PointerCast ( bcx, body, T_ptr ( type_of ( ccx, body_mt. ty ) ) ) ;
704
720
let bcx = drop_ty ( bcx, body, body_mt. ty ) ;
705
721
trans_free ( bcx, v)
706
722
}
707
723
ty:: ty_opaque_box => {
708
- let v = PointerCast ( bcx, v, type_of ( ccx , t ) ) ;
724
+ let v = Load ( bcx, v) ;
709
725
let td = Load ( bcx, GEPi ( bcx, v, ~[ 0 u, abi:: box_field_tydesc] ) ) ;
710
726
let valptr = GEPi ( bcx, v, ~[ 0 u, abi:: box_field_body] ) ;
711
727
// Generate code that, dynamically, indexes into the
@@ -715,7 +731,6 @@ fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) {
715
731
trans_free ( bcx, v)
716
732
}
717
733
ty:: ty_uniq( content_mt) => {
718
- let v = PointerCast ( bcx, v, type_of ( ccx, t) ) ;
719
734
uniq:: make_free_glue ( bcx, v, t)
720
735
}
721
736
ty:: ty_evec( _, ty:: vstore_uniq) | ty:: ty_estr( ty:: vstore_uniq) |
@@ -785,7 +800,7 @@ fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
785
800
}
786
801
ty:: ty_uniq( _) |
787
802
ty:: ty_evec( _, ty:: vstore_uniq) | ty:: ty_estr( ty:: vstore_uniq) => {
788
- free_ty ( bcx, Load ( bcx , v0 ) , t)
803
+ free_ty ( bcx, v0 , t)
789
804
}
790
805
ty:: ty_unboxed_vec( _) => {
791
806
tvec:: make_drop_glue_unboxed ( bcx, v0, t)
@@ -861,14 +876,12 @@ fn decr_refcnt_maybe_free(bcx: block, box_ptr: ValueRef, t: ty::t) -> block {
861
876
let ccx = bcx. ccx ( ) ;
862
877
maybe_validate_box ( bcx, box_ptr) ;
863
878
864
- let llbox_ty = T_opaque_box_ptr ( ccx) ;
865
- let box_ptr = PointerCast ( bcx, box_ptr, llbox_ty) ;
866
879
do with_cond( bcx, IsNotNull ( bcx, box_ptr) ) |bcx| {
867
880
let rc_ptr = GEPi ( bcx, box_ptr, ~[ 0 u, abi:: box_field_refcnt] ) ;
868
881
let rc = Sub ( bcx, Load ( bcx, rc_ptr) , C_int ( ccx, 1 ) ) ;
869
882
Store ( bcx, rc, rc_ptr) ;
870
883
let zero_test = ICmp ( bcx, lib:: llvm:: IntEQ , C_int ( ccx, 0 ) , rc) ;
871
- with_cond ( bcx, zero_test, |bcx| free_ty ( bcx, box_ptr, t) )
884
+ with_cond ( bcx, zero_test, |bcx| free_ty_immediate ( bcx, box_ptr, t) )
872
885
}
873
886
}
874
887
@@ -1097,17 +1110,16 @@ fn lazily_emit_all_tydesc_glue(ccx: @crate_ctxt,
1097
1110
fn lazily_emit_tydesc_glue( ccx: @crate_ctxt, field: uint,
1098
1111
ti: @tydesc_info) {
1099
1112
let _icx = ccx. insn_ctxt( ~"lazily_emit_tydesc_glue") ;
1113
+ let llfnty = type_of_glue_fn( ccx, ti. ty) ;
1100
1114
if field == abi:: tydesc_field_take_glue {
1101
1115
match ti. take_glue {
1102
1116
some( _) => ( ) ,
1103
1117
none => {
1104
1118
debug ! { "+++ lazily_emit_tydesc_glue TAKE %s" ,
1105
1119
ppaux:: ty_to_str( ccx. tcx, ti. ty) } ;
1106
- let glue_fn = declare_generic_glue
1107
- ( ccx, ti. ty , T_glue_fn ( ccx) , ~"take") ;
1120
+ let glue_fn = declare_generic_glue ( ccx, ti. ty , llfnty, ~"take") ;
1108
1121
ti. take_glue = some ( glue_fn) ;
1109
- make_generic_glue ( ccx, ti. ty , glue_fn,
1110
- make_take_glue, ~"take") ;
1122
+ make_generic_glue ( ccx, ti. ty , glue_fn, make_take_glue, ~"take") ;
1111
1123
debug ! { "--- lazily_emit_tydesc_glue TAKE %s" ,
1112
1124
ppaux:: ty_to_str( ccx. tcx, ti. ty) } ;
1113
1125
}
@@ -1118,11 +1130,9 @@ fn lazily_emit_tydesc_glue(ccx: @crate_ctxt, field: uint,
1118
1130
none => {
1119
1131
debug ! { "+++ lazily_emit_tydesc_glue DROP %s" ,
1120
1132
ppaux:: ty_to_str( ccx. tcx, ti. ty) } ;
1121
- let glue_fn =
1122
- declare_generic_glue ( ccx, ti. ty , T_glue_fn ( ccx) , ~"drop") ;
1133
+ let glue_fn = declare_generic_glue ( ccx, ti. ty , llfnty, ~"drop") ;
1123
1134
ti. drop_glue = some ( glue_fn) ;
1124
- make_generic_glue ( ccx, ti. ty , glue_fn,
1125
- make_drop_glue, ~"drop") ;
1135
+ make_generic_glue ( ccx, ti. ty , glue_fn, make_drop_glue, ~"drop") ;
1126
1136
debug ! { "--- lazily_emit_tydesc_glue DROP %s" ,
1127
1137
ppaux:: ty_to_str( ccx. tcx, ti. ty) } ;
1128
1138
}
@@ -1133,11 +1143,9 @@ fn lazily_emit_tydesc_glue(ccx: @crate_ctxt, field: uint,
1133
1143
none => {
1134
1144
debug ! { "+++ lazily_emit_tydesc_glue FREE %s" ,
1135
1145
ppaux:: ty_to_str( ccx. tcx, ti. ty) } ;
1136
- let glue_fn =
1137
- declare_generic_glue ( ccx, ti. ty , T_glue_fn ( ccx) , ~"free") ;
1146
+ let glue_fn = declare_generic_glue ( ccx, ti. ty , llfnty, ~"free") ;
1138
1147
ti. free_glue = some ( glue_fn) ;
1139
- make_generic_glue ( ccx, ti. ty , glue_fn,
1140
- make_free_glue, ~"free") ;
1148
+ make_generic_glue ( ccx, ti. ty , glue_fn, make_free_glue, ~"free") ;
1141
1149
debug ! { "--- lazily_emit_tydesc_glue FREE %s" ,
1142
1150
ppaux:: ty_to_str( ccx. tcx, ti. ty) } ;
1143
1151
}
@@ -1148,11 +1156,9 @@ fn lazily_emit_tydesc_glue(ccx: @crate_ctxt, field: uint,
1148
1156
none => {
1149
1157
debug ! { "+++ lazily_emit_tydesc_glue VISIT %s" ,
1150
1158
ppaux:: ty_to_str( ccx. tcx, ti. ty) } ;
1151
- let glue_fn =
1152
- declare_generic_glue ( ccx, ti. ty , T_glue_fn ( ccx) , ~"visit") ;
1159
+ let glue_fn = declare_generic_glue ( ccx, ti. ty , llfnty, ~"visit") ;
1153
1160
ti. visit_glue = some ( glue_fn) ;
1154
- make_generic_glue ( ccx, ti. ty , glue_fn,
1155
- make_visit_glue, ~"visit") ;
1161
+ make_generic_glue ( ccx, ti. ty , glue_fn, make_visit_glue, ~"visit") ;
1156
1162
debug ! { "--- lazily_emit_tydesc_glue VISIT %s" ,
1157
1163
ppaux:: ty_to_str( ccx. tcx, ti. ty) } ;
1158
1164
}
@@ -1161,43 +1167,63 @@ fn lazily_emit_tydesc_glue(ccx: @crate_ctxt, field: uint,
1161
1167
}
1162
1168
1163
1169
// See [Note-arg-mode]
1164
- fn call_tydesc_glue_full ( ++cx : block , v : ValueRef , tydesc : ValueRef ,
1170
+ fn call_tydesc_glue_full ( ++bcx : block , v : ValueRef , tydesc : ValueRef ,
1165
1171
field : uint , static_ti : option < @tydesc_info > ) {
1166
- let _icx = cx. insn_ctxt ( ~"call_tydesc_glue_full") ;
1167
- if cx. unreachable { return ; }
1172
+ let _icx = bcx. insn_ctxt ( ~"call_tydesc_glue_full") ;
1173
+ if bcx. unreachable { return ; }
1174
+ let ccx = bcx. ccx ( ) ;
1168
1175
1169
- let mut static_glue_fn = none;
1170
- match static_ti {
1171
- none => { /* no-op */ }
1176
+ let static_glue_fn = match static_ti {
1177
+ none => none,
1172
1178
some( sti) => {
1173
- lazily_emit_tydesc_glue ( cx . ccx ( ) , field, sti) ;
1179
+ lazily_emit_tydesc_glue ( ccx, field, sti) ;
1174
1180
if field == abi:: tydesc_field_take_glue {
1175
- static_glue_fn = sti. take_glue ;
1181
+ sti. take_glue
1176
1182
} else if field == abi:: tydesc_field_drop_glue {
1177
- static_glue_fn = sti. drop_glue ;
1183
+ sti. drop_glue
1178
1184
} else if field == abi:: tydesc_field_free_glue {
1179
- static_glue_fn = sti. free_glue ;
1185
+ sti. free_glue
1180
1186
} else if field == abi:: tydesc_field_visit_glue {
1181
- static_glue_fn = sti. visit_glue ;
1187
+ sti. visit_glue
1188
+ } else {
1189
+ none
1182
1190
}
1183
1191
}
1184
- }
1192
+ } ;
1193
+
1194
+ // When available, use static type info to give glue the right type.
1195
+ let static_glue_fn = match static_ti {
1196
+ none => none,
1197
+ some( sti) => {
1198
+ match static_glue_fn {
1199
+ none => none,
1200
+ some( sgf) => some (
1201
+ PointerCast ( bcx, sgf, T_ptr ( type_of_glue_fn ( ccx, sti. ty ) ) ) )
1202
+ }
1203
+ }
1204
+ } ;
1185
1205
1186
- let llrawptr = PointerCast ( cx, v, T_ptr ( T_i8 ( ) ) ) ;
1206
+ // When static type info is available, avoid casting parameter because the
1207
+ // function already has the right type. Otherwise cast to generic pointer.
1208
+ let llrawptr = if is_none ( static_ti) || is_none ( static_glue_fn) {
1209
+ PointerCast ( bcx, v, T_ptr ( T_i8 ( ) ) )
1210
+ } else {
1211
+ v
1212
+ } ;
1187
1213
1188
1214
let llfn = {
1189
1215
match static_glue_fn {
1190
1216
none => {
1191
1217
// Select out the glue function to call from the tydesc
1192
- let llfnptr = GEPi ( cx , tydesc, ~[ 0 u, field] ) ;
1193
- Load ( cx , llfnptr)
1218
+ let llfnptr = GEPi ( bcx , tydesc, ~[ 0 u, field] ) ;
1219
+ Load ( bcx , llfnptr)
1194
1220
}
1195
1221
some( sgf) => sgf
1196
1222
}
1197
1223
} ;
1198
1224
1199
- Call ( cx , llfn, ~[ C_null ( T_ptr ( T_nil ( ) ) ) , C_null ( T_ptr ( T_nil ( ) ) ) ,
1200
- C_null ( T_ptr ( T_ptr ( cx . ccx ( ) . tydesc_type ) ) ) , llrawptr] ) ;
1225
+ Call ( bcx , llfn, ~[ C_null ( T_ptr ( T_nil ( ) ) ) , C_null ( T_ptr ( T_nil ( ) ) ) ,
1226
+ C_null ( T_ptr ( T_ptr ( bcx . ccx ( ) . tydesc_type ) ) ) , llrawptr] ) ;
1201
1227
}
1202
1228
1203
1229
// See [Note-arg-mode]
@@ -1231,6 +1257,7 @@ fn call_cmp_glue(bcx: block, lhs: ValueRef, rhs: ValueRef, t: ty::t,
1231
1257
}
1232
1258
1233
1259
fn take_ty ( cx : block , v : ValueRef , t : ty:: t ) -> block {
1260
+ // NB: v is an *alias* of type t here, not a direct value.
1234
1261
let _icx = cx. insn_ctxt ( ~"take_ty") ;
1235
1262
if ty:: type_needs_drop ( cx. tcx ( ) , t) {
1236
1263
return call_tydesc_glue ( cx, v, t, abi:: tydesc_field_take_glue) ;
@@ -1239,6 +1266,7 @@ fn take_ty(cx: block, v: ValueRef, t: ty::t) -> block {
1239
1266
}
1240
1267
1241
1268
fn drop_ty ( cx : block , v : ValueRef , t : ty:: t ) -> block {
1269
+ // NB: v is an *alias* of type t here, not a direct value.
1242
1270
let _icx = cx. insn_ctxt ( ~"drop_ty") ;
1243
1271
if ty:: type_needs_drop ( cx. tcx ( ) , t) {
1244
1272
return call_tydesc_glue ( cx, v, t, abi:: tydesc_field_drop_glue) ;
@@ -1252,7 +1280,7 @@ fn drop_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> block {
1252
1280
ty:: ty_uniq( _) |
1253
1281
ty:: ty_evec( _, ty:: vstore_uniq) |
1254
1282
ty:: ty_estr( ty:: vstore_uniq) => {
1255
- free_ty ( bcx, v, t)
1283
+ free_ty_immediate ( bcx, v, t)
1256
1284
}
1257
1285
ty:: ty_box( _) | ty:: ty_opaque_box |
1258
1286
ty:: ty_evec( _, ty:: vstore_box) |
@@ -1284,13 +1312,32 @@ fn take_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> result {
1284
1312
}
1285
1313
1286
1314
fn free_ty ( cx : block , v : ValueRef , t : ty:: t ) -> block {
1315
+ // NB: v is an *alias* of type t here, not a direct value.
1287
1316
let _icx = cx. insn_ctxt ( ~"free_ty") ;
1288
1317
if ty:: type_needs_drop ( cx. tcx ( ) , t) {
1289
1318
return call_tydesc_glue ( cx, v, t, abi:: tydesc_field_free_glue) ;
1290
1319
}
1291
1320
return cx;
1292
1321
}
1293
1322
1323
+ fn free_ty_immediate ( bcx : block , v : ValueRef , t : ty:: t ) -> block {
1324
+ let _icx = bcx. insn_ctxt ( ~"free_ty_immediate") ;
1325
+ match ty:: get ( t) . struct {
1326
+ ty:: ty_uniq( _) |
1327
+ ty:: ty_evec( _, ty:: vstore_uniq) |
1328
+ ty:: ty_estr( ty:: vstore_uniq) |
1329
+ ty:: ty_box( _) | ty:: ty_opaque_box |
1330
+ ty:: ty_evec( _, ty:: vstore_box) |
1331
+ ty:: ty_estr( ty:: vstore_box) |
1332
+ ty:: ty_opaque_closure_ptr( _) => {
1333
+ let vp = alloca_zeroed ( bcx, type_of ( bcx. ccx ( ) , t) ) ;
1334
+ Store ( bcx, v, vp) ;
1335
+ free_ty ( bcx, vp, t)
1336
+ }
1337
+ _ => bcx. tcx ( ) . sess . bug ( ~"free_ty_immediate: non-box ty")
1338
+ }
1339
+ }
1340
+
1294
1341
fn call_memmove ( cx : block , dst : ValueRef , src : ValueRef ,
1295
1342
n_bytes : ValueRef ) {
1296
1343
// FIXME (Related to #1645, I think?): Provide LLVM with better
0 commit comments