[lldb] Add SBType::FindDirectNestedType() function (#68705)

This patch adds a `SBType::FindDirectNestedType(name)` function which performs a non-recursive search in given class for a type with specified name. The intent is to perform a fast search in debug info, so that it can be used in formatters, and let them remain responsive.

This is driven by my work on formatters for Clang and LLVM types. In particular, by [`PointerIntPairInfo::MaskAndShiftConstants`](cde9f9df79/llvm/include/llvm/ADT/PointerIntPair.h (L174C16-L174C16)), which is required to extract pointer and integer from `PointerIntPair`.

Related Discourse thread: https://discourse.llvm.org/t/traversing-member-types-of-a-type/72452
This commit is contained in:
Vlad Serebrennikov 2023-10-14 10:52:34 +04:00 committed by GitHub
parent 02f67c097d
commit 93229c7bfd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 96 additions and 0 deletions

View File

@ -720,6 +720,14 @@ SBType supports the eq/ne operator. For example,::
"
) lldb::SBType::GetTypeFlags;
%feature("docstring",
"Searches for a directly nested type that has the provided name.
Returns the type if it was found.
Returns invalid type if nothing was found.
"
) lldb::SBType::FindDirectNestedType;
%feature("docstring",
"Represents a list of :py:class:`SBType` s.

View File

@ -215,6 +215,8 @@ public:
bool GetDescription(lldb::SBStream &description,
lldb::DescriptionLevel description_level);
lldb::SBType FindDirectNestedType(const char *name);
lldb::SBType &operator=(const lldb::SBType &rhs);
bool operator==(lldb::SBType &rhs);

View File

@ -304,6 +304,8 @@ public:
bool GetDescription(lldb_private::Stream &strm,
lldb::DescriptionLevel description_level);
CompilerType FindDirectNestedType(llvm::StringRef name);
private:
bool CheckModule(lldb::ModuleSP &module_sp) const;
bool CheckExeModule(lldb::ModuleSP &module_sp) const;

View File

@ -142,6 +142,10 @@ public:
virtual lldb::LanguageType DeclContextGetLanguage(void *opaque_decl_ctx) = 0;
/// Returns the direct parent context of specified type
virtual CompilerDeclContext
GetCompilerDeclContextForType(const CompilerType &type);
// Tests
#ifndef NDEBUG
/// Verify the integrity of the type to catch CompilerTypes that mix

View File

@ -586,6 +586,14 @@ lldb::TemplateArgumentKind SBType::GetTemplateArgumentKind(uint32_t idx) {
return eTemplateArgumentKindNull;
}
SBType SBType::FindDirectNestedType(const char *name) {
LLDB_INSTRUMENT_VA(this, name);
if (!IsValid())
return SBType();
return SBType(m_opaque_sp->FindDirectNestedType(name));
}
SBTypeList::SBTypeList() : m_opaque_up(new TypeListImpl()) {
LLDB_INSTRUMENT_VA(this);
}

View File

@ -2637,6 +2637,13 @@ TypeSystemClang::GetDeclContextForType(const CompilerType &type) {
return GetDeclContextForType(ClangUtil::GetQualType(type));
}
CompilerDeclContext
TypeSystemClang::GetCompilerDeclContextForType(const CompilerType &type) {
if (auto *decl_context = GetDeclContextForType(type))
return CreateDeclContext(decl_context);
return CompilerDeclContext();
}
/// Aggressively desugar the provided type, skipping past various kinds of
/// syntactic sugar and other constructs one typically wants to ignore.
/// The \p mask argument allows one to skip certain kinds of simplifications,

View File

@ -219,6 +219,9 @@ public:
static clang::DeclContext *GetDeclContextForType(const CompilerType &type);
CompilerDeclContext
GetCompilerDeclContextForType(const CompilerType &type) override;
uint32_t GetPointerByteSize() override;
clang::TranslationUnitDecl *GetTranslationUnitDecl() {

View File

@ -1040,6 +1040,23 @@ bool TypeImpl::GetDescription(lldb_private::Stream &strm,
return true;
}
CompilerType TypeImpl::FindDirectNestedType(llvm::StringRef name) {
if (name.empty())
return CompilerType();
auto type_system = GetTypeSystem(/*prefer_dynamic*/ false);
auto *symbol_file = type_system->GetSymbolFile();
auto decl_context = type_system->GetCompilerDeclContextForType(m_static_type);
if (!decl_context.IsValid())
return CompilerType();
llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
TypeMap search_result;
symbol_file->FindTypes(ConstString(name), decl_context, /*max_matches*/ 1,
searched_symbol_files, search_result);
if (search_result.Empty())
return CompilerType();
return search_result.GetTypeAtIndex(0)->GetFullCompilerType();
}
bool TypeMemberFunctionImpl::IsValid() {
return m_type.IsValid() && m_kind != lldb::eMemberFunctionKindUnknown;
}

View File

@ -186,6 +186,11 @@ std::optional<llvm::json::Value> TypeSystem::ReportStatistics() {
return std::nullopt;
}
CompilerDeclContext
TypeSystem::GetCompilerDeclContextForType(const CompilerType &type) {
return CompilerDeclContext();
}
#pragma mark TypeSystemMap
TypeSystemMap::TypeSystemMap() : m_mutex(), m_map() {}

View File

@ -119,6 +119,37 @@ class TypeAndTypeListTestCase(TestBase):
self.assertEqual(task_type, task_head_pointee_type)
# Check whether we can find a directly nested type by name
name_type = task_type.FindDirectNestedType("name")
self.assertTrue(name_type)
self.DebugSBType(name_type)
enum_type = task_type.FindDirectNestedType("E")
self.assertTrue(enum_type)
self.DebugSBType(enum_type)
union_type = task_type.FindDirectNestedType("U")
self.assertTrue(union_type)
self.DebugSBType(union_type)
# Check that we don't find indirectly nested types
self.assertTrue(enum_type.size == 1)
invalid_type = task_type.FindDirectNestedType("E2")
self.assertFalse(invalid_type)
# Check that FindDirectNestedType handles types without DeclContext
# and other errorneous inputs
task_ptr_type = task_type.GetPointerType()
invalid_type = task_ptr_type.FindDirectNestedType("name")
self.assertFalse(invalid_type)
invalid_type = task_type.FindDirectNestedType("")
self.assertFalse(invalid_type)
invalid_type = task_type.FindDirectNestedType(None)
self.assertFalse(invalid_type)
# We'll now get the child member 'id' from 'task_head'.
id = task_head.GetChildMemberWithName("id")
self.DebugSBValue(id)

View File

@ -21,7 +21,12 @@ public:
} my_type_is_nameless;
struct name {
int x;
enum E : int {} e;
enum E2 {} e2;
} my_type_is_named;
enum E : unsigned char {} e;
union U {
} u;
Task(int i, Task *n):
id(i),
next(n),

View File

@ -191,6 +191,10 @@ Changes to LLDB
* Methods in SBHostOS related to threads have had their implementations
removed. These methods will return a value indicating failure.
* ``SBType::FindDirectNestedType`` function is added. It's useful
for formatters to quickly find directly nested type when it's known
where to search for it, avoiding more expensive global search via
``SBTarget::FindFirstType``.
Changes to Sanitizers
---------------------