@@ -111,7 +111,7 @@ pub enum Repr {
111
111
StructWrappedNullablePointer {
112
112
pub nonnull : Struct ,
113
113
pub nndiscr : Disr ,
114
- pub ptrfield : uint ,
114
+ pub ptrfield : PointerField ,
115
115
pub nullfields : Vec < ty:: t > ,
116
116
}
117
117
}
@@ -211,24 +211,21 @@ fn represent_type_uncached(cx: &CrateContext, t: ty::t) -> Repr {
211
211
let mut discr = 0 ;
212
212
while discr < 2 {
213
213
if cases. get ( 1 - discr) . is_zerolen ( cx) {
214
+ let st = mk_struct ( cx, cases. get ( discr) . tys . as_slice ( ) , false ) ;
214
215
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
+ }
215
223
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 ( )
232
229
} ;
233
230
}
234
231
None => { }
@@ -283,23 +280,67 @@ pub fn is_ffi_safe(tcx: &ty::ctxt, def_id: ast::DefId) -> bool {
283
280
}
284
281
285
282
// 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
+
287
295
impl Case {
288
296
fn is_zerolen ( & self , cx : & CrateContext ) -> bool {
289
297
mk_struct ( cx, self . tys . as_slice ( ) , false ) . size == 0
290
298
}
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 ( ) {
293
303
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) )
297
326
} ,
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
+
301
340
}
302
- } )
341
+ }
342
+
343
+ None
303
344
}
304
345
}
305
346
@@ -552,8 +593,8 @@ pub fn trans_get_discr(bcx: &Block, r: &Repr, scrutinee: ValueRef, cast_to: Opti
552
593
val = ICmp ( bcx, cmp, Load ( bcx, scrutinee) , C_null ( llptrty) ) ;
553
594
signed = false ;
554
595
}
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) ;
557
598
signed = false ;
558
599
}
559
600
}
@@ -563,12 +604,15 @@ pub fn trans_get_discr(bcx: &Block, r: &Repr, scrutinee: ValueRef, cast_to: Opti
563
604
}
564
605
}
565
606
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 ,
567
608
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) ;
569
614
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) ) )
572
616
}
573
617
574
618
/// 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) {
655
699
}
656
700
StructWrappedNullablePointer { nonnull : ref nonnull, nndiscr, ptrfield, .. } => {
657
701
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
+ } ;
661
711
Store ( bcx, C_null ( llptrty) , llptrptr)
662
712
}
663
713
}
@@ -925,7 +975,11 @@ pub fn const_get_discrim(ccx: &CrateContext, r: &Repr, val: ValueRef)
925
975
}
926
976
}
927
977
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) ) {
929
983
/* subtraction as uint is ok because nndiscr is either 0 or 1 */
930
984
( 1 - nndiscr) as Disr
931
985
} else {
@@ -946,26 +1000,29 @@ pub fn const_get_field(ccx: &CrateContext, r: &Repr, val: ValueRef,
946
1000
_discr : Disr , ix : uint ) -> ValueRef {
947
1001
match * r {
948
1002
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 ) ,
951
1005
RawNullablePointer { .. } => {
952
1006
assert_eq ! ( ix, 0 ) ;
953
1007
val
954
1008
}
955
- StructWrappedNullablePointer { .. } => const_struct_field ( ccx, val, ix)
1009
+ StructWrappedNullablePointer { .. } => const_struct_field ( ccx, val, ix, None )
956
1010
}
957
1011
}
958
1012
959
1013
/// 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 > )
961
1015
-> ValueRef {
962
1016
// Get the ix-th non-undef element of the struct.
963
1017
let mut real_ix = 0 ; // actual position in the struct
964
1018
let mut ix = ix; // logical index relative to real_ix
965
1019
let mut field;
966
1020
loop {
967
1021
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
+ } ;
969
1026
if !is_undef ( field) {
970
1027
break ;
971
1028
}
0 commit comments