Skip to content

Commit c7c963a

Browse files
Merge pull request #8465 from augusto2112/build-decl-context
[lldb] Build DeclContext vector from a Swift demangle tree
2 parents 3b959ba + 08e70a2 commit c7c963a

File tree

6 files changed

+389
-84
lines changed

6 files changed

+389
-84
lines changed

lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp

Lines changed: 208 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -473,11 +473,109 @@ TypeSystemSwiftTypeRef::GetClangTypeNode(CompilerType clang_type,
473473
return pointee ? GetPointerTo(dem, nominal) : nominal;
474474
}
475475

476-
/// Return a pair of modulename, type name for the outermost nominal type.
477-
static std::optional<std::pair<StringRef, StringRef>>
478-
GetNominal(swift::Demangle::Demangler &dem, swift::Demangle::NodePointer node) {
476+
bool
477+
TypeSystemSwiftTypeRef::IsBuiltinType(CompilerType type) {
478+
assert(type.GetTypeSystem().isa_and_nonnull<TypeSystemSwift>() &&
479+
"Unexpected type system!");
480+
Demangler dem;
481+
auto *node = GetDemangledType(dem, type.GetMangledTypeName());
479482
if (!node)
483+
return false;
484+
return node->getKind() == Node::Kind::BuiltinTypeName;
485+
}
486+
487+
std::optional<std::pair<NodePointer, NodePointer>>
488+
ExtractTypeNode(NodePointer node) {
489+
// A type node is expected to have two children.
490+
if (node->getNumChildren() != 2)
491+
return {};
492+
493+
auto *first = node->getChild(0);
494+
auto *second = node->getChild(1);
495+
496+
// The second child of a type node is expected to be its identifier.
497+
if (second->getKind() != Node::Kind::Identifier)
498+
return {};
499+
return {{first, second}};
500+
}
501+
502+
static std::optional<llvm::StringRef>
503+
ExtractIdentifierFromLocalDeclName(NodePointer node) {
504+
assert(node->getKind() == Node::Kind::LocalDeclName &&
505+
"Expected LocalDeclName node!");
506+
507+
if (node->getNumChildren() != 2) {
508+
assert(false && "Local decl name node should have 2 children!");
509+
return {};
510+
}
511+
512+
auto *first = node->getChild(0);
513+
auto *second = node->getChild(1);
514+
515+
assert(first->getKind() == Node::Kind::Number && "Expected number node!");
516+
517+
if (second->getKind() == Node::Kind::Identifier) {
518+
if (!second->hasText()) {
519+
assert(false && "Identifier should have text!");
520+
return {};
521+
}
522+
return second->getText();
523+
}
524+
assert(false && "Expected second child of local decl name to be its "
525+
"identifier!");
526+
return {};
527+
}
528+
529+
static std::optional<std::pair<StringRef, StringRef>>
530+
ExtractIdentifiersFromPrivateDeclName(NodePointer node) {
531+
assert(node->getKind() == Node::Kind::PrivateDeclName && "Expected PrivateDeclName node!");
532+
533+
if (node->getNumChildren() != 2) {
534+
assert(false && "Private decl name node should have 2 children!");
535+
return {};
536+
}
537+
538+
auto *private_discriminator = node->getChild(0);
539+
auto *type_name = node->getChild(1);
540+
541+
if (private_discriminator->getKind() != Node::Kind::Identifier) {
542+
assert(
543+
false &&
544+
"Expected first child of private decl name node to be an identifier!");
480545
return {};
546+
}
547+
if (type_name->getKind() != Node::Kind::Identifier) {
548+
assert(
549+
false &&
550+
"Expected second child of private decl name node to be an identifier!");
551+
return {};
552+
}
553+
554+
if (!private_discriminator->hasText() || !type_name->hasText()) {
555+
assert(false && "Identifier nodes should have text!");
556+
return {};
557+
}
558+
559+
return {{private_discriminator->getText(), type_name->getText()}};
560+
}
561+
/// Builds the decl context of a given node. The decl context is the context in
562+
/// where this type is defined. For example, give a module A with the following
563+
/// code:
564+
///
565+
/// struct B {
566+
/// class C {
567+
/// ...
568+
/// }
569+
/// }
570+
///
571+
/// The decl context of C would be:
572+
/// <Module A>
573+
/// <AnyType B>
574+
/// <AnyType C>
575+
static bool BuildDeclContext(swift::Demangle::NodePointer node,
576+
std::vector<CompilerContext> &context) {
577+
if (!node)
578+
return false;
481579
using namespace swift::Demangle;
482580
switch (node->getKind()) {
483581
case Node::Kind::Structure:
@@ -489,14 +587,34 @@ GetNominal(swift::Demangle::Demangler &dem, swift::Demangle::NodePointer node) {
489587
case Node::Kind::ProtocolListWithAnyObject:
490588
case Node::Kind::TypeAlias: {
491589
if (node->getNumChildren() != 2)
492-
return {};
493-
auto *m = node->getChild(0);
494-
if (!m || m->getKind() != Node::Kind::Module || !m->hasText())
495-
return {};
496-
auto *n = node->getChild(1);
497-
if (!n || n->getKind() != Node::Kind::Identifier || !n->hasText())
498-
return {};
499-
return {{m->getText(), n->getText()}};
590+
return false;
591+
auto *first = node->getChild(0);
592+
if (!first)
593+
return false;
594+
if (first->getKind() == Node::Kind::Module) {
595+
assert(first->hasText() && "Module node should have text!");
596+
context.push_back(
597+
{CompilerContextKind::Module, ConstString(first->getText())});
598+
} else {
599+
// If the node's kind is not a module, this is probably a nested type, so
600+
// build the decl context for the parent type first.
601+
if (!BuildDeclContext(first, context))
602+
return false;
603+
}
604+
605+
auto *second = node->getChild(1);
606+
if (!second)
607+
return false;
608+
609+
if (second->getKind() == Node::Kind::Identifier) {
610+
assert(second->hasText() && "Identifier node should have text!");
611+
context.push_back(
612+
{CompilerContextKind::AnyType, ConstString(second->getText())});
613+
return true;
614+
}
615+
// If the second child is not an identifier, it could be a private decl
616+
// name or a local decl name.
617+
return BuildDeclContext(second, context);
500618
}
501619
case Node::Kind::BoundGenericClass:
502620
case Node::Kind::BoundGenericEnum:
@@ -509,36 +627,91 @@ GetNominal(swift::Demangle::Demangler &dem, swift::Demangle::NodePointer node) {
509627
auto *type = node->getChild(0);
510628
if (!type || type->getKind() != Node::Kind::Type || !type->hasChildren())
511629
return {};
512-
return GetNominal(dem, type->getFirstChild());
630+
return BuildDeclContext(type->getFirstChild(), context);
631+
}
632+
case Node::Kind::Function: {
633+
if (node->getNumChildren() != 3)
634+
return false;
635+
636+
auto *first = node->getChild(0);
637+
auto *second = node->getChild(1);
638+
639+
if (first->getKind() == Node::Kind::Module) {
640+
if (!first->hasText()) {
641+
assert(false && "Module should have text!");
642+
return false;
643+
}
644+
context.push_back(
645+
{CompilerContextKind::Module, ConstString(first->getText())});
646+
} else if (!BuildDeclContext(first, context))
647+
return false;
648+
649+
if (second->getKind() == Node::Kind::Identifier) {
650+
if (!second->hasText()) {
651+
assert(false && "Identifier should have text!");
652+
return false;
653+
}
654+
context.push_back(
655+
{CompilerContextKind::Function, ConstString(second->getText())});
656+
} else if (!BuildDeclContext(second, context))
657+
return false;
658+
659+
return true;
660+
}
661+
case Node::Kind::LocalDeclName: {
662+
std::optional<llvm::StringRef> identifier =
663+
ExtractIdentifierFromLocalDeclName(node);
664+
if (!identifier)
665+
return false;
666+
667+
context.push_back(
668+
{CompilerContextKind::AnyDeclContext, ConstString(*identifier)});
669+
return true;
670+
}
671+
672+
case Node::Kind::PrivateDeclName: {
673+
auto discriminator_and_type_name =
674+
ExtractIdentifiersFromPrivateDeclName(node);
675+
676+
if (!discriminator_and_type_name)
677+
return false;
678+
auto &[private_discriminator, type_name] = *discriminator_and_type_name;
679+
680+
context.push_back(
681+
{CompilerContextKind::Namespace, ConstString(private_discriminator)});
682+
context.push_back(
683+
{CompilerContextKind::AnyDeclContext, ConstString(type_name)});
684+
return true;
513685
}
514686
default:
515687
break;
516688
}
517-
return {};
518-
}
519-
520-
bool
521-
TypeSystemSwiftTypeRef::IsBuiltinType(CompilerType type) {
522-
assert(type.GetTypeSystem().isa_and_nonnull<TypeSystemSwift>() &&
523-
"Unexpected type system!");
524-
Demangler dem;
525-
auto *node = GetDemangledType(dem, type.GetMangledTypeName());
526-
if (!node)
527-
return false;
528-
return node->getKind() == Node::Kind::BuiltinTypeName;
689+
return false;
529690
}
530691

531-
/// Return a pair of module name and type name, given a mangled name.
532-
static std::optional<std::pair<StringRef, StringRef>>
533-
GetNominal(llvm::StringRef mangled_name, swift::Demangle::Demangler &dem) {
692+
/// Builds the decl context of a given swift type. See the documentation in the
693+
/// other implementation of BuildDeclContext for more details.
694+
static std::optional<std::vector<CompilerContext>>
695+
BuildDeclContext(llvm::StringRef mangled_name,
696+
swift::Demangle::Demangler &dem) {
697+
std::vector<CompilerContext> context;
534698
auto *node = GetDemangledType(dem, mangled_name);
699+
535700
/// Builtin names belong to the builtin module, and are stored only with their
536701
/// mangled name.
537-
if (node->getKind() == Node::Kind::BuiltinTypeName)
538-
return {{"Builtin", mangled_name}};
702+
if (node->getKind() == Node::Kind::BuiltinTypeName) {
703+
context.push_back({CompilerContextKind::Module, ConstString("Builtin")});
704+
context.push_back(
705+
{CompilerContextKind::AnyType, ConstString(mangled_name)});
706+
return std::move(context);
707+
}
539708

540-
return GetNominal(dem, node);
709+
auto success = BuildDeclContext(node, context);
710+
if (success)
711+
return std::move(context);
712+
return {};
541713
}
714+
542715
/// Detect the AnyObject type alias.
543716
static bool IsAnyObjectTypeAlias(swift::Demangle::NodePointer node) {
544717
using namespace swift::Demangle;
@@ -630,10 +803,6 @@ TypeSystemSwiftTypeRef::ResolveTypeAlias(swift::Demangle::Demangler &dem,
630803
ConstString mangled(mangling.result());
631804

632805
auto resolve_clang_type = [&]() -> CompilerType {
633-
auto maybe_module_and_type_names = GetNominal(dem, node);
634-
if (!maybe_module_and_type_names)
635-
return {};
636-
637806
// This is an imported Objective-C type; look it up in the debug info.
638807
llvm::SmallVector<CompilerContext, 2> decl_context;
639808
if (!IsClangImportedType(node, decl_context))
@@ -1885,20 +2054,14 @@ TypeSystemSwiftTypeRef::FindTypeInModule(opaque_compiler_type_t opaque_type) {
18852054
return {};
18862055

18872056
swift::Demangle::Demangler dem;
1888-
auto module_type = GetNominal(AsMangledName(opaque_type), dem);
1889-
if (!module_type)
2057+
auto context = BuildDeclContext(AsMangledName(opaque_type), dem);
2058+
if (!context)
18902059
return {};
18912060
// DW_AT_linkage_name is not part of the accelerator table, so
1892-
// we need to search by module+name.
1893-
ConstString module(module_type->first);
1894-
ConstString type(module_type->second);
1895-
llvm::SmallVector<CompilerContext, 2> decl_context;
1896-
if (!module.IsEmpty())
1897-
decl_context.push_back({CompilerContextKind::Module, module});
1898-
decl_context.push_back({CompilerContextKind::AnyType, type});
2061+
// we need to search by decl context.
18992062

1900-
TypeQuery query(decl_context, TypeQueryOptions::e_find_one |
1901-
TypeQueryOptions::e_module_search);
2063+
TypeQuery query(*context, TypeQueryOptions::e_find_one |
2064+
TypeQueryOptions::e_module_search);
19022065
query.SetLanguages(TypeSystemSwift::GetSupportedLanguagesForTypes());
19032066

19042067
TypeResults results;

lldb/test/API/lang/swift/embedded/frame_variable/TestSwiftEmbeddedFrameVariable.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,4 +178,34 @@ def implementation(self):
178178
lldbutil.check_variable(self, second, False, value="315")
179179
u = right.GetChildMemberWithName("u")
180180
two = u.GetChildMemberWithName("two")
181-
lldbutil.check_variable(self, two, False, value="one")
181+
lldbutil.check_variable(self, two, False, value='one')
182+
183+
inner = frame.FindVariable("inner")
184+
value = inner.GetChildMemberWithName("value")
185+
lldbutil.check_variable(self, value, False, value='99')
186+
187+
innerer = frame.FindVariable("innerer")
188+
innererValue = innerer.GetChildMemberWithName("innererValue")
189+
lldbutil.check_variable(self, innererValue, False, value='101')
190+
191+
privateType = frame.FindVariable("privateType")
192+
privateField = privateType.GetChildMemberWithName("privateField")
193+
lldbutil.check_variable(self, privateField, False, value='100')
194+
195+
specializedInner = frame.FindVariable("specializedInner")
196+
t = specializedInner.GetChildMemberWithName("t")
197+
lldbutil.check_variable(self, t, False, value='837')
198+
199+
genericInner = frame.FindVariable("genericInner")
200+
t = genericInner.GetChildMemberWithName("t")
201+
lldbutil.check_variable(self, t, False, value='647')
202+
u = genericInner.GetChildMemberWithName("u")
203+
lldbutil.check_variable(self, u, False, value='674.5')
204+
205+
functionType = frame.FindVariable("functionType")
206+
funcField = functionType.GetChildMemberWithName("funcField")
207+
lldbutil.check_variable(self, funcField, False, value='67')
208+
209+
innerFunctionType = frame.FindVariable("innerFunctionType")
210+
innerFuncField = innerFunctionType.GetChildMemberWithName("innerFuncField")
211+
lldbutil.check_variable(self, innerFuncField, False, value='8479')

0 commit comments

Comments
 (0)