Skip to content

Commit d4112d9

Browse files
Merge pull request #31118 from adrian-prantl/generic-type-params
Store the type parameters of bound generics in the debug info.
2 parents bb4d076 + 8ef2178 commit d4112d9

File tree

5 files changed

+127
-47
lines changed

5 files changed

+127
-47
lines changed

lib/IRGen/DebugTypeInfo.cpp

Lines changed: 14 additions & 4 deletions
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,8 +52,9 @@ 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,
57-
Info.getBestKnownAlignment(), hasDefaultAlignment(Ty),
57+
Info.getBestKnownAlignment(), ::hasDefaultAlignment(Ty),
5858
false);
5959
}
6060

@@ -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) {
@@ -104,7 +112,7 @@ DebugTypeInfo DebugTypeInfo::getGlobal(SILGlobalVariable *GV,
104112
if (DeclType->isEqual(LowTy))
105113
Type = DeclType.getPointer();
106114
}
107-
DebugTypeInfo DbgTy(Type, StorageTy, size, align, hasDefaultAlignment(Type),
115+
DebugTypeInfo DbgTy(Type, StorageTy, size, align, ::hasDefaultAlignment(Type),
108116
false);
109117
assert(StorageTy && "StorageType is a nullptr");
110118
assert(!DbgTy.isContextArchetype() &&
@@ -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
}
@@ -158,6 +167,7 @@ LLVM_DUMP_METHOD void DebugTypeInfo::dump() const {
158167
if (StorageType) {
159168
llvm::errs() << "StorageType=";
160169
StorageType->dump();
161-
}
170+
} else
171+
llvm::errs() << "forward-declared\n";
162172
}
163173
#endif

lib/IRGen/DebugTypeInfo.h

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ class TypeInfo;
3636
/// This data structure holds everything needed to emit debug info
3737
/// for a type.
3838
class DebugTypeInfo {
39-
public:
4039
/// The type we need to emit may be different from the type
4140
/// mentioned in the Decl, for example, stripped of qualifiers.
4241
TypeBase *Type = nullptr;
@@ -48,7 +47,8 @@ class DebugTypeInfo {
4847
bool DefaultAlignment = true;
4948
bool IsMetadataType = false;
5049

51-
DebugTypeInfo() {}
50+
public:
51+
DebugTypeInfo() = default;
5252
DebugTypeInfo(swift::Type Ty, llvm::Type *StorageTy, Size SizeInBytes,
5353
Alignment AlignInBytes, bool HasDefaultAlignment,
5454
bool IsMetadataType);
@@ -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.
@@ -88,11 +91,24 @@ class DebugTypeInfo {
8891
return false;
8992
}
9093

94+
llvm::Type *getStorageType() const {
95+
assert((StorageType || size.isZero()) &&
96+
"only defined types may have a size");
97+
return StorageType;
98+
}
99+
Size getSize() const { return size; }
100+
void setSize(Size NewSize) { size = NewSize; }
101+
Alignment getAlignment() const { return align; }
91102
bool isNull() const { return Type == nullptr; }
103+
bool isForwardDecl() const { return StorageType == nullptr; }
104+
bool isMetadataType() const { return IsMetadataType; }
105+
bool hasDefaultAlignment() const { return DefaultAlignment; }
106+
92107
bool operator==(DebugTypeInfo T) const;
93108
bool operator!=(DebugTypeInfo T) const;
94-
95-
void dump() const;
109+
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
110+
LLVM_DUMP_METHOD void dump() const;
111+
#endif
96112
};
97113
}
98114
}

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 78 additions & 36 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.
@@ -765,7 +766,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
765766
}
766767

767768
StringRef getMangledName(DebugTypeInfo DbgTy) {
768-
if (DbgTy.IsMetadataType)
769+
if (DbgTy.isMetadataType())
769770
return MetadataTypeDeclCache.find(DbgTy.getDecl()->getName().str())
770771
->getKey();
771772

@@ -829,12 +830,12 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
829830
llvm::DINode::DIFlags Flags) {
830831
unsigned SizeOfByte = CI.getTargetInfo().getCharWidth();
831832
auto *Ty = getOrCreateType(DbgTy);
832-
auto *DITy = DBuilder.createMemberType(Scope, Name, File, 0,
833-
SizeOfByte * DbgTy.size.getValue(),
834-
0, OffsetInBits, Flags, Ty);
833+
auto *DITy = DBuilder.createMemberType(
834+
Scope, Name, File, 0, SizeOfByte * DbgTy.getSize().getValue(), 0,
835+
OffsetInBits, Flags, Ty);
835836
OffsetInBits += getSizeInBits(Ty);
836-
OffsetInBits =
837-
llvm::alignTo(OffsetInBits, SizeOfByte * DbgTy.align.getValue());
837+
OffsetInBits = llvm::alignTo(OffsetInBits,
838+
SizeOfByte * DbgTy.getAlignment().getValue());
838839
return DITy;
839840
}
840841

@@ -929,8 +930,9 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
929930
// one of the raw type as long as it is large enough to hold
930931
// all enum values. Use the raw type for the debug type, but
931932
// the storage size from the enum.
932-
ElemDbgTy = DebugTypeInfo(ED->getRawType(), DbgTy.StorageType,
933-
DbgTy.size, DbgTy.align, true, false);
933+
ElemDbgTy =
934+
DebugTypeInfo(ED->getRawType(), DbgTy.getStorageType(),
935+
DbgTy.getSize(), DbgTy.getAlignment(), true, false);
934936
else if (auto ArgTy = ElemDecl->getArgumentInterfaceType()) {
935937
// A discriminated union. This should really be described as a
936938
// DW_TAG_variant_type. For now only describing the data.
@@ -941,12 +943,13 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
941943
// Discriminated union case without argument. Fallback to Int
942944
// as the element type; there is no storage here.
943945
Type IntTy = IGM.Context.getIntDecl()->getDeclaredType();
944-
ElemDbgTy = DebugTypeInfo(IntTy, DbgTy.StorageType, Size(0),
946+
ElemDbgTy = DebugTypeInfo(IntTy, DbgTy.getStorageType(), Size(0),
945947
Alignment(1), true, false);
946948
}
947949
unsigned Offset = 0;
948-
auto MTy = createMemberType(ElemDbgTy, ElemDecl->getBaseIdentifier().str(),
949-
Offset, Scope, File, Flags);
950+
auto MTy =
951+
createMemberType(ElemDbgTy, ElemDecl->getBaseIdentifier().str(),
952+
Offset, Scope, File, Flags);
950953
Elements.push_back(MTy);
951954
}
952955
return DBuilder.getOrCreateArray(Elements);
@@ -958,7 +961,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
958961
llvm::DIFile *File, unsigned Line,
959962
llvm::DINode::DIFlags Flags) {
960963
unsigned SizeOfByte = CI.getTargetInfo().getCharWidth();
961-
unsigned SizeInBits = DbgTy.size.getValue() * SizeOfByte;
964+
unsigned SizeInBits = DbgTy.getSize().getValue() * SizeOfByte;
962965
// Default, since Swift doesn't allow specifying a custom alignment.
963966
unsigned AlignInBits = 0;
964967

@@ -982,16 +985,17 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
982985
}
983986

984987
llvm::DIType *getOrCreateDesugaredType(Type Ty, DebugTypeInfo DbgTy) {
985-
DebugTypeInfo BlandDbgTy(Ty, DbgTy.StorageType, DbgTy.size, DbgTy.align,
986-
DbgTy.DefaultAlignment, DbgTy.IsMetadataType);
988+
DebugTypeInfo BlandDbgTy(Ty, DbgTy.getStorageType(), DbgTy.getSize(),
989+
DbgTy.getAlignment(), DbgTy.hasDefaultAlignment(),
990+
DbgTy.isMetadataType());
987991
return getOrCreateType(BlandDbgTy);
988992
}
989993

990994
uint64_t getSizeOfBasicType(DebugTypeInfo DbgTy) {
991995
uint64_t SizeOfByte = CI.getTargetInfo().getCharWidth();
992-
uint64_t BitWidth = DbgTy.size.getValue() * SizeOfByte;
993-
llvm::Type *StorageType = DbgTy.StorageType
994-
? DbgTy.StorageType
996+
uint64_t BitWidth = DbgTy.getSize().getValue() * SizeOfByte;
997+
llvm::Type *StorageType = DbgTy.getStorageType()
998+
? DbgTy.getStorageType()
995999
: IGM.DataLayout.getSmallestLegalIntType(
9961000
IGM.getLLVMContext(), BitWidth);
9971001

@@ -1003,23 +1007,44 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
10031007
return BitWidth;
10041008
}
10051009

1010+
/// Collect the type parameters of a bound generic type. This is needed to
1011+
/// anchor any typedefs that may appear in parameters so they can be
1012+
/// resolved in the debugger without needing to query the Swift module.
1013+
llvm::DINodeArray collectGenericParams(BoundGenericType *BGT) {
1014+
SmallVector<llvm::Metadata *, 16> TemplateParams;
1015+
for (auto Param : BGT->getGenericArgs()) {
1016+
TemplateParams.push_back(DBuilder.createTemplateTypeParameter(
1017+
TheCU, "", getOrCreateType(DebugTypeInfo::getForwardDecl(Param))));
1018+
}
1019+
return DBuilder.getOrCreateArray(TemplateParams);
1020+
}
1021+
10061022
/// Create a sized container for a sizeless type. Used to represent
10071023
/// BoundGenericEnums that may have different sizes depending on what they are
10081024
/// bound to, but still share a mangled name.
10091025
llvm::DIType *createOpaqueStructWithSizedContainer(
10101026
llvm::DIScope *Scope, StringRef Name, llvm::DIFile *File, unsigned Line,
10111027
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);
1028+
StringRef MangledName, llvm::DINodeArray BoundParams) {
1029+
// This uses a separate cache and not DIRefMap for the inner type to avoid
1030+
// associating the anonymous container (which is specific to the
1031+
// variable/storage and not the type) with the MangledName.
1032+
llvm::DICompositeType *UniqueType = nullptr;
1033+
auto *UID = llvm::MDString::get(IGM.getLLVMContext(), MangledName);
1034+
if (llvm::Metadata *V = InnerTypeCache.lookup(UID))
1035+
UniqueType = cast<llvm::DICompositeType>(V);
1036+
else {
1037+
UniqueType = DBuilder.createStructType(
1038+
Scope, Name, File, Line, 0, 0, Flags, nullptr, nullptr,
1039+
llvm::dwarf::DW_LANG_Swift, nullptr, MangledName);
1040+
if (BoundParams)
1041+
DBuilder.replaceArrays(UniqueType, nullptr, BoundParams);
1042+
InnerTypeCache[UID] = llvm::TrackingMDNodeRef(UniqueType);
1043+
}
1044+
10191045
llvm::Metadata *Elements[] = {
10201046
DBuilder.createMemberType(Scope, "", File, 0, SizeInBits,
10211047
AlignInBits, 0, Flags, UniqueType)};
1022-
10231048
return DBuilder.createStructType(
10241049
Scope, "", File, Line, SizeInBits, AlignInBits, Flags,
10251050
/* DerivedFrom */ nullptr, DBuilder.getOrCreateArray(Elements),
@@ -1188,9 +1213,10 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
11881213
// emitting the storage size of the struct, but it may be necessary
11891214
// to emit the (target!) size of the underlying basic type.
11901215
uint64_t SizeOfByte = CI.getTargetInfo().getCharWidth();
1191-
uint64_t SizeInBits = DbgTy.size.getValue() * SizeOfByte;
1192-
unsigned AlignInBits =
1193-
DbgTy.DefaultAlignment ? 0 : DbgTy.align.getValue() * SizeOfByte;
1216+
uint64_t SizeInBits = DbgTy.getSize().getValue() * SizeOfByte;
1217+
unsigned AlignInBits = DbgTy.hasDefaultAlignment()
1218+
? 0
1219+
: DbgTy.getAlignment().getValue() * SizeOfByte;
11941220
unsigned Encoding = 0;
11951221
llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
11961222

@@ -1332,7 +1358,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
13321358
auto L = getDebugLoc(*this, Decl);
13331359
return createOpaqueStructWithSizedContainer(
13341360
Scope, Decl ? Decl->getNameStr() : "", File, L.Line, SizeInBits,
1335-
AlignInBits, Flags, MangledName);
1361+
AlignInBits, Flags, MangledName, collectGenericParams(StructTy));
13361362
}
13371363

13381364
case TypeKind::BoundGenericClass: {
@@ -1441,7 +1467,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
14411467
auto *File = getOrCreateFile(L.Filename);
14421468
return createOpaqueStructWithSizedContainer(
14431469
Scope, Decl->getName().str(), File, L.Line, SizeInBits, AlignInBits,
1444-
Flags, MangledName);
1470+
Flags, MangledName, collectGenericParams(EnumTy));
14451471
}
14461472

14471473
case TypeKind::BuiltinVector: {
@@ -1480,9 +1506,9 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
14801506
auto File = getOrCreateFile(L.Filename);
14811507
// For TypeAlias types, the DeclContext for the aliased type is
14821508
// in the decl of the alias type.
1483-
DebugTypeInfo AliasedDbgTy(AliasedTy, DbgTy.StorageType, DbgTy.size,
1484-
DbgTy.align, DbgTy.DefaultAlignment,
1485-
false);
1509+
DebugTypeInfo AliasedDbgTy(AliasedTy, DbgTy.getStorageType(),
1510+
DbgTy.getSize(), DbgTy.getAlignment(),
1511+
DbgTy.hasDefaultAlignment(), false);
14861512
return DBuilder.createTypedef(getOrCreateType(AliasedDbgTy), MangledName,
14871513
File, L.Line, Scope);
14881514
}
@@ -1637,8 +1663,24 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
16371663
if (Decl->isOutermostPrivateOrFilePrivateScope())
16381664
Scope = getFilePrivateScope(Scope, Decl);
16391665

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

1680+
// Don't cache a type alias to a forward declaration either.
1681+
if (DbgTy.isForwardDecl())
1682+
return DITy;
1683+
16421684
// Incrementally build the DIRefMap.
16431685
if (auto *CTy = dyn_cast<llvm::DICompositeType>(DITy)) {
16441686
#ifndef NDEBUG
@@ -2178,11 +2220,11 @@ void IRGenDebugInfoImpl::emitVariableDeclaration(
21782220
return;
21792221

21802222
// We cannot yet represent opened existentials.
2181-
if (DbgTy.Type->hasOpenedExistential())
2223+
if (DbgTy.getType()->hasOpenedExistential())
21822224
return;
21832225

2184-
if (!DbgTy.size)
2185-
DbgTy.size = getStorageSize(IGM.DataLayout, Storage);
2226+
if (!DbgTy.getSize())
2227+
DbgTy.setSize(getStorageSize(IGM.DataLayout, Storage));
21862228

21872229
auto *Scope = dyn_cast_or_null<llvm::DILocalScope>(getOrCreateScope(DS));
21882230
assert(Scope && "variable has no local scope");
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)