Skip to content

Commit 66748f7

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 1814a15 commit 66748f7

16 files changed

+251
-104
lines changed

include/swift/AST/Types.h

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

73127312
/// Get the name of the generic type parameter.
73137313
Identifier getName() const;
7314-
7314+
7315+
/// Get the canonical <tau>_n_n name;
7316+
Identifier getCanonicalName() const;
7317+
73157318
/// The depth of this generic type parameter, i.e., the number of outer
73167319
/// levels of generic parameter lists that enclose this type parameter.
73177320
///

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+
llvm::SmallString<8> Buf;
3946+
llvm::raw_svector_ostream OS(Buf);
3947+
OS << "$" << Type->getCanonicalName().str();
3948+
auto Name = Type->getName().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->getDeclaredType());
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: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1168,8 +1168,42 @@ class IRGenSILFunction :
11681168
emitPackCountDebugVariable(Shape);
11691169
}
11701170
});
1171+
1172+
if (auto *BGT = llvm::dyn_cast<BoundGenericType>(Ty)) {
1173+
auto Decl = BGT->getDecl();
1174+
auto GE = Decl->getGenericEnvironment();
1175+
auto Requirements = BGT->getDecl()
1176+
->getGenericEnvironment()
1177+
->getGenericSignature()
1178+
.getRequirements();
1179+
for (auto Requirement : Requirements) {
1180+
if (Requirement.getKind() == RequirementKind::Conformance) {
1181+
auto ProtocolDecl = Requirement.getProtocolDecl();
1182+
auto ConformingType = Requirement.getFirstType();
1183+
Type Archetype;
1184+
if (auto GTPT = llvm::dyn_cast<GenericTypeParamType>(
1185+
ConformingType.getPointer()))
1186+
Archetype = GE->mapTypeIntoContext(GTPT);
1187+
else if (auto DMT = llvm::dyn_cast<DependentMemberType>(
1188+
ConformingType.getPointer()))
1189+
Archetype = GE->mapTypeIntoContext(DMT);
1190+
1191+
if (Lowering::TypeConverter::protocolRequiresWitnessTable(
1192+
ProtocolDecl) &&
1193+
tryGetLocalTypeData(
1194+
Archetype->getCanonicalType(),
1195+
LocalTypeDataKind::forAbstractProtocolWitnessTable(
1196+
ProtocolDecl))) {
1197+
auto Conformance =
1198+
ProtocolConformanceRef::forAbstract(Archetype, ProtocolDecl);
1199+
1200+
emitWitnessTableRef(*this, Archetype->getCanonicalType(),
1201+
Conformance);
1202+
}
1203+
}
1204+
}
1205+
}
11711206
}
1172-
11731207
/// Emit debug info for a function argument or a local variable.
11741208
template <typename StorageType>
11751209
void emitDebugVariableDeclaration(

lib/IRGen/LocalTypeData.cpp

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -408,26 +408,59 @@ static void maybeEmitDebugInfoForLocalTypeData(IRGenFunction &IGF,
408408
// functions that were inlined into transparent functions. Correct would be to
409409
// check which instruction requests the type metadata and see whether its
410410
// inlined function is transparent.
411-
auto * DS = IGF.getDebugScope();
411+
auto *DS = IGF.getDebugScope();
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+
llvm::SmallString<16> displayName;
437+
if (auto DMT =
438+
llvm::dyn_cast<DependentMemberType>(interfaceType.getPointer())) {
439+
std::function<void(DependentMemberType *)> visitDependentMembers =
440+
[&](DependentMemberType *member) {
441+
if (member == nullptr)
442+
return;
443+
if (auto *parent =
444+
llvm::dyn_cast<DependentMemberType>(member->getBase())) {
445+
visitDependentMembers(parent);
446+
name.append("$");
447+
displayName.append(".");
448+
}
449+
name.append(member->getName().str());
450+
displayName.append(member->getName().str());
451+
};
452+
name.append(DMT->getRootGenericParam()->getCanonicalName().str());
453+
name.append("$");
454+
displayName.append(DMT->getRootGenericParam()->getName().str());
455+
displayName.append(".");
456+
visitDependentMembers(DMT);
457+
} else if (auto GTPT = llvm::dyn_cast<GenericTypeParamType>(
458+
interfaceType.getPointer())) {
459+
name = GTPT->getCanonicalName().str();
460+
displayName = GTPT->getName().str();
461+
} else {
462+
return;
463+
}
431464

432465
llvm::Value *data = value.getMetadata();
433466

@@ -438,7 +471,7 @@ static void maybeEmitDebugInfoForLocalTypeData(IRGenFunction &IGF,
438471
// though; see the comment in IRGenFunctionSIL::emitShadowCopyIfNeeded().
439472
if (!IGF.IGM.IRGen.Opts.shouldOptimize() && !IGF.isAsync()) {
440473
auto alloca =
441-
IGF.createAlloca(data->getType(), IGF.IGM.getPointerAlignment(), name);
474+
IGF.createAlloca(data->getType(), IGF.IGM.getPointerAlignment(), displayName);
442475
IGF.Builder.CreateStore(data, alloca);
443476
data = alloca.getAddress();
444477
}
@@ -447,10 +480,12 @@ static void maybeEmitDebugInfoForLocalTypeData(IRGenFunction &IGF,
447480
if (!IGF.IGM.DebugInfo)
448481
return;
449482

450-
IGF.IGM.DebugInfo->emitTypeMetadata(IGF, data,
451-
typeParam->getDepth(),
452-
typeParam->getIndex(),
453-
name);
483+
if (proto) {
484+
IGF.IGM.DebugInfo->emitWitnessTable(IGF, data, name, proto);
485+
} else {
486+
auto *typeParam = type->getInterfaceType()->castTo<GenericTypeParamType>();
487+
IGF.IGM.DebugInfo->emitTypeMetadata(IGF, data, typeParam);
488+
}
454489
}
455490

456491
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\317\204_0_0$$$s3out1P_pD")
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()

0 commit comments

Comments
 (0)