@@ -235,7 +235,6 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
235
235
236
236
// Discriminant field of enums.
237
237
match * l {
238
- layout:: General { .. } |
239
238
layout:: NullablePointer { .. } if l. variant_index . is_none ( ) => {
240
239
let ty = ccx. llvm_type_of ( field. ty ) ;
241
240
let size = field. size ( ccx) . bytes ( ) ;
@@ -350,60 +349,66 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
350
349
}
351
350
}
352
351
353
- /// Helper for cases where the discriminant is simply loaded.
354
- fn load_discr ( self , bcx : & Builder , discr : layout:: Primitive , min : u64 , max : u64 ) -> ValueRef {
355
- if let layout:: Int ( ity, _) = discr {
356
- let bits = ity. size ( ) . bits ( ) ;
357
- assert ! ( bits <= 64 ) ;
358
- let bits = bits as usize ;
359
- let mask = !0u64 >> ( 64 - bits) ;
360
- // For a (max) discr of -1, max will be `-1 as usize`, which overflows.
361
- // However, that is fine here (it would still represent the full range),
362
- if max. wrapping_add ( 1 ) & mask == min & mask {
363
- // i.e., if the range is everything. The lo==hi case would be
364
- // rejected by the LLVM verifier (it would mean either an
365
- // empty set, which is impossible, or the entire range of the
366
- // type, which is pointless).
367
- } else {
368
- // llvm::ConstantRange can deal with ranges that wrap around,
369
- // so an overflow on (max + 1) is fine.
370
- return bcx. load_range_assert ( self . llval , min, max. wrapping_add ( 1 ) ,
371
- /* signed: */ llvm:: True ,
372
- self . alignment . non_abi ( ) ) ;
373
- }
374
- }
375
- bcx. load ( self . llval , self . alignment . non_abi ( ) )
376
- }
377
-
378
352
/// Obtain the actual discriminant of a value.
379
353
pub fn trans_get_discr ( self , bcx : & Builder < ' a , ' tcx > , cast_to : Ty < ' tcx > ) -> ValueRef {
380
354
let l = bcx. ccx . layout_of ( self . ty . to_ty ( bcx. tcx ( ) ) ) ;
381
355
382
356
let cast_to = bcx. ccx . immediate_llvm_type_of ( cast_to) ;
383
- let ( val , discr ) = match * l {
357
+ match * l {
384
358
layout:: Univariant { .. } |
385
359
layout:: UntaggedUnion { .. } => return C_uint ( cast_to, 0 ) ,
386
- layout:: CEnum { discr, min, max, .. } => {
387
- ( self . load_discr ( bcx, discr, min, max) , discr)
360
+ _ => { }
361
+ }
362
+
363
+ let discr = self . project_field ( bcx, 0 ) ;
364
+ let discr_layout = bcx. ccx . layout_of ( discr. ty . to_ty ( bcx. tcx ( ) ) ) ;
365
+ let discr_scalar = match discr_layout. abi {
366
+ layout:: Abi :: Scalar ( discr) => discr,
367
+ _ => bug ! ( "discriminant not scalar: {:#?}" , discr_layout)
368
+ } ;
369
+ let ( min, max) = match * l {
370
+ layout:: CEnum { min, max, .. } => ( min, max) ,
371
+ layout:: General { ref variants, .. } => ( 0 , variants. len ( ) as u64 - 1 ) ,
372
+ _ => ( 0 , u64:: max_value ( ) ) ,
373
+ } ;
374
+ let max_next = max. wrapping_add ( 1 ) ;
375
+ let bits = discr_scalar. size ( bcx. ccx ) . bits ( ) ;
376
+ assert ! ( bits <= 64 ) ;
377
+ let mask = !0u64 >> ( 64 - bits) ;
378
+ let lldiscr = match discr_scalar {
379
+ // For a (max) discr of -1, max will be `-1 as usize`, which overflows.
380
+ // However, that is fine here (it would still represent the full range),
381
+ layout:: Int ( ..) if max_next & mask != min & mask => {
382
+ // llvm::ConstantRange can deal with ranges that wrap around,
383
+ // so an overflow on (max + 1) is fine.
384
+ bcx. load_range_assert ( discr. llval , min, max_next,
385
+ /* signed: */ llvm:: True ,
386
+ discr. alignment . non_abi ( ) )
388
387
}
389
- layout:: General { discr, ref variants, .. } => {
390
- let ptr = self . project_field ( bcx, 0 ) ;
391
- ( ptr. load_discr ( bcx, discr, 0 , variants. len ( ) as u64 - 1 ) , discr)
388
+ _ => {
389
+ // i.e., if the range is everything. The lo==hi case would be
390
+ // rejected by the LLVM verifier (it would mean either an
391
+ // empty set, which is impossible, or the entire range of the
392
+ // type, which is pointless).
393
+ bcx. load ( discr. llval , discr. alignment . non_abi ( ) )
394
+ }
395
+ } ;
396
+ match * l {
397
+ layout:: CEnum { .. } |
398
+ layout:: General { .. } => {
399
+ let signed = match discr_scalar {
400
+ layout:: Int ( _, signed) => signed,
401
+ _ => false
402
+ } ;
403
+ bcx. intcast ( lldiscr, cast_to, signed)
392
404
}
393
405
layout:: NullablePointer { nndiscr, .. } => {
394
- let ptr = self . project_field ( bcx, 0 ) ;
395
- let lldiscr = bcx. load ( ptr. llval , ptr. alignment . non_abi ( ) ) ;
396
406
let cmp = if nndiscr == 0 { llvm:: IntEQ } else { llvm:: IntNE } ;
397
- ( bcx . icmp ( cmp , lldiscr , C_null ( bcx. ccx . llvm_type_of ( ptr . ty . to_ty ( bcx . tcx ( ) ) ) ) ) ,
398
- layout :: Int ( layout :: I1 , false ) )
399
- } ,
407
+ let zero = C_null ( bcx. ccx . llvm_type_of ( discr_layout . ty ) ) ;
408
+ bcx . intcast ( bcx . icmp ( cmp , lldiscr , zero ) , cast_to , false )
409
+ }
400
410
_ => bug ! ( "{} is not an enum" , l. ty)
401
- } ;
402
- let signed = match discr {
403
- layout:: Int ( _, signed) => signed,
404
- _ => false
405
- } ;
406
- bcx. intcast ( val, cast_to, signed)
411
+ }
407
412
}
408
413
409
414
/// Set the discriminant for a new value of the given case of the given
@@ -414,20 +419,12 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
414
419
. discriminant_for_variant ( bcx. tcx ( ) , variant_index)
415
420
. to_u128_unchecked ( ) as u64 ;
416
421
match * l {
417
- layout:: CEnum { .. } => {
418
- bcx. store ( C_int ( bcx. ccx . llvm_type_of ( self . ty . to_ty ( bcx. tcx ( ) ) ) , to as i64 ) ,
419
- self . llval , self . alignment . non_abi ( ) ) ;
420
- }
422
+ layout:: CEnum { .. } |
421
423
layout:: General { .. } => {
422
424
let ptr = self . project_field ( bcx, 0 ) ;
423
425
bcx. store ( C_int ( bcx. ccx . llvm_type_of ( ptr. ty . to_ty ( bcx. tcx ( ) ) ) , to as i64 ) ,
424
426
ptr. llval , ptr. alignment . non_abi ( ) ) ;
425
427
}
426
- layout:: Univariant { .. }
427
- | layout:: UntaggedUnion { .. }
428
- | layout:: Vector { .. } => {
429
- assert_eq ! ( to, 0 ) ;
430
- }
431
428
layout:: NullablePointer { nndiscr, .. } => {
432
429
if to != nndiscr {
433
430
let use_memset = match l. abi {
@@ -451,7 +448,9 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
451
448
}
452
449
}
453
450
}
454
- _ => bug ! ( "Cannot handle {} represented as {:#?}" , l. ty, l)
451
+ _ => {
452
+ assert_eq ! ( to, 0 ) ;
453
+ }
455
454
}
456
455
}
457
456
0 commit comments