[llvm] Reduce llvm-gsymutil memory usage (PR #139907)

via llvm-commits llvm-commits at lists.llvm.org
Thu May 15 06:01:01 PDT 2025


https://github.com/peremyach updated https://github.com/llvm/llvm-project/pull/139907

>From d92d7da4c9274a8f4ce69323a47f04d3dd6dd9a1 Mon Sep 17 00:00:00 2001
From: Arslan Khabutdinov <akhabutdinov at fb.com>
Date: Wed, 14 May 2025 02:56:12 -0700
Subject: [PATCH] Reduce llvm-gsymutil memory usage

---
 .../llvm/DebugInfo/DWARF/DWARFContext.h       |  16 +-
 llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h |  22 +-
 llvm/lib/DebugInfo/DWARF/DWARFContext.cpp     | 177 +++++------
 llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp        | 278 ++++++++++--------
 llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp  |  35 ++-
 5 files changed, 271 insertions(+), 257 deletions(-)

diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
index 6df3f5066e327..4cb1033aab8e4 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h
@@ -66,6 +66,7 @@ class DWARFContext : public DIContext {
     };
 
     DWARFContext &D;
+
   public:
     DWARFContextState(DWARFContext &DC) : D(DC) {}
     virtual ~DWARFContextState() = default;
@@ -79,8 +80,8 @@ class DWARFContext : public DIContext {
     virtual const DWARFDebugLoc *getDebugLoc() = 0;
     virtual const DWARFDebugAranges *getDebugAranges() = 0;
     virtual Expected<const DWARFDebugLine::LineTable *>
-        getLineTableForUnit(DWARFUnit *U,
-                            function_ref<void(Error)> RecoverableErrHandler) = 0;
+    getLineTableForUnit(DWARFUnit *U,
+                        function_ref<void(Error)> RecoverableErrHandler) = 0;
     virtual void clearLineTableForUnit(DWARFUnit *U) = 0;
     virtual Expected<const DWARFDebugFrame *> getDebugFrame() = 0;
     virtual Expected<const DWARFDebugFrame *> getEHFrame() = 0;
@@ -94,7 +95,7 @@ class DWARFContext : public DIContext {
     virtual const AppleAcceleratorTable &getAppleNamespaces() = 0;
     virtual const AppleAcceleratorTable &getAppleObjC() = 0;
     virtual std::shared_ptr<DWARFContext>
-        getDWOContext(StringRef AbsolutePath) = 0;
+    getDWOContext(StringRef AbsolutePath) = 0;
     virtual const DenseMap<uint64_t, DWARFTypeUnit *> &
     getTypeUnitMap(bool IsDWO) = 0;
     virtual bool isThreadSafe() const = 0;
@@ -103,6 +104,7 @@ class DWARFContext : public DIContext {
     std::unique_ptr<DWARFDebugMacro>
     parseMacroOrMacinfo(MacroSecType SectionType);
 
+    virtual void doWorkThreadSafely(function_ref<void()> Work) = 0;
   };
   friend class DWARFContextState;
 
@@ -205,9 +207,7 @@ class DWARFContext : public DIContext {
                                DWOUnits.begin() + DWOUnits.getNumInfoUnits());
   }
 
-  const DWARFUnitVector &getDWOUnitsVector() {
-    return State->getDWOUnits();
-  }
+  const DWARFUnitVector &getDWOUnitsVector() { return State->getDWOUnits(); }
 
   /// Return true of this DWARF context is a DWP file.
   bool isDWP() const;
@@ -491,6 +491,10 @@ class DWARFContext : public DIContext {
   /// manually only for DWARF5.
   void setParseCUTUIndexManually(bool PCUTU) { ParseCUTUIndexManually = PCUTU; }
 
+  void doWorkThreadSafely(function_ref<void()> Work) {
+    State->doWorkThreadSafely(Work);
+  }
+
 private:
   void addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram, DWARFDie Die,
                        std::vector<DILocal> &Result);
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h
index 80c27aea89312..75a800bdf017a 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h
@@ -27,6 +27,7 @@
 #include <cstdint>
 #include <map>
 #include <memory>
+#include <mutex>
 #include <set>
 #include <utility>
 #include <vector>
@@ -125,7 +126,8 @@ bool isCompileUnit(const std::unique_ptr<DWARFUnit> &U);
 
 /// Describe a collection of units. Intended to hold all units either from
 /// .debug_info and .debug_types, or from .debug_info.dwo and .debug_types.dwo.
-class DWARFUnitVector final : public SmallVector<std::unique_ptr<DWARFUnit>, 1> {
+class DWARFUnitVector final
+    : public SmallVector<std::unique_ptr<DWARFUnit>, 1> {
   std::function<std::unique_ptr<DWARFUnit>(uint64_t, DWARFSectionKind,
                                            const DWARFSection *,
                                            const DWARFUnitIndex::Entry *)>
@@ -137,8 +139,8 @@ class DWARFUnitVector final : public SmallVector<std::unique_ptr<DWARFUnit>, 1>
   using iterator = typename UnitVector::iterator;
   using iterator_range = llvm::iterator_range<typename UnitVector::iterator>;
 
-  using compile_unit_range =
-      decltype(make_filter_range(std::declval<iterator_range>(), isCompileUnit));
+  using compile_unit_range = decltype(make_filter_range(
+      std::declval<iterator_range>(), isCompileUnit));
 
   DWARFUnit *getUnitForOffset(uint64_t Offset) const;
   DWARFUnit *getUnitForIndexEntry(const DWARFUnitIndex::Entry &E);
@@ -257,6 +259,8 @@ class DWARFUnit {
 
   std::shared_ptr<DWARFUnit> DWO;
 
+  mutable std::recursive_mutex FreeDIEsMutex;
+
 protected:
   friend dwarf_linker::parallel::CompileUnit;
 
@@ -316,7 +320,7 @@ class DWARFUnit {
 
   bool isLittleEndian() const { return IsLittleEndian; }
   bool isDWOUnit() const { return IsDWO; }
-  DWARFContext& getContext() const { return Context; }
+  DWARFContext &getContext() const { return Context; }
   const DWARFSection &getInfoSection() const { return InfoSection; }
   uint64_t getOffset() const { return Header.getOffset(); }
   const dwarf::FormParams &getFormParams() const {
@@ -377,9 +381,7 @@ class DWARFUnit {
     RangeSectionBase = Base;
   }
 
-  uint64_t getLocSectionBase() const {
-    return LocSectionBase;
-  }
+  uint64_t getLocSectionBase() const { return LocSectionBase; }
 
   std::optional<object::SectionedAddress>
   getAddrOffsetSectionItem(uint32_t Index) const;
@@ -566,6 +568,9 @@ class DWARFUnit {
 
   Error tryExtractDIEsIfNeeded(bool CUDieOnly);
 
+  /// clearDIEs - Clear parsed DIEs to keep memory usage low.
+  void clearDIEs(bool KeepCUDie, bool KeepDWODies = false);
+
 private:
   /// Size in bytes of the .debug_info data associated with this compile unit.
   size_t getDebugInfoSize() const {
@@ -581,9 +586,6 @@ class DWARFUnit {
   void extractDIEsToVector(bool AppendCUDie, bool AppendNonCUDIEs,
                            std::vector<DWARFDebugInfoEntry> &DIEs) const;
 
-  /// clearDIEs - Clear parsed DIEs to keep memory usage low.
-  void clearDIEs(bool KeepCUDie);
-
   /// parseDWO - Parses .dwo file for current compile unit. Returns true if
   /// it was actually constructed.
   /// The \p AlternativeLocation specifies an alternative location to get
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index e76e518ef8595..907f8e3eba8b6 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -68,7 +68,6 @@ using DWARFLineTable = DWARFDebugLine::LineTable;
 using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind;
 using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind;
 
-
 void fixupIndexV4(DWARFContext &C, DWARFUnitIndex &Index) {
   using EntryType = DWARFUnitIndex::Entry::SectionContribution;
   using EntryMap = DenseMap<uint32_t, EntryType>;
@@ -201,7 +200,6 @@ static T &getAccelTable(std::unique_ptr<T> &Cache, const DWARFObject &Obj,
   return *Cache;
 }
 
-
 std::unique_ptr<DWARFDebugMacro>
 DWARFContext::DWARFContextState::parseMacroOrMacinfo(MacroSecType SectionType) {
   auto Macro = std::make_unique<DWARFDebugMacro>();
@@ -281,9 +279,8 @@ class ThreadUnsafeDWARFContextState : public DWARFContext::DWARFContextState {
   std::string DWPName;
 
 public:
-  ThreadUnsafeDWARFContextState(DWARFContext &DC, std::string &DWP) :
-      DWARFContext::DWARFContextState(DC),
-      DWPName(std::move(DWP)) {}
+  ThreadUnsafeDWARFContextState(DWARFContext &DC, std::string &DWP)
+      : DWARFContext::DWARFContextState(DC), DWPName(std::move(DWP)) {}
 
   DWARFUnitVector &getNormalUnits() override {
     if (NormalUnits.empty()) {
@@ -327,8 +324,8 @@ class ThreadUnsafeDWARFContextState : public DWARFContext::DWARFContextState {
     if (CUIndex)
       return *CUIndex;
 
-    DataExtractor Data(D.getDWARFObj().getCUIndexSection(),
-                       D.isLittleEndian(), 0);
+    DataExtractor Data(D.getDWARFObj().getCUIndexSection(), D.isLittleEndian(),
+                       0);
     CUIndex = std::make_unique<DWARFUnitIndex>(DW_SECT_INFO);
     if (CUIndex->parse(Data))
       fixupIndex(D, *CUIndex);
@@ -338,8 +335,8 @@ class ThreadUnsafeDWARFContextState : public DWARFContext::DWARFContextState {
     if (TUIndex)
       return *TUIndex;
 
-    DataExtractor Data(D.getDWARFObj().getTUIndexSection(),
-                       D.isLittleEndian(), 0);
+    DataExtractor Data(D.getDWARFObj().getTUIndexSection(), D.isLittleEndian(),
+                       0);
     TUIndex = std::make_unique<DWARFUnitIndex>(DW_SECT_EXT_TYPES);
     bool isParseSuccessful = TUIndex->parse(Data);
     // If we are parsing TU-index and for .debug_types section we don't need
@@ -363,8 +360,8 @@ class ThreadUnsafeDWARFContextState : public DWARFContext::DWARFContextState {
     if (Abbrev)
       return Abbrev.get();
 
-    DataExtractor Data(D.getDWARFObj().getAbbrevSection(),
-                       D.isLittleEndian(), 0);
+    DataExtractor Data(D.getDWARFObj().getAbbrevSection(), D.isLittleEndian(),
+                       0);
     Abbrev = std::make_unique<DWARFDebugAbbrev>(Data);
     return Abbrev.get();
   }
@@ -393,8 +390,9 @@ class ThreadUnsafeDWARFContextState : public DWARFContext::DWARFContextState {
     return Aranges.get();
   }
 
-  Expected<const DWARFDebugLine::LineTable *>
-  getLineTableForUnit(DWARFUnit *U, function_ref<void(Error)> RecoverableErrorHandler) override {
+  Expected<const DWARFDebugLine::LineTable *> getLineTableForUnit(
+      DWARFUnit *U,
+      function_ref<void(Error)> RecoverableErrorHandler) override {
     if (!Line)
       Line = std::make_unique<DWARFDebugLine>();
 
@@ -420,7 +418,6 @@ class ThreadUnsafeDWARFContextState : public DWARFContext::DWARFContextState {
                             U->isLittleEndian(), U->getAddressByteSize());
     return Line->getOrParseLineTable(Data, stmtOffset, U->getContext(), U,
                                      RecoverableErrorHandler);
-
   }
 
   void clearLineTableForUnit(DWARFUnit *U) override {
@@ -445,20 +442,19 @@ class ThreadUnsafeDWARFContextState : public DWARFContext::DWARFContextState {
     const DWARFObject &DObj = D.getDWARFObj();
     const DWARFSection &DS = DObj.getFrameSection();
 
-    // There's a "bug" in the DWARFv3 standard with respect to the target address
-    // size within debug frame sections. While DWARF is supposed to be independent
-    // of its container, FDEs have fields with size being "target address size",
-    // which isn't specified in DWARF in general. It's only specified for CUs, but
-    // .eh_frame can appear without a .debug_info section. Follow the example of
-    // other tools (libdwarf) and extract this from the container (ObjectFile
-    // provides this information). This problem is fixed in DWARFv4
-    // See this dwarf-discuss discussion for more details:
+    // There's a "bug" in the DWARFv3 standard with respect to the target
+    // address size within debug frame sections. While DWARF is supposed to be
+    // independent of its container, FDEs have fields with size being "target
+    // address size", which isn't specified in DWARF in general. It's only
+    // specified for CUs, but .eh_frame can appear without a .debug_info
+    // section. Follow the example of other tools (libdwarf) and extract this
+    // from the container (ObjectFile provides this information). This problem
+    // is fixed in DWARFv4 See this dwarf-discuss discussion for more details:
     // http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html
     DWARFDataExtractor Data(DObj, DS, D.isLittleEndian(),
                             DObj.getAddressSize());
-    auto DF =
-        std::make_unique<DWARFDebugFrame>(D.getArch(), /*IsEH=*/false,
-                                          DS.Address);
+    auto DF = std::make_unique<DWARFDebugFrame>(D.getArch(), /*IsEH=*/false,
+                                                DS.Address);
     if (Error E = DF->parse(Data))
       return std::move(E);
 
@@ -474,9 +470,8 @@ class ThreadUnsafeDWARFContextState : public DWARFContext::DWARFContextState {
     const DWARFSection &DS = DObj.getEHFrameSection();
     DWARFDataExtractor Data(DObj, DS, D.isLittleEndian(),
                             DObj.getAddressSize());
-    auto DF =
-        std::make_unique<DWARFDebugFrame>(D.getArch(), /*IsEH=*/true,
-                                          DS.Address);
+    auto DF = std::make_unique<DWARFDebugFrame>(D.getArch(), /*IsEH=*/true,
+                                                DS.Address);
     if (Error E = DF->parse(Data))
       return std::move(E);
     EHFrame.swap(DF);
@@ -512,20 +507,17 @@ class ThreadUnsafeDWARFContextState : public DWARFContext::DWARFContextState {
     const DWARFObject &DObj = D.getDWARFObj();
     return getAccelTable(AppleNames, DObj, DObj.getAppleNamesSection(),
                          DObj.getStrSection(), D.isLittleEndian());
-
   }
   const AppleAcceleratorTable &getAppleTypes() override {
     const DWARFObject &DObj = D.getDWARFObj();
     return getAccelTable(AppleTypes, DObj, DObj.getAppleTypesSection(),
                          DObj.getStrSection(), D.isLittleEndian());
-
   }
   const AppleAcceleratorTable &getAppleNamespaces() override {
     const DWARFObject &DObj = D.getDWARFObj();
     return getAccelTable(AppleNamespaces, DObj,
-                         DObj.getAppleNamespacesSection(),
-                         DObj.getStrSection(), D.isLittleEndian());
-
+                         DObj.getAppleNamespacesSection(), DObj.getStrSection(),
+                         D.isLittleEndian());
   }
   const AppleAcceleratorTable &getAppleObjC() override {
     const DWARFObject &DObj = D.getDWARFObj();
@@ -533,8 +525,7 @@ class ThreadUnsafeDWARFContextState : public DWARFContext::DWARFContextState {
                          DObj.getStrSection(), D.isLittleEndian());
   }
 
-  std::shared_ptr<DWARFContext>
-  getDWOContext(StringRef AbsolutePath) override {
+  std::shared_ptr<DWARFContext> getDWOContext(StringRef AbsolutePath) override {
     if (auto S = DWP.lock()) {
       DWARFContext *Ctxt = S->Context.get();
       return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
@@ -595,7 +586,7 @@ class ThreadUnsafeDWARFContextState : public DWARFContext::DWARFContextState {
   const DenseMap<uint64_t, DWARFTypeUnit *> &getNormalTypeUnitMap() {
     if (!NormalTypeUnits) {
       NormalTypeUnits.emplace();
-      for (const auto &U :D.normal_units()) {
+      for (const auto &U : D.normal_units()) {
         if (DWARFTypeUnit *TU = dyn_cast<DWARFTypeUnit>(U.get()))
           (*NormalTypeUnits)[TU->getTypeHash()] = TU;
       }
@@ -606,7 +597,7 @@ class ThreadUnsafeDWARFContextState : public DWARFContext::DWARFContextState {
   const DenseMap<uint64_t, DWARFTypeUnit *> &getDWOTypeUnitMap() {
     if (!DWOTypeUnits) {
       DWOTypeUnits.emplace();
-      for (const auto &U :D.dwo_units()) {
+      for (const auto &U : D.dwo_units()) {
         if (DWARFTypeUnit *TU = dyn_cast<DWARFTypeUnit>(U.get()))
           (*DWOTypeUnits)[TU->getTypeHash()] = TU;
       }
@@ -622,15 +613,15 @@ class ThreadUnsafeDWARFContextState : public DWARFContext::DWARFContextState {
       return getNormalTypeUnitMap();
   }
 
-
+  void doWorkThreadSafely(function_ref<void()> Work) override { Work(); }
 };
 
 class ThreadSafeState : public ThreadUnsafeDWARFContextState {
   std::recursive_mutex Mutex;
 
 public:
-  ThreadSafeState(DWARFContext &DC, std::string &DWP) :
-      ThreadUnsafeDWARFContextState(DC, DWP) {}
+  ThreadSafeState(DWARFContext &DC, std::string &DWP)
+      : ThreadUnsafeDWARFContextState(DC, DWP) {}
 
   DWARFUnitVector &getNormalUnits() override {
     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
@@ -672,10 +663,12 @@ class ThreadSafeState : public ThreadUnsafeDWARFContextState {
     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
     return ThreadUnsafeDWARFContextState::getDebugAranges();
   }
-  Expected<const DWARFDebugLine::LineTable *>
-  getLineTableForUnit(DWARFUnit *U, function_ref<void(Error)> RecoverableErrorHandler) override {
+  Expected<const DWARFDebugLine::LineTable *> getLineTableForUnit(
+      DWARFUnit *U,
+      function_ref<void(Error)> RecoverableErrorHandler) override {
     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
-    return ThreadUnsafeDWARFContextState::getLineTableForUnit(U, RecoverableErrorHandler);
+    return ThreadUnsafeDWARFContextState::getLineTableForUnit(
+        U, RecoverableErrorHandler);
   }
   void clearLineTableForUnit(DWARFUnit *U) override {
     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
@@ -725,8 +718,7 @@ class ThreadSafeState : public ThreadUnsafeDWARFContextState {
     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
     return ThreadUnsafeDWARFContextState::getAppleObjC();
   }
-  std::shared_ptr<DWARFContext>
-  getDWOContext(StringRef AbsolutePath) override {
+  std::shared_ptr<DWARFContext> getDWOContext(StringRef AbsolutePath) override {
     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
     return ThreadUnsafeDWARFContextState::getDWOContext(AbsolutePath);
   }
@@ -738,6 +730,11 @@ class ThreadSafeState : public ThreadUnsafeDWARFContextState {
     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
     return ThreadUnsafeDWARFContextState::getTypeUnitMap(IsDWO);
   }
+
+  void doWorkThreadSafely(function_ref<void()> Work) override {
+    std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
+    ThreadUnsafeDWARFContextState::doWorkThreadSafely(Work);
+  }
 };
 } // namespace
 
@@ -746,14 +743,13 @@ DWARFContext::DWARFContext(std::unique_ptr<const DWARFObject> DObj,
                            std::function<void(Error)> RecoverableErrorHandler,
                            std::function<void(Error)> WarningHandler,
                            bool ThreadSafe)
-    : DIContext(CK_DWARF),
-      RecoverableErrorHandler(RecoverableErrorHandler),
+    : DIContext(CK_DWARF), RecoverableErrorHandler(RecoverableErrorHandler),
       WarningHandler(WarningHandler), DObj(std::move(DObj)) {
-        if (ThreadSafe)
-          State = std::make_unique<ThreadSafeState>(*this, DWPName);
-        else
-          State = std::make_unique<ThreadUnsafeDWARFContextState>(*this, DWPName);
-      }
+  if (ThreadSafe)
+    State = std::make_unique<ThreadSafeState>(*this, DWPName);
+  else
+    State = std::make_unique<ThreadUnsafeDWARFContextState>(*this, DWPName);
+}
 
 DWARFContext::~DWARFContext() = default;
 
@@ -770,7 +766,7 @@ static void dumpUUID(raw_ostream &OS, const ObjectFile &Obj) {
         return;
       }
       OS << "UUID: ";
-      memcpy(&UUID, LC.Ptr+sizeof(LC.C), sizeof(UUID));
+      memcpy(&UUID, LC.Ptr + sizeof(LC.C), sizeof(UUID));
       OS.write_uuid(UUID);
       Triple T = MachO->getArchTriple();
       OS << " (" << T.getArchName() << ')';
@@ -944,7 +940,6 @@ static void dumpRnglistsSection(
   }
 }
 
-
 static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts,
                                 DWARFDataExtractor Data, const DWARFObject &Obj,
                                 std::optional<uint64_t> DumpOffset) {
@@ -1234,8 +1229,8 @@ void DWARFContext::dump(
 
   if (shouldDump(Explicit, ".debug_addr", DIDT_ID_DebugAddr,
                  DObj->getAddrSection().Data)) {
-    DWARFDataExtractor AddrData(*DObj, DObj->getAddrSection(),
-                                   isLittleEndian(), 0);
+    DWARFDataExtractor AddrData(*DObj, DObj->getAddrSection(), isLittleEndian(),
+                                0);
     dumpAddrSection(OS, AddrData, DumpOpts, getMaxVersion(), getCUAddrSize());
   }
 
@@ -1347,8 +1342,7 @@ DWARFTypeUnit *DWARFContext::getTypeUnitForHash(uint64_t Hash, bool IsDWO) {
   DWARFUnitVector &DWOUnits = State->getDWOUnits();
   if (const auto &TUI = getTUIndex()) {
     if (const auto *R = TUI.getFromHash(Hash))
-      return dyn_cast_or_null<DWARFTypeUnit>(
-          DWOUnits.getUnitForIndexEntry(*R));
+      return dyn_cast_or_null<DWARFTypeUnit>(DWOUnits.getUnitForIndexEntry(*R));
     return nullptr;
   }
   return State->getTypeUnitMap(IsDWO).lookup(Hash);
@@ -1410,17 +1404,11 @@ bool DWARFContext::verify(raw_ostream &OS, DIDumpOptions DumpOpts) {
   return Success;
 }
 
-const DWARFUnitIndex &DWARFContext::getCUIndex() {
-  return State->getCUIndex();
-}
+const DWARFUnitIndex &DWARFContext::getCUIndex() { return State->getCUIndex(); }
 
-const DWARFUnitIndex &DWARFContext::getTUIndex() {
-  return State->getTUIndex();
-}
+const DWARFUnitIndex &DWARFContext::getTUIndex() { return State->getTUIndex(); }
 
-DWARFGdbIndex &DWARFContext::getGdbIndex() {
-  return State->getGdbIndex();
-}
+DWARFGdbIndex &DWARFContext::getGdbIndex() { return State->getGdbIndex(); }
 
 const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
   return State->getDebugAbbrev();
@@ -1462,7 +1450,6 @@ const DWARFDebugMacro *DWARFContext::getDebugMacinfoDWO() {
   return State->getDebugMacinfoDWO();
 }
 
-
 const DWARFDebugNames &DWARFContext::getDebugNames() {
   return State->getDebugNames();
 }
@@ -2147,7 +2134,7 @@ class DWARFObjInMemory final : public DWARFObject {
         consumeError(NameOrErr.takeError());
 
       ++SectionAmountMap[Name];
-      SectionNames.push_back({ Name, true });
+      SectionNames.push_back({Name, true});
 
       // Skip BSS and Virtual sections, they aren't interesting.
       if (Section.isBSS() || Section.isVirtual())
@@ -2382,17 +2369,19 @@ class DWARFObjInMemory final : public DWARFObject {
 
   StringRef getAbbrevSection() const override { return AbbrevSection; }
   const DWARFSection &getLocSection() const override { return LocSection; }
-  const DWARFSection &getLoclistsSection() const override { return LoclistsSection; }
-  StringRef getArangesSection() const override { return ArangesSection; }
-  const DWARFSection &getFrameSection() const override {
-    return FrameSection;
+  const DWARFSection &getLoclistsSection() const override {
+    return LoclistsSection;
   }
+  StringRef getArangesSection() const override { return ArangesSection; }
+  const DWARFSection &getFrameSection() const override { return FrameSection; }
   const DWARFSection &getEHFrameSection() const override {
     return EHFrameSection;
   }
   const DWARFSection &getLineSection() const override { return LineSection; }
   StringRef getStrSection() const override { return StrSection; }
-  const DWARFSection &getRangesSection() const override { return RangesSection; }
+  const DWARFSection &getRangesSection() const override {
+    return RangesSection;
+  }
   const DWARFSection &getRnglistsSection() const override {
     return RnglistsSection;
   }
@@ -2400,8 +2389,12 @@ class DWARFObjInMemory final : public DWARFObject {
   StringRef getMacroDWOSection() const override { return MacroDWOSection; }
   StringRef getMacinfoSection() const override { return MacinfoSection; }
   StringRef getMacinfoDWOSection() const override { return MacinfoDWOSection; }
-  const DWARFSection &getPubnamesSection() const override { return PubnamesSection; }
-  const DWARFSection &getPubtypesSection() const override { return PubtypesSection; }
+  const DWARFSection &getPubnamesSection() const override {
+    return PubnamesSection;
+  }
+  const DWARFSection &getPubtypesSection() const override {
+    return PubtypesSection;
+  }
   const DWARFSection &getGnuPubnamesSection() const override {
     return GnuPubnamesSection;
   }
@@ -2420,9 +2413,7 @@ class DWARFObjInMemory final : public DWARFObject {
   const DWARFSection &getAppleObjCSection() const override {
     return AppleObjCSection;
   }
-  const DWARFSection &getNamesSection() const override {
-    return NamesSection;
-  }
+  const DWARFSection &getNamesSection() const override { return NamesSection; }
 
   StringRef getFileName() const override { return FileName; }
   uint8_t getAddressSize() const override { return AddressSize; }
@@ -2439,28 +2430,22 @@ class DWARFObjInMemory final : public DWARFObject {
 };
 } // namespace
 
-std::unique_ptr<DWARFContext>
-DWARFContext::create(const object::ObjectFile &Obj,
-                     ProcessDebugRelocations RelocAction,
-                     const LoadedObjectInfo *L, std::string DWPName,
-                     std::function<void(Error)> RecoverableErrorHandler,
-                     std::function<void(Error)> WarningHandler,
-                     bool ThreadSafe) {
+std::unique_ptr<DWARFContext> DWARFContext::create(
+    const object::ObjectFile &Obj, ProcessDebugRelocations RelocAction,
+    const LoadedObjectInfo *L, std::string DWPName,
+    std::function<void(Error)> RecoverableErrorHandler,
+    std::function<void(Error)> WarningHandler, bool ThreadSafe) {
   auto DObj = std::make_unique<DWARFObjInMemory>(
       Obj, L, RecoverableErrorHandler, WarningHandler, RelocAction);
-  return std::make_unique<DWARFContext>(std::move(DObj),
-                                        std::move(DWPName),
-                                        RecoverableErrorHandler,
-                                        WarningHandler,
+  return std::make_unique<DWARFContext>(std::move(DObj), std::move(DWPName),
+                                        RecoverableErrorHandler, WarningHandler,
                                         ThreadSafe);
 }
 
-std::unique_ptr<DWARFContext>
-DWARFContext::create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
-                     uint8_t AddrSize, bool isLittleEndian,
-                     std::function<void(Error)> RecoverableErrorHandler,
-                     std::function<void(Error)> WarningHandler,
-                     bool ThreadSafe) {
+std::unique_ptr<DWARFContext> DWARFContext::create(
+    const StringMap<std::unique_ptr<MemoryBuffer>> &Sections, uint8_t AddrSize,
+    bool isLittleEndian, std::function<void(Error)> RecoverableErrorHandler,
+    std::function<void(Error)> WarningHandler, bool ThreadSafe) {
   auto DObj =
       std::make_unique<DWARFObjInMemory>(Sections, AddrSize, isLittleEndian);
   return std::make_unique<DWARFContext>(
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
index bdd04b00f557b..60d2298d0da14 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
@@ -33,6 +33,7 @@
 #include <cassert>
 #include <cstddef>
 #include <cstdint>
+#include <iostream>
 #include <utility>
 #include <vector>
 
@@ -44,10 +45,9 @@ void DWARFUnitVector::addUnitsForSection(DWARFContext &C,
                                          DWARFSectionKind SectionKind) {
   const DWARFObject &D = C.getDWARFObj();
   addUnitsImpl(C, D, Section, C.getDebugAbbrev(), &D.getRangesSection(),
-               &D.getLocSection(), D.getStrSection(),
-               D.getStrOffsetsSection(), &D.getAddrSection(),
-               D.getLineSection(), D.isLittleEndian(), false, false,
-               SectionKind);
+               &D.getLocSection(), D.getStrSection(), D.getStrOffsetsSection(),
+               &D.getAddrSection(), D.getLineSection(), D.isLittleEndian(),
+               false, false, SectionKind);
 }
 
 void DWARFUnitVector::addUnitsForDWOSection(DWARFContext &C,
@@ -55,11 +55,11 @@ void DWARFUnitVector::addUnitsForDWOSection(DWARFContext &C,
                                             DWARFSectionKind SectionKind,
                                             bool Lazy) {
   const DWARFObject &D = C.getDWARFObj();
-  addUnitsImpl(C, D, DWOSection, C.getDebugAbbrevDWO(), &D.getRangesDWOSection(),
-               &D.getLocDWOSection(), D.getStrDWOSection(),
-               D.getStrOffsetsDWOSection(), &D.getAddrSection(),
-               D.getLineDWOSection(), C.isLittleEndian(), true, Lazy,
-               SectionKind);
+  addUnitsImpl(C, D, DWOSection, C.getDebugAbbrevDWO(),
+               &D.getRangesDWOSection(), &D.getLocDWOSection(),
+               D.getStrDWOSection(), D.getStrOffsetsDWOSection(),
+               &D.getAddrSection(), D.getLineDWOSection(), C.isLittleEndian(),
+               true, Lazy, SectionKind);
 }
 
 void DWARFUnitVector::addUnitsImpl(
@@ -107,12 +107,12 @@ void DWARFUnitVector::addUnitsImpl(
       std::unique_ptr<DWARFUnit> U;
       if (Header.isTypeUnit())
         U = std::make_unique<DWARFTypeUnit>(Context, InfoSection, Header, DA,
-                                             RS, LocSection, SS, SOS, AOS, LS,
-                                             LE, IsDWO, *this);
+                                            RS, LocSection, SS, SOS, AOS, LS,
+                                            LE, IsDWO, *this);
       else
-        U = std::make_unique<DWARFCompileUnit>(Context, InfoSection, Header,
-                                                DA, RS, LocSection, SS, SOS,
-                                                AOS, LS, LE, IsDWO, *this);
+        U = std::make_unique<DWARFCompileUnit>(Context, InfoSection, Header, DA,
+                                               RS, LocSection, SS, SOS, AOS, LS,
+                                               LE, IsDWO, *this);
       return U;
     };
   }
@@ -496,108 +496,114 @@ void DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
 }
 
 Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) {
-  if ((CUDieOnly && !DieArray.empty()) ||
-      DieArray.size() > 1)
-    return Error::success(); // Already parsed.
-
-  bool HasCUDie = !DieArray.empty();
-  extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray);
-
-  if (DieArray.empty())
-    return Error::success();
-
-  // If CU DIE was just parsed, copy several attribute values from it.
-  if (HasCUDie)
-    return Error::success();
-
-  DWARFDie UnitDie(this, &DieArray[0]);
-  if (std::optional<uint64_t> DWOId =
-          toUnsigned(UnitDie.find(DW_AT_GNU_dwo_id)))
-    Header.setDWOId(*DWOId);
-  if (!IsDWO) {
-    assert(AddrOffsetSectionBase == std::nullopt);
-    assert(RangeSectionBase == 0);
-    assert(LocSectionBase == 0);
-    AddrOffsetSectionBase = toSectionOffset(UnitDie.find(DW_AT_addr_base));
-    if (!AddrOffsetSectionBase)
-      AddrOffsetSectionBase =
-          toSectionOffset(UnitDie.find(DW_AT_GNU_addr_base));
-    RangeSectionBase = toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0);
-    LocSectionBase = toSectionOffset(UnitDie.find(DW_AT_loclists_base), 0);
-  }
+  Error e = Error::success();
+  Context.doWorkThreadSafely([&] {
+    if ((CUDieOnly && !DieArray.empty()) || DieArray.size() > 1) {
+      return; // Already parsed.
+    }
+    bool HasCUDie = !DieArray.empty();
+    extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray);
 
-  // In general, in DWARF v5 and beyond we derive the start of the unit's
-  // contribution to the string offsets table from the unit DIE's
-  // DW_AT_str_offsets_base attribute. Split DWARF units do not use this
-  // attribute, so we assume that there is a contribution to the string
-  // offsets table starting at offset 0 of the debug_str_offsets.dwo section.
-  // In both cases we need to determine the format of the contribution,
-  // which may differ from the unit's format.
-  DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection,
-                        IsLittleEndian, 0);
-  if (IsDWO || getVersion() >= 5) {
-    auto StringOffsetOrError =
-        IsDWO ? determineStringOffsetsTableContributionDWO(DA)
-              : determineStringOffsetsTableContribution(DA);
-    if (!StringOffsetOrError)
-      return createStringError(errc::invalid_argument,
-                               "invalid reference to or invalid content in "
-                               ".debug_str_offsets[.dwo]: " +
-                                   toString(StringOffsetOrError.takeError()));
+    if (DieArray.empty()) {
+      return;
+    }
 
-    StringOffsetsTableContribution = *StringOffsetOrError;
-  }
+    // If CU DIE was just parsed, copy several attribute values from it.
+    if (HasCUDie) {
+      return;
+    }
+
+    DWARFDie UnitDie(this, &DieArray[0]);
+    if (std::optional<uint64_t> DWOId =
+            toUnsigned(UnitDie.find(DW_AT_GNU_dwo_id)))
+      Header.setDWOId(*DWOId);
+    if (!IsDWO) {
+      assert(AddrOffsetSectionBase == std::nullopt);
+      assert(RangeSectionBase == 0);
+      assert(LocSectionBase == 0);
+      AddrOffsetSectionBase = toSectionOffset(UnitDie.find(DW_AT_addr_base));
+      if (!AddrOffsetSectionBase)
+        AddrOffsetSectionBase =
+            toSectionOffset(UnitDie.find(DW_AT_GNU_addr_base));
+      RangeSectionBase = toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0);
+      LocSectionBase = toSectionOffset(UnitDie.find(DW_AT_loclists_base), 0);
+    }
+
+    // In general, in DWARF v5 and beyond we derive the start of the unit's
+    // contribution to the string offsets table from the unit DIE's
+    // DW_AT_str_offsets_base attribute. Split DWARF units do not use this
+    // attribute, so we assume that there is a contribution to the string
+    // offsets table starting at offset 0 of the debug_str_offsets.dwo section.
+    // In both cases we need to determine the format of the contribution,
+    // which may differ from the unit's format.
+    DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection,
+                          IsLittleEndian, 0);
+    if (IsDWO || getVersion() >= 5) {
+      auto StringOffsetOrError =
+          IsDWO ? determineStringOffsetsTableContributionDWO(DA)
+                : determineStringOffsetsTableContribution(DA);
+      if (!StringOffsetOrError) {
+        e = createStringError(errc::invalid_argument,
+                              "invalid reference to or invalid content in "
+                              ".debug_str_offsets[.dwo]: " +
+                                  toString(StringOffsetOrError.takeError()));
+        return;
+      }
+
+      StringOffsetsTableContribution = *StringOffsetOrError;
+    }
+
+    // DWARF v5 uses the .debug_rnglists and .debug_rnglists.dwo sections to
+    // describe address ranges.
+    if (getVersion() >= 5) {
+      // In case of DWP, the base offset from the index has to be added.
+      if (IsDWO) {
+        uint64_t ContributionBaseOffset = 0;
+        if (auto *IndexEntry = Header.getIndexEntry())
+          if (auto *Contrib = IndexEntry->getContribution(DW_SECT_RNGLISTS))
+            ContributionBaseOffset = Contrib->getOffset();
+        setRangesSection(
+            &Context.getDWARFObj().getRnglistsDWOSection(),
+            ContributionBaseOffset +
+                DWARFListTableHeader::getHeaderSize(Header.getFormat()));
+      } else
+        setRangesSection(&Context.getDWARFObj().getRnglistsSection(),
+                         toSectionOffset(UnitDie.find(DW_AT_rnglists_base),
+                                         DWARFListTableHeader::getHeaderSize(
+                                             Header.getFormat())));
+    }
 
-  // DWARF v5 uses the .debug_rnglists and .debug_rnglists.dwo sections to
-  // describe address ranges.
-  if (getVersion() >= 5) {
-    // In case of DWP, the base offset from the index has to be added.
     if (IsDWO) {
-      uint64_t ContributionBaseOffset = 0;
+      // If we are reading a package file, we need to adjust the location list
+      // data based on the index entries.
+      StringRef Data = Header.getVersion() >= 5
+                           ? Context.getDWARFObj().getLoclistsDWOSection().Data
+                           : Context.getDWARFObj().getLocDWOSection().Data;
       if (auto *IndexEntry = Header.getIndexEntry())
-        if (auto *Contrib = IndexEntry->getContribution(DW_SECT_RNGLISTS))
-          ContributionBaseOffset = Contrib->getOffset();
-      setRangesSection(
-          &Context.getDWARFObj().getRnglistsDWOSection(),
-          ContributionBaseOffset +
-              DWARFListTableHeader::getHeaderSize(Header.getFormat()));
-    } else
-      setRangesSection(&Context.getDWARFObj().getRnglistsSection(),
-                       toSectionOffset(UnitDie.find(DW_AT_rnglists_base),
-                                       DWARFListTableHeader::getHeaderSize(
-                                           Header.getFormat())));
-  }
-
-  if (IsDWO) {
-    // If we are reading a package file, we need to adjust the location list
-    // data based on the index entries.
-    StringRef Data = Header.getVersion() >= 5
-                         ? Context.getDWARFObj().getLoclistsDWOSection().Data
-                         : Context.getDWARFObj().getLocDWOSection().Data;
-    if (auto *IndexEntry = Header.getIndexEntry())
-      if (const auto *C = IndexEntry->getContribution(
-              Header.getVersion() >= 5 ? DW_SECT_LOCLISTS : DW_SECT_EXT_LOC))
-        Data = Data.substr(C->getOffset(), C->getLength());
-
-    DWARFDataExtractor DWARFData(Data, IsLittleEndian, getAddressByteSize());
-    LocTable =
-        std::make_unique<DWARFDebugLoclists>(DWARFData, Header.getVersion());
-    LocSectionBase = DWARFListTableHeader::getHeaderSize(Header.getFormat());
-  } else if (getVersion() >= 5) {
-    LocTable = std::make_unique<DWARFDebugLoclists>(
-        DWARFDataExtractor(Context.getDWARFObj(),
-                           Context.getDWARFObj().getLoclistsSection(),
-                           IsLittleEndian, getAddressByteSize()),
-        getVersion());
-  } else {
-    LocTable = std::make_unique<DWARFDebugLoc>(DWARFDataExtractor(
-        Context.getDWARFObj(), Context.getDWARFObj().getLocSection(),
-        IsLittleEndian, getAddressByteSize()));
-  }
+        if (const auto *C = IndexEntry->getContribution(
+                Header.getVersion() >= 5 ? DW_SECT_LOCLISTS : DW_SECT_EXT_LOC))
+          Data = Data.substr(C->getOffset(), C->getLength());
+
+      DWARFDataExtractor DWARFData(Data, IsLittleEndian, getAddressByteSize());
+      LocTable =
+          std::make_unique<DWARFDebugLoclists>(DWARFData, Header.getVersion());
+      LocSectionBase = DWARFListTableHeader::getHeaderSize(Header.getFormat());
+    } else if (getVersion() >= 5) {
+      LocTable = std::make_unique<DWARFDebugLoclists>(
+          DWARFDataExtractor(Context.getDWARFObj(),
+                             Context.getDWARFObj().getLoclistsSection(),
+                             IsLittleEndian, getAddressByteSize()),
+          getVersion());
+    } else {
+      LocTable = std::make_unique<DWARFDebugLoc>(DWARFDataExtractor(
+          Context.getDWARFObj(), Context.getDWARFObj().getLocSection(),
+          IsLittleEndian, getAddressByteSize()));
+    }
 
-  // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for
-  // skeleton CU DIE, so that DWARF users not aware of it are not broken.
-  return Error::success();
+    // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for
+    // skeleton CU DIE, so that DWARF users not aware of it are not broken.
+  });
+  return e;
 }
 
 bool DWARFUnit::parseDWO(StringRef DWOAlternativeLocation) {
@@ -652,15 +658,20 @@ bool DWARFUnit::parseDWO(StringRef DWOAlternativeLocation) {
   return true;
 }
 
-void DWARFUnit::clearDIEs(bool KeepCUDie) {
-  // Do not use resize() + shrink_to_fit() to free memory occupied by dies.
-  // shrink_to_fit() is a *non-binding* request to reduce capacity() to size().
-  // It depends on the implementation whether the request is fulfilled.
-  // Create a new vector with a small capacity and assign it to the DieArray to
-  // have previous contents freed.
-  DieArray = (KeepCUDie && !DieArray.empty())
-                 ? std::vector<DWARFDebugInfoEntry>({DieArray[0]})
-                 : std::vector<DWARFDebugInfoEntry>();
+void DWARFUnit::clearDIEs(bool KeepCUDie, bool KeepDWODies) {
+  Context.doWorkThreadSafely([&] {
+    if (!KeepDWODies && DWO) {
+      DWO->clearDIEs(KeepCUDie, KeepDWODies);
+    }
+    // Do not use resize() + shrink_to_fit() to free memory occupied by dies.
+    // shrink_to_fit() is a *non-binding* request to reduce capacity() to
+    // size(). It depends on the implementation whether the request is
+    // fulfilled. Create a new vector with a small capacity and assign it to the
+    // DieArray to have previous contents freed.
+    DieArray = (KeepCUDie && !DieArray.empty())
+                   ? std::vector<DWARFDebugInfoEntry>({DieArray[0]})
+                   : std::vector<DWARFDebugInfoEntry>();
+  });
 }
 
 Expected<DWARFAddressRangesVector>
@@ -868,9 +879,8 @@ DWARFDie DWARFUnit::getVariableForAddress(uint64_t Address) {
   return R->second.second;
 }
 
-void
-DWARFUnit::getInlinedChainForAddress(uint64_t Address,
-                                     SmallVectorImpl<DWARFDie> &InlinedChain) {
+void DWARFUnit::getInlinedChainForAddress(
+    uint64_t Address, SmallVectorImpl<DWARFDie> &InlinedChain) {
   assert(InlinedChain.empty());
   // Try to look for subprogram DIEs in the DWO file.
   parseDWO();
@@ -886,7 +896,7 @@ DWARFUnit::getInlinedChainForAddress(uint64_t Address,
     }
     if (SubroutineDIE.getTag() == DW_TAG_inlined_subroutine)
       InlinedChain.push_back(SubroutineDIE);
-    SubroutineDIE  = SubroutineDIE.getParent();
+    SubroutineDIE = SubroutineDIE.getParent();
   }
 }
 
@@ -1087,7 +1097,8 @@ StrOffsetsContributionDescriptor::validateContributionSize(
   if (ValidationSize >= Size)
     if (DA.isValidOffsetForDataOfSize((uint32_t)Base, ValidationSize))
       return *this;
-  return createStringError(errc::invalid_argument, "length exceeds section size");
+  return createStringError(errc::invalid_argument,
+                           "length exceeds section size");
 }
 
 // Look for a DWARF64-formatted contribution to the string offsets table
@@ -1095,10 +1106,13 @@ StrOffsetsContributionDescriptor::validateContributionSize(
 static Expected<StrOffsetsContributionDescriptor>
 parseDWARF64StringOffsetsTableHeader(DWARFDataExtractor &DA, uint64_t Offset) {
   if (!DA.isValidOffsetForDataOfSize(Offset, 16))
-    return createStringError(errc::invalid_argument, "section offset exceeds section size");
+    return createStringError(errc::invalid_argument,
+                             "section offset exceeds section size");
 
   if (DA.getU32(&Offset) != dwarf::DW_LENGTH_DWARF64)
-    return createStringError(errc::invalid_argument, "32 bit contribution referenced from a 64 bit unit");
+    return createStringError(
+        errc::invalid_argument,
+        "32 bit contribution referenced from a 64 bit unit");
 
   uint64_t Size = DA.getU64(&Offset);
   uint8_t Version = DA.getU16(&Offset);
@@ -1113,7 +1127,8 @@ parseDWARF64StringOffsetsTableHeader(DWARFDataExtractor &DA, uint64_t Offset) {
 static Expected<StrOffsetsContributionDescriptor>
 parseDWARF32StringOffsetsTableHeader(DWARFDataExtractor &DA, uint64_t Offset) {
   if (!DA.isValidOffsetForDataOfSize(Offset, 8))
-    return createStringError(errc::invalid_argument, "section offset exceeds section size");
+    return createStringError(errc::invalid_argument,
+                             "section offset exceeds section size");
 
   uint32_t ContributionSize = DA.getU32(&Offset);
   if (ContributionSize >= dwarf::DW_LENGTH_lo_reserved)
@@ -1135,7 +1150,8 @@ parseDWARFStringOffsetsTableHeader(DWARFDataExtractor &DA,
   switch (Format) {
   case dwarf::DwarfFormat::DWARF64: {
     if (Offset < 16)
-      return createStringError(errc::invalid_argument, "insufficient space for 64 bit header prefix");
+      return createStringError(errc::invalid_argument,
+                               "insufficient space for 64 bit header prefix");
     auto DescOrError = parseDWARF64StringOffsetsTableHeader(DA, Offset - 16);
     if (!DescOrError)
       return DescOrError.takeError();
@@ -1144,7 +1160,8 @@ parseDWARFStringOffsetsTableHeader(DWARFDataExtractor &DA,
   }
   case dwarf::DwarfFormat::DWARF32: {
     if (Offset < 8)
-      return createStringError(errc::invalid_argument, "insufficient space for 32 bit header prefix");
+      return createStringError(errc::invalid_argument,
+                               "insufficient space for 32 bit header prefix");
     auto DescOrError = parseDWARF32StringOffsetsTableHeader(DA, Offset - 8);
     if (!DescOrError)
       return DescOrError.takeError();
@@ -1182,7 +1199,8 @@ DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor &DA) {
       return std::nullopt;
     Offset += Header.getFormat() == dwarf::DwarfFormat::DWARF32 ? 8 : 16;
     // Look for a valid contribution at the given offset.
-    auto DescOrError = parseDWARFStringOffsetsTableHeader(DA, Header.getFormat(), Offset);
+    auto DescOrError =
+        parseDWARFStringOffsetsTableHeader(DA, Header.getFormat(), Offset);
     if (!DescOrError)
       return DescOrError.takeError();
     return *DescOrError;
diff --git a/llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp b/llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp
index 7a0256f10ea60..cba59955131b4 100644
--- a/llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp
+++ b/llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp
@@ -82,7 +82,6 @@ struct llvm::gsym::CUInfo {
   }
 };
 
-
 static DWARFDie GetParentDeclContextDIE(DWARFDie &Die) {
   if (DWARFDie SpecDie =
           Die.getAttributeValueAsReferencedDie(dwarf::DW_AT_specification)) {
@@ -170,7 +169,7 @@ getQualifiedNameIndex(DWARFDie &Die, uint64_t Language, GsymCreator &Gsym) {
         // templates
         if (ParentName.front() == '<' && ParentName.back() == '>')
           Name = "{" + ParentName.substr(1, ParentName.size() - 2).str() + "}" +
-                "::" + Name;
+                 "::" + Name;
         else
           Name = ParentName.str() + "::" + Name;
       }
@@ -432,7 +431,7 @@ static void convertFunctionLineTable(OutputAggregator &Out, CUInfo &CUI,
     // Skip multiple line entries for the same file and line.
     auto LastLE = FI.OptLineTable->last();
     if (LastLE && LastLE->File == FileIdx && LastLE->Line == Row.Line)
-        continue;
+      continue;
     // Only push a row if it isn't an end sequence. End sequence markers are
     // included for the last address in a function or the last contiguous
     // address in a sequence.
@@ -656,6 +655,11 @@ Error DwarfTransformer::convert(uint32_t NumThreads, OutputAggregator &Out) {
       DWARFDie Die = getDie(*CU);
       CUInfo CUI(DICtx, dyn_cast<DWARFCompileUnit>(CU.get()));
       handleDie(Out, CUI, Die);
+      // Release the line table, once we're done.
+      DICtx.clearLineTableForUnit(CU.get());
+      // Free any DIEs that were allocated by the DWARF parser.
+      // If/when they're needed by other CU's, they'll be recreated.
+      CU->clearDIEs(/*KeepCUDie=*/false);
     }
   } else {
     // LLVM Dwarf parser is not thread-safe and we need to parse all DWARF up
@@ -668,12 +672,7 @@ Error DwarfTransformer::convert(uint32_t NumThreads, OutputAggregator &Out) {
     for (const auto &CU : DICtx.compile_units())
       CU->getAbbreviations();
 
-    // Now parse all DIEs in case we have cross compile unit references in a
-    // thread pool.
     DefaultThreadPool pool(hardware_concurrency(NumThreads));
-    for (const auto &CU : DICtx.compile_units())
-      pool.async([&CU]() { CU->getUnitDIE(false /*CUDieOnly*/); });
-    pool.wait();
 
     // Now convert all DWARF to GSYM in a thread pool.
     std::mutex LogMutex;
@@ -681,11 +680,16 @@ Error DwarfTransformer::convert(uint32_t NumThreads, OutputAggregator &Out) {
       DWARFDie Die = getDie(*CU);
       if (Die) {
         CUInfo CUI(DICtx, dyn_cast<DWARFCompileUnit>(CU.get()));
-        pool.async([this, CUI, &LogMutex, &Out, Die]() mutable {
+        pool.async([this, CUI, &CU, &LogMutex, &Out, Die]() mutable {
           std::string storage;
           raw_string_ostream StrStream(storage);
           OutputAggregator ThreadOut(Out.GetOS() ? &StrStream : nullptr);
           handleDie(ThreadOut, CUI, Die);
+          // Release the line table once we're done.
+          DICtx.clearLineTableForUnit(CU.get());
+          // Free any DIEs that were allocated by the DWARF parser.
+          // If/when they're needed by other CU's, they'll be recreated.
+          CU->clearDIEs(/*KeepCUDie=*/false);
           // Print ThreadLogStorage lines into an actual stream under a lock
           std::lock_guard<std::mutex> guard(LogMutex);
           if (Out.GetOS()) {
@@ -697,6 +701,9 @@ Error DwarfTransformer::convert(uint32_t NumThreads, OutputAggregator &Out) {
     }
     pool.wait();
   }
+  // Now get rid of all the DIEs that may have been recreated
+  for (const auto &CU : DICtx.compile_units())
+    CU->clearDIEs(/*KeepCUDie=*/false);
   size_t FunctionsAddedCount = Gsym.getNumFunctionInfos() - NumBefore;
   Out << "Loaded " << FunctionsAddedCount << " functions from DWARF.\n";
   return Error::success();
@@ -718,8 +725,8 @@ llvm::Error DwarfTransformer::verify(StringRef GsymPath,
   for (uint32_t I = 0; I < NumAddrs; ++I) {
     auto FuncAddr = Gsym->getAddress(I);
     if (!FuncAddr)
-        return createStringError(std::errc::invalid_argument,
-                                  "failed to extract address[%i]", I);
+      return createStringError(std::errc::invalid_argument,
+                               "failed to extract address[%i]", I);
 
     auto FI = Gsym->getFunctionInfo(*FuncAddr);
     if (!FI)
@@ -734,8 +741,7 @@ llvm::Error DwarfTransformer::verify(StringRef GsymPath,
       if (!LR)
         return LR.takeError();
 
-      auto DwarfInlineInfos =
-          DICtx.getInliningInfoForAddress(SectAddr, DLIS);
+      auto DwarfInlineInfos = DICtx.getInliningInfoForAddress(SectAddr, DLIS);
       uint32_t NumDwarfInlineInfos = DwarfInlineInfos.getNumberOfFrames();
       if (NumDwarfInlineInfos == 0) {
         DwarfInlineInfos.addFrame(
@@ -773,8 +779,7 @@ llvm::Error DwarfTransformer::verify(StringRef GsymPath,
         continue;
       }
 
-      for (size_t Idx = 0, count = LR->Locations.size(); Idx < count;
-            ++Idx) {
+      for (size_t Idx = 0, count = LR->Locations.size(); Idx < count; ++Idx) {
         const auto &gii = LR->Locations[Idx];
         if (Idx < NumDwarfInlineInfos) {
           const auto &dii = DwarfInlineInfos.getFrame(Idx);



More information about the llvm-commits mailing list