@@ -546,18 +546,18 @@ fn make_generic_glue_inner(ccx: @crate_ctxt, t: ty::t,
546546 let fcx = new_fn_ctxt ( ccx, ~[ ] , llfn, none) ;
547547 lib:: llvm:: SetLinkage ( llfn, lib:: llvm:: InternalLinkage ) ;
548548 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
550550 // requirement since in many contexts glue is invoked indirectly and
551551 // the caller has no idea if it's dealing with something that can be
552552 // 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.
555556
556557 let bcx = top_scope_block ( fcx, none) ;
557558 let lltop = bcx. llbb ;
558559 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) ;
561561 finish_fn ( fcx, lltop) ;
562562 return llfn;
563563}
@@ -581,28 +581,44 @@ fn make_generic_glue(ccx: @crate_ctxt, t: ty::t, llfn: ValueRef,
581581fn emit_tydescs(ccx: @crate_ctxt) {
582582 let _icx = ccx.insn_ctxt(~" emit_tydescs") ;
583583 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) ) ;
585585 let ti = val;
586586
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.
587591 let take_glue =
588592 match copy ti. take_glue {
589593 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+ }
591598 } ;
592599 let drop_glue =
593600 match copy ti. drop_glue {
594601 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+ }
596606 } ;
597607 let free_glue =
598608 match copy ti. free_glue {
599609 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+ }
601614 } ;
602615 let visit_glue =
603616 match copy ti. visit_glue {
604617 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+ }
606622 } ;
607623
608624 let shape = shape_of ( ccx, key) ;
@@ -692,20 +708,20 @@ fn make_visit_glue(bcx: block, v: ValueRef, t: ty::t) {
692708
693709
694710fn 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.
698712 let _icx = bcx. insn_ctxt ( ~"make_free_glue") ;
699713 let ccx = bcx. ccx ( ) ;
700714 let bcx = match ty:: get ( t) . struct {
701715 ty:: ty_box( body_mt) => {
702- let v = PointerCast ( bcx, v, type_of ( ccx , t ) ) ;
716+ let v = Load ( bcx, v) ;
703717 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 ) ) ) ;
704720 let bcx = drop_ty ( bcx, body, body_mt. ty ) ;
705721 trans_free ( bcx, v)
706722 }
707723 ty:: ty_opaque_box => {
708- let v = PointerCast ( bcx, v, type_of ( ccx , t ) ) ;
724+ let v = Load ( bcx, v) ;
709725 let td = Load ( bcx, GEPi ( bcx, v, ~[ 0 u, abi:: box_field_tydesc] ) ) ;
710726 let valptr = GEPi ( bcx, v, ~[ 0 u, abi:: box_field_body] ) ;
711727 // Generate code that, dynamically, indexes into the
@@ -715,7 +731,6 @@ fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) {
715731 trans_free ( bcx, v)
716732 }
717733 ty:: ty_uniq( content_mt) => {
718- let v = PointerCast ( bcx, v, type_of ( ccx, t) ) ;
719734 uniq:: make_free_glue ( bcx, v, t)
720735 }
721736 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) {
785800 }
786801 ty:: ty_uniq( _) |
787802 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)
789804 }
790805 ty:: ty_unboxed_vec( _) => {
791806 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 {
861876 let ccx = bcx. ccx ( ) ;
862877 maybe_validate_box ( bcx, box_ptr) ;
863878
864- let llbox_ty = T_opaque_box_ptr ( ccx) ;
865- let box_ptr = PointerCast ( bcx, box_ptr, llbox_ty) ;
866879 do with_cond( bcx, IsNotNull ( bcx, box_ptr) ) |bcx| {
867880 let rc_ptr = GEPi ( bcx, box_ptr, ~[ 0 u, abi:: box_field_refcnt] ) ;
868881 let rc = Sub ( bcx, Load ( bcx, rc_ptr) , C_int ( ccx, 1 ) ) ;
869882 Store ( bcx, rc, rc_ptr) ;
870883 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) )
872885 }
873886}
874887
@@ -1097,17 +1110,16 @@ fn lazily_emit_all_tydesc_glue(ccx: @crate_ctxt,
10971110fn lazily_emit_tydesc_glue( ccx: @crate_ctxt, field: uint,
10981111 ti: @tydesc_info) {
10991112 let _icx = ccx. insn_ctxt( ~"lazily_emit_tydesc_glue") ;
1113+ let llfnty = type_of_glue_fn( ccx, ti. ty) ;
11001114 if field == abi:: tydesc_field_take_glue {
11011115 match ti. take_glue {
11021116 some( _) => ( ) ,
11031117 none => {
11041118 debug ! { "+++ lazily_emit_tydesc_glue TAKE %s" ,
11051119 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") ;
11081121 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") ;
11111123 debug ! { "--- lazily_emit_tydesc_glue TAKE %s" ,
11121124 ppaux:: ty_to_str( ccx. tcx, ti. ty) } ;
11131125 }
@@ -1118,11 +1130,9 @@ fn lazily_emit_tydesc_glue(ccx: @crate_ctxt, field: uint,
11181130 none => {
11191131 debug ! { "+++ lazily_emit_tydesc_glue DROP %s" ,
11201132 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") ;
11231134 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") ;
11261136 debug ! { "--- lazily_emit_tydesc_glue DROP %s" ,
11271137 ppaux:: ty_to_str( ccx. tcx, ti. ty) } ;
11281138 }
@@ -1133,11 +1143,9 @@ fn lazily_emit_tydesc_glue(ccx: @crate_ctxt, field: uint,
11331143 none => {
11341144 debug ! { "+++ lazily_emit_tydesc_glue FREE %s" ,
11351145 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") ;
11381147 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") ;
11411149 debug ! { "--- lazily_emit_tydesc_glue FREE %s" ,
11421150 ppaux:: ty_to_str( ccx. tcx, ti. ty) } ;
11431151 }
@@ -1148,11 +1156,9 @@ fn lazily_emit_tydesc_glue(ccx: @crate_ctxt, field: uint,
11481156 none => {
11491157 debug ! { "+++ lazily_emit_tydesc_glue VISIT %s" ,
11501158 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") ;
11531160 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") ;
11561162 debug ! { "--- lazily_emit_tydesc_glue VISIT %s" ,
11571163 ppaux:: ty_to_str( ccx. tcx, ti. ty) } ;
11581164 }
@@ -1161,43 +1167,63 @@ fn lazily_emit_tydesc_glue(ccx: @crate_ctxt, field: uint,
11611167}
11621168
11631169// 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 ,
11651171 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 ( ) ;
11681175
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,
11721178 some( sti) => {
1173- lazily_emit_tydesc_glue ( cx . ccx ( ) , field, sti) ;
1179+ lazily_emit_tydesc_glue ( ccx, field, sti) ;
11741180 if field == abi:: tydesc_field_take_glue {
1175- static_glue_fn = sti. take_glue ;
1181+ sti. take_glue
11761182 } else if field == abi:: tydesc_field_drop_glue {
1177- static_glue_fn = sti. drop_glue ;
1183+ sti. drop_glue
11781184 } else if field == abi:: tydesc_field_free_glue {
1179- static_glue_fn = sti. free_glue ;
1185+ sti. free_glue
11801186 } else if field == abi:: tydesc_field_visit_glue {
1181- static_glue_fn = sti. visit_glue ;
1187+ sti. visit_glue
1188+ } else {
1189+ none
11821190 }
11831191 }
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+ } ;
11851205
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+ } ;
11871213
11881214 let llfn = {
11891215 match static_glue_fn {
11901216 none => {
11911217 // 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)
11941220 }
11951221 some( sgf) => sgf
11961222 }
11971223 } ;
11981224
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] ) ;
12011227}
12021228
12031229// See [Note-arg-mode]
@@ -1231,6 +1257,7 @@ fn call_cmp_glue(bcx: block, lhs: ValueRef, rhs: ValueRef, t: ty::t,
12311257}
12321258
12331259fn take_ty ( cx : block , v : ValueRef , t : ty:: t ) -> block {
1260+ // NB: v is an *alias* of type t here, not a direct value.
12341261 let _icx = cx. insn_ctxt ( ~"take_ty") ;
12351262 if ty:: type_needs_drop ( cx. tcx ( ) , t) {
12361263 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 {
12391266}
12401267
12411268fn drop_ty ( cx : block , v : ValueRef , t : ty:: t ) -> block {
1269+ // NB: v is an *alias* of type t here, not a direct value.
12421270 let _icx = cx. insn_ctxt ( ~"drop_ty") ;
12431271 if ty:: type_needs_drop ( cx. tcx ( ) , t) {
12441272 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 {
12521280 ty:: ty_uniq( _) |
12531281 ty:: ty_evec( _, ty:: vstore_uniq) |
12541282 ty:: ty_estr( ty:: vstore_uniq) => {
1255- free_ty ( bcx, v, t)
1283+ free_ty_immediate ( bcx, v, t)
12561284 }
12571285 ty:: ty_box( _) | ty:: ty_opaque_box |
12581286 ty:: ty_evec( _, ty:: vstore_box) |
@@ -1284,13 +1312,32 @@ fn take_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> result {
12841312}
12851313
12861314fn free_ty ( cx : block , v : ValueRef , t : ty:: t ) -> block {
1315+ // NB: v is an *alias* of type t here, not a direct value.
12871316 let _icx = cx. insn_ctxt ( ~"free_ty") ;
12881317 if ty:: type_needs_drop ( cx. tcx ( ) , t) {
12891318 return call_tydesc_glue ( cx, v, t, abi:: tydesc_field_free_glue) ;
12901319 }
12911320 return cx;
12921321}
12931322
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+
12941341fn call_memmove ( cx : block , dst : ValueRef , src : ValueRef ,
12951342 n_bytes : ValueRef ) {
12961343 // FIXME (Related to #1645, I think?): Provide LLVM with better
0 commit comments