Skip to content

Commit aa6b5c2

Browse files
committed
[DebugInfo] Fix recursively generating debug info for same type
Debug Info generation already has a check to stop it from generating debug info for a type with the same mangled name. However, most of the code paths in debug info generation would not add the mangled name to the cache while generation was not done. This patch fixes that so types that are in-flight don't have their debug info generated twice. rdar://142500619
1 parent 29bcd2c commit aa6b5c2

File tree

2 files changed

+130
-128
lines changed

2 files changed

+130
-128
lines changed

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 103 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,28 +1092,30 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
10921092
return DITy;
10931093
}
10941094

1095-
llvm::TempDIType createStructForwardDecl(
1096-
DebugTypeInfo DbgTy, NominalTypeDecl *Decl, llvm::DIScope *Scope,
1097-
llvm::DIFile *File, unsigned Line, unsigned SizeInBits,
1098-
llvm::DINode::DIFlags Flags, StringRef UniqueID, StringRef Name) {
1099-
// Forward declare this first because types may be recursive.
1100-
llvm::TempDICompositeType FwdDecl(DBuilder.createReplaceableCompositeType(
1101-
llvm::dwarf::DW_TAG_structure_type, Name, Scope, File, Line,
1102-
llvm::dwarf::DW_LANG_Swift, SizeInBits, 0, Flags, UniqueID));
1103-
1095+
/// Creates a temporary replaceable forward decl to protect against recursion.
1096+
llvm::TempDIType createTemporaryReplaceableForwardDecl(
1097+
TypeBase *Type, llvm::DIScope *Scope, llvm::DIFile *File, unsigned Line,
1098+
unsigned SizeInBits, unsigned AlignInBits, llvm::DINode::DIFlags Flags,
1099+
StringRef MangledName, StringRef Name) {
11041100
#ifndef NDEBUG
1105-
if (UniqueID.empty())
1101+
if (MangledName.empty())
11061102
assert(!Name.empty() &&
11071103
"no mangled name and no human readable name given");
11081104
else
1109-
assert((UniqueID.starts_with("_T") ||
1110-
UniqueID.starts_with(MANGLING_PREFIX_STR) ||
1111-
UniqueID.starts_with(MANGLING_PREFIX_EMBEDDED_STR)) &&
1105+
assert(swift::Demangle::isMangledName(MangledName) &&
11121106
"UID is not a mangled name");
11131107
#endif
1108+
auto ReplaceableType = DBuilder.createReplaceableCompositeType(
1109+
llvm::dwarf::DW_TAG_structure_type, "", Scope, File, Line,
1110+
llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags,
1111+
MangledName);
1112+
auto FwdDecl = llvm::TempDIType(ReplaceableType);
11141113

11151114
auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
1116-
DITypeCache[DbgTy.getType()] = TH;
1115+
DITypeCache[Type] = TH;
1116+
if (auto UID = ReplaceableType->getRawIdentifier())
1117+
DIRefMap[UID] = llvm::TrackingMDNodeRef(TH);
1118+
11171119
return FwdDecl;
11181120
}
11191121

@@ -1124,8 +1126,9 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
11241126
llvm::DINode::DIFlags Flags, llvm::DIType *DerivedFrom,
11251127
unsigned RuntimeLang, StringRef UniqueID) {
11261128
StringRef Name = Decl->getName().str();
1127-
auto FwdDecl = createStructForwardDecl(DbgTy, Decl, Scope, File, Line,
1128-
SizeInBits, Flags, UniqueID, Name);
1129+
auto FwdDecl = createTemporaryReplaceableForwardDecl(
1130+
DbgTy.getType(), Scope, File, Line, SizeInBits, AlignInBits, Flags,
1131+
UniqueID, Name);
11291132
// Collect the members.
11301133
SmallVector<llvm::Metadata *, 16> Elements;
11311134
unsigned OffsetInBits = 0;
@@ -1171,9 +1174,9 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
11711174
unsigned SizeInBits = 0;
11721175
unsigned AlignInBits = 0;
11731176
StringRef Name = Decl->getName().str();
1174-
auto FwdDecl = createStructForwardDecl(DbgTy, Decl, Scope, File, Line,
1175-
SizeInBits, Flags, UniqueID, Name);
1176-
1177+
auto FwdDecl = createTemporaryReplaceableForwardDecl(
1178+
DbgTy.getType(), Scope, File, Line, SizeInBits, AlignInBits, Flags,
1179+
UniqueID, Name);
11771180
// Collect the members.
11781181
SmallVector<llvm::Metadata *, 16> Elements;
11791182
for (VarDecl *VD : Decl->getStoredProperties()) {
@@ -1215,12 +1218,10 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
12151218
return createUnsubstitutedVariantType(DbgTy, Decl, MangledName, Scope,
12161219
File, 0, Flags);
12171220
}
1218-
auto FwdDecl = llvm::TempDIType(DBuilder.createReplaceableCompositeType(
1219-
llvm::dwarf::DW_TAG_structure_type, "", Scope, File, 0,
1220-
llvm::dwarf::DW_LANG_Swift, 0, 0, llvm::DINode::FlagZero, MangledName));
1221-
1222-
auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
1223-
DITypeCache[EnumTy] = TH;
1221+
StringRef Name = Decl->getName().str();
1222+
auto FwdDecl = createTemporaryReplaceableForwardDecl(
1223+
EnumTy, Scope, File, Line, SizeInBits, AlignInBits, Flags, MangledName,
1224+
Name);
12241225
// Force the creation of the unsubstituted type, don't create it
12251226
// directly so it goes through all the caching/verification logic.
12261227
auto unsubstitutedDbgTy = getOrCreateType(DbgTy);
@@ -1231,78 +1232,71 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
12311232
return DIType;
12321233
}
12331234

1234-
/// Create a DICompositeType from a specialized struct. A specialized type
1235-
/// is a generic type, or a child type whose parent is generic.
1236-
llvm::DIType *
1237-
createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
1238-
NominalTypeDecl *Decl, llvm::DIScope *Scope,
1239-
llvm::DIFile *File, unsigned Line,
1240-
unsigned SizeInBits, unsigned AlignInBits,
1241-
llvm::DINode::DIFlags Flags,
1242-
StringRef MangledName,
1243-
bool IsClass = false) {
1244-
// To emit debug info of the DwarfTypes level for generic types, the strategy
1245-
// is to emit a description of all the fields for the type with archetypes,
1246-
// and still the same debug info as the ASTTypes level for the specialized
1247-
// type. For example, given:
1248-
// struct Pair<T, U> {
1249-
// let t: T
1250-
// let u: U
1251-
// }
1252-
// When emitting debug information for a type such as Pair<Int, Double>,
1253-
// emit a description of all the fields for Pair<T, U>, and emit the regular
1254-
// debug information for Pair<Int, Double>.
1255-
1256-
auto FwdDecl = llvm::TempDIType(DBuilder.createReplaceableCompositeType(
1257-
llvm::dwarf::DW_TAG_structure_type, "", Scope, File, Line,
1258-
llvm::dwarf::DW_LANG_Swift, SizeInBits, 0, Flags, MangledName));
1259-
1260-
auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
1261-
DITypeCache[Type] = TH;
1262-
1263-
// Go from Pair<Int, Double> to Pair<T, U>.
1264-
auto UnsubstitutedTy = Decl->getDeclaredInterfaceType();
1265-
UnsubstitutedTy = Decl->mapTypeIntoContext(UnsubstitutedTy);
1266-
1267-
auto DbgTy = DebugTypeInfo::getFromTypeInfo(
1268-
UnsubstitutedTy, IGM.getTypeInfoForUnlowered(UnsubstitutedTy), IGM);
1269-
Mangle::ASTMangler Mangler(IGM.Context);
1270-
std::string DeclTypeMangledName =
1271-
Mangler.mangleTypeForDebugger(UnsubstitutedTy->mapTypeOutOfContext(), {});
1272-
if (DeclTypeMangledName == MangledName) {
1273-
return createUnsubstitutedGenericStructOrClassType(
1274-
DbgTy, Decl, UnsubstitutedTy, Scope, File, Line, Flags, nullptr,
1275-
llvm::dwarf::DW_LANG_Swift, DeclTypeMangledName);
1276-
}
1277-
// Force the creation of the unsubstituted type, don't create it
1278-
// directly so it goes through all the caching/verification logic.
1279-
auto UnsubstitutedType = getOrCreateType(DbgTy);
1280-
1281-
if (auto *ClassTy = llvm::dyn_cast<BoundGenericClassType>(Type)) {
1282-
auto SuperClassTy = ClassTy->getSuperclass();
1283-
if (SuperClassTy) {
1284-
auto SuperClassDbgTy = DebugTypeInfo::getFromTypeInfo(
1285-
SuperClassTy, IGM.getTypeInfoForUnlowered(SuperClassTy), IGM);
1286-
1287-
llvm::DIType *SuperClassDITy = getOrCreateType(SuperClassDbgTy);
1288-
assert(SuperClassDITy && "getOrCreateType should never return null!");
1289-
DBuilder.createInheritance(UnsubstitutedType, SuperClassDITy, 0, 0,
1290-
llvm::DINode::FlagZero);
1291-
}
1292-
1293-
auto *OpaqueType = createPointerSizedStruct(
1294-
Scope, Decl ? Decl->getNameStr() : MangledName, File, 0, Flags,
1295-
MangledName, UnsubstitutedType);
1235+
/// Create a DICompositeType from a specialized struct. A specialized type
1236+
/// is a generic type, or a child type whose parent is generic.
1237+
llvm::DIType *createSpecializedStructOrClassType(
1238+
NominalOrBoundGenericNominalType *Type, NominalTypeDecl *Decl,
1239+
llvm::DIScope *Scope, llvm::DIFile *File, unsigned Line,
1240+
unsigned SizeInBits, unsigned AlignInBits, llvm::DINode::DIFlags Flags,
1241+
StringRef MangledName, bool IsClass = false) {
1242+
// To emit debug info of the DwarfTypes level for generic types, the
1243+
// strategy is to emit a description of all the fields for the type with
1244+
// archetypes, and still the same debug info as the ASTTypes level for the
1245+
// specialized type. For example, given: struct Pair<T, U> {
1246+
// let t: T
1247+
// let u: U
1248+
// }
1249+
// When emitting debug information for a type such as Pair<Int, Double>,
1250+
// emit a description of all the fields for Pair<T, U>, and emit the regular
1251+
// debug information for Pair<Int, Double>.
1252+
StringRef Name = Decl->getName().str();
1253+
auto FwdDecl = createTemporaryReplaceableForwardDecl(
1254+
Type, Scope, File, Line, SizeInBits, AlignInBits, Flags, MangledName,
1255+
Name);
1256+
1257+
// Go from Pair<Int, Double> to Pair<T, U>.
1258+
auto UnsubstitutedTy = Decl->getDeclaredInterfaceType();
1259+
UnsubstitutedTy = Decl->mapTypeIntoContext(UnsubstitutedTy);
1260+
1261+
auto DbgTy = DebugTypeInfo::getFromTypeInfo(
1262+
UnsubstitutedTy, IGM.getTypeInfoForUnlowered(UnsubstitutedTy), IGM);
1263+
Mangle::ASTMangler Mangler(IGM.Context);
1264+
std::string DeclTypeMangledName = Mangler.mangleTypeForDebugger(
1265+
UnsubstitutedTy->mapTypeOutOfContext(), {});
1266+
if (DeclTypeMangledName == MangledName) {
1267+
return createUnsubstitutedGenericStructOrClassType(
1268+
DbgTy, Decl, UnsubstitutedTy, Scope, File, Line, Flags, nullptr,
1269+
llvm::dwarf::DW_LANG_Swift, DeclTypeMangledName);
1270+
}
1271+
// Force the creation of the unsubstituted type, don't create it
1272+
// directly so it goes through all the caching/verification logic.
1273+
auto UnsubstitutedType = getOrCreateType(DbgTy);
1274+
1275+
if (auto *ClassTy = llvm::dyn_cast<BoundGenericClassType>(Type)) {
1276+
auto SuperClassTy = ClassTy->getSuperclass();
1277+
if (SuperClassTy) {
1278+
auto SuperClassDbgTy = DebugTypeInfo::getFromTypeInfo(
1279+
SuperClassTy, IGM.getTypeInfoForUnlowered(SuperClassTy), IGM);
1280+
1281+
llvm::DIType *SuperClassDITy = getOrCreateType(SuperClassDbgTy);
1282+
assert(SuperClassDITy && "getOrCreateType should never return null!");
1283+
DBuilder.createInheritance(UnsubstitutedType, SuperClassDITy, 0, 0,
1284+
llvm::DINode::FlagZero);
1285+
}
1286+
1287+
auto *OpaqueType = createPointerSizedStruct(
1288+
Scope, Decl ? Decl->getNameStr() : MangledName, File, 0, Flags,
1289+
MangledName, UnsubstitutedType);
1290+
return OpaqueType;
1291+
}
1292+
1293+
auto *OpaqueType = createOpaqueStruct(
1294+
Scope, "", File, Line, SizeInBits, AlignInBits, Flags, MangledName,
1295+
collectGenericParams(Type), UnsubstitutedType);
1296+
DBuilder.replaceTemporary(std::move(FwdDecl), OpaqueType);
12961297
return OpaqueType;
12971298
}
12981299

1299-
auto *OpaqueType = createOpaqueStruct(
1300-
Scope, "", File, Line, SizeInBits, AlignInBits, Flags, MangledName,
1301-
collectGenericParams(Type), UnsubstitutedType);
1302-
DBuilder.replaceTemporary(std::move(FwdDecl), OpaqueType);
1303-
return OpaqueType;
1304-
}
1305-
13061300
/// Create debug information for an enum with a raw type (enum E : Int {}).
13071301
llvm::DICompositeType *createRawEnumType(CompletedDebugTypeInfo DbgTy,
13081302
EnumDecl *Decl,
@@ -1319,13 +1313,9 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
13191313
// Default, since Swift doesn't allow specifying a custom alignment.
13201314
unsigned AlignInBits = 0;
13211315

1322-
llvm::TempDICompositeType FwdDecl(DBuilder.createReplaceableCompositeType(
1323-
llvm::dwarf::DW_TAG_enumeration_type, MangledName, Scope, File, Line,
1324-
llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags,
1325-
MangledName));
1326-
1327-
auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
1328-
DITypeCache[DbgTy.getType()] = TH;
1316+
auto FwdDecl = createTemporaryReplaceableForwardDecl(
1317+
DbgTy.getType(), Scope, File, Line, SizeInBits, AlignInBits, Flags,
1318+
MangledName, Name);
13291319

13301320
auto RawType = Decl->getRawType();
13311321
auto &TI = IGM.getTypeInfoForUnlowered(RawType);
@@ -1373,14 +1363,10 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
13731363

13741364
// A variant part should actually be a child to a DW_TAG_structure_type
13751365
// according to the DWARF spec.
1376-
llvm::TempDICompositeType FwdDecl(DBuilder.createReplaceableCompositeType(
1377-
llvm::dwarf::DW_TAG_structure_type, MangledName, Scope, File, Line,
1378-
llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags,
1379-
MangledName));
1380-
1381-
auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
1382-
DITypeCache[DbgTy.getType()] = TH;
13831366

1367+
auto FwdDecl = createTemporaryReplaceableForwardDecl(
1368+
DbgTy.getType(), Scope, File, Line, SizeInBits, AlignInBits, Flags,
1369+
MangledName, Name);
13841370
SmallVector<llvm::Metadata *, 16> Elements;
13851371
for (auto *ElemDecl : Decl->getAllElements()) {
13861372
std::optional<CompletedDebugTypeInfo> ElemDbgTy;
@@ -1437,13 +1423,9 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
14371423
unsigned AlignInBits = 0;
14381424
// A variant part should actually be a child to a DW_TAG_structure_type
14391425
// according to the DWARF spec.
1440-
llvm::TempDICompositeType FwdDecl(DBuilder.createReplaceableCompositeType(
1441-
llvm::dwarf::DW_TAG_structure_type, MangledName, Scope, File, Line,
1442-
llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags,
1443-
MangledName));
1444-
1445-
auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
1446-
DITypeCache[DbgTy.getType()] = TH;
1426+
auto FwdDecl = createTemporaryReplaceableForwardDecl(
1427+
DbgTy.getType(), Scope, File, Line, SizeInBits, AlignInBits, Flags,
1428+
MangledName, Name);
14471429

14481430
SmallVector<llvm::Metadata *, 16> Elements;
14491431
for (auto *ElemDecl : Decl->getAllElements()) {
@@ -1655,13 +1637,9 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
16551637
unsigned SizeInBits, unsigned AlignInBits,
16561638
llvm::DINode::DIFlags Flags,
16571639
StringRef MangledName) {
1658-
llvm::TempDICompositeType FwdDecl(DBuilder.createReplaceableCompositeType(
1659-
llvm::dwarf::DW_TAG_subroutine_type, MangledName, Scope, MainFile, 0,
1660-
llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags,
1661-
MangledName));
1662-
1663-
auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
1664-
DITypeCache[DbgTy.getType()] = TH;
1640+
auto FwdDecl = createTemporaryReplaceableForwardDecl(
1641+
DbgTy.getType(), Scope, MainFile, 0, SizeInBits, AlignInBits, Flags,
1642+
MangledName, MangledName);
16651643

16661644
CanSILFunctionType FunTy;
16671645
TypeBase *BaseTy = DbgTy.getType();
@@ -1720,12 +1698,9 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
17201698
}
17211699
// FIXME: assert that SizeInBits == OffsetInBits.
17221700

1723-
llvm::TempDICompositeType FwdDecl(DBuilder.createReplaceableCompositeType(
1724-
llvm::dwarf::DW_TAG_structure_type, MangledName, Scope, MainFile, 0,
1725-
llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags,
1726-
MangledName));
1727-
1728-
DITypeCache[DbgTy.getType()] = llvm::TrackingMDNodeRef(FwdDecl.get());
1701+
auto FwdDecl = createTemporaryReplaceableForwardDecl(
1702+
DbgTy.getType(), Scope, MainFile, 0, SizeInBits, AlignInBits, Flags,
1703+
MangledName, MangledName);
17291704

17301705
auto DITy = DBuilder.createStructType(
17311706
Scope, MangledName, MainFile, 0, SizeInBits, AlignInBits, Flags,
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %{python} %utils/split_file.py -o %t %s
3+
4+
// RUN: %target-swift-frontend %t/Main.swift -g -target %target-cpu-apple-macos14 -import-bridging-header %t/BridgingHeader.h -enable-experimental-feature Embedded -wmo -emit-ir -o - | %FileCheck %s
5+
6+
// REQUIRES: swift_in_compiler
7+
// REQUIRES: executable_test
8+
// REQUIRES: OS=macosx
9+
// REQUIRES: embedded_stdlib
10+
// REQUIRES: swift_feature_Embedded
11+
12+
// BEGIN BridgingHeader.h
13+
#pragma once
14+
typedef struct S2 S2_t;
15+
typedef struct S1 {
16+
struct S2 *other;
17+
} S1_t;
18+
typedef struct S2 {
19+
S1_t *producer_pool;
20+
} S2_t;
21+
22+
// BEGIN Main.swift
23+
24+
public var v: UnsafeMutablePointer<S1_t>? = nil
25+
26+
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, {{.*}} identifier: "$eSpySo4S1_taGD"
27+
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, {{.*}} identifier: "$eSpySo2S2VGD"

0 commit comments

Comments
 (0)