Skip to content

Commit fcbebc5

Browse files
committed
[Debug Info] Emit -gdwarf-types debug info for Builtin.FixedArray<>
This commit also changes how specialized types are being emitted. Previously we would not emitthe detailed member information in the specialized type itself, and instead rely on the fact that it was present in the unspecialized type, however, this wold prevent us from emitting any bound generic members, so we're now emitting the members in both variants of the type. This uncovered a with type aliases that this commit also addresses: Because we don't canonicalize types prior to caching in order to preserve type sugar, alternative representations of recursive types (with one or more levels of recursion unfolded) could create potential infinite chains of types. This is addressed by checking whether a sugared type has an already emitted canonical representation first, and if yes, creating a typedef node pointing directly to it. The donwside of doing this is that it can lead to the disappearnce of type aliases definitions when they are used as parameters in bound generic types. However, we still preserve that a type was `MyClass<MyAlias>`. We just might have a typedef pointing director from `MyClass<MyAlias>` -> `MyClass<CanonicalType>`. rdar://144315592
1 parent b455e60 commit fcbebc5

10 files changed

+266
-114
lines changed

lib/IRGen/DebugTypeInfo.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,8 @@ LLVM_DUMP_METHOD void DebugTypeInfo::dump() const {
191191
std::optional<CompletedDebugTypeInfo>
192192
CompletedDebugTypeInfo::getFromTypeInfo(swift::Type Ty, const TypeInfo &Info,
193193
IRGenModule &IGM) {
194+
if (!Ty || Ty->hasTypeParameter())
195+
return {};
194196
auto *StorageType = IGM.getStorageTypeForUnlowered(Ty);
195197
std::optional<uint64_t> SizeInBits;
196198
if (StorageType->isSized())

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 161 additions & 85 deletions
Large diffs are not rendered by default.

test/DebugInfo/BoundGenericStruct.swift

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

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

20-
// DWARF: ![[PARAMS]] = !{![[INTPARAM:[0-9]+]]}
21-
// DWARF: ![[INTPARAM]] = !DITemplateTypeParameter(type: ![[INT:[0-9]+]])
22-
// DWARF: ![[INT]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Int", {{.*}}identifier: "$sSiD"
17+
// DWARF-DAG: ![[PARAMS]] = !{![[INTPARAM:[0-9]+]]}
18+
// DWARF-DAG: ![[INTPARAM]] = !DITemplateTypeParameter(type: ![[INT:[0-9]+]])
19+
// DWARF-DAG: ![[INT]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Int", {{.*}}identifier: "$sSiD"
2320

24-
// DWARF: !DICompositeType(tag: DW_TAG_structure_type, name: "S",
25-
// DWARF-SAME: identifier: "$s18BoundGenericStruct1SVyxGD")
26-
// DWARF: !DIDerivedType(tag: DW_TAG_member, name: "t"
27-
// DWARF: ![[GENERIC_PARAM_TYPE:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "$sxD"
21+
// DWARF-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "S", {{.*}}identifier: "$s18BoundGenericStruct1SVyxGD")
22+
// DWARF-DAG: !DIDerivedType(tag: DW_TAG_member, name: "t"
2823

2924

3025
public struct S2<T> {
@@ -39,17 +34,15 @@ public let inner = S2<Double>.Inner(t:4.2)
3934
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "$s18BoundGenericStruct2S2VyxGD",
4035
// CHECK-SAME: flags: DIFlagFwdDecl, runtimeLang: DW_LANG_Swift)
4136

42-
// DWARF: !DICompositeType(tag: DW_TAG_structure_type, name: "Inner", scope: ![[SCOPE1:[0-9]+]],{{.*}} size: 64, {{.*}}, templateParams: ![[PARAMS2:[0-9]+]], identifier: "$s18BoundGenericStruct2S2V5InnerVySd_GD",{{.*}} specification: ![[SPECIFICATION:[0-9]+]]
43-
// DWARF: ![[SCOPE1]] = !DICompositeType(tag: DW_TAG_structure_type, name: "$s18BoundGenericStruct2S2VyxGD",
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]+]])
38+
// DWARF-DAG: ![[SCOPE1]] = !DICompositeType(tag: DW_TAG_structure_type, name: "$s18BoundGenericStruct2S2VyxGD",
4439

45-
// DWARF: ![[PARAMS2]] = !{![[PARAMS3:[0-9]+]]}
46-
// DWARF: ![[PARAMS3]] = !DITemplateTypeParameter(type: ![[PARAMS4:[0-9]+]])
47-
// DWARF: ![[PARAMS4]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Double",
48-
// DWARF-SAME: size: 64, {{.*}}runtimeLang: DW_LANG_Swift, identifier: "$sSdD")
40+
// DWARF-DAG: ![[PARAMS2]] = !{![[PARAMS3:[0-9]+]]}
41+
// DWARF-DAG: ![[PARAMS3]] = !DITemplateTypeParameter(type: ![[PARAMS4:[0-9]+]])
42+
// DWARF-DAG: ![[PARAMS4]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Double"{{.*}} size: 64, {{.*}}runtimeLang: DW_LANG_Swift,{{.*}} identifier: "$sSdD")
4943

50-
// DWARF: [[SPECIFICATION]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Inner",
51-
// DWARF-SAME: elements: ![[ELEMENTS1:[0-9]+]], runtimeLang: DW_LANG_Swift, identifier: "$s18BoundGenericStruct2S2V5InnerVyx_GD")
44+
// DWARF-DAG: [[SPECIFICATION]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Inner", {{.*}}runtimeLang: DW_LANG_Swift, identifier: "$s18BoundGenericStruct2S2V5InnerVyx_GD")
5245

53-
// DWARF: ![[ELEMENTS1]] = !{![[ELEMENTS2:[0-9]+]]}
46+
// DWARF-DAG: ![[ELEMENTS1]] = !{![[ELEMENTS2:[0-9]+]]}
5447

55-
// DWARF: ![[ELEMENTS2]] = !DIDerivedType(tag: DW_TAG_member, name: "t", {{.*}}, baseType: ![[GENERIC_PARAM_TYPE]])
48+
// DWARF-DAG: ![[ELEMENTS2]] = !DIDerivedType(tag: DW_TAG_member, name: "t"

test/DebugInfo/classes.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class SomeClass {
77

88
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "SomeClass",
99
// CHECK-SAME: size: {{64|32}}, elements:
10-
// CHECK-SAME: runtimeLang: DW_LANG_Swift, identifier: "$s7classes9SomeClassCD")
10+
// CHECK-SAME: runtimeLang: DW_LANG_Swift,{{.*}} identifier: "$s7classes9SomeClassCD")
1111

1212
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "first",
1313
// CHECK-SAME: size: {{64|32}})

test/DebugInfo/enum.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ enum Either {
2525
// DWARF: DIDerivedType(tag: DW_TAG_member, name: "Neither",
2626
// DWARF-SAME: baseType: null)
2727
}
28-
// CHECK: ![[EMPTY:.*]] = !{}
2928
let E : Either = .Neither;
3029

3130
// CHECK: !DICompositeType({{.*}}name: "Color",
3231
// CHECK-SAME: size: 8,
3332
// CHECK-SAME: identifier: "$s4enum5ColorOD"
33+
3434
enum Color : UInt64 {
3535
// This is effectively a 2-bit bitfield:
3636
// DWARF: DICompositeType(tag: DW_TAG_enumeration_type, name: "Color",
@@ -72,8 +72,7 @@ let movie : Maybe<Color> = .none
7272

7373
public enum Nothing { }
7474
public func foo(_ empty : Nothing) { }
75-
// CHECK: !DICompositeType({{.*}}name: "Nothing", {{.*}}elements: ![[EMPTY]]
76-
75+
// CHECK: !DICompositeType({{.*}}name: "Nothing"
7776
// CHECK: !DICompositeType({{.*}}name: "$s4enum4RoseOyxG{{z?}}D"
7877
enum Rose<A> {
7978
case MkRose(() -> A, () -> [Rose<A>])

test/DebugInfo/parent-scope.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public struct Generic<T : P> {
1919
// But only one concrete type is expected.
2020
// CHECK: !DISubprogram({{.*}}linkageName: "$s4main8ConcreteV3getSiSgyF",
2121
// CHECK-SAME: scope: ![[CONC:[0-9]+]],
22-
// CHECK: ![[CONC]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Concrete", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, elements: !{{[0-9]+}}, runtimeLang: DW_LANG_Swift, identifier: "$s4main8ConcreteVD")
22+
// CHECK: ![[CONC]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Concrete", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, runtimeLang: DW_LANG_Swift, identifier: "$s4main8ConcreteVD")
2323
public struct Concrete {
2424
public func get() -> Int? {
2525
return nil
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// RUN: %target-swift-frontend -primary-file %s -emit-ir -gdwarf-types -o - | %FileCheck %s
2+
3+
protocol TraitsProtocol {
4+
associatedtype IntType: FixedWidthInteger
5+
}
6+
7+
final class MyClass<SomeTraits: TraitsProtocol> {
8+
typealias Traits = SomeTraits
9+
private var blame: MyClass<Traits>?
10+
}
11+
12+
struct Traits32: TraitsProtocol {
13+
typealias IntType = UInt32
14+
}
15+
16+
let v : MyClass<Traits32>? = nil
17+
18+
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]+]])
23+
24+
// CHECK-DAG: ![[OPTIONAL]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Optional"
25+
26+
// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "MyClass", {{.*}}templateParams: ![[PARAMS:[0-9]+]], identifier: "$s4main7MyClassCyAA8Traits32VGD", specification: ![[SPEC:[0-9]+]])
27+
// CHECK-DAG: ![[PARAMS]] = !{![[PARAM:[0-9]+]]}
28+
// CHECK-DAG: ![[PARAM]] = !DITemplateTypeParameter(type: ![[TRAITS32:[0-9]+]])
29+
// CHECK-DAG: ![[TRAITS32]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Traits32"
30+
// CHECK-DAG: ![[SPEC]] = !DICompositeType(tag: DW_TAG_structure_type, name: "MyClass", {{.*}}identifier: "$s4main7MyClassCyxGD")
31+
32+
33+
// have a second cache from (DIScope???, CanonicalMangledName) -> DIType
34+
// if is non-canonical type emit a typealias to DIType.
35+
36+
struct C {}
37+
struct A {
38+
typealias B = C
39+
let b: B
40+
}
41+
42+
struct D {
43+
typealias B = C
44+
let b: B
45+
}
46+
47+
let a : A? = nil
48+
let b : D? = nil
49+
50+
// Check that the mechanism creating the canoicalization typedefs, doesn't merge
51+
// more than it should:
52+
// CHECK-DAG: ![[B1:[0-9]+]] = !DIDerivedType(tag: DW_TAG_typedef, name: "$s4main1AV1BaD"
53+
// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "b", {{.*}} baseType: ![[B1]])
54+
// CHECK-DAG: ![[B2:[0-9]+]] = !DIDerivedType(tag: DW_TAG_typedef, name: "$s4main1DV1BaD"
55+
// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "b", {{.*}}, baseType: ![[B2]])

test/DebugInfo/typealias.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,15 @@ extension Up where A.A == Int {
127127
var gg: DependentAlias<Self> = 123
128128
}
129129
}
130+
131+
typealias UsedAsGenericParameter = Float
132+
struct S<T> {}
133+
public func bar() {
134+
let s = S<UsedAsGenericParameter>()
135+
// CHECK-DAG: !DILocalVariable(name: "s",{{.*}} type: ![[LET_S_WITH_ALIAS:[0-9]+]]
136+
// CHECK-DAG: ![[LET_S_WITH_ALIAS]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[S_WITH_ALIAS:[0-9]+]]
137+
// CHECK-DAG: ![[S_WITH_ALIAS]] = !DICompositeType(tag: DW_TAG_structure_type, {{.*}}elements: ![[ELTS:[0-9]+]]
138+
// CHECK-DAG: ![[ELTS]] = !{![[MEMBER:[0-9]+]]}
139+
// CHECK-DAG: ![[MEMBER]] = !DIDerivedType(tag: DW_TAG_member, {{.*}}baseType: ![[USED_AS_GENERIC:[0-9]+]])
140+
// CHECK-DAG: ![[USED_AS_GENERIC]] = !DICompositeType(tag: DW_TAG_structure_type, name: "$s9typealias1SVyAA22UsedAsGenericParameteraGD"
141+
}

test/DebugInfo/typealias_indirect.swift

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
// RUN: %target-swift-frontend %s -emit-ir -parse-as-library -module-name a -g -o - | %FileCheck %s
2-
// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "$s1a10LocalAliasaD", {{.*}}baseType: ![[BASETY:[0-9]+]]
3-
// CHECK: ![[BASETY]]{{.*}}$sSbD
2+
3+
// FIXME: While we can preserve that ClassAlias = MyClass<LocalAlias, Bool>
4+
// and we can preserve that MyClass<LocalAlias, Bool> = MyClass<Bool, Bool>
5+
// we cannot preserve that LocalAlias = Bool.
6+
7+
// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "$s1a7MyClassCyAA10LocalAliasaSbGD",{{.*}}baseType: ![[BOOLBOOLTY:[0-9]+]]
8+
// CHECK: ![[BOOLBOOLTY]] = !DICompositeType(tag: DW_TAG_structure_type, name: "MyClass", {{.*}}identifier: "$s1a7MyClassCyS2bGD"
9+
10+
// FIXME: !DIDerivedType(tag: DW_TAG_typedef, name: "$s1a10LocalAliasaD", {{.*}}baseType: ![[BASETY:[0-9]+]]
11+
// FIXME: ![[BASETY]]{{.*}}$sSbD
412
public class MyClass<A, B> {}
513
public typealias LocalAlias = Bool
614
public typealias ClassAlias = MyClass<LocalAlias, Bool>

test/DebugInfo/value-generics-embedded.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,19 @@
55
// REQUIRES: swift_feature_Embedded
66
// REQUIRES: swift_feature_ValueGenerics
77

8-
// CHECK-DAG: !DICompositeType({{.*}}templateParams: ![[SLAB_PARAMS:.*]], {{.*}}identifier: "$es11InlineArrayVy$0_4main8MySpriteVGD"
8+
// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "InlineArray",{{.*}}size: 64{{.*}}elements: ![[ELTS:[0-9]+]], runtimeLang: DW_LANG_Swift, templateParams: ![[SLAB_PARAMS:[0-9]+]], identifier: "$es11InlineArrayVy$0_4main8MySpriteVGD", specification:
99
// CHECK-DAG: ![[SLAB_PARAMS]] = !{![[COUNT_PARAM:.*]], ![[ELEMENT_PARAM:.*]]}
1010
// CHECK-DAG: ![[COUNT_PARAM]] = !DITemplateTypeParameter(type: ![[COUNT_TYPE:.*]])
1111
// CHECK-DAG: ![[COUNT_TYPE]] = !DICompositeType({{.*}}name: "$e$0_D"
1212
// CHECK-DAG: ![[ELEMENT_PARAM]] = !DITemplateTypeParameter(type: ![[ELEMENT_TYPE:.*]])
1313
// CHECK-DAG: ![[ELEMENT_TYPE]] = !DICompositeType({{.*}}name: "MySprite", {{.*}}identifier: "$e4main8MySpriteVD"
14+
15+
// CHECK-DAG: ![[ELTS]] = !{![[STORAGE_MEMBER:.*]]}
16+
// CHECK-DAG: ![[STORAGE_MEMBER]] = !DIDerivedType(tag: DW_TAG_member, name: "_storage",{{.*}}baseType: ![[ARRAY:[0-9]+]], size: 64
17+
// CHECK-DAG: ![[ARRAY]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELEMENT_TYPE]], size: 64, elements: ![[SUBRANGES:[0-9]+]])
18+
// CHECK-DAG: ![[SUBRANGES]] = !{![[DIM:[0-9]+]]}
19+
// CHECK-DAG: ![[DIM]] = !DISubrange(count: 1)
20+
1421
struct MySprites {
1522
var bricks: InlineArray<1, MySprite>
1623
}

0 commit comments

Comments
 (0)