Skip to content

Commit 851470f

Browse files
committed
[Debug Info] Do not emit children of bound generic types
This reverts the problematic parts of fcbebc5 which had caused a lot of unintended fallout, while preserving the actual feature supported by the patch. Before that patch (fcbeb), and after this one, we don't emit members of specialized bound generic types, because these can be reconstructed by substituting the "template parameters" in the unspecialized type. This patch carves out an exception for inline arrays, because DWARF has special support for arrays, which allows debuggers to reason about them without needing special support. rdar://146326633
1 parent 26eaf75 commit 851470f

File tree

5 files changed

+42
-28
lines changed

5 files changed

+42
-28
lines changed

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,8 +1226,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
12261226
return DITy;
12271227
}
12281228

1229-
std::pair<bool, Type>
1230-
getUnsubstituedType(Type Ty, StringRef MangledName) {
1229+
std::pair<bool, Type> getUnsubstitutedType(Type Ty, StringRef MangledName) {
12311230
if (!Ty)
12321231
return {false,{}};
12331232
// Go from Pair<Int, Double> to Pair<T, U>.
@@ -1252,7 +1251,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
12521251
llvm::DIScope *Scope, llvm::DIFile *File,
12531252
unsigned Line, llvm::DINode::DIFlags Flags) {
12541253
auto [IsUnsubstituted, UnsubstitutedTy] =
1255-
getUnsubstituedType(EnumTy, MangledName);
1254+
getUnsubstitutedType(EnumTy, MangledName);
12561255
auto UnsubstitutedDbgTy = DebugTypeInfo::getFromTypeInfo(
12571256
UnsubstitutedTy, IGM.getTypeInfoForUnlowered(UnsubstitutedTy), IGM);
12581257
if (IsUnsubstituted)
@@ -1301,7 +1300,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
13011300
Name);
13021301

13031302
auto [IsUnsubstitued, UnsubstitutedType] =
1304-
getUnsubstituedType(Type, MangledName);
1303+
getUnsubstitutedType(Type, MangledName);
13051304
auto UnsubstitutedDbgTy = DebugTypeInfo::getFromTypeInfo(
13061305
UnsubstitutedType, IGM.getTypeInfoForUnlowered(UnsubstitutedType), IGM);
13071306
if (IsUnsubstitued)
@@ -1326,19 +1325,24 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
13261325
}
13271326
}
13281327

1329-
// Recursive types such as `class A<B> { let a : A<A<B>> }` would produce an
1330-
// infinite chain of expansions for the type of `a`. Break these cycles by
1331-
// emitting any bound generics that still have type parameters as forward
1332-
// declarations.
1333-
if (Type->hasTypeParameter() || Type->hasPrimaryArchetype())
1334-
return createOpaqueStructWithSizedContainer(
1335-
Scope, Decl ? Decl->getNameStr() : "", File, Line, SizeInBits,
1336-
AlignInBits, Flags, MangledName, collectGenericParams(Type, true),
1337-
UnsubstitutedDITy);
1328+
// Generally, we don't emit members of a specialized bound generic, because
1329+
// these can be reconstructed by substituting the "template parameters" in
1330+
// the unspecialized type. We make an exception for inline arrays, because
1331+
// DWARF has special support for arrays.
1332+
if (Type->isInlineArray() && !Type->hasTypeParameter() &&
1333+
!Type->hasPrimaryArchetype())
1334+
// Create the substituted type.
1335+
return createStructType(Type, Decl, Scope, File, Line, SizeInBits,
1336+
AlignInBits, Flags, MangledName,
1337+
UnsubstitutedDITy);
13381338

1339-
// Create the substituted type.
1340-
return createStructType(Type, Decl, Scope, File, Line, SizeInBits,
1341-
AlignInBits, Flags, MangledName, UnsubstitutedDITy);
1339+
// Create the substituted type (without members).
1340+
llvm::DIType *SpecializedDITy = createOpaqueStructWithSizedContainer(
1341+
Scope, Decl ? Decl->getNameStr() : "", File, Line, SizeInBits,
1342+
AlignInBits, Flags, MangledName, collectGenericParams(Type),
1343+
UnsubstitutedDITy);
1344+
DBuilder.replaceTemporary(std::move(FwdDecl), SpecializedDITy);
1345+
return SpecializedDITy;
13421346
}
13431347

13441348
/// Create debug information for an enum with a raw type (enum E : Int {}).
@@ -1600,6 +1604,10 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
16001604

16011605
llvm::Metadata *Elements[] = {DBuilder.createMemberType(
16021606
Scope, "", File, 0, SizeInBits, AlignInBits, 0, Flags, UniqueType)};
1607+
// FIXME: It's a limitation of LLVM that a forward declaration cannot have a
1608+
// specificationOf, so this attritbute is put on the sized container type
1609+
// instead. This is confusing consumers, and LLDB has to go out of its way
1610+
// to parse these confusing types as intended.
16031611
return DBuilder.createStructType(
16041612
Scope, "", File, Line, SizeInBits, AlignInBits, Flags,
16051613
/* DerivedFrom */ nullptr, DBuilder.getOrCreateArray(Elements),
@@ -2338,7 +2346,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
23382346
if (!isa<llvm::DICompositeType>(CachedType))
23392347
return true;
23402348
bool IsUnsubstituted =
2341-
getUnsubstituedType(DbgTy.getType(), getMangledName(DbgTy).Canonical)
2349+
getUnsubstitutedType(DbgTy.getType(), getMangledName(DbgTy).Canonical)
23422350
.first;
23432351
std::optional<uint64_t> SizeInBits;
23442352
if (!IsUnsubstituted)

test/DebugInfo/BoundGenericStruct.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public let s = S<Int>(t: 0)
1212
// CHECK: ![[INTPARAM]] = !DITemplateTypeParameter(type: ![[INT:[0-9]+]])
1313
// CHECK: ![[INT]] = !DICompositeType(tag: DW_TAG_structure_type, {{.*}}"$sSiD"
1414

15-
// DWARF-DAG: !DICompositeType(tag: DW_TAG_structure_type, {{.*}}templateParams: ![[PARAMS:[0-9]+]]{{.*}}identifier: "$s18BoundGenericStruct1SVySiGD"{{.*}}specification:
15+
// DWARF-DAG: !DICompositeType(tag: DW_TAG_structure_type, {{.*}}name: "$s18BoundGenericStruct1SVySiGD"{{.*}}templateParams: ![[PARAMS:[0-9]+]]
1616

1717
// DWARF-DAG: ![[PARAMS]] = !{![[INTPARAM:[0-9]+]]}
1818
// DWARF-DAG: ![[INTPARAM]] = !DITemplateTypeParameter(type: ![[INT:[0-9]+]])
@@ -34,14 +34,16 @@ public let inner = S2<Double>.Inner(t:4.2)
3434
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "$s18BoundGenericStruct2S2VyxGD",
3535
// CHECK-SAME: flags: DIFlagFwdDecl, runtimeLang: DW_LANG_Swift)
3636

37-
// DWARF-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "Inner", scope: ![[SCOPE1:[0-9]+]],{{.*}} size: 64, elements: ![[ELEMENTS1:[0-9]+]], {{.*}}templateParams: ![[PARAMS2:[0-9]+]], identifier: "$s18BoundGenericStruct2S2V5InnerVySd_GD", specification: ![[SPECIFICATION:[0-9]+]])
37+
// DWARF-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "$s18BoundGenericStruct2S2V5InnerVySd_GD", scope: ![[SCOPE1:[0-9]+]], {{.*}}flags: DIFlagFwdDecl, runtimeLang: DW_LANG_Swift, templateParams: ![[PARAMS2:[0-9]+]])
38+
3839
// DWARF-DAG: ![[SCOPE1]] = !DICompositeType(tag: DW_TAG_structure_type, name: "$s18BoundGenericStruct2S2VyxGD",
3940

4041
// DWARF-DAG: ![[PARAMS2]] = !{![[PARAMS3:[0-9]+]]}
4142
// DWARF-DAG: ![[PARAMS3]] = !DITemplateTypeParameter(type: ![[PARAMS4:[0-9]+]])
4243
// DWARF-DAG: ![[PARAMS4]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Double"{{.*}} size: 64, {{.*}}runtimeLang: DW_LANG_Swift,{{.*}} identifier: "$sSdD")
4344

44-
// DWARF-DAG: [[SPECIFICATION]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Inner", {{.*}}runtimeLang: DW_LANG_Swift, identifier: "$s18BoundGenericStruct2S2V5InnerVyx_GD")
45+
// DWARF-DAG: ![[SPECIFICATION:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Inner", {{.*}}elements: ![[ELEMENTS1:[0-9]+]], runtimeLang: DW_LANG_Swift, identifier: "$s18BoundGenericStruct2S2V5InnerVyx_GD")
46+
// DWARF-DAG: !DICompositeType(tag: DW_TAG_structure_type, {{.*}}line: 26, size: 64, {{.*}}specification: ![[SPECIFICATION]]
4547

4648
// DWARF-DAG: ![[ELEMENTS1]] = !{![[ELEMENTS2:[0-9]+]]}
4749

test/DebugInfo/embedded-recur-c-types.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ typedef struct S2 {
2323

2424
public var v: UnsafeMutablePointer<S1_t>? = nil
2525

26-
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, {{.*}} identifier: "$eSpySo4S1_taGD"
27-
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, {{.*}} identifier: "$eSpySo2S2VGD"
26+
// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, {{.*}}name: "$eSpySo4S1_taGD"
27+
// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, {{.*}}name: "$eSpySo2S2VGD"

test/DebugInfo/typealias-recursive.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ struct Traits32: TraitsProtocol {
1616
let v : MyClass<Traits32>? = nil
1717

1818

19-
// This typedef is not necessary from a semantic point of view, but the result
20-
// of a trade-off done to preserve type sugar (= not generally canonicalizing types).
21-
// CHECK-DAG: !DIDerivedType(tag: DW_TAG_typedef, name: "$s4main7MyClassCyAC6TraitsayAA8Traits32V_GGSgD", {{.*}}baseType: ![[CANONICAL:[0-9]+]])
22-
// CHECK-DAG: ![[CANONICAL]] = !DICompositeType(tag: DW_TAG_structure_type, {{.*}}identifier: "$s4main7MyClassCyAA8Traits32VGSgD", specification: ![[OPTIONAL:[0-9]+]])
19+
// CHECK-DAG: ![[CANONICAL:.*]] = !DICompositeType(tag: DW_TAG_structure_type, {{.*}}identifier: "$s4main7MyClassCyAA8Traits32VGSgD", specification: ![[OPTIONAL:[0-9]+]])
2320

2421
// CHECK-DAG: ![[OPTIONAL]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Optional"
2522

26-
// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "MyClass", {{.*}}templateParams: ![[PARAMS:[0-9]+]], identifier: "$s4main7MyClassCyAA8Traits32VGD", specification: ![[SPEC:[0-9]+]])
23+
// CHECK-DAG: ![[CONTAINER:.*]] = !DICompositeType(tag: DW_TAG_structure_type, {{.*}}line: 7, {{.*}}elements: ![[ELTS:[0-9]+]], runtimeLang: DW_LANG_Swift, specification: ![[SPEC:[0-9]+]])
24+
// CHECK-DAG: ![[ELTS]] = !{![[MEMBER:[0-9]+]]}
25+
// CHECK-DAG: ![[MEMBER]] = !DIDerivedType(tag: DW_TAG_member, {{.*}}baseType: ![[UNSIZED:[0-9]+]]
26+
// CHECK-DAG: ![[UNSIZED]] = !DICompositeType(tag: DW_TAG_structure_type, name: "$s4main7MyClassCyAA8Traits32VGD", {{.*}}flags: DIFlagFwdDecl, runtimeLang: DW_LANG_Swift, templateParams: ![[PARAMS:[0-9]+]])
2727
// CHECK-DAG: ![[PARAMS]] = !{![[PARAM:[0-9]+]]}
2828
// CHECK-DAG: ![[PARAM]] = !DITemplateTypeParameter(type: ![[TRAITS32:[0-9]+]])
2929
// CHECK-DAG: ![[TRAITS32]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Traits32"

test/DebugInfo/typealias_indirect.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@
55
// we cannot preserve that LocalAlias = Bool.
66

77
// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "$s1a10ClassAliasaD"{{.*}}baseType: ![[LOCAL_BOOLTY:[0-9]+]]
8-
// CHECK: ![[LOCAL_BOOLTY]] = !DICompositeType(tag: DW_TAG_structure_type, name: "MyClass", {{.*}}identifier: "$s1a7MyClassCyAA10LocalAliasaSbGD"
8+
// CHECK: ![[LOCAL_BOOLTY]] = !DICompositeType(tag: DW_TAG_structure_type, {{.*}}elements: ![[ELTS:[0-9]+]], runtimeLang: DW_LANG_Swift, specification: ![[SPEC:[0-9]+]])
9+
// CHECK-DAG: ![[ELTS]] = !{![[MEMBER:[0-9]+]]}
10+
// CHECK-DAG: ![[MEMBER]] = !DIDerivedType(tag: DW_TAG_member, {{.*}}baseType: ![[UNSIZED:[0-9]+]]
11+
// CHECK-DAG: ![[UNSIZED]] = !DICompositeType(tag: DW_TAG_structure_type, name: "$s1a7MyClassCyAA10LocalAliasaSbGD"
12+
// CHECK-DAG: ![[SPEC]] = !DICompositeType(tag: DW_TAG_structure_type, name: "MyClass"{{.*}}identifier: "$s1a7MyClassCyxq_GD")
913

1014
// FIXME: !DIDerivedType(tag: DW_TAG_typedef, name: "$s1a10LocalAliasaD", {{.*}}baseType: ![[BASETY:[0-9]+]]
1115
// FIXME: ![[BASETY]]{{.*}}$sSbD

0 commit comments

Comments
 (0)