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 [ ] ,
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
}
@@ -335,49 +335,67 @@ struct Case<'tcx> {
335
335
tys : Vec < Ty < ' tcx > >
336
336
}
337
337
338
+ /// This represents the (GEP) indices to follow to get to the discriminant field
339
+ pub type DiscrField = Vec < uint > ;
338
340
339
- #[ deriving( Copy , Eq , PartialEq , Show ) ]
340
- pub enum PointerField {
341
- ThinPointer ( uint ) ,
342
- FatPointer ( uint )
343
- }
341
+ fn find_discr_field_candidate < ' tcx > ( tcx : & ty:: ctxt < ' tcx > , ty : Ty < ' tcx > ) -> Option < DiscrField > {
342
+ match ty. sty {
343
+ // &T/&mut T/Box<T> could either be a thin or fat pointer depending on T
344
+ ty:: ty_rptr( _, ty:: mt { ty, .. } ) | ty:: ty_uniq( ty) => match ty. sty {
345
+ // &[T] and &str are a pointer and length pair
346
+ ty:: ty_vec( _, None ) | ty:: ty_str => Some ( vec ! [ FAT_PTR_ADDR ] ) ,
344
347
345
- impl < ' tcx > Case < ' tcx > {
346
- fn is_zerolen < ' a > ( & self , cx : & CrateContext < ' a , ' tcx > , scapegoat : Ty < ' tcx > )
347
- -> bool {
348
- mk_struct ( cx, self . tys [ ] , false , scapegoat) . size == 0
349
- }
348
+ ty:: ty_struct( ..) if !ty:: type_is_sized ( tcx, ty) => Some ( vec ! [ FAT_PTR_ADDR ] ) ,
350
349
351
- fn find_ptr < ' a > ( & self , cx : & CrateContext < ' a , ' tcx > ) -> Option < PointerField > {
352
- for ( i, & ty) in self . tys . iter ( ) . enumerate ( ) {
353
- match ty. sty {
354
- // &T/&mut T/Box<T> could either be a thin or fat pointer depending on T
355
- ty:: ty_rptr( _, ty:: mt { ty, .. } ) | ty:: ty_uniq( ty) => match ty. sty {
356
- // &[T] and &str are a pointer and length pair
357
- ty:: ty_vec( _, None ) | ty:: ty_str => return Some ( FatPointer ( i) ) ,
350
+ // Any other &T is just a pointer
351
+ _ => Some ( vec ! [ ] )
352
+ } ,
358
353
359
- // &Trait is a pair of pointers: the actual object and a vtable
360
- ty:: ty_trait ( ..) => return Some ( FatPointer ( i ) ) ,
354
+ // Functions are just pointers
355
+ ty:: ty_bare_fn ( ..) => Some ( vec ! [ ] ) ,
361
356
362
- ty:: ty_struct( ..) if !ty:: type_is_sized ( cx. tcx ( ) , ty) => {
363
- return Some ( FatPointer ( i) )
364
- }
357
+ // Closures are a pair of pointers: the code and environment
358
+ ty:: ty_closure( ..) => Some ( vec ! [ FAT_PTR_ADDR ] ) ,
365
359
366
- // Any other &T is just a pointer
367
- _ => return Some ( ThinPointer ( i) )
368
- } ,
360
+ // Perhaps one of the fields of this struct is non-null
361
+ // let's recurse and find out
362
+ ty:: ty_struct( def_id, ref substs) => {
363
+ let fields = ty:: lookup_struct_fields ( tcx, def_id) ;
364
+ for ( j, field) in fields. iter ( ) . enumerate ( ) {
365
+ let field_ty = ty:: lookup_field_type ( tcx, def_id, field. id , substs) ;
366
+ match find_discr_field_candidate ( tcx, field_ty) {
367
+ Some ( v) => {
368
+ let mut discrfield = vec ! [ j] ;
369
+ discrfield. extend ( v. into_iter ( ) ) ;
370
+ return Some ( discrfield) ;
371
+ }
372
+ None => continue
373
+ }
374
+ }
375
+ None
376
+ } ,
369
377
370
- // Functions are just pointers
371
- ty:: ty_bare_fn( ..) => return Some ( ThinPointer ( i) ) ,
378
+ // Anything else is not a pointer
379
+ _ => None
380
+ }
381
+ }
372
382
373
- // Closures are a pair of pointers: the code and environment
374
- ty:: ty_closure( ..) => return Some ( FatPointer ( i) ) ,
383
+ impl < ' tcx > Case < ' tcx > {
384
+ fn is_zerolen < ' a > ( & self , cx : & CrateContext < ' a , ' tcx > , scapegoat : Ty < ' tcx > ) -> bool {
385
+ mk_struct ( cx, self . tys [ ] , false , scapegoat) . size == 0
386
+ }
375
387
376
- // Anything else is not a pointer
377
- _ => continue
388
+ fn find_ptr < ' a > ( & self , cx : & CrateContext < ' a , ' tcx > ) -> Option < DiscrField > {
389
+ for ( i, & ty) in self . tys . iter ( ) . enumerate ( ) {
390
+ match find_discr_field_candidate ( cx. tcx ( ) , ty) {
391
+ Some ( v) => {
392
+ let mut discrfield = vec ! [ i] ;
393
+ discrfield. extend ( v. into_iter ( ) ) ;
394
+ return Some ( discrfield) ;
395
+ }
396
+ None => continue
378
397
}
379
398
}
380
-
381
399
None
382
400
}
383
401
}
@@ -709,8 +727,8 @@ pub fn trans_get_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
709
727
val = ICmp ( bcx, cmp, Load ( bcx, scrutinee) , C_null ( llptrty) ) ;
710
728
signed = false ;
711
729
}
712
- StructWrappedNullablePointer { nndiscr, ptrfield , .. } => {
713
- val = struct_wrapped_nullable_bitdiscr ( bcx, nndiscr, ptrfield , scrutinee) ;
730
+ StructWrappedNullablePointer { nndiscr, ref discrfield , .. } => {
731
+ val = struct_wrapped_nullable_bitdiscr ( bcx, nndiscr, discrfield , scrutinee) ;
714
732
signed = false ;
715
733
}
716
734
}
@@ -720,12 +738,9 @@ pub fn trans_get_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
720
738
}
721
739
}
722
740
723
- fn struct_wrapped_nullable_bitdiscr ( bcx : Block , nndiscr : Disr , ptrfield : PointerField ,
741
+ fn struct_wrapped_nullable_bitdiscr ( bcx : Block , nndiscr : Disr , discrfield : & DiscrField ,
724
742
scrutinee : ValueRef ) -> ValueRef {
725
- let llptrptr = match ptrfield {
726
- ThinPointer ( field) => GEPi ( bcx, scrutinee, & [ 0 , field] ) ,
727
- FatPointer ( field) => GEPi ( bcx, scrutinee, & [ 0 , field, abi:: FAT_PTR_ADDR ] )
728
- } ;
743
+ let llptrptr = GEPi ( bcx, scrutinee, discrfield[ ] ) ;
729
744
let llptr = Load ( bcx, llptrptr) ;
730
745
let cmp = if nndiscr == 0 { IntEQ } else { IntNE } ;
731
746
ICmp ( bcx, cmp, llptr, C_null ( val_ty ( llptr) ) )
@@ -811,17 +826,10 @@ pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
811
826
Store ( bcx, C_null ( llptrty) , val)
812
827
}
813
828
}
814
- StructWrappedNullablePointer { ref nonnull , nndiscr, ptrfield , .. } => {
829
+ StructWrappedNullablePointer { nndiscr, ref discrfield , .. } => {
815
830
if discr != nndiscr {
816
- let ( llptrptr, llptrty) = match ptrfield {
817
- ThinPointer ( field) =>
818
- ( GEPi ( bcx, val, & [ 0 , field] ) ,
819
- type_of:: type_of ( bcx. ccx ( ) , nonnull. fields [ field] ) ) ,
820
- FatPointer ( field) => {
821
- let v = GEPi ( bcx, val, & [ 0 , field, abi:: FAT_PTR_ADDR ] ) ;
822
- ( v, val_ty ( v) . element_type ( ) )
823
- }
824
- } ;
831
+ let llptrptr = GEPi ( bcx, val, discrfield[ ] ) ;
832
+ let llptrty = val_ty ( llptrptr) . element_type ( ) ;
825
833
Store ( bcx, C_null ( llptrty) , llptrptr)
826
834
}
827
835
}
@@ -1041,7 +1049,7 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, r: &Repr<'tcx>, discr
1041
1049
false )
1042
1050
} else {
1043
1051
let vals = nonnull. fields . iter ( ) . map ( |& ty| {
1044
- // Always use null even if it's not the `ptrfield `th
1052
+ // Always use null even if it's not the `discrfield `th
1045
1053
// field; see #8506.
1046
1054
C_null ( type_of:: sizing_type_of ( ccx, ty) )
1047
1055
} ) . collect :: < Vec < ValueRef > > ( ) ;
@@ -1121,9 +1129,8 @@ fn padding(ccx: &CrateContext, size: u64) -> ValueRef {
1121
1129
#[ inline]
1122
1130
fn roundup ( x : u64 , a : u32 ) -> u64 { let a = a as u64 ; ( ( x + ( a - 1 ) ) / a) * a }
1123
1131
1124
- /// Get the discriminant of a constant value. (Not currently used.)
1125
- pub fn const_get_discrim ( ccx : & CrateContext , r : & Repr , val : ValueRef )
1126
- -> Disr {
1132
+ /// Get the discriminant of a constant value.
1133
+ pub fn const_get_discrim ( ccx : & CrateContext , r : & Repr , val : ValueRef ) -> Disr {
1127
1134
match * r {
1128
1135
CEnum ( ity, _, _) => {
1129
1136
match ity {
@@ -1138,25 +1145,8 @@ pub fn const_get_discrim(ccx: &CrateContext, r: &Repr, val: ValueRef)
1138
1145
}
1139
1146
}
1140
1147
Univariant ( ..) => 0 ,
1141
- RawNullablePointer { nndiscr, .. } => {
1142
- if is_null ( val) {
1143
- /* subtraction as uint is ok because nndiscr is either 0 or 1 */
1144
- ( 1 - nndiscr) as Disr
1145
- } else {
1146
- nndiscr
1147
- }
1148
- }
1149
- StructWrappedNullablePointer { nndiscr, ptrfield, .. } => {
1150
- let ( idx, sub_idx) = match ptrfield {
1151
- ThinPointer ( field) => ( field, None ) ,
1152
- FatPointer ( field) => ( field, Some ( abi:: FAT_PTR_ADDR ) )
1153
- } ;
1154
- if is_null ( const_struct_field ( ccx, val, idx, sub_idx) ) {
1155
- /* subtraction as uint is ok because nndiscr is either 0 or 1 */
1156
- ( 1 - nndiscr) as Disr
1157
- } else {
1158
- nndiscr
1159
- }
1148
+ RawNullablePointer { .. } | StructWrappedNullablePointer { .. } => {
1149
+ ccx. sess ( ) . bug ( "const discrim access of non c-like enum" )
1160
1150
}
1161
1151
}
1162
1152
}
@@ -1170,29 +1160,25 @@ pub fn const_get_field(ccx: &CrateContext, r: &Repr, val: ValueRef,
1170
1160
_discr : Disr , ix : uint ) -> ValueRef {
1171
1161
match * r {
1172
1162
CEnum ( ..) => ccx. sess ( ) . bug ( "element access in C-like enum const" ) ,
1173
- Univariant ( ..) => const_struct_field ( ccx, val, ix, None ) ,
1174
- General ( ..) => const_struct_field ( ccx, val, ix + 1 , None ) ,
1163
+ Univariant ( ..) => const_struct_field ( ccx, val, ix) ,
1164
+ General ( ..) => const_struct_field ( ccx, val, ix + 1 ) ,
1175
1165
RawNullablePointer { .. } => {
1176
1166
assert_eq ! ( ix, 0 ) ;
1177
1167
val
1178
- }
1179
- StructWrappedNullablePointer { .. } => const_struct_field ( ccx, val, ix, None )
1168
+ } ,
1169
+ StructWrappedNullablePointer { .. } => const_struct_field ( ccx, val, ix)
1180
1170
}
1181
1171
}
1182
1172
1183
1173
/// Extract field of struct-like const, skipping our alignment padding.
1184
- fn const_struct_field ( ccx : & CrateContext , val : ValueRef , ix : uint , sub_idx : Option < uint > )
1185
- -> ValueRef {
1174
+ fn const_struct_field ( ccx : & CrateContext , val : ValueRef , ix : uint ) -> ValueRef {
1186
1175
// Get the ix-th non-undef element of the struct.
1187
1176
let mut real_ix = 0 ; // actual position in the struct
1188
1177
let mut ix = ix; // logical index relative to real_ix
1189
1178
let mut field;
1190
1179
loop {
1191
1180
loop {
1192
- field = match sub_idx {
1193
- Some ( si) => const_get_elt ( ccx, val, & [ real_ix, si as u32 ] ) ,
1194
- None => const_get_elt ( ccx, val, & [ real_ix] )
1195
- } ;
1181
+ field = const_get_elt ( ccx, val, & [ real_ix] ) ;
1196
1182
if !is_undef ( field) {
1197
1183
break ;
1198
1184
}
0 commit comments