[llvm] [lldb] [DoNotMerge] DW_IDX_parent full implementation (PR #77121)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 5 09:23:53 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: Felipe de Azevedo Piovezan (felipepiovezan)

<details>
<summary>Changes</summary>

https://discourse.llvm.org/t/rfc-improve-dwarf-5-debug-names-type-lookup-parsing-speed/74151

---

Patch is 52.45 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/77121.diff


25 Files Affected:

- (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp (+7) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h (+5) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp (+6) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h (+5) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp (+20) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h (+14) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp (+8) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h (+5) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp (+96) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h (+9) 
- (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (+2-7) 
- (modified) lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp (+109) 
- (modified) llvm/include/llvm/CodeGen/AccelTable.h (+25-9) 
- (modified) llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h (+17) 
- (modified) llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp (+107-20) 
- (modified) llvm/lib/DWARFLinker/DWARFLinker.cpp (+8) 
- (modified) llvm/lib/DWARFLinkerParallel/DWARFLinkerImpl.cpp (+2-1) 
- (modified) llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp (+15) 
- (modified) llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp (+15-1) 
- (added) llvm/test/CodeGen/X86/dwarf-headers.o () 
- (modified) llvm/test/DebugInfo/X86/debug-names-dwarf64.ll (+12-4) 
- (modified) llvm/test/DebugInfo/X86/debug-names-end-of-list.ll (+4-2) 
- (modified) llvm/test/DebugInfo/X86/debug-names-types.ll (+39-19) 
- (modified) llvm/test/tools/dsymutil/ARM/accel-imported-declarations.test (+2) 
- (modified) llvm/test/tools/dsymutil/ARM/dwarf5-dwarf4-combination-macho.test (+8-4) 


``````````diff
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
index 553b6a4c551d20..775b7a2e73f512 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
@@ -191,3 +191,10 @@ DWARFDebugInfo::GetDIE(const DIERef &die_ref) {
     return cu->GetNonSkeletonUnit().GetDIE(die_ref.die_offset());
   return DWARFDIE(); // Not found
 }
+
+llvm::StringRef
+DWARFDebugInfo::PeekDIEName(const DIERef &die_ref) {
+  if(DWARFUnit *cu = GetUnit(die_ref))
+    return cu->GetNonSkeletonUnit().PeekDIEName(die_ref.die_offset());
+  return llvm::StringRef();
+}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
index d5e48f312ea0e9..a8b5abc3beed2d 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
@@ -43,6 +43,11 @@ class DWARFDebugInfo {
   bool ContainsTypeUnits();
   DWARFDIE GetDIE(const DIERef &die_ref);
 
+  /// Returns the AT_Name of this DIE, if it exists, without parsing the entire
+  /// compile unit. An empty is string is returned upon error or if the
+  /// attribute is not present.
+  llvm::StringRef PeekDIEName(const DIERef &die_ref);
+
   enum {
     eDumpFlag_Verbose = (1 << 0),  // Verbose dumping
     eDumpFlag_ShowForm = (1 << 1), // Show the DW_form type
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp
index 44421c0eda3eec..3cdb47d50bbfc0 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp
@@ -55,6 +55,12 @@ const char *DWARFDeclContext::GetQualifiedName() const {
   return m_qualified_name.c_str();
 }
 
+llvm::SmallVector<llvm::StringRef>
+DWARFDeclContext::GetQualifiedNameAsVector() const {
+  return llvm::to_vector_of<llvm::StringRef>(
+      llvm::map_range(m_entries, GetName));
+}
+
 bool DWARFDeclContext::operator==(const DWARFDeclContext &rhs) const {
   if (m_entries.size() != rhs.m_entries.size())
     return false;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
index a20a862d340296..40ebb72c91d8f0 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
@@ -68,6 +68,11 @@ class DWARFDeclContext {
 
   const char *GetQualifiedName() const;
 
+  /// Returns a vector of string, one string per entry in the fully qualified
+  /// name. For example, for the name `A::B::C`, this methods returns `{"A",
+  /// "B", "C"}`
+  llvm::SmallVector<llvm::StringRef> GetQualifiedNameAsVector() const;
+
   // Same as GetQualifiedName, but the life time of the returned string will
   // be that of the LLDB session.
   ConstString GetQualifiedNameAsConstString() const {
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
index b1c323b101cef3..20c07a94b50769 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
@@ -7,6 +7,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "Plugins/SymbolFile/DWARF/DWARFIndex.h"
+#include "DWARFDebugInfoEntry.h"
+#include "DWARFDeclContext.h"
 #include "Plugins/Language/ObjC/ObjCLanguage.h"
 #include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
@@ -112,3 +114,21 @@ void DWARFIndex::ReportInvalidDIERef(DIERef ref, llvm::StringRef name) const {
       "bad die {0:x16} for '{1}')\n",
       ref.die_offset(), name.str().c_str());
 }
+
+void DWARFIndex::GetFullyQualifiedType(
+    const DWARFDeclContext &context,
+    llvm::function_ref<bool(DWARFDIE die)> callback) {
+  GetTypes(context, [&](DWARFDIE die) {
+    return GetFullyQualifiedTypeImpl(context, die, callback);
+  });
+}
+
+bool DWARFIndex::GetFullyQualifiedTypeImpl(
+    const DWARFDeclContext &context, DWARFDIE die,
+    llvm::function_ref<bool(DWARFDIE die)> callback) {
+  DWARFDeclContext dwarf_decl_ctx =
+      die.GetDIE()->GetDWARFDeclContext(die.GetCU());
+  if (dwarf_decl_ctx == context)
+    return callback(die);
+  return true;
+}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h
index 9aadeddbb21753..0551b07100a96b 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h
@@ -53,6 +53,14 @@ class DWARFIndex {
                         llvm::function_ref<bool(DWARFDIE die)> callback) = 0;
   virtual void GetTypes(const DWARFDeclContext &context,
                         llvm::function_ref<bool(DWARFDIE die)> callback) = 0;
+
+  /// Finds all DIEs whose fully qualified name matches `context`. A base
+  /// implementation is provided, and it uses the entire CU to check the DIE
+  /// parent hierarchy. Specializations should override this if they are able
+  /// to provide a faster implementation.
+  virtual void
+  GetFullyQualifiedType(const DWARFDeclContext &context,
+                        llvm::function_ref<bool(DWARFDIE die)> callback);
   virtual void
   GetNamespaces(ConstString name,
                 llvm::function_ref<bool(DWARFDIE die)> callback) = 0;
@@ -102,6 +110,12 @@ class DWARFIndex {
   }
 
   void ReportInvalidDIERef(DIERef ref, llvm::StringRef name) const;
+
+  /// Implementation of `GetFullyQualifiedType` to check a single entry,
+  /// shareable with derived classes.
+  bool
+  GetFullyQualifiedTypeImpl(const DWARFDeclContext &context, DWARFDIE die,
+                            llvm::function_ref<bool(DWARFDIE die)> callback);
 };
 } // namespace dwarf
 } // namespace lldb_private::plugin
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
index 0e2f4d45543bb5..7db279ed37d04a 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -663,6 +663,14 @@ DWARFUnit::GetDIE(dw_offset_t die_offset) {
   return DWARFDIE(); // Not found
 }
 
+llvm::StringRef DWARFUnit::PeekDIEName(dw_offset_t die_offset) {
+  const DWARFDataExtractor &data = GetData();
+  DWARFDebugInfoEntry die;
+  if (!die.Extract(data, this, &die_offset))
+    return llvm::StringRef();
+  return die.GetName(this);
+}
+
 DWARFUnit &DWARFUnit::GetNonSkeletonUnit() {
   ExtractUnitDIEIfNeeded();
   if (m_dwo)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
index 3f528e913d8cfa..bc225a52e1d030 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
@@ -187,6 +187,11 @@ class DWARFUnit : public UserID {
 
   DWARFDIE GetDIE(dw_offset_t die_offset);
 
+  /// Returns the AT_Name of the DIE at `die_offset`, if it exists, without
+  /// parsing the entire compile unit. An empty is string is returned upon
+  /// error or if the attribute is not present.
+  llvm::StringRef PeekDIEName(dw_offset_t die_offset);
+
   DWARFUnit &GetNonSkeletonUnit();
 
   static uint8_t GetAddressByteSize(const DWARFUnit *cu);
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
index b718f98340a70b..8a82a77e6b1642 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
@@ -218,6 +218,102 @@ void DebugNamesDWARFIndex::GetCompleteObjCClass(
   m_fallback.GetCompleteObjCClass(class_name, must_be_implementation, callback);
 }
 
+namespace {
+using Entry = llvm::DWARFDebugNames::Entry;
+
+// If `entry` and all of its parents have an `IDX_parent`, use that information
+// to build and return a list of at most `max_parents` parent Entries.
+// `entry` itself is not included in the list.
+// If any parent does not have an `IDX_parent`, nullopt is returned.
+static std::optional<llvm::SmallVector<Entry, 4>>
+getParentChain(Entry entry, uint32_t max_parents) {
+  llvm::SmallVector<Entry, 4> parent_entries;
+
+  do {
+    if (!entry.hasParentInformation())
+      return std::nullopt;
+
+    llvm::Expected<std::optional<Entry>> parent = entry.getParentDIEEntry();
+    if (!parent) { // Bad data.
+      consumeError(parent.takeError());
+      return std::nullopt;
+    }
+
+    // Last parent in the chain
+    if (!parent->has_value())
+      break;
+
+    parent_entries.push_back(**parent);
+    entry = **parent;
+  } while (parent_entries.size() < max_parents);
+
+  return parent_entries;
+}
+} // namespace
+
+void DebugNamesDWARFIndex::GetFullyQualifiedType(
+    const DWARFDeclContext &context,
+    llvm::function_ref<bool(DWARFDIE die)> callback) {
+
+  // Fallback: use the base class implementation.
+  auto fallback_impl = [&](const DebugNames::Entry &entry) {
+    return ProcessEntry(entry, [&](DWARFDIE die) {
+      return GetFullyQualifiedTypeImpl(context, die, callback);
+    });
+  };
+
+  auto qualified_names = context.GetQualifiedNameAsVector();
+  if (qualified_names.empty())
+    return;
+  auto leaf_name = qualified_names.front();
+  auto parent_names = llvm::makeArrayRef(qualified_names).drop_front();
+
+  for (const DebugNames::Entry &entry :
+       m_debug_names_up->equal_range(leaf_name)) {
+    if (!isType(entry.tag()))
+      continue;
+
+    // Grab at most one extra parent, extra parents are not useful to test
+    // equality.
+    auto parent_chain = getParentChain(entry, parent_names.size() + 1);
+
+    if (!parent_chain) {
+      if (!fallback_impl(entry))
+        return;
+      continue;
+    }
+
+    if (CheckParentChain(parent_names, *parent_chain) &&
+        (!ProcessEntry(entry, callback)))
+      return;
+  }
+}
+
+bool DebugNamesDWARFIndex::CheckParentChain(
+    llvm::ArrayRef<llvm::StringRef> expected_parent_names,
+    llvm::ArrayRef<DebugNames::Entry> parent_entries) const {
+
+  if (parent_entries.size() != expected_parent_names.size())
+    return false;
+
+  auto CompareEntryATName = [this](llvm::StringRef expected_name,
+                                   const DebugNames::Entry &entry) {
+    auto maybe_dieoffset = entry.getDIEUnitOffset();
+    if (!maybe_dieoffset)
+      return false;
+    auto die_ref = ToDIERef(entry);
+    if (!die_ref)
+      return false;
+    return expected_name == m_debug_info.PeekDIEName(*die_ref);
+  };
+
+  for (auto [expected_parent_name, parent_entry] :
+       llvm::zip_equal(expected_parent_names, parent_entries))
+    if (!CompareEntryATName(expected_parent_name, parent_entry))
+      return false;
+  return true;
+}
+
 void DebugNamesDWARFIndex::GetTypes(
     ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
   for (const DebugNames::Entry &entry :
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h
index cca0913c4124c9..15eff7a2659633 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h
@@ -14,6 +14,7 @@
 #include "Plugins/SymbolFile/DWARF/ManualDWARFIndex.h"
 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
 #include "lldb/Utility/ConstString.h"
+#include "llvm/ADT/ArrayRef.h"
 #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
 #include <optional>
 
@@ -42,6 +43,11 @@ class DebugNamesDWARFIndex : public DWARFIndex {
   void GetCompleteObjCClass(
       ConstString class_name, bool must_be_implementation,
       llvm::function_ref<bool(DWARFDIE die)> callback) override;
+
+  /// Uses DWARF5's IDX_parent fields, when available, to speed up this query.
+  void GetFullyQualifiedType(
+      const DWARFDeclContext &context,
+      llvm::function_ref<bool(DWARFDIE die)> callback) override;
   void GetTypes(ConstString name,
                 llvm::function_ref<bool(DWARFDIE die)> callback) override;
   void GetTypes(const DWARFDeclContext &context,
@@ -83,6 +89,9 @@ class DebugNamesDWARFIndex : public DWARFIndex {
   bool ProcessEntry(const DebugNames::Entry &entry,
                     llvm::function_ref<bool(DWARFDIE die)> callback);
 
+  bool CheckParentChain(llvm::ArrayRef<llvm::StringRef> parent_names,
+                        llvm::ArrayRef<DebugNames::Entry> parent_entries) const;
+
   static void MaybeLogLookupError(llvm::Error error,
                                   const DebugNames::NameIndex &ni,
                                   llvm::StringRef name);
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 447930ffe07b3f..737da7798b82b9 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -3138,7 +3138,7 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die) {
     }
 
     const DWARFDeclContext die_dwarf_decl_ctx = GetDWARFDeclContext(die);
-    m_index->GetTypes(die_dwarf_decl_ctx, [&](DWARFDIE type_die) {
+    m_index->GetFullyQualifiedType(die_dwarf_decl_ctx, [&](DWARFDIE type_die) {
       // Make sure type_die's language matches the type system we are
       // looking for. We don't want to find a "Foo" type from Java if we
       // are looking for a "Foo" type for C, C++, ObjC, or ObjC++.
@@ -3165,9 +3165,8 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die) {
         return true;
       }
 
-      DWARFDeclContext type_dwarf_decl_ctx = GetDWARFDeclContext(type_die);
-
       if (log) {
+        DWARFDeclContext type_dwarf_decl_ctx = GetDWARFDeclContext(type_die);
         GetObjectFile()->GetModule()->LogMessage(
             log,
             "SymbolFileDWARF::"
@@ -3177,10 +3176,6 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(const DWARFDIE &die) {
             type_dwarf_decl_ctx.GetQualifiedName());
       }
 
-      // Make sure the decl contexts match all the way up
-      if (die_dwarf_decl_ctx != type_dwarf_decl_ctx)
-        return true;
-
       Type *resolved_type = ResolveType(type_die, false);
       if (!resolved_type || resolved_type == DIE_IS_BEING_PARSED)
         return true;
diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp
index 8497855b2f3db5..5672270ee31f89 100644
--- a/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp
+++ b/lldb/unittests/SymbolFile/DWARF/DWARFDIETest.cpp
@@ -7,8 +7,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h"
 #include "TestingSupport/Symbol/YAMLModuleTester.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
@@ -104,3 +106,110 @@ TEST(DWARFDIETest, ChildIteration) {
   DWARFDIE no_children_die(unit, die_child0);
   EXPECT_TRUE(no_children_die.children().empty());
 }
+
+TEST(DWARFDIETest, DeclContext) {
+  const char *yamldata = R"(
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_386
+DWARF:
+  debug_str:
+    - 'mynamespace'
+    - 'mystruct'
+    - 'mytype'
+  debug_abbrev:
+    - Table:
+        - Code:            0x00000001
+          Tag:             DW_TAG_compile_unit
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_language
+              Form:            DW_FORM_data2
+        - Code:            0x00000002
+          Tag:             DW_TAG_structure_type
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+        - Code:            0x00000003
+          Tag:             DW_TAG_base_type
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+        - Code:            0x00000004
+          Tag:             DW_TAG_namespace
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+  debug_info:
+    - Version:         4
+      AddrSize:        8
+      Entries:
+        - AbbrCode:        0x00000001 # compile_unit
+          Values:
+            - Value:           0x000000000000000C
+        - AbbrCode:        0x00000004 # namespace
+          Values:
+            - Value:           0x0000000000000000 # DW_ATE_strp
+        - AbbrCode:        0x00000002 # structure_type
+          Values:
+            - Value:           0x000000000000000c # DW_ATE_strp
+        - AbbrCode:        0x00000003 # base_type
+          Values:
+            - Value:           0x0000000000000015 # DW_ATE_strp
+        - AbbrCode:        0x00000000
+)";
+
+  YAMLModuleTester t(yamldata);
+  DWARFUnit *unit = t.GetDwarfUnit();
+  ASSERT_TRUE(unit != nullptr);
+  auto &ctx = unit->GetSymbolFileDWARF();
+
+  auto top_level_die = unit->DIE();
+  {
+    ASSERT_TRUE(top_level_die);
+    auto top_level_ctx = ctx.GetDWARFDeclContext(top_level_die);
+    auto top_level_name = llvm::StringRef(top_level_ctx.GetQualifiedName());
+    ASSERT_EQ(top_level_name, "");
+  }
+
+  auto namespace_die = top_level_die.GetFirstChild();
+  {
+    ASSERT_TRUE(namespace_die);
+    auto namespace_ctx = ctx.GetDWARFDeclContext(namespace_die);
+    auto namespace_name = llvm::StringRef(namespace_ctx.GetQualifiedName());
+    ASSERT_EQ(namespace_name, "::mynamespace");
+    auto namespace_names = namespace_ctx.GetQualifiedNameAsVector();
+    ASSERT_EQ(namespace_names.size(), 1u);
+    ASSERT_EQ(namespace_names.front(), "mynamespace");
+  }
+
+  auto struct_die = namespace_die.GetFirstChild();
+  {
+    ASSERT_TRUE(struct_die);
+    auto struct_ctx = ctx.GetDWARFDeclContext(struct_die);
+    auto struct_name = llvm::StringRef(struct_ctx.GetQualifiedName());
+    ASSERT_EQ(struct_name, "mynamespace::mystruct");
+    auto struct_names = struct_ctx.GetQualifiedNameAsVector();
+    ASSERT_EQ(struct_names.size(), 2u);
+    ASSERT_EQ(struct_names[0], "mystruct");
+    ASSERT_EQ(struct_names[1], "mynamespace");
+  }
+  auto simple_type_die = struct_die.GetFirstChild();
+  {
+    ASSERT_TRUE(simple_type_die);
+    auto simple_type_ctx = ctx.GetDWARFDeclContext(simple_type_die);
+    auto simple_type_name = llvm::StringRef(simple_type_ctx.GetQualifiedName());
+    ASSERT_EQ(simple_type_name, "mynamespace::mystruct::mytype");
+    auto simple_type_names = simple_type_ctx.GetQualifiedNameAsVector();
+    ASSERT_EQ(simple_type_names.size(), 3u);
+    ASSERT_EQ(simple_type_names[0], "mytype");
+    ASSERT_EQ(simple_type_names[1], "mystruct");
+    ASSERT_EQ(simple_type_names[2], "mynamespace");
+  }
+}
diff --git a/llvm/include/llvm/CodeGen/AccelTable.h b/llvm/include/llvm/CodeGen/AccelTable.h
index 6eb09f32f9f951..ddccc4600f14c1 100644
--- a/llvm/include/llvm/CodeGen/AccelTable.h
+++ b/llvm/include/llvm/CodeGen/AccelTable.h
@@ -143,6 +143,11 @@ class AccelTableBase {
     std::vector<AccelTableData *> Values;
     MCSymbol *Sym;
 
+    template <typename T = AccelTableData *> auto getValues() const {
+      return map_range(
+          Values, [](AccelTableData *Data) { return static_cast<T>(Data); });
+    }
+
 #ifndef NDEBUG
     void print(raw_ostream &OS) const;
     void dump() const { print(dbgs()); }
@@ -261,9 +266,12 @@ class DWARF5AccelTableData : public AccelTableData {
 
   DWARF5AccelTableData(const DIE &Die, const uint32_t UnitID,
                        const bool IsTU = false);
-  DWARF5AccelTableData(const uint64_t DieOffset, const unsigned DieTag,
-                       const unsigned UnitID, const bool IsTU = false)
-      : OffsetVal(DieOffset), DieTag(DieTag), UnitID(UnitID), IsTU(IsTU) {}
+  DWARF5AccelTableData(const uint64_t DieOffset,
+                       const std::optional<uint64_t> ParentOffset,
+                       const unsigned DieTag, const unsigned UnitID,
+                       const bool IsTU = false)
+      : OffsetVal(DieOffset), ParentOffset(ParentOffset), DieTag(DieT...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/77121


More information about the llvm-commits mailing list