Skip to content

Commit a3b4d06

Browse files
authored
Merge pull request #72442 from augusto2112/cp-deb-specialized-types
[Cherry-pick] [DebugInfo] Generate debug info for specialized types
2 parents e82360b + 9311d7a commit a3b4d06

File tree

3 files changed

+176
-77
lines changed

3 files changed

+176
-77
lines changed

lib/IRGen/GenEnum.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5889,8 +5889,10 @@ namespace {
58895889
std::optional<SpareBitsMaskInfo> calculateSpareBitsMask() const override {
58905890
SpareBitVector spareBits;
58915891
for (auto enumCase : getElementsWithPayload()) {
5892-
cast<FixedTypeInfo>(enumCase.ti)
5893-
->applyFixedSpareBitsMask(IGM, spareBits);
5892+
if (auto fixedTI = llvm::dyn_cast<FixedTypeInfo>(enumCase.ti))
5893+
fixedTI->applyFixedSpareBitsMask(IGM, spareBits);
5894+
else
5895+
return {};
58945896
}
58955897
// Trim leading/trailing zero bytes, then pad to a multiple of 32 bits
58965898
llvm::APInt bits = spareBits.asAPInt();

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 142 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,23 +1157,12 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
11571157
return DITy;;
11581158
}
11591159

1160-
llvm::DIType *createFullDebugInfoGenericForStructOrClassType(
1161-
BoundGenericType *Type, NominalTypeDecl *Decl, llvm::DIScope *Scope,
1162-
llvm::DIFile *File, unsigned Line, unsigned SizeInBits,
1163-
unsigned AlignInBits, llvm::DINode::DIFlags Flags,
1164-
StringRef MangledName, bool IsClass = false) {
1165-
// To emit full debug info for generic types, the strategy is to emit
1166-
// full debug info for the type with archetypes, and still emit opaque
1167-
// debug information for the specialized type. For example, given:
1168-
// struct Pair<T, U> {
1169-
// let t : T
1170-
// let u: U
1171-
// }
1172-
// When emitting debug information for a type such as Pair<Int, Double>,
1173-
// emit full debug info for Pair<T, U>, and emit the regular debug
1174-
// information for Pair<Int, Double>.
1175-
1176-
// Go from Pair<Int, Double> to Pair<T, U>.
1160+
llvm::DIType *
1161+
createSpecializedEnumType(NominalOrBoundGenericNominalType *EnumTy,
1162+
EnumDecl *Decl, StringRef MangledName,
1163+
unsigned SizeInBits, unsigned AlignInBits,
1164+
llvm::DIScope *Scope, llvm::DIFile *File,
1165+
unsigned Line, llvm::DINode::DIFlags Flags) {
11771166
auto UnsubstitutedTy = Decl->getDeclaredInterfaceType();
11781167
UnsubstitutedTy = Decl->mapTypeIntoContext(UnsubstitutedTy);
11791168

@@ -1183,39 +1172,99 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
11831172
std::string DeclTypeMangledName = Mangler.mangleTypeForDebugger(
11841173
UnsubstitutedTy->mapTypeOutOfContext(), {});
11851174
if (DeclTypeMangledName == MangledName) {
1186-
return createUnsubstitutedGenericStructOrClassType(
1187-
DbgTy, Decl, UnsubstitutedTy, Scope, File, Line, SizeInBits,
1188-
AlignInBits, Flags, nullptr, llvm::dwarf::DW_LANG_Swift,
1189-
DeclTypeMangledName);
1175+
return createUnsubstitutedVariantType(DbgTy, Decl, MangledName,
1176+
SizeInBits, AlignInBits, Scope,
1177+
File, 0, Flags);
11901178
}
1179+
auto FwdDecl = llvm::TempDIType(DBuilder.createReplaceableCompositeType(
1180+
llvm::dwarf::DW_TAG_structure_type, "", Scope, File, 0,
1181+
llvm::dwarf::DW_LANG_Swift, 0, 0, llvm::DINode::FlagZero, MangledName));
1182+
1183+
auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
1184+
DITypeCache[EnumTy] = TH;
11911185
// Force the creation of the unsubstituted type, don't create it
11921186
// directly so it goes through all the caching/verification logic.
1193-
auto UnsubstitutedType = getOrCreateType(DbgTy);
1194-
1195-
if (auto *ClassTy = llvm::dyn_cast<BoundGenericClassType>(Type)) {
1196-
auto SuperClassTy = ClassTy->getSuperclass();
1197-
if (SuperClassTy) {
1198-
auto SuperClassDbgTy = DebugTypeInfo::getFromTypeInfo(
1199-
SuperClassTy, IGM.getTypeInfoForUnlowered(SuperClassTy), IGM);
1200-
1201-
llvm::DIType *SuperClassDITy = getOrCreateType(SuperClassDbgTy);
1202-
assert(SuperClassDITy && "getOrCreateType should never return null!");
1203-
DBuilder.createInheritance(UnsubstitutedType, SuperClassDITy, 0, 0,
1204-
llvm::DINode::FlagZero);
1205-
}
1206-
1207-
auto *OpaqueType = createPointerSizedStruct(
1208-
Scope, Decl ? Decl->getNameStr() : MangledName, File, 0, Flags,
1209-
MangledName, UnsubstitutedType);
1210-
return OpaqueType;
1211-
}
1212-
1213-
auto *OpaqueType = createOpaqueStruct(
1214-
Scope, "", File, Line, SizeInBits, AlignInBits, Flags, MangledName,
1215-
collectGenericParams(Type), UnsubstitutedType);
1187+
auto unsubstitutedDbgTy = getOrCreateType(DbgTy);
1188+
auto DIType = createOpaqueStruct(
1189+
Scope, "", File, 0, SizeInBits, AlignInBits, Flags, MangledName,
1190+
collectGenericParams(EnumTy), unsubstitutedDbgTy);
1191+
DBuilder.replaceTemporary(std::move(FwdDecl), DIType);
1192+
return DIType;
1193+
}
1194+
1195+
/// Create a DICompositeType from a specialized struct. A specialized type
1196+
/// is a generic type, or a child type whose parent is generic.
1197+
llvm::DIType *
1198+
createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
1199+
NominalTypeDecl *Decl, llvm::DIScope *Scope,
1200+
llvm::DIFile *File, unsigned Line,
1201+
unsigned SizeInBits, unsigned AlignInBits,
1202+
llvm::DINode::DIFlags Flags,
1203+
StringRef MangledName,
1204+
bool IsClass = false) {
1205+
// To emit debug info of the DwarfTypes level for generic types, the strategy
1206+
// is to emit a description of all the fields for the type with archetypes,
1207+
// and still the same debug info as the ASTTypes level for the specialized
1208+
// type. For example, given:
1209+
// struct Pair<T, U> {
1210+
// let t: T
1211+
// let u: U
1212+
// }
1213+
// When emitting debug information for a type such as Pair<Int, Double>,
1214+
// emit a description of all the fields for Pair<T, U>, and emit the regular
1215+
// debug information for Pair<Int, Double>.
1216+
1217+
auto FwdDecl = llvm::TempDIType(DBuilder.createReplaceableCompositeType(
1218+
llvm::dwarf::DW_TAG_structure_type, "", Scope, File, Line,
1219+
llvm::dwarf::DW_LANG_Swift, SizeInBits, 0, Flags, MangledName));
1220+
1221+
auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
1222+
DITypeCache[Type] = TH;
1223+
1224+
// Go from Pair<Int, Double> to Pair<T, U>.
1225+
auto UnsubstitutedTy = Decl->getDeclaredInterfaceType();
1226+
UnsubstitutedTy = Decl->mapTypeIntoContext(UnsubstitutedTy);
1227+
1228+
auto DbgTy = DebugTypeInfo::getFromTypeInfo(
1229+
UnsubstitutedTy, IGM.getTypeInfoForUnlowered(UnsubstitutedTy), IGM);
1230+
Mangle::ASTMangler Mangler;
1231+
std::string DeclTypeMangledName =
1232+
Mangler.mangleTypeForDebugger(UnsubstitutedTy->mapTypeOutOfContext(), {});
1233+
if (DeclTypeMangledName == MangledName) {
1234+
return createUnsubstitutedGenericStructOrClassType(
1235+
DbgTy, Decl, UnsubstitutedTy, Scope, File, Line, SizeInBits,
1236+
AlignInBits, Flags, nullptr, llvm::dwarf::DW_LANG_Swift,
1237+
DeclTypeMangledName);
1238+
}
1239+
// Force the creation of the unsubstituted type, don't create it
1240+
// directly so it goes through all the caching/verification logic.
1241+
auto UnsubstitutedType = getOrCreateType(DbgTy);
1242+
1243+
if (auto *ClassTy = llvm::dyn_cast<BoundGenericClassType>(Type)) {
1244+
auto SuperClassTy = ClassTy->getSuperclass();
1245+
if (SuperClassTy) {
1246+
auto SuperClassDbgTy = DebugTypeInfo::getFromTypeInfo(
1247+
SuperClassTy, IGM.getTypeInfoForUnlowered(SuperClassTy), IGM);
1248+
1249+
llvm::DIType *SuperClassDITy = getOrCreateType(SuperClassDbgTy);
1250+
assert(SuperClassDITy && "getOrCreateType should never return null!");
1251+
DBuilder.createInheritance(UnsubstitutedType, SuperClassDITy, 0, 0,
1252+
llvm::DINode::FlagZero);
1253+
}
1254+
1255+
auto *OpaqueType = createPointerSizedStruct(
1256+
Scope, Decl ? Decl->getNameStr() : MangledName, File, 0, Flags,
1257+
MangledName, UnsubstitutedType);
12161258
return OpaqueType;
12171259
}
12181260

1261+
auto *OpaqueType = createOpaqueStruct(
1262+
Scope, "", File, Line, SizeInBits, AlignInBits, Flags, MangledName,
1263+
collectGenericParams(Type), UnsubstitutedType);
1264+
DBuilder.replaceTemporary(std::move(FwdDecl), OpaqueType);
1265+
return OpaqueType;
1266+
}
1267+
12191268
/// Create debug information for an enum with a raw type (enum E : Int {}).
12201269
llvm::DICompositeType *createRawEnumType(CompletedDebugTypeInfo DbgTy,
12211270
EnumDecl *Decl,
@@ -1441,17 +1490,29 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
14411490
/// Collect the type parameters of a bound generic type. This is needed to
14421491
/// anchor any typedefs that may appear in parameters so they can be
14431492
/// resolved in the debugger without needing to query the Swift module.
1444-
llvm::DINodeArray collectGenericParams(BoundGenericType *BGT) {
1493+
llvm::DINodeArray
1494+
collectGenericParams(NominalOrBoundGenericNominalType *BGT) {
1495+
1496+
// Collect the generic args from the type and its parent.
1497+
std::vector<Type> GenericArgs;
1498+
Type CurrentType = BGT;
1499+
while (CurrentType && CurrentType->getAnyNominal()) {
1500+
if (auto *BGT = llvm::dyn_cast<BoundGenericType>(CurrentType))
1501+
GenericArgs.insert(GenericArgs.end(), BGT->getGenericArgs().begin(),
1502+
BGT->getGenericArgs().end());
1503+
CurrentType = CurrentType->getNominalParent();
1504+
}
1505+
14451506
SmallVector<llvm::Metadata *, 16> TemplateParams;
1446-
for (auto Param : BGT->getGenericArgs()) {
1507+
for (auto Arg : GenericArgs) {
14471508
DebugTypeInfo ParamDebugType;
14481509
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes)
1449-
// For full debug info don't generate just a forward declaration for
1450-
// the generic type parameters.
1510+
// For the DwarfTypes level don't generate just a forward declaration
1511+
// for the generic type parameters.
14511512
ParamDebugType = DebugTypeInfo::getFromTypeInfo(
1452-
Param, IGM.getTypeInfoForUnlowered(Param), IGM);
1513+
Arg, IGM.getTypeInfoForUnlowered(Arg), IGM);
14531514
else
1454-
ParamDebugType = DebugTypeInfo::getForwardDecl(Param);
1515+
ParamDebugType = DebugTypeInfo::getForwardDecl(Arg);
14551516

14561517
TemplateParams.push_back(DBuilder.createTemplateTypeParameter(
14571518
TheCU, "", getOrCreateType(ParamDebugType), false));
@@ -1625,7 +1686,6 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
16251686
createMemberType(DbgTy, "", OffsetInBits, Scope, MainFile, Flags));
16261687
}
16271688
// FIXME: assert that SizeInBits == OffsetInBits.
1628-
SizeInBits = OffsetInBits;
16291689

16301690
auto FwdDecl = llvm::TempDINode(DBuilder.createReplaceableCompositeType(
16311691
llvm::dwarf::DW_TAG_structure_type, MangledName, Scope, MainFile, 0,
@@ -1786,10 +1846,15 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
17861846
// don't want a whitespace change to an secondary file trigger a
17871847
// recompilation of the debug info of a primary source file.
17881848
unsigned FwdDeclLine = 0;
1789-
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes)
1849+
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes) {
1850+
if (StructTy->isSpecialized())
1851+
return createSpecializedStructOrClassType(
1852+
StructTy, Decl, Scope, L.File, L.Line, SizeInBits, AlignInBits,
1853+
Flags, MangledName);
17901854
return createStructType(DbgTy, Decl, StructTy, Scope, L.File, L.Line,
17911855
SizeInBits, AlignInBits, Flags, nullptr,
17921856
llvm::dwarf::DW_LANG_Swift, MangledName);
1857+
}
17931858
StringRef Name = Decl->getName().str();
17941859
if (!SizeInBitsOrNull)
17951860
return DBuilder.createForwardDecl(
@@ -1814,6 +1879,11 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
18141879
assert(SizeInBits ==
18151880
CI.getTargetInfo().getPointerWidth(clang::LangAS::Default));
18161881
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes) {
1882+
if (ClassTy->isSpecialized())
1883+
return createSpecializedStructOrClassType(
1884+
ClassTy, Decl, Scope, L.File, L.Line, SizeInBits, AlignInBits,
1885+
Flags, MangledName);
1886+
18171887
auto *DIType = createStructType(
18181888
DbgTy, Decl, ClassTy, Scope, File, L.Line, SizeInBits, AlignInBits,
18191889
Flags, nullptr, llvm::dwarf::DW_LANG_Swift, MangledName);
@@ -1875,7 +1945,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
18751945
auto L = getFileAndLocation(Decl);
18761946
unsigned FwdDeclLine = 0;
18771947
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes)
1878-
return createFullDebugInfoGenericForStructOrClassType(
1948+
return createSpecializedStructOrClassType(
18791949
StructTy, Decl, Scope, L.File, L.Line, SizeInBits, AlignInBits,
18801950
Flags, MangledName);
18811951

@@ -1892,7 +1962,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
18921962
unsigned FwdDeclLine = 0;
18931963

18941964
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes)
1895-
return createFullDebugInfoGenericForStructOrClassType(
1965+
return createSpecializedStructOrClassType(
18961966
ClassTy, Decl, Scope, L.File, L.Line, SizeInBits, AlignInBits,
18971967
Flags, MangledName);
18981968

@@ -2011,10 +2081,16 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
20112081
auto *Decl = EnumTy->getDecl();
20122082
auto L = getFileAndLocation(Decl);
20132083
unsigned FwdDeclLine = 0;
2014-
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes)
2084+
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes) {
2085+
if (EnumTy->isSpecialized())
2086+
return createSpecializedEnumType(EnumTy, Decl, MangledName,
2087+
SizeInBits, AlignInBits, Scope, File,
2088+
FwdDeclLine, Flags);
2089+
20152090
if (CompletedDbgTy)
20162091
return createEnumType(*CompletedDbgTy, Decl, MangledName, AlignInBits,
20172092
Scope, L.File, L.Line, Flags);
2093+
}
20182094
return createOpaqueStruct(Scope, Decl->getName().str(), L.File,
20192095
FwdDeclLine, SizeInBits, AlignInBits, Flags,
20202096
MangledName);
@@ -2027,25 +2103,13 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
20272103
unsigned FwdDeclLine = 0;
20282104

20292105
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes) {
2030-
auto UnsubstitutedTy = Decl->getDeclaredInterfaceType();
2031-
UnsubstitutedTy = Decl->mapTypeIntoContext(UnsubstitutedTy);
2032-
2033-
auto DbgTy = DebugTypeInfo::getFromTypeInfo(
2034-
UnsubstitutedTy, IGM.getTypeInfoForUnlowered(UnsubstitutedTy), IGM);
2035-
Mangle::ASTMangler Mangler;
2036-
std::string DeclTypeMangledName = Mangler.mangleTypeForDebugger(
2037-
UnsubstitutedTy->mapTypeOutOfContext(), {});
2038-
if (DeclTypeMangledName == MangledName) {
2039-
return createUnsubstitutedVariantType(DbgTy, Decl, MangledName,
2040-
SizeInBits, AlignInBits, Scope, File,
2041-
FwdDeclLine, Flags);
2042-
}
2043-
// Force the creation of the unsubstituted type, don't create it
2044-
// directly so it goes through all the caching/verification logic.
2045-
auto unsubstitutedDbgTy = getOrCreateType(DbgTy);
2046-
return createOpaqueStruct(
2047-
Scope, "", L.File, FwdDeclLine, SizeInBits, AlignInBits, Flags,
2048-
MangledName, collectGenericParams(EnumTy), unsubstitutedDbgTy);
2106+
if (EnumTy->isSpecialized())
2107+
return createSpecializedEnumType(EnumTy, Decl, MangledName,
2108+
SizeInBits, AlignInBits, Scope, File,
2109+
FwdDeclLine, Flags);
2110+
if (CompletedDbgTy)
2111+
return createEnumType(*CompletedDbgTy, Decl, MangledName, AlignInBits,
2112+
Scope, L.File, L.Line, Flags);
20492113
}
20502114
return createOpaqueStructWithSizedContainer(
20512115
Scope, Decl->getName().str(), L.File, FwdDeclLine, SizeInBits,
@@ -2184,6 +2248,10 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
21842248
#ifndef NDEBUG
21852249
/// Verify that the size of this type matches the one of the cached type.
21862250
bool sanityCheckCachedType(DebugTypeInfo DbgTy, llvm::DIType *CachedType) {
2251+
// If this is a temporary, we're in the middle of creating a recursive type,
2252+
// so skip the sanity check.
2253+
if (CachedType->isTemporary())
2254+
return true;
21872255
if (DbgTy.isForwardDecl())
21882256
return true;
21892257
auto CompletedDbgTy = CompletedDebugTypeInfo::getFromTypeInfo(

test/DebugInfo/BoundGenericStruct.swift

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,35 @@ public let s = S<Int>(t: 0)
2525
// DWARF: !DICompositeType(tag: DW_TAG_structure_type, name: "S",
2626
// DWARF-SAME: identifier: "$s18BoundGenericStruct1SVyxGD")
2727
// DWARF: !DIDerivedType(tag: DW_TAG_member, name: "t"
28-
// DWARF: !DICompositeType(tag: DW_TAG_structure_type, name: "$sxD"
28+
// DWARF: ![[GENERIC_PARAM_TYPE:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "$sxD"
2929

3030

31+
public struct S2<T> {
32+
public struct Inner {
33+
let t: T
34+
}
35+
}
36+
public let inner = S2<Double>.Inner(t:4.2)
37+
38+
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Inner",
39+
// CHECK-SAME: size: 64, {{.*}}identifier: "$s18BoundGenericStruct2S2V5InnerVySd_GD")
40+
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "$s18BoundGenericStruct2S2VyxGD",
41+
// CHECK-SAME: flags: DIFlagFwdDecl, runtimeLang: DW_LANG_Swift)
42+
43+
// DWARF: !DICompositeType(tag: DW_TAG_structure_type, scope: ![[SCOPE1:[0-9]+]],
44+
// DWARF-SAME: size: 64, {{.*}}, templateParams: ![[PARAMS2:[0-9]+]], identifier: "$s18BoundGenericStruct2S2V5InnerVySd_GD"
45+
// DWARF-SAME: specification_of: ![[SPECIFICATION:[0-9]+]]
46+
47+
// DWARF: ![[SCOPE1]] = !DICompositeType(tag: DW_TAG_structure_type, name: "$s18BoundGenericStruct2S2VyxGD",
48+
49+
// DWARF: ![[PARAMS2]] = !{![[PARAMS3:[0-9]+]]}
50+
// DWARF: ![[PARAMS3]] = !DITemplateTypeParameter(type: ![[PARAMS4:[0-9]+]])
51+
// DWARF: ![[PARAMS4]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Double",
52+
// DWARF-SAME: size: 64, {{.*}}runtimeLang: DW_LANG_Swift, identifier: "$sSdD")
53+
54+
// DWARF: [[SPECIFICATION]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Inner",
55+
// DWARF-SAME: elements: ![[ELEMENTS1:[0-9]+]], runtimeLang: DW_LANG_Swift, identifier: "$s18BoundGenericStruct2S2V5InnerVyx_GD")
56+
57+
// DWARF: ![[ELEMENTS1]] = !{![[ELEMENTS2:[0-9]+]]}
58+
59+
// DWARF: ![[ELEMENTS2]] = !DIDerivedType(tag: DW_TAG_member, name: "t", scope: !27, file: !3, baseType: ![[GENERIC_PARAM_TYPE]])

0 commit comments

Comments
 (0)