mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[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
This commit is contained in:
@@ -1092,28 +1092,30 @@ private:
|
||||
return DITy;
|
||||
}
|
||||
|
||||
llvm::TempDIType createStructForwardDecl(
|
||||
DebugTypeInfo DbgTy, NominalTypeDecl *Decl, llvm::DIScope *Scope,
|
||||
llvm::DIFile *File, unsigned Line, unsigned SizeInBits,
|
||||
llvm::DINode::DIFlags Flags, StringRef UniqueID, StringRef Name) {
|
||||
// Forward declare this first because types may be recursive.
|
||||
llvm::TempDICompositeType FwdDecl(DBuilder.createReplaceableCompositeType(
|
||||
llvm::dwarf::DW_TAG_structure_type, Name, Scope, File, Line,
|
||||
llvm::dwarf::DW_LANG_Swift, SizeInBits, 0, Flags, UniqueID));
|
||||
|
||||
/// Creates a temporary replaceable forward decl to protect against recursion.
|
||||
llvm::TempDIType createTemporaryReplaceableForwardDecl(
|
||||
TypeBase *Type, llvm::DIScope *Scope, llvm::DIFile *File, unsigned Line,
|
||||
unsigned SizeInBits, unsigned AlignInBits, llvm::DINode::DIFlags Flags,
|
||||
StringRef MangledName, StringRef Name) {
|
||||
#ifndef NDEBUG
|
||||
if (UniqueID.empty())
|
||||
if (MangledName.empty())
|
||||
assert(!Name.empty() &&
|
||||
"no mangled name and no human readable name given");
|
||||
else
|
||||
assert((UniqueID.starts_with("_T") ||
|
||||
UniqueID.starts_with(MANGLING_PREFIX_STR) ||
|
||||
UniqueID.starts_with(MANGLING_PREFIX_EMBEDDED_STR)) &&
|
||||
assert(swift::Demangle::isMangledName(MangledName) &&
|
||||
"UID is not a mangled name");
|
||||
#endif
|
||||
auto ReplaceableType = DBuilder.createReplaceableCompositeType(
|
||||
llvm::dwarf::DW_TAG_structure_type, "", Scope, File, Line,
|
||||
llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags,
|
||||
MangledName);
|
||||
auto FwdDecl = llvm::TempDIType(ReplaceableType);
|
||||
|
||||
auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
|
||||
DITypeCache[DbgTy.getType()] = TH;
|
||||
DITypeCache[Type] = TH;
|
||||
if (auto UID = ReplaceableType->getRawIdentifier())
|
||||
DIRefMap[UID] = llvm::TrackingMDNodeRef(TH);
|
||||
|
||||
return FwdDecl;
|
||||
}
|
||||
|
||||
@@ -1124,8 +1126,9 @@ private:
|
||||
llvm::DINode::DIFlags Flags, llvm::DIType *DerivedFrom,
|
||||
unsigned RuntimeLang, StringRef UniqueID) {
|
||||
StringRef Name = Decl->getName().str();
|
||||
auto FwdDecl = createStructForwardDecl(DbgTy, Decl, Scope, File, Line,
|
||||
SizeInBits, Flags, UniqueID, Name);
|
||||
auto FwdDecl = createTemporaryReplaceableForwardDecl(
|
||||
DbgTy.getType(), Scope, File, Line, SizeInBits, AlignInBits, Flags,
|
||||
UniqueID, Name);
|
||||
// Collect the members.
|
||||
SmallVector<llvm::Metadata *, 16> Elements;
|
||||
unsigned OffsetInBits = 0;
|
||||
@@ -1171,9 +1174,9 @@ private:
|
||||
unsigned SizeInBits = 0;
|
||||
unsigned AlignInBits = 0;
|
||||
StringRef Name = Decl->getName().str();
|
||||
auto FwdDecl = createStructForwardDecl(DbgTy, Decl, Scope, File, Line,
|
||||
SizeInBits, Flags, UniqueID, Name);
|
||||
|
||||
auto FwdDecl = createTemporaryReplaceableForwardDecl(
|
||||
DbgTy.getType(), Scope, File, Line, SizeInBits, AlignInBits, Flags,
|
||||
UniqueID, Name);
|
||||
// Collect the members.
|
||||
SmallVector<llvm::Metadata *, 16> Elements;
|
||||
for (VarDecl *VD : Decl->getStoredProperties()) {
|
||||
@@ -1215,12 +1218,10 @@ private:
|
||||
return createUnsubstitutedVariantType(DbgTy, Decl, MangledName, Scope,
|
||||
File, 0, Flags);
|
||||
}
|
||||
auto FwdDecl = llvm::TempDIType(DBuilder.createReplaceableCompositeType(
|
||||
llvm::dwarf::DW_TAG_structure_type, "", Scope, File, 0,
|
||||
llvm::dwarf::DW_LANG_Swift, 0, 0, llvm::DINode::FlagZero, MangledName));
|
||||
|
||||
auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
|
||||
DITypeCache[EnumTy] = TH;
|
||||
StringRef Name = Decl->getName().str();
|
||||
auto FwdDecl = createTemporaryReplaceableForwardDecl(
|
||||
EnumTy, Scope, File, Line, SizeInBits, AlignInBits, Flags, MangledName,
|
||||
Name);
|
||||
// Force the creation of the unsubstituted type, don't create it
|
||||
// directly so it goes through all the caching/verification logic.
|
||||
auto unsubstitutedDbgTy = getOrCreateType(DbgTy);
|
||||
@@ -1231,34 +1232,27 @@ private:
|
||||
return DIType;
|
||||
}
|
||||
|
||||
/// Create a DICompositeType from a specialized struct. A specialized type
|
||||
/// is a generic type, or a child type whose parent is generic.
|
||||
llvm::DIType *
|
||||
createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
|
||||
NominalTypeDecl *Decl, llvm::DIScope *Scope,
|
||||
llvm::DIFile *File, unsigned Line,
|
||||
unsigned SizeInBits, unsigned AlignInBits,
|
||||
llvm::DINode::DIFlags Flags,
|
||||
StringRef MangledName,
|
||||
bool IsClass = false) {
|
||||
// To emit debug info of the DwarfTypes level for generic types, the strategy
|
||||
// is to emit a description of all the fields for the type with archetypes,
|
||||
// and still the same debug info as the ASTTypes level for the specialized
|
||||
// type. For example, given:
|
||||
// struct Pair<T, U> {
|
||||
/// Create a DICompositeType from a specialized struct. A specialized type
|
||||
/// is a generic type, or a child type whose parent is generic.
|
||||
llvm::DIType *createSpecializedStructOrClassType(
|
||||
NominalOrBoundGenericNominalType *Type, NominalTypeDecl *Decl,
|
||||
llvm::DIScope *Scope, llvm::DIFile *File, unsigned Line,
|
||||
unsigned SizeInBits, unsigned AlignInBits, llvm::DINode::DIFlags Flags,
|
||||
StringRef MangledName, bool IsClass = false) {
|
||||
// To emit debug info of the DwarfTypes level for generic types, the
|
||||
// strategy is to emit a description of all the fields for the type with
|
||||
// archetypes, and still the same debug info as the ASTTypes level for the
|
||||
// specialized type. For example, given: struct Pair<T, U> {
|
||||
// let t: T
|
||||
// let u: U
|
||||
// }
|
||||
// When emitting debug information for a type such as Pair<Int, Double>,
|
||||
// emit a description of all the fields for Pair<T, U>, and emit the regular
|
||||
// debug information for Pair<Int, Double>.
|
||||
|
||||
auto FwdDecl = llvm::TempDIType(DBuilder.createReplaceableCompositeType(
|
||||
llvm::dwarf::DW_TAG_structure_type, "", Scope, File, Line,
|
||||
llvm::dwarf::DW_LANG_Swift, SizeInBits, 0, Flags, MangledName));
|
||||
|
||||
auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
|
||||
DITypeCache[Type] = TH;
|
||||
StringRef Name = Decl->getName().str();
|
||||
auto FwdDecl = createTemporaryReplaceableForwardDecl(
|
||||
Type, Scope, File, Line, SizeInBits, AlignInBits, Flags, MangledName,
|
||||
Name);
|
||||
|
||||
// Go from Pair<Int, Double> to Pair<T, U>.
|
||||
auto UnsubstitutedTy = Decl->getDeclaredInterfaceType();
|
||||
@@ -1267,8 +1261,8 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
|
||||
auto DbgTy = DebugTypeInfo::getFromTypeInfo(
|
||||
UnsubstitutedTy, IGM.getTypeInfoForUnlowered(UnsubstitutedTy), IGM);
|
||||
Mangle::ASTMangler Mangler(IGM.Context);
|
||||
std::string DeclTypeMangledName =
|
||||
Mangler.mangleTypeForDebugger(UnsubstitutedTy->mapTypeOutOfContext(), {});
|
||||
std::string DeclTypeMangledName = Mangler.mangleTypeForDebugger(
|
||||
UnsubstitutedTy->mapTypeOutOfContext(), {});
|
||||
if (DeclTypeMangledName == MangledName) {
|
||||
return createUnsubstitutedGenericStructOrClassType(
|
||||
DbgTy, Decl, UnsubstitutedTy, Scope, File, Line, Flags, nullptr,
|
||||
@@ -1301,7 +1295,7 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
|
||||
collectGenericParams(Type), UnsubstitutedType);
|
||||
DBuilder.replaceTemporary(std::move(FwdDecl), OpaqueType);
|
||||
return OpaqueType;
|
||||
}
|
||||
}
|
||||
|
||||
/// Create debug information for an enum with a raw type (enum E : Int {}).
|
||||
llvm::DICompositeType *createRawEnumType(CompletedDebugTypeInfo DbgTy,
|
||||
@@ -1319,13 +1313,9 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
|
||||
// Default, since Swift doesn't allow specifying a custom alignment.
|
||||
unsigned AlignInBits = 0;
|
||||
|
||||
llvm::TempDICompositeType FwdDecl(DBuilder.createReplaceableCompositeType(
|
||||
llvm::dwarf::DW_TAG_enumeration_type, MangledName, Scope, File, Line,
|
||||
llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags,
|
||||
MangledName));
|
||||
|
||||
auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
|
||||
DITypeCache[DbgTy.getType()] = TH;
|
||||
auto FwdDecl = createTemporaryReplaceableForwardDecl(
|
||||
DbgTy.getType(), Scope, File, Line, SizeInBits, AlignInBits, Flags,
|
||||
MangledName, Name);
|
||||
|
||||
auto RawType = Decl->getRawType();
|
||||
auto &TI = IGM.getTypeInfoForUnlowered(RawType);
|
||||
@@ -1373,14 +1363,10 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
|
||||
|
||||
// A variant part should actually be a child to a DW_TAG_structure_type
|
||||
// according to the DWARF spec.
|
||||
llvm::TempDICompositeType FwdDecl(DBuilder.createReplaceableCompositeType(
|
||||
llvm::dwarf::DW_TAG_structure_type, MangledName, Scope, File, Line,
|
||||
llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags,
|
||||
MangledName));
|
||||
|
||||
auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
|
||||
DITypeCache[DbgTy.getType()] = TH;
|
||||
|
||||
auto FwdDecl = createTemporaryReplaceableForwardDecl(
|
||||
DbgTy.getType(), Scope, File, Line, SizeInBits, AlignInBits, Flags,
|
||||
MangledName, Name);
|
||||
SmallVector<llvm::Metadata *, 16> Elements;
|
||||
for (auto *ElemDecl : Decl->getAllElements()) {
|
||||
std::optional<CompletedDebugTypeInfo> ElemDbgTy;
|
||||
@@ -1437,13 +1423,9 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
|
||||
unsigned AlignInBits = 0;
|
||||
// A variant part should actually be a child to a DW_TAG_structure_type
|
||||
// according to the DWARF spec.
|
||||
llvm::TempDICompositeType FwdDecl(DBuilder.createReplaceableCompositeType(
|
||||
llvm::dwarf::DW_TAG_structure_type, MangledName, Scope, File, Line,
|
||||
llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags,
|
||||
MangledName));
|
||||
|
||||
auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
|
||||
DITypeCache[DbgTy.getType()] = TH;
|
||||
auto FwdDecl = createTemporaryReplaceableForwardDecl(
|
||||
DbgTy.getType(), Scope, File, Line, SizeInBits, AlignInBits, Flags,
|
||||
MangledName, Name);
|
||||
|
||||
SmallVector<llvm::Metadata *, 16> Elements;
|
||||
for (auto *ElemDecl : Decl->getAllElements()) {
|
||||
@@ -1655,13 +1637,9 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
|
||||
unsigned SizeInBits, unsigned AlignInBits,
|
||||
llvm::DINode::DIFlags Flags,
|
||||
StringRef MangledName) {
|
||||
llvm::TempDICompositeType FwdDecl(DBuilder.createReplaceableCompositeType(
|
||||
llvm::dwarf::DW_TAG_subroutine_type, MangledName, Scope, MainFile, 0,
|
||||
llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags,
|
||||
MangledName));
|
||||
|
||||
auto TH = llvm::TrackingMDNodeRef(FwdDecl.get());
|
||||
DITypeCache[DbgTy.getType()] = TH;
|
||||
auto FwdDecl = createTemporaryReplaceableForwardDecl(
|
||||
DbgTy.getType(), Scope, MainFile, 0, SizeInBits, AlignInBits, Flags,
|
||||
MangledName, MangledName);
|
||||
|
||||
CanSILFunctionType FunTy;
|
||||
TypeBase *BaseTy = DbgTy.getType();
|
||||
@@ -1720,12 +1698,9 @@ createSpecializedStructOrClassType(NominalOrBoundGenericNominalType *Type,
|
||||
}
|
||||
// FIXME: assert that SizeInBits == OffsetInBits.
|
||||
|
||||
llvm::TempDICompositeType FwdDecl(DBuilder.createReplaceableCompositeType(
|
||||
llvm::dwarf::DW_TAG_structure_type, MangledName, Scope, MainFile, 0,
|
||||
llvm::dwarf::DW_LANG_Swift, SizeInBits, AlignInBits, Flags,
|
||||
MangledName));
|
||||
|
||||
DITypeCache[DbgTy.getType()] = llvm::TrackingMDNodeRef(FwdDecl.get());
|
||||
auto FwdDecl = createTemporaryReplaceableForwardDecl(
|
||||
DbgTy.getType(), Scope, MainFile, 0, SizeInBits, AlignInBits, Flags,
|
||||
MangledName, MangledName);
|
||||
|
||||
auto DITy = DBuilder.createStructType(
|
||||
Scope, MangledName, MainFile, 0, SizeInBits, AlignInBits, Flags,
|
||||
|
||||
27
test/DebugInfo/embedded-recur-c-types.swift
Normal file
27
test/DebugInfo/embedded-recur-c-types.swift
Normal file
@@ -0,0 +1,27 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %{python} %utils/split_file.py -o %t %s
|
||||
|
||||
// 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
|
||||
|
||||
// REQUIRES: swift_in_compiler
|
||||
// REQUIRES: executable_test
|
||||
// REQUIRES: OS=macosx
|
||||
// REQUIRES: embedded_stdlib
|
||||
// REQUIRES: swift_feature_Embedded
|
||||
|
||||
// BEGIN BridgingHeader.h
|
||||
#pragma once
|
||||
typedef struct S2 S2_t;
|
||||
typedef struct S1 {
|
||||
struct S2 *other;
|
||||
} S1_t;
|
||||
typedef struct S2 {
|
||||
S1_t *producer_pool;
|
||||
} S2_t;
|
||||
|
||||
// BEGIN Main.swift
|
||||
|
||||
public var v: UnsafeMutablePointer<S1_t>? = nil
|
||||
|
||||
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, {{.*}} identifier: "$eSpySo4S1_taGD"
|
||||
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, {{.*}} identifier: "$eSpySo2S2VGD"
|
||||
Reference in New Issue
Block a user