@@ -1008,30 +1008,27 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
1008
1008
return BumpAllocatedString (Result);
1009
1009
}
1010
1010
1011
- llvm::DIDerivedType *createMemberType (CompletedDebugTypeInfo DbgTy,
1012
- StringRef Name, unsigned &OffsetInBits,
1011
+ llvm::DIDerivedType *createMemberType (DebugTypeInfo DbgTy, StringRef Name ,
1012
+ unsigned &OffsetInBits,
1013
1013
llvm::DIScope *Scope,
1014
1014
llvm::DIFile *File,
1015
1015
llvm::DINode::DIFlags Flags) {
1016
1016
unsigned SizeOfByte = CI.getTargetInfo ().getCharWidth ();
1017
1017
auto *Ty = getOrCreateType (DbgTy);
1018
- auto *DITy =
1019
- DBuilder.createMemberType (Scope, Name, File, 0 , DbgTy.getSizeInBits (),
1020
- 0 , OffsetInBits, Flags, Ty);
1018
+ auto *DITy = DBuilder.createMemberType (
1019
+ Scope, Name, File, 0 ,
1020
+ DbgTy.getRawSizeInBits () ? *DbgTy.getRawSizeInBits () : 0 , 0 ,
1021
+ OffsetInBits, Flags, Ty);
1021
1022
OffsetInBits += getSizeInBits (Ty);
1022
1023
OffsetInBits = llvm::alignTo (OffsetInBits,
1023
1024
SizeOfByte * DbgTy.getAlignment ().getValue ());
1024
1025
return DITy;
1025
1026
}
1026
1027
1027
- llvm::DICompositeType *
1028
- createStructType (DebugTypeInfo DbgTy, NominalTypeDecl *Decl, Type BaseTy,
1029
- llvm::DIScope *Scope, llvm::DIFile *File, unsigned Line,
1030
- unsigned SizeInBits, unsigned AlignInBits,
1031
- llvm::DINode::DIFlags Flags, llvm::DIType *DerivedFrom,
1032
- unsigned RuntimeLang, StringRef UniqueID) {
1033
- StringRef Name = Decl->getName ().str ();
1034
-
1028
+ llvm::TempDIType createStructForwardDecl (
1029
+ DebugTypeInfo DbgTy, NominalTypeDecl *Decl, llvm::DIScope *Scope,
1030
+ llvm::DIFile *File, unsigned Line, unsigned SizeInBits,
1031
+ llvm::DINode::DIFlags Flags, StringRef UniqueID, StringRef Name) {
1035
1032
// Forward declare this first because types may be recursive.
1036
1033
auto FwdDecl = llvm::TempDIType (DBuilder.createReplaceableCompositeType (
1037
1034
llvm::dwarf::DW_TAG_structure_type, Name, Scope, File, Line,
@@ -1049,6 +1046,18 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
1049
1046
1050
1047
auto TH = llvm::TrackingMDNodeRef (FwdDecl.get ());
1051
1048
DITypeCache[DbgTy.getType ()] = TH;
1049
+ return FwdDecl;
1050
+ }
1051
+
1052
+ llvm::DICompositeType *
1053
+ createStructType (DebugTypeInfo DbgTy, NominalTypeDecl *Decl, Type BaseTy,
1054
+ llvm::DIScope *Scope, llvm::DIFile *File, unsigned Line,
1055
+ unsigned SizeInBits, unsigned AlignInBits,
1056
+ llvm::DINode::DIFlags Flags, llvm::DIType *DerivedFrom,
1057
+ unsigned RuntimeLang, StringRef UniqueID) {
1058
+ StringRef Name = Decl->getName ().str ();
1059
+ auto FwdDecl = createStructForwardDecl (DbgTy, Decl, Scope, File, Line,
1060
+ SizeInBits, Flags, UniqueID, Name);
1052
1061
// Collect the members.
1053
1062
SmallVector<llvm::Metadata *, 16 > Elements;
1054
1063
unsigned OffsetInBits = 0 ;
@@ -1078,6 +1087,48 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
1078
1087
return DITy;
1079
1088
}
1080
1089
1090
+ // / Creates debug info for a generic struct with archetypes (e.g.:
1091
+ // / Pair<τ_0_0, τ_0_1>). For types with unsubstituted generic type parameters,
1092
+ // / debug info generation doesn't attempt to emit the size and aligment of
1093
+ // / the type, as in the general case those are all dependent on substituting
1094
+ // / the type parameters in (some exceptions exist, like generic types that are
1095
+ // / class constrained). It also doesn't attempt to emit the offset of the
1096
+ // / members for the same reason.
1097
+ llvm::DICompositeType *createUnsubstitutedGenericStructType (
1098
+ DebugTypeInfo DbgTy, NominalTypeDecl *Decl, Type UnsubstitutedType,
1099
+ llvm::DIScope *Scope, llvm::DIFile *File, unsigned Line,
1100
+ unsigned SizeInBits, unsigned AlignInBits, llvm::DINode::DIFlags Flags,
1101
+ llvm::DIType *DerivedFrom, unsigned RuntimeLang, StringRef UniqueID) {
1102
+ // FIXME: ideally, we'd like to emit this type with no size and alignment at
1103
+ // all (instead of emitting them as 0). Fix this by changing DIBuilder to
1104
+ // allow for struct types that have optional size and alignment.
1105
+ StringRef Name = Decl->getName ().str ();
1106
+ auto FwdDecl = createStructForwardDecl (DbgTy, Decl, Scope, File, Line,
1107
+ SizeInBits, Flags, UniqueID, Name);
1108
+
1109
+ // Collect the members.
1110
+ SmallVector<llvm::Metadata *, 16 > Elements;
1111
+ for (VarDecl *VD : Decl->getStoredProperties ()) {
1112
+ auto memberTy =
1113
+ UnsubstitutedType->getTypeOfMember (IGM.getSwiftModule (), VD);
1114
+ auto DbgTy = DebugTypeInfo::getFromTypeInfo (
1115
+ memberTy,
1116
+ IGM.getTypeInfoForUnlowered (
1117
+ IGM.getSILTypes ().getAbstractionPattern (VD), memberTy),
1118
+ IGM, false );
1119
+ unsigned OffsetInBits = 0 ;
1120
+ llvm::DIType *DITy = createMemberType (DbgTy, VD->getName ().str (),
1121
+ OffsetInBits, Scope, File, Flags);
1122
+ Elements.push_back (DITy);
1123
+ }
1124
+
1125
+ auto DITy = DBuilder.createStructType (
1126
+ Scope, Name, File, Line, SizeInBits, AlignInBits, Flags, DerivedFrom,
1127
+ DBuilder.getOrCreateArray (Elements), RuntimeLang, nullptr , UniqueID);
1128
+ DBuilder.replaceTemporary (std::move (FwdDecl), DITy);
1129
+ return DITy;
1130
+ }
1131
+
1081
1132
// / Create debug information for an enum with a raw type (enum E : Int {}).
1082
1133
llvm::DICompositeType *createRawEnumType (CompletedDebugTypeInfo DbgTy,
1083
1134
EnumDecl *Decl,
@@ -1443,6 +1494,20 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
1443
1494
llvm::dwarf::DW_LANG_Swift, nullptr , MangledName);
1444
1495
}
1445
1496
1497
+ bool shouldCacheDIType (llvm::DIType *DITy, DebugTypeInfo &DbgTy) {
1498
+ // Don't cache a type alias to a forward declaration either.
1499
+ if (DbgTy.isForwardDecl () || DbgTy.isFixedBuffer () ||
1500
+ DITy->isForwardDecl ())
1501
+ return false ;
1502
+
1503
+ if (auto Ty = DbgTy.getType ())
1504
+ // FIXME: Primary archetypes carry all sorts of auxiliary information
1505
+ // that isn't contained in their mangled name. See also
1506
+ // getMangledName().
1507
+ return Ty->getKind () != swift::TypeKind::PrimaryArchetype;
1508
+ return true ;
1509
+ }
1510
+
1446
1511
llvm::DIType *createType (DebugTypeInfo DbgTy, StringRef MangledName,
1447
1512
llvm::DIScope *Scope, llvm::DIFile *File) {
1448
1513
// FIXME: For SizeInBits, clang uses the actual size of the type on
@@ -1640,6 +1705,42 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
1640
1705
auto *Decl = StructTy->getDecl ();
1641
1706
auto L = getFileAndLocation (Decl);
1642
1707
unsigned FwdDeclLine = 0 ;
1708
+ if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes) {
1709
+ // To emit full debug info for generic types, the strategy is to emit
1710
+ // full debug info for the type with archetypes, and still emit opaque
1711
+ // debug information for the specialized type. For example, given:
1712
+ // struct Pair<T, U> {
1713
+ // let t : T
1714
+ // let u: U
1715
+ // }
1716
+ // When emitting debug information for a type such as Pair<Int, Double>,
1717
+ // emit full debug info for Pair<T, U>, and emit the regular debug
1718
+ // information for Pair<Int, Double>.
1719
+
1720
+ // Go from Pair<Int, Double> to Pair<T, U>.
1721
+ auto UnsubstitutedTy = Decl->getDeclaredInterfaceType ();
1722
+ UnsubstitutedTy = Decl->mapTypeIntoContext (UnsubstitutedTy);
1723
+
1724
+ auto DbgTy = DebugTypeInfo::getFromTypeInfo (
1725
+ UnsubstitutedTy, IGM.getTypeInfoForUnlowered (UnsubstitutedTy), IGM,
1726
+ false );
1727
+ Mangle::ASTMangler Mangler;
1728
+ std::string DeclTypeMangledName = Mangler.mangleTypeForDebugger (
1729
+ UnsubstitutedTy->mapTypeOutOfContext (), {});
1730
+ if (DeclTypeMangledName == MangledName) {
1731
+ return createUnsubstitutedGenericStructType (
1732
+ DbgTy, Decl, UnsubstitutedTy, Scope, File, FwdDeclLine,
1733
+ SizeInBits, AlignInBits, Flags, nullptr , llvm::dwarf::DW_LANG_Swift,
1734
+ DeclTypeMangledName);
1735
+ }
1736
+ // Force the creation of the unsubstituted type, don't create it
1737
+ // directly so it goes through all the caching/verification logic.
1738
+ DBuilder.retainType (getOrCreateType (DbgTy));
1739
+
1740
+ // Fallthrough and create the opaque struct. This way debug info will
1741
+ // have an opaque entry for Pair<Int, Double> and a full entry for
1742
+ // Pair<T, U>.
1743
+ }
1643
1744
return createOpaqueStructWithSizedContainer (
1644
1745
Scope, Decl ? Decl->getNameStr () : " " , L.File , FwdDeclLine,
1645
1746
SizeInBits, AlignInBits, Flags, MangledName,
@@ -2026,26 +2127,9 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
2026
2127
}
2027
2128
llvm::DIType *DITy = createType (DbgTy, MangledName, Scope, getFile (Scope));
2028
2129
2029
- // Don't cache a type alias to a forward declaration either.
2030
- if (DbgTy.isForwardDecl () || DbgTy.isFixedBuffer () ||
2031
- DITy->isForwardDecl ())
2032
- return DITy;
2033
2130
2034
- if (auto Ty = DbgTy.getType ())
2035
- switch (Ty->getKind ()) {
2036
- case TypeKind::PrimaryArchetype:
2037
- // FIXME: Primary archetypes carry all sorts of auxiliary information
2038
- // that isn't contained in their mangled name. See also
2039
- // getMangledName().
2040
- return DITy;
2041
- case TypeKind::BoundGenericEnum:
2042
- case TypeKind::BoundGenericStruct:
2043
- // FIXME: These are emitted in sized anonymous containers, and their
2044
- // size is not consistent when resilient.
2045
- return DITy;
2046
- default :
2047
- break ;
2048
- }
2131
+ if (!shouldCacheDIType (DITy, DbgTy))
2132
+ return DITy;
2049
2133
2050
2134
// Incrementally build the DIRefMap.
2051
2135
if (auto *CTy = dyn_cast<llvm::DICompositeType>(DITy)) {
0 commit comments