Skip to content

Commit ae5e341

Browse files
committed
[DebugInfo] Generate debug info for specialized types
Specialized types are generic types, or types whose parent is specialized. IRGenDebugInfo was previously mistankenly emitting debug info for nominal specialized types as if they regular nominal types, which caused problems as that code path does not handle references to generic parameters.
1 parent 2c6cc4a commit ae5e341

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
@@ -5887,8 +5887,10 @@ namespace {
58875887
std::optional<SpareBitsMaskInfo> calculateSpareBitsMask() const override {
58885888
SpareBitVector spareBits;
58895889
for (auto enumCase : getElementsWithPayload()) {
5890-
cast<FixedTypeInfo>(enumCase.ti)
5891-
->applyFixedSpareBitsMask(IGM, spareBits);
5890+
if (auto fixedTI = llvm::dyn_cast<FixedTypeInfo>(enumCase.ti))
5891+
fixedTI->applyFixedSpareBitsMask(IGM, spareBits);
5892+
else
5893+
return {};
58925894
}
58935895
// Trim leading/trailing zero bytes, then pad to a multiple of 32 bits
58945896
llvm::APInt bits = spareBits.asAPInt();

lib/IRGen/IRGenDebugInfo.cpp

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

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

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

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

14541515
TemplateParams.push_back(DBuilder.createTemplateTypeParameter(
14551516
TheCU, "", getOrCreateType(ParamDebugType), false));
@@ -1623,7 +1684,6 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
16231684
createMemberType(DbgTy, "", OffsetInBits, Scope, MainFile, Flags));
16241685
}
16251686
// FIXME: assert that SizeInBits == OffsetInBits.
1626-
SizeInBits = OffsetInBits;
16271687

16281688
auto FwdDecl = llvm::TempDINode(DBuilder.createReplaceableCompositeType(
16291689
llvm::dwarf::DW_TAG_structure_type, MangledName, Scope, MainFile, 0,
@@ -1784,10 +1844,15 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
17841844
// don't want a whitespace change to an secondary file trigger a
17851845
// recompilation of the debug info of a primary source file.
17861846
unsigned FwdDeclLine = 0;
1787-
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes)
1847+
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes) {
1848+
if (StructTy->isSpecialized())
1849+
return createSpecializedStructOrClassType(
1850+
StructTy, Decl, Scope, L.File, L.Line, SizeInBits, AlignInBits,
1851+
Flags, MangledName);
17881852
return createStructType(DbgTy, Decl, StructTy, Scope, L.File, L.Line,
17891853
SizeInBits, AlignInBits, Flags, nullptr,
17901854
llvm::dwarf::DW_LANG_Swift, MangledName);
1855+
}
17911856
StringRef Name = Decl->getName().str();
17921857
if (!SizeInBitsOrNull)
17931858
return DBuilder.createForwardDecl(
@@ -1812,6 +1877,11 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
18121877
assert(SizeInBits ==
18131878
CI.getTargetInfo().getPointerWidth(clang::LangAS::Default));
18141879
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes) {
1880+
if (ClassTy->isSpecialized())
1881+
return createSpecializedStructOrClassType(
1882+
ClassTy, Decl, Scope, L.File, L.Line, SizeInBits, AlignInBits,
1883+
Flags, MangledName);
1884+
18151885
auto *DIType = createStructType(
18161886
DbgTy, Decl, ClassTy, Scope, File, L.Line, SizeInBits, AlignInBits,
18171887
Flags, nullptr, llvm::dwarf::DW_LANG_Swift, MangledName);
@@ -1873,7 +1943,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
18731943
auto L = getFileAndLocation(Decl);
18741944
unsigned FwdDeclLine = 0;
18751945
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes)
1876-
return createFullDebugInfoGenericForStructOrClassType(
1946+
return createSpecializedStructOrClassType(
18771947
StructTy, Decl, Scope, L.File, L.Line, SizeInBits, AlignInBits,
18781948
Flags, MangledName);
18791949

@@ -1890,7 +1960,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
18901960
unsigned FwdDeclLine = 0;
18911961

18921962
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes)
1893-
return createFullDebugInfoGenericForStructOrClassType(
1963+
return createSpecializedStructOrClassType(
18941964
ClassTy, Decl, Scope, L.File, L.Line, SizeInBits, AlignInBits,
18951965
Flags, MangledName);
18961966

@@ -2009,10 +2079,16 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
20092079
auto *Decl = EnumTy->getDecl();
20102080
auto L = getFileAndLocation(Decl);
20112081
unsigned FwdDeclLine = 0;
2012-
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes)
2082+
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes) {
2083+
if (EnumTy->isSpecialized())
2084+
return createSpecializedEnumType(EnumTy, Decl, MangledName,
2085+
SizeInBits, AlignInBits, Scope, File,
2086+
FwdDeclLine, Flags);
2087+
20132088
if (CompletedDbgTy)
20142089
return createEnumType(*CompletedDbgTy, Decl, MangledName, AlignInBits,
20152090
Scope, L.File, L.Line, Flags);
2091+
}
20162092
return createOpaqueStruct(Scope, Decl->getName().str(), L.File,
20172093
FwdDeclLine, SizeInBits, AlignInBits, Flags,
20182094
MangledName);
@@ -2025,25 +2101,13 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
20252101
unsigned FwdDeclLine = 0;
20262102

20272103
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes) {
2028-
auto UnsubstitutedTy = Decl->getDeclaredInterfaceType();
2029-
UnsubstitutedTy = Decl->mapTypeIntoContext(UnsubstitutedTy);
2030-
2031-
auto DbgTy = DebugTypeInfo::getFromTypeInfo(
2032-
UnsubstitutedTy, IGM.getTypeInfoForUnlowered(UnsubstitutedTy), IGM);
2033-
Mangle::ASTMangler Mangler;
2034-
std::string DeclTypeMangledName = Mangler.mangleTypeForDebugger(
2035-
UnsubstitutedTy->mapTypeOutOfContext(), {});
2036-
if (DeclTypeMangledName == MangledName) {
2037-
return createUnsubstitutedVariantType(DbgTy, Decl, MangledName,
2038-
SizeInBits, AlignInBits, Scope, File,
2039-
FwdDeclLine, Flags);
2040-
}
2041-
// Force the creation of the unsubstituted type, don't create it
2042-
// directly so it goes through all the caching/verification logic.
2043-
auto unsubstitutedDbgTy = getOrCreateType(DbgTy);
2044-
return createOpaqueStruct(
2045-
Scope, "", L.File, FwdDeclLine, SizeInBits, AlignInBits, Flags,
2046-
MangledName, collectGenericParams(EnumTy), unsubstitutedDbgTy);
2104+
if (EnumTy->isSpecialized())
2105+
return createSpecializedEnumType(EnumTy, Decl, MangledName,
2106+
SizeInBits, AlignInBits, Scope, File,
2107+
FwdDeclLine, Flags);
2108+
if (CompletedDbgTy)
2109+
return createEnumType(*CompletedDbgTy, Decl, MangledName, AlignInBits,
2110+
Scope, L.File, L.Line, Flags);
20472111
}
20482112
return createOpaqueStructWithSizedContainer(
20492113
Scope, Decl->getName().str(), L.File, FwdDeclLine, SizeInBits,
@@ -2182,6 +2246,10 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
21822246
#ifndef NDEBUG
21832247
/// Verify that the size of this type matches the one of the cached type.
21842248
bool sanityCheckCachedType(DebugTypeInfo DbgTy, llvm::DIType *CachedType) {
2249+
// If this is a temporary, we're in the middle of creating a recursive type,
2250+
// so skip the sanity check.
2251+
if (CachedType->isTemporary())
2252+
return true;
21852253
if (DbgTy.isForwardDecl())
21862254
return true;
21872255
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)