[llvm] 93229c7 - [lldb] Add SBType::FindDirectNestedType() function (#68705)

via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 13 23:52:39 PDT 2023


Author: Vlad Serebrennikov
Date: 2023-10-14T10:52:34+04:00
New Revision: 93229c7bfd97429aa0ac55b45e618bdb013702b2

URL: https://github.com/llvm/llvm-project/commit/93229c7bfd97429aa0ac55b45e618bdb013702b2
DIFF: https://github.com/llvm/llvm-project/commit/93229c7bfd97429aa0ac55b45e618bdb013702b2.diff

LOG: [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`](https://github.com/llvm/llvm-project/blob/cde9f9df79805a0850310870d6dcc64004292727/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

Added: 
    

Modified: 
    lldb/bindings/interface/SBTypeDocstrings.i
    lldb/include/lldb/API/SBType.h
    lldb/include/lldb/Symbol/Type.h
    lldb/include/lldb/Symbol/TypeSystem.h
    lldb/source/API/SBType.cpp
    lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
    lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
    lldb/source/Symbol/Type.cpp
    lldb/source/Symbol/TypeSystem.cpp
    lldb/test/API/python_api/type/TestTypeList.py
    lldb/test/API/python_api/type/main.cpp
    llvm/docs/ReleaseNotes.rst

Removed: 
    


################################################################################
diff  --git a/lldb/bindings/interface/SBTypeDocstrings.i b/lldb/bindings/interface/SBTypeDocstrings.i
index 96421a6aa20104b..c49e9647ba0463c 100644
--- a/lldb/bindings/interface/SBTypeDocstrings.i
+++ b/lldb/bindings/interface/SBTypeDocstrings.i
@@ -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.
 

diff  --git a/lldb/include/lldb/API/SBType.h b/lldb/include/lldb/API/SBType.h
index 5962f0c50dee14f..9980fe1218305bb 100644
--- a/lldb/include/lldb/API/SBType.h
+++ b/lldb/include/lldb/API/SBType.h
@@ -215,6 +215,8 @@ class SBType {
   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);

diff  --git a/lldb/include/lldb/Symbol/Type.h b/lldb/include/lldb/Symbol/Type.h
index d7bccae5f413511..c505262cd9eaecf 100644
--- a/lldb/include/lldb/Symbol/Type.h
+++ b/lldb/include/lldb/Symbol/Type.h
@@ -304,6 +304,8 @@ class TypeImpl {
   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;

diff  --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h
index 56acb1db1546a22..5ac16be3347ff89 100644
--- a/lldb/include/lldb/Symbol/TypeSystem.h
+++ b/lldb/include/lldb/Symbol/TypeSystem.h
@@ -142,6 +142,10 @@ class TypeSystem : public PluginInterface,
 
   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

diff  --git a/lldb/source/API/SBType.cpp b/lldb/source/API/SBType.cpp
index ee5b6447428098e..ac0e56303fae3ef 100644
--- a/lldb/source/API/SBType.cpp
+++ b/lldb/source/API/SBType.cpp
@@ -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);
 }

diff  --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index bcf4b624780681b..f1353db2631ddc6 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -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,

diff  --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
index 7805be92ec1365e..66e59ec985fb890 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
@@ -219,6 +219,9 @@ class TypeSystemClang : public TypeSystem {
 
   static clang::DeclContext *GetDeclContextForType(const CompilerType &type);
 
+  CompilerDeclContext
+  GetCompilerDeclContextForType(const CompilerType &type) override;
+
   uint32_t GetPointerByteSize() override;
 
   clang::TranslationUnitDecl *GetTranslationUnitDecl() {

diff  --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp
index 5f4c6303334a255..548300d5709533c 100644
--- a/lldb/source/Symbol/Type.cpp
+++ b/lldb/source/Symbol/Type.cpp
@@ -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;
 }

diff  --git a/lldb/source/Symbol/TypeSystem.cpp b/lldb/source/Symbol/TypeSystem.cpp
index 24f20293056501f..874f12573eca3f0 100644
--- a/lldb/source/Symbol/TypeSystem.cpp
+++ b/lldb/source/Symbol/TypeSystem.cpp
@@ -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() {}

diff  --git a/lldb/test/API/python_api/type/TestTypeList.py b/lldb/test/API/python_api/type/TestTypeList.py
index c2fcadc46ec1531..c267defb58edf9a 100644
--- a/lldb/test/API/python_api/type/TestTypeList.py
+++ b/lldb/test/API/python_api/type/TestTypeList.py
@@ -119,6 +119,37 @@ def test(self):
 
         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)

diff  --git a/lldb/test/API/python_api/type/main.cpp b/lldb/test/API/python_api/type/main.cpp
index b1ef625283855b5..98de9707d886540 100644
--- a/lldb/test/API/python_api/type/main.cpp
+++ b/lldb/test/API/python_api/type/main.cpp
@@ -21,7 +21,12 @@ class Task {
     } 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),

diff  --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index 3453c7e61ae4a63..467b4b5320ad9f3 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -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
 ---------------------


        


More information about the llvm-commits mailing list