Skip to content

Commit 07ae73d

Browse files
Merge pull request #9768 from adrian-prantl/140940434
[lldb] Resolve typealias information for assiciated types via reflection
2 parents d3ced1f + a098c18 commit 07ae73d

15 files changed

+345
-49
lines changed

lldb/source/Plugins/LanguageRuntime/Swift/ReflectionContext.cpp

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ struct DescriptorFinderForwarder : public swift::reflection::DescriptorFinder {
8989
/// An implementation of the generic ReflectionContextInterface that
9090
/// is templatized on target pointer width and specialized to either
9191
/// 32-bit or 64-bit pointers, with and without ObjC interoperability.
92-
template <typename ReflectionContext>
92+
template <typename ReflectionContext, bool ObjCEnabled, unsigned PointerSize>
9393
class TargetReflectionContext : public ReflectionContextInterface {
9494
DescriptorFinderForwarder m_forwader;
9595
ReflectionContext m_reflection_ctx;
@@ -313,7 +313,7 @@ class TargetReflectionContext : public ReflectionContextInterface {
313313
}
314314

315315
std::optional<std::pair<const swift::reflection::TypeRef *,
316-
swift::reflection::RemoteAddress>>
316+
swift::reflection::RemoteAddress>>
317317
ProjectExistentialAndUnwrapClass(
318318
swift::reflection::RemoteAddress existential_address,
319319
const swift::reflection::TypeRef &existential_tr,
@@ -323,6 +323,19 @@ class TargetReflectionContext : public ReflectionContextInterface {
323323
existential_address, existential_tr);
324324
}
325325

326+
const swift::reflection::TypeRef *
327+
LookupTypeWitness(const std::string &MangledTypeName,
328+
const std::string &Member, StringRef Protocol) override {
329+
return m_type_converter.getBuilder().lookupTypeWitness(MangledTypeName,
330+
Member, Protocol);
331+
}
332+
swift::reflection::ConformanceCollectionResult GetAllConformances() override {
333+
swift::reflection::TypeRefBuilder &b = m_type_converter.getBuilder();
334+
if (ObjCEnabled)
335+
return b.collectAllConformances<swift::WithObjCInterop, PointerSize>();
336+
return b.collectAllConformances<swift::NoObjCInterop, PointerSize>();
337+
}
338+
326339
const swift::reflection::TypeRef *
327340
ReadTypeFromMetadata(lldb::addr_t metadata_address,
328341
swift::reflection::DescriptorFinder *descriptor_finder,
@@ -420,18 +433,22 @@ std::unique_ptr<ReflectionContextInterface>
420433
ReflectionContextInterface::CreateReflectionContext(
421434
uint8_t ptr_size, std::shared_ptr<swift::remote::MemoryReader> reader,
422435
bool ObjCInterop, SwiftMetadataCache *swift_metadata_cache) {
423-
using ReflectionContext32ObjCInterop =
424-
TargetReflectionContext<swift::reflection::ReflectionContext<
425-
swift::External<swift::WithObjCInterop<swift::RuntimeTarget<4>>>>>;
426-
using ReflectionContext32NoObjCInterop =
427-
TargetReflectionContext<swift::reflection::ReflectionContext<
428-
swift::External<swift::NoObjCInterop<swift::RuntimeTarget<4>>>>>;
429-
using ReflectionContext64ObjCInterop =
430-
TargetReflectionContext<swift::reflection::ReflectionContext<
431-
swift::External<swift::WithObjCInterop<swift::RuntimeTarget<8>>>>>;
432-
using ReflectionContext64NoObjCInterop =
433-
TargetReflectionContext<swift::reflection::ReflectionContext<
434-
swift::External<swift::NoObjCInterop<swift::RuntimeTarget<8>>>>>;
436+
using ReflectionContext32ObjCInterop = TargetReflectionContext<
437+
swift::reflection::ReflectionContext<
438+
swift::External<swift::WithObjCInterop<swift::RuntimeTarget<4>>>>,
439+
true, 4>;
440+
using ReflectionContext32NoObjCInterop = TargetReflectionContext<
441+
swift::reflection::ReflectionContext<
442+
swift::External<swift::NoObjCInterop<swift::RuntimeTarget<4>>>>,
443+
false, 4>;
444+
using ReflectionContext64ObjCInterop = TargetReflectionContext<
445+
swift::reflection::ReflectionContext<
446+
swift::External<swift::WithObjCInterop<swift::RuntimeTarget<8>>>>,
447+
true, 8>;
448+
using ReflectionContext64NoObjCInterop = TargetReflectionContext<
449+
swift::reflection::ReflectionContext<
450+
swift::External<swift::NoObjCInterop<swift::RuntimeTarget<8>>>>,
451+
false, 8>;
435452
if (ptr_size == 4) {
436453
if (ObjCInterop)
437454
return std::make_unique<ReflectionContext32ObjCInterop>(

lldb/source/Plugins/LanguageRuntime/Swift/ReflectionContextInterface.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,11 @@ class ReflectionContextInterface {
130130
const swift::reflection::TypeRef *enum_type_ref,
131131
swift::remote::TypeInfoProvider *provider,
132132
swift::reflection::DescriptorFinder *descriptor_finder) = 0;
133+
virtual const swift::reflection::TypeRef *
134+
LookupTypeWitness(const std::string &MangledTypeName,
135+
const std::string &Member, StringRef Protocol) = 0;
136+
virtual swift::reflection::ConformanceCollectionResult
137+
GetAllConformances() = 0;
133138
virtual const swift::reflection::TypeRef *ReadTypeFromMetadata(
134139
lldb::addr_t metadata_address,
135140
swift::reflection::DescriptorFinder *descriptor_finder,

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "Plugins/ExpressionParser/Swift/SwiftPersistentExpressionState.h"
2020
#include "Plugins/Process/Utility/RegisterContext_x86.h"
2121
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
22+
#include "Plugins/TypeSystem/Swift/SwiftDemangle.h"
2223
#include "Utility/ARM64_DWARF_Registers.h"
2324
#include "lldb/Breakpoint/StoppointCallbackContext.h"
2425
#include "lldb/Core/Debugger.h"
@@ -282,6 +283,11 @@ class SwiftLanguageRuntimeStub {
282283
return false;
283284
}
284285

286+
CompilerType ResolveTypeAlias(CompilerType alias) {
287+
STUB_LOG();
288+
return {};
289+
}
290+
285291
void DumpTyperef(CompilerType type, TypeSystemSwiftTypeRef *module_holder,
286292
Stream *s) {
287293
STUB_LOG();
@@ -523,6 +529,36 @@ SwiftLanguageRuntimeImpl::GetSwiftMetadataCache() {
523529
return &m_swift_metadata_cache;
524530
}
525531

532+
std::vector<std::string>
533+
SwiftLanguageRuntimeImpl::GetConformances(llvm::StringRef mangled_name) {
534+
if (m_conformances.empty()) {
535+
using namespace swift::Demangle;
536+
Demangler dem;
537+
538+
ThreadSafeReflectionContext reflection_ctx = GetReflectionContext();
539+
if (!reflection_ctx)
540+
return {};
541+
542+
Progress progress("Parsing Swift conformances");
543+
swift::reflection::ConformanceCollectionResult conformances =
544+
reflection_ctx->GetAllConformances();
545+
546+
for (auto &conformance : conformances.Conformances) {
547+
auto [mod, proto] = StringRef(conformance.ProtocolName).split('.');
548+
NodePointer n =
549+
swift_demangle::CreateNominal(dem, Node::Kind::Protocol, mod, proto);
550+
auto mangling = mangleNode(n);
551+
if (!mangling.isSuccess())
552+
return {};
553+
llvm::StringRef protocol =
554+
swift::Demangle::dropSwiftManglingPrefix(mangling.result());
555+
556+
m_conformances[mangled_name].push_back(protocol.str());
557+
}
558+
}
559+
return m_conformances.lookup(mangled_name);
560+
}
561+
526562
void SwiftLanguageRuntimeImpl::SetupReflection() {
527563
LLDB_SCOPED_TIMER();
528564

@@ -943,6 +979,9 @@ void SwiftLanguageRuntimeImpl::ModulesDidLoad(const ModuleList &module_list) {
943979
// The modules will be lazily processed on the next call to
944980
// GetReflectionContext.
945981
m_modules_to_add.AppendIfNeeded(module_list);
982+
983+
// This could be done more efficiently with a better reflection API.
984+
m_conformances.clear();
946985
}
947986

948987
std::string
@@ -2399,6 +2438,11 @@ bool SwiftLanguageRuntime::IsStoredInlineInBuffer(CompilerType type) {
23992438
FORWARD(IsStoredInlineInBuffer, type);
24002439
}
24012440

2441+
llvm::Expected<CompilerType>
2442+
SwiftLanguageRuntime::ResolveTypeAlias(CompilerType alias) {
2443+
FORWARD(ResolveTypeAlias, alias);
2444+
}
2445+
24022446
std::optional<uint64_t> SwiftLanguageRuntime::GetMemberVariableOffset(
24032447
CompilerType instance_type, ValueObject *instance,
24042448
llvm::StringRef member_name, Status *error) {

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,9 @@ class SwiftLanguageRuntime : public LanguageRuntime {
329329

330330
bool IsStoredInlineInBuffer(CompilerType type) override;
331331

332+
/// Check if this type alias is listed in any witness tables and resolve it.
333+
llvm::Expected<CompilerType> ResolveTypeAlias(CompilerType alias);
334+
332335
/// Retrieve the offset of the named member variable within an instance
333336
/// of the given type.
334337
///

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ class LLDBTypeInfoProvider : public swift::remote::TypeInfoProvider {
318318
auto *node = dem.demangleSymbol(wrapped);
319319
if (!node) {
320320
// Try `mangledName` as plain ObjC class name. Ex: NSObject, NSView, etc.
321-
auto maybeMangled = swift_demangle::mangleClass(
321+
auto maybeMangled = swift_demangle::MangleClass(
322322
dem, swift::MANGLING_MODULE_OBJC, mangledName);
323323
if (!maybeMangled.isSuccess()) {
324324
LLDB_LOG(GetLog(LLDBLog::Types),
@@ -3037,6 +3037,117 @@ bool SwiftLanguageRuntimeImpl::IsStoredInlineInBuffer(CompilerType type) {
30373037
return true;
30383038
}
30393039

3040+
llvm::Expected<CompilerType>
3041+
SwiftLanguageRuntimeImpl::ResolveTypeAlias(CompilerType alias) {
3042+
using namespace swift::Demangle;
3043+
Demangler dem;
3044+
3045+
auto tss = alias.GetTypeSystem().dyn_cast_or_null<TypeSystemSwift>();
3046+
if (!tss)
3047+
return llvm::createStringError("not a Swift type");
3048+
auto tr_ts = tss->GetTypeSystemSwiftTypeRef();
3049+
if (!tr_ts)
3050+
return llvm::createStringError("could not get typesystem");
3051+
3052+
// Extract the mangling of the alias type's parent type and its
3053+
// generic substitutions if any.
3054+
auto mangled = alias.GetMangledTypeName().GetStringRef();
3055+
NodePointer type = swift_demangle::GetDemangledType(dem, mangled);
3056+
if (!type || type->getKind() != Node::Kind::TypeAlias ||
3057+
type->getNumChildren() != 2)
3058+
return llvm::createStringError("not a type alias");
3059+
3060+
NodePointer alias_node = type->getChild(1);
3061+
if (!alias_node || alias_node->getKind() != Node::Kind::Identifier ||
3062+
!alias_node->hasText())
3063+
return llvm::createStringError("type alias has no name");
3064+
std::string member = alias_node->getText().str();
3065+
3066+
NodePointer parent_node = type->getChild(0);
3067+
if (!parent_node)
3068+
return llvm::createStringError("top-level type alias");
3069+
NodePointer subst_node = nullptr;
3070+
3071+
switch (parent_node->getKind()) {
3072+
case Node::Kind::Class:
3073+
case Node::Kind::Structure:
3074+
case Node::Kind::Enum:
3075+
break;
3076+
// For the lookup, get the unbound type.
3077+
case Node::Kind::BoundGenericClass:
3078+
subst_node =
3079+
swift_demangle::ChildAtPath(parent_node, {Node::Kind::TypeList});
3080+
parent_node = swift_demangle::ChildAtPath(
3081+
parent_node, {Node::Kind::Type, Node::Kind::Class});
3082+
break;
3083+
case Node::Kind::BoundGenericStructure:
3084+
subst_node =
3085+
swift_demangle::ChildAtPath(parent_node, {Node::Kind::TypeList});
3086+
parent_node = swift_demangle::ChildAtPath(
3087+
parent_node, {Node::Kind::Type, Node::Kind::Structure});
3088+
break;
3089+
case Node::Kind::BoundGenericEnum:
3090+
subst_node =
3091+
swift_demangle::ChildAtPath(parent_node, {Node::Kind::TypeList});
3092+
parent_node = swift_demangle::ChildAtPath(
3093+
parent_node, {Node::Kind::Type, Node::Kind::Enum});
3094+
break;
3095+
default:
3096+
return llvm::createStringError("unsupported parent kind");
3097+
}
3098+
if (!parent_node)
3099+
return llvm::createStringError("unsupported generic parent kind");
3100+
3101+
NodePointer global = dem.createNode(Node::Kind::Global);
3102+
global->addChild(parent_node, dem);
3103+
auto mangling = swift::Demangle::mangleNode(global);
3104+
if (!mangling.isSuccess())
3105+
return llvm::createStringError("mangling error");
3106+
std::string in_type =
3107+
swift::Demangle::dropSwiftManglingPrefix(mangling.result()).str();
3108+
3109+
// `in_type` now holds the type alias' parent type.
3110+
// `member` is the name of the type alias.
3111+
// Scan through the witness tables of all of the parent's conformances.
3112+
ThreadSafeReflectionContext reflection_ctx = GetReflectionContext();
3113+
if (!reflection_ctx)
3114+
return llvm::createStringError("no reflection context");
3115+
for (const std::string &protocol : GetConformances(in_type)) {
3116+
auto *type_ref =
3117+
reflection_ctx->LookupTypeWitness(in_type, member, protocol);
3118+
if (!type_ref)
3119+
continue;
3120+
3121+
// Success, we found an associated type in the conformance. If
3122+
// the parent type was generic, the type alias could point to a
3123+
// type parameter. Reapply any substitutions from the parent type.
3124+
if (subst_node) {
3125+
swift::reflection::GenericArgumentMap substitutions;
3126+
unsigned idx = 0;
3127+
for (auto &child : *subst_node) {
3128+
auto mangling = swift_demangle::GetMangledName(dem, child);
3129+
if (!mangling.isSuccess())
3130+
continue;
3131+
const auto *type_ref = reflection_ctx->GetTypeRefOrNull(
3132+
mangling.result(), tr_ts->GetDescriptorFinder());
3133+
if (!type_ref)
3134+
continue;
3135+
3136+
substitutions.insert({{0, idx++}, type_ref});
3137+
}
3138+
type_ref = reflection_ctx->ApplySubstitutions(
3139+
type_ref, substitutions, tr_ts->GetDescriptorFinder());
3140+
}
3141+
3142+
CompilerType resolved = GetTypeFromTypeRef(*tr_ts, type_ref);
3143+
LLDB_LOG(GetLog(LLDBLog::Types),
3144+
"Resolved type alias {0} = {1} using reflection metadata.",
3145+
alias.GetMangledTypeName(), resolved.GetMangledTypeName());
3146+
return resolved;
3147+
}
3148+
return llvm::createStringError("cannot resolve type alias via reflection");
3149+
}
3150+
30403151
std::optional<uint64_t>
30413152
SwiftLanguageRuntimeImpl::GetBitSize(CompilerType type,
30423153
ExecutionContextScope *exe_scope) {

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeImpl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ class SwiftLanguageRuntimeImpl {
102102
llvm::ArrayRef<swift::reflection::FieldInfo> fields);
103103

104104
bool IsStoredInlineInBuffer(CompilerType type);
105+
llvm::Expected<CompilerType> ResolveTypeAlias(CompilerType alias);
105106

106107
/// Ask Remote Mirrors for the size of a Swift type.
107108
std::optional<uint64_t> GetBitSize(CompilerType type,
@@ -357,6 +358,8 @@ class SwiftLanguageRuntimeImpl {
357358

358359
CompilerType m_box_metadata_type;
359360

361+
llvm::StringMap<std::vector<std::string>> m_conformances;
362+
360363
private:
361364
/// Don't call these directly.
362365
/// \{
@@ -385,6 +388,9 @@ class SwiftLanguageRuntimeImpl {
385388

386389
SwiftMetadataCache *GetSwiftMetadataCache();
387390

391+
/// Find all conformances for a nominal type in the reflection metadata.
392+
std::vector<std::string> GetConformances(llvm::StringRef mangled_name);
393+
388394
/// These members are used to track and toggle the state of the "dynamic
389395
/// exclusivity enforcement flag" in the swift runtime. This flag is set to
390396
/// true when an LLDB expression starts running, and reset to its original

lldb/source/Plugins/TypeSystem/Swift/SwiftDemangle.h

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -97,30 +97,48 @@ GetDemangledTypeMangling(swift::Demangle::Demangler &dem,
9797
}
9898

9999
/// Wrap node in Global/TypeMangling/Type.
100-
static swift::Demangle::NodePointer
101-
mangleType(swift::Demangle::Demangler &dem,
102-
swift::Demangle::NodePointer typeNode) {
100+
inline swift::Demangle::NodePointer
101+
MangleType(swift::Demangle::Demangler &dem,
102+
swift::Demangle::NodePointer type_node) {
103103
auto *global = dem.createNode(Node::Kind::Global);
104-
auto *typeMangling = dem.createNode(Node::Kind::TypeMangling);
105-
global->addChild(typeMangling, dem);
104+
auto *type_mangling = dem.createNode(Node::Kind::TypeMangling);
105+
global->addChild(type_mangling, dem);
106106
auto *type = dem.createNode(Node::Kind::Type);
107-
typeMangling->addChild(type, dem);
108-
type->addChild(typeNode, dem);
107+
type_mangling->addChild(type, dem);
108+
type->addChild(type_node, dem);
109109
return global;
110110
}
111111

112+
/// Produce a type mangle tree for a nominal type.
113+
inline swift::Demangle::NodePointer
114+
CreateNominal(swift::Demangle::Demangler &dem, swift::Demangle::Node::Kind kind,
115+
llvm::StringRef module_name, llvm::StringRef type_name) {
116+
auto *nominal = dem.createNode(kind);
117+
auto *m = dem.createNodeWithAllocatedText(Node::Kind::Module, module_name);
118+
auto *id = dem.createNodeWithAllocatedText(Node::Kind::Identifier, type_name);
119+
nominal->addChild(m, dem);
120+
nominal->addChild(id, dem);
121+
return nominal;
122+
}
123+
112124
/// Produce a type mangling for a class.
113-
inline ManglingErrorOr<std::string> mangleClass(swift::Demangle::Demangler &dem,
114-
llvm::StringRef moduleName,
115-
llvm::StringRef className) {
116-
auto *classNode = dem.createNode(Node::Kind::Class);
117-
auto *module =
118-
dem.createNodeWithAllocatedText(Node::Kind::Module, moduleName);
119-
auto *identifier =
120-
dem.createNodeWithAllocatedText(Node::Kind::Identifier, className);
121-
classNode->addChild(module, dem);
122-
classNode->addChild(identifier, dem);
123-
return mangleNode(mangleType(dem, classNode));
125+
inline ManglingErrorOr<std::string> MangleClass(swift::Demangle::Demangler &dem,
126+
llvm::StringRef module_name,
127+
llvm::StringRef class_name) {
128+
auto *node = CreateNominal(dem, Node::Kind::Class, module_name, class_name);
129+
return mangleNode(MangleType(dem, node));
130+
}
131+
132+
/// Create a mangled name for a type node.
133+
inline swift::Demangle::ManglingErrorOr<std::string>
134+
GetMangledName(swift::Demangle::Demangler &dem,
135+
swift::Demangle::NodePointer node) {
136+
using namespace swift::Demangle;
137+
auto global = dem.createNode(Node::Kind::Global);
138+
auto type_mangling = dem.createNode(Node::Kind::TypeMangling);
139+
global->addChild(type_mangling, dem);
140+
type_mangling->addChild(node, dem);
141+
return mangleNode(global);
124142
}
125143

126144
} // namespace swift_demangle

0 commit comments

Comments
 (0)