[lld] 908b780 - [LLD] Move duplicated dwarf parsing code to the Common library. NFC.

Martin Storsjo via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 21 01:00:39 PDT 2019


Author: Martin Storsjo
Date: 2019-10-21T08:01:52Z
New Revision: 908b780952d965d344b7fd85358d933272922c10

URL: https://github.com/llvm/llvm-project/commit/908b780952d965d344b7fd85358d933272922c10
DIFF: https://github.com/llvm/llvm-project/commit/908b780952d965d344b7fd85358d933272922c10.diff

LOG: [LLD] Move duplicated dwarf parsing code to the Common library. NFC.

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

llvm-svn: 375390

Added: 
    lld/Common/DWARF.cpp
    lld/include/lld/Common/DWARF.h

Modified: 
    lld/COFF/InputFiles.cpp
    lld/COFF/InputFiles.h
    lld/Common/CMakeLists.txt
    lld/ELF/InputFiles.cpp
    lld/ELF/InputFiles.h

Removed: 
    


################################################################################
diff  --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp
index 8770a870ddb8..4097cda59579 100644
--- a/lld/COFF/InputFiles.cpp
+++ b/lld/COFF/InputFiles.cpp
@@ -795,81 +795,16 @@ void ObjFile::initializeDependencies() {
 Optional<std::pair<StringRef, uint32_t>>
 ObjFile::getVariableLocation(StringRef var) {
   if (!dwarf) {
-    dwarf = DWARFContext::create(*getCOFFObj());
+    dwarf = make<DWARFCache>(DWARFContext::create(*getCOFFObj()));
     if (!dwarf)
       return None;
-    initializeDwarf();
   }
   if (config->machine == I386)
     var.consume_front("_");
-  auto it = variableLoc.find(var);
-  if (it == variableLoc.end())
+  Optional<std::pair<std::string, unsigned>> ret = dwarf->getVariableLoc(var);
+  if (!ret)
     return None;
-
-  // Take file name string from line table.
-  std::string fileName;
-  if (!it->second.lt->getFileNameByIndex(
-          it->second.file, {},
-          DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, fileName))
-    return None;
-
-  return std::make_pair(saver.save(fileName), it->second.line);
-}
-
-// Used only for DWARF debug info, which is not common (except in MinGW
-// environments). This initializes the dwarf, lineTables and variableLoc
-// members.
-void ObjFile::initializeDwarf() {
-  for (std::unique_ptr<DWARFUnit> &cu : dwarf->compile_units()) {
-    auto report = [](Error err) {
-      handleAllErrors(std::move(err),
-                      [](ErrorInfoBase &info) { warn(info.message()); });
-    };
-    Expected<const DWARFDebugLine::LineTable *> expectedLT =
-        dwarf->getLineTableForUnit(cu.get(), report);
-    const DWARFDebugLine::LineTable *lt = nullptr;
-    if (expectedLT)
-      lt = *expectedLT;
-    else
-      report(expectedLT.takeError());
-    if (!lt)
-      continue;
-    lineTables.push_back(lt);
-
-    // Loop over variable records and insert them to variableLoc.
-    for (const auto &entry : cu->dies()) {
-      DWARFDie die(cu.get(), &entry);
-      // Skip all tags that are not variables.
-      if (die.getTag() != dwarf::DW_TAG_variable)
-        continue;
-
-      // Skip if a local variable because we don't need them for generating
-      // error messages. In general, only non-local symbols can fail to be
-      // linked.
-      if (!dwarf::toUnsigned(die.find(dwarf::DW_AT_external), 0))
-        continue;
-
-      // Get the source filename index for the variable.
-      unsigned file = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_file), 0);
-      if (!lt->hasFileAtIndex(file))
-        continue;
-
-      // Get the line number on which the variable is declared.
-      unsigned line = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_line), 0);
-
-      // Here we want to take the variable name to add it into variableLoc.
-      // Variable can have regular and linkage name associated. At first, we try
-      // to get linkage name as it can be 
diff erent, for example when we have
-      // two variables in 
diff erent namespaces of the same object. Use common
-      // name otherwise, but handle the case when it also absent in case if the
-      // input object file lacks some debug info.
-      StringRef name =
-          dwarf::toString(die.find(dwarf::DW_AT_linkage_name),
-                          dwarf::toString(die.find(dwarf::DW_AT_name), ""));
-      if (!name.empty())
-        variableLoc.insert({name, {lt, file, line}});
-    }
-  }
+  return std::make_pair(saver.save(ret->first), ret->second);
 }
 
 StringRef ltrim1(StringRef s, const char *chars) {

diff  --git a/lld/COFF/InputFiles.h b/lld/COFF/InputFiles.h
index d3f4cd7bb2f5..66249715e216 100644
--- a/lld/COFF/InputFiles.h
+++ b/lld/COFF/InputFiles.h
@@ -10,13 +10,13 @@
 #define LLD_COFF_INPUT_FILES_H
 
 #include "Config.h"
+#include "lld/Common/DWARF.h"
 #include "lld/Common/LLVM.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/BinaryFormat/Magic.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/LTO/LTO.h"
 #include "llvm/Object/Archive.h"
 #include "llvm/Object/COFF.h"
@@ -216,7 +216,6 @@ class ObjFile : public InputFile {
   void initializeSymbols();
   void initializeFlags();
   void initializeDependencies();
-  void initializeDwarf();
 
   SectionChunk *
   readSection(uint32_t sectionNumber,
@@ -291,14 +290,7 @@ class ObjFile : public InputFile {
   // symbols in the real symbol table) are filled with null pointers.
   std::vector<Symbol *> symbols;
 
-  std::unique_ptr<llvm::DWARFContext> dwarf;
-  std::vector<const llvm::DWARFDebugLine::LineTable *> lineTables;
-  struct VarLoc {
-    const llvm::DWARFDebugLine::LineTable *lt;
-    unsigned file;
-    unsigned line;
-  };
-  llvm::DenseMap<StringRef, VarLoc> variableLoc;
+  DWARFCache *dwarf;
 };
 
 // This type represents import library members that contain DLL names

diff  --git a/lld/Common/CMakeLists.txt b/lld/Common/CMakeLists.txt
index 70849cc7b94b..1a04a8074bed 100644
--- a/lld/Common/CMakeLists.txt
+++ b/lld/Common/CMakeLists.txt
@@ -29,6 +29,7 @@ set_property(SOURCE Version.cpp APPEND PROPERTY
 
 add_lld_library(lldCommon
   Args.cpp
+  DWARF.cpp
   ErrorHandler.cpp
   Filesystem.cpp
   Memory.cpp
@@ -46,6 +47,7 @@ add_lld_library(lldCommon
   LINK_COMPONENTS
   Codegen
   Core
+  DebugInfoDWARF
   Demangle
   MC
   Option

diff  --git a/lld/Common/DWARF.cpp b/lld/Common/DWARF.cpp
new file mode 100644
index 000000000000..077adbcaf858
--- /dev/null
+++ b/lld/Common/DWARF.cpp
@@ -0,0 +1,103 @@
+//===- DWARF.cpp ----------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/Common/DWARF.h"
+#include "lld/Common/ErrorHandler.h"
+
+using namespace llvm;
+
+namespace lld {
+
+DWARFCache::DWARFCache(std::unique_ptr<llvm::DWARFContext> d)
+    : dwarf(std::move(d)) {
+  for (std::unique_ptr<DWARFUnit> &cu : dwarf->compile_units()) {
+    auto report = [](Error err) {
+      handleAllErrors(std::move(err),
+                      [](ErrorInfoBase &info) { warn(info.message()); });
+    };
+    Expected<const DWARFDebugLine::LineTable *> expectedLT =
+        dwarf->getLineTableForUnit(cu.get(), report);
+    const DWARFDebugLine::LineTable *lt = nullptr;
+    if (expectedLT)
+      lt = *expectedLT;
+    else
+      report(expectedLT.takeError());
+    if (!lt)
+      continue;
+    lineTables.push_back(lt);
+
+    // Loop over variable records and insert them to variableLoc.
+    for (const auto &entry : cu->dies()) {
+      DWARFDie die(cu.get(), &entry);
+      // Skip all tags that are not variables.
+      if (die.getTag() != dwarf::DW_TAG_variable)
+        continue;
+
+      // Skip if a local variable because we don't need them for generating
+      // error messages. In general, only non-local symbols can fail to be
+      // linked.
+      if (!dwarf::toUnsigned(die.find(dwarf::DW_AT_external), 0))
+        continue;
+
+      // Get the source filename index for the variable.
+      unsigned file = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_file), 0);
+      if (!lt->hasFileAtIndex(file))
+        continue;
+
+      // Get the line number on which the variable is declared.
+      unsigned line = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_line), 0);
+
+      // Here we want to take the variable name to add it into variableLoc.
+      // Variable can have regular and linkage name associated. At first, we try
+      // to get linkage name as it can be 
diff erent, for example when we have
+      // two variables in 
diff erent namespaces of the same object. Use common
+      // name otherwise, but handle the case when it also absent in case if the
+      // input object file lacks some debug info.
+      StringRef name =
+          dwarf::toString(die.find(dwarf::DW_AT_linkage_name),
+                          dwarf::toString(die.find(dwarf::DW_AT_name), ""));
+      if (!name.empty())
+        variableLoc.insert({name, {lt, file, line}});
+    }
+  }
+}
+
+// Returns the pair of file name and line number describing location of data
+// object (variable, array, etc) definition.
+Optional<std::pair<std::string, unsigned>>
+DWARFCache::getVariableLoc(StringRef name) {
+  // Return if we have no debug information about data object.
+  auto it = variableLoc.find(name);
+  if (it == variableLoc.end())
+    return None;
+
+  // Take file name string from line table.
+  std::string fileName;
+  if (!it->second.lt->getFileNameByIndex(
+          it->second.file, {},
+          DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, fileName))
+    return None;
+
+  return std::make_pair(fileName, it->second.line);
+}
+
+// Returns source line information for a given offset
+// using DWARF debug info.
+Optional<DILineInfo> DWARFCache::getDILineInfo(uint64_t offset,
+                                               uint64_t sectionIndex) {
+  DILineInfo info;
+  for (const llvm::DWARFDebugLine::LineTable *lt : lineTables) {
+    if (lt->getFileLineInfoForAddress(
+            {offset, sectionIndex}, nullptr,
+            DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, info))
+      return info;
+  }
+  return None;
+}
+
+} // namespace lld

diff  --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index b0389ccf100a..fdf935a30856 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -17,7 +17,6 @@
 #include "lld/Common/Memory.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/CodeGen/Analysis.h"
-#include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
 #include "llvm/LTO/LTO.h"
@@ -265,57 +264,8 @@ std::string InputFile::getSrcMsg(const Symbol &sym, InputSectionBase &sec,
 }
 
 template <class ELFT> void ObjFile<ELFT>::initializeDwarf() {
-  dwarf = std::make_unique<DWARFContext>(std::make_unique<LLDDwarfObj<ELFT>>(this));
-  for (std::unique_ptr<DWARFUnit> &cu : dwarf->compile_units()) {
-    auto report = [](Error err) {
-      handleAllErrors(std::move(err),
-                      [](ErrorInfoBase &info) { warn(info.message()); });
-    };
-    Expected<const DWARFDebugLine::LineTable *> expectedLT =
-        dwarf->getLineTableForUnit(cu.get(), report);
-    const DWARFDebugLine::LineTable *lt = nullptr;
-    if (expectedLT)
-      lt = *expectedLT;
-    else
-      report(expectedLT.takeError());
-    if (!lt)
-      continue;
-    lineTables.push_back(lt);
-
-    // Loop over variable records and insert them to variableLoc.
-    for (const auto &entry : cu->dies()) {
-      DWARFDie die(cu.get(), &entry);
-      // Skip all tags that are not variables.
-      if (die.getTag() != dwarf::DW_TAG_variable)
-        continue;
-
-      // Skip if a local variable because we don't need them for generating
-      // error messages. In general, only non-local symbols can fail to be
-      // linked.
-      if (!dwarf::toUnsigned(die.find(dwarf::DW_AT_external), 0))
-        continue;
-
-      // Get the source filename index for the variable.
-      unsigned file = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_file), 0);
-      if (!lt->hasFileAtIndex(file))
-        continue;
-
-      // Get the line number on which the variable is declared.
-      unsigned line = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_line), 0);
-
-      // Here we want to take the variable name to add it into variableLoc.
-      // Variable can have regular and linkage name associated. At first, we try
-      // to get linkage name as it can be 
diff erent, for example when we have
-      // two variables in 
diff erent namespaces of the same object. Use common
-      // name otherwise, but handle the case when it also absent in case if the
-      // input object file lacks some debug info.
-      StringRef name =
-          dwarf::toString(die.find(dwarf::DW_AT_linkage_name),
-                          dwarf::toString(die.find(dwarf::DW_AT_name), ""));
-      if (!name.empty())
-        variableLoc.insert({name, {lt, file, line}});
-    }
-  }
+  dwarf = make<DWARFCache>(std::make_unique<DWARFContext>(
+      std::make_unique<LLDDwarfObj<ELFT>>(this)));
 }
 
 // Returns the pair of file name and line number describing location of data
@@ -325,19 +275,7 @@ Optional<std::pair<std::string, unsigned>>
 ObjFile<ELFT>::getVariableLoc(StringRef name) {
   llvm::call_once(initDwarfLine, [this]() { initializeDwarf(); });
 
-  // Return if we have no debug information about data object.
-  auto it = variableLoc.find(name);
-  if (it == variableLoc.end())
-    return None;
-
-  // Take file name string from line table.
-  std::string fileName;
-  if (!it->second.lt->getFileNameByIndex(
-          it->second.file, {},
-          DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, fileName))
-    return None;
-
-  return std::make_pair(fileName, it->second.line);
+  return dwarf->getVariableLoc(name);
 }
 
 // Returns source line information for a given offset
@@ -359,14 +297,7 @@ Optional<DILineInfo> ObjFile<ELFT>::getDILineInfo(InputSectionBase *s,
 
   // Use fake address calcuated by adding section file offset and offset in
   // section. See comments for ObjectInfo class.
-  DILineInfo info;
-  for (const llvm::DWARFDebugLine::LineTable *lt : lineTables) {
-    if (lt->getFileLineInfoForAddress(
-            {s->getOffsetInFile() + offset, sectionIndex}, nullptr,
-            DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, info))
-      return info;
-  }
-  return None;
+  return dwarf->getDILineInfo(s->getOffsetInFile() + offset, sectionIndex);
 }
 
 ELFFileBase::ELFFileBase(Kind k, MemoryBufferRef mb) : InputFile(k, mb) {

diff  --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h
index 1c78654d00fc..cde6bc617764 100644
--- a/lld/ELF/InputFiles.h
+++ b/lld/ELF/InputFiles.h
@@ -10,13 +10,13 @@
 #define LLD_ELF_INPUT_FILES_H
 
 #include "Config.h"
+#include "lld/Common/DWARF.h"
 #include "lld/Common/ErrorHandler.h"
 #include "lld/Common/LLVM.h"
 #include "lld/Common/Reproduce.h"
 #include "llvm/ADT/CachedHashString.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/STLExtras.h"
-#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
 #include "llvm/IR/Comdat.h"
 #include "llvm/Object/Archive.h"
 #include "llvm/Object/ELF.h"
@@ -26,7 +26,6 @@
 
 namespace llvm {
 class TarWriter;
-struct DILineInfo;
 namespace lto {
 class InputFile;
 }
@@ -282,14 +281,7 @@ template <class ELFT> class ObjFile : public ELFFileBase {
   // reporting. Linker may find reasonable number of errors in a
   // single object file, so we cache debugging information in order to
   // parse it only once for each object file we link.
-  std::unique_ptr<llvm::DWARFContext> dwarf;
-  std::vector<const llvm::DWARFDebugLine::LineTable *> lineTables;
-  struct VarLoc {
-    const llvm::DWARFDebugLine::LineTable *lt;
-    unsigned file;
-    unsigned line;
-  };
-  llvm::DenseMap<StringRef, VarLoc> variableLoc;
+  DWARFCache *dwarf;
   llvm::once_flag initDwarfLine;
 };
 

diff  --git a/lld/include/lld/Common/DWARF.h b/lld/include/lld/Common/DWARF.h
new file mode 100644
index 000000000000..f0d3d2fbda77
--- /dev/null
+++ b/lld/include/lld/Common/DWARF.h
@@ -0,0 +1,47 @@
+//===- DWARF.h --------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_DWARF_H
+#define LLD_DWARF_H
+
+#include "lld/Common/LLVM.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
+#include <memory>
+#include <string>
+
+namespace llvm {
+struct DILineInfo;
+} // namespace llvm
+
+namespace lld {
+
+class DWARFCache {
+public:
+  DWARFCache(std::unique_ptr<llvm::DWARFContext> dwarf);
+  llvm::Optional<llvm::DILineInfo> getDILineInfo(uint64_t offset,
+                                                 uint64_t sectionIndex);
+  llvm::Optional<std::pair<std::string, unsigned>>
+  getVariableLoc(StringRef name);
+
+private:
+  std::unique_ptr<llvm::DWARFContext> dwarf;
+  std::vector<const llvm::DWARFDebugLine::LineTable *> lineTables;
+  struct VarLoc {
+    const llvm::DWARFDebugLine::LineTable *lt;
+    unsigned file;
+    unsigned line;
+  };
+  llvm::DenseMap<StringRef, VarLoc> variableLoc;
+};
+
+} // namespace lld
+
+#endif


        


More information about the llvm-commits mailing list