@@ -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
}
@@ -587,22 +587,34 @@ fn emit_tydescs(ccx: @crate_ctxt) {
587
587
let take_glue =
588
588
match copy ti. take_glue {
589
589
none => { ccx. stats . n_null_glues += 1 u; C_null ( glue_fn_ty) }
590
- some( v) => { ccx. stats . n_real_glues += 1 u; v }
590
+ some( v) => {
591
+ ccx. stats . n_real_glues += 1 u;
592
+ llvm:: LLVMConstPointerCast ( v, glue_fn_ty)
593
+ }
591
594
} ;
592
595
let drop_glue =
593
596
match copy ti. drop_glue {
594
597
none => { ccx. stats . n_null_glues += 1 u; C_null ( glue_fn_ty) }
595
- some( v) => { ccx. stats . n_real_glues += 1 u; v }
598
+ some( v) => {
599
+ ccx. stats . n_real_glues += 1 u;
600
+ llvm:: LLVMConstPointerCast ( v, glue_fn_ty)
601
+ }
596
602
} ;
597
603
let free_glue =
598
604
match copy ti. free_glue {
599
605
none => { ccx. stats . n_null_glues += 1 u; C_null ( glue_fn_ty) }
600
- some( v) => { ccx. stats . n_real_glues += 1 u; v }
606
+ some( v) => {
607
+ ccx. stats . n_real_glues += 1 u;
608
+ llvm:: LLVMConstPointerCast ( v, glue_fn_ty)
609
+ }
601
610
} ;
602
611
let visit_glue =
603
612
match copy ti. visit_glue {
604
613
none => { ccx. stats . n_null_glues += 1 u; C_null ( glue_fn_ty) }
605
- some( v) => { ccx. stats . n_real_glues += 1 u; v }
614
+ some( v) => {
615
+ ccx. stats . n_real_glues += 1 u;
616
+ llvm:: LLVMConstPointerCast ( v, glue_fn_ty)
617
+ }
606
618
} ;
607
619
608
620
let shape = shape_of ( ccx, key) ;
@@ -692,20 +704,20 @@ fn make_visit_glue(bcx: block, v: ValueRef, t: ty::t) {
692
704
693
705
694
706
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).
707
+ // NB: v0 is an *alias* of type t here, not a direct value.
698
708
let _icx = bcx. insn_ctxt ( ~"make_free_glue") ;
699
709
let ccx = bcx. ccx ( ) ;
700
710
let bcx = match ty:: get ( t) . struct {
701
711
ty:: ty_box( body_mt) => {
702
- let v = PointerCast ( bcx, v, type_of ( ccx , t ) ) ;
712
+ let v = Load ( bcx, v) ;
703
713
let body = GEPi ( bcx, v, ~[ 0 u, abi:: box_field_body] ) ;
714
+ // Cast away the addrspace of the box pointer.
715
+ let body = PointerCast ( bcx, body, T_ptr ( type_of ( ccx, body_mt. ty ) ) ) ;
704
716
let bcx = drop_ty ( bcx, body, body_mt. ty ) ;
705
717
trans_free ( bcx, v)
706
718
}
707
719
ty:: ty_opaque_box => {
708
- let v = PointerCast ( bcx, v, type_of ( ccx , t ) ) ;
720
+ let v = Load ( bcx, v) ;
709
721
let td = Load ( bcx, GEPi ( bcx, v, ~[ 0 u, abi:: box_field_tydesc] ) ) ;
710
722
let valptr = GEPi ( bcx, v, ~[ 0 u, abi:: box_field_body] ) ;
711
723
// Generate code that, dynamically, indexes into the
@@ -715,7 +727,6 @@ fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) {
715
727
trans_free ( bcx, v)
716
728
}
717
729
ty:: ty_uniq( content_mt) => {
718
- let v = PointerCast ( bcx, v, type_of ( ccx, t) ) ;
719
730
uniq:: make_free_glue ( bcx, v, t)
720
731
}
721
732
ty:: ty_evec( _, ty:: vstore_uniq) | ty:: ty_estr( ty:: vstore_uniq) |
@@ -785,7 +796,7 @@ fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
785
796
}
786
797
ty:: ty_uniq( _) |
787
798
ty:: ty_evec( _, ty:: vstore_uniq) | ty:: ty_estr( ty:: vstore_uniq) => {
788
- free_ty ( bcx, Load ( bcx , v0 ) , t)
799
+ free_ty ( bcx, v0 , t)
789
800
}
790
801
ty:: ty_unboxed_vec( _) => {
791
802
tvec:: make_drop_glue_unboxed ( bcx, v0, t)
@@ -861,14 +872,12 @@ fn decr_refcnt_maybe_free(bcx: block, box_ptr: ValueRef, t: ty::t) -> block {
861
872
let ccx = bcx. ccx ( ) ;
862
873
maybe_validate_box ( bcx, box_ptr) ;
863
874
864
- let llbox_ty = T_opaque_box_ptr ( ccx) ;
865
- let box_ptr = PointerCast ( bcx, box_ptr, llbox_ty) ;
866
875
do with_cond( bcx, IsNotNull ( bcx, box_ptr) ) |bcx| {
867
876
let rc_ptr = GEPi ( bcx, box_ptr, ~[ 0 u, abi:: box_field_refcnt] ) ;
868
877
let rc = Sub ( bcx, Load ( bcx, rc_ptr) , C_int ( ccx, 1 ) ) ;
869
878
Store ( bcx, rc, rc_ptr) ;
870
879
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) )
880
+ with_cond ( bcx, zero_test, |bcx| free_ty_immediate ( bcx, box_ptr, t) )
872
881
}
873
882
}
874
883
@@ -1097,17 +1106,16 @@ fn lazily_emit_all_tydesc_glue(ccx: @crate_ctxt,
1097
1106
fn lazily_emit_tydesc_glue( ccx: @crate_ctxt, field: uint,
1098
1107
ti: @tydesc_info) {
1099
1108
let _icx = ccx. insn_ctxt( ~"lazily_emit_tydesc_glue") ;
1109
+ let llfnty = type_of_glue_fn( ccx, ti. ty) ;
1100
1110
if field == abi:: tydesc_field_take_glue {
1101
1111
match ti. take_glue {
1102
1112
some( _) => ( ) ,
1103
1113
none => {
1104
1114
debug ! { "+++ lazily_emit_tydesc_glue TAKE %s" ,
1105
1115
ppaux:: ty_to_str( ccx. tcx, ti. ty) } ;
1106
- let glue_fn = declare_generic_glue
1107
- ( ccx, ti. ty , T_glue_fn ( ccx) , ~"take") ;
1116
+ let glue_fn = declare_generic_glue ( ccx, ti. ty , llfnty, ~"take") ;
1108
1117
ti. take_glue = some ( glue_fn) ;
1109
- make_generic_glue ( ccx, ti. ty , glue_fn,
1110
- make_take_glue, ~"take") ;
1118
+ make_generic_glue ( ccx, ti. ty , glue_fn, make_take_glue, ~"take") ;
1111
1119
debug ! { "--- lazily_emit_tydesc_glue TAKE %s" ,
1112
1120
ppaux:: ty_to_str( ccx. tcx, ti. ty) } ;
1113
1121
}
@@ -1118,11 +1126,9 @@ fn lazily_emit_tydesc_glue(ccx: @crate_ctxt, field: uint,
1118
1126
none => {
1119
1127
debug ! { "+++ lazily_emit_tydesc_glue DROP %s" ,
1120
1128
ppaux:: ty_to_str( ccx. tcx, ti. ty) } ;
1121
- let glue_fn =
1122
- declare_generic_glue ( ccx, ti. ty , T_glue_fn ( ccx) , ~"drop") ;
1129
+ let glue_fn = declare_generic_glue ( ccx, ti. ty , llfnty, ~"drop") ;
1123
1130
ti. drop_glue = some ( glue_fn) ;
1124
- make_generic_glue ( ccx, ti. ty , glue_fn,
1125
- make_drop_glue, ~"drop") ;
1131
+ make_generic_glue ( ccx, ti. ty , glue_fn, make_drop_glue, ~"drop") ;
1126
1132
debug ! { "--- lazily_emit_tydesc_glue DROP %s" ,
1127
1133
ppaux:: ty_to_str( ccx. tcx, ti. ty) } ;
1128
1134
}
@@ -1133,11 +1139,9 @@ fn lazily_emit_tydesc_glue(ccx: @crate_ctxt, field: uint,
1133
1139
none => {
1134
1140
debug ! { "+++ lazily_emit_tydesc_glue FREE %s" ,
1135
1141
ppaux:: ty_to_str( ccx. tcx, ti. ty) } ;
1136
- let glue_fn =
1137
- declare_generic_glue ( ccx, ti. ty , T_glue_fn ( ccx) , ~"free") ;
1142
+ let glue_fn = declare_generic_glue ( ccx, ti. ty , llfnty, ~"free") ;
1138
1143
ti. free_glue = some ( glue_fn) ;
1139
- make_generic_glue ( ccx, ti. ty , glue_fn,
1140
- make_free_glue, ~"free") ;
1144
+ make_generic_glue ( ccx, ti. ty , glue_fn, make_free_glue, ~"free") ;
1141
1145
debug ! { "--- lazily_emit_tydesc_glue FREE %s" ,
1142
1146
ppaux:: ty_to_str( ccx. tcx, ti. ty) } ;
1143
1147
}
@@ -1148,11 +1152,9 @@ fn lazily_emit_tydesc_glue(ccx: @crate_ctxt, field: uint,
1148
1152
none => {
1149
1153
debug ! { "+++ lazily_emit_tydesc_glue VISIT %s" ,
1150
1154
ppaux:: ty_to_str( ccx. tcx, ti. ty) } ;
1151
- let glue_fn =
1152
- declare_generic_glue ( ccx, ti. ty , T_glue_fn ( ccx) , ~"visit") ;
1155
+ let glue_fn = declare_generic_glue ( ccx, ti. ty , llfnty, ~"visit") ;
1153
1156
ti. visit_glue = some ( glue_fn) ;
1154
- make_generic_glue ( ccx, ti. ty , glue_fn,
1155
- make_visit_glue, ~"visit") ;
1157
+ make_generic_glue ( ccx, ti. ty , glue_fn, make_visit_glue, ~"visit") ;
1156
1158
debug ! { "--- lazily_emit_tydesc_glue VISIT %s" ,
1157
1159
ppaux:: ty_to_str( ccx. tcx, ti. ty) } ;
1158
1160
}
@@ -1161,43 +1163,63 @@ fn lazily_emit_tydesc_glue(ccx: @crate_ctxt, field: uint,
1161
1163
}
1162
1164
1163
1165
// See [Note-arg-mode]
1164
- fn call_tydesc_glue_full ( ++cx : block , v : ValueRef , tydesc : ValueRef ,
1166
+ fn call_tydesc_glue_full ( ++bcx : block , v : ValueRef , tydesc : ValueRef ,
1165
1167
field : uint , static_ti : option < @tydesc_info > ) {
1166
- let _icx = cx. insn_ctxt ( ~"call_tydesc_glue_full") ;
1167
- if cx. unreachable { return ; }
1168
+ let _icx = bcx. insn_ctxt ( ~"call_tydesc_glue_full") ;
1169
+ if bcx. unreachable { return ; }
1170
+ let ccx = bcx. ccx ( ) ;
1168
1171
1169
- let mut static_glue_fn = none;
1170
- match static_ti {
1171
- none => { /* no-op */ }
1172
+ let static_glue_fn = match static_ti {
1173
+ none => none,
1172
1174
some( sti) => {
1173
- lazily_emit_tydesc_glue ( cx . ccx ( ) , field, sti) ;
1175
+ lazily_emit_tydesc_glue ( ccx, field, sti) ;
1174
1176
if field == abi:: tydesc_field_take_glue {
1175
- static_glue_fn = sti. take_glue ;
1177
+ sti. take_glue
1176
1178
} else if field == abi:: tydesc_field_drop_glue {
1177
- static_glue_fn = sti. drop_glue ;
1179
+ sti. drop_glue
1178
1180
} else if field == abi:: tydesc_field_free_glue {
1179
- static_glue_fn = sti. free_glue ;
1181
+ sti. free_glue
1180
1182
} else if field == abi:: tydesc_field_visit_glue {
1181
- static_glue_fn = sti. visit_glue ;
1183
+ sti. visit_glue
1184
+ } else {
1185
+ none
1182
1186
}
1183
1187
}
1184
- }
1188
+ } ;
1189
+
1190
+ // When available, use static type info to give glue the right type.
1191
+ let static_glue_fn = match static_ti {
1192
+ none => none,
1193
+ some( sti) => {
1194
+ match static_glue_fn {
1195
+ none => none,
1196
+ some( sgf) => some (
1197
+ PointerCast ( bcx, sgf, T_ptr ( type_of_glue_fn ( ccx, sti. ty ) ) ) )
1198
+ }
1199
+ }
1200
+ } ;
1185
1201
1186
- let llrawptr = PointerCast ( cx, v, T_ptr ( T_i8 ( ) ) ) ;
1202
+ // When static type info is available, avoid casting parameter because the
1203
+ // function already has the right type. Otherwise cast to generic pointer.
1204
+ let llrawptr = if is_none ( static_ti) || is_none ( static_glue_fn) {
1205
+ PointerCast ( bcx, v, T_ptr ( T_i8 ( ) ) )
1206
+ } else {
1207
+ v
1208
+ } ;
1187
1209
1188
1210
let llfn = {
1189
1211
match static_glue_fn {
1190
1212
none => {
1191
1213
// Select out the glue function to call from the tydesc
1192
- let llfnptr = GEPi ( cx , tydesc, ~[ 0 u, field] ) ;
1193
- Load ( cx , llfnptr)
1214
+ let llfnptr = GEPi ( bcx , tydesc, ~[ 0 u, field] ) ;
1215
+ Load ( bcx , llfnptr)
1194
1216
}
1195
1217
some( sgf) => sgf
1196
1218
}
1197
1219
} ;
1198
1220
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] ) ;
1221
+ Call ( bcx , llfn, ~[ C_null ( T_ptr ( T_nil ( ) ) ) , C_null ( T_ptr ( T_nil ( ) ) ) ,
1222
+ C_null ( T_ptr ( T_ptr ( bcx . ccx ( ) . tydesc_type ) ) ) , llrawptr] ) ;
1201
1223
}
1202
1224
1203
1225
// See [Note-arg-mode]
@@ -1231,6 +1253,7 @@ fn call_cmp_glue(bcx: block, lhs: ValueRef, rhs: ValueRef, t: ty::t,
1231
1253
}
1232
1254
1233
1255
fn take_ty ( cx : block , v : ValueRef , t : ty:: t ) -> block {
1256
+ // NB: v is an *alias* of type t here, not a direct value.
1234
1257
let _icx = cx. insn_ctxt ( ~"take_ty") ;
1235
1258
if ty:: type_needs_drop ( cx. tcx ( ) , t) {
1236
1259
return call_tydesc_glue ( cx, v, t, abi:: tydesc_field_take_glue) ;
@@ -1239,6 +1262,7 @@ fn take_ty(cx: block, v: ValueRef, t: ty::t) -> block {
1239
1262
}
1240
1263
1241
1264
fn drop_ty ( cx : block , v : ValueRef , t : ty:: t ) -> block {
1265
+ // NB: v is an *alias* of type t here, not a direct value.
1242
1266
let _icx = cx. insn_ctxt ( ~"drop_ty") ;
1243
1267
if ty:: type_needs_drop ( cx. tcx ( ) , t) {
1244
1268
return call_tydesc_glue ( cx, v, t, abi:: tydesc_field_drop_glue) ;
@@ -1252,7 +1276,7 @@ fn drop_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> block {
1252
1276
ty:: ty_uniq( _) |
1253
1277
ty:: ty_evec( _, ty:: vstore_uniq) |
1254
1278
ty:: ty_estr( ty:: vstore_uniq) => {
1255
- free_ty ( bcx, v, t)
1279
+ free_ty_immediate ( bcx, v, t)
1256
1280
}
1257
1281
ty:: ty_box( _) | ty:: ty_opaque_box |
1258
1282
ty:: ty_evec( _, ty:: vstore_box) |
@@ -1284,13 +1308,32 @@ fn take_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> result {
1284
1308
}
1285
1309
1286
1310
fn free_ty ( cx : block , v : ValueRef , t : ty:: t ) -> block {
1311
+ // NB: v is an *alias* of type t here, not a direct value.
1287
1312
let _icx = cx. insn_ctxt ( ~"free_ty") ;
1288
1313
if ty:: type_needs_drop ( cx. tcx ( ) , t) {
1289
1314
return call_tydesc_glue ( cx, v, t, abi:: tydesc_field_free_glue) ;
1290
1315
}
1291
1316
return cx;
1292
1317
}
1293
1318
1319
+ fn free_ty_immediate ( bcx : block , v : ValueRef , t : ty:: t ) -> block {
1320
+ let _icx = bcx. insn_ctxt ( ~"free_ty_immediate") ;
1321
+ match ty:: get ( t) . struct {
1322
+ ty:: ty_uniq( _) |
1323
+ ty:: ty_evec( _, ty:: vstore_uniq) |
1324
+ ty:: ty_estr( ty:: vstore_uniq) |
1325
+ ty:: ty_box( _) | ty:: ty_opaque_box |
1326
+ ty:: ty_evec( _, ty:: vstore_box) |
1327
+ ty:: ty_estr( ty:: vstore_box) |
1328
+ ty:: ty_opaque_closure_ptr( _) => {
1329
+ let vp = alloca_zeroed ( bcx, type_of ( bcx. ccx ( ) , t) ) ;
1330
+ Store ( bcx, v, vp) ;
1331
+ free_ty ( bcx, vp, t)
1332
+ }
1333
+ _ => bcx. tcx ( ) . sess . bug ( ~"free_ty_immediate: non-box ty")
1334
+ }
1335
+ }
1336
+
1294
1337
fn call_memmove ( cx : block , dst : ValueRef , src : ValueRef ,
1295
1338
n_bytes : ValueRef ) {
1296
1339
// FIXME (Related to #1645, I think?): Provide LLVM with better
0 commit comments