@@ -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}
@@ -587,22 +587,34 @@ fn emit_tydescs(ccx: @crate_ctxt) {
587587 let take_glue =
588588 match copy ti. take_glue {
589589 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+ }
591594 } ;
592595 let drop_glue =
593596 match copy ti. drop_glue {
594597 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+ }
596602 } ;
597603 let free_glue =
598604 match copy ti. free_glue {
599605 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+ }
601610 } ;
602611 let visit_glue =
603612 match copy ti. visit_glue {
604613 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+ }
606618 } ;
607619
608620 let shape = shape_of ( ccx, key) ;
@@ -692,20 +704,20 @@ fn make_visit_glue(bcx: block, v: ValueRef, t: ty::t) {
692704
693705
694706fn 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.
698708 let _icx = bcx. insn_ctxt ( ~"make_free_glue") ;
699709 let ccx = bcx. ccx ( ) ;
700710 let bcx = match ty:: get ( t) . struct {
701711 ty:: ty_box( body_mt) => {
702- let v = PointerCast ( bcx, v, type_of ( ccx , t ) ) ;
712+ let v = Load ( bcx, v) ;
703713 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 ) ) ) ;
704716 let bcx = drop_ty ( bcx, body, body_mt. ty ) ;
705717 trans_free ( bcx, v)
706718 }
707719 ty:: ty_opaque_box => {
708- let v = PointerCast ( bcx, v, type_of ( ccx , t ) ) ;
720+ let v = Load ( bcx, v) ;
709721 let td = Load ( bcx, GEPi ( bcx, v, ~[ 0 u, abi:: box_field_tydesc] ) ) ;
710722 let valptr = GEPi ( bcx, v, ~[ 0 u, abi:: box_field_body] ) ;
711723 // Generate code that, dynamically, indexes into the
@@ -715,7 +727,6 @@ fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) {
715727 trans_free ( bcx, v)
716728 }
717729 ty:: ty_uniq( content_mt) => {
718- let v = PointerCast ( bcx, v, type_of ( ccx, t) ) ;
719730 uniq:: make_free_glue ( bcx, v, t)
720731 }
721732 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) {
785796 }
786797 ty:: ty_uniq( _) |
787798 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)
789800 }
790801 ty:: ty_unboxed_vec( _) => {
791802 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 {
861872 let ccx = bcx. ccx ( ) ;
862873 maybe_validate_box ( bcx, box_ptr) ;
863874
864- let llbox_ty = T_opaque_box_ptr ( ccx) ;
865- let box_ptr = PointerCast ( bcx, box_ptr, llbox_ty) ;
866875 do with_cond( bcx, IsNotNull ( bcx, box_ptr) ) |bcx| {
867876 let rc_ptr = GEPi ( bcx, box_ptr, ~[ 0 u, abi:: box_field_refcnt] ) ;
868877 let rc = Sub ( bcx, Load ( bcx, rc_ptr) , C_int ( ccx, 1 ) ) ;
869878 Store ( bcx, rc, rc_ptr) ;
870879 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) )
872881 }
873882}
874883
@@ -1097,17 +1106,16 @@ fn lazily_emit_all_tydesc_glue(ccx: @crate_ctxt,
10971106fn lazily_emit_tydesc_glue( ccx: @crate_ctxt, field: uint,
10981107 ti: @tydesc_info) {
10991108 let _icx = ccx. insn_ctxt( ~"lazily_emit_tydesc_glue") ;
1109+ let llfnty = type_of_glue_fn( ccx, ti. ty) ;
11001110 if field == abi:: tydesc_field_take_glue {
11011111 match ti. take_glue {
11021112 some( _) => ( ) ,
11031113 none => {
11041114 debug ! { "+++ lazily_emit_tydesc_glue TAKE %s" ,
11051115 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") ;
11081117 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") ;
11111119 debug ! { "--- lazily_emit_tydesc_glue TAKE %s" ,
11121120 ppaux:: ty_to_str( ccx. tcx, ti. ty) } ;
11131121 }
@@ -1118,11 +1126,9 @@ fn lazily_emit_tydesc_glue(ccx: @crate_ctxt, field: uint,
11181126 none => {
11191127 debug ! { "+++ lazily_emit_tydesc_glue DROP %s" ,
11201128 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") ;
11231130 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") ;
11261132 debug ! { "--- lazily_emit_tydesc_glue DROP %s" ,
11271133 ppaux:: ty_to_str( ccx. tcx, ti. ty) } ;
11281134 }
@@ -1133,11 +1139,9 @@ fn lazily_emit_tydesc_glue(ccx: @crate_ctxt, field: uint,
11331139 none => {
11341140 debug ! { "+++ lazily_emit_tydesc_glue FREE %s" ,
11351141 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") ;
11381143 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") ;
11411145 debug ! { "--- lazily_emit_tydesc_glue FREE %s" ,
11421146 ppaux:: ty_to_str( ccx. tcx, ti. ty) } ;
11431147 }
@@ -1148,11 +1152,9 @@ fn lazily_emit_tydesc_glue(ccx: @crate_ctxt, field: uint,
11481152 none => {
11491153 debug ! { "+++ lazily_emit_tydesc_glue VISIT %s" ,
11501154 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") ;
11531156 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") ;
11561158 debug ! { "--- lazily_emit_tydesc_glue VISIT %s" ,
11571159 ppaux:: ty_to_str( ccx. tcx, ti. ty) } ;
11581160 }
@@ -1161,43 +1163,63 @@ fn lazily_emit_tydesc_glue(ccx: @crate_ctxt, field: uint,
11611163}
11621164
11631165// 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 ,
11651167 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 ( ) ;
11681171
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,
11721174 some( sti) => {
1173- lazily_emit_tydesc_glue ( cx . ccx ( ) , field, sti) ;
1175+ lazily_emit_tydesc_glue ( ccx, field, sti) ;
11741176 if field == abi:: tydesc_field_take_glue {
1175- static_glue_fn = sti. take_glue ;
1177+ sti. take_glue
11761178 } else if field == abi:: tydesc_field_drop_glue {
1177- static_glue_fn = sti. drop_glue ;
1179+ sti. drop_glue
11781180 } else if field == abi:: tydesc_field_free_glue {
1179- static_glue_fn = sti. free_glue ;
1181+ sti. free_glue
11801182 } else if field == abi:: tydesc_field_visit_glue {
1181- static_glue_fn = sti. visit_glue ;
1183+ sti. visit_glue
1184+ } else {
1185+ none
11821186 }
11831187 }
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+ } ;
11851201
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+ } ;
11871209
11881210 let llfn = {
11891211 match static_glue_fn {
11901212 none => {
11911213 // 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)
11941216 }
11951217 some( sgf) => sgf
11961218 }
11971219 } ;
11981220
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] ) ;
12011223}
12021224
12031225// See [Note-arg-mode]
@@ -1231,6 +1253,7 @@ fn call_cmp_glue(bcx: block, lhs: ValueRef, rhs: ValueRef, t: ty::t,
12311253}
12321254
12331255fn take_ty ( cx : block , v : ValueRef , t : ty:: t ) -> block {
1256+ // NB: v is an *alias* of type t here, not a direct value.
12341257 let _icx = cx. insn_ctxt ( ~"take_ty") ;
12351258 if ty:: type_needs_drop ( cx. tcx ( ) , t) {
12361259 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 {
12391262}
12401263
12411264fn drop_ty ( cx : block , v : ValueRef , t : ty:: t ) -> block {
1265+ // NB: v is an *alias* of type t here, not a direct value.
12421266 let _icx = cx. insn_ctxt ( ~"drop_ty") ;
12431267 if ty:: type_needs_drop ( cx. tcx ( ) , t) {
12441268 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 {
12521276 ty:: ty_uniq( _) |
12531277 ty:: ty_evec( _, ty:: vstore_uniq) |
12541278 ty:: ty_estr( ty:: vstore_uniq) => {
1255- free_ty ( bcx, v, t)
1279+ free_ty_immediate ( bcx, v, t)
12561280 }
12571281 ty:: ty_box( _) | ty:: ty_opaque_box |
12581282 ty:: ty_evec( _, ty:: vstore_box) |
@@ -1284,13 +1308,32 @@ fn take_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> result {
12841308}
12851309
12861310fn free_ty ( cx : block , v : ValueRef , t : ty:: t ) -> block {
1311+ // NB: v is an *alias* of type t here, not a direct value.
12871312 let _icx = cx. insn_ctxt ( ~"free_ty") ;
12881313 if ty:: type_needs_drop ( cx. tcx ( ) , t) {
12891314 return call_tydesc_glue ( cx, v, t, abi:: tydesc_field_free_glue) ;
12901315 }
12911316 return cx;
12921317}
12931318
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+
12941337fn call_memmove ( cx : block , dst : ValueRef , src : ValueRef ,
12951338 n_bytes : ValueRef ) {
12961339 // FIXME (Related to #1645, I think?): Provide LLVM with better
0 commit comments