Skip to content

Commit 3bc9d43

Browse files
committed
Store the type parameters of bound generics in the debug info.
This is needed to anchor any typedefs that appear in bound generic parameters so they can be resolved in the typeref-based part of the debugger without needing to query the Swift module.
1 parent f5fa89b commit 3bc9d43

File tree

5 files changed

+77
-14
lines changed

5 files changed

+77
-14
lines changed

lib/IRGen/DebugTypeInfo.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ DebugTypeInfo::DebugTypeInfo(swift::Type Ty, llvm::Type *StorageTy, Size size,
2929
bool IsMetadata)
3030
: Type(Ty.getPointer()), StorageType(StorageTy), size(size), align(align),
3131
DefaultAlignment(HasDefaultAlignment), IsMetadataType(IsMetadata) {
32-
assert(StorageType && "StorageType is a nullptr");
3332
assert(align.getValue() != 0);
3433
}
3534

@@ -53,6 +52,7 @@ DebugTypeInfo DebugTypeInfo::getFromTypeInfo(swift::Type Ty,
5352
// encounter one.
5453
size = Size(0);
5554
}
55+
assert(Info.getStorageType() && "StorageType is a nullptr");
5656
return DebugTypeInfo(Ty.getPointer(), Info.getStorageType(), size,
5757
Info.getBestKnownAlignment(), hasDefaultAlignment(Ty),
5858
false);
@@ -80,6 +80,7 @@ DebugTypeInfo DebugTypeInfo::getMetadata(swift::Type Ty, llvm::Type *StorageTy,
8080
Size size, Alignment align) {
8181
DebugTypeInfo DbgTy(Ty.getPointer(), StorageTy, size,
8282
align, true, false);
83+
assert(StorageTy && "StorageType is a nullptr");
8384
assert(!DbgTy.isContextArchetype() && "type metadata cannot contain an archetype");
8485
return DbgTy;
8586
}
@@ -88,10 +89,17 @@ DebugTypeInfo DebugTypeInfo::getArchetype(swift::Type Ty, llvm::Type *StorageTy,
8889
Size size, Alignment align) {
8990
DebugTypeInfo DbgTy(Ty.getPointer(), StorageTy, size,
9091
align, true, true);
92+
assert(StorageTy && "StorageType is a nullptr");
9193
assert(!DbgTy.isContextArchetype() && "type metadata cannot contain an archetype");
9294
return DbgTy;
9395
}
9496

97+
DebugTypeInfo DebugTypeInfo::getForwardDecl(swift::Type Ty) {
98+
DebugTypeInfo DbgTy(Ty.getPointer(), nullptr, {}, Alignment(1), true,
99+
false);
100+
return DbgTy;
101+
}
102+
95103
DebugTypeInfo DebugTypeInfo::getGlobal(SILGlobalVariable *GV,
96104
llvm::Type *StorageTy, Size size,
97105
Alignment align) {
@@ -118,6 +126,7 @@ DebugTypeInfo DebugTypeInfo::getObjCClass(ClassDecl *theClass,
118126
Alignment align) {
119127
DebugTypeInfo DbgTy(theClass->getInterfaceType().getPointer(), StorageType,
120128
size, align, true, false);
129+
assert(StorageType && "StorageType is a nullptr");
121130
assert(!DbgTy.isContextArchetype() && "type of objc class cannot be an archetype");
122131
return DbgTy;
123132
}

lib/IRGen/DebugTypeInfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ class DebugTypeInfo {
6363
static DebugTypeInfo getArchetype(swift::Type Ty, llvm::Type *StorageTy,
6464
Size size, Alignment align);
6565

66+
/// Create a forward declaration for a type whose size is unknown.
67+
static DebugTypeInfo getForwardDecl(swift::Type Ty);
68+
6669
/// Create a standalone type from a TypeInfo object.
6770
static DebugTypeInfo getFromTypeInfo(swift::Type Ty, const TypeInfo &Info);
6871
/// Global variables.
@@ -89,6 +92,7 @@ class DebugTypeInfo {
8992
}
9093

9194
bool isNull() const { return Type == nullptr; }
95+
bool isForwardDecl() const { return StorageType == nullptr; }
9296
bool operator==(DebugTypeInfo T) const;
9397
bool operator!=(DebugTypeInfo T) const;
9498

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
9292
llvm::DenseMap<const void *, llvm::TrackingMDNodeRef> DIModuleCache;
9393
llvm::StringMap<llvm::TrackingMDNodeRef> DIFileCache;
9494
TrackingDIRefMap DIRefMap;
95+
TrackingDIRefMap InnerTypeCache;
9596
/// @}
9697

9798
/// A list of replaceable fwddecls that need to be RAUWed at the end.
@@ -1003,23 +1004,44 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
10031004
return BitWidth;
10041005
}
10051006

1007+
/// Collect the type parameters of a bound generic type. This is needed to
1008+
/// anchor any typedefs that may appear in parameters so they can be
1009+
/// resolved in the debugger without needing to query the Swift module.
1010+
llvm::DINodeArray collectGenericParams(BoundGenericType *BGT) {
1011+
SmallVector<llvm::Metadata *, 16> TemplateParams;
1012+
for (auto Param : BGT->getGenericArgs()) {
1013+
TemplateParams.push_back(DBuilder.createTemplateTypeParameter(
1014+
TheCU, "", getOrCreateType(DebugTypeInfo::getForwardDecl(Param))));
1015+
}
1016+
return DBuilder.getOrCreateArray(TemplateParams);
1017+
}
1018+
10061019
/// Create a sized container for a sizeless type. Used to represent
10071020
/// BoundGenericEnums that may have different sizes depending on what they are
10081021
/// bound to, but still share a mangled name.
10091022
llvm::DIType *createOpaqueStructWithSizedContainer(
10101023
llvm::DIScope *Scope, StringRef Name, llvm::DIFile *File, unsigned Line,
10111024
unsigned SizeInBits, unsigned AlignInBits, llvm::DINode::DIFlags Flags,
1012-
StringRef MangledName) {
1013-
// Let the MDNode folding set do the work of uniquing the inner type. This
1014-
// should be cheap.
1015-
llvm::DICompositeType *UniqueType = DBuilder.createStructType(
1016-
Scope, Name, File, Line, 0, 0, Flags, nullptr,
1017-
DBuilder.getOrCreateArray(ArrayRef<llvm::Metadata *>()),
1018-
llvm::dwarf::DW_LANG_Swift, nullptr, MangledName);
1025+
StringRef MangledName, llvm::DINodeArray BoundParams) {
1026+
// This uses a separate cache and not DIRefMap for the inner type to avoid
1027+
// associating the anonymous container (which is specific to the
1028+
// variable/storage and not the type) with the MangledName.
1029+
llvm::DICompositeType *UniqueType = nullptr;
1030+
auto *UID = llvm::MDString::get(IGM.getLLVMContext(), MangledName);
1031+
if (llvm::Metadata *V = InnerTypeCache.lookup(UID))
1032+
UniqueType = cast<llvm::DICompositeType>(V);
1033+
else {
1034+
UniqueType = DBuilder.createStructType(
1035+
Scope, Name, File, Line, 0, 0, Flags, nullptr, nullptr,
1036+
llvm::dwarf::DW_LANG_Swift, nullptr, MangledName);
1037+
if (BoundParams)
1038+
DBuilder.replaceArrays(UniqueType, nullptr, BoundParams);
1039+
InnerTypeCache[UID] = llvm::TrackingMDNodeRef(UniqueType);
1040+
}
1041+
10191042
llvm::Metadata *Elements[] = {
10201043
DBuilder.createMemberType(Scope, "", File, 0, SizeInBits,
10211044
AlignInBits, 0, Flags, UniqueType)};
1022-
10231045
return DBuilder.createStructType(
10241046
Scope, "", File, Line, SizeInBits, AlignInBits, Flags,
10251047
/* DerivedFrom */ nullptr, DBuilder.getOrCreateArray(Elements),
@@ -1332,7 +1354,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
13321354
auto L = getDebugLoc(*this, Decl);
13331355
return createOpaqueStructWithSizedContainer(
13341356
Scope, Decl ? Decl->getNameStr() : "", File, L.Line, SizeInBits,
1335-
AlignInBits, Flags, MangledName);
1357+
AlignInBits, Flags, MangledName, collectGenericParams(StructTy));
13361358
}
13371359

13381360
case TypeKind::BoundGenericClass: {
@@ -1441,7 +1463,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
14411463
auto *File = getOrCreateFile(L.Filename);
14421464
return createOpaqueStructWithSizedContainer(
14431465
Scope, Decl->getName().str(), File, L.Line, SizeInBits, AlignInBits,
1444-
Flags, MangledName);
1466+
Flags, MangledName, collectGenericParams(EnumTy));
14451467
}
14461468

14471469
case TypeKind::BuiltinVector: {
@@ -1637,8 +1659,24 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
16371659
if (Decl->isOutermostPrivateOrFilePrivateScope())
16381660
Scope = getFilePrivateScope(Scope, Decl);
16391661

1662+
// If this is a forward decl, create one for this mangled name and don't
1663+
// cache it.
1664+
if (DbgTy.isForwardDecl() && !isa<TypeAliasType>(DbgTy.getType())) {
1665+
auto *FwdDecl = DBuilder.createReplaceableCompositeType(
1666+
llvm::dwarf::DW_TAG_structure_type, MangledName, Scope, 0, 0,
1667+
llvm::dwarf::DW_LANG_Swift, 0, 0, llvm::DINode::FlagFwdDecl,
1668+
MangledName);
1669+
ReplaceMap.emplace_back(
1670+
std::piecewise_construct, std::make_tuple(DbgTy.getType()),
1671+
std::make_tuple(static_cast<llvm::Metadata *>(FwdDecl)));
1672+
return FwdDecl;
1673+
}
16401674
llvm::DIType *DITy = createType(DbgTy, MangledName, Scope, getFile(Scope));
16411675

1676+
// Don't cache a type alias to a forward declaration either.
1677+
if (DbgTy.isForwardDecl())
1678+
return DITy;
1679+
16421680
// Incrementally build the DIRefMap.
16431681
if (auto *CTy = dyn_cast<llvm::DICompositeType>(DITy)) {
16441682
#ifndef NDEBUG
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %target-swift-frontend %s -O -emit-ir -g -o - | %FileCheck %s
2+
public struct S<T> {
3+
let t : T
4+
}
5+
6+
public let s = S<Int>(t: 0)
7+
8+
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "S",
9+
// CHECK-SAME: templateParams: ![[PARAMS:[0-9]+]], identifier:
10+
// CHECK: ![[PARAMS]] = !{![[INTPARAM:[0-9]+]]}
11+
// CHECK: ![[INTPARAM]] = !DITemplateTypeParameter(type: ![[INT:[0-9]+]])
12+
// CHECK: ![[INT]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Int",

test/DebugInfo/enum.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public enum Nothing { }
5959
public func foo(_ empty : Nothing) { }
6060
// CHECK: !DICompositeType({{.*}}name: "Nothing", {{.*}}elements: ![[EMPTY]]
6161

62-
// CHECK: !DICompositeType({{.*}}name: "Rose", {{.*}}elements: ![[ELTS:[0-9]+]],
62+
// CHECK: !DICompositeType({{.*}}name: "Rose",
6363
// CHECK-SAME: {{.*}}identifier: "$s4enum4RoseOyxG{{z?}}D")
6464
enum Rose<A> {
6565
case MkRose(() -> A, () -> [Rose<A>])
@@ -69,8 +69,8 @@ enum Rose<A> {
6969

7070
func foo<T>(_ x : Rose<T>) -> Rose<T> { return x }
7171

72-
// CHECK: !DICompositeType({{.*}}name: "Tuple", {{.*}}elements: ![[ELTS:[0-9]+]], {{.*}}identifier: "$s4enum5TupleOyxGD")
73-
// DWARF: !DICompositeType({{.*}}name: "Tuple", {{.*}}elements: ![[ELTS:[0-9]+]],
72+
// CHECK: !DICompositeType({{.*}}name: "Tuple", {{.*}}identifier: "$s4enum5TupleOyxGD")
73+
// DWARF: !DICompositeType({{.*}}name: "Tuple",
7474
// DWARF-SAME: {{.*}}identifier: "$s4enum5TupleOyxG{{z?}}D")
7575
public enum Tuple<P> {
7676
case C(P, () -> Tuple)

0 commit comments

Comments
 (0)