[llvm] 2216ee4 - This patch allows llvm-dwarfutil to utilize accelerator tables

Alexey Lapshin via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 16 05:49:08 PST 2023


Author: Alexey Lapshin
Date: 2023-01-16T14:42:30+01:00
New Revision: 2216ee4909f01d6547fd3bda978c00b2c587ff2f

URL: https://github.com/llvm/llvm-project/commit/2216ee4909f01d6547fd3bda978c00b2c587ff2f
DIFF: https://github.com/llvm/llvm-project/commit/2216ee4909f01d6547fd3bda978c00b2c587ff2f.diff

LOG: This patch allows llvm-dwarfutil to utilize accelerator tables
generation code from DWARFLinker. It adds command line option:

--build-accelerator [none,DWARF]
                        Build accelerator tables(default: none)
  =none - Do not build accelerators
  =DWARF - Build accelerator tables according to the resulting DWARF version
       DWARFv4: .debug_pubnames and .debug_pubtypes
       DWARFv5: .debug_names

Differential Revision: https://reviews.llvm.org/D139638

Added: 
    llvm/test/tools/llvm-dwarfutil/ELF/X86/Inputs/dwarf5.out
    llvm/test/tools/llvm-dwarfutil/ELF/X86/accelerator-dwarf4.test
    llvm/test/tools/llvm-dwarfutil/ELF/X86/accelerator-dwarf5.test
    llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-pubnames.test
    llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-pubtypes.test

Modified: 
    llvm/include/llvm/CodeGen/AsmPrinter.h
    llvm/include/llvm/DWARFLinker/DWARFLinker.h
    llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
    llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
    llvm/lib/CodeGen/AsmPrinter/DIE.cpp
    llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
    llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
    llvm/lib/DWARFLinker/DWARFLinker.cpp
    llvm/lib/DWARFLinker/DWARFStreamer.cpp
    llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf4-macro.test
    llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-macro.test
    llvm/test/tools/llvm-dwarfutil/ELF/X86/verbose.test
    llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
    llvm/tools/llvm-dwarfutil/Options.h
    llvm/tools/llvm-dwarfutil/Options.td
    llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
    llvm/unittests/CodeGen/TestAsmPrinter.cpp

Removed: 
    llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-skipped-names.test
    llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-skipped-pubnames.test
    llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-skipped-pubtypes.test


################################################################################
diff  --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index a88056534458f..33fda248120bd 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -327,6 +327,14 @@ class AsmPrinter : public MachineFunctionPass {
   /// definition in the same module.
   MCSymbol *getSymbolPreferLocal(const GlobalValue &GV) const;
 
+  bool doesDwarfUseRelocationsAcrossSections() const {
+    return DwarfUsesRelocationsAcrossSections;
+  }
+
+  void setDwarfUsesRelocationsAcrossSections(bool Enable) {
+    DwarfUsesRelocationsAcrossSections = Enable;
+  }
+
   //===------------------------------------------------------------------===//
   // XRay instrumentation implementation.
   //===------------------------------------------------------------------===//
@@ -820,6 +828,8 @@ class AsmPrinter : public MachineFunctionPass {
   mutable unsigned LastFn = 0;
   mutable unsigned Counter = ~0U;
 
+  bool DwarfUsesRelocationsAcrossSections = false;
+
   /// This method emits the header for the current function.
   virtual void emitFunctionHeader();
 

diff  --git a/llvm/include/llvm/DWARFLinker/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/DWARFLinker.h
index a9473bef49dc3..619d878b7b5da 100644
--- a/llvm/include/llvm/DWARFLinker/DWARFLinker.h
+++ b/llvm/include/llvm/DWARFLinker/DWARFLinker.h
@@ -705,7 +705,7 @@ class DWARFLinker {
     /// it to \p Die.
     /// \returns the size of the new attribute.
     unsigned cloneAddressAttribute(DIE &Die, AttributeSpec AttrSpec,
-                                   const DWARFFormValue &Val,
+                                   unsigned AttrSize, const DWARFFormValue &Val,
                                    const CompileUnit &Unit,
                                    AttributesInfo &Info);
 

diff  --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 0f5e1648f09d7..f40ddad5d8895 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -350,6 +350,8 @@ AsmPrinter::AsmPrinter(TargetMachine &tm, std::unique_ptr<MCStreamer> Streamer)
       OutContext(Streamer->getContext()), OutStreamer(std::move(Streamer)),
       SM(*this) {
   VerboseAsm = OutStreamer->isVerboseAsm();
+  DwarfUsesRelocationsAcrossSections =
+      MAI->doesDwarfUseRelocationsAcrossSections();
 }
 
 AsmPrinter::~AsmPrinter() {
@@ -4033,7 +4035,7 @@ unsigned int AsmPrinter::getDwarfOffsetByteSize() const {
 dwarf::FormParams AsmPrinter::getDwarfFormParams() const {
   return {getDwarfVersion(), uint8_t(getPointerSize()),
           OutStreamer->getContext().getDwarfFormat(),
-          MAI->doesDwarfUseRelocationsAcrossSections()};
+          doesDwarfUseRelocationsAcrossSections()};
 }
 
 unsigned int AsmPrinter::getUnitLengthFieldByteSize() const {

diff  --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
index bfa53f5b93749..ecaa64afab4da 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
@@ -163,7 +163,7 @@ void AsmPrinter::emitDwarfSymbolReference(const MCSymbol *Label,
     }
 
     // If the format uses relocations with dwarf, refer to the symbol directly.
-    if (MAI->doesDwarfUseRelocationsAcrossSections()) {
+    if (doesDwarfUseRelocationsAcrossSections()) {
       OutStreamer->emitSymbolValue(Label, getDwarfOffsetByteSize());
       return;
     }
@@ -175,7 +175,7 @@ void AsmPrinter::emitDwarfSymbolReference(const MCSymbol *Label,
 }
 
 void AsmPrinter::emitDwarfStringOffset(DwarfStringPoolEntry S) const {
-  if (MAI->doesDwarfUseRelocationsAcrossSections()) {
+  if (doesDwarfUseRelocationsAcrossSections()) {
     assert(S.Symbol && "No symbol available");
     emitDwarfSymbolReference(S.Symbol);
     return;

diff  --git a/llvm/lib/CodeGen/AsmPrinter/DIE.cpp b/llvm/lib/CodeGen/AsmPrinter/DIE.cpp
index f324eada6a074..308d4b1b5d610 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DIE.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DIE.cpp
@@ -580,7 +580,7 @@ void DIEString::emitValue(const AsmPrinter *AP, dwarf::Form Form) const {
     DIEInteger(S.getIndex()).emitValue(AP, Form);
     return;
   case dwarf::DW_FORM_strp:
-    if (AP->MAI->doesDwarfUseRelocationsAcrossSections())
+    if (AP->doesDwarfUseRelocationsAcrossSections())
       DIELabel(S.getSymbol()).emitValue(AP, Form);
     else
       DIEInteger(S.getOffset()).emitValue(AP, Form);

diff  --git a/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
index 67b72f0b455db..2292590b135ea 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
@@ -20,7 +20,7 @@ using namespace llvm;
 DwarfStringPool::DwarfStringPool(BumpPtrAllocator &A, AsmPrinter &Asm,
                                  StringRef Prefix)
     : Pool(A), Prefix(Prefix),
-      ShouldCreateSymbols(Asm.MAI->doesDwarfUseRelocationsAcrossSections()) {}
+      ShouldCreateSymbols(Asm.doesDwarfUseRelocationsAcrossSections()) {}
 
 StringMapEntry<DwarfStringPool::EntryTy> &
 DwarfStringPool::getEntryImpl(AsmPrinter &Asm, StringRef Str) {

diff  --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 9497a6a3207f0..c2ff899c04abe 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -1796,7 +1796,7 @@ void DwarfUnit::addSectionDelta(DIE &Die, dwarf::Attribute Attribute,
 
 void DwarfUnit::addSectionLabel(DIE &Die, dwarf::Attribute Attribute,
                                 const MCSymbol *Label, const MCSymbol *Sec) {
-  if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
+  if (Asm->doesDwarfUseRelocationsAcrossSections())
     addLabel(Die, Attribute, DD->getDwarfSectionOffsetForm(), Label);
   else
     addSectionDelta(Die, Attribute, Label, Sec);
@@ -1819,7 +1819,7 @@ void DwarfTypeUnit::addGlobalType(const DIType *Ty, const DIE &Die,
 }
 
 const MCSymbol *DwarfUnit::getCrossSectionRelativeBaseAddress() const {
-  if (!Asm->MAI->doesDwarfUseRelocationsAcrossSections())
+  if (!Asm->doesDwarfUseRelocationsAcrossSections())
     return nullptr;
   if (isDwoUnit())
     return nullptr;

diff  --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp
index d496245434ff7..2d1282455b6b1 100644
--- a/llvm/lib/DWARFLinker/DWARFLinker.cpp
+++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp
@@ -1151,14 +1151,14 @@ unsigned DWARFLinker::DIECloner::cloneBlockAttribute(
 }
 
 unsigned DWARFLinker::DIECloner::cloneAddressAttribute(
-    DIE &Die, AttributeSpec AttrSpec, const DWARFFormValue &Val,
-    const CompileUnit &Unit, AttributesInfo &Info) {
+    DIE &Die, AttributeSpec AttrSpec, unsigned AttrSize,
+    const DWARFFormValue &Val, const CompileUnit &Unit, AttributesInfo &Info) {
   if (LLVM_UNLIKELY(Linker.Options.Update)) {
     if (AttrSpec.Attr == dwarf::DW_AT_low_pc)
       Info.HasLowPc = true;
     Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
                  dwarf::Form(AttrSpec.Form), DIEInteger(Val.getRawUValue()));
-    return Unit.getOrigUnit().getAddressByteSize();
+    return AttrSize;
   }
 
   dwarf::Form Form = AttrSpec.Form;
@@ -1348,7 +1348,7 @@ unsigned DWARFLinker::DIECloner::cloneAttribute(
                                IsLittleEndian);
   case dwarf::DW_FORM_addr:
   case dwarf::DW_FORM_addrx:
-    return cloneAddressAttribute(Die, AttrSpec, Val, Unit, Info);
+    return cloneAddressAttribute(Die, AttrSpec, AttrSize, Val, Unit, Info);
   case dwarf::DW_FORM_data1:
   case dwarf::DW_FORM_data2:
   case dwarf::DW_FORM_data4:
@@ -1417,17 +1417,16 @@ void DWARFLinker::DIECloner::addObjCAccelerator(CompileUnit &Unit,
   }
 }
 
-static bool
-shouldSkipAttribute(DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
-                    uint16_t Tag, bool InDebugMap, bool SkipPC,
-                    bool InFunctionScope) {
+static bool shouldSkipAttribute(
+    bool Update, DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
+    uint16_t Tag, bool InDebugMap, bool SkipPC, bool InFunctionScope) {
   switch (AttrSpec.Attr) {
   default:
     return false;
   case dwarf::DW_AT_low_pc:
   case dwarf::DW_AT_high_pc:
   case dwarf::DW_AT_ranges:
-    return SkipPC;
+    return !Update && SkipPC;
   case dwarf::DW_AT_str_offsets_base:
     // FIXME: Use the string offset table with Dwarf 5.
     return true;
@@ -1438,7 +1437,8 @@ shouldSkipAttribute(DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
     // wrong for globals where we will keep a wrong address. It is mostly
     // harmless for locals, but there is no point in keeping these anyway when
     // the function wasn't linked.
-    return (SkipPC || (!InFunctionScope && Tag == dwarf::DW_TAG_variable &&
+    return !Update &&
+           (SkipPC || (!InFunctionScope && Tag == dwarf::DW_TAG_variable &&
                        !InDebugMap)) &&
            !DWARFFormValue(AttrSpec.Form).isFormClass(DWARFFormValue::FC_Block);
   }
@@ -1544,8 +1544,7 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
   }
 
   for (const auto &AttrSpec : Abbrev->attributes()) {
-    if (LLVM_LIKELY(!Update) &&
-        shouldSkipAttribute(AttrSpec, Die->getTag(), Info.InDebugMap,
+    if (shouldSkipAttribute(Update, AttrSpec, Die->getTag(), Info.InDebugMap,
                             Flags & TF_SkipPC, Flags & TF_InFunctionScope)) {
       DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset,
                                 U.getFormParams());

diff  --git a/llvm/lib/DWARFLinker/DWARFStreamer.cpp b/llvm/lib/DWARFLinker/DWARFStreamer.cpp
index 01a7e5a4f3e3f..94dcd78f98b42 100644
--- a/llvm/lib/DWARFLinker/DWARFStreamer.cpp
+++ b/llvm/lib/DWARFLinker/DWARFStreamer.cpp
@@ -105,6 +105,7 @@ bool DwarfStreamer::init(Triple TheTriple,
   Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS)));
   if (!Asm)
     return error("no asm printer for target " + TripleName, Context), false;
+  Asm->setDwarfUsesRelocationsAcrossSections(false);
 
   RangesSectionSize = 0;
   LocSectionSize = 0;

diff  --git a/llvm/test/tools/llvm-dwarfutil/ELF/X86/Inputs/dwarf5.out b/llvm/test/tools/llvm-dwarfutil/ELF/X86/Inputs/dwarf5.out
new file mode 100755
index 0000000000000..24ec57913066e
Binary files /dev/null and b/llvm/test/tools/llvm-dwarfutil/ELF/X86/Inputs/dwarf5.out 
diff er

diff  --git a/llvm/test/tools/llvm-dwarfutil/ELF/X86/accelerator-dwarf4.test b/llvm/test/tools/llvm-dwarfutil/ELF/X86/accelerator-dwarf4.test
new file mode 100644
index 0000000000000..0a107aa2ff57d
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfutil/ELF/X86/accelerator-dwarf4.test
@@ -0,0 +1,33 @@
+## This test checks that .debug_names accelerator tables are
+## generated if --build-accelerator=DWARF option is specified
+## and source file has DWARFv4 debug info.
+
+# RUN: yaml2obj %p/Inputs/common.yaml -o %t.o
+
+# RUN: llvm-dwarfutil --no-garbage-collection --build-accelerator=DWARF %t.o %t1
+# RUN: llvm-dwarfdump --verify %t1 | FileCheck %s --check-prefix=VERIFY
+# RUN: llvm-dwarfdump -a %t1 | FileCheck %s
+
+# RUN: llvm-dwarfutil --garbage-collection --build-accelerator=DWARF %t.o %t1
+# RUN: llvm-dwarfdump --verify %t1 | FileCheck %s --check-prefix=VERIFY
+# RUN: llvm-dwarfdump -a %t1 | FileCheck %s
+
+# VERIFY: No errors
+
+# CHECK: .debug_names contents:
+# CHECK:  Compilation Unit offsets [
+# CHECK:    CU[0]: 0x00000000
+# CHECK:  ]
+# CHECK: Abbreviations
+# CHECK: String: {{.*}} "foo1"
+# CHECK: Tag: DW_TAG_subprogram
+# CHECK: String: {{.*}} "class1"
+# CHECK: Tag: DW_TAG_class_type
+# CHECK: String: {{.*}} "float"
+# CHECK: Tag: DW_TAG_base_type
+# CHECK: String: {{.*}} "int"
+# CHECK: Tag: DW_TAG_base_type
+# CHECK: String: {{.*}} "var1"
+# CHECK: Tag: DW_TAG_variable
+# CHECK: String: {{.*}} "char"
+# CHECK: Tag: DW_TAG_base_type

diff  --git a/llvm/test/tools/llvm-dwarfutil/ELF/X86/accelerator-dwarf5.test b/llvm/test/tools/llvm-dwarfutil/ELF/X86/accelerator-dwarf5.test
new file mode 100644
index 0000000000000..05872423efc12
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfutil/ELF/X86/accelerator-dwarf5.test
@@ -0,0 +1,31 @@
+## This test checks that .debug_names accelerator table
+## is generated if --build-accelerator=DWARF option is
+## specified and source file has DWARFv5 debug info.
+
+# RUN: llvm-dwarfutil --no-garbage-collection --build-accelerator=DWARF %p/Inputs/dwarf5.out %t1
+# RUN: llvm-dwarfdump --verify %t1 | FileCheck %s --check-prefix=VERIFY
+# RUN: llvm-dwarfdump -a %t1 | FileCheck %s
+
+# RUN: llvm-dwarfutil --garbage-collection --build-accelerator=DWARF %p/Inputs/dwarf5.out %t1
+# RUN: llvm-dwarfdump --verify %t1 | FileCheck %s --check-prefix=VERIFY
+# RUN: llvm-dwarfdump -a %t1 | FileCheck %s
+
+# VERIFY: No errors
+
+# CHECK: .debug_names contents:
+# CHECK:  Compilation Unit offsets [
+# CHECK:    CU[0]: 0x00000000
+# CHECK:  ]
+# CHECK: Abbreviations
+# CHECK: String: {{.*}} "_Z3foov"
+# CHECK: Tag: DW_TAG_subprogram
+# CHECK: String: {{.*}} "int"
+# CHECK: Tag: DW_TAG_base_type
+# CHECK: String: {{.*}} "foo"
+# CHECK: Tag: DW_TAG_subprogram
+# CHECK: String: {{.*}} "A"
+# CHECK: Tag: DW_TAG_structure_type
+# CHECK: String: {{.*}} "main"
+# CHECK: Tag: DW_TAG_subprogram
+# CHECK: String: {{.*}} "char"
+# CHECK: Tag: DW_TAG_base_type

diff  --git a/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf4-macro.test b/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf4-macro.test
index 0377a0aa63ec7..a84653c612cb7 100644
--- a/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf4-macro.test
+++ b/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf4-macro.test
@@ -45,6 +45,11 @@
 #RUN: llvm-dwarfdump -verify %t1 | FileCheck %s
 #RUN: llvm-dwarfdump -a  %t1 | FileCheck %s --check-prefix=MACINFO
 
+## Check that macro table preserved during updating accelerator tables.
+#RUN: llvm-dwarfutil --no-garbage-collection --build-accelerator=DWARF %p/Inputs/dwarf4-macro.out %t1
+#RUN: llvm-dwarfdump -verify %t1 | FileCheck %s
+#RUN: llvm-dwarfdump -a  %t1 | FileCheck %s --check-prefixes=MACINFO,NAMES
+
 #CHECK: No errors.
 
 #MACINFO: .debug_info contents
@@ -2222,3 +2227,7 @@
 #MACINFO-NEXT: DW_MACINFO_define - lineno: 0 macro: __STDC_UTF_16__ 1
 #MACINFO-NEXT: DW_MACINFO_define - lineno: 0 macro: __STDC_UTF_32__ 1
 #MACINFO-NEXT: DW_MACINFO_define - lineno: 0 macro: __GCC_HAVE_DWARF2_CFI_ASM 1
+
+
+#NAMES: .debug_names contents
+#NAMES: Name Index

diff  --git a/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-macro.test b/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-macro.test
index 278ba56f34ac8..57487be9d4270 100644
--- a/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-macro.test
+++ b/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-macro.test
@@ -45,6 +45,11 @@
 #RUN: llvm-dwarfdump -verify %t1 | FileCheck %s
 #RUN: llvm-dwarfdump -a  %t1 | FileCheck %s --check-prefix=MACRO
 
+## Check that macro table preserved during updating accelerator tables.
+#RUN: llvm-dwarfutil --no-garbage-collection --build-accelerator=DWARF %p/Inputs/dwarf5-macro.out %t1
+#RUN: llvm-dwarfdump -verify %t1 | FileCheck %s
+#RUN: llvm-dwarfdump -a  %t1 | FileCheck %s --check-prefixes=MACRO,NAMES
+
 #CHECK: No errors.
 
 #MACRO: .debug_info contents
@@ -2228,3 +2233,6 @@
 #MACRO-NEXT: DW_MACRO_define_str{{[px]}} - lineno: 0 macro: __STDC_UTF_16__ 1
 #MACRO-NEXT: DW_MACRO_define_str{{[px]}} - lineno: 0 macro: __STDC_UTF_32__ 1
 #MACRO-NEXT: DW_MACRO_define_str{{[px]}} - lineno: 0 macro: __GCC_HAVE_DWARF2_CFI_ASM 1
+
+#NAMES: .debug_names contents
+#NAMES: Name Index

diff  --git a/llvm/test/tools/llvm-dwarfutil/ELF/X86/verbose.test b/llvm/test/tools/llvm-dwarfutil/ELF/X86/verbose.test
index 6675d7cd8a3bb..940bc34e0c2c5 100644
--- a/llvm/test/tools/llvm-dwarfutil/ELF/X86/verbose.test
+++ b/llvm/test/tools/llvm-dwarfutil/ELF/X86/verbose.test
@@ -16,7 +16,7 @@
 # RUN: llvm-dwarfutil %t.o %t1 -j 1 --verbose --verify 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-VERIFY
 
 # CHECK-NOT: warning: --num-threads set to 1 because verbose mode is specified
-# CHECK: Do garbage collection for debug info ...
+# CHECK: Do debug info linking...
 # CHECK: Input compilation unit:
 # CHECK: DW_TAG_compile_unit
 # CHECK: Keeping subprogram DIE

diff  --git a/llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-skipped-pubnames.test b/llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-pubnames.test
similarity index 67%
rename from llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-skipped-pubnames.test
rename to llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-pubnames.test
index 3aa42a843aaca..f6b939e918deb 100644
--- a/llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-skipped-pubnames.test
+++ b/llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-pubnames.test
@@ -1,11 +1,18 @@
 ## This test checks the warning message displayed if input file
-## contains .debug_pubnames section.
+## contains .debug_pubnames section which is incompatible with
+## requested accelerator table.
 
 # RUN: yaml2obj %s -o %t.o
 
-# RUN: llvm-dwarfutil --garbage-collection %t.o %t1 2>&1 | FileCheck %s -DFILE=%t.o
+# RUN: llvm-dwarfutil --garbage-collection %t.o %t1 2>&1 | FileCheck %s -DFILE=%t.o --check-prefix=WARN1
 
-# CHECK: [[FILE]]: warning: '.debug_pubnames' is not currently supported: section will be skipped
+# RUN: llvm-dwarfutil --build-accelerator=DWARF --garbage-collection %t.o %t1 2>&1 | FileCheck %s -DFILE=%t.o --check-prefix=WARN2
+
+# RUN: llvm-dwarfutil --build-accelerator=DWARF --no-garbage-collection %t.o %t1 2>&1 | FileCheck %s -DFILE=%t.o --check-prefix=WARN2
+
+# WARN1: [[FILE]]: warning: '.debug_pubnames' will be deleted as no accelerator tables are requested
+
+# WARN2: [[FILE]]: warning: '.debug_pubnames' will be replaced with requested .debug_names table
 
 --- !ELF
 FileHeader:
@@ -41,7 +48,8 @@ DWARF:
           - Attribute: DW_AT_high_pc
             Form:      DW_FORM_data8
   debug_info:
-    - Version: 4
+    - Version: 5
+      UnitType:   DW_UT_compile
       Entries:
         - AbbrCode: 1
           Values:

diff  --git a/llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-skipped-pubtypes.test b/llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-pubtypes.test
similarity index 67%
rename from llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-skipped-pubtypes.test
rename to llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-pubtypes.test
index 4134349f014f9..a0ea6369e28a7 100644
--- a/llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-skipped-pubtypes.test
+++ b/llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-pubtypes.test
@@ -1,11 +1,18 @@
 ## This test checks the warning message displayed if input file
-## contains .debug_pubtypes section.
+## contains .debug_pubtypes section which is incompatible with
+## requested accelerator table.
 
 # RUN: yaml2obj %s -o %t.o
+ 
+# RUN: llvm-dwarfutil --garbage-collection %t.o %t1 2>&1 | FileCheck %s -DFILE=%t.o --check-prefix=WARN1
 
-# RUN: llvm-dwarfutil --garbage-collection %t.o %t1 2>&1 | FileCheck %s -DFILE=%t.o
+# RUN: llvm-dwarfutil --build-accelerator=DWARF --garbage-collection %t.o %t1 2>&1 | FileCheck %s -DFILE=%t.o --check-prefix=WARN2
 
-# CHECK: [[FILE]]: warning: '.debug_pubtypes' is not currently supported: section will be skipped
+# RUN: llvm-dwarfutil --build-accelerator=DWARF --no-garbage-collection %t.o %t1 2>&1 | FileCheck %s -DFILE=%t.o --check-prefix=WARN2
+
+# WARN1: [[FILE]]: warning: '.debug_pubtypes' will be deleted as no accelerator tables are requested
+
+# WARN2: [[FILE]]: warning: '.debug_pubtypes' will be replaced with requested .debug_names table
 
 --- !ELF
 FileHeader:
@@ -41,7 +48,8 @@ DWARF:
           - Attribute: DW_AT_high_pc
             Form:      DW_FORM_data8
   debug_info:
-    - Version: 4
+    - Version: 5
+      UnitType:   DW_UT_compile
       Entries:
         - AbbrCode: 1
           Values:

diff  --git a/llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-skipped-names.test b/llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-skipped-names.test
deleted file mode 100644
index a68855294edb4..0000000000000
--- a/llvm/test/tools/llvm-dwarfutil/ELF/X86/warning-skipped-names.test
+++ /dev/null
@@ -1,54 +0,0 @@
-## This test checks the warning message displayed if input file
-## contains .debug_names section.
-
-# RUN: yaml2obj %s -o %t.o
-
-# RUN: llvm-dwarfutil --garbage-collection %t.o %t1 2>&1 | FileCheck %s -DFILE=%t.o
-
-# CHECK: [[FILE]]: warning: '.debug_names' is not currently supported: section will be skipped
-
---- !ELF
-FileHeader:
-  Class:    ELFCLASS64
-  Data:     ELFDATA2LSB
-  Type:     ET_REL
-  Machine:  EM_X86_64
-Sections:
-  - Name:            .text
-    Type:            SHT_PROGBITS
-    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
-    Address:         0x1000
-    AddressAlign:    0x0000000000000010
-    Content:         "FFFFFFFF"
-  - Name:            .debug_names
-    Type:            SHT_PROGBITS
-    Flags:           [  ]
-    Content:         "0000"
-DWARF:
-  debug_abbrev:
-    - Table:
-      - Tag:      DW_TAG_compile_unit
-        Children: DW_CHILDREN_yes
-        Attributes:
-          - Attribute: DW_AT_producer
-            Form:      DW_FORM_string
-          - Attribute: DW_AT_language
-            Form:      DW_FORM_data2
-          - Attribute: DW_AT_name
-            Form:      DW_FORM_string
-          - Attribute: DW_AT_low_pc
-            Form:      DW_FORM_addr
-          - Attribute: DW_AT_high_pc
-            Form:      DW_FORM_data8
-  debug_info:
-    - Version: 4
-      Entries:
-        - AbbrCode: 1
-          Values:
-            - CStr: by_hand
-            - Value:  0x04
-            - CStr: CU1
-            - Value:  0x1000
-            - Value:  0x4
-        - AbbrCode: 0
-...

diff  --git a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
index adf48cd87e0d9..ef222f8cc1a4f 100644
--- a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
+++ b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
@@ -252,9 +252,63 @@ static bool knownByDWARFUtil(StringRef SecName) {
       .Case(".debug_macinfo", true)
       .Case(".debug_str", true)
       .Case(".debug_str_offsets", true)
+      .Case(".debug_pubnames", true)
+      .Case(".debug_pubtypes", true)
+      .Case(".debug_names", true)
       .Default(false);
 }
 
+static std::optional<DwarfLinkerAccelTableKind>
+getAcceleratorTableKind(StringRef SecName) {
+  return llvm::StringSwitch<std::optional<DwarfLinkerAccelTableKind>>(SecName)
+      .Case(".debug_pubnames", DwarfLinkerAccelTableKind::Pub)
+      .Case(".debug_pubtypes", DwarfLinkerAccelTableKind::Pub)
+      .Case(".debug_names", DwarfLinkerAccelTableKind::DebugNames)
+      .Default(std::nullopt);
+}
+
+static std::string getMessageForReplacedAcceleratorTables(
+    SmallVector<StringRef> &AccelTableNamesToReplace,
+    DwarfUtilAccelKind TargetTable) {
+  std::string Message;
+
+  Message += "'";
+  for (StringRef Name : AccelTableNamesToReplace) {
+    if (Message.size() > 1)
+      Message += ", ";
+    Message += Name;
+  }
+
+  Message += "' will be replaced with requested ";
+
+  switch (TargetTable) {
+  case DwarfUtilAccelKind::DWARF:
+    Message += ".debug_names table";
+    break;
+
+  default:
+    assert(false);
+  }
+
+  return Message;
+}
+
+static std::string getMessageForDeletedAcceleratorTables(
+    SmallVector<StringRef> &AccelTableNamesToReplace) {
+  std::string Message;
+
+  Message += "'";
+  for (StringRef Name : AccelTableNamesToReplace) {
+    if (Message.size() > 1)
+      Message += ", ";
+    Message += Name;
+  }
+
+  Message += "' will be deleted as no accelerator tables are requested";
+
+  return Message;
+}
+
 Error linkDebugInfo(object::ObjectFile &File, const Options &Options,
                     raw_pwrite_stream &OutStream) {
 
@@ -288,12 +342,6 @@ Error linkDebugInfo(object::ObjectFile &File, const Options &Options,
 
   std::unique_ptr<DWARFContext> Context = DWARFContext::create(File);
 
-  uint16_t MaxDWARFVersion = 0;
-  std::function<void(const DWARFUnit &Unit)> OnCUDieLoaded =
-      [&MaxDWARFVersion](const DWARFUnit &Unit) {
-        MaxDWARFVersion = std::max(Unit.getVersion(), MaxDWARFVersion);
-      };
-
   // Create DWARF linker.
   DWARFLinker DebugInfoLinker(&OutStreamer, DwarfLinkerClient::LLD);
 
@@ -309,16 +357,6 @@ Error linkDebugInfo(object::ObjectFile &File, const Options &Options,
   std::vector<std::unique_ptr<AddressesMap>> AddresssMapForLinking(1);
   std::vector<std::string> EmptyWarnings;
 
-  // Unknown debug sections would be removed. Display warning
-  // for such sections.
-  for (SectionName Sec : Context->getDWARFObj().getSectionNames()) {
-    if (isDebugSection(Sec.Name) && !knownByDWARFUtil(Sec.Name))
-      warning(
-          formatv("'{0}' is not currently supported: section will be skipped",
-                  Sec.Name),
-          Options.InputFileName);
-  }
-
   // Add object files to the DWARFLinker.
   AddresssMapForLinking[0] =
       std::make_unique<ObjFileAddressMap>(*Context, Options, File);
@@ -327,6 +365,12 @@ Error linkDebugInfo(object::ObjectFile &File, const Options &Options,
       File.getFileName(), &*Context, AddresssMapForLinking[0].get(),
       EmptyWarnings);
 
+  uint16_t MaxDWARFVersion = 0;
+  std::function<void(const DWARFUnit &Unit)> OnCUDieLoaded =
+      [&MaxDWARFVersion](const DWARFUnit &Unit) {
+        MaxDWARFVersion = std::max(Unit.getVersion(), MaxDWARFVersion);
+      };
+
   for (size_t I = 0; I < ObjectsForLinking.size(); I++)
     DebugInfoLinker.addObjectFile(*ObjectsForLinking[I], nullptr,
                                   OnCUDieLoaded);
@@ -338,6 +382,61 @@ Error linkDebugInfo(object::ObjectFile &File, const Options &Options,
   if (Error Err = DebugInfoLinker.setTargetDWARFVersion(MaxDWARFVersion))
     return Err;
 
+  SmallVector<DwarfLinkerAccelTableKind> AccelTables;
+
+  switch (Options.AccelTableKind) {
+  case DwarfUtilAccelKind::None:
+    // Nothing to do.
+    break;
+  case DwarfUtilAccelKind::DWARF:
+    // use .debug_names for all DWARF versions.
+    AccelTables.push_back(DwarfLinkerAccelTableKind::DebugNames);
+    break;
+  }
+
+  // Add accelerator tables to DWARFLinker.
+  for (DwarfLinkerAccelTableKind Table : AccelTables)
+    DebugInfoLinker.addAccelTableKind(Table);
+
+  SmallVector<StringRef> AccelTableNamesToReplace;
+  SmallVector<StringRef> AccelTableNamesToDelete;
+
+  // Unknown debug sections or non-requested accelerator sections would be
+  // removed. Display warning for such sections.
+  for (SectionName Sec : Context->getDWARFObj().getSectionNames()) {
+    if (isDebugSection(Sec.Name)) {
+      std::optional<DwarfLinkerAccelTableKind> SrcAccelTableKind =
+          getAcceleratorTableKind(Sec.Name);
+
+      if (SrcAccelTableKind) {
+        assert(knownByDWARFUtil(Sec.Name));
+
+        if (Options.AccelTableKind == DwarfUtilAccelKind::None)
+          AccelTableNamesToDelete.push_back(Sec.Name);
+        else if (std::find(AccelTables.begin(), AccelTables.end(),
+                           *SrcAccelTableKind) == AccelTables.end())
+          AccelTableNamesToReplace.push_back(Sec.Name);
+      } else if (!knownByDWARFUtil(Sec.Name)) {
+        assert(!SrcAccelTableKind);
+        warning(
+            formatv("'{0}' is not currently supported: section will be skipped",
+                    Sec.Name),
+            Options.InputFileName);
+      }
+    }
+  }
+
+  // Display message for the replaced accelerator tables.
+  if (!AccelTableNamesToReplace.empty())
+    warning(getMessageForReplacedAcceleratorTables(AccelTableNamesToReplace,
+                                                   Options.AccelTableKind),
+            Options.InputFileName);
+
+  // Display message for the removed accelerator tables.
+  if (!AccelTableNamesToDelete.empty())
+    warning(getMessageForDeletedAcceleratorTables(AccelTableNamesToDelete),
+            Options.InputFileName);
+
   // Link debug info.
   if (Error Err = DebugInfoLinker.link())
     return Err;

diff  --git a/llvm/tools/llvm-dwarfutil/Options.h b/llvm/tools/llvm-dwarfutil/Options.h
index c993200ceb4b7..38fa2b9eda631 100644
--- a/llvm/tools/llvm-dwarfutil/Options.h
+++ b/llvm/tools/llvm-dwarfutil/Options.h
@@ -24,6 +24,12 @@ enum class TombstoneKind {
   Exec,      /// match with address range of executable sections.
 };
 
+/// The kind of accelerator table.
+enum class DwarfUtilAccelKind : uint8_t {
+  None,
+  DWARF // DWARFv5: .debug_names
+};
+
 struct Options {
   std::string InputFileName;
   std::string OutputFileName;
@@ -34,6 +40,7 @@ struct Options {
   bool Verbose = false;
   int NumThreads = 0;
   bool Verify = false;
+  DwarfUtilAccelKind AccelTableKind = DwarfUtilAccelKind::None;
 
   std::string getSeparateDebugFileName() const {
     return OutputFileName + ".debug";

diff  --git a/llvm/tools/llvm-dwarfutil/Options.td b/llvm/tools/llvm-dwarfutil/Options.td
index 4ab1b51d808d8..d4541188c0c2a 100644
--- a/llvm/tools/llvm-dwarfutil/Options.td
+++ b/llvm/tools/llvm-dwarfutil/Options.td
@@ -5,6 +5,14 @@ multiclass BB<string name, string help1, string help2> {
   def no_ # NAME: Flag<["--"], "no-" # name>, HelpText<help2>;
 }
 
+def build_accelerator: Separate<["--", "-"], "build-accelerator">,
+  MetaVarName<"[none,DWARF]">,
+  HelpText<"Build accelerator tables(default: none)\n"
+  "    =none - Do not build accelerators\n"
+  "    =DWARF - .debug_names are generated for all DWARF versions\n"
+  >;
+def: Joined<["--", "-"], "build-accelerator=">, Alias<build_accelerator>;
+
 def help : Flag<["--"], "help">,
   HelpText<"Prints this help output">;
 

diff  --git a/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp b/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
index 0e87c1370fd3d..74b6104bc6689 100644
--- a/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
+++ b/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
@@ -123,6 +123,19 @@ static Error validateAndSetOptions(opt::InputArgList &Args, Options &Options) {
           formatv("unknown tombstone value: '{0}'", S).str().c_str());
   }
 
+  if (opt::Arg *BuildAccelerator = Args.getLastArg(OPT_build_accelerator)) {
+    StringRef S = BuildAccelerator->getValue();
+
+    if (S == "none")
+      Options.AccelTableKind = DwarfUtilAccelKind::None;
+    else if (S == "DWARF")
+      Options.AccelTableKind = DwarfUtilAccelKind::DWARF;
+    else
+      return createStringError(
+          std::errc::invalid_argument,
+          formatv("unknown build-accelerator value: '{0}'", S).str().c_str());
+  }
+
   if (Options.Verbose) {
     if (Options.NumThreads != 1 && Args.hasArg(OPT_threads))
       warning("--num-threads set to 1 because verbose mode is specified");
@@ -423,8 +436,9 @@ static Error saveCopyOfFile(const Options &Opts, ObjectFile &InputFile) {
 }
 
 static Error applyCLOptions(const struct Options &Opts, ObjectFile &InputFile) {
-  if (Opts.DoGarbageCollection) {
-    verbose("Do garbage collection for debug info ...", Opts.Verbose);
+  if (Opts.DoGarbageCollection ||
+      Opts.AccelTableKind != DwarfUtilAccelKind::None) {
+    verbose("Do debug info linking...", Opts.Verbose);
 
     DebugInfoBits LinkedDebugInfo;
     raw_svector_ostream OutStream(LinkedDebugInfo);

diff  --git a/llvm/unittests/CodeGen/TestAsmPrinter.cpp b/llvm/unittests/CodeGen/TestAsmPrinter.cpp
index b651fcfcb2dfd..7f6b52df39af6 100644
--- a/llvm/unittests/CodeGen/TestAsmPrinter.cpp
+++ b/llvm/unittests/CodeGen/TestAsmPrinter.cpp
@@ -80,11 +80,5 @@ llvm::Error TestAsmPrinter::init(const Target *TheTarget, StringRef TripleName,
 }
 
 void TestAsmPrinter::setDwarfUsesRelocationsAcrossSections(bool Enable) {
-  struct HackMCAsmInfo : MCAsmInfo {
-    void setDwarfUsesRelocationsAcrossSections(bool Enable) {
-      DwarfUsesRelocationsAcrossSections = Enable;
-    }
-  };
-  static_cast<HackMCAsmInfo *>(const_cast<MCAsmInfo *>(TM->getMCAsmInfo()))
-      ->setDwarfUsesRelocationsAcrossSections(Enable);
+  Asm->setDwarfUsesRelocationsAcrossSections(Enable);
 }


        


More information about the llvm-commits mailing list