Skip to content

Commit 29c87df

Browse files
committed
[DebugInfo] Emit debug info for witness tables
This change emits debug info for witness tables passed into generic functions when a generic type is constrained to a protocol. This information is required for LLDB's generic expression evaluator to work in such functions. rdar://104446865
1 parent 3490c73 commit 29c87df

16 files changed

+204
-101
lines changed

include/swift/AST/Types.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7296,7 +7296,10 @@ class GenericTypeParamType : public SubstitutableType,
72967296

72977297
/// Get the name of the generic type parameter.
72987298
Identifier getName() const;
7299-
7299+
7300+
/// Get the canonical <tau>_n_n name;
7301+
Identifier getCanonicalName() const;
7302+
73007303
/// The depth of this generic type parameter, i.e., the number of outer
73017304
/// levels of generic parameter lists that enclose this type parameter.
73027305
///

lib/AST/Type.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2124,8 +2124,10 @@ Identifier GenericTypeParamType::getName() const {
21242124
if (!isCanonical())
21252125
return Name;
21262126

2127-
// Otherwise, we're canonical. Produce an anonymous '<tau>_n_n' name.
2127+
return getCanonicalName();
2128+
}
21282129

2130+
Identifier GenericTypeParamType::getCanonicalName() const {
21292131
// getASTContext() doesn't actually mutate an already-canonical type.
21302132
auto &C = const_cast<GenericTypeParamType*>(this)->getASTContext();
21312133
auto &names = C.CanonicalGenericTypeParamTypeNames;

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 54 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,16 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
279279
DebugTypeInfo DebugType,
280280
bool IsLocalToUnit,
281281
std::optional<SILLocation> Loc);
282+
283+
void emitArtificialVariable(IRGenFunction &IGF, llvm::Value *Metadata,
284+
StringRef Name, StringRef Identifier);
285+
282286
void emitTypeMetadata(IRGenFunction &IGF, llvm::Value *Metadata,
283-
unsigned Depth, unsigned Index, StringRef Name);
287+
GenericTypeParamType *Type);
288+
289+
void emitWitnessTable(IRGenFunction &IGF, llvm::Value *Metadata,
290+
StringRef Name, ProtocolDecl *protocol);
291+
284292
void emitPackCountParameter(IRGenFunction &IGF, llvm::Value *Metadata,
285293
SILDebugVariable VarInfo);
286294

@@ -3904,9 +3912,10 @@ void IRGenDebugInfoImpl::emitGlobalVariableDeclaration(
39043912
Var->addDebugInfo(GV);
39053913
}
39063914

3907-
void IRGenDebugInfoImpl::emitTypeMetadata(IRGenFunction &IGF,
3908-
llvm::Value *Metadata, unsigned Depth,
3909-
unsigned Index, StringRef Name) {
3915+
void IRGenDebugInfoImpl::emitArtificialVariable(IRGenFunction &IGF,
3916+
llvm::Value *Metadata,
3917+
StringRef Name,
3918+
StringRef Identifier) {
39103919
if (Opts.DebugInfoLevel <= IRGenDebugInfoLevel::LineTables)
39113920
return;
39123921

@@ -3915,23 +3924,44 @@ void IRGenDebugInfoImpl::emitTypeMetadata(IRGenFunction &IGF,
39153924
if (!DS || DS->getInlinedFunction()->isTransparent())
39163925
return;
39173926

3918-
llvm::SmallString<8> Buf;
3919-
static const char *Tau = SWIFT_UTF8("\u03C4");
3920-
llvm::raw_svector_ostream OS(Buf);
3921-
OS << '$' << Tau << '_' << Depth << '_' << Index;
3922-
uint64_t PtrWidthInBits = CI.getTargetInfo().getPointerWidth(clang::LangAS::Default);
3927+
uint64_t PtrWidthInBits =
3928+
CI.getTargetInfo().getPointerWidth(clang::LangAS::Default);
39233929
assert(PtrWidthInBits % 8 == 0);
39243930
auto DbgTy = DebugTypeInfo::getTypeMetadata(
39253931
getMetadataType(Name)->getDeclaredInterfaceType().getPointer(),
39263932
Size(PtrWidthInBits / 8),
39273933
Alignment(CI.getTargetInfo().getPointerAlign(clang::LangAS::Default)));
3928-
emitVariableDeclaration(IGF.Builder, Metadata, DbgTy, IGF.getDebugScope(),
3929-
{}, {OS.str().str(), 0, false},
3930-
// swift.type is already a pointer type,
3931-
// having a shadow copy doesn't add another
3932-
// layer of indirection.
3933-
IGF.isAsync() ? CoroDirectValue : DirectValue,
3934-
ArtificialValue);
3934+
emitVariableDeclaration(
3935+
IGF.Builder, Metadata, DbgTy, IGF.getDebugScope(), {},
3936+
{Identifier, 0, false}, // swift.type is already a pointer type,
3937+
// having a shadow copy doesn't add another
3938+
// layer of indirection.
3939+
IGF.isAsync() ? CoroDirectValue : DirectValue, ArtificialValue);
3940+
}
3941+
3942+
void IRGenDebugInfoImpl::emitTypeMetadata(IRGenFunction &IGF,
3943+
llvm::Value *Metadata,
3944+
GenericTypeParamType *Type) {
3945+
auto Name = Type->getName().str();
3946+
llvm::SmallString<8> Buf;
3947+
llvm::raw_svector_ostream OS(Buf);
3948+
OS << "$" << Type->getCanonicalName().str();
3949+
3950+
emitArtificialVariable(IGF, Metadata, Name, OS.str());
3951+
}
3952+
3953+
void IRGenDebugInfoImpl::emitWitnessTable(IRGenFunction &IGF,
3954+
llvm::Value *Metadata, StringRef Name,
3955+
ProtocolDecl *protocol) {
3956+
llvm::SmallString<32> Buf;
3957+
llvm::raw_svector_ostream OS(Buf);
3958+
DebugTypeInfo DbgTy(protocol->getInterfaceType());
3959+
auto MangledName = getMangledName(DbgTy).Canonical;
3960+
OS << "$WT_" << Name << "_" << MangledName;
3961+
// Make sure this ID lives long enough.
3962+
auto Id = IGF.getSwiftModule()->getASTContext().getIdentifier(OS.str());
3963+
3964+
emitArtificialVariable(IGF, Metadata, Name, Id.str());
39353965
}
39363966

39373967
void IRGenDebugInfoImpl::emitPackCountParameter(IRGenFunction &IGF,
@@ -4070,10 +4100,15 @@ void IRGenDebugInfo::emitGlobalVariableDeclaration(
40704100
}
40714101

40724102
void IRGenDebugInfo::emitTypeMetadata(IRGenFunction &IGF, llvm::Value *Metadata,
4073-
unsigned Depth, unsigned Index,
4074-
StringRef Name) {
4103+
GenericTypeParamType *Type) {
40754104
static_cast<IRGenDebugInfoImpl *>(this)->emitTypeMetadata(IGF, Metadata,
4076-
Depth, Index, Name);
4105+
Type);
4106+
}
4107+
4108+
void IRGenDebugInfo::emitWitnessTable(IRGenFunction &IGF, llvm::Value *Metadata,
4109+
StringRef Name, ProtocolDecl *protocol) {
4110+
static_cast<IRGenDebugInfoImpl *>(this)->emitWitnessTable(IGF, Metadata, Name,
4111+
protocol);
40774112
}
40784113

40794114
void IRGenDebugInfo::emitPackCountParameter(IRGenFunction &IGF,

lib/IRGen/IRGenDebugInfo.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,11 @@ class IRGenDebugInfo {
186186

187187
/// Emit debug metadata for type metadata (for generic types). So meta.
188188
void emitTypeMetadata(IRGenFunction &IGF, llvm::Value *Metadata,
189-
unsigned Depth, unsigned Index, StringRef Name);
189+
GenericTypeParamType *Type);
190+
191+
/// Emit debug metadata for a (protocol) witness table.
192+
void emitWitnessTable(IRGenFunction &IGF, llvm::Value *Metadata,
193+
StringRef Name, ProtocolDecl *protocol);
190194

191195
/// Emit debug info for the IR function parameter holding the size of one or
192196
/// more parameter / type packs.

lib/IRGen/IRGenSIL.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,6 +1158,15 @@ class IRGenSILFunction :
11581158
}
11591159

11601160
emitTypeMetadataRef(archetype);
1161+
for (auto protocol : archetype->getConformsTo()) {
1162+
if (Lowering::TypeConverter::protocolRequiresWitnessTable(
1163+
protocol)) {
1164+
auto conformance =
1165+
ProtocolConformanceRef::forAbstract(archetype, protocol);
1166+
emitWitnessTableRef(*this, archetype->getCanonicalType(),
1167+
conformance);
1168+
}
1169+
}
11611170
} else if (auto packArchetype = dyn_cast<PackArchetypeType>(t)) {
11621171
emitTypeMetadataRef(packArchetype);
11631172
} else if (auto packtype = dyn_cast<SILPackType>(t)) {

lib/IRGen/LocalTypeData.cpp

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -412,22 +412,36 @@ static void maybeEmitDebugInfoForLocalTypeData(IRGenFunction &IGF,
412412
if (DS && DS->getInlinedFunction() &&
413413
DS->getInlinedFunction()->isTransparent())
414414
return;
415-
416-
// Only for formal type metadata.
417-
if (key.Kind != LocalTypeDataKind::forFormalTypeMetadata())
415+
// For formal type metadata and witness tables.
416+
ProtocolDecl *proto = nullptr;
417+
418+
if (key.Kind.isAbstractProtocolConformance())
419+
proto = key.Kind.getAbstractProtocolConformance();
420+
else if (key.Kind.isConcreteProtocolConformance())
421+
proto = key.Kind.getConcreteProtocolConformance()->getProtocol();
422+
else if (key.Kind != LocalTypeDataKind::forFormalTypeMetadata())
418423
return;
419424

420425
// Only for archetypes, and not for opened/opaque archetypes.
421426
auto type = dyn_cast<ArchetypeType>(key.Type);
422427
if (!type)
423428
return;
424-
if (!type->isRoot())
429+
if (!type->isRoot() && !proto)
425430
return;
426431
if (!isa<PrimaryArchetypeType>(type) && !isa<PackArchetypeType>(type))
427432
return;
428433

429-
auto *typeParam = type->getInterfaceType()->castTo<GenericTypeParamType>();
430-
auto name = typeParam->getName().str();
434+
auto interfaceType = type->getInterfaceType();
435+
llvm::SmallString<16> name;
436+
if (auto DMT =
437+
llvm::dyn_cast<DependentMemberType>(interfaceType.getPointer())) {
438+
name = DMT->getString();
439+
} else if (auto GTPT = llvm::dyn_cast<GenericTypeParamType>(
440+
interfaceType.getPointer())) {
441+
name = GTPT->getString();
442+
} else {
443+
return;
444+
}
431445

432446
llvm::Value *data = value.getMetadata();
433447

@@ -447,10 +461,12 @@ static void maybeEmitDebugInfoForLocalTypeData(IRGenFunction &IGF,
447461
if (!IGF.IGM.DebugInfo)
448462
return;
449463

450-
IGF.IGM.DebugInfo->emitTypeMetadata(IGF, data,
451-
typeParam->getDepth(),
452-
typeParam->getIndex(),
453-
name);
464+
if (proto) {
465+
IGF.IGM.DebugInfo->emitWitnessTable(IGF, data, name, proto);
466+
} else {
467+
auto *typeParam = type->getInterfaceType()->castTo<GenericTypeParamType>();
468+
IGF.IGM.DebugInfo->emitTypeMetadata(IGF, data, typeParam);
469+
}
454470
}
455471

456472
void

test/DebugInfo/move_function_dbginfo.swift

Lines changed: 6 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -237,19 +237,19 @@ public func copyableVarArgTest(_ k: inout Klass) {
237237
// DWARF-NEXT: DW_AT_artificial (true)
238238
//
239239
// DWARF: DW_TAG_variable
240+
// DWARF: DW_AT_location
241+
// DWARF: DW_AT_name ("$WT_T_$s3out1P_pmD")
242+
// DWARF: DW_AT_type (
243+
// DWARF: DW_AT_artificial (true)
244+
//
245+
// DWARF: DW_TAG_variable
240246
// DWARF-NEXT: DW_AT_location (0x{{[a-z0-9]+}}:
241247
// DWARF-NEXT: [0x{{[a-z0-9]+}}, 0x{{[a-z0-9]+}}):
242248
// DWARF-NEXT: DW_AT_name ("k")
243249
// DWARF-NEXT: DW_AT_decl_file (
244250
// DWARF-NEXT: DW_AT_decl_line (
245251
// DWARF-NEXT: DW_AT_type (
246252
//
247-
// DWARF: DW_TAG_variable
248-
// DWARF-NEXT: DW_AT_location (
249-
// DWARF-NEXT: DW_AT_name ("m")
250-
// DWARF-NEXT: DW_AT_decl_file (
251-
// DWARF-NEXT: DW_AT_decl_line (
252-
// DWARF-NEXT: DW_AT_type (
253253
public func addressOnlyValueTest<T : P>(_ x: T) {
254254
let k = x
255255
k.doSomething()
@@ -265,33 +265,6 @@ public func addressOnlyValueTest<T : P>(_ x: T) {
265265
// CHECK: ret void
266266
// CHECK-NEXT: }
267267
//
268-
// DWARF: DW_AT_linkage_name ("$s3out23addressOnlyValueArgTestyyxnAA1PRzlF")
269-
// DWARF-NEXT: DW_AT_name ("addressOnlyValueArgTest")
270-
// DWARF-NEXT: DW_AT_decl_file (
271-
// DWARF-NEXT: DW_AT_decl_line (
272-
// DWARF-NEXT: DW_AT_type (
273-
// DWARF-NEXT: DW_AT_external (
274-
//
275-
// DWARF: DW_TAG_formal_parameter
276-
// DWARF-NEXT: DW_AT_location (0x{{[a-z0-9]+}}:
277-
// DWARF-NEXT: [0x{{[a-z0-9]+}}, 0x{{[a-z0-9]+}}):
278-
// DWARF-NEXT: DW_AT_name ("k")
279-
// DWARF-NEXT: DW_AT_decl_file (
280-
// DWARF-NEXT: DW_AT_decl_line (
281-
// DWARF-NEXT: DW_AT_type (
282-
//
283-
// DWARF: DW_TAG_variable
284-
// DWARF-NEXT: DW_AT_location (
285-
// DWARF-NEXT: DW_AT_name ("$\317\204_0_0")
286-
// DWARF-NEXT: DW_AT_type (
287-
// DWARF-NEXT: DW_AT_artificial (true)
288-
//
289-
// DWARF: DW_TAG_variable
290-
// DWARF-NEXT: DW_AT_location (
291-
// DWARF-NEXT: DW_AT_name ("m")
292-
// DWARF-NEXT: DW_AT_decl_file (
293-
// DWARF-NEXT: DW_AT_decl_line (
294-
// DWARF-NEXT: DW_AT_type (
295268
public func addressOnlyValueArgTest<T : P>(_ k: __owned T) {
296269
k.doSomething()
297270
let m = consume k
@@ -306,35 +279,6 @@ public func addressOnlyValueArgTest<T : P>(_ k: __owned T) {
306279
// CHECK: ret void
307280
// CHECK-NEXT: }
308281
//
309-
// DWARF: DW_AT_linkage_name ("$s3out18addressOnlyVarTestyyxAA1PRzlF")
310-
// DWARF-NEXT: DW_AT_name ("addressOnlyVarTest")
311-
// DWARF-NEXT: DW_AT_decl_file (
312-
// DWARF-NEXT: DW_AT_decl_line (
313-
// DWARF-NEXT: DW_AT_type (
314-
// DWARF-NEXT: DW_AT_external (
315-
//
316-
// DWARF: DW_TAG_formal_parameter
317-
// DWARF-NEXT: DW_AT_location (
318-
// DWARF-NEXT: DW_AT_name ("x")
319-
// DWARF-NEXT: DW_AT_decl_file (
320-
// DWARF-NEXT: DW_AT_decl_line (
321-
// DWARF-NEXT: DW_AT_type (
322-
//
323-
// DWARF: DW_TAG_variable
324-
// DWARF-NEXT: DW_AT_location (
325-
// DWARF-NEXT: DW_AT_name ("$\317\204_0_0")
326-
// DWARF-NEXT: DW_AT_type (
327-
// DWARF-NEXT: DW_AT_artificial (true)
328-
//
329-
// DWARF: DW_TAG_variable
330-
// DWARF-NEXT: DW_AT_location (0x{{[a-z0-9]+}}:
331-
// DWARF-NEXT: [0x{{[a-z0-9]+}}, 0x{{[a-z0-9]+}}):
332-
// TODO: Missing def in dbg info here.
333-
// DWARF-NEXT: [0x{{[a-z0-9]+}}, 0x{{[a-z0-9]+}}):
334-
// DWARF-NEXT: DW_AT_name ("k")
335-
// DWARF-NEXT: DW_AT_decl_file (
336-
// DWARF-NEXT: DW_AT_decl_line (
337-
// DWARF-NEXT: DW_AT_type (
338282
public func addressOnlyVarTest<T : P>(_ x: T) {
339283
var k = x // << this
340284
k.doSomething()

test/DebugInfo/witness_table.swift

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// RUN: %target-swift-frontend %s -emit-ir -g -o -
2+
import StdlibUnittest
3+
protocol P1 {}
4+
protocol P2 {}
5+
protocol P3 {}
6+
protocol P4 {}
7+
protocol P5 {}
8+
9+
struct I: P1, P2, P4 {}
10+
struct I2: P3 {}
11+
struct I3: P5 {}
12+
13+
struct S<T, U: P3> where T: P1, T: P2 {
14+
let t: T
15+
let u: U
16+
17+
func foo() {
18+
}
19+
//CHECK: ![[foo:[0-9]+]] = distinct !DISubprogram(name: "foo", linkageName: "$s13witness_table1SV3fooyyF",
20+
//CHECK: !DILocalVariable(name: "$WT_T_$s13witness_table2P1_pmD", scope: ![[foo]], {{.*}}, flags: DIFlagArtificial)
21+
//CHECK: !DILocalVariable(name: "$WT_T_$s13witness_table2P2_pmD", scope: ![[foo]], {{.*}}, flags: DIFlagArtificial)
22+
//CHECK: !DILocalVariable(name: "$\CF\84_0_0", scope: ![[foo]], {{.*}}, flags: DIFlagArtificial)
23+
//CHECK: !DILocalVariable(name: "$WT_U_$s13witness_table2P3_pmD", scope: ![[foo]], {{.*}}, flags: DIFlagArtificial)
24+
//CHECK: !DILocalVariable(name: "$\CF\84_0_1", scope: ![[foo]], {{.*}}, flags: DIFlagArtificial)
25+
26+
func bar<V: P4>(v: V) {
27+
}
28+
//CHECK: ![[bar:[0-9]+]] = distinct !DISubprogram(name: "bar", linkageName: "$s13witness_table1SV3bar1vyqd___tAA2P4Rd__lF",
29+
//CHECK: !DILocalVariable(name: "$\CF\84_1_0", scope: ![[bar]], {{.*}}, flags: DIFlagArtificial)
30+
//CHECK: !DILocalVariable(name: "$WT_V_$s13witness_table2P4_pmD", scope: ![[bar]], {{.*}}, flags: DIFlagArtificial)
31+
//CHECK: !DILocalVariable(name: "$WT_T_$s13witness_table2P1_pmD", scope: ![[bar]], {{.*}}, flags: DIFlagArtificial)
32+
//CHECK: !DILocalVariable(name: "$WT_T_$s13witness_table2P2_pmD", scope: ![[bar]], {{.*}}, flags: DIFlagArtificial)
33+
//CHECK: !DILocalVariable(name: "$\CF\84_0_0", scope: ![[bar]], {{.*}}, flags: DIFlagArtificial)
34+
//CHECK: !DILocalVariable(name: "$WT_U_$s13witness_table2P3_pmD", scope: ![[bar]], {{.*}}, flags: DIFlagArtificial)
35+
//CHECK: !DILocalVariable(name: "$\CF\84_0_1", scope: ![[bar]], {{.*}}, flags: DIFlagArtificial)
36+
}
37+
38+
extension S where T: P5 {
39+
func baz() {
40+
}
41+
42+
//CHECK: ![[baz:[0-9]+]] = distinct !DISubprogram(name: "baz", linkageName: "$s13witness_table1SVA2A2P5RzrlE3bazyyF",
43+
//CHECK: !DILocalVariable(name: "$WT_T_$s13witness_table2P5_pmD", scope: ![[baz]], {{.*}}, flags: DIFlagArtificial)
44+
//CHECK: !DILocalVariable(name: "$WT_T_$s13witness_table2P1_pmD", scope: ![[baz]], {{.*}}, flags: DIFlagArtificial)
45+
//CHECK: !DILocalVariable(name: "$WT_T_$s13witness_table2P2_pmD", scope: ![[baz]], {{.*}}, flags: DIFlagArtificial)
46+
//CHECK: !DILocalVariable(name: "$\CF\84_0_0", scope: ![[baz]], {{.*}}, flags: DIFlagArtificial)
47+
//CHECK: !DILocalVariable(name: "$WT_U_$s13witness_table2P3_pmD", scope: ![[baz]], {{.*}}, flags: DIFlagArtificial)
48+
//CHECK: !DILocalVariable(name: "$\CF\84_0_1", scope: ![[baz]], {{.*}}, flags: DIFlagArtificial)
49+
}
50+
51+
S(t: I(), u: I2())
52+
53+
func freeFunc<T1: P1, T2>(t1: T1, t2: T2) where T2: P3, T2: P4 {
54+
}
55+
//CHECK: ![[freeFunc:[0-9]+]] = distinct !DISubprogram(name: "freeFunc", linkageName: "$s13witness_table8freeFunc2t12t2yx_q_tAA2P1RzAA2P3R_AA2P4R_r0_lF",
56+
//CHECK: !DILocalVariable(name: "$\CF\84_0_0", scope: ![[freeFunc]], {{.*}}, flags: DIFlagArtificial)
57+
//CHECK: !DILocalVariable(name: "$\CF\84_0_1", scope: ![[freeFunc]], {{.*}}, flags: DIFlagArtificial)
58+
//CHECK: !DILocalVariable(name: "$WT_T1_$s13witness_table2P1_pmD", scope: ![[freeFunc]], {{.*}}, flags: DIFlagArtificial)
59+
//CHECK: !DILocalVariable(name: "$WT_T2_$s13witness_table2P3_pmD", scope: ![[freeFunc]], {{.*}}, flags: DIFlagArtificial)
60+
//CHECK: !DILocalVariable(name: "$WT_T2_$s13witness_table2P4_pmD", scope: ![[freeFunc]], {{.*}}, flags: DIFlagArtificial)
61+
62+
protocol A {
63+
associatedtype Element
64+
}
65+
66+
func withAssociatedType<T: A>(_: T) where T.Element: A {
67+
}
68+
69+
//CHECK: ![[withAssociatedType:[0-9]+]] = distinct !DISubprogram(name: "withAssociatedType", linkageName: "$s13witness_table18withAssociatedTypeyyxAA1ARzAaC7ElementRpzlF"
70+
//CHECK: !DILocalVariable(name: "$\CF\84_0_0", scope: ![[withAssociatedType]], {{.*}}, flags: DIFlagArtificial)
71+
//CHECK: !DILocalVariable(name: "$WT_T_$s13witness_table1A_pmD", scope: ![[withAssociatedType]], {{.*}}, flags: DIFlagArtificial)
72+
//CHECK: !DILocalVariable(name: "$WT_T.Element_$s13witness_table1A_pmD", scope: ![[withAssociatedType]], {{.*}}, flags: DIFlagArtificial)
73+

0 commit comments

Comments
 (0)