Skip to content

Commit 563051c

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 28d1cf9 commit 563051c

File tree

2 files changed

+130
-127
lines changed

2 files changed

+130
-127
lines changed

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 103 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,27 +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)) &&
1105+
assert(swift::Demangle::isMangledName(MangledName) &&
11111106
"UID is not a mangled name");
11121107
#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);
11131113

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

@@ -1123,8 +1126,9 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
11231126
llvm::DINode::DIFlags Flags, llvm::DIType *DerivedFrom,
11241127
unsigned RuntimeLang, StringRef UniqueID) {
11251128
StringRef Name = Decl->getName().str();
1126-
auto FwdDecl = createStructForwardDecl(DbgTy, Decl, Scope, File, Line,
1127-
SizeInBits, Flags, UniqueID, Name);
1129+
auto FwdDecl = createTemporaryReplaceableForwardDecl(
1130+
DbgTy.getType(), Scope, File, Line, SizeInBits, AlignInBits, Flags,
1131+
UniqueID, Name);
11281132
// Collect the members.
11291133
SmallVector<llvm::Metadata *, 16> Elements;
11301134
unsigned OffsetInBits = 0;
@@ -1170,9 +1174,9 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
11701174
unsigned SizeInBits = 0;
11711175
unsigned AlignInBits = 0;
11721176
StringRef Name = Decl->getName().str();
1173-
auto FwdDecl = createStructForwardDecl(DbgTy, Decl, Scope, File, Line,
1174-
SizeInBits, Flags, UniqueID, Name);
1175-
1177+
auto FwdDecl = createTemporaryReplaceableForwardDecl(
1178+
DbgTy.getType(), Scope, File, Line, SizeInBits, AlignInBits, Flags,
1179+
UniqueID, Name);
11761180
// Collect the members.
11771181
SmallVector<llvm::Metadata *, 16> Elements;
11781182
for (VarDecl *VD : Decl->getStoredProperties()) {
@@ -1214,12 +1218,10 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
12141218
return createUnsubstitutedVariantType(DbgTy, Decl, MangledName, Scope,
12151219
File, 0, Flags);
12161220
}
1217-
auto FwdDecl = llvm::TempDIType(DBuilder.createReplaceableCompositeType(
1218-
llvm::dwarf::DW_TAG_structure_type, "", Scope, File, 0,
1219-
llvm::dwarf::DW_LANG_Swift, 0, 0, llvm::DINode::FlagZero, MangledName));
1220-
1221-
auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
1222-
DITypeCache[EnumTy] = TH;
1221+
StringRef Name = Decl->getName().str();
1222+
auto FwdDecl = createTemporaryReplaceableForwardDecl(
1223+
EnumTy, Scope, File, Line, SizeInBits, AlignInBits, Flags, MangledName,
1224+
Name);
12231225
// Force the creation of the unsubstituted type, don't create it
12241226
// directly so it goes through all the caching/verification logic.
12251227
auto unsubstitutedDbgTy = getOrCreateType(DbgTy);
@@ -1230,78 +1232,71 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
12301232
return DIType;
12311233
}
12321234

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

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

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

13291320
auto RawType = Decl->getRawType();
13301321
auto &TI = IGM.getTypeInfoForUnlowered(RawType);
@@ -1372,14 +1363,10 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
13721363

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

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

14471430
SmallVector<llvm::Metadata *, 16> Elements;
14481431
for (auto *ElemDecl : Decl->getAllElements()) {
@@ -1649,13 +1632,9 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
16491632
unsigned SizeInBits, unsigned AlignInBits,
16501633
llvm::DINode::DIFlags Flags,
16511634
StringRef MangledName) {
1652-
llvm::TempDICompositeType FwdDecl(DBuilder.createReplaceableCompositeType(
1653-
llvm::dwarf::DW_TAG_subroutine_type, MangledName, Scope, MainFile, 0,
1654-
llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags,
1655-
MangledName));
1656-
1657-
auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
1658-
DITypeCache[DbgTy.getType()] = TH;
1635+
auto FwdDecl = createTemporaryReplaceableForwardDecl(
1636+
DbgTy.getType(), Scope, MainFile, 0, SizeInBits, AlignInBits, Flags,
1637+
MangledName, MangledName);
16591638

16601639
CanSILFunctionType FunTy;
16611640
TypeBase *BaseTy = DbgTy.getType();
@@ -1714,12 +1693,9 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
17141693
}
17151694
// FIXME: assert that SizeInBits == OffsetInBits.
17161695

1717-
llvm::TempDICompositeType FwdDecl(DBuilder.createReplaceableCompositeType(
1718-
llvm::dwarf::DW_TAG_structure_type, MangledName, Scope, MainFile, 0,
1719-
llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags,
1720-
MangledName));
1721-
1722-
DITypeCache[DbgTy.getType()] = llvm::TrackingMDNodeRef(FwdDecl.get());
1696+
auto FwdDecl = createTemporaryReplaceableForwardDecl(
1697+
DbgTy.getType(), Scope, MainFile, 0, SizeInBits, AlignInBits, Flags,
1698+
MangledName, MangledName);
17231699

17241700
auto DITy = DBuilder.createStructType(
17251701
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)