@@ -7,6 +7,7 @@ use crate::spirv_type::SpirvType;
7
7
use rspirv:: spirv:: { StorageClass , Word } ;
8
8
use rustc_data_structures:: fx:: FxHashMap ;
9
9
use rustc_errors:: ErrorReported ;
10
+ use rustc_index:: vec:: Idx ;
10
11
use rustc_middle:: bug;
11
12
use rustc_middle:: ty:: layout:: { FnAbiExt , TyAndLayout } ;
12
13
use rustc_middle:: ty:: subst:: SubstsRef ;
@@ -18,7 +19,7 @@ use rustc_span::Span;
18
19
use rustc_span:: DUMMY_SP ;
19
20
use rustc_target:: abi:: call:: { CastTarget , FnAbi , PassMode , Reg , RegKind } ;
20
21
use rustc_target:: abi:: {
21
- Abi , Align , FieldsShape , LayoutOf , Primitive , Scalar , Size , TagEncoding , VariantIdx , Variants ,
22
+ Abi , Align , FieldsShape , LayoutOf , Primitive , Scalar , Size , VariantIdx , Variants ,
22
23
} ;
23
24
use std:: cell:: RefCell ;
24
25
use std:: collections:: hash_map:: Entry ;
@@ -349,15 +350,15 @@ fn trans_type_impl<'tcx>(
349
350
field_names : None ,
350
351
}
351
352
. def_with_name ( cx, span, TyLayoutNameKey :: from ( ty) ) ,
352
- Abi :: Scalar ( ref scalar) => trans_scalar ( cx, span, ty, scalar, None , is_immediate) ,
353
+ Abi :: Scalar ( ref scalar) => trans_scalar ( cx, span, ty, scalar, Size :: ZERO , is_immediate) ,
353
354
Abi :: ScalarPair ( ref a, ref b) => {
354
355
// Note: We can't use auto_struct_layout here because the spirv types here might be undefined due to
355
356
// recursive pointer types.
356
357
let a_offset = Size :: ZERO ;
357
358
let b_offset = a. value . size ( cx) . align_to ( b. value . align ( cx) . abi ) ;
358
359
// Note! Do not pass through is_immediate here - they're wrapped in a struct, hence, not immediate.
359
- let a = trans_scalar ( cx, span, ty, a, Some ( a_offset) , false ) ;
360
- let b = trans_scalar ( cx, span, ty, b, Some ( b_offset) , false ) ;
360
+ let a = trans_scalar ( cx, span, ty, a, a_offset, false ) ;
361
+ let b = trans_scalar ( cx, span, ty, b, b_offset, false ) ;
361
362
let size = if ty. is_unsized ( ) { None } else { Some ( ty. size ) } ;
362
363
SpirvType :: Adt {
363
364
def_id : def_id_for_spirv_type_adt ( ty) ,
@@ -370,7 +371,7 @@ fn trans_type_impl<'tcx>(
370
371
. def_with_name ( cx, span, TyLayoutNameKey :: from ( ty) )
371
372
}
372
373
Abi :: Vector { ref element, count } => {
373
- let elem_spirv = trans_scalar ( cx, span, ty, element, None , false ) ;
374
+ let elem_spirv = trans_scalar ( cx, span, ty, element, Size :: ZERO , false ) ;
374
375
SpirvType :: Vector {
375
376
element : elem_spirv,
376
377
count : count as u32 ,
@@ -399,7 +400,7 @@ pub fn scalar_pair_element_backend_type<'tcx>(
399
400
1 => a. value . size ( cx) . align_to ( b. value . align ( cx) . abi ) ,
400
401
_ => unreachable ! ( ) ,
401
402
} ;
402
- trans_scalar ( cx, span, ty, [ a, b] [ index] , Some ( offset) , is_immediate)
403
+ trans_scalar ( cx, span, ty, [ a, b] [ index] , offset, is_immediate)
403
404
}
404
405
405
406
/// A "scalar" is a basic building block: bools, ints, floats, pointers. (i.e. not something complex like a struct)
@@ -414,7 +415,7 @@ fn trans_scalar<'tcx>(
414
415
span : Span ,
415
416
ty : TyAndLayout < ' tcx > ,
416
417
scalar : & Scalar ,
417
- scalar_pair_field_offset : Option < Size > ,
418
+ offset : Size ,
418
419
is_immediate : bool ,
419
420
) -> Word {
420
421
if is_immediate && scalar. is_bool ( ) {
@@ -428,7 +429,7 @@ fn trans_scalar<'tcx>(
428
429
Primitive :: F32 => SpirvType :: Float ( 32 ) . def ( span, cx) ,
429
430
Primitive :: F64 => SpirvType :: Float ( 64 ) . def ( span, cx) ,
430
431
Primitive :: Pointer => {
431
- let pointee_ty = dig_scalar_pointee ( cx, ty, scalar_pair_field_offset ) ;
432
+ let pointee_ty = dig_scalar_pointee ( cx, ty, offset ) ;
432
433
// Pointers can be recursive. So, record what we're currently translating, and if we're already translating
433
434
// the same type, emit an OpTypeForwardPointer and use that ID.
434
435
if let Some ( predefined_result) = cx
@@ -459,125 +460,72 @@ fn trans_scalar<'tcx>(
459
460
// If the above didn't make sense, please poke Ashley, it's probably easier to explain via conversation.
460
461
fn dig_scalar_pointee < ' tcx > (
461
462
cx : & CodegenCx < ' tcx > ,
462
- ty : TyAndLayout < ' tcx > ,
463
- scalar_pair_field_offset : Option < Size > ,
463
+ layout : TyAndLayout < ' tcx > ,
464
+ offset : Size ,
464
465
) -> PointeeTy < ' tcx > {
465
- match * ty. ty . kind ( ) {
466
- TyKind :: Ref ( _, elem_ty, _) | TyKind :: RawPtr ( TypeAndMut { ty : elem_ty, .. } ) => {
467
- let elem = cx. layout_of ( elem_ty) ;
468
- match scalar_pair_field_offset {
469
- None => PointeeTy :: Ty ( elem) ,
470
- Some ( scalar_pair_field_offset) => {
471
- if elem. is_unsized ( ) {
472
- let field_idx = if scalar_pair_field_offset == Size :: ZERO {
473
- 0
474
- } else {
475
- 1
476
- } ;
477
- dig_scalar_pointee ( cx, ty. field ( cx, field_idx) , None )
478
- } else {
479
- // This can sometimes happen in weird cases when going through the Adt case below - an ABI
480
- // of ScalarPair could be deduced, but it's actually e.g. a sized pointer followed by some other
481
- // completely unrelated type, not a wide pointer. So, translate this as a single scalar, one
482
- // component of that ScalarPair.
483
- PointeeTy :: Ty ( elem)
484
- }
485
- }
466
+ if let FieldsShape :: Primitive = layout. fields {
467
+ assert_eq ! ( offset, Size :: ZERO ) ;
468
+ let pointee = match * layout. ty . kind ( ) {
469
+ TyKind :: Ref ( _, pointee_ty, _) | TyKind :: RawPtr ( TypeAndMut { ty : pointee_ty, .. } ) => {
470
+ PointeeTy :: Ty ( cx. layout_of ( pointee_ty) )
486
471
}
487
- }
488
- TyKind :: FnPtr ( sig) if scalar_pair_field_offset. is_none ( ) => PointeeTy :: Fn ( sig) ,
489
- TyKind :: Adt ( def, _) if def. is_box ( ) => {
490
- let ptr_ty = cx. layout_of ( cx. tcx . mk_mut_ptr ( ty. ty . boxed_ty ( ) ) ) ;
491
- dig_scalar_pointee ( cx, ptr_ty, scalar_pair_field_offset)
492
- }
493
- TyKind :: Tuple ( _) | TyKind :: Adt ( ..) | TyKind :: Closure ( ..) => {
494
- dig_scalar_pointee_adt ( cx, ty, scalar_pair_field_offset)
495
- }
496
- ref kind => cx. tcx . sess . fatal ( & format ! (
497
- "TODO: Unimplemented Primitive::Pointer TyKind scalar_pair_field_offset={:?} ({:#?}):\n {:#?}" ,
498
- scalar_pair_field_offset, kind, ty
499
- ) ) ,
472
+ TyKind :: FnPtr ( sig) => PointeeTy :: Fn ( sig) ,
473
+ _ => bug ! ( "Pointer is not `&T`, `*T` or `fn` pointer: {:#?}" , layout) ,
474
+ } ;
475
+ return pointee;
500
476
}
501
- }
502
477
503
- fn dig_scalar_pointee_adt < ' tcx > (
504
- cx : & CodegenCx < ' tcx > ,
505
- ty : TyAndLayout < ' tcx > ,
506
- scalar_pair_field_offset : Option < Size > ,
507
- ) -> PointeeTy < ' tcx > {
508
- match & ty. variants {
509
- // If it's a Variants::Multiple, then we want to emit the type of the dataful variant, not the type of the
510
- // discriminant. This is because the discriminant can e.g. have type *mut(), whereas we want the full underlying
511
- // type, only available in the dataful variant.
512
- Variants :: Multiple {
513
- tag_encoding,
514
- tag_field,
515
- variants,
516
- ..
517
- } => {
518
- match * tag_encoding {
519
- TagEncoding :: Direct => cx. tcx . sess . fatal ( & format ! (
520
- "dig_scalar_pointee_adt Variants::Multiple TagEncoding::Direct makes no sense: {:#?}" ,
521
- ty
522
- ) ) ,
523
- TagEncoding :: Niche { dataful_variant, .. } => {
524
- // This *should* be something like Option<&T>: a very simple enum.
525
- // TODO: This might not be, if it's a scalar pair?
526
- assert_eq ! ( 1 , ty. fields. count( ) ) ;
527
- assert_eq ! ( 1 , variants[ dataful_variant] . fields. count( ) ) ;
528
- if let TyKind :: Adt ( adt, substs) = ty. ty . kind ( ) {
529
- assert_eq ! ( 1 , adt. variants[ dataful_variant] . fields. len( ) ) ;
530
- assert_eq ! ( 0 , * tag_field) ;
531
- let field_ty = adt. variants [ dataful_variant] . fields [ 0 ] . ty ( cx. tcx , substs) ;
532
- dig_scalar_pointee ( cx, cx. layout_of ( field_ty) , scalar_pair_field_offset)
533
- } else {
534
- bug ! ( "Variants::Multiple not TyKind::Adt: {:#?}" , ty)
535
- }
536
- } ,
537
- }
478
+ let all_fields = ( match & layout. variants {
479
+ Variants :: Multiple { variants, .. } => 0 ..variants. len ( ) ,
480
+ Variants :: Single { index } => {
481
+ let i = index. as_usize ( ) ;
482
+ i..i + 1
538
483
}
539
- Variants :: Single { .. } => {
540
- let fields = ty
541
- . fields
542
- . index_by_increasing_offset ( )
543
- . map ( |f| ty. field ( cx, f) )
544
- . filter ( |f| !f. is_zst ( ) )
545
- . collect :: < Vec < _ > > ( ) ;
546
- match scalar_pair_field_offset {
547
- Some ( scalar_pair_field_offset) => match fields. len ( ) {
548
- 1 => dig_scalar_pointee ( cx, fields[ 0 ] , Some ( scalar_pair_field_offset) ) ,
549
- // This case right here is the cause of the comment handling TyKind::Ref.
550
- 2 => {
551
- let field_idx = if scalar_pair_field_offset == Size :: ZERO {
552
- 0
553
- } else {
554
- 1
555
- } ;
556
- dig_scalar_pointee ( cx, fields[ field_idx] , None )
557
- }
558
- other => cx. tcx . sess . fatal ( & format ! (
559
- "Unable to dig scalar pair pointer type: fields length {}" ,
560
- other
561
- ) ) ,
562
- } ,
563
- None => match fields. len ( ) {
564
- 1 => dig_scalar_pointee ( cx, fields[ 0 ] , None ) ,
565
- other => cx. tcx . sess . fatal ( & format ! (
566
- "Unable to dig scalar pointer type: fields length {}" ,
567
- other
568
- ) ) ,
569
- } ,
484
+ } )
485
+ . flat_map ( |variant_idx| {
486
+ let variant = layout. for_variant ( cx, VariantIdx :: new ( variant_idx) ) ;
487
+ ( 0 ..variant. fields . count ( ) ) . map ( move |field_idx| {
488
+ (
489
+ variant. field ( cx, field_idx) ,
490
+ variant. fields . offset ( field_idx) ,
491
+ )
492
+ } )
493
+ } ) ;
494
+
495
+ let mut pointee = None ;
496
+ for ( field, field_offset) in all_fields {
497
+ if field. is_zst ( ) {
498
+ continue ;
499
+ }
500
+ if ( field_offset..field_offset + field. size ) . contains ( & offset) {
501
+ let new_pointee = dig_scalar_pointee ( cx, field, offset - field_offset) ;
502
+ match pointee {
503
+ Some ( old_pointee) if old_pointee != new_pointee => {
504
+ cx. tcx . sess . fatal ( & format ! (
505
+ "dig_scalar_pointee: unsupported Pointer with different \
506
+ pointee types ({:?} vs {:?}) at offset {:?} in {:#?}",
507
+ old_pointee, new_pointee, offset, layout
508
+ ) ) ;
509
+ }
510
+ _ => pointee = Some ( new_pointee) ,
570
511
}
571
512
}
572
513
}
514
+ pointee. unwrap_or_else ( || {
515
+ bug ! (
516
+ "field containing Pointer scalar at offset {:?} not found in {:#?}" ,
517
+ offset,
518
+ layout
519
+ )
520
+ } )
573
521
}
574
522
575
523
fn trans_aggregate < ' tcx > ( cx : & CodegenCx < ' tcx > , span : Span , ty : TyAndLayout < ' tcx > ) -> Word {
576
524
match ty. fields {
577
- FieldsShape :: Primitive => cx . tcx . sess . fatal ( & format ! (
578
- "FieldsShape::Primitive not supported yet in trans_type: {: ?}" ,
525
+ FieldsShape :: Primitive => bug ! (
526
+ "trans_aggregate called for FieldsShape::Primitive layout {:# ?}" ,
579
527
ty
580
- ) ) ,
528
+ ) ,
581
529
FieldsShape :: Union ( _) => {
582
530
assert_ne ! ( ty. size. bytes( ) , 0 , "{:#?}" , ty) ;
583
531
assert ! ( !ty. is_unsized( ) , "{:#?}" , ty) ;
0 commit comments