@@ -111,7 +111,7 @@ pub enum Repr {
111111 StructWrappedNullablePointer {
112112 pub nonnull : Struct ,
113113 pub nndiscr : Disr ,
114- pub ptrfield : uint ,
114+ pub ptrfield : PointerField ,
115115 pub nullfields : Vec < ty:: t > ,
116116 }
117117}
@@ -211,24 +211,21 @@ fn represent_type_uncached(cx: &CrateContext, t: ty::t) -> Repr {
211211 let mut discr = 0 ;
212212 while discr < 2 {
213213 if cases. get ( 1 - discr) . is_zerolen ( cx) {
214+ let st = mk_struct ( cx, cases. get ( discr) . tys . as_slice ( ) , false ) ;
214215 match cases. get ( discr) . find_ptr ( ) {
216+ Some ( ThinPointer ( _) ) if st. fields . len ( ) == 1 => {
217+ return RawNullablePointer {
218+ nndiscr : discr as Disr ,
219+ nnty : * st. fields . get ( 0 ) ,
220+ nullfields : cases. get ( 1 - discr) . tys . clone ( )
221+ } ;
222+ }
215223 Some ( ptrfield) => {
216- let st = mk_struct ( cx, cases. get ( discr) . tys . as_slice ( ) ,
217- false ) ;
218-
219- return if st. fields . len ( ) == 1 {
220- RawNullablePointer {
221- nndiscr : discr as Disr ,
222- nnty : * st. fields . get ( 0 ) ,
223- nullfields : cases. get ( 1 - discr) . tys . clone ( )
224- }
225- } else {
226- StructWrappedNullablePointer {
227- nndiscr : discr as Disr ,
228- nonnull : st,
229- ptrfield : ptrfield,
230- nullfields : cases. get ( 1 - discr) . tys . clone ( )
231- }
224+ return StructWrappedNullablePointer {
225+ nndiscr : discr as Disr ,
226+ nonnull : st,
227+ ptrfield : ptrfield,
228+ nullfields : cases. get ( 1 - discr) . tys . clone ( )
232229 } ;
233230 }
234231 None => { }
@@ -283,23 +280,67 @@ pub fn is_ffi_safe(tcx: &ty::ctxt, def_id: ast::DefId) -> bool {
283280}
284281
285282// this should probably all be in ty
286- struct Case { discr : Disr , tys : Vec < ty:: t > }
283+ struct Case {
284+ discr : Disr ,
285+ tys : Vec < ty:: t >
286+ }
287+
288+
289+ #[ deriving( Show ) ]
290+ pub enum PointerField {
291+ ThinPointer ( uint ) ,
292+ FatPointer ( uint , uint )
293+ }
294+
287295impl Case {
288296 fn is_zerolen ( & self , cx : & CrateContext ) -> bool {
289297 mk_struct ( cx, self . tys . as_slice ( ) , false ) . size == 0
290298 }
291- fn find_ptr ( & self ) -> Option < uint > {
292- self . tys . iter ( ) . position ( |& ty| {
299+ fn find_ptr ( & self ) -> Option < PointerField > {
300+ use back:: abi:: { fn_field_code, slice_elt_base, trt_field_box} ;
301+
302+ for ( i, & ty) in self . tys . iter ( ) . enumerate ( ) {
293303 match ty:: get ( ty) . sty {
294- ty:: ty_uniq( ty) | ty:: ty_rptr( _, ty:: mt { ty, ..} ) => match ty:: get ( ty) . sty {
295- ty:: ty_vec( _, None ) | ty:: ty_str| ty:: ty_trait( ..) => false ,
296- _ => true ,
304+ // &T/&mut T could either be a thin or fat pointer depending on T
305+ ty:: ty_rptr( _, ty:: mt { ty, .. } ) => match ty:: get ( ty) . sty {
306+ // &[T] and &str are a pointer and length pair
307+ ty:: ty_vec( _, None ) | ty:: ty_str => return Some ( FatPointer ( i, slice_elt_base) ) ,
308+
309+ // &Trait/&mut Trait are a pair of pointers: the actual object and a vtable
310+ ty:: ty_trait( ..) => return Some ( FatPointer ( i, trt_field_box) ) ,
311+
312+ // Any other &T/&mut T is just a pointer
313+ _ => return Some ( ThinPointer ( i) )
314+ } ,
315+
316+ // Box<T> could either be a thin or fat pointer depending on T
317+ ty:: ty_uniq( t) => match ty:: get ( t) . sty {
318+ // Box<[T]>/Box<str> might be FatPointer in a post DST world
319+ ty:: ty_vec( _, None ) | ty:: ty_str => continue ,
320+
321+ // Box<Trait> is a pair of pointers: the actual object and a vtable
322+ ty:: ty_trait( ..) => return Some ( FatPointer ( i, trt_field_box) ) ,
323+
324+ // Any other Box<T> is just a pointer
325+ _ => return Some ( ThinPointer ( i) )
297326 } ,
298- ty:: ty_box( ..) | ty:: ty_bare_fn( ..) => true ,
299- // Is that everything? Would closures or slices qualify?
300- _ => false
327+
328+ // Gc<T> is just a pointer
329+ ty:: ty_box( ..) => return Some ( ThinPointer ( i) ) ,
330+
331+ // Functions are just pointers
332+ ty:: ty_bare_fn( ..) => return Some ( ThinPointer ( i) ) ,
333+
334+ // Closures are a pair of pointers: the code and environment
335+ ty:: ty_closure( ..) => return Some ( FatPointer ( i, fn_field_code) ) ,
336+
337+ // Anything else is not a pointer
338+ _ => continue
339+
301340 }
302- } )
341+ }
342+
343+ None
303344 }
304345}
305346
@@ -552,8 +593,8 @@ pub fn trans_get_discr(bcx: &Block, r: &Repr, scrutinee: ValueRef, cast_to: Opti
552593 val = ICmp ( bcx, cmp, Load ( bcx, scrutinee) , C_null ( llptrty) ) ;
553594 signed = false ;
554595 }
555- StructWrappedNullablePointer { nonnull : ref nonnull , nndiscr, ptrfield, .. } => {
556- val = struct_wrapped_nullable_bitdiscr ( bcx, nonnull , nndiscr, ptrfield, scrutinee) ;
596+ StructWrappedNullablePointer { nndiscr, ptrfield, .. } => {
597+ val = struct_wrapped_nullable_bitdiscr ( bcx, nndiscr, ptrfield, scrutinee) ;
557598 signed = false ;
558599 }
559600 }
@@ -563,12 +604,15 @@ pub fn trans_get_discr(bcx: &Block, r: &Repr, scrutinee: ValueRef, cast_to: Opti
563604 }
564605}
565606
566- fn struct_wrapped_nullable_bitdiscr ( bcx : & Block , nonnull : & Struct , nndiscr : Disr , ptrfield : uint ,
607+ fn struct_wrapped_nullable_bitdiscr ( bcx : & Block , nndiscr : Disr , ptrfield : PointerField ,
567608 scrutinee : ValueRef ) -> ValueRef {
568- let llptr = Load ( bcx, GEPi ( bcx, scrutinee, [ 0 , ptrfield] ) ) ;
609+ let llptrptr = match ptrfield {
610+ ThinPointer ( field) => GEPi ( bcx, scrutinee, [ 0 , field] ) ,
611+ FatPointer ( field, pair) => GEPi ( bcx, scrutinee, [ 0 , field, pair] )
612+ } ;
613+ let llptr = Load ( bcx, llptrptr) ;
569614 let cmp = if nndiscr == 0 { IntEQ } else { IntNE } ;
570- let llptrty = type_of:: type_of ( bcx. ccx ( ) , * nonnull. fields . get ( ptrfield) ) ;
571- ICmp ( bcx, cmp, llptr, C_null ( llptrty) )
615+ ICmp ( bcx, cmp, llptr, C_null ( val_ty ( llptr) ) )
572616}
573617
574618/// Helper for cases where the discriminant is simply loaded.
@@ -655,9 +699,15 @@ pub fn trans_start_init(bcx: &Block, r: &Repr, val: ValueRef, discr: Disr) {
655699 }
656700 StructWrappedNullablePointer { nonnull : ref nonnull, nndiscr, ptrfield, .. } => {
657701 if discr != nndiscr {
658- let llptrptr = GEPi ( bcx, val, [ 0 , ptrfield] ) ;
659- let llptrty = type_of:: type_of ( bcx. ccx ( ) ,
660- * nonnull. fields . get ( ptrfield) ) ;
702+ let ( llptrptr, llptrty) = match ptrfield {
703+ ThinPointer ( field) =>
704+ ( GEPi ( bcx, val, [ 0 , field] ) ,
705+ type_of:: type_of ( bcx. ccx ( ) , * nonnull. fields . get ( field) ) ) ,
706+ FatPointer ( field, pair) => {
707+ let v = GEPi ( bcx, val, [ 0 , field, pair] ) ;
708+ ( v, val_ty ( v) . element_type ( ) )
709+ }
710+ } ;
661711 Store ( bcx, C_null ( llptrty) , llptrptr)
662712 }
663713 }
@@ -925,7 +975,11 @@ pub fn const_get_discrim(ccx: &CrateContext, r: &Repr, val: ValueRef)
925975 }
926976 }
927977 StructWrappedNullablePointer { nndiscr, ptrfield, .. } => {
928- if is_null ( const_struct_field ( ccx, val, ptrfield) ) {
978+ let ( idx, sub_idx) = match ptrfield {
979+ ThinPointer ( field) => ( field, None ) ,
980+ FatPointer ( field, pair) => ( field, Some ( pair) )
981+ } ;
982+ if is_null ( const_struct_field ( ccx, val, idx, sub_idx) ) {
929983 /* subtraction as uint is ok because nndiscr is either 0 or 1 */
930984 ( 1 - nndiscr) as Disr
931985 } else {
@@ -946,26 +1000,29 @@ pub fn const_get_field(ccx: &CrateContext, r: &Repr, val: ValueRef,
9461000 _discr : Disr , ix : uint ) -> ValueRef {
9471001 match * r {
9481002 CEnum ( ..) => ccx. sess ( ) . bug ( "element access in C-like enum const" ) ,
949- Univariant ( ..) => const_struct_field ( ccx, val, ix) ,
950- General ( ..) => const_struct_field ( ccx, val, ix + 1 ) ,
1003+ Univariant ( ..) => const_struct_field ( ccx, val, ix, None ) ,
1004+ General ( ..) => const_struct_field ( ccx, val, ix + 1 , None ) ,
9511005 RawNullablePointer { .. } => {
9521006 assert_eq ! ( ix, 0 ) ;
9531007 val
9541008 }
955- StructWrappedNullablePointer { .. } => const_struct_field ( ccx, val, ix)
1009+ StructWrappedNullablePointer { .. } => const_struct_field ( ccx, val, ix, None )
9561010 }
9571011}
9581012
9591013/// Extract field of struct-like const, skipping our alignment padding.
960- fn const_struct_field ( ccx : & CrateContext , val : ValueRef , ix : uint )
1014+ fn const_struct_field ( ccx : & CrateContext , val : ValueRef , ix : uint , sub_idx : Option < uint > )
9611015 -> ValueRef {
9621016 // Get the ix-th non-undef element of the struct.
9631017 let mut real_ix = 0 ; // actual position in the struct
9641018 let mut ix = ix; // logical index relative to real_ix
9651019 let mut field;
9661020 loop {
9671021 loop {
968- field = const_get_elt ( ccx, val, [ real_ix] ) ;
1022+ field = match sub_idx {
1023+ Some ( si) => const_get_elt ( ccx, val, [ real_ix, si as u32 ] ) ,
1024+ None => const_get_elt ( ccx, val, [ real_ix] )
1025+ } ;
9691026 if !is_undef ( field) {
9701027 break ;
9711028 }
0 commit comments