43
43
44
44
#![ allow( unsigned_negation) ]
45
45
46
- pub use self :: PointerField :: * ;
47
46
pub use self :: Repr :: * ;
48
47
49
48
use std:: num:: Int ;
50
49
use std:: rc:: Rc ;
51
50
52
51
use llvm:: { ValueRef , True , IntEQ , IntNE } ;
53
- use back:: abi;
52
+ use back:: abi:: FAT_PTR_ADDR ;
54
53
use middle:: subst;
55
54
use middle:: subst:: Subst ;
56
55
use trans:: _match;
@@ -71,7 +70,6 @@ use util::ppaux::ty_to_string;
71
70
72
71
type Hint = attr:: ReprAttr ;
73
72
74
-
75
73
/// Representations.
76
74
#[ deriving( Eq , PartialEq , Show ) ]
77
75
pub enum Repr < ' tcx > {
@@ -101,7 +99,7 @@ pub enum Repr<'tcx> {
101
99
nullfields : Vec < Ty < ' tcx > >
102
100
} ,
103
101
/// Two cases distinguished by a nullable pointer: the case with discriminant
104
- /// `nndiscr` is represented by the struct `nonnull`, where the `ptrfield `th
102
+ /// `nndiscr` is represented by the struct `nonnull`, where the `discrfield `th
105
103
/// field is known to be nonnull due to its type; if that field is null, then
106
104
/// it represents the other case, which is inhabited by at most one value
107
105
/// (and all other fields are undefined/unused).
@@ -112,7 +110,7 @@ pub enum Repr<'tcx> {
112
110
StructWrappedNullablePointer {
113
111
nonnull : Struct < ' tcx > ,
114
112
nndiscr : Disr ,
115
- ptrfield : PointerField ,
113
+ discrfield : DiscrField ,
116
114
nullfields : Vec < Ty < ' tcx > > ,
117
115
}
118
116
}
@@ -230,18 +228,20 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
230
228
let st = mk_struct ( cx, cases[ discr] . tys . as_slice ( ) ,
231
229
false , t) ;
232
230
match cases[ discr] . find_ptr ( cx) {
233
- Some ( ThinPointer ( _ ) ) if st. fields . len ( ) == 1 => {
231
+ Some ( ref pf ) if pf . len ( ) == 1 && st. fields . len ( ) == 1 => {
234
232
return RawNullablePointer {
235
233
nndiscr : discr as Disr ,
236
234
nnty : st. fields [ 0 ] ,
237
235
nullfields : cases[ 1 - discr] . tys . clone ( )
238
236
} ;
239
237
}
240
- Some ( ptrfield) => {
238
+ Some ( pf) => {
239
+ let mut discrfield = vec ! [ 0 ] ;
240
+ discrfield. extend ( pf. into_iter ( ) ) ;
241
241
return StructWrappedNullablePointer {
242
242
nndiscr : discr as Disr ,
243
243
nonnull : st,
244
- ptrfield : ptrfield ,
244
+ discrfield : discrfield ,
245
245
nullfields : cases[ 1 - discr] . tys . clone ( )
246
246
} ;
247
247
}
@@ -280,48 +280,70 @@ struct Case<'tcx> {
280
280
tys : Vec < Ty < ' tcx > >
281
281
}
282
282
283
+ /// This represents the (GEP) indices to follow to get to the discriminant field
284
+ pub type DiscrField = Vec < uint > ;
283
285
284
- #[ deriving( Eq , PartialEq , Show ) ]
285
- pub enum PointerField {
286
- ThinPointer ( uint ) ,
287
- FatPointer ( uint )
288
- }
286
+ fn find_discr_field_candidate < ' tcx > ( tcx : & ty:: ctxt < ' tcx > , ty : Ty < ' tcx > ) -> Option < DiscrField > {
287
+ match ty. sty {
288
+ // &T/&mut T/Box<T> could either be a thin or fat pointer depending on T
289
+ ty:: ty_rptr( _, ty:: mt { ty, .. } ) | ty:: ty_uniq( ty) => match ty. sty {
290
+ // &[T] and &str are a pointer and length pair
291
+ ty:: ty_vec( _, None ) | ty:: ty_str => Some ( vec ! [ FAT_PTR_ADDR ] ) ,
289
292
290
- impl < ' tcx > Case < ' tcx > {
291
- fn is_zerolen < ' a > ( & self , cx : & CrateContext < ' a , ' tcx > , scapegoat : Ty < ' tcx > ) -> bool {
292
- mk_struct ( cx, self . tys . as_slice ( ) , false , scapegoat) . size == 0
293
- }
293
+ // &Trait is a pair of pointers: the actual object and a vtable
294
+ ty:: ty_trait( ..) => Some ( vec ! [ FAT_PTR_ADDR ] ) ,
294
295
295
- fn find_ptr < ' a > ( & self , cx : & CrateContext < ' a , ' tcx > ) -> Option < PointerField > {
296
- for ( i, & ty) in self . tys . iter ( ) . enumerate ( ) {
297
- match ty. sty {
298
- // &T/&mut T/Box<T> could either be a thin or fat pointer depending on T
299
- ty:: ty_rptr( _, ty:: mt { ty, .. } ) | ty:: ty_uniq( ty) => match ty. sty {
300
- // &[T] and &str are a pointer and length pair
301
- ty:: ty_vec( _, None ) | ty:: ty_str => return Some ( FatPointer ( i) ) ,
296
+ ty:: ty_struct( ..) if !ty:: type_is_sized ( tcx, ty) => Some ( vec ! [ FAT_PTR_ADDR ] ) ,
302
297
303
- // &Trait is a pair of pointers: the actual object and a vtable
304
- ty:: ty_trait( ..) => return Some ( FatPointer ( i) ) ,
298
+ // Any other &T is just a pointer
299
+ _ => Some ( vec ! [ ] )
300
+ } ,
305
301
306
- ty:: ty_struct( ..) if !ty:: type_is_sized ( cx. tcx ( ) , ty) => {
307
- return Some ( FatPointer ( i) )
308
- }
302
+ // Functions are just pointers
303
+ ty:: ty_bare_fn( ..) => Some ( vec ! [ ] ) ,
309
304
310
- // Any other &T is just a pointer
311
- _ => return Some ( ThinPointer ( i) )
312
- } ,
305
+ // Closures are a pair of pointers: the code and environment
306
+ ty:: ty_closure( ..) => Some ( vec ! [ FAT_PTR_ADDR ] ) ,
313
307
314
- // Functions are just pointers
315
- ty:: ty_bare_fn( ..) => return Some ( ThinPointer ( i) ) ,
308
+ // Perhaps one of the fields of this struct is non-null
309
+ // let's recurse and find out
310
+ ty:: ty_struct( def_id, ref substs) => {
311
+ let fields = ty:: lookup_struct_fields ( tcx, def_id) ;
312
+ for ( j, field) in fields. iter ( ) . enumerate ( ) {
313
+ let field_ty = ty:: lookup_field_type ( tcx, def_id, field. id , substs) ;
314
+ match find_discr_field_candidate ( tcx, field_ty) {
315
+ Some ( v) => {
316
+ let mut discrfield = vec ! [ j] ;
317
+ discrfield. extend ( v. into_iter ( ) ) ;
318
+ return Some ( discrfield) ;
319
+ }
320
+ None => continue
321
+ }
322
+ }
323
+ None
324
+ } ,
316
325
317
- // Closures are a pair of pointers: the code and environment
318
- ty:: ty_closure( ..) => return Some ( FatPointer ( i) ) ,
326
+ // Anything else is not a pointer
327
+ _ => None
328
+ }
329
+ }
319
330
320
- // Anything else is not a pointer
321
- _ => continue
331
+ impl < ' tcx > Case < ' tcx > {
332
+ fn is_zerolen < ' a > ( & self , cx : & CrateContext < ' a , ' tcx > , scapegoat : Ty < ' tcx > ) -> bool {
333
+ mk_struct ( cx, self . tys . as_slice ( ) , false , scapegoat) . size == 0
334
+ }
335
+
336
+ fn find_ptr < ' a > ( & self , cx : & CrateContext < ' a , ' tcx > ) -> Option < DiscrField > {
337
+ for ( i, & ty) in self . tys . iter ( ) . enumerate ( ) {
338
+ match find_discr_field_candidate ( cx. tcx ( ) , ty) {
339
+ Some ( v) => {
340
+ let mut discrfield = vec ! [ i] ;
341
+ discrfield. extend ( v. into_iter ( ) ) ;
342
+ return Some ( discrfield) ;
343
+ }
344
+ None => continue
322
345
}
323
346
}
324
-
325
347
None
326
348
}
327
349
}
@@ -653,8 +675,8 @@ pub fn trans_get_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
653
675
val = ICmp ( bcx, cmp, Load ( bcx, scrutinee) , C_null ( llptrty) ) ;
654
676
signed = false ;
655
677
}
656
- StructWrappedNullablePointer { nndiscr, ptrfield , .. } => {
657
- val = struct_wrapped_nullable_bitdiscr ( bcx, nndiscr, ptrfield , scrutinee) ;
678
+ StructWrappedNullablePointer { nndiscr, ref discrfield , .. } => {
679
+ val = struct_wrapped_nullable_bitdiscr ( bcx, nndiscr, discrfield , scrutinee) ;
658
680
signed = false ;
659
681
}
660
682
}
@@ -664,12 +686,9 @@ pub fn trans_get_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
664
686
}
665
687
}
666
688
667
- fn struct_wrapped_nullable_bitdiscr ( bcx : Block , nndiscr : Disr , ptrfield : PointerField ,
689
+ fn struct_wrapped_nullable_bitdiscr ( bcx : Block , nndiscr : Disr , discrfield : & DiscrField ,
668
690
scrutinee : ValueRef ) -> ValueRef {
669
- let llptrptr = match ptrfield {
670
- ThinPointer ( field) => GEPi ( bcx, scrutinee, & [ 0 , field] ) ,
671
- FatPointer ( field) => GEPi ( bcx, scrutinee, & [ 0 , field, abi:: FAT_PTR_ADDR ] )
672
- } ;
691
+ let llptrptr = GEPi ( bcx, scrutinee, discrfield[ ] ) ;
673
692
let llptr = Load ( bcx, llptrptr) ;
674
693
let cmp = if nndiscr == 0 { IntEQ } else { IntNE } ;
675
694
ICmp ( bcx, cmp, llptr, C_null ( val_ty ( llptr) ) )
@@ -755,17 +774,10 @@ pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
755
774
Store ( bcx, C_null ( llptrty) , val)
756
775
}
757
776
}
758
- StructWrappedNullablePointer { ref nonnull , nndiscr, ptrfield , .. } => {
777
+ StructWrappedNullablePointer { nndiscr, ref discrfield , .. } => {
759
778
if discr != nndiscr {
760
- let ( llptrptr, llptrty) = match ptrfield {
761
- ThinPointer ( field) =>
762
- ( GEPi ( bcx, val, & [ 0 , field] ) ,
763
- type_of:: type_of ( bcx. ccx ( ) , nonnull. fields [ field] ) ) ,
764
- FatPointer ( field) => {
765
- let v = GEPi ( bcx, val, & [ 0 , field, abi:: FAT_PTR_ADDR ] ) ;
766
- ( v, val_ty ( v) . element_type ( ) )
767
- }
768
- } ;
779
+ let llptrptr = GEPi ( bcx, val, discrfield[ ] ) ;
780
+ let llptrty = val_ty ( llptrptr) . element_type ( ) ;
769
781
Store ( bcx, C_null ( llptrty) , llptrptr)
770
782
}
771
783
}
@@ -982,7 +994,7 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, r: &Repr<'tcx>, discr
982
994
false )
983
995
} else {
984
996
let vals = nonnull. fields . iter ( ) . map ( |& ty| {
985
- // Always use null even if it's not the `ptrfield `th
997
+ // Always use null even if it's not the `discrfield `th
986
998
// field; see #8506.
987
999
C_null ( type_of:: sizing_type_of ( ccx, ty) )
988
1000
} ) . collect :: < Vec < ValueRef > > ( ) ;
@@ -1062,9 +1074,8 @@ fn padding(ccx: &CrateContext, size: u64) -> ValueRef {
1062
1074
#[ inline]
1063
1075
fn roundup ( x : u64 , a : u32 ) -> u64 { let a = a as u64 ; ( ( x + ( a - 1 ) ) / a) * a }
1064
1076
1065
- /// Get the discriminant of a constant value. (Not currently used.)
1066
- pub fn const_get_discrim ( ccx : & CrateContext , r : & Repr , val : ValueRef )
1067
- -> Disr {
1077
+ /// Get the discriminant of a constant value.
1078
+ pub fn const_get_discrim ( ccx : & CrateContext , r : & Repr , val : ValueRef ) -> Disr {
1068
1079
match * r {
1069
1080
CEnum ( ity, _, _) => {
1070
1081
match ity {
@@ -1079,25 +1090,8 @@ pub fn const_get_discrim(ccx: &CrateContext, r: &Repr, val: ValueRef)
1079
1090
}
1080
1091
}
1081
1092
Univariant ( ..) => 0 ,
1082
- RawNullablePointer { nndiscr, .. } => {
1083
- if is_null ( val) {
1084
- /* subtraction as uint is ok because nndiscr is either 0 or 1 */
1085
- ( 1 - nndiscr) as Disr
1086
- } else {
1087
- nndiscr
1088
- }
1089
- }
1090
- StructWrappedNullablePointer { nndiscr, ptrfield, .. } => {
1091
- let ( idx, sub_idx) = match ptrfield {
1092
- ThinPointer ( field) => ( field, None ) ,
1093
- FatPointer ( field) => ( field, Some ( abi:: FAT_PTR_ADDR ) )
1094
- } ;
1095
- if is_null ( const_struct_field ( ccx, val, idx, sub_idx) ) {
1096
- /* subtraction as uint is ok because nndiscr is either 0 or 1 */
1097
- ( 1 - nndiscr) as Disr
1098
- } else {
1099
- nndiscr
1100
- }
1093
+ RawNullablePointer { .. } | StructWrappedNullablePointer { .. } => {
1094
+ ccx. sess ( ) . bug ( "const discrim access of non c-like enum" )
1101
1095
}
1102
1096
}
1103
1097
}
@@ -1111,29 +1105,25 @@ pub fn const_get_field(ccx: &CrateContext, r: &Repr, val: ValueRef,
1111
1105
_discr : Disr , ix : uint ) -> ValueRef {
1112
1106
match * r {
1113
1107
CEnum ( ..) => ccx. sess ( ) . bug ( "element access in C-like enum const" ) ,
1114
- Univariant ( ..) => const_struct_field ( ccx, val, ix, None ) ,
1115
- General ( ..) => const_struct_field ( ccx, val, ix + 1 , None ) ,
1108
+ Univariant ( ..) => const_struct_field ( ccx, val, ix) ,
1109
+ General ( ..) => const_struct_field ( ccx, val, ix + 1 ) ,
1116
1110
RawNullablePointer { .. } => {
1117
1111
assert_eq ! ( ix, 0 ) ;
1118
1112
val
1119
- }
1120
- StructWrappedNullablePointer { .. } => const_struct_field ( ccx, val, ix, None )
1113
+ } ,
1114
+ StructWrappedNullablePointer { .. } => const_struct_field ( ccx, val, ix)
1121
1115
}
1122
1116
}
1123
1117
1124
1118
/// Extract field of struct-like const, skipping our alignment padding.
1125
- fn const_struct_field ( ccx : & CrateContext , val : ValueRef , ix : uint , sub_idx : Option < uint > )
1126
- -> ValueRef {
1119
+ fn const_struct_field ( ccx : & CrateContext , val : ValueRef , ix : uint ) -> ValueRef {
1127
1120
// Get the ix-th non-undef element of the struct.
1128
1121
let mut real_ix = 0 ; // actual position in the struct
1129
1122
let mut ix = ix; // logical index relative to real_ix
1130
1123
let mut field;
1131
1124
loop {
1132
1125
loop {
1133
- field = match sub_idx {
1134
- Some ( si) => const_get_elt ( ccx, val, & [ real_ix, si as u32 ] ) ,
1135
- None => const_get_elt ( ccx, val, & [ real_ix] )
1136
- } ;
1126
+ field = const_get_elt ( ccx, val, & [ real_ix] ) ;
1137
1127
if !is_undef ( field) {
1138
1128
break ;
1139
1129
}
0 commit comments