@@ -10,6 +10,8 @@ use super::CrateDebugContext;
10
10
11
11
use crate :: abi;
12
12
use crate :: common:: CodegenCx ;
13
+ use crate :: debuginfo:: utils:: fat_pointer_kind;
14
+ use crate :: debuginfo:: utils:: FatPtrKind ;
13
15
use crate :: llvm;
14
16
use crate :: llvm:: debuginfo:: {
15
17
DIArray , DICompositeType , DIDescriptor , DIFile , DIFlags , DILexicalBlock , DIScope , DIType ,
@@ -376,22 +378,24 @@ macro_rules! return_if_metadata_created_in_meantime {
376
378
} ;
377
379
}
378
380
379
- fn fixed_vec_metadata < ' ll , ' tcx > (
381
+ /// Creates debuginfo for a fixed size array (e.g. `[u64; 123]`).
382
+ /// For slices (that is, "arrays" of unknown size) use [slice_type_metadata].
383
+ fn fixed_size_array_metadata < ' ll , ' tcx > (
380
384
cx : & CodegenCx < ' ll , ' tcx > ,
381
385
unique_type_id : UniqueTypeId ,
382
- array_or_slice_type : Ty < ' tcx > ,
383
- element_type : Ty < ' tcx > ,
386
+ array_type : Ty < ' tcx > ,
384
387
) -> MetadataCreationResult < ' ll > {
388
+ let ty:: Array ( element_type, len) = array_type. kind ( ) else {
389
+ bug ! ( "fixed_size_array_metadata() called with non-ty::Array type `{:?}`" , array_type)
390
+ } ;
391
+
385
392
let element_type_metadata = type_metadata ( cx, element_type) ;
386
393
387
394
return_if_metadata_created_in_meantime ! ( cx, unique_type_id) ;
388
395
389
- let ( size, align) = cx. size_and_align_of ( array_or_slice_type ) ;
396
+ let ( size, align) = cx. size_and_align_of ( array_type ) ;
390
397
391
- let upper_bound = match array_or_slice_type. kind ( ) {
392
- ty:: Array ( _, len) => len. eval_usize ( cx. tcx , ty:: ParamEnv :: reveal_all ( ) ) as c_longlong ,
393
- _ => -1 ,
394
- } ;
398
+ let upper_bound = len. eval_usize ( cx. tcx , ty:: ParamEnv :: reveal_all ( ) ) as c_longlong ;
395
399
396
400
let subrange =
397
401
unsafe { Some ( llvm:: LLVMRustDIBuilderGetOrCreateSubrange ( DIB ( cx) , 0 , upper_bound) ) } ;
@@ -410,55 +414,111 @@ fn fixed_vec_metadata<'ll, 'tcx>(
410
414
MetadataCreationResult :: new ( metadata, false )
411
415
}
412
416
413
- fn vec_slice_metadata < ' ll , ' tcx > (
417
+ /// Creates debuginfo for built-in pointer-like things:
418
+ ///
419
+ /// - ty::Ref
420
+ /// - ty::RawPtr
421
+ /// - ty::Adt in the case it's Box
422
+ ///
423
+ /// At some point we might want to remove the special handling of Box
424
+ /// and treat it the same as other smart pointers (like Rc, Arc, ...).
425
+ fn pointer_or_reference_metadata < ' ll , ' tcx > (
414
426
cx : & CodegenCx < ' ll , ' tcx > ,
415
- slice_ptr_type : Ty < ' tcx > ,
416
- element_type : Ty < ' tcx > ,
427
+ ptr_type : Ty < ' tcx > ,
428
+ pointee_type : Ty < ' tcx > ,
417
429
unique_type_id : UniqueTypeId ,
418
430
) -> MetadataCreationResult < ' ll > {
419
- let data_ptr_type = cx. tcx . mk_imm_ptr ( element_type) ;
420
-
421
- let data_ptr_metadata = type_metadata ( cx, data_ptr_type) ;
431
+ let pointee_type_metadata = type_metadata ( cx, pointee_type) ;
422
432
423
433
return_if_metadata_created_in_meantime ! ( cx, unique_type_id) ;
424
434
425
- let slice_type_name = compute_debuginfo_type_name ( cx. tcx , slice_ptr_type, true ) ;
426
-
427
- let ( pointer_size, pointer_align) = cx. size_and_align_of ( data_ptr_type) ;
428
- let ( usize_size, usize_align) = cx. size_and_align_of ( cx. tcx . types . usize ) ;
429
-
430
- let member_descriptions = vec ! [
431
- MemberDescription {
432
- name: "data_ptr" . to_owned( ) ,
433
- type_metadata: data_ptr_metadata,
434
- offset: Size :: ZERO ,
435
- size: pointer_size,
436
- align: pointer_align,
437
- flags: DIFlags :: FlagZero ,
438
- discriminant: None ,
439
- source_info: None ,
440
- } ,
441
- MemberDescription {
442
- name: "length" . to_owned( ) ,
443
- type_metadata: type_metadata( cx, cx. tcx. types. usize ) ,
444
- offset: pointer_size,
445
- size: usize_size,
446
- align: usize_align,
447
- flags: DIFlags :: FlagZero ,
448
- discriminant: None ,
449
- source_info: None ,
450
- } ,
451
- ] ;
435
+ let ( thin_pointer_size, thin_pointer_align) =
436
+ cx. size_and_align_of ( cx. tcx . mk_imm_ptr ( cx. tcx . types . unit ) ) ;
437
+ let ptr_type_debuginfo_name = compute_debuginfo_type_name ( cx. tcx , ptr_type, true ) ;
452
438
453
- let metadata = composite_type_metadata (
454
- cx,
455
- slice_ptr_type,
456
- & slice_type_name,
457
- unique_type_id,
458
- member_descriptions,
459
- NO_SCOPE_METADATA ,
460
- ) ;
461
- MetadataCreationResult :: new ( metadata, false )
439
+ let pointer_type_metadata = match fat_pointer_kind ( cx, pointee_type) {
440
+ None => {
441
+ // This is a thin pointer. Create a regular pointer type and give it the correct name.
442
+ debug_assert_eq ! (
443
+ ( thin_pointer_size, thin_pointer_align) ,
444
+ cx. size_and_align_of( ptr_type)
445
+ ) ;
446
+
447
+ unsafe {
448
+ llvm:: LLVMRustDIBuilderCreatePointerType (
449
+ DIB ( cx) ,
450
+ pointee_type_metadata,
451
+ thin_pointer_size. bits ( ) ,
452
+ thin_pointer_align. bits ( ) as u32 ,
453
+ 0 , // Ignore DWARF address space.
454
+ ptr_type_debuginfo_name. as_ptr ( ) . cast ( ) ,
455
+ ptr_type_debuginfo_name. len ( ) ,
456
+ )
457
+ }
458
+ }
459
+ Some ( fat_pointer_kind) => {
460
+ let layout = cx. layout_of ( ptr_type) ;
461
+
462
+ let addr_field = layout. field ( cx, abi:: FAT_PTR_ADDR ) ;
463
+ let extra_field = layout. field ( cx, abi:: FAT_PTR_EXTRA ) ;
464
+
465
+ let ( addr_field_name, extra_field_name) = match fat_pointer_kind {
466
+ FatPtrKind :: Dyn => ( "pointer" , "vtable" ) ,
467
+ FatPtrKind :: Slice => ( "data_ptr" , "length" ) ,
468
+ } ;
469
+
470
+ debug_assert_eq ! ( abi:: FAT_PTR_ADDR , 0 ) ;
471
+ debug_assert_eq ! ( abi:: FAT_PTR_EXTRA , 1 ) ;
472
+
473
+ // The data pointer type is a regular, thin pointer, regardless of whether this is a slice
474
+ // or a trait object.
475
+ let data_ptr_type_metadata = unsafe {
476
+ llvm:: LLVMRustDIBuilderCreatePointerType (
477
+ DIB ( cx) ,
478
+ pointee_type_metadata,
479
+ addr_field. size . bits ( ) ,
480
+ addr_field. align . abi . bits ( ) as u32 ,
481
+ 0 , // Ignore DWARF address space.
482
+ std:: ptr:: null ( ) ,
483
+ 0 ,
484
+ )
485
+ } ;
486
+
487
+ let member_descriptions = vec ! [
488
+ MemberDescription {
489
+ name: addr_field_name. into( ) ,
490
+ type_metadata: data_ptr_type_metadata,
491
+ offset: layout. fields. offset( abi:: FAT_PTR_ADDR ) ,
492
+ size: addr_field. size,
493
+ align: addr_field. align. abi,
494
+ flags: DIFlags :: FlagArtificial ,
495
+ discriminant: None ,
496
+ source_info: None ,
497
+ } ,
498
+ MemberDescription {
499
+ name: extra_field_name. into( ) ,
500
+ type_metadata: type_metadata( cx, extra_field. ty) ,
501
+ offset: layout. fields. offset( abi:: FAT_PTR_EXTRA ) ,
502
+ size: extra_field. size,
503
+ align: extra_field. align. abi,
504
+ flags: DIFlags :: FlagArtificial ,
505
+ discriminant: None ,
506
+ source_info: None ,
507
+ } ,
508
+ ] ;
509
+
510
+ composite_type_metadata (
511
+ cx,
512
+ ptr_type,
513
+ & ptr_type_debuginfo_name,
514
+ unique_type_id,
515
+ member_descriptions,
516
+ NO_SCOPE_METADATA ,
517
+ )
518
+ }
519
+ } ;
520
+
521
+ MetadataCreationResult { metadata : pointer_type_metadata, already_stored_in_typemap : false }
462
522
}
463
523
464
524
fn subroutine_type_metadata < ' ll , ' tcx > (
@@ -495,83 +555,57 @@ fn subroutine_type_metadata<'ll, 'tcx>(
495
555
)
496
556
}
497
557
498
- // FIXME(1563): This is all a bit of a hack because 'trait pointer' is an ill-
499
- // defined concept. For the case of an actual trait pointer (i.e., `Box<Trait>`,
500
- // `&Trait`), `trait_object_type` should be the whole thing (e.g, `Box<Trait>`) and
501
- // `trait_type` should be the actual trait (e.g., `Trait`). Where the trait is part
502
- // of a DST struct, there is no `trait_object_type` and the results of this
503
- // function will be a little bit weird.
504
- fn trait_pointer_metadata < ' ll , ' tcx > (
558
+ // Create debuginfo for `dyn SomeTrait` types. Currently these are empty structs
559
+ // we with the correct type name (e.g. "dyn SomeTrait<Foo, Item=u32> + Sync").
560
+ fn dyn_type_metadata < ' ll , ' tcx > (
505
561
cx : & CodegenCx < ' ll , ' tcx > ,
506
- trait_type : Ty < ' tcx > ,
507
- trait_object_type : Option < Ty < ' tcx > > ,
562
+ dyn_type : Ty < ' tcx > ,
508
563
unique_type_id : UniqueTypeId ,
509
564
) -> & ' ll DIType {
510
- // The implementation provided here is a stub. It makes sure that the trait
511
- // type is assigned the correct name, size, namespace, and source location.
512
- // However, it does not describe the trait's methods.
513
-
514
- let ( containing_scope, trait_type_name) = match trait_object_type {
515
- Some ( trait_object_type) => match trait_object_type. kind ( ) {
516
- ty:: Adt ( def, _) => (
517
- Some ( get_namespace_for_item ( cx, def. did ) ) ,
518
- compute_debuginfo_type_name ( cx. tcx , trait_object_type, false ) ,
519
- ) ,
520
- ty:: RawPtr ( _) | ty:: Ref ( ..) => {
521
- ( NO_SCOPE_METADATA , compute_debuginfo_type_name ( cx. tcx , trait_object_type, true ) )
522
- }
523
- _ => {
524
- bug ! (
525
- "debuginfo: unexpected trait-object type in \
526
- trait_pointer_metadata(): {:?}",
527
- trait_object_type
528
- ) ;
529
- }
530
- } ,
565
+ if let ty:: Dynamic ( ..) = dyn_type. kind ( ) {
566
+ let type_name = compute_debuginfo_type_name ( cx. tcx , dyn_type, true ) ;
567
+ composite_type_metadata ( cx, dyn_type, & type_name, unique_type_id, vec ! [ ] , NO_SCOPE_METADATA )
568
+ } else {
569
+ bug ! ( "Only ty::Dynamic is valid for dyn_type_metadata(). Found {:?} instead." , dyn_type)
570
+ }
571
+ }
531
572
532
- // No object type, use the trait type directly (no scope here since the type
533
- // will be wrapped in the dyn$ synthetic type).
534
- None => ( NO_SCOPE_METADATA , compute_debuginfo_type_name ( cx. tcx , trait_type, true ) ) ,
573
+ // Create debuginfo for `[T]` and `str`. These are unsized.
574
+ //
575
+ // Note: We currently emit just emit the debuginfo for the element type here
576
+ // (i.e. `T` for slices and `u8` for `str`), so that we end up with
577
+ // `*const T` for the `data_ptr` field of the corresponding fat-pointer
578
+ // debuginfo of `&[T]`.
579
+ //
580
+ // It would be preferable and more accurate if we emitted a DIArray of T
581
+ // without an upper bound instead. That is, LLVM already supports emitting
582
+ // debuginfo of arrays of unknown size. But GDB currently seems to end up
583
+ // in an infinite loop when confronted with such a type.
584
+ //
585
+ // As a side effect of the current encoding every instance of a type like
586
+ // `struct Foo { unsized_field: [u8] }` will look like
587
+ // `struct Foo { unsized_field: u8 }` in debuginfo. If the length of the
588
+ // slice is zero, then accessing `unsized_field` in the debugger would
589
+ // result in an out-of-bounds access.
590
+ fn slice_type_metadata < ' ll , ' tcx > (
591
+ cx : & CodegenCx < ' ll , ' tcx > ,
592
+ slice_type : Ty < ' tcx > ,
593
+ unique_type_id : UniqueTypeId ,
594
+ ) -> MetadataCreationResult < ' ll > {
595
+ let element_type = match slice_type. kind ( ) {
596
+ ty:: Slice ( element_type) => element_type,
597
+ ty:: Str => cx. tcx . types . u8 ,
598
+ _ => {
599
+ bug ! (
600
+ "Only ty::Slice is valid for slice_type_metadata(). Found {:?} instead." ,
601
+ slice_type
602
+ )
603
+ }
535
604
} ;
536
605
537
- let layout = cx. layout_of ( cx. tcx . mk_mut_ptr ( trait_type) ) ;
538
-
539
- assert_eq ! ( abi:: FAT_PTR_ADDR , 0 ) ;
540
- assert_eq ! ( abi:: FAT_PTR_EXTRA , 1 ) ;
541
-
542
- let data_ptr_field = layout. field ( cx, 0 ) ;
543
- let vtable_field = layout. field ( cx, 1 ) ;
544
- let member_descriptions = vec ! [
545
- MemberDescription {
546
- name: "pointer" . to_owned( ) ,
547
- type_metadata: type_metadata( cx, cx. tcx. mk_mut_ptr( cx. tcx. types. u8 ) ) ,
548
- offset: layout. fields. offset( 0 ) ,
549
- size: data_ptr_field. size,
550
- align: data_ptr_field. align. abi,
551
- flags: DIFlags :: FlagArtificial ,
552
- discriminant: None ,
553
- source_info: None ,
554
- } ,
555
- MemberDescription {
556
- name: "vtable" . to_owned( ) ,
557
- type_metadata: type_metadata( cx, vtable_field. ty) ,
558
- offset: layout. fields. offset( 1 ) ,
559
- size: vtable_field. size,
560
- align: vtable_field. align. abi,
561
- flags: DIFlags :: FlagArtificial ,
562
- discriminant: None ,
563
- source_info: None ,
564
- } ,
565
- ] ;
566
-
567
- composite_type_metadata (
568
- cx,
569
- trait_object_type. unwrap_or ( trait_type) ,
570
- & trait_type_name,
571
- unique_type_id,
572
- member_descriptions,
573
- containing_scope,
574
- )
606
+ let element_type_metadata = type_metadata ( cx, element_type) ;
607
+ return_if_metadata_created_in_meantime ! ( cx, unique_type_id) ;
608
+ MetadataCreationResult { metadata : element_type_metadata, already_stored_in_typemap : false }
575
609
}
576
610
577
611
pub fn type_metadata < ' ll , ' tcx > ( cx : & CodegenCx < ' ll , ' tcx > , t : Ty < ' tcx > ) -> & ' ll DIType {
@@ -610,49 +644,27 @@ pub fn type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll
610
644
611
645
debug ! ( "type_metadata: {:?}" , t) ;
612
646
613
- let ptr_metadata = |ty : Ty < ' tcx > | match * ty. kind ( ) {
614
- ty:: Slice ( typ) => Ok ( vec_slice_metadata ( cx, t, typ, unique_type_id) ) ,
615
- ty:: Str => Ok ( vec_slice_metadata ( cx, t, cx. tcx . types . u8 , unique_type_id) ) ,
616
- ty:: Dynamic ( ..) => Ok ( MetadataCreationResult :: new (
617
- trait_pointer_metadata ( cx, ty, Some ( t) , unique_type_id) ,
618
- false ,
619
- ) ) ,
620
- _ => {
621
- let pointee_metadata = type_metadata ( cx, ty) ;
622
-
623
- if let Some ( metadata) =
624
- debug_context ( cx) . type_map . borrow ( ) . find_metadata_for_unique_id ( unique_type_id)
625
- {
626
- return Err ( metadata) ;
627
- }
628
-
629
- Ok ( MetadataCreationResult :: new ( pointer_type_metadata ( cx, t, pointee_metadata) , false ) )
630
- }
631
- } ;
632
-
633
647
let MetadataCreationResult { metadata, already_stored_in_typemap } = match * t. kind ( ) {
634
648
ty:: Never | ty:: Bool | ty:: Char | ty:: Int ( _) | ty:: Uint ( _) | ty:: Float ( _) => {
635
649
MetadataCreationResult :: new ( basic_type_metadata ( cx, t) , false )
636
650
}
637
651
ty:: Tuple ( elements) if elements. is_empty ( ) => {
638
652
MetadataCreationResult :: new ( basic_type_metadata ( cx, t) , false )
639
653
}
640
- ty:: Array ( typ , _ ) | ty :: Slice ( typ ) => fixed_vec_metadata ( cx, unique_type_id, t, typ ) ,
641
- ty:: Str => fixed_vec_metadata ( cx, unique_type_id , t, cx . tcx . types . i8 ) ,
654
+ ty:: Array ( .. ) => fixed_size_array_metadata ( cx, unique_type_id, t) ,
655
+ ty:: Slice ( _ ) | ty :: Str => slice_type_metadata ( cx, t, unique_type_id ) ,
642
656
ty:: Dynamic ( ..) => {
643
- MetadataCreationResult :: new ( trait_pointer_metadata ( cx, t, None , unique_type_id) , false )
657
+ MetadataCreationResult :: new ( dyn_type_metadata ( cx, t, unique_type_id) , false )
644
658
}
645
659
ty:: Foreign ( ..) => {
646
660
MetadataCreationResult :: new ( foreign_type_metadata ( cx, t, unique_type_id) , false )
647
661
}
648
- ty:: RawPtr ( ty:: TypeAndMut { ty, .. } ) | ty:: Ref ( _, ty, _) => match ptr_metadata ( ty) {
649
- Ok ( res) => res,
650
- Err ( metadata) => return metadata,
651
- } ,
652
- ty:: Adt ( def, _) if def. is_box ( ) => match ptr_metadata ( t. boxed_ty ( ) ) {
653
- Ok ( res) => res,
654
- Err ( metadata) => return metadata,
655
- } ,
662
+ ty:: RawPtr ( ty:: TypeAndMut { ty : pointee_type, .. } ) | ty:: Ref ( _, pointee_type, _) => {
663
+ pointer_or_reference_metadata ( cx, t, pointee_type, unique_type_id)
664
+ }
665
+ ty:: Adt ( def, _) if def. is_box ( ) => {
666
+ pointer_or_reference_metadata ( cx, t, t. boxed_ty ( ) , unique_type_id)
667
+ }
656
668
ty:: FnDef ( ..) | ty:: FnPtr ( _) => {
657
669
if let Some ( metadata) =
658
670
debug_context ( cx) . type_map . borrow ( ) . find_metadata_for_unique_id ( unique_type_id)
@@ -694,7 +706,22 @@ pub fn type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll
694
706
type_map. borrow_mut ( ) . remove_type ( t) ;
695
707
696
708
// This is actually a function pointer, so wrap it in pointer DI.
697
- MetadataCreationResult :: new ( pointer_type_metadata ( cx, t, fn_metadata) , false )
709
+ let ( pointer_size, pointer_align) =
710
+ cx. size_and_align_of ( cx. tcx . mk_imm_ptr ( cx. tcx . mk_unit ( ) ) ) ;
711
+ let name = compute_debuginfo_type_name ( cx. tcx , t, false ) ;
712
+ let md = unsafe {
713
+ llvm:: LLVMRustDIBuilderCreatePointerType (
714
+ DIB ( cx) ,
715
+ fn_metadata,
716
+ pointer_size. bits ( ) ,
717
+ pointer_align. bits ( ) as u32 ,
718
+ 0 , // Ignore DWARF address space.
719
+ name. as_ptr ( ) . cast ( ) ,
720
+ name. len ( ) ,
721
+ )
722
+ } ;
723
+
724
+ MetadataCreationResult :: new ( md, false )
698
725
}
699
726
ty:: Closure ( def_id, substs) => {
700
727
let upvar_tys: Vec < _ > = substs. as_closure ( ) . upvar_tys ( ) . collect ( ) ;
@@ -959,26 +986,6 @@ fn foreign_type_metadata<'ll, 'tcx>(
959
986
create_struct_stub ( cx, t, & name, unique_type_id, NO_SCOPE_METADATA , DIFlags :: FlagZero )
960
987
}
961
988
962
- fn pointer_type_metadata < ' ll , ' tcx > (
963
- cx : & CodegenCx < ' ll , ' tcx > ,
964
- pointer_type : Ty < ' tcx > ,
965
- pointee_type_metadata : & ' ll DIType ,
966
- ) -> & ' ll DIType {
967
- let ( pointer_size, pointer_align) = cx. size_and_align_of ( pointer_type) ;
968
- let name = compute_debuginfo_type_name ( cx. tcx , pointer_type, false ) ;
969
- unsafe {
970
- llvm:: LLVMRustDIBuilderCreatePointerType (
971
- DIB ( cx) ,
972
- pointee_type_metadata,
973
- pointer_size. bits ( ) ,
974
- pointer_align. bits ( ) as u32 ,
975
- 0 , // Ignore DWARF address space.
976
- name. as_ptr ( ) . cast ( ) ,
977
- name. len ( ) ,
978
- )
979
- }
980
- }
981
-
982
989
fn param_type_metadata < ' ll , ' tcx > ( cx : & CodegenCx < ' ll , ' tcx > , t : Ty < ' tcx > ) -> & ' ll DIType {
983
990
debug ! ( "param_type_metadata: {:?}" , t) ;
984
991
let name = format ! ( "{:?}" , t) ;
0 commit comments