@@ -96,6 +96,14 @@ impl<'tcx> GotocCtx<'tcx> {
96
96
}
97
97
}
98
98
99
+ /// Is the MIR type a ref of an unsized type (i.e. one represented by a fat pointer?)
100
+ pub fn is_ref_of_sized ( & self , t : & ' tcx TyS < ' _ > ) -> bool {
101
+ match t. kind ( ) {
102
+ ty:: Ref ( _, to, _) | ty:: RawPtr ( ty:: TypeAndMut { ty : to, .. } ) => !self . is_unsized ( to) ,
103
+ _ => false ,
104
+ }
105
+ }
106
+
99
107
/// Is the MIR type a box of an unsized type (i.e. one represented by a fat pointer?)
100
108
pub fn is_box_of_unsized ( & self , t : & ' tcx TyS < ' _ > ) -> bool {
101
109
if t. is_box ( ) {
@@ -519,65 +527,61 @@ impl<'tcx> GotocCtx<'tcx> {
519
527
} )
520
528
}
521
529
522
- pub fn codegen_fat_ptr ( & mut self , t : Ty < ' tcx > ) -> Type {
523
- // implement "fat pointers", which are pointers with metadata.
524
- // to my knowledge, there are three kinds of fat pointers:
525
- // 1. references to slices
526
- // 2. references to trait objects.
527
- // 3. references to structs whose last field is a fat pointer
528
- match t. kind ( ) {
529
- ty:: Adt ( ..) if self . is_unsized ( t) => {
530
- // https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp
531
- let fat_ptr_name = format ! ( "&{}" , self . ty_mangled_name( t) ) ;
532
- self . ensure_struct ( & fat_ptr_name, |ctx, _| {
533
- vec ! [
534
- Type :: datatype_component( "data" , ctx. codegen_ty( t) . to_pointer( ) ) ,
535
- Type :: datatype_component( "len" , Type :: size_t( ) ) ,
536
- ]
537
- } )
538
- }
539
- ty:: Slice ( e) => {
540
- // a slice &[t] is translated to
541
- // struct {
542
- // t *data;
543
- // usize len;
544
- // }
545
- // c.f. core::ptr::FatPtr<T>
546
- let slice_name = self . ty_mangled_name ( t) ;
547
- self . ensure_struct ( & slice_name, |ctx, _| {
548
- vec ! [
549
- Type :: datatype_component( "data" , ctx. codegen_ty( e) . to_pointer( ) ) ,
550
- Type :: datatype_component( "len" , Type :: size_t( ) ) ,
551
- ]
552
- } )
553
- }
554
- ty:: Str => self . ensure_struct ( "str" , |_, _| {
530
+ pub fn codegen_fat_ptr ( & mut self , mir_type : Ty < ' tcx > ) -> Type {
531
+ assert ! (
532
+ !self . use_thin_pointer( mir_type) ,
533
+ "Generating a fat pointer for a type requiring a thin pointer: {:?}" ,
534
+ mir_type. kind( )
535
+ ) ;
536
+ if self . use_slice_fat_pointer ( mir_type) {
537
+ let pointer_name = match mir_type. kind ( ) {
538
+ ty:: Slice ( ..) => self . ty_mangled_name ( mir_type) ,
539
+ ty:: Str => "str" . to_string ( ) ,
540
+ ty:: Adt ( ..) => format ! ( "&{}" , self . ty_mangled_name( mir_type) ) ,
541
+ kind => unreachable ! ( "Generating a slice fat pointer to {:?}" , kind) ,
542
+ } ;
543
+ let element_type = match mir_type. kind ( ) {
544
+ ty:: Slice ( elt_type) => self . codegen_ty ( elt_type) ,
545
+ ty:: Str => Type :: c_char ( ) ,
546
+ // For adt, see https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp
547
+ ty:: Adt ( ..) => self . codegen_ty ( mir_type) ,
548
+ kind => unreachable ! ( "Generating a slice fat pointer to {:?}" , kind) ,
549
+ } ;
550
+ self . ensure_struct ( & pointer_name, |_, _| {
555
551
vec ! [
556
- Type :: datatype_component( "data" , Type :: c_char ( ) . to_pointer( ) ) ,
552
+ Type :: datatype_component( "data" , element_type . to_pointer( ) ) ,
557
553
Type :: datatype_component( "len" , Type :: size_t( ) ) ,
558
554
]
559
- } ) ,
560
- ty:: Dynamic ( binder, _region) => {
561
- debug ! ( "type codegen for dynamic with binder {:?} type {:?}" , binder, t) ;
562
- self . codegen_trait_vtable_type ( t) ;
563
- self . codegen_trait_fat_ptr_type ( t)
564
- }
565
-
566
- _ => unreachable ! ( ) ,
555
+ } )
556
+ } else if self . use_vtable_fat_pointer ( mir_type) {
557
+ let ( _, trait_type) =
558
+ self . nested_pair_of_concrete_and_trait_types ( mir_type, mir_type) . unwrap ( ) ;
559
+ self . codegen_trait_vtable_type ( trait_type) ;
560
+ self . codegen_trait_fat_ptr_type ( trait_type)
561
+ } else {
562
+ unreachable ! (
563
+ "A pointer is either a thin pointer, slice fat pointer, or vtable fat pointer."
564
+ ) ;
567
565
}
568
566
}
569
567
570
- pub fn codegen_ty_ref ( & mut self , t : Ty < ' tcx > ) -> Type {
571
- // Normalize t to remove projection and opaque types
572
- let t = self . tcx . normalize_erasing_regions ( ty:: ParamEnv :: reveal_all ( ) , t) ;
568
+ pub fn codegen_ty_ref ( & mut self , pointee_type : Ty < ' tcx > ) -> Type {
569
+ // Normalize pointee_type to remove projection and opaque types
570
+ let pointee_type =
571
+ self . tcx . normalize_erasing_regions ( ty:: ParamEnv :: reveal_all ( ) , pointee_type) ;
573
572
574
- match t. kind ( ) {
575
- // These types go to fat pointers
576
- ty:: Dynamic ( ..) | ty:: Slice ( _) | ty:: Str => self . codegen_fat_ptr ( t) ,
577
- ty:: Adt ( ..) if self . is_unsized ( t) => self . codegen_fat_ptr ( t) ,
573
+ if !self . use_thin_pointer ( pointee_type) {
574
+ return self . codegen_fat_ptr ( pointee_type) ;
575
+ }
576
+
577
+ match pointee_type. kind ( ) {
578
+ ty:: Dynamic ( ..) | ty:: Slice ( _) | ty:: Str => {
579
+ unreachable ! ( "Should have generated a fat pointer" )
580
+ }
578
581
ty:: Projection ( _) | ty:: Opaque ( ..) => {
579
582
unreachable ! ( "Should have been removed by normalization" )
580
583
}
584
+
581
585
// We have a "thin pointer", which is just a pointer
582
586
ty:: Adt ( ..)
583
587
| ty:: Array ( ..)
@@ -590,22 +594,22 @@ impl<'tcx> GotocCtx<'tcx> {
590
594
| ty:: RawPtr ( _)
591
595
| ty:: Ref ( ..)
592
596
| ty:: Tuple ( _)
593
- | ty:: Uint ( _) => self . codegen_ty ( t ) . to_pointer ( ) ,
597
+ | ty:: Uint ( _) => self . codegen_ty ( pointee_type ) . to_pointer ( ) ,
594
598
595
599
// These types were blocking firecracker. Doing the default thing to unblock.
596
600
// TODO, determine if this is the right course of action
597
- ty:: FnDef ( _, _) | ty:: Never => self . codegen_ty ( t ) . to_pointer ( ) ,
601
+ ty:: FnDef ( _, _) | ty:: Never => self . codegen_ty ( pointee_type ) . to_pointer ( ) ,
598
602
599
603
// These types have no regression tests for them.
600
604
// For soundess, hold off on generating them till we have test-cases.
601
- ty:: Bound ( _, _) => todo ! ( "{:?} {:?}" , t , t . kind( ) ) ,
602
- ty:: Error ( _) => todo ! ( "{:?} {:?}" , t , t . kind( ) ) ,
603
- ty:: FnPtr ( _) => todo ! ( "{:?} {:?}" , t , t . kind( ) ) ,
604
- ty:: Generator ( _, _, _) => todo ! ( "{:?} {:?}" , t , t . kind( ) ) ,
605
- ty:: GeneratorWitness ( _) => todo ! ( "{:?} {:?}" , t , t . kind( ) ) ,
606
- ty:: Infer ( _) => todo ! ( "{:?} {:?}" , t , t . kind( ) ) ,
607
- ty:: Param ( _) => todo ! ( "{:?} {:?}" , t , t . kind( ) ) ,
608
- ty:: Placeholder ( _) => todo ! ( "{:?} {:?}" , t , t . kind( ) ) ,
605
+ ty:: Bound ( _, _) => todo ! ( "{:?} {:?}" , pointee_type , pointee_type . kind( ) ) ,
606
+ ty:: Error ( _) => todo ! ( "{:?} {:?}" , pointee_type , pointee_type . kind( ) ) ,
607
+ ty:: FnPtr ( _) => todo ! ( "{:?} {:?}" , pointee_type , pointee_type . kind( ) ) ,
608
+ ty:: Generator ( _, _, _) => todo ! ( "{:?} {:?}" , pointee_type , pointee_type . kind( ) ) ,
609
+ ty:: GeneratorWitness ( _) => todo ! ( "{:?} {:?}" , pointee_type , pointee_type . kind( ) ) ,
610
+ ty:: Infer ( _) => todo ! ( "{:?} {:?}" , pointee_type , pointee_type . kind( ) ) ,
611
+ ty:: Param ( _) => todo ! ( "{:?} {:?}" , pointee_type , pointee_type . kind( ) ) ,
612
+ ty:: Placeholder ( _) => todo ! ( "{:?} {:?}" , pointee_type , pointee_type . kind( ) ) ,
609
613
}
610
614
}
611
615
@@ -1006,6 +1010,11 @@ impl<'tcx> GotocCtx<'tcx> {
1006
1010
}
1007
1011
}
1008
1012
1013
+ /// The mir type is a mir pointer type.
1014
+ pub fn is_pointer ( mir_type : Ty < ' tcx > ) -> bool {
1015
+ return matches ! ( mir_type. kind( ) , ty:: Ref ( ..) | ty:: RawPtr ( ..) ) ;
1016
+ }
1017
+
1009
1018
/// Extract from a mir pointer type the mir type of the value to which the
1010
1019
/// pointer points.
1011
1020
pub fn pointee_type ( pointer_type : Ty < ' tcx > ) -> Option < Ty < ' tcx > > {
@@ -1019,7 +1028,9 @@ pub fn pointee_type(pointer_type: Ty<'tcx>) -> Option<Ty<'tcx>> {
1019
1028
impl < ' tcx > GotocCtx < ' tcx > {
1020
1029
/// A pointer to the mir type should be a thin pointer.
1021
1030
pub fn use_thin_pointer ( & self , mir_type : Ty < ' tcx > ) -> bool {
1022
- return mir_type. ptr_metadata_ty ( self . tcx ) == self . tcx . types . unit ;
1031
+ // ptr_metadata_ty is not defined on all types, the projection of an associated type
1032
+ return !self . is_unsized ( mir_type)
1033
+ || mir_type. ptr_metadata_ty ( self . tcx ) == self . tcx . types . unit ;
1023
1034
}
1024
1035
/// A pointer to the mir type should be a slice fat pointer.
1025
1036
pub fn use_slice_fat_pointer ( & self , mir_type : Ty < ' tcx > ) -> bool {
0 commit comments