10
10
11
11
use llvm:: { self , ValueRef } ;
12
12
use rustc:: ty:: { self , Ty , TypeFoldable } ;
13
- use rustc:: ty:: layout:: { self , Align , Layout , LayoutOf , Size } ;
13
+ use rustc:: ty:: layout:: { self , Align , Layout , LayoutOf } ;
14
14
use rustc:: mir;
15
15
use rustc:: mir:: tcx:: LvalueTy ;
16
16
use rustc_data_structures:: indexed_vec:: Idx ;
@@ -205,50 +205,68 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
205
205
l = l. for_variant ( variant_index)
206
206
}
207
207
}
208
- let fty = l. field ( ccx, ix) . ty ;
208
+ let field = l. field ( ccx, ix) ;
209
+ let offset = l. fields . offset ( ix) . bytes ( ) ;
209
210
210
211
let alignment = self . alignment | Alignment :: from ( & * l) ;
211
212
212
213
// Handle all the non-aggregate cases first.
213
214
match * l {
214
215
layout:: UntaggedUnion { .. } => {
215
- let ty = ccx. llvm_type_of ( fty ) ;
216
+ let ty = ccx. llvm_type_of ( field . ty ) ;
216
217
return LvalueRef :: new_sized (
217
- bcx. pointercast ( self . llval , ty. ptr_to ( ) ) , fty , alignment) ;
218
+ bcx. pointercast ( self . llval , ty. ptr_to ( ) ) , field . ty , alignment) ;
218
219
}
219
- layout:: General { .. } if l. variant_index . is_none ( ) => {
220
- let ty = ccx. llvm_type_of ( fty) ;
220
+ // Discriminant field of enums.
221
+ layout:: General { .. } |
222
+ layout:: RawNullablePointer { .. } |
223
+ layout:: StructWrappedNullablePointer { .. } if l. variant_index . is_none ( ) => {
224
+ let ty = ccx. llvm_type_of ( field. ty ) ;
225
+ let size = field. size ( ccx) . bytes ( ) ;
226
+
227
+ // If the discriminant is not on a multiple of the primitive's size,
228
+ // we need to go through i8*. Also assume the worst alignment.
229
+ if offset % size != 0 {
230
+ let byte_ptr = bcx. pointercast ( self . llval , Type :: i8p ( ccx) ) ;
231
+ let byte_ptr = bcx. inbounds_gep ( byte_ptr, & [ C_usize ( ccx, offset) ] ) ;
232
+ let byte_align = Alignment :: Packed ( Align :: from_bytes ( 1 , 1 ) . unwrap ( ) ) ;
233
+ return LvalueRef :: new_sized (
234
+ bcx. pointercast ( byte_ptr, ty. ptr_to ( ) ) , field. ty , byte_align) ;
235
+ }
236
+
237
+ let discr_ptr = bcx. pointercast ( self . llval , ty. ptr_to ( ) ) ;
221
238
return LvalueRef :: new_sized (
222
- bcx. pointercast ( self . llval , ty. ptr_to ( ) ) , fty, alignment) ;
239
+ bcx. inbounds_gep ( discr_ptr, & [ C_usize ( ccx, offset / size) ] ) ,
240
+ field. ty , alignment) ;
223
241
}
224
242
layout:: RawNullablePointer { nndiscr, .. } |
225
243
layout:: StructWrappedNullablePointer { nndiscr, .. }
226
244
if l. variant_index . unwrap ( ) as u64 != nndiscr => {
227
245
// The unit-like case might have a nonzero number of unit-like fields.
228
246
// (e.d., Result of Either with (), as one side.)
229
- let ty = ccx. llvm_type_of ( fty ) ;
230
- assert_eq ! ( ccx . size_of ( fty ) . bytes( ) , 0 ) ;
247
+ let ty = ccx. llvm_type_of ( field . ty ) ;
248
+ assert_eq ! ( field . size ( ccx ) . bytes( ) , 0 ) ;
231
249
return LvalueRef :: new_sized (
232
- bcx. pointercast ( self . llval , ty. ptr_to ( ) ) , fty ,
250
+ bcx. pointercast ( self . llval , ty. ptr_to ( ) ) , field . ty ,
233
251
Alignment :: Packed ( Align :: from_bytes ( 1 , 1 ) . unwrap ( ) ) ) ;
234
252
}
235
253
layout:: RawNullablePointer { .. } => {
236
- let ty = ccx. llvm_type_of ( fty ) ;
254
+ let ty = ccx. llvm_type_of ( field . ty ) ;
237
255
return LvalueRef :: new_sized (
238
- bcx. pointercast ( self . llval , ty. ptr_to ( ) ) , fty , alignment) ;
256
+ bcx. pointercast ( self . llval , ty. ptr_to ( ) ) , field . ty , alignment) ;
239
257
}
240
258
_ => { }
241
259
}
242
260
243
261
let simple = || {
244
262
LvalueRef {
245
263
llval : bcx. struct_gep ( self . llval , l. llvm_field_index ( ix) ) ,
246
- llextra : if !ccx. shared ( ) . type_has_metadata ( fty) {
247
- ptr:: null_mut ( )
248
- } else {
264
+ llextra : if ccx. shared ( ) . type_has_metadata ( field. ty ) {
249
265
self . llextra
266
+ } else {
267
+ ptr:: null_mut ( )
250
268
} ,
251
- ty : LvalueTy :: from_ty ( fty ) ,
269
+ ty : LvalueTy :: from_ty ( field . ty ) ,
252
270
alignment,
253
271
}
254
272
} ;
@@ -264,13 +282,13 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
264
282
// Simple case - we can just GEP the field
265
283
// * Packed struct - There is no alignment padding
266
284
// * Field is sized - pointer is properly aligned already
267
- if is_packed || ccx . shared ( ) . type_is_sized ( fty ) {
285
+ if is_packed || !field . is_unsized ( ) {
268
286
return simple ( ) ;
269
287
}
270
288
271
289
// If the type of the last field is [T], str or a foreign type, then we don't need to do
272
290
// any adjusments
273
- match fty . sty {
291
+ match field . ty . sty {
274
292
ty:: TySlice ( ..) | ty:: TyStr | ty:: TyForeign ( ..) => return simple ( ) ,
275
293
_ => ( )
276
294
}
@@ -299,12 +317,10 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
299
317
300
318
let meta = self . llextra ;
301
319
302
-
303
- let offset = l. fields . offset ( ix) . bytes ( ) ;
304
320
let unaligned_offset = C_usize ( ccx, offset) ;
305
321
306
322
// Get the alignment of the field
307
- let ( _, align) = glue:: size_and_align_of_dst ( bcx, fty , meta) ;
323
+ let ( _, align) = glue:: size_and_align_of_dst ( bcx, field . ty , meta) ;
308
324
309
325
// Bump the unaligned offset up to the appropriate alignment using the
310
326
// following expression:
@@ -323,39 +339,17 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
323
339
let byte_ptr = bcx. gep ( byte_ptr, & [ offset] ) ;
324
340
325
341
// Finally, cast back to the type expected
326
- let ll_fty = ccx. llvm_type_of ( fty ) ;
342
+ let ll_fty = ccx. llvm_type_of ( field . ty ) ;
327
343
debug ! ( "struct_field_ptr: Field type is {:?}" , ll_fty) ;
328
344
329
345
LvalueRef {
330
346
llval : bcx. pointercast ( byte_ptr, ll_fty. ptr_to ( ) ) ,
331
347
llextra : self . llextra ,
332
- ty : LvalueTy :: from_ty ( fty ) ,
348
+ ty : LvalueTy :: from_ty ( field . ty ) ,
333
349
alignment,
334
350
}
335
351
}
336
352
337
- // Return a pointer to the discriminant, given its type and offset.
338
- fn gepi_discr_at_offset ( self , bcx : & Builder ,
339
- discr : ty:: layout:: Primitive ,
340
- offset : Size )
341
- -> ( ValueRef , Alignment ) {
342
- let size = discr. size ( bcx. ccx ) ;
343
- let ptr_ty = Type :: from_primitive ( bcx. ccx , discr) . ptr_to ( ) ;
344
-
345
- // If the discriminant is not on a multiple of the primitive's size,
346
- // we need to go through i8*. Also assume the worst alignment.
347
- if offset. bytes ( ) % size. bytes ( ) != 0 {
348
- let byte_ptr = bcx. pointercast ( self . llval , Type :: i8p ( bcx. ccx ) ) ;
349
- let byte_ptr = bcx. inbounds_gep ( byte_ptr, & [ C_usize ( bcx. ccx , offset. bytes ( ) ) ] ) ;
350
- let byte_align = Alignment :: Packed ( Align :: from_bytes ( 1 , 1 ) . unwrap ( ) ) ;
351
- return ( bcx. pointercast ( byte_ptr, ptr_ty) , byte_align) ;
352
- }
353
-
354
- let discr_ptr = bcx. pointercast ( self . llval , ptr_ty) ;
355
- ( bcx. inbounds_gep ( discr_ptr, & [ C_usize ( bcx. ccx , offset. bytes ( ) / size. bytes ( ) ) ] ) ,
356
- self . alignment )
357
- }
358
-
359
353
/// Helper for cases where the discriminant is simply loaded.
360
354
fn load_discr ( self , bcx : & Builder , ity : layout:: Integer , ptr : ValueRef ,
361
355
min : u64 , max : u64 ) -> ValueRef {
@@ -394,16 +388,12 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
394
388
self . load_discr ( bcx, discr, ptr. llval , 0 , variants. len ( ) as u64 - 1 )
395
389
}
396
390
layout:: Univariant { .. } | layout:: UntaggedUnion { .. } => C_u8 ( bcx. ccx , 0 ) ,
397
- layout:: RawNullablePointer { nndiscr, discr } |
398
- layout:: StructWrappedNullablePointer { nndiscr, discr, .. } => {
399
- let discr_offset = match * l {
400
- layout:: StructWrappedNullablePointer { discr_offset, .. } => discr_offset,
401
- _ => Size :: from_bytes ( 0 ) ,
402
- } ;
403
- let ( lldiscrptr, alignment) = self . gepi_discr_at_offset ( bcx, discr, discr_offset) ;
404
- let lldiscr = bcx. load ( lldiscrptr, alignment. non_abi ( ) ) ;
391
+ layout:: RawNullablePointer { nndiscr, .. } |
392
+ layout:: StructWrappedNullablePointer { nndiscr, .. } => {
393
+ let ptr = self . project_field ( bcx, 0 ) ;
394
+ let lldiscr = bcx. load ( ptr. llval , ptr. alignment . non_abi ( ) ) ;
405
395
let cmp = if nndiscr == 0 { llvm:: IntEQ } else { llvm:: IntNE } ;
406
- bcx. icmp ( cmp, lldiscr, C_null ( Type :: from_primitive ( bcx. ccx , discr ) ) )
396
+ bcx. icmp ( cmp, lldiscr, C_null ( bcx. ccx . llvm_type_of ( ptr . ty . to_ty ( bcx . tcx ( ) ) ) ) )
407
397
} ,
408
398
_ => bug ! ( "{} is not an enum" , l. ty)
409
399
} ;
@@ -434,14 +424,14 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
434
424
| layout:: Vector { .. } => {
435
425
assert_eq ! ( to, 0 ) ;
436
426
}
437
- layout:: RawNullablePointer { nndiscr, discr , .. } |
438
- layout:: StructWrappedNullablePointer { nndiscr, discr , .. } => {
427
+ layout:: RawNullablePointer { nndiscr, .. } |
428
+ layout:: StructWrappedNullablePointer { nndiscr, .. } => {
439
429
if to != nndiscr {
440
- let ( use_memset, discr_offset ) = match * l {
441
- layout:: StructWrappedNullablePointer { discr_offset , .. } => {
442
- ( target_sets_discr_via_memset ( bcx) , discr_offset )
430
+ let use_memset = match * l {
431
+ layout:: StructWrappedNullablePointer { .. } => {
432
+ target_sets_discr_via_memset ( bcx)
443
433
}
444
- _ => ( false , Size :: from_bytes ( 0 ) ) ,
434
+ _ => false ,
445
435
} ;
446
436
if use_memset {
447
437
// Issue #34427: As workaround for LLVM bug on
@@ -454,10 +444,9 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
454
444
let align = C_u32 ( bcx. ccx , align. abi ( ) as u32 ) ;
455
445
base:: call_memset ( bcx, llptr, fill_byte, size, align, false ) ;
456
446
} else {
457
- let ( lldiscrptr, alignment) =
458
- self . gepi_discr_at_offset ( bcx, discr, discr_offset) ;
459
- bcx. store ( C_null ( Type :: from_primitive ( bcx. ccx , discr) ) ,
460
- lldiscrptr, alignment. non_abi ( ) ) ;
447
+ let ptr = self . project_field ( bcx, 0 ) ;
448
+ bcx. store ( C_null ( bcx. ccx . llvm_type_of ( ptr. ty . to_ty ( bcx. tcx ( ) ) ) ) ,
449
+ ptr. llval , ptr. alignment . non_abi ( ) ) ;
461
450
}
462
451
}
463
452
}
0 commit comments