Skip to content

Commit b6b0046

Browse files
Merge pull request #28020 from adrian-prantl/56521648
Debug Info: Avoid type uniquing clashes for bound generic enums.
2 parents ea950df + e881168 commit b6b0046

File tree

6 files changed

+132
-13
lines changed

6 files changed

+132
-13
lines changed

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,6 +1001,29 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
10011001
return BitWidth;
10021002
}
10031003

1004+
/// Create a sized container for a sizeless type. Used to represent
1005+
/// BoundGenericEnums that may have different sizes depending on what they are
1006+
/// bound to, but still share a mangled name.
1007+
llvm::DIType *createOpaqueStructWithSizedContainer(
1008+
llvm::DIScope *Scope, StringRef Name, llvm::DIFile *File, unsigned Line,
1009+
unsigned SizeInBits, unsigned AlignInBits, llvm::DINode::DIFlags Flags,
1010+
StringRef MangledName) {
1011+
// Let the MDNode folding set do the work of uniquing the inner type. This
1012+
// should be cheap.
1013+
llvm::DICompositeType *UniqueType = DBuilder.createStructType(
1014+
Scope, Name, File, Line, 0, 0, Flags, nullptr,
1015+
DBuilder.getOrCreateArray(ArrayRef<llvm::Metadata *>()),
1016+
llvm::dwarf::DW_LANG_Swift, nullptr, MangledName);
1017+
llvm::Metadata *Elements[] = {
1018+
DBuilder.createMemberType(Scope, "", File, 0, SizeInBits,
1019+
AlignInBits, 0, Flags, UniqueType)};
1020+
1021+
return DBuilder.createStructType(
1022+
Scope, "", File, Line, SizeInBits, AlignInBits, Flags,
1023+
/* DerivedFrom */ nullptr, DBuilder.getOrCreateArray(Elements),
1024+
llvm::dwarf::DW_LANG_Swift);
1025+
}
1026+
10041027
llvm::DIType *createPointerSizedStruct(llvm::DIScope *Scope, StringRef Name,
10051028
llvm::DIFile *File, unsigned Line,
10061029
llvm::DINode::DIFlags Flags,
@@ -1414,12 +1437,9 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
14141437
auto *Decl = EnumTy->getDecl();
14151438
auto L = getDebugLoc(*this, Decl);
14161439
auto *File = getOrCreateFile(L.Filename);
1417-
if (Opts.DebugInfoLevel > IRGenDebugInfoLevel::ASTTypes)
1418-
return createEnumType(DbgTy, Decl, MangledName, Scope, File, L.Line,
1419-
Flags);
1420-
else
1421-
return createOpaqueStruct(Scope, Decl->getName().str(), File, L.Line,
1422-
SizeInBits, AlignInBits, Flags, MangledName);
1440+
return createOpaqueStructWithSizedContainer(
1441+
Scope, Decl->getName().str(), File, L.Line, SizeInBits, AlignInBits,
1442+
Flags, MangledName);
14231443
}
14241444

14251445
case TypeKind::BuiltinVector: {

test/DebugInfo/BoundGenericEnum.swift

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// RUN: %target-swift-frontend %s -Onone -emit-ir -g -o - -module-name a \
2+
// RUN: -disable-debugger-shadow-copies | %FileCheck %s
3+
public enum Result<Value> {
4+
case success(Value)
5+
case failure(Error)
6+
}
7+
8+
extension Result {
9+
public func map<U>(_ transform: (Value) -> U) -> Result<U> {
10+
switch self {
11+
case .success(let value):
12+
return .success(transform(value))
13+
case .failure(let error):
14+
return .failure(error)
15+
}
16+
}
17+
}
18+
19+
func use<T>(_ t : T) {
20+
}
21+
22+
public class SomeClass {
23+
public let s = "hello"
24+
}
25+
26+
extension Result where Value : SomeClass {
27+
public func f() -> Self {
28+
use(self)
29+
return map({ $0 })
30+
}
31+
}
32+
33+
extension Result {
34+
public func g() {
35+
use(self)
36+
}
37+
}
38+
39+
let x : Result<SomeClass> = .success(SomeClass())
40+
let y : Result<(Int64, Int64, Int64, Int64)> = .success((1, 2, 3, 4))
41+
x.f()
42+
y.g()
43+
44+
// Here we have three types, all named $s1a6ResultOyxGD (---> a.Result<A>),
45+
// but with different storage sizes:
46+
//
47+
// 0. Unsized from the subroutine tupe of map<U>.
48+
// 1. Enum wrapping a pointer-sized object [map() and f()].
49+
// 2. Enum wrapping a 4x64-bit tuple.
50+
//
51+
// Test that bound generic enums are *not* using their mangled name as a unique
52+
// identifier.
53+
54+
// (0) unsized.
55+
// CHECK: !DISubprogram(name: "map", {{.*}}line: 9, type: ![[SBTY:[0-9]+]]
56+
// CHECK: ![[SBTY]] = !DISubroutineType(types: ![[SBTYS:[0-9]+]])
57+
// CHECK: ![[SBTYS]] = !{!{{[0-9]+}}, !{{[0-9]+}}, ![[SELFTY:[0-9]+]]}
58+
// CHECK: ![[SELFTY]] =
59+
// CHECK-SAME: !DICompositeType(tag: DW_TAG_structure_type, {{.*}}line: 3,
60+
// CHECK-SAME: elements: ![[UNSIZED_ELTS:[0-9]+]]
61+
// CHECK: ![[UNSIZED_ELTS]] = !{![[UNSIZED_MEM:[0-9]+]]}
62+
// CHECK: ![[UNSIZED_MEM]] = !DIDerivedType(tag: DW_TAG_member,
63+
// CHECK-SAME: baseType: ![[UNIQ:[0-9]+]]
64+
65+
// The unique unsized type.
66+
// CHECK: ![[UNIQ]] = !DICompositeType(
67+
// CHECK-SAME: tag: DW_TAG_structure_type, name: "Result",
68+
// CHECK-SAME: line: 3,
69+
// CHECK-NOT: size:
70+
// CHECK-SAME: runtimeLang: DW_LANG_Swift,
71+
// CHECK-SAME: identifier: "$s1a6ResultOyxGD")
72+
73+
// (2)
74+
// CHECK: !DILocalVariable(name: "self", arg: 2, {{.*}}line: 9,
75+
// CHECK-SAME: type: ![[C_TUP:[0-9]+]]
76+
// CHECK: ![[C_TUP]] = !DIDerivedType(tag: DW_TAG_const_type,
77+
// CHECK-SAME: baseType: ![[TUP:[0-9]+]])
78+
// CHECK: ![[TUP]] = !DICompositeType(tag: DW_TAG_structure_type,
79+
// CHECK-SAME: line: 3, size: {{256|512}},
80+
81+
// (1)
82+
// CHECK: !DILocalVariable(name: "self", arg: 1, {{.*}}line: 27,
83+
// CHECK-SAME: type: ![[C_CLASS:[0-9]+]]
84+
// CHECK: ![[C_CLASS]] = !DIDerivedType(tag: DW_TAG_const_type,
85+
// CHECK-SAME: baseType: ![[CLASS:[0-9]+]])
86+
// CHECK: ![[CLASS]] = !DICompositeType(tag: DW_TAG_structure_type,
87+
// CHECK-SAME: line: 3, size:

test/DebugInfo/bound-namealiastype.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ func dispatch_queue_create() -> dispatch_queue_t! {
99
}
1010

1111
// CHECK: !DIGlobalVariable(name: "queue",
12-
// CHECK-SAME: line: [[@LINE+3]], type: ![[T:[0-9]+]]
13-
// CHECK: ![[T]] = !DICompositeType(
12+
// CHECK-SAME: line: [[@LINE+6]], type: ![[TY_CONTAINER:[0-9]+]]
13+
// CHECK: ![[TY_CONTAINER]] = !DICompositeType({{.*}}elements: ![[TY_ELTS:[0-9]+]]
14+
// CHECK: ![[TY_ELTS]] = !{![[TY_MEMBER:[0-9]+]]}
15+
// CHECK: ![[TY_MEMBER]] = !DIDerivedType(tag: DW_TAG_member, {{.*}}baseType: ![[TY:[0-9]+]]
16+
// CHECK: ![[TY]] = !DICompositeType(
1417
// CHECK-SAME: identifier: "$s4main16dispatch_queue_taSgD"
1518
public var queue = dispatch_queue_create()

test/DebugInfo/enum.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ let r = Color.Red
5252
let c = MaybeIntPair.just(74, 75)
5353
// CHECK: !DICompositeType({{.*}}name: "Maybe",
5454
// CHECK-SAME: line: [[@LINE-8]],
55-
// CHECK-SAME: size: 8{{[,)]}}
5655
// CHECK-SAME: identifier: "$s4enum5MaybeOyAA5ColorOGD"
5756
let movie : Maybe<Color> = .none
5857

@@ -79,8 +78,12 @@ public enum Tuple<P> {
7978

8079
func bar<T>(_ x : Tuple<T>) -> Tuple<T> { return x }
8180

82-
// CHECK: ![[LIST:.*]] = !DICompositeType({{.*}}identifier: "$s4enum4ListOyxGD"
83-
// CHECK-DAG: ![[LET_LIST:.*]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[LIST]])
81+
// CHECK-DAG: ![[LIST:.*]] = !DICompositeType({{.*}}identifier: "$s4enum4ListOyxGD"
82+
// CHECK-DAG: ![[LIST_MEMBER:.*]] = !DIDerivedType(tag: DW_TAG_member, {{.*}} baseType: ![[LIST]]
83+
// CHECK-DAG: ![[LIST_ELTS:.*]] = !{![[LIST_MEMBER]]}
84+
// CHECK-DAG: ![[LIST_CONTAINER:.*]] = !DICompositeType({{.*}}elements: ![[LIST_ELTS]]
85+
86+
// CHECK-DAG: ![[LET_LIST:.*]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[LIST_CONTAINER]])
8487
// CHECK-DAG: !DILocalVariable(name: "self", arg: 1, {{.*}} line: [[@LINE+4]], type: ![[LET_LIST]], flags: DIFlagArtificial)
8588
public enum List<T> {
8689
indirect case Tail(List, T)

test/DebugInfo/generic_enum.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ func wrapTrivialGeneric<T, U>(_ t: T, u: U) -> TrivialGeneric<T, U> {
1717
return .x(t, u)
1818
}
1919
// CHECK-DAG: ![[T1:.*]] = !DICompositeType({{.*}}identifier: "$s12generic_enum14TrivialGenericOys5Int64VSSGD"
20-
// CHECK-DAG: !DIGlobalVariable(name: "tg",{{.*}} line: [[@LINE+2]],{{.*}} type: ![[T1]],{{.*}} isLocal: false, isDefinition: true
20+
// CHECK-DAG: ![[T1_MEMBER:.*]] = !DIDerivedType(tag: DW_TAG_member, {{.*}}baseType: ![[T1]]
21+
// CHECK-DAG: ![[T1_ELTS:.*]] = !{![[T1_MEMBER]]}
22+
// CHECK-DAG: ![[T1_CONTAINER:.*]] = !DICompositeType({{.*}}elements: ![[T1_ELTS]]
23+
// CHECK-DAG: !DIGlobalVariable(name: "tg",{{.*}} line: [[@LINE+2]],{{.*}} type: ![[T1_CONTAINER]],{{.*}} isLocal: false, isDefinition: true
2124
// CHECK-DAG: !DICompositeType({{.*}}, name: "TrivialGeneric", {{.*}}identifier: "$s12generic_enum14TrivialGenericOys5Int64VSSGD"
2225
var tg : TrivialGeneric<Int64, String> = .x(23, "skidoo")
2326
switch tg {

test/DebugInfo/protocol-sugar.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,8 @@ protocol B {}
44
typealias C = B & A
55
protocol D {}
66
var p: (C & D)?
7-
// CHECK-DAG: !DIGlobalVariable(name: "p", {{.*}}type: ![[TY:[0-9]+]]
7+
// CHECK-DAG: !DIGlobalVariable(name: "p", {{.*}}type: ![[TY_CONTAINER:[0-9]+]]
8+
// CHECK-DAG: ![[TY_CONTAINER]] = !DICompositeType({{.*}}elements: ![[TY_ELTS:[0-9]+]]
9+
// CHECK-DAG: ![[TY_ELTS]] = !{![[TY_MEMBER:[0-9]+]]}
10+
// CHECK-DAG: ![[TY_MEMBER]] = !DIDerivedType(tag: DW_TAG_member, {{.*}}baseType: ![[TY:[0-9]+]]
811
// CHECK-DAG: ![[TY]] = {{.*}}identifier: "$s4main1A_AA1BAA1DpXSpSgD"

0 commit comments

Comments
 (0)