@@ -1008,30 +1008,27 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
10081008 return BumpAllocatedString (Result);
10091009 }
10101010
1011- llvm::DIDerivedType *createMemberType (CompletedDebugTypeInfo DbgTy,
1012- StringRef Name, unsigned &OffsetInBits,
1011+ llvm::DIDerivedType *createMemberType (DebugTypeInfo DbgTy, StringRef Name ,
1012+ unsigned &OffsetInBits,
10131013 llvm::DIScope *Scope,
10141014 llvm::DIFile *File,
10151015 llvm::DINode::DIFlags Flags) {
10161016 unsigned SizeOfByte = CI.getTargetInfo ().getCharWidth ();
10171017 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);
10211022 OffsetInBits += getSizeInBits (Ty);
10221023 OffsetInBits = llvm::alignTo (OffsetInBits,
10231024 SizeOfByte * DbgTy.getAlignment ().getValue ());
10241025 return DITy;
10251026 }
10261027
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) {
10351032 // Forward declare this first because types may be recursive.
10361033 auto FwdDecl = llvm::TempDIType (DBuilder.createReplaceableCompositeType (
10371034 llvm::dwarf::DW_TAG_structure_type, Name, Scope, File, Line,
@@ -1049,6 +1046,18 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
10491046
10501047 auto TH = llvm::TrackingMDNodeRef (FwdDecl.get ());
10511048 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);
10521061 // Collect the members.
10531062 SmallVector<llvm::Metadata *, 16 > Elements;
10541063 unsigned OffsetInBits = 0 ;
@@ -1078,6 +1087,48 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
10781087 return DITy;
10791088 }
10801089
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+
10811132 // / Create debug information for an enum with a raw type (enum E : Int {}).
10821133 llvm::DICompositeType *createRawEnumType (CompletedDebugTypeInfo DbgTy,
10831134 EnumDecl *Decl,
@@ -1443,6 +1494,20 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
14431494 llvm::dwarf::DW_LANG_Swift, nullptr , MangledName);
14441495 }
14451496
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+
14461511 llvm::DIType *createType (DebugTypeInfo DbgTy, StringRef MangledName,
14471512 llvm::DIScope *Scope, llvm::DIFile *File) {
14481513 // FIXME: For SizeInBits, clang uses the actual size of the type on
@@ -1640,6 +1705,42 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
16401705 auto *Decl = StructTy->getDecl ();
16411706 auto L = getFileAndLocation (Decl);
16421707 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+ }
16431744 return createOpaqueStructWithSizedContainer (
16441745 Scope, Decl ? Decl->getNameStr () : " " , L.File , FwdDeclLine,
16451746 SizeInBits, AlignInBits, Flags, MangledName,
@@ -2026,26 +2127,9 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
20262127 }
20272128 llvm::DIType *DITy = createType (DbgTy, MangledName, Scope, getFile (Scope));
20282129
2029- // Don't cache a type alias to a forward declaration either.
2030- if (DbgTy.isForwardDecl () || DbgTy.isFixedBuffer () ||
2031- DITy->isForwardDecl ())
2032- return DITy;
20332130
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;
20492133
20502134 // Incrementally build the DIRefMap.
20512135 if (auto *CTy = dyn_cast<llvm::DICompositeType>(DITy)) {
0 commit comments