[llvm] [DWARFLinker][DWARFLinkerParallel][NFC] Refactor DWARFLinker&DWARFLinkerParallel to have a common library. (PR #74725)

via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 8 01:22:30 PST 2023


https://github.com/avl-llvm updated https://github.com/llvm/llvm-project/pull/74725

>From ba54bdf20f63f82a0bef26dc6f6b9654772e7fa6 Mon Sep 17 00:00:00 2001
From: Alexey Lapshin <a.v.lapshin at mail.ru>
Date: Thu, 7 Dec 2023 17:10:17 +0300
Subject: [PATCH 1/4] [DWARFLinker][DWARFLinkerParallel] Refactor
 DWARFLinker&DWARFLinkerParallel to have a common library.

This creates DWARFLinkerBase library which shares code between DWARFLinker
and DWARFLinkerParallel. Now AddressesMap, DWARFFile, IndexedValuesMap
are shared between DWARFLinker implementations.
---
 .../AddressesMap.h                            |  10 +-
 .../DWARFLinker/{ => Apple}/DWARFLinker.h     | 425 +++---------------
 .../{ => Apple}/DWARFLinkerCompileUnit.h      |   8 +-
 .../{ => Apple}/DWARFLinkerDeclContext.h      |   8 +-
 .../DWARFLinker/{ => Apple}/DWARFStreamer.h   | 143 +++---
 .../llvm/DWARFLinker}/ArrayList.h             |  10 +-
 .../DWARFFile.h                               |  17 +-
 .../llvm/DWARFLinker/DWARFLinkerBase.h        | 124 +++++
 .../llvm/DWARFLinker}/IndexedValuesMap.h      |  13 +-
 .../llvm/DWARFLinker/LLVM/DWARFLinker.h       | 191 ++++++++
 .../StringPool.h                              |  12 +-
 .../llvm/DWARFLinker}/Utils.h                 |  36 +-
 .../llvm/DWARFLinkerParallel/DWARFLinker.h    | 223 ---------
 .../llvm/DebugInfo/DWARF/DWARFDebugMacro.h    |   7 +-
 llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h |   4 +-
 llvm/lib/CMakeLists.txt                       |   1 -
 llvm/lib/DWARFLinker/Apple/CMakeLists.txt     |  24 +
 .../DWARFLinker/{ => Apple}/DWARFLinker.cpp   | 225 ++++------
 .../{ => Apple}/DWARFLinkerCompileUnit.cpp    |   9 +-
 .../{ => Apple}/DWARFLinkerDeclContext.cpp    |   9 +-
 .../DWARFLinker/{ => Apple}/DWARFStreamer.cpp |  89 ++--
 llvm/lib/DWARFLinker/CMakeLists.txt           |  19 +-
 .../LLVM}/AcceleratorRecordsSaver.cpp         |  10 +-
 .../LLVM}/AcceleratorRecordsSaver.h           |   8 +-
 .../LLVM}/CMakeLists.txt                      |   6 +-
 .../LLVM}/DIEAttributeCloner.cpp              |   8 +-
 .../LLVM}/DIEAttributeCloner.h                |  10 +-
 .../LLVM}/DIEGenerator.h                      |   8 +-
 .../LLVM}/DWARFEmitterImpl.cpp                |  30 +-
 .../LLVM}/DWARFEmitterImpl.h                  |  30 +-
 llvm/lib/DWARFLinker/LLVM/DWARFLinker.cpp     |  77 ++++
 .../LLVM}/DWARFLinkerCompileUnit.cpp          |  39 +-
 .../LLVM}/DWARFLinkerCompileUnit.h            |  18 +-
 .../LLVM}/DWARFLinkerGlobalData.h             |  33 +-
 .../LLVM}/DWARFLinkerImpl.cpp                 | 293 ++++++------
 .../LLVM}/DWARFLinkerImpl.h                   |  32 +-
 .../LLVM}/DWARFLinkerTypeUnit.cpp             |   3 +-
 .../LLVM}/DWARFLinkerTypeUnit.h               |   8 +-
 .../LLVM}/DWARFLinkerUnit.cpp                 |  33 +-
 .../LLVM}/DWARFLinkerUnit.h                   |  14 +-
 .../LLVM}/DebugLineSectionEmitter.h           |  12 +-
 .../LLVM}/DependencyTracker.cpp               |   8 +-
 .../LLVM}/DependencyTracker.h                 |   8 +-
 .../LLVM}/OutputSections.cpp                  | 115 +----
 .../LLVM}/OutputSections.h                    | 135 +++---
 .../StringEntryToDwarfStringPoolEntryMap.h    |  10 +-
 .../LLVM}/SyntheticTypeNameBuilder.cpp        |   8 +-
 .../LLVM}/SyntheticTypeNameBuilder.h          |   8 +-
 .../LLVM}/TypePool.h                          |  10 +-
 .../StringPool.cpp => DWARFLinker/Utils.cpp}  |   7 +-
 llvm/lib/DWARFLinkerParallel/DWARFFile.cpp    |  17 -
 llvm/lib/DWARFLinkerParallel/DWARFLinker.cpp  |  18 -
 llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp   |  10 +-
 llvm/tools/dsymutil/CMakeLists.txt            |   1 +
 llvm/tools/dsymutil/DwarfLinkerForBinary.cpp  | 193 ++++----
 llvm/tools/dsymutil/DwarfLinkerForBinary.h    |  21 +-
 llvm/tools/dsymutil/LinkUtils.h               |   6 +-
 llvm/tools/dsymutil/dsymutil.cpp              |   3 +-
 llvm/tools/llvm-dwarfutil/CMakeLists.txt      |   1 +
 llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp |  57 ++-
 .../DWARFLinkerParallel/StringPoolTest.cpp    |   4 +-
 61 files changed, 1330 insertions(+), 1589 deletions(-)
 rename llvm/include/llvm/{DWARFLinkerParallel => DWARFLinker}/AddressesMap.h (97%)
 rename llvm/include/llvm/DWARFLinker/{ => Apple}/DWARFLinker.h (61%)
 rename llvm/include/llvm/DWARFLinker/{ => Apple}/DWARFLinkerCompileUnit.h (98%)
 rename llvm/include/llvm/DWARFLinker/{ => Apple}/DWARFLinkerDeclContext.h (96%)
 rename llvm/include/llvm/DWARFLinker/{ => Apple}/DWARFStreamer.h (72%)
 rename llvm/{lib/DWARFLinkerParallel => include/llvm/DWARFLinker}/ArrayList.h (95%)
 rename llvm/include/llvm/{DWARFLinkerParallel => DWARFLinker}/DWARFFile.h (79%)
 create mode 100644 llvm/include/llvm/DWARFLinker/DWARFLinkerBase.h
 rename llvm/{lib/DWARFLinkerParallel => include/llvm/DWARFLinker}/IndexedValuesMap.h (76%)
 create mode 100644 llvm/include/llvm/DWARFLinker/LLVM/DWARFLinker.h
 rename llvm/include/llvm/{DWARFLinkerParallel => DWARFLinker}/StringPool.h (90%)
 rename llvm/{lib/DWARFLinkerParallel => include/llvm/DWARFLinker}/Utils.h (51%)
 delete mode 100644 llvm/include/llvm/DWARFLinkerParallel/DWARFLinker.h
 create mode 100644 llvm/lib/DWARFLinker/Apple/CMakeLists.txt
 rename llvm/lib/DWARFLinker/{ => Apple}/DWARFLinker.cpp (94%)
 rename llvm/lib/DWARFLinker/{ => Apple}/DWARFLinkerCompileUnit.cpp (97%)
 rename llvm/lib/DWARFLinker/{ => Apple}/DWARFLinkerDeclContext.cpp (98%)
 rename llvm/lib/DWARFLinker/{ => Apple}/DWARFStreamer.cpp (94%)
 rename llvm/lib/{DWARFLinkerParallel => DWARFLinker/LLVM}/AcceleratorRecordsSaver.cpp (98%)
 rename llvm/lib/{DWARFLinkerParallel => DWARFLinker/LLVM}/AcceleratorRecordsSaver.h (91%)
 rename llvm/lib/{DWARFLinkerParallel => DWARFLinker/LLVM}/CMakeLists.txt (85%)
 rename llvm/lib/{DWARFLinkerParallel => DWARFLinker/LLVM}/DIEAttributeCloner.cpp (99%)
 rename llvm/lib/{DWARFLinkerParallel => DWARFLinker/LLVM}/DIEAttributeCloner.h (96%)
 rename llvm/lib/{DWARFLinkerParallel => DWARFLinker/LLVM}/DIEGenerator.h (97%)
 rename llvm/lib/{DWARFLinkerParallel => DWARFLinker/LLVM}/DWARFEmitterImpl.cpp (92%)
 rename llvm/lib/{DWARFLinkerParallel => DWARFLinker/LLVM}/DWARFEmitterImpl.h (84%)
 create mode 100644 llvm/lib/DWARFLinker/LLVM/DWARFLinker.cpp
 rename llvm/lib/{DWARFLinkerParallel => DWARFLinker/LLVM}/DWARFLinkerCompileUnit.cpp (98%)
 rename llvm/lib/{DWARFLinkerParallel => DWARFLinker/LLVM}/DWARFLinkerCompileUnit.h (97%)
 rename llvm/lib/{DWARFLinkerParallel => DWARFLinker/LLVM}/DWARFLinkerGlobalData.h (82%)
 rename llvm/lib/{DWARFLinkerParallel => DWARFLinker/LLVM}/DWARFLinkerImpl.cpp (87%)
 rename llvm/lib/{DWARFLinkerParallel => DWARFLinker/LLVM}/DWARFLinkerImpl.h (94%)
 rename llvm/lib/{DWARFLinkerParallel => DWARFLinker/LLVM}/DWARFLinkerTypeUnit.cpp (99%)
 rename llvm/lib/{DWARFLinkerParallel => DWARFLinker/LLVM}/DWARFLinkerTypeUnit.h (95%)
 rename llvm/lib/{DWARFLinkerParallel => DWARFLinker/LLVM}/DWARFLinkerUnit.cpp (89%)
 rename llvm/lib/{DWARFLinkerParallel => DWARFLinker/LLVM}/DWARFLinkerUnit.h (94%)
 rename llvm/lib/{DWARFLinkerParallel => DWARFLinker/LLVM}/DebugLineSectionEmitter.h (97%)
 rename llvm/lib/{DWARFLinkerParallel => DWARFLinker/LLVM}/DependencyTracker.cpp (99%)
 rename llvm/lib/{DWARFLinkerParallel => DWARFLinker/LLVM}/DependencyTracker.h (97%)
 rename llvm/lib/{DWARFLinkerParallel => DWARFLinker/LLVM}/OutputSections.cpp (77%)
 rename llvm/lib/{DWARFLinkerParallel => DWARFLinker/LLVM}/OutputSections.h (84%)
 rename llvm/lib/{DWARFLinkerParallel => DWARFLinker/LLVM}/StringEntryToDwarfStringPoolEntryMap.h (88%)
 rename llvm/lib/{DWARFLinkerParallel => DWARFLinker/LLVM}/SyntheticTypeNameBuilder.cpp (99%)
 rename llvm/lib/{DWARFLinkerParallel => DWARFLinker/LLVM}/SyntheticTypeNameBuilder.h (96%)
 rename llvm/lib/{DWARFLinkerParallel => DWARFLinker/LLVM}/TypePool.h (95%)
 rename llvm/lib/{DWARFLinkerParallel/StringPool.cpp => DWARFLinker/Utils.cpp} (65%)
 delete mode 100644 llvm/lib/DWARFLinkerParallel/DWARFFile.cpp
 delete mode 100644 llvm/lib/DWARFLinkerParallel/DWARFLinker.cpp

diff --git a/llvm/include/llvm/DWARFLinkerParallel/AddressesMap.h b/llvm/include/llvm/DWARFLinker/AddressesMap.h
similarity index 97%
rename from llvm/include/llvm/DWARFLinkerParallel/AddressesMap.h
rename to llvm/include/llvm/DWARFLinker/AddressesMap.h
index b451fee4e0b723..b9d4223456cb4b 100644
--- a/llvm/include/llvm/DWARFLinkerParallel/AddressesMap.h
+++ b/llvm/include/llvm/DWARFLinker/AddressesMap.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_DWARFLINKERPARALLEL_ADDRESSESMAP_H
-#define LLVM_DWARFLINKERPARALLEL_ADDRESSESMAP_H
+#ifndef LLVM_DWARFLINKER_ADDRESSESMAP_H
+#define LLVM_DWARFLINKER_ADDRESSESMAP_H
 
 #include "llvm/ADT/AddressRanges.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
@@ -17,7 +17,7 @@
 #include <cstdint>
 
 namespace llvm {
-namespace dwarflinker_parallel {
+namespace dwarflinker {
 
 /// Mapped value in the address map is the offset to apply to the
 /// linked address.
@@ -186,7 +186,7 @@ class AddressesMap {
   }
 };
 
-} // end of namespace dwarflinker_parallel
+} // end namespace dwarflinker
 } // end namespace llvm
 
-#endif // LLVM_DWARFLINKERPARALLEL_ADDRESSESMAP_H
+#endif // LLVM_DWARFLINKER_ADDRESSESMAP_H
diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/Apple/DWARFLinker.h
similarity index 61%
rename from llvm/include/llvm/DWARFLinker/DWARFLinker.h
rename to llvm/include/llvm/DWARFLinker/Apple/DWARFLinker.h
index 2bd85e30d3b13b..0788ac7547b207 100644
--- a/llvm/include/llvm/DWARFLinker/DWARFLinker.h
+++ b/llvm/include/llvm/DWARFLinker/Apple/DWARFLinker.h
@@ -6,14 +6,15 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_DWARFLINKER_DWARFLINKER_H
-#define LLVM_DWARFLINKER_DWARFLINKER_H
+#ifndef LLVM_DWARFLINKER_APPLE_DWARFLINKER_H
+#define LLVM_DWARFLINKER_APPLE_DWARFLINKER_H
 
 #include "llvm/ADT/AddressRanges.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/CodeGen/AccelTable.h"
 #include "llvm/CodeGen/NonRelocatableStringpool.h"
-#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
+#include "llvm/DWARFLinker/Apple/DWARFLinkerCompileUnit.h"
+#include "llvm/DWARFLinker/DWARFLinkerBase.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
@@ -25,301 +26,15 @@ namespace llvm {
 class DWARFExpression;
 class DWARFUnit;
 class DataExtractor;
-class DeclContextTree;
 template <typename T> class SmallVectorImpl;
 
-enum class DwarfLinkerClient { Dsymutil, LLD, General };
-
-/// AddressesMap represents information about valid addresses used
-/// by debug information. Valid addresses are those which points to
-/// live code sections. i.e. relocations for these addresses point
-/// into sections which would be/are placed into resulting binary.
-class AddressesMap {
-public:
-  virtual ~AddressesMap();
-
-  /// Checks that there are valid relocations against a .debug_info
-  /// section.
-  virtual bool hasValidRelocs() = 0;
-
-  /// Checks that the specified DWARF expression operand \p Op references live
-  /// code section and returns the relocation adjustment value (to get the
-  /// linked address this value might be added to the source expression operand
-  /// address).
-  /// \returns relocation adjustment value or std::nullopt if there is no
-  /// corresponding live address.
-  virtual std::optional<int64_t>
-  getExprOpAddressRelocAdjustment(DWARFUnit &U,
-                                  const DWARFExpression::Operation &Op,
-                                  uint64_t StartOffset, uint64_t EndOffset) = 0;
-
-  /// Checks that the specified subprogram \p DIE references the live code
-  /// section and returns the relocation adjustment value (to get the linked
-  /// address this value might be added to the source subprogram address).
-  /// Allowed kinds of input DIE: DW_TAG_subprogram, DW_TAG_label.
-  /// \returns relocation adjustment value or std::nullopt if there is no
-  /// corresponding live address.
-  virtual std::optional<int64_t>
-  getSubprogramRelocAdjustment(const DWARFDie &DIE) = 0;
-
-  /// Returns the file name associated to the AddessesMap
-  virtual std::optional<StringRef> getLibraryInstallName() = 0;
-
-  /// Apply the valid relocations to the buffer \p Data, taking into
-  /// account that Data is at \p BaseOffset in the .debug_info section.
-  ///
-  /// \returns true whether any reloc has been applied.
-  virtual bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
-                                bool IsLittleEndian) = 0;
-
-  /// Check if the linker needs to gather and save relocation info.
-  virtual bool needToSaveValidRelocs() = 0;
-
-  /// Update and save original relocations located in between StartOffset and
-  /// EndOffset. LinkedOffset is the value which should be added to the original
-  /// relocation offset to get new relocation offset in linked binary.
-  virtual void updateAndSaveValidRelocs(bool IsDWARF5,
-                                        uint64_t OriginalUnitOffset,
-                                        int64_t LinkedOffset,
-                                        uint64_t StartOffset,
-                                        uint64_t EndOffset) = 0;
-
-  /// Update the valid relocations that used OriginalUnitOffset as the compile
-  /// unit offset, and update their values to reflect OutputUnitOffset.
-  virtual void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,
-                                               uint64_t OutputUnitOffset) = 0;
-
-  /// Erases all data.
-  virtual void clear() = 0;
-};
-
+namespace dwarflinker {
+class DeclContextTree;
 using Offset2UnitMap = DenseMap<uint64_t, CompileUnit *>;
 
-struct DebugDieValuePool {
-  DenseMap<uint64_t, uint64_t> DieValueMap;
-  SmallVector<uint64_t> DieValues;
-
-  uint64_t getValueIndex(uint64_t Value) {
-    DenseMap<uint64_t, uint64_t>::iterator It = DieValueMap.find(Value);
-    if (It == DieValueMap.end()) {
-      It = DieValueMap.insert(std::make_pair(Value, DieValues.size())).first;
-      DieValues.push_back(Value);
-    }
-    return It->second;
-  }
-
-  void clear() {
-    DieValueMap.clear();
-    DieValues.clear();
-  }
-};
-
-/// DwarfEmitter presents interface to generate all debug info tables.
-class DwarfEmitter {
-public:
-  virtual ~DwarfEmitter();
-
-  /// Emit section named SecName with data SecData.
-  virtual void emitSectionContents(StringRef SecData, StringRef SecName) = 0;
-
-  /// Emit the abbreviation table \p Abbrevs to the .debug_abbrev section.
-  virtual void
-  emitAbbrevs(const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs,
-              unsigned DwarfVersion) = 0;
-
-  /// Emit the string table described by \p Pool into .debug_str table.
-  virtual void emitStrings(const NonRelocatableStringpool &Pool) = 0;
-
-  /// Emit the debug string offset table described by \p StringOffsets into the
-  /// .debug_str_offsets table.
-  virtual void emitStringOffsets(const SmallVector<uint64_t> &StringOffsets,
-                                 uint16_t TargetDWARFVersion) = 0;
-
-  /// Emit the string table described by \p Pool into .debug_line_str table.
-  virtual void emitLineStrings(const NonRelocatableStringpool &Pool) = 0;
-
-  /// Emit DWARF debug names.
-  virtual void emitDebugNames(DWARF5AccelTable &Table) = 0;
-
-  /// Emit Apple namespaces accelerator table.
-  virtual void
-  emitAppleNamespaces(AccelTable<AppleAccelTableStaticOffsetData> &Table) = 0;
-
-  /// Emit Apple names accelerator table.
-  virtual void
-  emitAppleNames(AccelTable<AppleAccelTableStaticOffsetData> &Table) = 0;
-
-  /// Emit Apple Objective-C accelerator table.
-  virtual void
-  emitAppleObjc(AccelTable<AppleAccelTableStaticOffsetData> &Table) = 0;
-
-  /// Emit Apple type accelerator table.
-  virtual void
-  emitAppleTypes(AccelTable<AppleAccelTableStaticTypeData> &Table) = 0;
-
-  /// Emit debug ranges (.debug_ranges, .debug_rnglists) header.
-  virtual MCSymbol *emitDwarfDebugRangeListHeader(const CompileUnit &Unit) = 0;
-
-  /// Emit debug ranges (.debug_ranges, .debug_rnglists) fragment.
-  virtual void emitDwarfDebugRangeListFragment(
-      const CompileUnit &Unit, const AddressRanges &LinkedRanges,
-      PatchLocation Patch, DebugDieValuePool &AddrPool) = 0;
-
-  /// Emit debug ranges (.debug_ranges, .debug_rnglists) footer.
-  virtual void emitDwarfDebugRangeListFooter(const CompileUnit &Unit,
-                                             MCSymbol *EndLabel) = 0;
-
-  /// Emit debug locations (.debug_loc, .debug_loclists) header.
-  virtual MCSymbol *emitDwarfDebugLocListHeader(const CompileUnit &Unit) = 0;
-
-  /// Emit debug locations (.debug_loc, .debug_loclists) fragment.
-  virtual void emitDwarfDebugLocListFragment(
-      const CompileUnit &Unit,
-      const DWARFLocationExpressionsVector &LinkedLocationExpression,
-      PatchLocation Patch, DebugDieValuePool &AddrPool) = 0;
-
-  /// Emit debug locations (.debug_loc, .debug_loclists) footer.
-  virtual void emitDwarfDebugLocListFooter(const CompileUnit &Unit,
-                                           MCSymbol *EndLabel) = 0;
-
-  /// Emit .debug_addr header.
-  virtual MCSymbol *emitDwarfDebugAddrsHeader(const CompileUnit &Unit) = 0;
-
-  /// Emit the addresses described by \p Addrs into the .debug_addr section.
-  virtual void emitDwarfDebugAddrs(const SmallVector<uint64_t> &Addrs,
-                                   uint8_t AddrSize) = 0;
-
-  /// Emit .debug_addr footer.
-  virtual void emitDwarfDebugAddrsFooter(const CompileUnit &Unit,
-                                         MCSymbol *EndLabel) = 0;
-
-  /// Emit .debug_aranges entries for \p Unit
-  virtual void
-  emitDwarfDebugArangesTable(const CompileUnit &Unit,
-                             const AddressRanges &LinkedRanges) = 0;
-
-  /// Emit specified \p LineTable into .debug_line table.
-  virtual void emitLineTableForUnit(const DWARFDebugLine::LineTable &LineTable,
-                                    const CompileUnit &Unit,
-                                    OffsetsStringPool &DebugStrPool,
-                                    OffsetsStringPool &DebugLineStrPool) = 0;
-
-  /// Emit the .debug_pubnames contribution for \p Unit.
-  virtual void emitPubNamesForUnit(const CompileUnit &Unit) = 0;
-
-  /// Emit the .debug_pubtypes contribution for \p Unit.
-  virtual void emitPubTypesForUnit(const CompileUnit &Unit) = 0;
-
-  /// Emit a CIE.
-  virtual void emitCIE(StringRef CIEBytes) = 0;
-
-  /// Emit an FDE with data \p Bytes.
-  virtual void emitFDE(uint32_t CIEOffset, uint32_t AddreSize, uint64_t Address,
-                       StringRef Bytes) = 0;
-
-  /// Emit the compilation unit header for \p Unit in the
-  /// .debug_info section.
-  ///
-  /// As a side effect, this also switches the current Dwarf version
-  /// of the MC layer to the one of U.getOrigUnit().
-  virtual void emitCompileUnitHeader(CompileUnit &Unit,
-                                     unsigned DwarfVersion) = 0;
-
-  /// Recursively emit the DIE tree rooted at \p Die.
-  virtual void emitDIE(DIE &Die) = 0;
-
-  /// Emit all available macro tables(DWARFv4 and DWARFv5).
-  /// Use \p UnitMacroMap to get compilation unit by macro table offset.
-  /// Side effects: Fill \p StringPool with macro strings, update
-  /// DW_AT_macro_info, DW_AT_macros attributes for corresponding compile
-  /// units.
-  virtual void emitMacroTables(DWARFContext *Context,
-                               const Offset2UnitMap &UnitMacroMap,
-                               OffsetsStringPool &StringPool) = 0;
-
-  /// Returns size of generated .debug_line section.
-  virtual uint64_t getLineSectionSize() const = 0;
-
-  /// Returns size of generated .debug_frame section.
-  virtual uint64_t getFrameSectionSize() const = 0;
-
-  /// Returns size of generated .debug_ranges section.
-  virtual uint64_t getRangesSectionSize() const = 0;
-
-  /// Returns size of generated .debug_rnglists section.
-  virtual uint64_t getRngListsSectionSize() const = 0;
-
-  /// Returns size of generated .debug_info section.
-  virtual uint64_t getDebugInfoSectionSize() const = 0;
-
-  /// Returns size of generated .debug_macinfo section.
-  virtual uint64_t getDebugMacInfoSectionSize() const = 0;
-
-  /// Returns size of generated .debug_macro section.
-  virtual uint64_t getDebugMacroSectionSize() const = 0;
-
-  /// Returns size of generated .debug_loclists section.
-  virtual uint64_t getLocListsSectionSize() const = 0;
-
-  /// Returns size of generated .debug_addr section.
-  virtual uint64_t getDebugAddrSectionSize() const = 0;
-
-  /// Dump the file to the disk.
-  virtual void finish() = 0;
-
-  /// Emit the swift_ast section stored in \p Buffer.
-  virtual void emitSwiftAST(StringRef Buffer) = 0;
-
-  /// Emit the swift reflection section stored in \p Buffer.
-  virtual void emitSwiftReflectionSection(
-      llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind,
-      StringRef Buffer, uint32_t Alignment, uint32_t Size) = 0;
-
-  /// Returns underlying AsmPrinter.
-  virtual AsmPrinter &getAsmPrinter() const = 0;
-};
-
 class DwarfStreamer;
 using UnitListTy = std::vector<std::unique_ptr<CompileUnit>>;
 
-/// This class represents DWARF information for source file
-/// and its address map.
-class DWARFFile {
-public:
-  using UnloadCallbackTy = std::function<void(StringRef FileName)>;
-  DWARFFile(StringRef Name, std::unique_ptr<DWARFContext> Dwarf,
-            std::unique_ptr<AddressesMap> Addresses,
-            UnloadCallbackTy UnloadFunc = nullptr)
-      : FileName(Name), Dwarf(std::move(Dwarf)),
-        Addresses(std::move(Addresses)), UnloadFunc(UnloadFunc) {}
-
-  /// The object file name.
-  StringRef FileName;
-
-  /// The source DWARF information.
-  std::unique_ptr<DWARFContext> Dwarf;
-
-  /// Helpful address information(list of valid address ranges, relocations).
-  std::unique_ptr<AddressesMap> Addresses;
-
-  /// Callback to the module keeping object file to unload.
-  UnloadCallbackTy UnloadFunc;
-
-  /// Unloads object file and corresponding AddressesMap and Dwarf Context.
-  void unload() {
-    Addresses.reset();
-    Dwarf.reset();
-
-    if (UnloadFunc)
-      UnloadFunc(FileName);
-  }
-};
-
-typedef std::map<std::string, std::string> swiftInterfacesMap;
-typedef std::map<std::string, std::string> objectPrefixMap;
-
-typedef function_ref<void(const DWARFUnit &Unit)> CompileUnitHandler;
-
 /// The core of the Dwarf linking logic.
 ///
 /// The generation of the dwarf information from the object files will be
@@ -334,46 +49,20 @@ typedef function_ref<void(const DWARFUnit &Unit)> CompileUnitHandler;
 /// a variable). These relocations are called ValidRelocs in the
 /// AddressesInfo and are gathered as a very first step when we start
 /// processing a object file.
-class DWARFLinker {
+class DWARFLinker : public DWARFLinkerBase {
 public:
-  typedef std::function<void(const Twine &Warning, StringRef Context,
-                             const DWARFDie *DIE)>
-      messageHandler;
-  DWARFLinker(messageHandler ErrorHandler, messageHandler WarningHandler,
+  DWARFLinker(MessageHandlerTy ErrorHandler, MessageHandlerTy WarningHandler,
               std::function<StringRef(StringRef)> StringsTranslator)
-      : DwarfLinkerClientID(DwarfLinkerClient::Dsymutil),
-        StringsTranslator(StringsTranslator), ErrorHandler(ErrorHandler),
+      : StringsTranslator(StringsTranslator), ErrorHandler(ErrorHandler),
         WarningHandler(WarningHandler) {}
 
   static std::unique_ptr<DWARFLinker> createLinker(
-      messageHandler ErrorHandler, messageHandler WarningHandler,
+      MessageHandlerTy ErrorHandler, MessageHandlerTy WarningHandler,
       std::function<StringRef(StringRef)> StringsTranslator = nullptr) {
     return std::make_unique<DWARFLinker>(ErrorHandler, WarningHandler,
                                          StringsTranslator);
   }
 
-  /// Type of output file.
-  enum class OutputFileType {
-    Object,
-    Assembly,
-  };
-
-  /// The kind of accelerator tables we should emit.
-  enum class AccelTableKind : uint8_t {
-    Apple,     ///< .apple_names, .apple_namespaces, .apple_types, .apple_objc.
-    Pub,       ///< .debug_pubnames, .debug_pubtypes
-    DebugNames ///< .debug_names.
-  };
-  typedef std::function<void(const DWARFFile &File, llvm::StringRef Output)> inputVerificationHandler;
-  typedef std::function<ErrorOr<DWARFFile &>(StringRef ContainerName,
-                                             StringRef Path)>
-      objFileLoader;
-
-  Error createEmitter(const Triple &TheTriple, OutputFileType FileType,
-                      raw_pwrite_stream &OutFile);
-
-  DwarfEmitter *getEmitter();
-
   /// Add object file to be linked. Pre-load compile unit die. Call
   /// \p OnCUDieLoaded for each compile unit die. If specified \p File
   /// has reference to the Clang module then such module would be
@@ -381,73 +70,84 @@ class DWARFLinker {
   ///
   /// \pre NoODR, Update options should be set before call to addObjectFile.
   void addObjectFile(
-      DWARFFile &File, objFileLoader Loader = nullptr,
-      CompileUnitHandler OnCUDieLoaded = [](const DWARFUnit &) {});
+      DWARFFile &File, ObjFileLoaderTy Loader = nullptr,
+      CompileUnitHandlerTy OnCUDieLoaded = [](const DWARFUnit &) {}) override;
 
   /// Link debug info for added objFiles. Object files are linked all together.
-  Error link();
+  Error link() override;
 
   /// A number of methods setting various linking options:
 
   /// Allows to generate log of linking process to the standard output.
-  void setVerbosity(bool Verbose) { Options.Verbose = Verbose; }
+  void setVerbosity(bool Verbose) override { Options.Verbose = Verbose; }
 
   /// Print statistics to standard output.
-  void setStatistics(bool Statistics) { Options.Statistics = Statistics; }
+  void setStatistics(bool Statistics) override {
+    Options.Statistics = Statistics;
+  }
 
   /// Verify the input DWARF.
-  void setVerifyInputDWARF(bool Verify) { Options.VerifyInputDWARF = Verify; }
+  void setVerifyInputDWARF(bool Verify) override {
+    Options.VerifyInputDWARF = Verify;
+  }
 
   /// Do not unique types according to ODR.
-  void setNoODR(bool NoODR) { Options.NoODR = NoODR; }
+  void setNoODR(bool NoODR) override { Options.NoODR = NoODR; }
 
   /// Update index tables only(do not modify rest of DWARF).
-  void setUpdateIndexTablesOnly(bool Update) { Options.Update = Update; }
+  void setUpdateIndexTablesOnly(bool Update) override {
+    Options.Update = Update;
+  }
 
   /// Allow generating valid, but non-deterministic output.
-  void setAllowNonDeterministicOutput(bool) { /* Nothing to do. */
+  void setAllowNonDeterministicOutput(bool) override { /* Nothing to do. */
   }
 
   /// Set whether to keep the enclosing function for a static variable.
-  void setKeepFunctionForStatic(bool KeepFunctionForStatic) {
+  void setKeepFunctionForStatic(bool KeepFunctionForStatic) override {
     Options.KeepFunctionForStatic = KeepFunctionForStatic;
   }
 
   /// Use specified number of threads for parallel files linking.
-  void setNumThreads(unsigned NumThreads) { Options.Threads = NumThreads; }
+  void setNumThreads(unsigned NumThreads) override {
+    Options.Threads = NumThreads;
+  }
 
   /// Add kind of accelerator tables to be generated.
-  void addAccelTableKind(AccelTableKind Kind) {
+  void addAccelTableKind(AccelTableKind Kind) override {
     assert(!llvm::is_contained(Options.AccelTables, Kind));
     Options.AccelTables.emplace_back(Kind);
   }
 
   /// Set prepend path for clang modules.
-  void setPrependPath(const std::string &Ppath) { Options.PrependPath = Ppath; }
+  void setPrependPath(const std::string &Ppath) override {
+    Options.PrependPath = Ppath;
+  }
 
   /// Set estimated objects files amount, for preliminary data allocation.
-  void setEstimatedObjfilesAmount(unsigned ObjFilesNum) {
+  void setEstimatedObjfilesAmount(unsigned ObjFilesNum) override {
     ObjectContexts.reserve(ObjFilesNum);
   }
 
   /// Set verification handler which would be used to report verification
   /// errors.
-  void setInputVerificationHandler(inputVerificationHandler Handler) {
+  void
+  setInputVerificationHandler(InputVerificationHandlerTy Handler) override {
     Options.InputVerificationHandler = Handler;
   }
 
   /// Set map for Swift interfaces.
-  void setSwiftInterfacesMap(swiftInterfacesMap *Map) {
+  void setSwiftInterfacesMap(SwiftInterfacesMapTy *Map) override {
     Options.ParseableSwiftInterfaces = Map;
   }
 
   /// Set prefix map for objects.
-  void setObjectPrefixMap(objectPrefixMap *Map) {
+  void setObjectPrefixMap(ObjectPrefixMapTy *Map) override {
     Options.ObjectPrefixMap = Map;
   }
 
   /// Set target DWARF version.
-  Error setTargetDWARFVersion(uint16_t TargetDWARFVersion) {
+  Error setTargetDWARFVersion(uint16_t TargetDWARFVersion) override {
     if ((TargetDWARFVersion < 1) || (TargetDWARFVersion > 5))
       return createStringError(std::errc::invalid_argument,
                                "unsupported DWARF version: %d",
@@ -457,6 +157,11 @@ class DWARFLinker {
     return Error::success();
   }
 
+  /// Set output DWARF emitter.
+  void setOutputDWARFStreamer(DwarfStreamer *Streamer) {
+    OutDwarfStreamer = Streamer;
+  }
+
 private:
   /// Flags passed to DwarfLinker::lookForDIEsToKeep
   enum TraversalFlags {
@@ -619,23 +324,24 @@ class DWARFLinker {
   /// pointing to the module, and a DW_AT_gnu_dwo_id with the module
   /// hash.
   bool registerModuleReference(const DWARFDie &CUDie, LinkContext &Context,
-                               objFileLoader Loader,
-                               CompileUnitHandler OnCUDieLoaded,
+                               ObjFileLoaderTy Loader,
+                               CompileUnitHandlerTy OnCUDieLoaded,
                                unsigned Indent = 0);
 
   /// Recursively add the debug info in this clang module .pcm
   /// file (and all the modules imported by it in a bottom-up fashion)
   /// to ModuleUnits.
-  Error loadClangModule(objFileLoader Loader, const DWARFDie &CUDie,
+  Error loadClangModule(ObjFileLoaderTy Loader, const DWARFDie &CUDie,
                         const std::string &PCMFile, LinkContext &Context,
-                        CompileUnitHandler OnCUDieLoaded, unsigned Indent = 0);
+                        CompileUnitHandlerTy OnCUDieLoaded,
+                        unsigned Indent = 0);
 
   /// Clone specified Clang module unit \p Unit.
   Error cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit,
                         DeclContextTree &ODRContexts,
                         OffsetsStringPool &DebugStrPool,
                         OffsetsStringPool &DebugLineStrPool,
-                        DebugDieValuePool &StringOffsetPool,
+                        IndexedValuesMap<uint64_t> &StringOffsetPool,
                         unsigned Indent = 0);
 
   unsigned shouldKeepDIE(AddressesMap &RelocMgr, const DWARFDie &DIE,
@@ -679,12 +385,12 @@ class DWARFLinker {
 
   class DIECloner {
     DWARFLinker &Linker;
-    DwarfEmitter *Emitter;
+    DwarfStreamer *Streamer;
     DWARFFile &ObjFile;
     OffsetsStringPool &DebugStrPool;
     OffsetsStringPool &DebugLineStrPool;
-    DebugDieValuePool &StringOffsetPool;
-    DebugDieValuePool AddrPool;
+    IndexedValuesMap<uint64_t> &StringOffsetPool;
+    IndexedValuesMap<uint64_t> AddrPool;
 
     /// Allocator used for all the DIEValue objects.
     BumpPtrAllocator &DIEAlloc;
@@ -698,13 +404,13 @@ class DWARFLinker {
     bool Update;
 
   public:
-    DIECloner(DWARFLinker &Linker, DwarfEmitter *Emitter, DWARFFile &ObjFile,
+    DIECloner(DWARFLinker &Linker, DwarfStreamer *Streamer, DWARFFile &ObjFile,
               BumpPtrAllocator &DIEAlloc,
               std::vector<std::unique_ptr<CompileUnit>> &CompileUnits,
               bool Update, OffsetsStringPool &DebugStrPool,
               OffsetsStringPool &DebugLineStrPool,
-              DebugDieValuePool &StringOffsetPool)
-        : Linker(Linker), Emitter(Emitter), ObjFile(ObjFile),
+              IndexedValuesMap<uint64_t> &StringOffsetPool)
+        : Linker(Linker), Streamer(Streamer), ObjFile(ObjFile),
           DebugStrPool(DebugStrPool), DebugLineStrPool(DebugLineStrPool),
           StringOffsetPool(StringOffsetPool), DIEAlloc(DIEAlloc),
           CompileUnits(CompileUnits), Update(Update) {}
@@ -863,7 +569,7 @@ class DWARFLinker {
   /// Compute and emit debug ranges(.debug_aranges, .debug_ranges,
   /// .debug_rnglists) for \p Unit, patch the attributes referencing it.
   void generateUnitRanges(CompileUnit &Unit, const DWARFFile &File,
-                          DebugDieValuePool &AddrPool) const;
+                          IndexedValuesMap<uint64_t> &AddrPool) const;
 
   /// Emit the accelerator entries for \p Unit.
   void emitAcceleratorEntriesForUnit(CompileUnit &Unit);
@@ -889,7 +595,7 @@ class DWARFLinker {
   BumpPtrAllocator DIEAlloc;
   /// @}
 
-  std::unique_ptr<DwarfStreamer> TheDwarfEmitter;
+  DwarfStreamer *OutDwarfStreamer = nullptr;
   std::vector<LinkContext> ObjectContexts;
 
   /// The CIEs that have been emitted in the output section. The actual CIE
@@ -911,18 +617,16 @@ class DWARFLinker {
   /// Mapping the PCM filename to the DwoId.
   StringMap<uint64_t> ClangModules;
 
-  DwarfLinkerClient DwarfLinkerClientID;
-
   std::function<StringRef(StringRef)> StringsTranslator = nullptr;
 
   /// A unique ID that identifies each compile unit.
   unsigned UniqueUnitID = 0;
 
   // error handler
-  messageHandler ErrorHandler = nullptr;
+  MessageHandlerTy ErrorHandler = nullptr;
 
   // warning handler
-  messageHandler WarningHandler = nullptr;
+  MessageHandlerTy WarningHandler = nullptr;
 
   /// linking options
   struct DWARFLinkerOptions {
@@ -958,20 +662,21 @@ class DWARFLinker {
     std::string PrependPath;
 
     // input verification handler
-    inputVerificationHandler InputVerificationHandler = nullptr;
+    InputVerificationHandlerTy InputVerificationHandler = nullptr;
 
     /// A list of all .swiftinterface files referenced by the debug
     /// info, mapping Module name to path on disk. The entries need to
     /// be uniqued and sorted and there are only few entries expected
     /// per compile unit, which is why this is a std::map.
     /// this is dsymutil specific fag.
-    swiftInterfacesMap *ParseableSwiftInterfaces = nullptr;
+    SwiftInterfacesMapTy *ParseableSwiftInterfaces = nullptr;
 
     /// A list of remappings to apply to file paths.
-    objectPrefixMap *ObjectPrefixMap = nullptr;
+    ObjectPrefixMapTy *ObjectPrefixMap = nullptr;
   } Options;
 };
 
+} // end namespace dwarflinker
 } // end namespace llvm
 
-#endif // LLVM_DWARFLINKER_DWARFLINKER_H
+#endif // LLVM_DWARFLINKER_APPLE_DWARFLINKER_H
diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h b/llvm/include/llvm/DWARFLinker/Apple/DWARFLinkerCompileUnit.h
similarity index 98%
rename from llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h
rename to llvm/include/llvm/DWARFLinker/Apple/DWARFLinkerCompileUnit.h
index 08ebd4bc70bc93..915fba7c0bacc2 100644
--- a/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h
+++ b/llvm/include/llvm/DWARFLinker/Apple/DWARFLinkerCompileUnit.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_DWARFLINKER_DWARFLINKERCOMPILEUNIT_H
-#define LLVM_DWARFLINKER_DWARFLINKERCOMPILEUNIT_H
+#ifndef LLVM_DWARFLINKER_APPLE_DWARFLINKERCOMPILEUNIT_H
+#define LLVM_DWARFLINKER_APPLE_DWARFLINKERCOMPILEUNIT_H
 
 #include "llvm/ADT/AddressRanges.h"
 #include "llvm/ADT/DenseMap.h"
@@ -16,6 +16,7 @@
 #include <optional>
 
 namespace llvm {
+namespace dwarflinker {
 
 class DeclContext;
 
@@ -327,6 +328,7 @@ class CompileUnit {
   std::string ClangModuleName;
 };
 
+} // end namespace dwarflinker
 } // end namespace llvm
 
-#endif // LLVM_DWARFLINKER_DWARFLINKERCOMPILEUNIT_H
+#endif // LLVM_DWARFLINKER_APPLE_DWARFLINKERCOMPILEUNIT_H
diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinkerDeclContext.h b/llvm/include/llvm/DWARFLinker/Apple/DWARFLinkerDeclContext.h
similarity index 96%
rename from llvm/include/llvm/DWARFLinker/DWARFLinkerDeclContext.h
rename to llvm/include/llvm/DWARFLinker/Apple/DWARFLinkerDeclContext.h
index fb02b0fc1b4dfe..dd10deb6378a3d 100644
--- a/llvm/include/llvm/DWARFLinker/DWARFLinkerDeclContext.h
+++ b/llvm/include/llvm/DWARFLinker/Apple/DWARFLinkerDeclContext.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_DWARFLINKER_DWARFLINKERDECLCONTEXT_H
-#define LLVM_DWARFLINKER_DWARFLINKERDECLCONTEXT_H
+#ifndef LLVM_DWARFLINKER_APPLE_DWARFLINKERDECLCONTEXT_H
+#define LLVM_DWARFLINKER_APPLE_DWARFLINKERDECLCONTEXT_H
 
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/DenseMapInfo.h"
@@ -21,6 +21,7 @@
 #include <atomic>
 
 namespace llvm {
+namespace dwarflinker {
 
 class CompileUnit;
 struct DeclMapInfo;
@@ -184,6 +185,7 @@ struct DeclMapInfo : private DenseMapInfo<DeclContext *> {
   }
 };
 
+} // end namespace dwarflinker
 } // end namespace llvm
 
-#endif // LLVM_DWARFLINKER_DWARFLINKERDECLCONTEXT_H
+#endif // LLVM_DWARFLINKER_APPLE_DWARFLINKERDECLCONTEXT_H
diff --git a/llvm/include/llvm/DWARFLinker/DWARFStreamer.h b/llvm/include/llvm/DWARFLinker/Apple/DWARFStreamer.h
similarity index 72%
rename from llvm/include/llvm/DWARFLinker/DWARFStreamer.h
rename to llvm/include/llvm/DWARFLinker/Apple/DWARFStreamer.h
index 18eb7277bfa2df..fa2c0c30ed6832 100644
--- a/llvm/include/llvm/DWARFLinker/DWARFStreamer.h
+++ b/llvm/include/llvm/DWARFLinker/Apple/DWARFStreamer.h
@@ -6,12 +6,13 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_DWARFLINKER_DWARFSTREAMER_H
-#define LLVM_DWARFLINKER_DWARFSTREAMER_H
+#ifndef LLVM_DWARFLINKER_APPLE_DWARFSTREAMER_H
+#define LLVM_DWARFLINKER_APPLE_DWARFSTREAMER_H
 
 #include "llvm/BinaryFormat/Swift.h"
 #include "llvm/CodeGen/AsmPrinter.h"
-#include "llvm/DWARFLinker/DWARFLinker.h"
+#include "llvm/DWARFLinker/Apple/DWARFLinker.h"
+#include "llvm/DWARFLinker/IndexedValuesMap.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCInstrInfo.h"
@@ -34,25 +35,36 @@ template <typename DataT> class AccelTable;
 class MCCodeEmitter;
 class DWARFDebugMacro;
 
+namespace dwarflinker {
+
 /// The Dwarf streaming logic.
 ///
 /// All interactions with the MC layer that is used to build the debug
 /// information binary representation are handled in this class.
-class DwarfStreamer : public DwarfEmitter {
+class DwarfStreamer {
 public:
-  DwarfStreamer(DWARFLinker::OutputFileType OutFileType,
+  DwarfStreamer(DWARFLinkerBase::OutputFileType OutFileType,
                 raw_pwrite_stream &OutFile,
                 std::function<StringRef(StringRef Input)> Translator,
-                DWARFLinker::messageHandler Warning)
+                DWARFLinkerBase::MessageHandlerTy Warning)
       : OutFile(OutFile), OutFileType(OutFileType), Translator(Translator),
         WarningHandler(Warning) {}
 
+  static Expected<DwarfStreamer *>
+  createStreamer(const Triple &TheTriple,
+                 DWARFLinkerBase::OutputFileType FileType,
+                 raw_pwrite_stream &OutFile,
+                 std::function<StringRef(StringRef Input)> Translator,
+                 DWARFLinkerBase::MessageHandlerTy Warning);
+
   Error init(Triple TheTriple, StringRef Swift5ReflectionSegmentName);
 
+  const Triple &getTargetTriple() { return TheTargetTriple; }
+
   /// Dump the file to the disk.
-  void finish() override;
+  void finish();
 
-  AsmPrinter &getAsmPrinter() const override { return *Asm; }
+  AsmPrinter &getAsmPrinter() const { return *Asm; }
 
   /// Set the current output section to debug_info and change
   /// the MC Dwarf version to \p DwarfVersion.
@@ -63,147 +75,131 @@ class DwarfStreamer : public DwarfEmitter {
   ///
   /// As a side effect, this also switches the current Dwarf version
   /// of the MC layer to the one of U.getOrigUnit().
-  void emitCompileUnitHeader(CompileUnit &Unit, unsigned DwarfVersion) override;
+  void emitCompileUnitHeader(CompileUnit &Unit, unsigned DwarfVersion);
 
   /// Recursively emit the DIE tree rooted at \p Die.
-  void emitDIE(DIE &Die) override;
+  void emitDIE(DIE &Die);
 
   /// Emit the abbreviation table \p Abbrevs to the debug_abbrev section.
   void emitAbbrevs(const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs,
-                   unsigned DwarfVersion) override;
+                   unsigned DwarfVersion);
 
   /// Emit contents of section SecName From Obj.
-  void emitSectionContents(StringRef SecData, StringRef SecName) override;
+  void emitSectionContents(StringRef SecData, StringRef SecName);
 
   /// Emit the string table described by \p Pool into .debug_str table.
-  void emitStrings(const NonRelocatableStringpool &Pool) override;
+  void emitStrings(const NonRelocatableStringpool &Pool);
 
   /// Emit the debug string offset table described by \p StringOffsets into the
   /// .debug_str_offsets table.
   void emitStringOffsets(const SmallVector<uint64_t> &StringOffset,
-                         uint16_t TargetDWARFVersion) override;
+                         uint16_t TargetDWARFVersion);
 
   /// Emit the string table described by \p Pool into .debug_line_str table.
-  void emitLineStrings(const NonRelocatableStringpool &Pool) override;
+  void emitLineStrings(const NonRelocatableStringpool &Pool);
 
   /// Emit the swift_ast section stored in \p Buffer.
-  void emitSwiftAST(StringRef Buffer) override;
+  void emitSwiftAST(StringRef Buffer);
 
   /// Emit the swift reflection section stored in \p Buffer.
   void emitSwiftReflectionSection(
       llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind,
-      StringRef Buffer, uint32_t Alignment, uint32_t Size) override;
+      StringRef Buffer, uint32_t Alignment, uint32_t Size);
 
   /// Emit debug ranges(.debug_ranges, .debug_rnglists) header.
-  MCSymbol *emitDwarfDebugRangeListHeader(const CompileUnit &Unit) override;
+  MCSymbol *emitDwarfDebugRangeListHeader(const CompileUnit &Unit);
 
   /// Emit debug ranges(.debug_ranges, .debug_rnglists) fragment.
   void emitDwarfDebugRangeListFragment(const CompileUnit &Unit,
                                        const AddressRanges &LinkedRanges,
                                        PatchLocation Patch,
-                                       DebugDieValuePool &AddrPool) override;
+                                       IndexedValuesMap<uint64_t> &AddrPool);
 
   /// Emit debug ranges(.debug_ranges, .debug_rnglists) footer.
   void emitDwarfDebugRangeListFooter(const CompileUnit &Unit,
-                                     MCSymbol *EndLabel) override;
+                                     MCSymbol *EndLabel);
 
   /// Emit debug locations(.debug_loc, .debug_loclists) header.
-  MCSymbol *emitDwarfDebugLocListHeader(const CompileUnit &Unit) override;
+  MCSymbol *emitDwarfDebugLocListHeader(const CompileUnit &Unit);
 
   /// Emit .debug_addr header.
-  MCSymbol *emitDwarfDebugAddrsHeader(const CompileUnit &Unit) override;
+  MCSymbol *emitDwarfDebugAddrsHeader(const CompileUnit &Unit);
 
   /// Emit the addresses described by \p Addrs into .debug_addr table.
   void emitDwarfDebugAddrs(const SmallVector<uint64_t> &Addrs,
-                           uint8_t AddrSize) override;
+                           uint8_t AddrSize);
 
   /// Emit .debug_addr footer.
-  void emitDwarfDebugAddrsFooter(const CompileUnit &Unit,
-                                 MCSymbol *EndLabel) override;
+  void emitDwarfDebugAddrsFooter(const CompileUnit &Unit, MCSymbol *EndLabel);
 
   /// Emit debug ranges(.debug_loc, .debug_loclists) fragment.
   void emitDwarfDebugLocListFragment(
       const CompileUnit &Unit,
       const DWARFLocationExpressionsVector &LinkedLocationExpression,
-      PatchLocation Patch, DebugDieValuePool &AddrPool) override;
+      PatchLocation Patch, IndexedValuesMap<uint64_t> &AddrPool);
 
   /// Emit debug ranges(.debug_loc, .debug_loclists) footer.
-  void emitDwarfDebugLocListFooter(const CompileUnit &Unit,
-                                   MCSymbol *EndLabel) override;
+  void emitDwarfDebugLocListFooter(const CompileUnit &Unit, MCSymbol *EndLabel);
 
   /// Emit .debug_aranges entries for \p Unit
   void emitDwarfDebugArangesTable(const CompileUnit &Unit,
-                                  const AddressRanges &LinkedRanges) override;
+                                  const AddressRanges &LinkedRanges);
 
-  uint64_t getRangesSectionSize() const override { return RangesSectionSize; }
+  uint64_t getRangesSectionSize() const { return RangesSectionSize; }
 
-  uint64_t getRngListsSectionSize() const override {
-    return RngListsSectionSize;
-  }
+  uint64_t getRngListsSectionSize() const { return RngListsSectionSize; }
 
   /// Emit .debug_line table entry for specified \p LineTable
   void emitLineTableForUnit(const DWARFDebugLine::LineTable &LineTable,
                             const CompileUnit &Unit,
                             OffsetsStringPool &DebugStrPool,
-                            OffsetsStringPool &DebugLineStrPool) override;
+                            OffsetsStringPool &DebugLineStrPool);
 
-  uint64_t getLineSectionSize() const override { return LineSectionSize; }
+  uint64_t getLineSectionSize() const { return LineSectionSize; }
 
   /// Emit the .debug_pubnames contribution for \p Unit.
-  void emitPubNamesForUnit(const CompileUnit &Unit) override;
+  void emitPubNamesForUnit(const CompileUnit &Unit);
 
   /// Emit the .debug_pubtypes contribution for \p Unit.
-  void emitPubTypesForUnit(const CompileUnit &Unit) override;
+  void emitPubTypesForUnit(const CompileUnit &Unit);
 
   /// Emit a CIE.
-  void emitCIE(StringRef CIEBytes) override;
+  void emitCIE(StringRef CIEBytes);
 
   /// Emit an FDE with data \p Bytes.
   void emitFDE(uint32_t CIEOffset, uint32_t AddreSize, uint64_t Address,
-               StringRef Bytes) override;
+               StringRef Bytes);
 
   /// Emit DWARF debug names.
-  void emitDebugNames(DWARF5AccelTable &Table) override;
+  void emitDebugNames(DWARF5AccelTable &Table);
 
   /// Emit Apple namespaces accelerator table.
-  void emitAppleNamespaces(
-      AccelTable<AppleAccelTableStaticOffsetData> &Table) override;
+  void emitAppleNamespaces(AccelTable<AppleAccelTableStaticOffsetData> &Table);
 
   /// Emit Apple names accelerator table.
-  void
-  emitAppleNames(AccelTable<AppleAccelTableStaticOffsetData> &Table) override;
+  void emitAppleNames(AccelTable<AppleAccelTableStaticOffsetData> &Table);
 
   /// Emit Apple Objective-C accelerator table.
-  void
-  emitAppleObjc(AccelTable<AppleAccelTableStaticOffsetData> &Table) override;
+  void emitAppleObjc(AccelTable<AppleAccelTableStaticOffsetData> &Table);
 
   /// Emit Apple type accelerator table.
-  void
-  emitAppleTypes(AccelTable<AppleAccelTableStaticTypeData> &Table) override;
+  void emitAppleTypes(AccelTable<AppleAccelTableStaticTypeData> &Table);
 
-  uint64_t getFrameSectionSize() const override { return FrameSectionSize; }
+  uint64_t getFrameSectionSize() const { return FrameSectionSize; }
 
-  uint64_t getDebugInfoSectionSize() const override {
-    return DebugInfoSectionSize;
-  }
+  uint64_t getDebugInfoSectionSize() const { return DebugInfoSectionSize; }
 
-  uint64_t getDebugMacInfoSectionSize() const override {
-    return MacInfoSectionSize;
-  }
+  uint64_t getDebugMacInfoSectionSize() const { return MacInfoSectionSize; }
 
-  uint64_t getDebugMacroSectionSize() const override {
-    return MacroSectionSize;
-  }
+  uint64_t getDebugMacroSectionSize() const { return MacroSectionSize; }
 
-  uint64_t getLocListsSectionSize() const override {
-    return LocListsSectionSize;
-  }
+  uint64_t getLocListsSectionSize() const { return LocListsSectionSize; }
 
-  uint64_t getDebugAddrSectionSize() const override { return AddrSectionSize; }
+  uint64_t getDebugAddrSectionSize() const { return AddrSectionSize; }
 
   void emitMacroTables(DWARFContext *Context,
                        const Offset2UnitMap &UnitMacroMap,
-                       OffsetsStringPool &StringPool) override;
+                       OffsetsStringPool &StringPool);
 
 private:
   inline void warn(const Twine &Warning, StringRef Context = "") {
@@ -211,6 +207,8 @@ class DwarfStreamer : public DwarfEmitter {
       WarningHandler(Warning, Context, nullptr);
   }
 
+  MCSection *switchSection(StringRef SecName);
+
   void emitMacroTableImpl(const DWARFDebugMacro *MacroTable,
                           const Offset2UnitMap &UnitMacroMap,
                           OffsetsStringPool &StringPool, uint64_t &OutOffset);
@@ -221,10 +219,9 @@ class DwarfStreamer : public DwarfEmitter {
                                          PatchLocation Patch);
 
   /// Emit piece of .debug_rnglists for \p LinkedRanges.
-  void emitDwarfDebugRngListsTableFragment(const CompileUnit &Unit,
-                                           const AddressRanges &LinkedRanges,
-                                           PatchLocation Patch,
-                                           DebugDieValuePool &AddrPool);
+  void emitDwarfDebugRngListsTableFragment(
+      const CompileUnit &Unit, const AddressRanges &LinkedRanges,
+      PatchLocation Patch, IndexedValuesMap<uint64_t> &AddrPool);
 
   /// Emit piece of .debug_loc for \p LinkedRanges.
   void emitDwarfDebugLocTableFragment(
@@ -236,7 +233,7 @@ class DwarfStreamer : public DwarfEmitter {
   void emitDwarfDebugLocListsTableFragment(
       const CompileUnit &Unit,
       const DWARFLocationExpressionsVector &LinkedLocationExpression,
-      PatchLocation Patch, DebugDieValuePool &AddrPool);
+      PatchLocation Patch, IndexedValuesMap<uint64_t> &AddrPool);
 
   /// \defgroup Line table emission
   /// @{
@@ -282,9 +279,12 @@ class DwarfStreamer : public DwarfEmitter {
 
   /// The output file we stream the linked Dwarf to.
   raw_pwrite_stream &OutFile;
-  DWARFLinker::OutputFileType OutFileType = DWARFLinker::OutputFileType::Object;
+  DWARFLinkerBase::OutputFileType OutFileType =
+      DWARFLinkerBase::OutputFileType::Object;
   std::function<StringRef(StringRef Input)> Translator;
 
+  Triple TheTargetTriple;
+
   uint64_t RangesSectionSize = 0;
   uint64_t RngListsSectionSize = 0;
   uint64_t LocSectionSize = 0;
@@ -310,9 +310,10 @@ class DwarfStreamer : public DwarfEmitter {
                              const CompileUnit &Unit,
                              const std::vector<CompileUnit::AccelInfo> &Names);
 
-  DWARFLinker::messageHandler WarningHandler = nullptr;
+  DWARFLinkerBase::MessageHandlerTy WarningHandler = nullptr;
 };
 
+} // end namespace dwarflinker
 } // end namespace llvm
 
-#endif // LLVM_DWARFLINKER_DWARFSTREAMER_H
+#endif // LLVM_DWARFLINKER_APPLE_DWARFSTREAMER_H
diff --git a/llvm/lib/DWARFLinkerParallel/ArrayList.h b/llvm/include/llvm/DWARFLinker/ArrayList.h
similarity index 95%
rename from llvm/lib/DWARFLinkerParallel/ArrayList.h
rename to llvm/include/llvm/DWARFLinker/ArrayList.h
index def83f91bc6f31..e09735713db392 100644
--- a/llvm/lib/DWARFLinkerParallel/ArrayList.h
+++ b/llvm/include/llvm/DWARFLinker/ArrayList.h
@@ -6,14 +6,14 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_LIB_DWARFLINKERPARALLEL_ARRAYLIST_H
-#define LLVM_LIB_DWARFLINKERPARALLEL_ARRAYLIST_H
+#ifndef LLVM_DWARFLINKER_ARRAYLIST_H
+#define LLVM_DWARFLINKER_ARRAYLIST_H
 
 #include "llvm/Support/PerThreadBumpPtrAllocator.h"
 #include <atomic>
 
 namespace llvm {
-namespace dwarflinker_parallel {
+namespace dwarflinker {
 
 /// This class is a simple list of T structures. It keeps elements as
 /// pre-allocated groups to save memory for each element's next pointer.
@@ -159,7 +159,7 @@ template <typename T, size_t ItemsGroupSize = 512> class ArrayList {
   parallel::PerThreadBumpPtrAllocator *Allocator = nullptr;
 };
 
-} // end of namespace dwarflinker_parallel
+} // end namespace dwarflinker
 } // end namespace llvm
 
-#endif // LLVM_LIB_DWARFLINKERPARALLEL_ARRAYLIST_H
+#endif // LLVM_DWARFLINKER_ARRAYLIST_H
diff --git a/llvm/include/llvm/DWARFLinkerParallel/DWARFFile.h b/llvm/include/llvm/DWARFLinker/DWARFFile.h
similarity index 79%
rename from llvm/include/llvm/DWARFLinkerParallel/DWARFFile.h
rename to llvm/include/llvm/DWARFLinker/DWARFFile.h
index c320530569bb05..a6997260dcf22e 100644
--- a/llvm/include/llvm/DWARFLinkerParallel/DWARFFile.h
+++ b/llvm/include/llvm/DWARFLinker/DWARFFile.h
@@ -6,18 +6,17 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_DWARFLINKERPARALLEL_DWARFFILE_H
-#define LLVM_DWARFLINKERPARALLEL_DWARFFILE_H
+#ifndef LLVM_DWARFLINKER_DWARFFILE_H
+#define LLVM_DWARFLINKER_DWARFFILE_H
 
+#include "AddressesMap.h"
 #include "llvm/ADT/StringRef.h"
-#include "llvm/DWARFLinkerParallel/AddressesMap.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
-#include "llvm/Support/Endian.h"
 #include <functional>
 #include <memory>
 
 namespace llvm {
-namespace dwarflinker_parallel {
+namespace dwarflinker {
 
 /// This class represents DWARF information for source file
 /// and it's address map.
@@ -29,7 +28,9 @@ class DWARFFile {
 
   DWARFFile(StringRef Name, std::unique_ptr<DWARFContext> Dwarf,
             std::unique_ptr<AddressesMap> Addresses,
-            UnloadCallbackTy UnloadFunc = nullptr);
+            UnloadCallbackTy UnloadFunc = nullptr)
+      : FileName(Name), Dwarf(std::move(Dwarf)),
+        Addresses(std::move(Addresses)), UnloadFunc(UnloadFunc) {}
 
   /// Object file name.
   StringRef FileName;
@@ -53,7 +54,7 @@ class DWARFFile {
   }
 };
 
-} // end namespace dwarflinker_parallel
+} // end namespace dwarflinker
 } // end namespace llvm
 
-#endif // LLVM_DWARFLINKERPARALLEL_DWARFFILE_H
+#endif // LLVM_DWARFLINKER_DWARFFILE_H
diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinkerBase.h b/llvm/include/llvm/DWARFLinker/DWARFLinkerBase.h
new file mode 100644
index 00000000000000..f29a722c81ff25
--- /dev/null
+++ b/llvm/include/llvm/DWARFLinker/DWARFLinkerBase.h
@@ -0,0 +1,124 @@
+//===- DWARFLinkerBase.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 LLVM_DWARFLINKER_DWARFLINKERBASE_H
+#define LLVM_DWARFLINKER_DWARFLINKERBASE_H
+
+#include "AddressesMap.h"
+#include "DWARFFile.h"
+#include "IndexedValuesMap.h"
+#include "llvm/ADT/AddressRanges.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
+#include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
+#include <map>
+
+namespace llvm {
+class DWARFUnit;
+
+namespace dwarflinker {
+
+/// The base interface for DWARFLinker implementations.
+class DWARFLinkerBase {
+public:
+  virtual ~DWARFLinkerBase() = default;
+
+  using MessageHandlerTy = std::function<void(
+      const Twine &Warning, StringRef Context, const DWARFDie *DIE)>;
+  using ObjFileLoaderTy = std::function<ErrorOr<DWARFFile &>(
+      StringRef ContainerName, StringRef Path)>;
+  using InputVerificationHandlerTy =
+      std::function<void(const DWARFFile &File, llvm::StringRef Output)>;
+  using ObjectPrefixMapTy = std::map<std::string, std::string>;
+  using CompileUnitHandlerTy = function_ref<void(const DWARFUnit &Unit)>;
+  using TranslatorFuncTy = std::function<StringRef(StringRef)>;
+  using SwiftInterfacesMapTy = std::map<std::string, std::string>;
+
+  /// Type of output file.
+  enum class OutputFileType : uint8_t {
+    Object,
+    Assembly,
+  };
+
+  /// The kind of accelerator tables we should emit.
+  enum class AccelTableKind : uint8_t {
+    Apple,     ///< .apple_names, .apple_namespaces, .apple_types, .apple_objc.
+    Pub,       ///< .debug_pubnames, .debug_pubtypes
+    DebugNames ///< .debug_names.
+  };
+
+  /// Add object file to be linked. Pre-load compile unit die. Call
+  /// \p OnCUDieLoaded for each compile unit die. If specified \p File
+  /// has reference to the Clang module then such module would be
+  /// pre-loaded by \p Loader for !Update case.
+  ///
+  /// \pre NoODR, Update options should be set before call to addObjectFile.
+  virtual void addObjectFile(
+      DWARFFile &File, ObjFileLoaderTy Loader = nullptr,
+      CompileUnitHandlerTy OnCUDieLoaded = [](const DWARFUnit &) {}) = 0;
+
+  /// Link debug info for added objFiles. Object files are linked all together.
+  virtual Error link() = 0;
+
+  /// A number of methods setting various linking options:
+
+  /// Allows to generate log of linking process to the standard output.
+  virtual void setVerbosity(bool Verbose) = 0;
+
+  /// Print statistics to standard output.
+  virtual void setStatistics(bool Statistics) = 0;
+
+  /// Verify the input DWARF.
+  virtual void setVerifyInputDWARF(bool Verify) = 0;
+
+  /// Do not unique types according to ODR.
+  virtual void setNoODR(bool NoODR) = 0;
+
+  /// Update index tables only(do not modify rest of DWARF).
+  virtual void setUpdateIndexTablesOnly(bool Update) = 0;
+
+  /// Allow generating valid, but non-deterministic output.
+  virtual void setAllowNonDeterministicOutput(bool) = 0;
+
+  /// Set whether to keep the enclosing function for a static variable.
+  virtual void setKeepFunctionForStatic(bool KeepFunctionForStatic) = 0;
+
+  /// Use specified number of threads for parallel files linking.
+  virtual void setNumThreads(unsigned NumThreads) = 0;
+
+  /// Add kind of accelerator tables to be generated.
+  virtual void addAccelTableKind(AccelTableKind Kind) = 0;
+
+  /// Set prepend path for clang modules.
+  virtual void setPrependPath(const std::string &Ppath) = 0;
+
+  /// Set estimated objects files amount, for preliminary data allocation.
+  virtual void setEstimatedObjfilesAmount(unsigned ObjFilesNum) = 0;
+
+  /// Set verification handler which would be used to report verification
+  /// errors.
+  virtual void
+  setInputVerificationHandler(InputVerificationHandlerTy Handler) = 0;
+
+  /// Set map for Swift interfaces.
+  virtual void setSwiftInterfacesMap(SwiftInterfacesMapTy *Map) = 0;
+
+  /// Set prefix map for objects.
+  virtual void setObjectPrefixMap(ObjectPrefixMapTy *Map) = 0;
+
+  /// Set target DWARF version.
+  virtual Error setTargetDWARFVersion(uint16_t TargetDWARFVersion) = 0;
+};
+
+} // end namespace dwarflinker
+} // end namespace llvm
+
+#endif // LLVM_DWARFLINKER_DWARFLINKERBASE_H
diff --git a/llvm/lib/DWARFLinkerParallel/IndexedValuesMap.h b/llvm/include/llvm/DWARFLinker/IndexedValuesMap.h
similarity index 76%
rename from llvm/lib/DWARFLinkerParallel/IndexedValuesMap.h
rename to llvm/include/llvm/DWARFLinker/IndexedValuesMap.h
index 0dc8de860a42e8..1d9424715e1af9 100644
--- a/llvm/lib/DWARFLinkerParallel/IndexedValuesMap.h
+++ b/llvm/include/llvm/DWARFLinker/IndexedValuesMap.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_LIB_DWARFLINKERPARALLEL_INDEXEDVALUESMAP_H
-#define LLVM_LIB_DWARFLINKERPARALLEL_INDEXEDVALUESMAP_H
+#ifndef LLVM_DWARFLINKER_INDEXEDVALUESMAP_H
+#define LLVM_DWARFLINKER_INDEXEDVALUESMAP_H
 
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallVector.h"
@@ -15,8 +15,9 @@
 #include <utility>
 
 namespace llvm {
-namespace dwarflinker_parallel {
+namespace dwarflinker {
 
+/// This class stores values sequentually and assigns index to the each value.
 template <typename T> class IndexedValuesMap {
 public:
   uint64_t getValueIndex(T Value) {
@@ -28,7 +29,7 @@ template <typename T> class IndexedValuesMap {
     return It->second;
   }
 
-  const SmallVector<T> &getValues() { return Values; }
+  const SmallVector<T> &getValues() const { return Values; }
 
   void clear() {
     ValueToIndexMap.clear();
@@ -43,7 +44,7 @@ template <typename T> class IndexedValuesMap {
   SmallVector<T> Values;
 };
 
-} // end of namespace dwarflinker_parallel
+} // end namespace dwarflinker
 } // end namespace llvm
 
-#endif // LLVM_LIB_DWARFLINKERPARALLEL_INDEXEDVALUESMAP_H
+#endif // LLVM_DWARFLINKERPARALLEL_INDEXEDVALUESMAP_H
diff --git a/llvm/include/llvm/DWARFLinker/LLVM/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/LLVM/DWARFLinker.h
new file mode 100644
index 00000000000000..38615d2fc73544
--- /dev/null
+++ b/llvm/include/llvm/DWARFLinker/LLVM/DWARFLinker.h
@@ -0,0 +1,191 @@
+//===- DWARFLinker.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 LLVM_DWARFLINKER_LLVM_DWARFLINKER_H
+#define LLVM_DWARFLINKER_LLVM_DWARFLINKER_H
+
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/DWARFLinker/DWARFFile.h"
+#include "llvm/DWARFLinker/DWARFLinkerBase.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/MC/MCDwarf.h"
+#include "llvm/TargetParser/Triple.h"
+
+/// ------------------------------------------------------------------
+/// The core of the Dwarf linking logic.
+///
+/// The generation of the dwarf information from the object files will be
+/// driven by the selection of 'root DIEs', which are DIEs that
+/// describe variables or functions that resolves to the corresponding
+/// code section(and thus have entries in the Addresses map). All the debug
+/// information that will be generated(the DIEs, but also the line
+/// tables, ranges, ...) is derived from that set of root DIEs.
+///
+/// The root DIEs are identified because they contain relocations that
+/// points to code section(the low_pc for a function, the location for
+/// a variable). These relocations are gathered as a very first step
+/// when we start processing a object file by AddressesMap.
+///
+/// The overall linking process looks like this:
+///
+/// parrallel_for_each(ObjectFile) {
+///   for_each (Compile Unit) {
+///     1. Load Clang modules.
+///   }
+///
+///   parrallel_for_each(Compile Unit) {
+///     1. Load input DWARF for Compile Unit.
+///     2. Report warnings for Clang modules.
+///     3. Analyze live DIEs and type names(if ODR deduplication is requested).
+///     4. Clone DIEs(Generate output DIEs and resulting DWARF tables).
+///        The result is in an OutDebugInfoBytes, which is an ELF file
+///        containing DWARF tables corresponding to the current compile unit.
+///     5. Cleanup Input and Output DIEs.
+///   }
+///
+///   Deallocate loaded Object file.
+/// }
+///
+/// if (ODR deduplication is requested)
+///   Generate an artificial compilation unit ("Type Table": used to partially
+///   generate DIEs at the clone stage).
+///
+/// for_each (ObjectFile) {
+///   for_each (Compile Unit) {
+///     1. Set offsets to Compile Units DWARF tables.
+///     2. Sort offsets/attributes/patches to have a predictable result.
+///     3. Patch size/offsets fields.
+///     4. Generate index tables.
+///     5. Move DWARF tables of compile units into the resulting file.
+///   }
+/// }
+///
+/// Every compile unit is processed separately, visited only once
+/// (except case inter-CU references exist), and used data is freed
+/// after the compile unit is processed. The resulting file is glued together
+/// from the generated debug tables which correspond to separate compile units.
+///
+/// Handling inter-CU references: inter-CU references are hard to process
+/// using only one pass. f.e. if CU1 references CU100 and CU100 references
+/// CU1, we could not finish handling of CU1 until we finished CU100.
+/// Thus we either need to load all CUs into the memory, either load CUs several
+/// times. This implementation loads inter-connected CU into memory at the first
+/// pass and processes them at the second pass.
+///
+/// ODR deduplication: Artificial compilation unit will be constructed to keep
+/// type dies. All types are moved into that compilation unit. Type's references
+/// are patched so that they point to the corresponding types from artificial
+/// compilation unit. All partial type definitions would be merged into single
+/// type definition.
+///
+
+namespace llvm {
+namespace dwarflinker {
+namespace dwarflinker_parallel {
+
+/// List of tracked debug tables.
+enum class DebugSectionKind : uint8_t {
+  DebugInfo = 0,
+  DebugLine,
+  DebugFrame,
+  DebugRange,
+  DebugRngLists,
+  DebugLoc,
+  DebugLocLists,
+  DebugARanges,
+  DebugAbbrev,
+  DebugMacinfo,
+  DebugMacro,
+  DebugAddr,
+  DebugStr,
+  DebugLineStr,
+  DebugStrOffsets,
+  DebugPubNames,
+  DebugPubTypes,
+  DebugNames,
+  AppleNames,
+  AppleNamespaces,
+  AppleObjC,
+  AppleTypes,
+  NumberOfEnumEntries // must be last
+};
+
+static constexpr size_t SectionKindsNum =
+    static_cast<size_t>(DebugSectionKind::NumberOfEnumEntries);
+
+static constexpr StringLiteral SectionNames[SectionKindsNum] = {
+    "debug_info",     "debug_line",     "debug_frame",       "debug_ranges",
+    "debug_rnglists", "debug_loc",      "debug_loclists",    "debug_aranges",
+    "debug_abbrev",   "debug_macinfo",  "debug_macro",       "debug_addr",
+    "debug_str",      "debug_line_str", "debug_str_offsets", "debug_pubnames",
+    "debug_pubtypes", "debug_names",    "apple_names",       "apple_namespac",
+    "apple_objc",     "apple_types"};
+
+/// Return the name of the section.
+static constexpr const StringLiteral &
+getSectionName(DebugSectionKind SectionKind) {
+  return SectionNames[static_cast<uint8_t>(SectionKind)];
+}
+
+/// Recognise the table name and match it with the DebugSectionKind.
+std::optional<DebugSectionKind> parseDebugTableName(StringRef Name);
+
+/// This structure keeps data of the concrete section.
+struct SectionDescriptorBase {
+  SectionDescriptorBase(DebugSectionKind SectionKind, dwarf::FormParams Format,
+                        llvm::endianness Endianess)
+      : SectionKind(SectionKind), Format(Format), Endianess(Endianess) {}
+  virtual ~SectionDescriptorBase() = default;
+
+  /// Returns section content.
+  virtual StringRef getContent() = 0;
+
+  /// Returns section kind.
+  DebugSectionKind getKind() { return SectionKind; }
+
+  /// Returns section name.
+  const StringLiteral &getName() const { return getSectionName(SectionKind); }
+
+  /// Returns endianess used by section.
+  llvm::endianness getEndianess() const { return Endianess; }
+
+  /// Returns FormParams used by section.
+  dwarf::FormParams getFormParams() const { return Format; }
+
+protected:
+  /// The section kind.
+  DebugSectionKind SectionKind = DebugSectionKind::NumberOfEnumEntries;
+
+  /// Output format.
+  dwarf::FormParams Format = {4, 4, dwarf::DWARF32};
+  llvm::endianness Endianess = llvm::endianness::little;
+};
+
+using SectionHandlerTy =
+    std::function<void(std::shared_ptr<SectionDescriptorBase> Section)>;
+
+class DWARFLinker : public DWARFLinkerBase {
+public:
+  virtual ~DWARFLinker() = default;
+
+  /// Creates dwarf linker instance.
+  static std::unique_ptr<DWARFLinker>
+  createLinker(MessageHandlerTy ErrorHandler, MessageHandlerTy WarningHandler,
+               TranslatorFuncTy StringsTranslator = nullptr);
+
+  /// Set output DWARF handler.
+  virtual void setOutputDWARFHandler(const Triple &TargetTriple,
+                                     SectionHandlerTy SectionHandler) = 0;
+};
+
+} // end namespace dwarflinker_parallel
+} // end namespace dwarflinker
+} // end namespace llvm
+
+#endif // LLVM_DWARFLINKER_LLVM_DWARFLINKER_H
diff --git a/llvm/include/llvm/DWARFLinkerParallel/StringPool.h b/llvm/include/llvm/DWARFLinker/StringPool.h
similarity index 90%
rename from llvm/include/llvm/DWARFLinkerParallel/StringPool.h
rename to llvm/include/llvm/DWARFLinker/StringPool.h
index e55909f343116d..8e307486420693 100644
--- a/llvm/include/llvm/DWARFLinkerParallel/StringPool.h
+++ b/llvm/include/llvm/DWARFLinker/StringPool.h
@@ -6,17 +6,16 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_DWARFLINKERPARALLEL_STRINGPOOL_H
-#define LLVM_DWARFLINKERPARALLEL_STRINGPOOL_H
+#ifndef LLVM_DWARFLINKER_STRINGPOOL_H
+#define LLVM_DWARFLINKER_STRINGPOOL_H
 
 #include "llvm/ADT/ConcurrentHashtable.h"
 #include "llvm/CodeGen/DwarfStringPoolEntry.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/PerThreadBumpPtrAllocator.h"
-#include <string_view>
 
 namespace llvm {
-namespace dwarflinker_parallel {
+namespace dwarflinker {
 
 /// StringEntry keeps data of the string: the length, external offset
 /// and a string body which is placed right after StringEntry.
@@ -46,6 +45,7 @@ class StringPoolEntryInfo {
   }
 };
 
+/// This class keeps strings. String values could be added asynchronously.
 class StringPool
     : public ConcurrentHashTableByPtr<StringRef, StringEntry,
                                       parallel::PerThreadBumpPtrAllocator,
@@ -69,7 +69,7 @@ class StringPool
   parallel::PerThreadBumpPtrAllocator Allocator;
 };
 
-} // end of namespace dwarflinker_parallel
+} // end namespace dwarflinker
 } // end namespace llvm
 
-#endif // LLVM_DWARFLINKERPARALLEL_STRINGPOOL_H
+#endif // LLVM_DWARFLINKER_STRINGPOOL_H
diff --git a/llvm/lib/DWARFLinkerParallel/Utils.h b/llvm/include/llvm/DWARFLinker/Utils.h
similarity index 51%
rename from llvm/lib/DWARFLinkerParallel/Utils.h
rename to llvm/include/llvm/DWARFLinker/Utils.h
index 91f9dca46a82b1..5b915ee1d6f39f 100644
--- a/llvm/lib/DWARFLinkerParallel/Utils.h
+++ b/llvm/include/llvm/DWARFLinker/Utils.h
@@ -6,13 +6,17 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_LIB_DWARFLINKERPARALLEL_UTILS_H
-#define LLVM_LIB_DWARFLINKERPARALLEL_UTILS_H
+#ifndef LLVM_DWARFLINKER_UTILS_H
+#define LLVM_DWARFLINKER_UTILS_H
 
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Twine.h"
 #include "llvm/Support/Error.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
 
 namespace llvm {
-namespace dwarflinker_parallel {
+namespace dwarflinker {
 
 /// This function calls \p Iteration() until it returns false.
 /// If number of iterations exceeds \p MaxCounter then an Error is returned.
@@ -34,7 +38,29 @@ inline Error finiteLoop(function_ref<Expected<bool>()> Iteration,
   return createStringError(std::errc::invalid_argument, "Infinite recursion");
 }
 
-} // end of namespace dwarflinker_parallel
+/// Make a best effort to guess the
+/// Xcode.app/Contents/Developer/Toolchains/ path from an SDK path.
+inline SmallString<128> guessToolchainBaseDir(StringRef SysRoot) {
+  SmallString<128> Result;
+  // Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk
+  StringRef Base = sys::path::parent_path(SysRoot);
+  if (sys::path::filename(Base) != "SDKs")
+    return Result;
+  Base = sys::path::parent_path(Base);
+  Result = Base;
+  Result += "/Toolchains";
+  return Result;
+}
+
+inline bool isPathAbsoluteOnWindowsOrPosix(const Twine &Path) {
+  // Debug info can contain paths from any OS, not necessarily
+  // an OS we're currently running on. Moreover different compilation units can
+  // be compiled on different operating systems and linked together later.
+  return sys::path::is_absolute(Path, sys::path::Style::posix) ||
+         sys::path::is_absolute(Path, sys::path::Style::windows);
+}
+
+} // end namespace dwarflinker
 } // end namespace llvm
 
-#endif // LLVM_LIB_DWARFLINKERPARALLEL_UTILS_H
+#endif // LLVM_DWARFLINKER_UTILS_H
diff --git a/llvm/include/llvm/DWARFLinkerParallel/DWARFLinker.h b/llvm/include/llvm/DWARFLinkerParallel/DWARFLinker.h
deleted file mode 100644
index c16c94d65c2fe6..00000000000000
--- a/llvm/include/llvm/DWARFLinkerParallel/DWARFLinker.h
+++ /dev/null
@@ -1,223 +0,0 @@
-//===- DWARFLinker.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 LLVM_DWARFLINKERPARALLEL_DWARFLINKER_H
-#define LLVM_DWARFLINKERPARALLEL_DWARFLINKER_H
-
-#include "llvm/CodeGen/AsmPrinter.h"
-#include "llvm/DWARFLinkerParallel/DWARFFile.h"
-#include "llvm/DebugInfo/DWARF/DWARFContext.h"
-#include "llvm/DebugInfo/DWARF/DWARFDie.h"
-#include "llvm/MC/MCDwarf.h"
-#include "llvm/TargetParser/Triple.h"
-
-/// ------------------------------------------------------------------
-/// The core of the Dwarf linking logic.
-///
-/// The generation of the dwarf information from the object files will be
-/// driven by the selection of 'root DIEs', which are DIEs that
-/// describe variables or functions that resolves to the corresponding
-/// code section(and thus have entries in the Addresses map). All the debug
-/// information that will be generated(the DIEs, but also the line
-/// tables, ranges, ...) is derived from that set of root DIEs.
-///
-/// The root DIEs are identified because they contain relocations that
-/// points to code section(the low_pc for a function, the location for
-/// a variable). These relocations are gathered as a very first step
-/// when we start processing a object file by AddressesMap.
-///
-/// The overall linking process looks like this:
-///
-/// parrallel_for_each(ObjectFile) {
-///   for_each (Compile Unit) {
-///     1. Load Clang modules.
-///   }
-///
-///   parrallel_for_each(Compile Unit) {
-///     1. Load input DWARF for Compile Unit.
-///     2. Report warnings for Clang modules.
-///     3. Analyze live DIEs and type names(if ODR deduplication is requested).
-///     4. Clone DIEs(Generate output DIEs and resulting DWARF tables).
-///        The result is in an OutDebugInfoBytes, which is an ELF file
-///        containing DWARF tables corresponding to the current compile unit.
-///     5. Cleanup Input and Output DIEs.
-///   }
-///
-///   Deallocate loaded Object file.
-/// }
-///
-/// if (ODR deduplication is requested)
-///   Generate an artificial compilation unit ("Type Table": used to partially
-///   generate DIEs at the clone stage).
-///
-/// for_each (ObjectFile) {
-///   for_each (Compile Unit) {
-///     1. Set offsets to Compile Units DWARF tables.
-///     2. Sort offsets/attributes/patches to have a predictable result.
-///     3. Patch size/offsets fields.
-///     4. Generate index tables.
-///     5. Move DWARF tables of compile units into the resulting file.
-///   }
-/// }
-///
-/// Every compile unit is processed separately, visited only once
-/// (except case inter-CU references exist), and used data is freed
-/// after the compile unit is processed. The resulting file is glued together
-/// from the generated debug tables which correspond to separate compile units.
-///
-/// Handling inter-CU references: inter-CU references are hard to process
-/// using only one pass. f.e. if CU1 references CU100 and CU100 references
-/// CU1, we could not finish handling of CU1 until we finished CU100.
-/// Thus we either need to load all CUs into the memory, either load CUs several
-/// times. This implementation loads inter-connected CU into memory at the first
-/// pass and processes them at the second pass.
-///
-/// ODR deduplication: Artificial compilation unit will be constructed to keep
-/// type dies. All types are moved into that compilation unit. Type's references
-/// are patched so that they point to the corresponding types from artificial
-/// compilation unit. All partial type definitions would be merged into single
-/// type definition.
-///
-
-namespace llvm {
-namespace dwarflinker_parallel {
-
-/// ExtraDwarfEmitter allows adding extra data to the DWARFLinker output.
-/// The finish() method should be called after all extra data are emitted.
-class ExtraDwarfEmitter {
-public:
-  virtual ~ExtraDwarfEmitter() = default;
-
-  /// Dump the file to the disk.
-  virtual void finish() = 0;
-
-  /// Emit section named SecName with data SecData.
-  virtual void emitSectionContents(StringRef SecData, StringRef SecName) = 0;
-
-  /// Emit the swift_ast section stored in \p Buffer.
-  virtual void emitSwiftAST(StringRef Buffer) = 0;
-
-  /// Emit the swift reflection section stored in \p Buffer.
-  virtual void emitSwiftReflectionSection(
-      llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind,
-      StringRef Buffer, uint32_t Alignment, uint32_t Size) = 0;
-
-  /// Returns underlying AsmPrinter.
-  virtual AsmPrinter &getAsmPrinter() const = 0;
-};
-
-class DWARFLinker {
-public:
-  /// Type of output file.
-  enum class OutputFileType {
-    Object,
-    Assembly,
-  };
-
-  /// The kind of accelerator tables we should emit.
-  enum class AccelTableKind : uint8_t {
-    Apple,     ///< .apple_names, .apple_namespaces, .apple_types, .apple_objc.
-    Pub,       ///< .debug_pubnames, .debug_pubtypes
-    DebugNames ///< .debug_names.
-  };
-
-  using MessageHandlerTy = std::function<void(
-      const Twine &Warning, StringRef Context, const DWARFDie *DIE)>;
-  using ObjFileLoaderTy = std::function<ErrorOr<DWARFFile &>(
-      StringRef ContainerName, StringRef Path)>;
-  using InputVerificationHandlerTy = std::function<void(const DWARFFile &File, llvm::StringRef Output)>;
-  using ObjectPrefixMapTy = std::map<std::string, std::string>;
-  using CompileUnitHandlerTy = function_ref<void(const DWARFUnit &Unit)>;
-  using TranslatorFuncTy = std::function<StringRef(StringRef)>;
-  using SwiftInterfacesMapTy = std::map<std::string, std::string>;
-
-  virtual ~DWARFLinker() = default;
-
-  /// Creates dwarf linker instance.
-  static std::unique_ptr<DWARFLinker>
-  createLinker(MessageHandlerTy ErrorHandler, MessageHandlerTy WarningHandler,
-               TranslatorFuncTy StringsTranslator = nullptr);
-
-  /// Creates emitter for output dwarf.
-  virtual Error createEmitter(const Triple &TheTriple, OutputFileType FileType,
-                              raw_pwrite_stream &OutFile) = 0;
-
-  /// Returns previously created dwarf emitter. May be nullptr.
-  virtual ExtraDwarfEmitter *getEmitter() = 0;
-
-  /// Add object file to be linked. Pre-load compile unit die. Call
-  /// \p OnCUDieLoaded for each compile unit die. If specified \p File
-  /// has reference to the Clang module then such module would be
-  /// pre-loaded by \p Loader for !Update case.
-  ///
-  /// \pre NoODR, Update options should be set before call to addObjectFile.
-  virtual void addObjectFile(
-      DWARFFile &File, ObjFileLoaderTy Loader = nullptr,
-      CompileUnitHandlerTy OnCUDieLoaded = [](const DWARFUnit &) {}) = 0;
-
-  /// Link debug info for added files.
-  virtual Error link() = 0;
-
-  /// \defgroup Methods setting various linking options:
-  ///
-  /// @{
-
-  /// Allows to generate log of linking process to the standard output.
-  virtual void setVerbosity(bool Verbose) = 0;
-
-  /// Print statistics to standard output.
-  virtual void setStatistics(bool Statistics) = 0;
-
-  /// Verify the input DWARF.
-  virtual void setVerifyInputDWARF(bool Verify) = 0;
-
-  /// Do not unique types according to ODR.
-  virtual void setNoODR(bool NoODR) = 0;
-
-  /// Update index tables only(do not modify rest of DWARF).
-  virtual void setUpdateIndexTablesOnly(bool UpdateIndexTablesOnly) = 0;
-
-  /// Allow generating valid, but non-deterministic output.
-  virtual void
-  setAllowNonDeterministicOutput(bool AllowNonDeterministicOutput) = 0;
-
-  /// Set to keep the enclosing function for a static variable.
-  virtual void setKeepFunctionForStatic(bool KeepFunctionForStatic) = 0;
-
-  /// Use specified number of threads for parallel files linking.
-  virtual void setNumThreads(unsigned NumThreads) = 0;
-
-  /// Add kind of accelerator tables to be generated.
-  virtual void addAccelTableKind(AccelTableKind Kind) = 0;
-
-  /// Set prepend path for clang modules.
-  virtual void setPrependPath(const std::string &Ppath) = 0;
-
-  /// Set estimated objects files amount, for preliminary data allocation.
-  virtual void setEstimatedObjfilesAmount(unsigned ObjFilesNum) = 0;
-
-  /// Set verification handler which would be used to report verification
-  /// errors.
-  virtual void
-  setInputVerificationHandler(InputVerificationHandlerTy Handler) = 0;
-
-  /// Set map for Swift interfaces.
-  virtual void setSwiftInterfacesMap(SwiftInterfacesMapTy *Map) = 0;
-
-  /// Set prefix map for objects.
-  virtual void setObjectPrefixMap(ObjectPrefixMapTy *Map) = 0;
-
-  /// Set target DWARF version.
-  virtual Error setTargetDWARFVersion(uint16_t TargetDWARFVersion) = 0;
-  /// @}
-};
-
-} // end namespace dwarflinker_parallel
-} // end namespace llvm
-
-#endif // LLVM_DWARFLINKERPARALLEL_DWARFLINKER_H
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h
index 6b1b2ae6d7e049..3fc9b05e6d0a6e 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h
@@ -18,11 +18,14 @@
 namespace llvm {
 
 class raw_ostream;
+
+namespace dwarflinker {
 class DwarfStreamer;
+}
 
 class DWARFDebugMacro {
-  friend DwarfStreamer;
-  friend dwarflinker_parallel::CompileUnit;
+  friend dwarflinker::DwarfStreamer;
+  friend dwarflinker::dwarflinker_parallel::CompileUnit;
 
   /// DWARFv5 section 6.3.1 Macro Information Header.
   enum HeaderFlagMask {
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h
index 7084081ce61a43..286b67a82d68a4 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h
@@ -43,9 +43,11 @@ class DWARFObject;
 class raw_ostream;
 struct DIDumpOptions;
 struct DWARFSection;
+namespace dwarflinker {
 namespace dwarflinker_parallel {
 class CompileUnit;
 }
+} // namespace dwarflinker
 
 /// Base class describing the header of any kind of "unit."  Some information
 /// is specific to certain unit types.  We separate this class out so we can
@@ -256,7 +258,7 @@ class DWARFUnit {
   std::shared_ptr<DWARFUnit> DWO;
 
 protected:
-  friend dwarflinker_parallel::CompileUnit;
+  friend dwarflinker::dwarflinker_parallel::CompileUnit;
 
   /// Return the index of a \p Die entry inside the unit's DIE vector.
   ///
diff --git a/llvm/lib/CMakeLists.txt b/llvm/lib/CMakeLists.txt
index 283baa6090eb9a..ea22ff21820a98 100644
--- a/llvm/lib/CMakeLists.txt
+++ b/llvm/lib/CMakeLists.txt
@@ -14,7 +14,6 @@ add_subdirectory(BinaryFormat)
 add_subdirectory(Bitcode)
 add_subdirectory(Bitstream)
 add_subdirectory(DWARFLinker)
-add_subdirectory(DWARFLinkerParallel)
 add_subdirectory(Extensions)
 add_subdirectory(Frontend)
 add_subdirectory(Transforms)
diff --git a/llvm/lib/DWARFLinker/Apple/CMakeLists.txt b/llvm/lib/DWARFLinker/Apple/CMakeLists.txt
new file mode 100644
index 00000000000000..b173d42eb01539
--- /dev/null
+++ b/llvm/lib/DWARFLinker/Apple/CMakeLists.txt
@@ -0,0 +1,24 @@
+add_llvm_component_library(LLVMDWARFLinker
+  DWARFLinkerCompileUnit.cpp
+  DWARFLinkerDeclContext.cpp
+  DWARFLinker.cpp
+  DWARFStreamer.cpp
+
+  ADDITIONAL_HEADER_DIRS
+  ${LLVM_MAIN_INCLUDE_DIR}/llvm/DWARFLinker
+
+  DEPENDS
+  intrinsics_gen
+
+  LINK_COMPONENTS
+  AsmPrinter
+  BinaryFormat
+  CodeGen
+  CodeGenTypes
+  DebugInfoDWARF
+  DWARFLinkerBase
+  MC
+  Object
+  Support
+  TargetParser
+  )
diff --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/Apple/DWARFLinker.cpp
similarity index 94%
rename from llvm/lib/DWARFLinker/DWARFLinker.cpp
rename to llvm/lib/DWARFLinker/Apple/DWARFLinker.cpp
index 1a7ea47adc5ca3..6ad873804dd763 100644
--- a/llvm/lib/DWARFLinker/DWARFLinker.cpp
+++ b/llvm/lib/DWARFLinker/Apple/DWARFLinker.cpp
@@ -6,14 +6,15 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/DWARFLinker/DWARFLinker.h"
+#include "llvm/DWARFLinker/Apple/DWARFLinker.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/CodeGen/NonRelocatableStringpool.h"
-#include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
-#include "llvm/DWARFLinker/DWARFStreamer.h"
+#include "llvm/DWARFLinker/Apple/DWARFLinkerDeclContext.h"
+#include "llvm/DWARFLinker/Apple/DWARFStreamer.h"
+#include "llvm/DWARFLinker/Utils.h"
 #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
 #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
@@ -37,7 +38,8 @@
 #include "llvm/Support/ThreadPool.h"
 #include <vector>
 
-namespace llvm {
+using namespace llvm;
+using namespace dwarflinker;
 
 /// Hold the input and output of the debug info size in bytes.
 struct DebugInfoSize {
@@ -137,10 +139,6 @@ static bool isTypeTag(uint16_t Tag) {
   return false;
 }
 
-AddressesMap::~AddressesMap() = default;
-
-DwarfEmitter::~DwarfEmitter() = default;
-
 bool DWARFLinker::DIECloner::getDIENames(const DWARFDie &Die,
                                          AttributesInfo &Info,
                                          OffsetsStringPool &StringPool,
@@ -177,25 +175,11 @@ static void resolveRelativeObjectPath(SmallVectorImpl<char> &Buf, DWARFDie CU) {
   sys::path::append(Buf, dwarf::toString(CU.find(dwarf::DW_AT_comp_dir), ""));
 }
 
-/// Make a best effort to guess the
-/// Xcode.app/Contents/Developer/Toolchains/ path from an SDK path.
-static SmallString<128> guessToolchainBaseDir(StringRef SysRoot) {
-  SmallString<128> Result;
-  // Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk
-  StringRef Base = sys::path::parent_path(SysRoot);
-  if (sys::path::filename(Base) != "SDKs")
-    return Result;
-  Base = sys::path::parent_path(Base);
-  Result = Base;
-  Result += "/Toolchains";
-  return Result;
-}
-
 /// Collect references to parseable Swift interfaces in imported
 /// DW_TAG_module blocks.
 static void analyzeImportedModule(
     const DWARFDie &DIE, CompileUnit &CU,
-    swiftInterfacesMap *ParseableSwiftInterfaces,
+    DWARFLinkerBase::SwiftInterfacesMapTy *ParseableSwiftInterfaces,
     std::function<void(const Twine &, const DWARFDie &)> ReportWarning) {
   if (CU.getLanguage() != dwarf::DW_LANG_Swift)
     return;
@@ -307,7 +291,8 @@ static void updateChildPruning(const DWARFDie &Die, CompileUnit &CU,
 static void analyzeContextInfo(
     const DWARFDie &DIE, unsigned ParentIdx, CompileUnit &CU,
     DeclContext *CurrentDeclContext, DeclContextTree &Contexts,
-    uint64_t ModulesEndOffset, swiftInterfacesMap *ParseableSwiftInterfaces,
+    uint64_t ModulesEndOffset,
+    DWARFLinkerBase::SwiftInterfacesMapTy *ParseableSwiftInterfaces,
     std::function<void(const Twine &, const DWARFDie &)> ReportWarning) {
   // LIFO work list.
   std::vector<ContextWorklistItem> Worklist;
@@ -1357,9 +1342,9 @@ unsigned DWARFLinker::DIECloner::cloneAddressAttribute(
   //     independently by the linker).
   //   - If address relocated in an inline_subprogram that happens at the
   //     beginning of its inlining function.
-  //  To avoid above cases and to not apply relocation twice (in applyValidRelocs
-  //  and here), read address attribute from InputDIE and apply Info.PCOffset
-  //  here.
+  //  To avoid above cases and to not apply relocation twice (in
+  //  applyValidRelocs and here), read address attribute from InputDIE and apply
+  //  Info.PCOffset here.
 
   std::optional<DWARFFormValue> AddrAttribute = InputDIE.find(AttrSpec.Attr);
   if (!AddrAttribute)
@@ -1906,8 +1891,9 @@ DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
 /// Patch the input object file relevant debug_ranges or debug_rnglists
 /// entries and emit them in the output file. Update the relevant attributes
 /// to point at the new entries.
-void DWARFLinker::generateUnitRanges(CompileUnit &Unit, const DWARFFile &File,
-                                     DebugDieValuePool &AddrPool) const {
+void DWARFLinker::generateUnitRanges(
+    CompileUnit &Unit, const DWARFFile &File,
+    IndexedValuesMap<uint64_t> &AddrPool) const {
   if (LLVM_UNLIKELY(Options.Update))
     return;
 
@@ -1921,7 +1907,7 @@ void DWARFLinker::generateUnitRanges(CompileUnit &Unit, const DWARFFile &File,
 
   // Emit LinkedFunctionRanges into .debug_aranges
   if (!LinkedFunctionRanges.empty())
-    TheDwarfEmitter->emitDwarfDebugArangesTable(Unit, LinkedFunctionRanges);
+    OutDwarfStreamer->emitDwarfDebugArangesTable(Unit, LinkedFunctionRanges);
 
   RngListAttributesTy AllRngListAttributes = Unit.getRangesAttributes();
   std::optional<PatchLocation> UnitRngListAttribute =
@@ -1929,7 +1915,7 @@ void DWARFLinker::generateUnitRanges(CompileUnit &Unit, const DWARFFile &File,
 
   if (!AllRngListAttributes.empty() || UnitRngListAttribute) {
     std::optional<AddressRangeValuePair> CachedRange;
-    MCSymbol *EndLabel = TheDwarfEmitter->emitDwarfDebugRangeListHeader(Unit);
+    MCSymbol *EndLabel = OutDwarfStreamer->emitDwarfDebugRangeListHeader(Unit);
 
     // Read original address ranges, apply relocation value, emit linked address
     // ranges.
@@ -1960,17 +1946,17 @@ void DWARFLinker::generateUnitRanges(CompileUnit &Unit, const DWARFFile &File,
       }
 
       // Emit linked ranges.
-      TheDwarfEmitter->emitDwarfDebugRangeListFragment(
+      OutDwarfStreamer->emitDwarfDebugRangeListFragment(
           Unit, LinkedRanges, AttributePatch, AddrPool);
     }
 
     // Emit ranges for Unit AT_ranges attribute.
     if (UnitRngListAttribute.has_value())
-      TheDwarfEmitter->emitDwarfDebugRangeListFragment(
+      OutDwarfStreamer->emitDwarfDebugRangeListFragment(
           Unit, LinkedFunctionRanges, *UnitRngListAttribute, AddrPool);
 
     // Emit ranges footer.
-    TheDwarfEmitter->emitDwarfDebugRangeListFooter(Unit, EndLabel);
+    OutDwarfStreamer->emitDwarfDebugRangeListFooter(Unit, EndLabel);
   }
 }
 
@@ -1987,7 +1973,7 @@ void DWARFLinker::DIECloner::generateUnitLocations(
     return;
 
   // Emit locations list table header.
-  MCSymbol *EndLabel = Emitter->emitDwarfDebugLocListHeader(Unit);
+  MCSymbol *EndLabel = Streamer->emitDwarfDebugLocListHeader(Unit);
 
   for (auto &CurLocAttr : AllLocListAttributes) {
     // Get location expressions vector corresponding to the current attribute
@@ -2021,12 +2007,12 @@ void DWARFLinker::DIECloner::generateUnitLocations(
     }
 
     // Emit locations list table fragment corresponding to the CurLocAttr.
-    Emitter->emitDwarfDebugLocListFragment(Unit, LinkedLocationExpressions,
-                                           CurLocAttr, AddrPool);
+    Streamer->emitDwarfDebugLocListFragment(Unit, LinkedLocationExpressions,
+                                            CurLocAttr, AddrPool);
   }
 
   // Emit locations list table footer.
-  Emitter->emitDwarfDebugLocListFooter(Unit, EndLabel);
+  Streamer->emitDwarfDebugLocListFooter(Unit, EndLabel);
 }
 
 static void patchAddrBase(DIE &Die, DIEInteger Offset) {
@@ -2040,8 +2026,7 @@ static void patchAddrBase(DIE &Die, DIEInteger Offset) {
 }
 
 void DWARFLinker::DIECloner::emitDebugAddrSection(
-    CompileUnit &Unit,
-    const uint16_t DwarfVersion) const {
+    CompileUnit &Unit, const uint16_t DwarfVersion) const {
 
   if (LLVM_UNLIKELY(Linker.Options.Update))
     return;
@@ -2049,15 +2034,15 @@ void DWARFLinker::DIECloner::emitDebugAddrSection(
   if (DwarfVersion < 5)
     return;
 
-  if (AddrPool.DieValues.empty())
+  if (AddrPool.getValues().empty())
     return;
 
-  MCSymbol *EndLabel = Emitter->emitDwarfDebugAddrsHeader(Unit);
+  MCSymbol *EndLabel = Streamer->emitDwarfDebugAddrsHeader(Unit);
   patchAddrBase(*Unit.getOutputUnitDIE(),
-                DIEInteger(Emitter->getDebugAddrSectionSize()));
-  Emitter->emitDwarfDebugAddrs(AddrPool.DieValues,
-                               Unit.getOrigUnit().getAddressByteSize());
-  Emitter->emitDwarfDebugAddrsFooter(Unit, EndLabel);
+                DIEInteger(Streamer->getDebugAddrSectionSize()));
+  Streamer->emitDwarfDebugAddrs(AddrPool.getValues(),
+                                Unit.getOrigUnit().getAddressByteSize());
+  Streamer->emitDwarfDebugAddrsFooter(Unit, EndLabel);
 }
 
 /// Insert the new line info sequence \p Seq into the current
@@ -2120,7 +2105,7 @@ void DWARFLinker::DIECloner::rememberUnitForMacroOffset(CompileUnit &Unit) {
 }
 
 void DWARFLinker::DIECloner::generateLineTableForUnit(CompileUnit &Unit) {
-  if (LLVM_UNLIKELY(Emitter == nullptr))
+  if (LLVM_UNLIKELY(Streamer == nullptr))
     return;
 
   // Check whether DW_AT_stmt_list attribute is presented.
@@ -2131,7 +2116,7 @@ void DWARFLinker::DIECloner::generateLineTableForUnit(CompileUnit &Unit) {
 
   // Update the cloned DW_AT_stmt_list with the correct debug_line offset.
   if (auto *OutputDIE = Unit.getOutputUnitDIE())
-    patchStmtList(*OutputDIE, DIEInteger(Emitter->getLineSectionSize()));
+    patchStmtList(*OutputDIE, DIEInteger(Streamer->getLineSectionSize()));
 
   if (const DWARFDebugLine::LineTable *LT =
           ObjFile.Dwarf->getLineTableForUnit(&Unit.getOrigUnit())) {
@@ -2217,8 +2202,8 @@ void DWARFLinker::DIECloner::generateLineTableForUnit(CompileUnit &Unit) {
       LineTable.Rows = std::move(NewRows);
     }
 
-    Emitter->emitLineTableForUnit(LineTable, Unit, DebugStrPool,
-                                  DebugLineStrPool);
+    Streamer->emitLineTableForUnit(LineTable, Unit, DebugStrPool,
+                                   DebugLineStrPool);
   } else
     Linker.reportWarning("Cann't load line table.", ObjFile);
 }
@@ -2249,8 +2234,8 @@ void DWARFLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) {
                           ObjC.Die->getOffset() + Unit.getStartOffset());
     } break;
     case AccelTableKind::Pub: {
-      TheDwarfEmitter->emitPubNamesForUnit(Unit);
-      TheDwarfEmitter->emitPubTypesForUnit(Unit);
+      OutDwarfStreamer->emitPubNamesForUnit(Unit);
+      OutDwarfStreamer->emitPubTypesForUnit(Unit);
     } break;
     case AccelTableKind::DebugNames: {
       for (const auto &Namespace : Unit.getNamespaces())
@@ -2334,21 +2319,21 @@ void DWARFLinker::patchFrameInfoForObject(LinkContext &Context) {
     // Look if we already emitted a CIE that corresponds to the
     // referenced one (the CIE data is the key of that lookup).
     auto IteratorInserted = EmittedCIEs.insert(
-        std::make_pair(CIEData, TheDwarfEmitter->getFrameSectionSize()));
+        std::make_pair(CIEData, OutDwarfStreamer->getFrameSectionSize()));
     // If there is no CIE yet for this ID, emit it.
     if (IteratorInserted.second) {
-      LastCIEOffset = TheDwarfEmitter->getFrameSectionSize();
+      LastCIEOffset = OutDwarfStreamer->getFrameSectionSize();
       IteratorInserted.first->getValue() = LastCIEOffset;
-      TheDwarfEmitter->emitCIE(CIEData);
+      OutDwarfStreamer->emitCIE(CIEData);
     }
 
     // Emit the FDE with updated address and CIE pointer.
     // (4 + AddrSize) is the size of the CIEId + initial_location
     // fields that will get reconstructed by emitFDE().
     unsigned FDERemainingBytes = InitialLength - (4 + SrcAddrSize);
-    TheDwarfEmitter->emitFDE(IteratorInserted.first->getValue(), SrcAddrSize,
-                             Loc + Range->Value,
-                             FrameData.substr(InputOffset, FDERemainingBytes));
+    OutDwarfStreamer->emitFDE(IteratorInserted.first->getValue(), SrcAddrSize,
+                              Loc + Range->Value,
+                              FrameData.substr(InputOffset, FDERemainingBytes));
     InputOffset += FDERemainingBytes;
   }
 }
@@ -2407,8 +2392,9 @@ static uint64_t getDwoId(const DWARFDie &CUDie) {
   return 0;
 }
 
-static std::string remapPath(StringRef Path,
-                             const objectPrefixMap &ObjectPrefixMap) {
+static std::string
+remapPath(StringRef Path,
+          const DWARFLinkerBase::ObjectPrefixMapTy &ObjectPrefixMap) {
   if (ObjectPrefixMap.empty())
     return Path.str();
 
@@ -2419,8 +2405,9 @@ static std::string remapPath(StringRef Path,
   return p.str().str();
 }
 
-static std::string getPCMFile(const DWARFDie &CUDie,
-                              objectPrefixMap *ObjectPrefixMap) {
+static std::string
+getPCMFile(const DWARFDie &CUDie,
+           DWARFLinkerBase::ObjectPrefixMapTy *ObjectPrefixMap) {
   std::string PCMFile = dwarf::toString(
       CUDie.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), "");
 
@@ -2477,8 +2464,8 @@ std::pair<bool, bool> DWARFLinker::isClangModuleRef(const DWARFDie &CUDie,
 
 bool DWARFLinker::registerModuleReference(const DWARFDie &CUDie,
                                           LinkContext &Context,
-                                          objFileLoader Loader,
-                                          CompileUnitHandler OnCUDieLoaded,
+                                          ObjFileLoaderTy Loader,
+                                          CompileUnitHandlerTy OnCUDieLoaded,
                                           unsigned Indent) {
   std::string PCMFile = getPCMFile(CUDie, Options.ObjectPrefixMap);
   std::pair<bool, bool> IsClangModuleRef =
@@ -2505,11 +2492,9 @@ bool DWARFLinker::registerModuleReference(const DWARFDie &CUDie,
   return true;
 }
 
-Error DWARFLinker::loadClangModule(objFileLoader Loader, const DWARFDie &CUDie,
-                                   const std::string &PCMFile,
-                                   LinkContext &Context,
-                                   CompileUnitHandler OnCUDieLoaded,
-                                   unsigned Indent) {
+Error DWARFLinker::loadClangModule(
+    ObjFileLoaderTy Loader, const DWARFDie &CUDie, const std::string &PCMFile,
+    LinkContext &Context, CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) {
 
   uint64_t DwoId = getDwoId(CUDie);
   std::string ModuleName = dwarf::toString(CUDie.find(dwarf::DW_AT_name), "");
@@ -2578,7 +2563,7 @@ Error DWARFLinker::loadClangModule(objFileLoader Loader, const DWARFDie &CUDie,
 uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits(
     DWARFContext &DwarfContext, const DWARFFile &File, bool IsLittleEndian) {
   uint64_t OutputDebugInfoSize =
-      (Emitter == nullptr) ? 0 : Emitter->getDebugInfoSectionSize();
+      (Streamer == nullptr) ? 0 : Streamer->getDebugInfoSectionSize();
   const uint64_t StartOutputDebugInfoSize = OutputDebugInfoSize;
 
   for (auto &CurrentUnit : CompileUnits) {
@@ -2601,7 +2586,7 @@ uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits(
 
     OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion);
 
-    if (Emitter != nullptr) {
+    if (Streamer != nullptr) {
 
       generateLineTableForUnit(*CurrentUnit);
 
@@ -2630,10 +2615,10 @@ uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits(
     AddrPool.clear();
   }
 
-  if (Emitter != nullptr) {
-    assert(Emitter);
+  if (Streamer != nullptr) {
+    assert(Streamer);
     // Emit macro tables.
-    Emitter->emitMacroTables(File.Dwarf.get(), UnitMacroMap, DebugStrPool);
+    Streamer->emitMacroTables(File.Dwarf.get(), UnitMacroMap, DebugStrPool);
 
     // Emit all the compile unit's debug information.
     for (auto &CurrentUnit : CompileUnits) {
@@ -2644,11 +2629,11 @@ uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits(
 
       unsigned DwarfVersion = CurrentUnit->getOrigUnit().getVersion();
 
-      assert(Emitter->getDebugInfoSectionSize() ==
+      assert(Streamer->getDebugInfoSectionSize() ==
              CurrentUnit->getStartOffset());
-      Emitter->emitCompileUnitHeader(*CurrentUnit, DwarfVersion);
-      Emitter->emitDIE(*CurrentUnit->getOutputUnitDIE());
-      assert(Emitter->getDebugInfoSectionSize() ==
+      Streamer->emitCompileUnitHeader(*CurrentUnit, DwarfVersion);
+      Streamer->emitDIE(*CurrentUnit->getOutputUnitDIE());
+      assert(Streamer->getDebugInfoSectionSize() ==
              CurrentUnit->computeNextUnitOffset(DwarfVersion));
     }
   }
@@ -2657,24 +2642,24 @@ uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits(
 }
 
 void DWARFLinker::copyInvariantDebugSection(DWARFContext &Dwarf) {
-  TheDwarfEmitter->emitSectionContents(Dwarf.getDWARFObj().getLocSection().Data,
-                                       "debug_loc");
-  TheDwarfEmitter->emitSectionContents(
+  OutDwarfStreamer->emitSectionContents(
+      Dwarf.getDWARFObj().getLocSection().Data, "debug_loc");
+  OutDwarfStreamer->emitSectionContents(
       Dwarf.getDWARFObj().getRangesSection().Data, "debug_ranges");
-  TheDwarfEmitter->emitSectionContents(
+  OutDwarfStreamer->emitSectionContents(
       Dwarf.getDWARFObj().getFrameSection().Data, "debug_frame");
-  TheDwarfEmitter->emitSectionContents(Dwarf.getDWARFObj().getArangesSection(),
-                                       "debug_aranges");
-  TheDwarfEmitter->emitSectionContents(
+  OutDwarfStreamer->emitSectionContents(Dwarf.getDWARFObj().getArangesSection(),
+                                        "debug_aranges");
+  OutDwarfStreamer->emitSectionContents(
       Dwarf.getDWARFObj().getAddrSection().Data, "debug_addr");
-  TheDwarfEmitter->emitSectionContents(
+  OutDwarfStreamer->emitSectionContents(
       Dwarf.getDWARFObj().getRnglistsSection().Data, "debug_rnglists");
-  TheDwarfEmitter->emitSectionContents(
+  OutDwarfStreamer->emitSectionContents(
       Dwarf.getDWARFObj().getLoclistsSection().Data, "debug_loclists");
 }
 
-void DWARFLinker::addObjectFile(DWARFFile &File, objFileLoader Loader,
-                                CompileUnitHandler OnCUDieLoaded) {
+void DWARFLinker::addObjectFile(DWARFFile &File, ObjFileLoaderTy Loader,
+                                CompileUnitHandlerTy OnCUDieLoaded) {
   ObjectContexts.emplace_back(LinkContext(File));
 
   if (ObjectContexts.back().File.Dwarf) {
@@ -2707,18 +2692,14 @@ Error DWARFLinker::link() {
   // reproducibility.
   OffsetsStringPool DebugStrPool(StringsTranslator, true);
   OffsetsStringPool DebugLineStrPool(StringsTranslator, false);
-  DebugDieValuePool StringOffsetPool;
+  IndexedValuesMap<uint64_t> StringOffsetPool;
 
   // ODR Contexts for the optimize.
   DeclContextTree ODRContexts;
 
   for (LinkContext &OptContext : ObjectContexts) {
-    if (Options.Verbose) {
-      if (DwarfLinkerClientID == DwarfLinkerClient::Dsymutil)
-        outs() << "DEBUG MAP OBJECT: " << OptContext.File.FileName << "\n";
-      else
-        outs() << "OBJECT FILE: " << OptContext.File.FileName << "\n";
-    }
+    if (Options.Verbose)
+      outs() << "DEBUG MAP OBJECT: " << OptContext.File.FileName << "\n";
 
     if (!OptContext.File.Dwarf)
       continue;
@@ -2782,8 +2763,9 @@ Error DWARFLinker::link() {
   // later. This prevents undeterminism when analyze and clone execute
   // concurrently, as clone set the canonical DIE offset and analyze reads it.
   const uint64_t ModulesEndOffset =
-      (TheDwarfEmitter == nullptr) ? 0
-                                   : TheDwarfEmitter->getDebugInfoSectionSize();
+      (OutDwarfStreamer == nullptr)
+          ? 0
+          : OutDwarfStreamer->getDebugInfoSectionSize();
 
   // These variables manage the list of processed object files.
   // The mutex and condition variable are to ensure that this is thread safe.
@@ -2866,13 +2848,13 @@ Error DWARFLinker::link() {
       SizeByObject[OptContext.File.FileName].Input =
           getDebugInfoSize(*OptContext.File.Dwarf);
       SizeByObject[OptContext.File.FileName].Output =
-          DIECloner(*this, TheDwarfEmitter.get(), OptContext.File, DIEAlloc,
+          DIECloner(*this, OutDwarfStreamer, OptContext.File, DIEAlloc,
                     OptContext.CompileUnits, Options.Update, DebugStrPool,
                     DebugLineStrPool, StringOffsetPool)
               .cloneAllCompileUnits(*OptContext.File.Dwarf, OptContext.File,
                                     OptContext.File.Dwarf->isLittleEndian());
     }
-    if ((TheDwarfEmitter != nullptr) && !OptContext.CompileUnits.empty() &&
+    if ((OutDwarfStreamer != nullptr) && !OptContext.CompileUnits.empty() &&
         LLVM_LIKELY(!Options.Update))
       patchFrameInfoForObject(OptContext);
 
@@ -2882,26 +2864,26 @@ Error DWARFLinker::link() {
 
   auto EmitLambda = [&]() {
     // Emit everything that's global.
-    if (TheDwarfEmitter != nullptr) {
-      TheDwarfEmitter->emitAbbrevs(Abbreviations, Options.TargetDWARFVersion);
-      TheDwarfEmitter->emitStrings(DebugStrPool);
-      TheDwarfEmitter->emitStringOffsets(StringOffsetPool.DieValues,
-                                         Options.TargetDWARFVersion);
-      TheDwarfEmitter->emitLineStrings(DebugLineStrPool);
+    if (OutDwarfStreamer != nullptr) {
+      OutDwarfStreamer->emitAbbrevs(Abbreviations, Options.TargetDWARFVersion);
+      OutDwarfStreamer->emitStrings(DebugStrPool);
+      OutDwarfStreamer->emitStringOffsets(StringOffsetPool.getValues(),
+                                          Options.TargetDWARFVersion);
+      OutDwarfStreamer->emitLineStrings(DebugLineStrPool);
       for (AccelTableKind TableKind : Options.AccelTables) {
         switch (TableKind) {
         case AccelTableKind::Apple:
-          TheDwarfEmitter->emitAppleNamespaces(AppleNamespaces);
-          TheDwarfEmitter->emitAppleNames(AppleNames);
-          TheDwarfEmitter->emitAppleTypes(AppleTypes);
-          TheDwarfEmitter->emitAppleObjc(AppleObjc);
+          OutDwarfStreamer->emitAppleNamespaces(AppleNamespaces);
+          OutDwarfStreamer->emitAppleNames(AppleNames);
+          OutDwarfStreamer->emitAppleTypes(AppleTypes);
+          OutDwarfStreamer->emitAppleObjc(AppleObjc);
           break;
         case AccelTableKind::Pub:
           // Already emitted by emitAcceleratorEntriesForUnit.
           // Already emitted by emitAcceleratorEntriesForUnit.
           break;
         case AccelTableKind::DebugNames:
-          TheDwarfEmitter->emitDebugNames(DebugNames);
+          OutDwarfStreamer->emitDebugNames(DebugNames);
           break;
         }
       }
@@ -3003,7 +2985,7 @@ Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit,
                                    DeclContextTree &ODRContexts,
                                    OffsetsStringPool &DebugStrPool,
                                    OffsetsStringPool &DebugLineStrPool,
-                                   DebugDieValuePool &StringOffsetPool,
+                                   IndexedValuesMap<uint64_t> &StringOffsetPool,
                                    unsigned Indent) {
   assert(Unit.Unit.get() != nullptr);
 
@@ -3028,8 +3010,8 @@ Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit,
   // Clone unit.
   UnitListTy CompileUnits;
   CompileUnits.emplace_back(std::move(Unit.Unit));
-  assert(TheDwarfEmitter);
-  DIECloner(*this, TheDwarfEmitter.get(), Unit.File, DIEAlloc, CompileUnits,
+  assert(OutDwarfStreamer);
+  DIECloner(*this, OutDwarfStreamer, Unit.File, DIEAlloc, CompileUnits,
             Options.Update, DebugStrPool, DebugLineStrPool, StringOffsetPool)
       .cloneAllCompileUnits(*Unit.File.Dwarf, Unit.File,
                             Unit.File.Dwarf->isLittleEndian());
@@ -3039,7 +3021,6 @@ Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit,
 void DWARFLinker::verifyInput(const DWARFFile &File) {
   assert(File.Dwarf);
 
-
   std::string Buffer;
   raw_string_ostream OS(Buffer);
   DIDumpOptions DumpOpts;
@@ -3048,17 +3029,3 @@ void DWARFLinker::verifyInput(const DWARFFile &File) {
       Options.InputVerificationHandler(File, OS.str());
   }
 }
-
-Error DWARFLinker::createEmitter(const Triple &TheTriple,
-                                 OutputFileType FileType,
-                                 raw_pwrite_stream &OutFile) {
-
-  TheDwarfEmitter = std::make_unique<DwarfStreamer>(
-      FileType, OutFile, StringsTranslator, WarningHandler);
-
-  return TheDwarfEmitter->init(TheTriple, "__DWARF");
-}
-
-DwarfEmitter *DWARFLinker::getEmitter() { return TheDwarfEmitter.get(); }
-
-} // namespace llvm
diff --git a/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp b/llvm/lib/DWARFLinker/Apple/DWARFLinkerCompileUnit.cpp
similarity index 97%
rename from llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp
rename to llvm/lib/DWARFLinker/Apple/DWARFLinkerCompileUnit.cpp
index 06559bc38c86cc..af5353d9489007 100644
--- a/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp
+++ b/llvm/lib/DWARFLinker/Apple/DWARFLinkerCompileUnit.cpp
@@ -6,14 +6,15 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
+#include "llvm/DWARFLinker/Apple/DWARFLinkerCompileUnit.h"
 #include "llvm/ADT/StringExtras.h"
-#include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
+#include "llvm/DWARFLinker/Apple/DWARFLinkerDeclContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/Support/FormatVariadic.h"
 
-namespace llvm {
+using namespace llvm;
+using namespace dwarflinker;
 
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
 LLVM_DUMP_METHOD void CompileUnit::DIEInfo::dump() {
@@ -205,5 +206,3 @@ void CompileUnit::addTypeAccelerator(const DIE *Die,
                                      uint32_t QualifiedNameHash) {
   Pubtypes.emplace_back(Name, Die, QualifiedNameHash, ObjcClassImplementation);
 }
-
-} // namespace llvm
diff --git a/llvm/lib/DWARFLinker/DWARFLinkerDeclContext.cpp b/llvm/lib/DWARFLinker/Apple/DWARFLinkerDeclContext.cpp
similarity index 98%
rename from llvm/lib/DWARFLinker/DWARFLinkerDeclContext.cpp
rename to llvm/lib/DWARFLinker/Apple/DWARFLinkerDeclContext.cpp
index 015a4f9e8ac6bb..009990eba2f7e0 100644
--- a/llvm/lib/DWARFLinker/DWARFLinkerDeclContext.cpp
+++ b/llvm/lib/DWARFLinker/Apple/DWARFLinkerDeclContext.cpp
@@ -6,13 +6,14 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
-#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
+#include "llvm/DWARFLinker/Apple/DWARFLinkerDeclContext.h"
+#include "llvm/DWARFLinker/Apple/DWARFLinkerCompileUnit.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
 
-namespace llvm {
+using namespace llvm;
+using namespace dwarflinker;
 
 /// Set the last DIE/CU a context was seen in and, possibly invalidate the
 /// context if it is ambiguous.
@@ -212,5 +213,3 @@ DeclContextTree::getResolvedPath(CompileUnit &CU, unsigned FileNum,
 
   return It->second;
 }
-
-} // namespace llvm
diff --git a/llvm/lib/DWARFLinker/DWARFStreamer.cpp b/llvm/lib/DWARFLinker/Apple/DWARFStreamer.cpp
similarity index 94%
rename from llvm/lib/DWARFLinker/DWARFStreamer.cpp
rename to llvm/lib/DWARFLinker/Apple/DWARFStreamer.cpp
index cd649c328ed930..fc058428867a3c 100644
--- a/llvm/lib/DWARFLinker/DWARFStreamer.cpp
+++ b/llvm/lib/DWARFLinker/Apple/DWARFStreamer.cpp
@@ -6,9 +6,9 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/DWARFLinker/DWARFStreamer.h"
+#include "llvm/DWARFLinker/Apple/DWARFStreamer.h"
 #include "llvm/CodeGen/NonRelocatableStringpool.h"
-#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
+#include "llvm/DWARFLinker/Apple/DWARFLinkerCompileUnit.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
 #include "llvm/MC/MCAsmBackend.h"
@@ -26,10 +26,28 @@
 #include "llvm/Target/TargetOptions.h"
 #include "llvm/TargetParser/Triple.h"
 
-namespace llvm {
+using namespace llvm;
+using namespace dwarflinker;
+
+Expected<DwarfStreamer *> DwarfStreamer::createStreamer(
+    const Triple &TheTriple, DWARFLinkerBase::OutputFileType FileType,
+    raw_pwrite_stream &OutFile,
+    std::function<StringRef(StringRef Input)> Translator,
+    DWARFLinkerBase::MessageHandlerTy Warning) {
+  DwarfStreamer *Streamer =
+      new DwarfStreamer(FileType, OutFile, Translator, Warning);
+  if (Error Err = Streamer->init(TheTriple, "__DWARF")) {
+    delete Streamer;
+    return std::move(Err);
+  }
+
+  return Streamer;
+}
 
 Error DwarfStreamer::init(Triple TheTriple,
                           StringRef Swift5ReflectionSegmentName) {
+  TheTargetTriple = TheTriple;
+
   std::string ErrorStr;
   std::string TripleName;
 
@@ -211,29 +229,50 @@ void DwarfStreamer::emitDIE(DIE &Die) {
 
 /// Emit contents of section SecName From Obj.
 void DwarfStreamer::emitSectionContents(StringRef SecData, StringRef SecName) {
-  MCSection *Section =
-      StringSwitch<MCSection *>(SecName)
-          .Case("debug_line", MC->getObjectFileInfo()->getDwarfLineSection())
-          .Case("debug_loc", MC->getObjectFileInfo()->getDwarfLocSection())
-          .Case("debug_ranges",
-                MC->getObjectFileInfo()->getDwarfRangesSection())
-          .Case("debug_frame", MC->getObjectFileInfo()->getDwarfFrameSection())
-          .Case("debug_aranges",
-                MC->getObjectFileInfo()->getDwarfARangesSection())
-          .Case("debug_addr", MC->getObjectFileInfo()->getDwarfAddrSection())
-          .Case("debug_rnglists",
-                MC->getObjectFileInfo()->getDwarfRnglistsSection())
-          .Case("debug_loclists",
-                MC->getObjectFileInfo()->getDwarfLoclistsSection())
-          .Default(nullptr);
-
-  if (Section) {
+  if (SecData.empty())
+    return;
+
+  if (MCSection *Section = switchSection(SecName)) {
     MS->switchSection(Section);
 
     MS->emitBytes(SecData);
   }
 }
 
+MCSection *DwarfStreamer::switchSection(StringRef SecName) {
+  return StringSwitch<MCSection *>(SecName)
+      .Case("debug_info", MC->getObjectFileInfo()->getDwarfInfoSection())
+      .Case("debug_abbrev", MC->getObjectFileInfo()->getDwarfAbbrevSection())
+      .Case("debug_line", MC->getObjectFileInfo()->getDwarfLineSection())
+      .Case("debug_loc", MC->getObjectFileInfo()->getDwarfLocSection())
+      .Case("debug_ranges", MC->getObjectFileInfo()->getDwarfRangesSection())
+      .Case("debug_frame", MC->getObjectFileInfo()->getDwarfFrameSection())
+      .Case("debug_aranges", MC->getObjectFileInfo()->getDwarfARangesSection())
+      .Case("debug_rnglists",
+            MC->getObjectFileInfo()->getDwarfRnglistsSection())
+      .Case("debug_loclists",
+            MC->getObjectFileInfo()->getDwarfLoclistsSection())
+      .Case("debug_macro", MC->getObjectFileInfo()->getDwarfMacroSection())
+      .Case("debug_macinfo", MC->getObjectFileInfo()->getDwarfMacinfoSection())
+      .Case("debug_addr", MC->getObjectFileInfo()->getDwarfAddrSection())
+      .Case("debug_str", MC->getObjectFileInfo()->getDwarfStrSection())
+      .Case("debug_line_str", MC->getObjectFileInfo()->getDwarfLineStrSection())
+      .Case("debug_str_offsets",
+            MC->getObjectFileInfo()->getDwarfStrOffSection())
+      .Case("debug_pubnames",
+            MC->getObjectFileInfo()->getDwarfPubNamesSection())
+      .Case("debug_pubtypes",
+            MC->getObjectFileInfo()->getDwarfPubTypesSection())
+      .Case("debug_names", MC->getObjectFileInfo()->getDwarfDebugNamesSection())
+      .Case("apple_names", MC->getObjectFileInfo()->getDwarfAccelNamesSection())
+      .Case("apple_namespac",
+            MC->getObjectFileInfo()->getDwarfAccelNamespaceSection())
+      .Case("apple_objc", MC->getObjectFileInfo()->getDwarfAccelObjCSection())
+      .Case("apple_types", MC->getObjectFileInfo()->getDwarfAccelTypesSection())
+
+      .Default(nullptr);
+}
+
 /// Emit the debug_str section stored in \p Pool.
 void DwarfStreamer::emitStrings(const NonRelocatableStringpool &Pool) {
   Asm->OutStreamer->switchSection(MOFI->getDwarfStrSection());
@@ -484,7 +523,7 @@ DwarfStreamer::emitDwarfDebugRangeListHeader(const CompileUnit &Unit) {
 
 void DwarfStreamer::emitDwarfDebugRangeListFragment(
     const CompileUnit &Unit, const AddressRanges &LinkedRanges,
-    PatchLocation Patch, DebugDieValuePool &AddrPool) {
+    PatchLocation Patch, IndexedValuesMap<uint64_t> &AddrPool) {
   if (Unit.getOrigUnit().getVersion() < 5) {
     emitDwarfDebugRangesTableFragment(Unit, LinkedRanges, Patch);
     return;
@@ -507,7 +546,7 @@ void DwarfStreamer::emitDwarfDebugRangeListFooter(const CompileUnit &Unit,
 
 void DwarfStreamer::emitDwarfDebugRngListsTableFragment(
     const CompileUnit &Unit, const AddressRanges &LinkedRanges,
-    PatchLocation Patch, DebugDieValuePool &AddrPool) {
+    PatchLocation Patch, IndexedValuesMap<uint64_t> &AddrPool) {
   Patch.set(RngListsSectionSize);
 
   // Make .debug_rnglists to be current section.
@@ -583,7 +622,7 @@ MCSymbol *DwarfStreamer::emitDwarfDebugLocListHeader(const CompileUnit &Unit) {
 void DwarfStreamer::emitDwarfDebugLocListFragment(
     const CompileUnit &Unit,
     const DWARFLocationExpressionsVector &LinkedLocationExpression,
-    PatchLocation Patch, DebugDieValuePool &AddrPool) {
+    PatchLocation Patch, IndexedValuesMap<uint64_t> &AddrPool) {
   if (Unit.getOrigUnit().getVersion() < 5) {
     emitDwarfDebugLocTableFragment(Unit, LinkedLocationExpression, Patch);
     return;
@@ -701,7 +740,7 @@ void DwarfStreamer::emitDwarfDebugAddrsFooter(const CompileUnit &Unit,
 void DwarfStreamer::emitDwarfDebugLocListsTableFragment(
     const CompileUnit &Unit,
     const DWARFLocationExpressionsVector &LinkedLocationExpression,
-    PatchLocation Patch, DebugDieValuePool &AddrPool) {
+    PatchLocation Patch, IndexedValuesMap<uint64_t> &AddrPool) {
   Patch.set(LocListsSectionSize);
 
   // Make .debug_loclists the current section.
@@ -1404,5 +1443,3 @@ void DwarfStreamer::emitMacroTableImpl(const DWARFDebugMacro *MacroTable,
     }
   }
 }
-
-} // namespace llvm
diff --git a/llvm/lib/DWARFLinker/CMakeLists.txt b/llvm/lib/DWARFLinker/CMakeLists.txt
index f720c5e844b36e..e1f1613f14d31f 100644
--- a/llvm/lib/DWARFLinker/CMakeLists.txt
+++ b/llvm/lib/DWARFLinker/CMakeLists.txt
@@ -1,8 +1,5 @@
-add_llvm_component_library(LLVMDWARFLinker
-  DWARFLinkerCompileUnit.cpp
-  DWARFLinkerDeclContext.cpp
-  DWARFLinker.cpp
-  DWARFStreamer.cpp
+add_llvm_component_library(LLVMDWARFLinkerBase
+  Utils.cpp
 
   ADDITIONAL_HEADER_DIRS
   ${LLVM_MAIN_INCLUDE_DIR}/llvm/DWARFLinker
@@ -11,13 +8,7 @@ add_llvm_component_library(LLVMDWARFLinker
   intrinsics_gen
 
   LINK_COMPONENTS
-  AsmPrinter
-  BinaryFormat
-  CodeGen
-  CodeGenTypes
-  DebugInfoDWARF
-  MC
-  Object
-  Support
-  TargetParser
   )
+
+add_subdirectory(Apple)
+add_subdirectory(LLVM)
diff --git a/llvm/lib/DWARFLinkerParallel/AcceleratorRecordsSaver.cpp b/llvm/lib/DWARFLinker/LLVM/AcceleratorRecordsSaver.cpp
similarity index 98%
rename from llvm/lib/DWARFLinkerParallel/AcceleratorRecordsSaver.cpp
rename to llvm/lib/DWARFLinker/LLVM/AcceleratorRecordsSaver.cpp
index 5ec25cfe5fd26e..83c2872f3a598f 100644
--- a/llvm/lib/DWARFLinkerParallel/AcceleratorRecordsSaver.cpp
+++ b/llvm/lib/DWARFLinker/LLVM/AcceleratorRecordsSaver.cpp
@@ -7,12 +7,13 @@
 //===----------------------------------------------------------------------===//
 
 #include "AcceleratorRecordsSaver.h"
-#include "Utils.h"
+#include "llvm/DWARFLinker/Utils.h"
 #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
 #include "llvm/Support/DJB.h"
 
-namespace llvm {
-namespace dwarflinker_parallel {
+using namespace llvm;
+using namespace dwarflinker;
+using namespace dwarflinker_parallel;
 
 static uint32_t hashFullyQualifiedName(CompileUnit &InputCU, DWARFDie &InputDIE,
                                        int ChildRecurseDepth = 0) {
@@ -290,6 +291,3 @@ void AcceleratorRecordsSaver::saveTypeRecord(StringEntry *Name, DIE *OutDIE,
   Info.TypeEntryBodyPtr = TypeEntry->getValue().load();
   OutUnit.getAsTypeUnit()->saveAcceleratorInfo(Info);
 }
-
-} // end of namespace dwarflinker_parallel
-} // namespace llvm
diff --git a/llvm/lib/DWARFLinkerParallel/AcceleratorRecordsSaver.h b/llvm/lib/DWARFLinker/LLVM/AcceleratorRecordsSaver.h
similarity index 91%
rename from llvm/lib/DWARFLinkerParallel/AcceleratorRecordsSaver.h
rename to llvm/lib/DWARFLinker/LLVM/AcceleratorRecordsSaver.h
index 5e7f4d0c3166fd..22504f1f45f6a5 100644
--- a/llvm/lib/DWARFLinkerParallel/AcceleratorRecordsSaver.h
+++ b/llvm/lib/DWARFLinker/LLVM/AcceleratorRecordsSaver.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_LIB_DWARFLINKERPARALLEL_ACCELERATORRECORDSSAVER_H
-#define LLVM_LIB_DWARFLINKERPARALLEL_ACCELERATORRECORDSSAVER_H
+#ifndef LLVM_LIB_DWARFLINKER_LLVM_ACCELERATORRECORDSSAVER_H
+#define LLVM_LIB_DWARFLINKER_LLVM_ACCELERATORRECORDSSAVER_H
 
 #include "DIEAttributeCloner.h"
 #include "DWARFLinkerCompileUnit.h"
@@ -15,6 +15,7 @@
 #include "DWARFLinkerTypeUnit.h"
 
 namespace llvm {
+namespace dwarflinker {
 namespace dwarflinker_parallel {
 
 /// This class helps to store information for accelerator entries.
@@ -65,6 +66,7 @@ class AcceleratorRecordsSaver {
 };
 
 } // end of namespace dwarflinker_parallel
+} // end of namespace dwarflinker
 } // end namespace llvm
 
-#endif // LLVM_LIB_DWARFLINKERPARALLEL_ACCELERATORRECORDSSAVER_H
+#endif // LLVM_LIB_DWARFLINKER_LLVM_ACCELERATORRECORDSSAVER_H
diff --git a/llvm/lib/DWARFLinkerParallel/CMakeLists.txt b/llvm/lib/DWARFLinker/LLVM/CMakeLists.txt
similarity index 85%
rename from llvm/lib/DWARFLinkerParallel/CMakeLists.txt
rename to llvm/lib/DWARFLinker/LLVM/CMakeLists.txt
index b0f0b3910e586a..012d3fe43e2cad 100644
--- a/llvm/lib/DWARFLinkerParallel/CMakeLists.txt
+++ b/llvm/lib/DWARFLinker/LLVM/CMakeLists.txt
@@ -3,18 +3,16 @@ add_llvm_component_library(LLVMDWARFLinkerParallel
   DependencyTracker.cpp
   DIEAttributeCloner.cpp
   DWARFEmitterImpl.cpp
-  DWARFFile.cpp
   DWARFLinker.cpp
   DWARFLinkerCompileUnit.cpp
   DWARFLinkerTypeUnit.cpp
   DWARFLinkerImpl.cpp
   DWARFLinkerUnit.cpp
   OutputSections.cpp
-  StringPool.cpp
   SyntheticTypeNameBuilder.cpp
 
   ADDITIONAL_HEADER_DIRS
-  ${LLVM_MAIN_INCLUDE_DIR}/llvm/DWARFLinkerParallel
+  ${LLVM_MAIN_INCLUDE_DIR}/llvm/DWARFLinker
 
   DEPENDS
   intrinsics_gen
@@ -23,7 +21,9 @@ add_llvm_component_library(LLVMDWARFLinkerParallel
   AsmPrinter
   BinaryFormat
   CodeGen
+  CodeGenTypes
   DebugInfoDWARF
+  DWARFLinkerBase
   MC
   Object
   Support
diff --git a/llvm/lib/DWARFLinkerParallel/DIEAttributeCloner.cpp b/llvm/lib/DWARFLinker/LLVM/DIEAttributeCloner.cpp
similarity index 99%
rename from llvm/lib/DWARFLinkerParallel/DIEAttributeCloner.cpp
rename to llvm/lib/DWARFLinker/LLVM/DIEAttributeCloner.cpp
index 81fc57f7cabbb7..afec44e3e69211 100644
--- a/llvm/lib/DWARFLinkerParallel/DIEAttributeCloner.cpp
+++ b/llvm/lib/DWARFLinker/LLVM/DIEAttributeCloner.cpp
@@ -9,8 +9,9 @@
 #include "DIEAttributeCloner.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
 
-namespace llvm {
-namespace dwarflinker_parallel {
+using namespace llvm;
+using namespace dwarflinker;
+using namespace dwarflinker_parallel;
 
 void DIEAttributeCloner::clone() {
   // Extract and clone every attribute.
@@ -650,6 +651,3 @@ unsigned DIEAttributeCloner::finalizeAbbreviations(bool HasChildrenToClone) {
 
   return AttrOutOffset;
 }
-
-} // end of namespace dwarflinker_parallel
-} // namespace llvm
diff --git a/llvm/lib/DWARFLinkerParallel/DIEAttributeCloner.h b/llvm/lib/DWARFLinker/LLVM/DIEAttributeCloner.h
similarity index 96%
rename from llvm/lib/DWARFLinkerParallel/DIEAttributeCloner.h
rename to llvm/lib/DWARFLinker/LLVM/DIEAttributeCloner.h
index e18c0a15cefc63..fcbe26403f07c9 100644
--- a/llvm/lib/DWARFLinkerParallel/DIEAttributeCloner.h
+++ b/llvm/lib/DWARFLinker/LLVM/DIEAttributeCloner.h
@@ -6,16 +6,17 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_LIB_DWARFLINKERPARALLEL_DIEATTRIBUTECLONER_H
-#define LLVM_LIB_DWARFLINKERPARALLEL_DIEATTRIBUTECLONER_H
+#ifndef LLVM_LIB_DWARFLINKER_LLVM_DIEATTRIBUTECLONER_H
+#define LLVM_LIB_DWARFLINKER_LLVM_DIEATTRIBUTECLONER_H
 
-#include "ArrayList.h"
 #include "DIEGenerator.h"
 #include "DWARFLinkerCompileUnit.h"
 #include "DWARFLinkerGlobalData.h"
 #include "DWARFLinkerTypeUnit.h"
+#include "llvm/DWARFLinker/ArrayList.h"
 
 namespace llvm {
+namespace dwarflinker {
 namespace dwarflinker_parallel {
 
 /// Information gathered and exchanged between the various
@@ -179,6 +180,7 @@ class DIEAttributeCloner {
 };
 
 } // end of namespace dwarflinker_parallel
+} // end of namespace dwarflinker
 } // end namespace llvm
 
-#endif // LLVM_LIB_DWARFLINKERPARALLEL_DIEATTRIBUTECLONER_H
+#endif // LLVM_LIB_DWARFLINKER_LLVM_DIEATTRIBUTECLONER_H
diff --git a/llvm/lib/DWARFLinkerParallel/DIEGenerator.h b/llvm/lib/DWARFLinker/LLVM/DIEGenerator.h
similarity index 97%
rename from llvm/lib/DWARFLinkerParallel/DIEGenerator.h
rename to llvm/lib/DWARFLinker/LLVM/DIEGenerator.h
index 42bf00f55ff180..b38c032f2339fa 100644
--- a/llvm/lib/DWARFLinkerParallel/DIEGenerator.h
+++ b/llvm/lib/DWARFLinker/LLVM/DIEGenerator.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_LIB_DWARFLINKERPARALLEL_DIEGENERATOR_H
-#define LLVM_LIB_DWARFLINKERPARALLEL_DIEGENERATOR_H
+#ifndef LLVM_LIB_DWARFLINKER_LLVM_DIEGENERATOR_H
+#define LLVM_LIB_DWARFLINKER_LLVM_DIEGENERATOR_H
 
 #include "DWARFLinkerGlobalData.h"
 #include "DWARFLinkerUnit.h"
@@ -15,6 +15,7 @@
 #include "llvm/Support/LEB128.h"
 
 namespace llvm {
+namespace dwarflinker {
 namespace dwarflinker_parallel {
 
 /// This class is a helper to create output DIE tree.
@@ -175,6 +176,7 @@ class DIEGenerator {
 };
 
 } // end of namespace dwarflinker_parallel
+} // end of namespace dwarflinker
 } // end namespace llvm
 
-#endif // LLVM_LIB_DWARFLINKERPARALLEL_DIEGENERATOR_H
+#endif // LLVM_LIB_DWARFLINKER_LLVM_DIEGENERATOR_H
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.cpp b/llvm/lib/DWARFLinker/LLVM/DWARFEmitterImpl.cpp
similarity index 92%
rename from llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.cpp
rename to llvm/lib/DWARFLinker/LLVM/DWARFEmitterImpl.cpp
index 355cfae3a64629..422a4d2709daaa 100644
--- a/llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.cpp
+++ b/llvm/lib/DWARFLinker/LLVM/DWARFEmitterImpl.cpp
@@ -7,7 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "DWARFEmitterImpl.h"
-#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
+#include "DWARFLinkerCompileUnit.h"
 #include "llvm/MC/MCAsmBackend.h"
 #include "llvm/MC/MCCodeEmitter.h"
 #include "llvm/MC/MCObjectWriter.h"
@@ -17,8 +17,9 @@
 #include "llvm/MC/TargetRegistry.h"
 #include "llvm/Support/FormattedStream.h"
 
-namespace llvm {
-namespace dwarflinker_parallel {
+using namespace llvm;
+using namespace dwarflinker;
+using namespace dwarflinker_parallel;
 
 Error DwarfEmitterImpl::init(Triple TheTriple,
                              StringRef Swift5ReflectionSegmentName) {
@@ -119,26 +120,6 @@ Error DwarfEmitterImpl::init(Triple TheTriple,
   return Error::success();
 }
 
-void DwarfEmitterImpl::emitSwiftAST(StringRef Buffer) {
-  MCSection *SwiftASTSection = MOFI->getDwarfSwiftASTSection();
-  SwiftASTSection->setAlignment(Align(32));
-  MS->switchSection(SwiftASTSection);
-  MS->emitBytes(Buffer);
-}
-
-/// Emit the swift reflection section stored in \p Buffer.
-void DwarfEmitterImpl::emitSwiftReflectionSection(
-    llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind,
-    StringRef Buffer, uint32_t Alignment, uint32_t) {
-  MCSection *ReflectionSection =
-      MOFI->getSwift5ReflectionSection(ReflSectionKind);
-  if (ReflectionSection == nullptr)
-    return;
-  ReflectionSection->setAlignment(Align(Alignment));
-  MS->switchSection(ReflectionSection);
-  MS->emitBytes(Buffer);
-}
-
 void DwarfEmitterImpl::emitSectionContents(StringRef SecData,
                                            StringRef SecName) {
   if (SecData.empty())
@@ -276,6 +257,3 @@ void DwarfEmitterImpl::emitAppleTypes(
   Asm->OutStreamer->emitLabel(SectionBegin);
   emitAppleAccelTable(Asm.get(), Table, "types", SectionBegin);
 }
-
-} // end of namespace dwarflinker_parallel
-} // namespace llvm
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.h b/llvm/lib/DWARFLinker/LLVM/DWARFEmitterImpl.h
similarity index 84%
rename from llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.h
rename to llvm/lib/DWARFLinker/LLVM/DWARFEmitterImpl.h
index d03336c1c11a36..950ed15607c837 100644
--- a/llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.h
+++ b/llvm/lib/DWARFLinker/LLVM/DWARFEmitterImpl.h
@@ -6,14 +6,14 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_LIB_DWARFLINKERPARALLEL_DWARFEMITTERIMPL_H
-#define LLVM_LIB_DWARFLINKERPARALLEL_DWARFEMITTERIMPL_H
+#ifndef LLVM_LIB_DWARFLINKER_LLVM_DWARFEMITTERIMPL_H
+#define LLVM_LIB_DWARFLINKER_LLVM_DWARFEMITTERIMPL_H
 
 #include "DWARFLinkerCompileUnit.h"
 #include "llvm/BinaryFormat/Swift.h"
 #include "llvm/CodeGen/AccelTable.h"
 #include "llvm/CodeGen/AsmPrinter.h"
-#include "llvm/DWARFLinkerParallel/DWARFLinker.h"
+#include "llvm/DWARFLinker/LLVM/DWARFLinker.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCInstrInfo.h"
@@ -36,6 +36,7 @@ namespace llvm {
 template <typename DataT> class AccelTable;
 class MCCodeEmitter;
 
+namespace dwarflinker {
 namespace dwarflinker_parallel {
 
 using DebugNamesUnitsOffsets = std::vector<std::variant<MCSymbol *, uint64_t>>;
@@ -44,7 +45,7 @@ using CompUnitIDToIdx = DenseMap<unsigned, unsigned>;
 /// This class emits DWARF data to the output stream. It emits already
 /// generated section data and specific data, which could not be generated
 /// by CompileUnit.
-class DwarfEmitterImpl : public ExtraDwarfEmitter {
+class DwarfEmitterImpl {
 public:
   DwarfEmitterImpl(DWARFLinker::OutputFileType OutFileType,
                    raw_pwrite_stream &OutFile)
@@ -57,21 +58,10 @@ class DwarfEmitterImpl : public ExtraDwarfEmitter {
   const Triple &getTargetTriple() { return MC->getTargetTriple(); }
 
   /// Dump the file to the disk.
-  void finish() override { MS->finish(); }
-
-  /// Returns AsmPrinter.
-  AsmPrinter &getAsmPrinter() const override { return *Asm; }
-
-  /// Emit the swift_ast section stored in \p Buffer.
-  void emitSwiftAST(StringRef Buffer) override;
-
-  /// Emit the swift reflection section stored in \p Buffer.
-  void emitSwiftReflectionSection(
-      llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind,
-      StringRef Buffer, uint32_t Alignment, uint32_t) override;
+  void finish() { MS->finish(); }
 
   /// Emit specified section data.
-  void emitSectionContents(StringRef SecData, StringRef SecName) override;
+  void emitSectionContents(StringRef SecData, StringRef SecName);
 
   /// Emit abbreviations.
   void emitAbbrevs(const SmallVector<std::unique_ptr<DIEAbbrev>> &Abbrevs,
@@ -134,12 +124,14 @@ class DwarfEmitterImpl : public ExtraDwarfEmitter {
 
   /// The output file we stream the linked Dwarf to.
   raw_pwrite_stream &OutFile;
-  DWARFLinker::OutputFileType OutFileType = DWARFLinker::OutputFileType::Object;
+  DWARFLinkerBase::OutputFileType OutFileType =
+      DWARFLinkerBase::OutputFileType::Object;
 
   uint64_t DebugInfoSectionSize = 0;
 };
 
 } // end namespace dwarflinker_parallel
+} // end namespace dwarflinker
 } // end namespace llvm
 
-#endif // LLVM_LIB_DWARFLINKERPARALLEL_DWARFEMITTERIMPL_H
+#endif // LLVM_LIB_DWARFLINKER_LLVM_DWARFEMITTERIMPL_H
diff --git a/llvm/lib/DWARFLinker/LLVM/DWARFLinker.cpp b/llvm/lib/DWARFLinker/LLVM/DWARFLinker.cpp
new file mode 100644
index 00000000000000..16649ff8cc7549
--- /dev/null
+++ b/llvm/lib/DWARFLinker/LLVM/DWARFLinker.cpp
@@ -0,0 +1,77 @@
+//=== DWARFLinker.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 "DWARFLinkerImpl.h"
+#include "DependencyTracker.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace llvm;
+using namespace dwarflinker;
+using namespace dwarflinker_parallel;
+
+std::unique_ptr<DWARFLinker>
+llvm::dwarflinker::dwarflinker_parallel::DWARFLinker::createLinker(
+    MessageHandlerTy ErrorHandler, MessageHandlerTy WarningHandler,
+    TranslatorFuncTy StringsTranslator) {
+  return std::make_unique<DWARFLinkerImpl>(ErrorHandler, WarningHandler,
+                                           StringsTranslator);
+}
+
+std::optional<DebugSectionKind>
+llvm::dwarflinker::dwarflinker_parallel::parseDebugTableName(
+    llvm::StringRef SecName) {
+  return llvm::StringSwitch<std::optional<DebugSectionKind>>(
+             SecName.substr(SecName.find_first_not_of("._")))
+      .Case(getSectionName(DebugSectionKind::DebugInfo),
+            DebugSectionKind::DebugInfo)
+      .Case(getSectionName(DebugSectionKind::DebugLine),
+            DebugSectionKind::DebugLine)
+      .Case(getSectionName(DebugSectionKind::DebugFrame),
+            DebugSectionKind::DebugFrame)
+      .Case(getSectionName(DebugSectionKind::DebugRange),
+            DebugSectionKind::DebugRange)
+      .Case(getSectionName(DebugSectionKind::DebugRngLists),
+            DebugSectionKind::DebugRngLists)
+      .Case(getSectionName(DebugSectionKind::DebugLoc),
+            DebugSectionKind::DebugLoc)
+      .Case(getSectionName(DebugSectionKind::DebugLocLists),
+            DebugSectionKind::DebugLocLists)
+      .Case(getSectionName(DebugSectionKind::DebugARanges),
+            DebugSectionKind::DebugARanges)
+      .Case(getSectionName(DebugSectionKind::DebugAbbrev),
+            DebugSectionKind::DebugAbbrev)
+      .Case(getSectionName(DebugSectionKind::DebugMacinfo),
+            DebugSectionKind::DebugMacinfo)
+      .Case(getSectionName(DebugSectionKind::DebugMacro),
+            DebugSectionKind::DebugMacro)
+      .Case(getSectionName(DebugSectionKind::DebugAddr),
+            DebugSectionKind::DebugAddr)
+      .Case(getSectionName(DebugSectionKind::DebugStr),
+            DebugSectionKind::DebugStr)
+      .Case(getSectionName(DebugSectionKind::DebugLineStr),
+            DebugSectionKind::DebugLineStr)
+      .Case(getSectionName(DebugSectionKind::DebugStrOffsets),
+            DebugSectionKind::DebugStrOffsets)
+      .Case(getSectionName(DebugSectionKind::DebugPubNames),
+            DebugSectionKind::DebugPubNames)
+      .Case(getSectionName(DebugSectionKind::DebugPubTypes),
+            DebugSectionKind::DebugPubTypes)
+      .Case(getSectionName(DebugSectionKind::DebugNames),
+            DebugSectionKind::DebugNames)
+      .Case(getSectionName(DebugSectionKind::AppleNames),
+            DebugSectionKind::AppleNames)
+      .Case(getSectionName(DebugSectionKind::AppleNamespaces),
+            DebugSectionKind::AppleNamespaces)
+      .Case(getSectionName(DebugSectionKind::AppleObjC),
+            DebugSectionKind::AppleObjC)
+      .Case(getSectionName(DebugSectionKind::AppleTypes),
+            DebugSectionKind::AppleTypes)
+      .Default(std::nullopt);
+
+  return std::nullopt;
+}
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFLinkerCompileUnit.cpp b/llvm/lib/DWARFLinker/LLVM/DWARFLinkerCompileUnit.cpp
similarity index 98%
rename from llvm/lib/DWARFLinkerParallel/DWARFLinkerCompileUnit.cpp
rename to llvm/lib/DWARFLinker/LLVM/DWARFLinkerCompileUnit.cpp
index 48e7cb1fd7e2f3..1328d810c42b9a 100644
--- a/llvm/lib/DWARFLinkerParallel/DWARFLinkerCompileUnit.cpp
+++ b/llvm/lib/DWARFLinker/LLVM/DWARFLinkerCompileUnit.cpp
@@ -12,6 +12,7 @@
 #include "DIEGenerator.h"
 #include "DependencyTracker.h"
 #include "SyntheticTypeNameBuilder.h"
+#include "llvm/DWARFLinker/Utils.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
 #include "llvm/Support/DJB.h"
@@ -21,7 +22,8 @@
 #include <utility>
 
 using namespace llvm;
-using namespace llvm::dwarflinker_parallel;
+using namespace dwarflinker;
+using namespace dwarflinker_parallel;
 
 CompileUnit::CompileUnit(LinkingGlobalData &GlobalData, unsigned ID,
                          StringRef ClangModuleName, DWARFFile &File,
@@ -246,20 +248,6 @@ void CompileUnit::cleanupDataAfterClonning() {
   getOrigUnit().clear();
 }
 
-/// Make a best effort to guess the
-/// Xcode.app/Contents/Developer/Toolchains/ path from an SDK path.
-static SmallString<128> guessToolchainBaseDir(StringRef SysRoot) {
-  SmallString<128> Result;
-  // Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk
-  StringRef Base = sys::path::parent_path(SysRoot);
-  if (sys::path::filename(Base) != "SDKs")
-    return Result;
-  Base = sys::path::parent_path(Base);
-  Result = Base;
-  Result += "/Toolchains";
-  return Result;
-}
-
 /// Collect references to parseable Swift interfaces in imported
 /// DW_TAG_module blocks.
 void CompileUnit::analyzeImportedModule(const DWARFDebugInfoEntry *DieEntry) {
@@ -1241,8 +1229,9 @@ void CompileUnit::cloneDieAttrExpression(
   }
 }
 
-Error CompileUnit::cloneAndEmit(std::optional<Triple> TargetTriple,
-                                TypeUnit *ArtificialTypeUnit) {
+Error CompileUnit::cloneAndEmit(
+    std::optional<std::reference_wrapper<const Triple>> TargetTriple,
+    TypeUnit *ArtificialTypeUnit) {
   BumpPtrAllocator Allocator;
 
   DWARFDie OrigUnitDIE = getOrigUnit().getUnitDIE();
@@ -1263,14 +1252,14 @@ Error CompileUnit::cloneAndEmit(std::optional<Triple> TargetTriple,
     return Error::success();
 
   assert(TargetTriple.has_value());
-  if (Error Err = cloneAndEmitLineTable(*TargetTriple))
+  if (Error Err = cloneAndEmitLineTable((*TargetTriple).get()))
     return Err;
 
   if (Error Err = cloneAndEmitDebugMacro())
     return Err;
 
   getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);
-  if (Error Err = emitDebugInfo(*TargetTriple))
+  if (Error Err = emitDebugInfo((*TargetTriple).get()))
     return Err;
 
   // ASSUMPTION: .debug_info section should already be emitted at this point.
@@ -1526,7 +1515,7 @@ TypeEntry *CompileUnit::createTypeDIEandCloneAttributes(
   return Entry;
 }
 
-Error CompileUnit::cloneAndEmitLineTable(Triple &TargetTriple) {
+Error CompileUnit::cloneAndEmitLineTable(const Triple &TargetTriple) {
   const DWARFDebugLine::LineTable *InputLineTable =
       getContaingFile().Dwarf->getLineTableForUnit(&getOrigUnit());
   if (InputLineTable == nullptr) {
@@ -1697,14 +1686,6 @@ CompileUnit::getDirAndFilenameFromLineTable(
   return getDirAndFilenameFromLineTable(FileIdx);
 }
 
-static bool isPathAbsoluteOnWindowsOrPosix(const Twine &Path) {
-  // Debug info can contain paths from any OS, not necessarily
-  // an OS we're currently running on. Moreover different compilation units can
-  // be compiled on different operating systems and linked together later.
-  return sys::path::is_absolute(Path, sys::path::Style::posix) ||
-         sys::path::is_absolute(Path, sys::path::Style::windows);
-}
-
 std::optional<std::pair<StringRef, StringRef>>
 CompileUnit::getDirAndFilenameFromLineTable(uint64_t FileIdx) {
   FileNamesCache::iterator FileData = FileNames.find(FileIdx);
@@ -1870,7 +1851,7 @@ void CompileUnit::verifyDependencies() {
   Dependencies.get()->verifyKeepChain();
 }
 
-ArrayRef<dwarf::Attribute> llvm::dwarflinker_parallel::getODRAttributes() {
+ArrayRef<dwarf::Attribute> dwarflinker_parallel::getODRAttributes() {
   static dwarf::Attribute ODRAttributes[] = {
       dwarf::DW_AT_type, dwarf::DW_AT_specification,
       dwarf::DW_AT_abstract_origin, dwarf::DW_AT_import};
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFLinkerCompileUnit.h b/llvm/lib/DWARFLinker/LLVM/DWARFLinkerCompileUnit.h
similarity index 97%
rename from llvm/lib/DWARFLinkerParallel/DWARFLinkerCompileUnit.h
rename to llvm/lib/DWARFLinker/LLVM/DWARFLinkerCompileUnit.h
index 28fcc34d867dbd..833108629e8824 100644
--- a/llvm/lib/DWARFLinkerParallel/DWARFLinkerCompileUnit.h
+++ b/llvm/lib/DWARFLinker/LLVM/DWARFLinkerCompileUnit.h
@@ -6,14 +6,16 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_LIB_DWARFLINKERPARALLEL_DWARFLINKERCOMPILEUNIT_H
-#define LLVM_LIB_DWARFLINKERPARALLEL_DWARFLINKERCOMPILEUNIT_H
+#ifndef LLVM_LIB_DWARFLINKER_LLVM_DWARFLINKERCOMPILEUNIT_H
+#define LLVM_LIB_DWARFLINKER_LLVM_DWARFLINKERCOMPILEUNIT_H
 
 #include "DWARFLinkerUnit.h"
-#include "llvm/DWARFLinkerParallel/DWARFFile.h"
+#include "llvm/DWARFLinker/DWARFFile.h"
+#include "llvm/DWARFLinker/StringPool.h"
 #include <optional>
 
 namespace llvm {
+namespace dwarflinker {
 namespace dwarflinker_parallel {
 
 using OffsetToUnitTy = function_ref<CompileUnit *(uint64_t Offset)>;
@@ -400,8 +402,9 @@ class alignas(8) CompileUnit : public DwarfUnit {
   const RangesTy &getFunctionRanges() const { return Ranges; }
 
   /// Clone and emit this compilation unit.
-  Error cloneAndEmit(std::optional<Triple> TargetTriple,
-                     TypeUnit *ArtificialTypeUnit);
+  Error
+  cloneAndEmit(std::optional<std::reference_wrapper<const Triple>> TargetTriple,
+               TypeUnit *ArtificialTypeUnit);
 
   /// Clone and emit debug locations(.debug_loc/.debug_loclists).
   Error cloneAndEmitDebugLocations();
@@ -421,7 +424,7 @@ class alignas(8) CompileUnit : public DwarfUnit {
            BumpPtrAllocator &Allocator, TypeUnit *ArtificialTypeUnit);
 
   // Clone and emit line table.
-  Error cloneAndEmitLineTable(Triple &TargetTriple);
+  Error cloneAndEmitLineTable(const Triple &TargetTriple);
 
   /// Clone attribute location axpression.
   void cloneDieAttrExpression(const DWARFExpression &InputExpression,
@@ -731,6 +734,7 @@ class alignas(8) CompileUnit : public DwarfUnit {
 ArrayRef<dwarf::Attribute> getODRAttributes();
 
 } // end of namespace dwarflinker_parallel
+} // end of namespace dwarflinker
 } // end namespace llvm
 
-#endif // LLVM_LIB_DWARFLINKERPARALLEL_DWARFLINKERCOMPILEUNIT_H
+#endif // LLVM_LIB_DWARFLINKER_LLVM_DWARFLINKERCOMPILEUNIT_H
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFLinkerGlobalData.h b/llvm/lib/DWARFLinker/LLVM/DWARFLinkerGlobalData.h
similarity index 82%
rename from llvm/lib/DWARFLinkerParallel/DWARFLinkerGlobalData.h
rename to llvm/lib/DWARFLinker/LLVM/DWARFLinkerGlobalData.h
index 31724770093d64..621a879d7ab110 100644
--- a/llvm/lib/DWARFLinkerParallel/DWARFLinkerGlobalData.h
+++ b/llvm/lib/DWARFLinker/LLVM/DWARFLinkerGlobalData.h
@@ -6,18 +6,19 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_LIB_DWARFLINKERPARALLEL_DWARFLINKERGLOBALDATA_H
-#define LLVM_LIB_DWARFLINKERPARALLEL_DWARFLINKERGLOBALDATA_H
+#ifndef LLVM_LIB_DWARFLINKER_LLVM_DWARFLINKERGLOBALDATA_H
+#define LLVM_LIB_DWARFLINKER_LLVM_DWARFLINKERGLOBALDATA_H
 
 #include "TypePool.h"
-#include "llvm/DWARFLinkerParallel/DWARFLinker.h"
-#include "llvm/DWARFLinkerParallel/StringPool.h"
+#include "llvm/DWARFLinker/LLVM/DWARFLinker.h"
+#include "llvm/DWARFLinker/StringPool.h"
 #include "llvm/Support/PerThreadBumpPtrAllocator.h"
 
 namespace llvm {
 
 class DWARFDie;
 
+namespace dwarflinker {
 namespace dwarflinker_parallel {
 
 using TranslatorFuncTy = std::function<StringRef(StringRef)>;
@@ -58,13 +59,14 @@ struct DWARFLinkerOptions {
   unsigned Threads = 1;
 
   /// The accelerator table kinds
-  SmallVector<DWARFLinker::AccelTableKind, 1> AccelTables;
+  SmallVector<DWARFLinkerBase::AccelTableKind, 1> AccelTables;
 
   /// Prepend path for the clang modules.
   std::string PrependPath;
 
   /// input verification handler(it might be called asynchronously).
-  DWARFLinker::InputVerificationHandlerTy InputVerificationHandler = nullptr;
+  DWARFLinkerBase::InputVerificationHandlerTy InputVerificationHandler =
+      nullptr;
 
   /// A list of all .swiftinterface files referenced by the debug
   /// info, mapping Module name to path on disk. The entries need to
@@ -73,12 +75,12 @@ struct DWARFLinkerOptions {
   /// this is dsymutil specific fag.
   ///
   /// (it might be called asynchronously).
-  DWARFLinker::SwiftInterfacesMapTy *ParseableSwiftInterfaces = nullptr;
+  DWARFLinkerBase::SwiftInterfacesMapTy *ParseableSwiftInterfaces = nullptr;
 
   /// A list of remappings to apply to file paths.
   ///
   /// (it might be called asynchronously).
-  DWARFLinker::ObjectPrefixMapTy *ObjectPrefixMap = nullptr;
+  DWARFLinkerBase::ObjectPrefixMapTy *ObjectPrefixMap = nullptr;
 };
 
 class DWARFLinkerImpl;
@@ -144,6 +146,17 @@ class LinkingGlobalData {
     });
   }
 
+  void setTriple(const Triple &TargetTriple) {
+    this->TargetTriple = TargetTriple;
+  }
+
+  std::optional<std::reference_wrapper<const Triple>> getTriple() {
+    if (TargetTriple)
+      return std::cref(*TargetTriple);
+
+    return std::nullopt;
+  }
+
 protected:
   parallel::PerThreadBumpPtrAllocator Allocator;
   StringPool Strings;
@@ -151,9 +164,11 @@ class LinkingGlobalData {
   DWARFLinkerOptions Options;
   MessageHandlerTy WarningHandler;
   MessageHandlerTy ErrorHandler;
+  std::optional<Triple> TargetTriple;
 };
 
 } // end of namespace dwarflinker_parallel
+} // end of namespace dwarflinker
 } // end namespace llvm
 
-#endif // LLVM_LIB_DWARFLINKERPARALLEL_DWARFLINKERGLOBALDATA_H
+#endif // LLVM_LIB_DWARFLINKER_LLVM_DWARFLINKERGLOBALDATA_H
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFLinkerImpl.cpp b/llvm/lib/DWARFLinker/LLVM/DWARFLinkerImpl.cpp
similarity index 87%
rename from llvm/lib/DWARFLinkerParallel/DWARFLinkerImpl.cpp
rename to llvm/lib/DWARFLinker/LLVM/DWARFLinkerImpl.cpp
index c49b9ef0cdf989..3146b56e0ec5f9 100644
--- a/llvm/lib/DWARFLinkerParallel/DWARFLinkerImpl.cpp
+++ b/llvm/lib/DWARFLinker/LLVM/DWARFLinkerImpl.cpp
@@ -9,14 +9,15 @@
 #include "DWARFLinkerImpl.h"
 #include "DIEGenerator.h"
 #include "DependencyTracker.h"
-#include "Utils.h"
+#include "llvm/DWARFLinker/Utils.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/Parallel.h"
 #include "llvm/Support/ThreadPool.h"
 
-namespace llvm {
-namespace dwarflinker_parallel {
+using namespace llvm;
+using namespace dwarflinker;
+using namespace dwarflinker_parallel;
 
 DWARFLinkerImpl::DWARFLinkerImpl(MessageHandlerTy ErrorHandler,
                                  MessageHandlerTy WarningHandler,
@@ -31,11 +32,9 @@ DWARFLinkerImpl::DWARFLinkerImpl(MessageHandlerTy ErrorHandler,
 DWARFLinkerImpl::LinkContext::LinkContext(LinkingGlobalData &GlobalData,
                                           DWARFFile &File,
                                           StringMap<uint64_t> &ClangModules,
-                                          std::atomic<size_t> &UniqueUnitID,
-                                          std::optional<Triple> TargetTriple)
+                                          std::atomic<size_t> &UniqueUnitID)
     : OutputSections(GlobalData), InputDWARFFile(File),
-      ClangModules(ClangModules), TargetTriple(TargetTriple),
-      UniqueUnitID(UniqueUnitID) {
+      ClangModules(ClangModules), UniqueUnitID(UniqueUnitID) {
 
   if (File.Dwarf) {
     if (!File.Dwarf->compile_units().empty())
@@ -62,25 +61,10 @@ void DWARFLinkerImpl::LinkContext::addModulesCompileUnit(
   ModulesCompileUnits.emplace_back(std::move(Unit));
 }
 
-Error DWARFLinkerImpl::createEmitter(const Triple &TheTriple,
-                                     OutputFileType FileType,
-                                     raw_pwrite_stream &OutFile) {
-
-  TheDwarfEmitter = std::make_unique<DwarfEmitterImpl>(FileType, OutFile);
-
-  return TheDwarfEmitter->init(TheTriple, "__DWARF");
-}
-
-ExtraDwarfEmitter *DWARFLinkerImpl::getEmitter() {
-  return TheDwarfEmitter.get();
-}
-
 void DWARFLinkerImpl::addObjectFile(DWARFFile &File, ObjFileLoaderTy Loader,
                                     CompileUnitHandlerTy OnCUDieLoaded) {
   ObjectContexts.emplace_back(std::make_unique<LinkContext>(
-      GlobalData, File, ClangModules, UniqueUnitID,
-      (TheDwarfEmitter.get() == nullptr ? std::optional<Triple>(std::nullopt)
-                                        : TheDwarfEmitter->getTargetTriple())));
+      GlobalData, File, ClangModules, UniqueUnitID));
 
   if (ObjectContexts.back()->InputDWARFFile.Dwarf) {
     for (const std::unique_ptr<DWARFUnit> &CU :
@@ -116,8 +100,9 @@ Error DWARFLinkerImpl::link() {
                                     0, dwarf::DwarfFormat::DWARF32};
   llvm::endianness GlobalEndianness = llvm::endianness::native;
 
-  if (TheDwarfEmitter) {
-    GlobalEndianness = TheDwarfEmitter->getTargetTriple().isLittleEndian()
+  if (std::optional<std::reference_wrapper<const Triple>> CurTriple =
+          GlobalData.getTriple()) {
+    GlobalEndianness = (*CurTriple).get().isLittleEndian()
                            ? llvm::endianness::little
                            : llvm::endianness::big;
   }
@@ -146,7 +131,7 @@ Error DWARFLinkerImpl::link() {
     if (GlobalData.getOptions().VerifyInputDWARF)
       verifyInput(Context->InputDWARFFile);
 
-    if (!TheDwarfEmitter)
+    if (!GlobalData.getTriple())
       GlobalEndianness = Context->getEndianness();
     GlobalFormat.AddrSize =
         std::max(GlobalFormat.AddrSize, Context->getFormParams().AddrSize);
@@ -172,9 +157,9 @@ Error DWARFLinkerImpl::link() {
   }
 
   if (GlobalFormat.AddrSize == 0) {
-    if (TheDwarfEmitter)
-      GlobalFormat.AddrSize =
-          TheDwarfEmitter->getTargetTriple().isArch32Bit() ? 4 : 8;
+    if (std::optional<std::reference_wrapper<const Triple>> TargetTriple =
+            GlobalData.getTriple())
+      GlobalFormat.AddrSize = (*TargetTriple).get().isArch32Bit() ? 4 : 8;
     else
       GlobalFormat.AddrSize = 8;
   }
@@ -223,12 +208,10 @@ Error DWARFLinkerImpl::link() {
                                                   ->getValue()
                                                   .load()
                                                   ->Children.empty()) {
-    std::optional<Triple> OutTriple = TheDwarfEmitter.get() == nullptr
-                                          ? std::optional<Triple>(std::nullopt)
-                                          : TheDwarfEmitter->getTargetTriple();
-
-    if (Error Err = ArtificialTypeUnit.get()->finishCloningAndEmit(OutTriple))
-      return Err;
+    if (!GlobalData.getOptions().NoOutput)
+      if (Error Err = ArtificialTypeUnit.get()->finishCloningAndEmit(
+              (*GlobalData.getTriple()).get()))
+        return Err;
   }
 
   // At this stage each compile units are cloned to their own set of debug
@@ -256,7 +239,7 @@ Error DWARFLinkerImpl::validateAndUpdateOptions() {
     return createStringError(std::errc::invalid_argument,
                              "target DWARF version is not set");
 
-  GlobalData.Options.NoOutput = TheDwarfEmitter.get() == nullptr;
+  GlobalData.Options.NoOutput = !GlobalData.getTriple().has_value();
 
   if (GlobalData.getOptions().Verbose && GlobalData.getOptions().Threads != 1) {
     GlobalData.Options.Threads = 1;
@@ -486,108 +469,104 @@ Error DWARFLinkerImpl::LinkContext::link(TypeUnit *ArtificialTypeUnit) {
     return Error::success();
   }
 
-    OriginalDebugInfoSize = getInputDebugInfoSize();
-
-    // Create CompileUnit structures to keep information about source
-    // DWARFUnit`s, load line tables.
-    for (const auto &OrigCU : InputDWARFFile.Dwarf->compile_units()) {
-      // Load only unit DIE at this stage.
-      auto CUDie = OrigCU->getUnitDIE();
-      std::string PCMFile =
-          getPCMFile(CUDie, GlobalData.getOptions().ObjectPrefixMap);
-
-      // The !isClangModuleRef condition effectively skips over fully resolved
-      // skeleton units.
-      if (!CUDie || GlobalData.getOptions().UpdateIndexTablesOnly ||
-          !isClangModuleRef(CUDie, PCMFile, 0, true).first) {
-        CompileUnits.emplace_back(std::make_unique<CompileUnit>(
-            GlobalData, *OrigCU, UniqueUnitID.fetch_add(1), "", InputDWARFFile,
-            getUnitForOffset, OrigCU->getFormParams(), getEndianness()));
-
-        // Preload line table, as it can't be loaded asynchronously.
-        CompileUnits.back()->loadLineTable();
-      }
-    };
+  OriginalDebugInfoSize = getInputDebugInfoSize();
+
+  // Create CompileUnit structures to keep information about source
+  // DWARFUnit`s, load line tables.
+  for (const auto &OrigCU : InputDWARFFile.Dwarf->compile_units()) {
+    // Load only unit DIE at this stage.
+    auto CUDie = OrigCU->getUnitDIE();
+    std::string PCMFile =
+        getPCMFile(CUDie, GlobalData.getOptions().ObjectPrefixMap);
+
+    // The !isClangModuleRef condition effectively skips over fully resolved
+    // skeleton units.
+    if (!CUDie || GlobalData.getOptions().UpdateIndexTablesOnly ||
+        !isClangModuleRef(CUDie, PCMFile, 0, true).first) {
+      CompileUnits.emplace_back(std::make_unique<CompileUnit>(
+          GlobalData, *OrigCU, UniqueUnitID.fetch_add(1), "", InputDWARFFile,
+          getUnitForOffset, OrigCU->getFormParams(), getEndianness()));
+
+      // Preload line table, as it can't be loaded asynchronously.
+      CompileUnits.back()->loadLineTable();
+    }
+  };
 
-    HasNewInterconnectedCUs = false;
+  HasNewInterconnectedCUs = false;
 
-    // Link self-sufficient compile units and discover inter-connected compile
-    // units.
-    parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
-      linkSingleCompileUnit(*CU, ArtificialTypeUnit);
-    });
+  // Link self-sufficient compile units and discover inter-connected compile
+  // units.
+  parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
+    linkSingleCompileUnit(*CU, ArtificialTypeUnit);
+  });
 
-    // Link all inter-connected units.
-    if (HasNewInterconnectedCUs) {
-      InterCUProcessingStarted = true;
-
-      if (Error Err = finiteLoop([&]() -> Expected<bool> {
-            HasNewInterconnectedCUs = false;
-
-            // Load inter-connected units.
-            parallelForEach(
-                CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
-                  if (CU->isInterconnectedCU()) {
-                    CU->maybeResetToLoadedStage();
-                    linkSingleCompileUnit(*CU, ArtificialTypeUnit,
-                                          CompileUnit::Stage::Loaded);
-                  }
-                });
-
-            // Do liveness analysis for inter-connected units.
-            parallelForEach(CompileUnits,
-                            [&](std::unique_ptr<CompileUnit> &CU) {
-                              linkSingleCompileUnit(
-                                  *CU, ArtificialTypeUnit,
+  // Link all inter-connected units.
+  if (HasNewInterconnectedCUs) {
+    InterCUProcessingStarted = true;
+
+    if (Error Err = finiteLoop([&]() -> Expected<bool> {
+          HasNewInterconnectedCUs = false;
+
+          // Load inter-connected units.
+          parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
+            if (CU->isInterconnectedCU()) {
+              CU->maybeResetToLoadedStage();
+              linkSingleCompileUnit(*CU, ArtificialTypeUnit,
+                                    CompileUnit::Stage::Loaded);
+            }
+          });
+
+          // Do liveness analysis for inter-connected units.
+          parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
+            linkSingleCompileUnit(*CU, ArtificialTypeUnit,
                                   CompileUnit::Stage::LivenessAnalysisDone);
-                            });
+          });
 
-            return HasNewInterconnectedCUs.load();
-          }))
-        return Err;
+          return HasNewInterconnectedCUs.load();
+        }))
+      return Err;
 
-      // Update dependencies.
-      if (Error Err = finiteLoop([&]() -> Expected<bool> {
-            HasNewGlobalDependency = false;
-            parallelForEach(
-                CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
-                  linkSingleCompileUnit(
-                      *CU, ArtificialTypeUnit,
-                      CompileUnit::Stage::UpdateDependenciesCompleteness);
-                });
-            return HasNewGlobalDependency.load();
-          }))
-        return Err;
-      parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
-        if (CU->isInterconnectedCU() &&
-            CU->getStage() == CompileUnit::Stage::LivenessAnalysisDone)
-          CU->setStage(CompileUnit::Stage::UpdateDependenciesCompleteness);
-      });
+    // Update dependencies.
+    if (Error Err = finiteLoop([&]() -> Expected<bool> {
+          HasNewGlobalDependency = false;
+          parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
+            linkSingleCompileUnit(
+                *CU, ArtificialTypeUnit,
+                CompileUnit::Stage::UpdateDependenciesCompleteness);
+          });
+          return HasNewGlobalDependency.load();
+        }))
+      return Err;
+    parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
+      if (CU->isInterconnectedCU() &&
+          CU->getStage() == CompileUnit::Stage::LivenessAnalysisDone)
+        CU->setStage(CompileUnit::Stage::UpdateDependenciesCompleteness);
+    });
 
-      // Assign type names.
-      parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
-        linkSingleCompileUnit(*CU, ArtificialTypeUnit,
-                              CompileUnit::Stage::TypeNamesAssigned);
-      });
+    // Assign type names.
+    parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
+      linkSingleCompileUnit(*CU, ArtificialTypeUnit,
+                            CompileUnit::Stage::TypeNamesAssigned);
+    });
 
-      // Clone inter-connected units.
-      parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
-        linkSingleCompileUnit(*CU, ArtificialTypeUnit,
-                              CompileUnit::Stage::Cloned);
-      });
+    // Clone inter-connected units.
+    parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
+      linkSingleCompileUnit(*CU, ArtificialTypeUnit,
+                            CompileUnit::Stage::Cloned);
+    });
 
-      // Update patches for inter-connected units.
-      parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
-        linkSingleCompileUnit(*CU, ArtificialTypeUnit,
-                              CompileUnit::Stage::PatchesUpdated);
-      });
+    // Update patches for inter-connected units.
+    parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
+      linkSingleCompileUnit(*CU, ArtificialTypeUnit,
+                            CompileUnit::Stage::PatchesUpdated);
+    });
 
-      // Release data.
-      parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
-        linkSingleCompileUnit(*CU, ArtificialTypeUnit,
-                              CompileUnit::Stage::Cleaned);
-      });
-    }
+    // Release data.
+    parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
+      linkSingleCompileUnit(*CU, ArtificialTypeUnit,
+                            CompileUnit::Stage::Cleaned);
+    });
+  }
 
   if (GlobalData.getOptions().UpdateIndexTablesOnly) {
     // Emit Invariant sections.
@@ -692,7 +671,8 @@ void DWARFLinkerImpl::LinkContext::linkSingleCompileUnit(
           if (CU.isClangModule() ||
               GlobalData.getOptions().UpdateIndexTablesOnly ||
               CU.getContaingFile().Addresses->hasValidRelocs()) {
-            if (Error Err = CU.cloneAndEmit(TargetTriple, ArtificialTypeUnit))
+            if (Error Err =
+                    CU.cloneAndEmit(GlobalData.getTriple(), ArtificialTypeUnit))
               return std::move(Err);
           }
 
@@ -910,7 +890,7 @@ void DWARFLinkerImpl::printStatistic() {
     for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
       if (std::optional<SectionDescriptor *> DebugInfo =
               CU->tryGetSectionDescriptor(DebugSectionKind::DebugInfo))
-        AllDebugInfoSectionsSize += (*DebugInfo)->getContents().size();
+        AllDebugInfoSectionsSize += (*DebugInfo)->getContent().size();
 
     SizeByObject[Context->InputDWARFFile.FileName].Input =
         Context->OriginalDebugInfoSize;
@@ -1009,10 +989,26 @@ void DWARFLinkerImpl::assignOffsetsToStrings() {
 
 void DWARFLinkerImpl::assignOffsetsToSections() {
   std::array<uint64_t, SectionKindsNum> SectionSizesAccumulator = {0};
+  bool HasAbbreviations = false;
 
   forEachObjectSectionsSet([&](OutputSections &UnitSections) {
+    if (!HasAbbreviations) {
+      if (std::optional<SectionDescriptor *> Section =
+              UnitSections.tryGetSectionDescriptor(
+                  DebugSectionKind::DebugAbbrev))
+        if (!(*Section)->getContent().empty())
+          HasAbbreviations = true;
+    }
+
     UnitSections.assignSectionsOffsetAndAccumulateSize(SectionSizesAccumulator);
   });
+
+  if (!HasAbbreviations && !ObjectContexts.empty()) {
+    SectionDescriptor &DebugAbbrevSection =
+        ObjectContexts[0]->getOrCreateSectionDescriptor(
+            DebugSectionKind::DebugAbbrev);
+    DebugAbbrevSection.OS << '\0';
+  }
 }
 
 void DWARFLinkerImpl::forEachOutputString(
@@ -1156,21 +1152,23 @@ void DWARFLinkerImpl::emitCommonSectionsAndWriteCompileUnitsToTheOutput() {
                          AccelTableKind::DebugNames))
     CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugNames);
 
-  const Triple &TargetTriple = TheDwarfEmitter->getTargetTriple();
-
   // Emit .debug_str and .debug_line_str sections.
   TG.spawn([&]() { emitStringSections(); });
 
   if (llvm::is_contained(GlobalData.Options.AccelTables,
                          AccelTableKind::Apple)) {
     // Emit apple accelerator sections.
-    TG.spawn([&]() { emitAppleAcceleratorSections(TargetTriple); });
+    TG.spawn([&]() {
+      emitAppleAcceleratorSections((*GlobalData.getTriple()).get());
+    });
   }
 
   if (llvm::is_contained(GlobalData.Options.AccelTables,
                          AccelTableKind::DebugNames)) {
     // Emit .debug_names section.
-    TG.spawn([&]() { emitDWARFv5DebugNamesSection(TargetTriple); });
+    TG.spawn([&]() {
+      emitDWARFv5DebugNamesSection((*GlobalData.getTriple()).get());
+    });
   }
 
   // Write compile units to the output file.
@@ -1421,36 +1419,17 @@ void DWARFLinkerImpl::cleanupDataAfterDWARFOutputIsWritten() {
 }
 
 void DWARFLinkerImpl::writeCompileUnitsToTheOutput() {
-  bool HasAbbreviations = false;
-
   // Enumerate all sections and store them into the final emitter.
   forEachObjectSectionsSet([&](OutputSections &Sections) {
-    Sections.forEach([&](SectionDescriptor &OutSection) {
-      if (!HasAbbreviations && !OutSection.getContents().empty() &&
-          OutSection.getKind() == DebugSectionKind::DebugAbbrev)
-        HasAbbreviations = true;
-
+    Sections.forEach([&](std::shared_ptr<SectionDescriptor> OutSection) {
       // Emit section content.
-      TheDwarfEmitter->emitSectionContents(OutSection.getContents(),
-                                           OutSection.getName());
-      OutSection.clearSectionContent();
+      SectionHandler(OutSection);
     });
   });
-
-  if (!HasAbbreviations) {
-    const SmallVector<std::unique_ptr<DIEAbbrev>> Abbreviations;
-    TheDwarfEmitter->emitAbbrevs(Abbreviations, 3);
-  }
 }
 
 void DWARFLinkerImpl::writeCommonSectionsToTheOutput() {
-  CommonSections.forEach([&](SectionDescriptor &OutSection) {
-    // Emit section content.
-    TheDwarfEmitter->emitSectionContents(OutSection.getContents(),
-                                         OutSection.getName());
-    OutSection.clearSectionContent();
+  CommonSections.forEach([&](std::shared_ptr<SectionDescriptor> OutSection) {
+    SectionHandler(OutSection);
   });
 }
-
-} // end of namespace dwarflinker_parallel
-} // namespace llvm
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFLinkerImpl.h b/llvm/lib/DWARFLinker/LLVM/DWARFLinkerImpl.h
similarity index 94%
rename from llvm/lib/DWARFLinkerParallel/DWARFLinkerImpl.h
rename to llvm/lib/DWARFLinker/LLVM/DWARFLinkerImpl.h
index 60018eea121f20..8c71c4ce24ac80 100644
--- a/llvm/lib/DWARFLinkerParallel/DWARFLinkerImpl.h
+++ b/llvm/lib/DWARFLinker/LLVM/DWARFLinkerImpl.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_LIB_DWARFLINKERPARALLEL_DWARFLINKERIMPL_H
-#define LLVM_LIB_DWARFLINKERPARALLEL_DWARFLINKERIMPL_H
+#ifndef LLVM_LIB_DWARFLINKER_LLVM_DWARFLINKERPARALLELIMPL_H
+#define LLVM_LIB_DWARFLINKER_LLVM_DWARFLINKERPARALLELIMPL_H
 
 #include "DWARFEmitterImpl.h"
 #include "DWARFLinkerCompileUnit.h"
@@ -15,10 +15,11 @@
 #include "StringEntryToDwarfStringPoolEntryMap.h"
 #include "llvm/ADT/AddressRanges.h"
 #include "llvm/CodeGen/AccelTable.h"
-#include "llvm/DWARFLinkerParallel/DWARFLinker.h"
-#include "llvm/DWARFLinkerParallel/StringPool.h"
+#include "llvm/DWARFLinker/LLVM/DWARFLinker.h"
+#include "llvm/DWARFLinker/StringPool.h"
 
 namespace llvm {
+namespace dwarflinker {
 namespace dwarflinker_parallel {
 
 /// This class links debug info.
@@ -28,12 +29,6 @@ class DWARFLinkerImpl : public DWARFLinker {
                   MessageHandlerTy WarningHandler,
                   TranslatorFuncTy StringsTranslator);
 
-  /// Create debug info emitter.
-  Error createEmitter(const Triple &TheTriple, OutputFileType FileType,
-                      raw_pwrite_stream &OutFile) override;
-
-  ExtraDwarfEmitter *getEmitter() override;
-
   /// Add object file to be linked. Pre-load compile unit die. Call
   /// \p OnCUDieLoaded for each compile unit die. If specified \p File
   /// has reference to the Clang module then such module would be
@@ -48,6 +43,13 @@ class DWARFLinkerImpl : public DWARFLinker {
   /// Link debug info for added files.
   Error link() override;
 
+  /// Set output DWARF handler.
+  void setOutputDWARFHandler(const Triple &TargetTriple,
+                             SectionHandlerTy SectionHandler) override {
+    GlobalData.setTriple(TargetTriple);
+    this->SectionHandler = SectionHandler;
+  }
+
   /// \defgroup Methods setting various linking options:
   ///
   /// @{
@@ -189,8 +191,6 @@ class DWARFLinkerImpl : public DWARFLinker {
 
     StringMap<uint64_t> &ClangModules;
 
-    std::optional<Triple> TargetTriple;
-
     /// Flag indicating that new inter-connected compilation units were
     /// discovered. It is used for restarting units processing
     /// if new inter-connected units were found.
@@ -203,8 +203,7 @@ class DWARFLinkerImpl : public DWARFLinker {
 
     LinkContext(LinkingGlobalData &GlobalData, DWARFFile &File,
                 StringMap<uint64_t> &ClangModules,
-                std::atomic<size_t> &UniqueUnitID,
-                std::optional<Triple> TargetTriple);
+                std::atomic<size_t> &UniqueUnitID);
 
     /// Check whether specified \p CUDie is a Clang module reference.
     /// if \p Quiet is false then display error messages.
@@ -364,7 +363,7 @@ class DWARFLinkerImpl : public DWARFLinker {
   OutputSections CommonSections;
 
   /// The emitter of final dwarf file.
-  std::unique_ptr<DwarfEmitterImpl> TheDwarfEmitter;
+  SectionHandlerTy SectionHandler = nullptr;
 
   /// Overall compile units number.
   uint64_t OverallNumberOfCU = 0;
@@ -375,6 +374,7 @@ class DWARFLinkerImpl : public DWARFLinker {
 };
 
 } // end namespace dwarflinker_parallel
+} // end namespace dwarflinker
 } // end namespace llvm
 
-#endif // LLVM_LIB_DWARFLINKERPARALLEL_DWARFLINKERIMPL_H
+#endif // LLVM_LIB_DWARFLINKER_LLVM_DWARFLINKERPARALLELIMPL_H
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFLinkerTypeUnit.cpp b/llvm/lib/DWARFLinker/LLVM/DWARFLinkerTypeUnit.cpp
similarity index 99%
rename from llvm/lib/DWARFLinkerParallel/DWARFLinkerTypeUnit.cpp
rename to llvm/lib/DWARFLinker/LLVM/DWARFLinkerTypeUnit.cpp
index 9d5c213085c293..ff0ed76fa22d1c 100644
--- a/llvm/lib/DWARFLinkerParallel/DWARFLinkerTypeUnit.cpp
+++ b/llvm/lib/DWARFLinker/LLVM/DWARFLinkerTypeUnit.cpp
@@ -12,7 +12,8 @@
 #include "llvm/Support/LEB128.h"
 
 using namespace llvm;
-using namespace llvm::dwarflinker_parallel;
+using namespace dwarflinker;
+using namespace dwarflinker_parallel;
 
 TypeUnit::TypeUnit(LinkingGlobalData &GlobalData, unsigned ID,
                    std::optional<uint16_t> Language, dwarf::FormParams Format,
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFLinkerTypeUnit.h b/llvm/lib/DWARFLinker/LLVM/DWARFLinkerTypeUnit.h
similarity index 95%
rename from llvm/lib/DWARFLinkerParallel/DWARFLinkerTypeUnit.h
rename to llvm/lib/DWARFLinker/LLVM/DWARFLinkerTypeUnit.h
index 97e620eee0c424..671a7328adeb19 100644
--- a/llvm/lib/DWARFLinkerParallel/DWARFLinkerTypeUnit.h
+++ b/llvm/lib/DWARFLinker/LLVM/DWARFLinkerTypeUnit.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_DWARFLINKERPARALLEL_DWARFLINKERTYPEUNIT_H
-#define LLVM_DWARFLINKERPARALLEL_DWARFLINKERTYPEUNIT_H
+#ifndef LLVM_DWARFLINKER_LLVM_DWARFLINKERTYPEUNIT_H
+#define LLVM_DWARFLINKER_LLVM_DWARFLINKERTYPEUNIT_H
 
 #include "DWARFLinkerUnit.h"
 #include "llvm/CodeGen/DIE.h"
@@ -15,6 +15,7 @@
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
 
 namespace llvm {
+namespace dwarflinker {
 namespace dwarflinker_parallel {
 
 /// Type Unit is used to represent an artificial compilation unit
@@ -133,6 +134,7 @@ class TypeUnit : public DwarfUnit {
 };
 
 } // end of namespace dwarflinker_parallel
+} // end of namespace dwarflinker
 } // end namespace llvm
 
-#endif // LLVM_DWARFLINKERPARALLEL_DWARFLINKERTYPEUNIT_H
+#endif // LLVM_DWARFLINKER_LLVM_DWARFLINKERTYPEUNIT_H
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.cpp b/llvm/lib/DWARFLinker/LLVM/DWARFLinkerUnit.cpp
similarity index 89%
rename from llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.cpp
rename to llvm/lib/DWARFLinker/LLVM/DWARFLinkerUnit.cpp
index b1da1900d65ef7..800b549c9a7fbe 100644
--- a/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.cpp
+++ b/llvm/lib/DWARFLinker/LLVM/DWARFLinkerUnit.cpp
@@ -10,10 +10,11 @@
 #include "DWARFEmitterImpl.h"
 #include "DebugLineSectionEmitter.h"
 
-namespace llvm {
-namespace dwarflinker_parallel {
+using namespace llvm;
+using namespace dwarflinker;
+using namespace dwarflinker_parallel;
 
-void DwarfUnit::assignAbbrev(DIEAbbrev &Abbrev) {
+void dwarflinker_parallel::DwarfUnit::assignAbbrev(DIEAbbrev &Abbrev) {
   // Check the set for priors.
   FoldingSetNodeID ID;
   Abbrev.Profile(ID);
@@ -37,7 +38,7 @@ void DwarfUnit::assignAbbrev(DIEAbbrev &Abbrev) {
   }
 }
 
-Error DwarfUnit::emitAbbreviations() {
+Error dwarflinker_parallel::DwarfUnit::emitAbbreviations() {
   const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs = getAbbreviations();
   if (Abbrevs.empty())
     return Error::success();
@@ -55,8 +56,8 @@ Error DwarfUnit::emitAbbreviations() {
   return Error::success();
 }
 
-void DwarfUnit::emitDwarfAbbrevEntry(const DIEAbbrev &Abbrev,
-                                     SectionDescriptor &AbbrevSection) {
+void dwarflinker_parallel::DwarfUnit::emitDwarfAbbrevEntry(
+    const DIEAbbrev &Abbrev, SectionDescriptor &AbbrevSection) {
   // Emit the abbreviations code (base 1 index.)
   encodeULEB128(Abbrev.getNumber(), AbbrevSection.OS);
 
@@ -88,7 +89,8 @@ void DwarfUnit::emitDwarfAbbrevEntry(const DIEAbbrev &Abbrev,
   encodeULEB128(0, AbbrevSection.OS);
 }
 
-Error DwarfUnit::emitDebugInfo(const Triple &TargetTriple) {
+Error dwarflinker_parallel::DwarfUnit::emitDebugInfo(
+    const Triple &TargetTriple) {
   DIE *OutUnitDIE = getOutUnitDIE();
   if (OutUnitDIE == nullptr)
     return Error::success();
@@ -119,14 +121,14 @@ Error DwarfUnit::emitDebugInfo(const Triple &TargetTriple) {
   return Error::success();
 }
 
-Error DwarfUnit::emitDebugLine(const Triple &TargetTriple,
-                               const DWARFDebugLine::LineTable &OutLineTable) {
+Error dwarflinker_parallel::DwarfUnit::emitDebugLine(
+    const Triple &TargetTriple, const DWARFDebugLine::LineTable &OutLineTable) {
   DebugLineSectionEmitter DebugLineEmitter(TargetTriple, *this);
 
   return DebugLineEmitter.emit(OutLineTable);
 }
 
-Error DwarfUnit::emitDebugStringOffsetSection() {
+Error dwarflinker_parallel::DwarfUnit::emitDebugStringOffsetSection() {
   if (getVersion() < 5)
     return Error::success();
 
@@ -171,9 +173,9 @@ Error DwarfUnit::emitDebugStringOffsetSection() {
 /// Emit the pubnames or pubtypes section contribution for \p
 /// Unit into \p Sec. The data is provided in \p Info.
 std::optional<uint64_t>
-DwarfUnit::emitPubAcceleratorEntry(SectionDescriptor &OutSection,
-                                   const DwarfUnit::AccelInfo &Info,
-                                   std::optional<uint64_t> LengthOffset) {
+dwarflinker_parallel::DwarfUnit::emitPubAcceleratorEntry(
+    SectionDescriptor &OutSection, const DwarfUnit::AccelInfo &Info,
+    std::optional<uint64_t> LengthOffset) {
   if (!LengthOffset) {
     // Emit the header.
     OutSection.emitIntVal(0xBADDEF,
@@ -198,7 +200,7 @@ DwarfUnit::emitPubAcceleratorEntry(SectionDescriptor &OutSection,
 }
 
 /// Emit .debug_pubnames and .debug_pubtypes for \p Unit.
-void DwarfUnit::emitPubAccelerators() {
+void dwarflinker_parallel::DwarfUnit::emitPubAccelerators() {
   std::optional<uint64_t> NamesLengthOffset;
   std::optional<uint64_t> TypesLengthOffset;
 
@@ -245,6 +247,3 @@ void DwarfUnit::emitPubAccelerators() {
                      OutSection.OS.tell() - *TypesLengthOffset);
   }
 }
-
-} // end of namespace dwarflinker_parallel
-} // end of namespace llvm
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.h b/llvm/lib/DWARFLinker/LLVM/DWARFLinkerUnit.h
similarity index 94%
rename from llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.h
rename to llvm/lib/DWARFLinker/LLVM/DWARFLinkerUnit.h
index 9640a8ee711eb0..63182ee6d58982 100644
--- a/llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.h
+++ b/llvm/lib/DWARFLinker/LLVM/DWARFLinkerUnit.h
@@ -6,19 +6,20 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_LIB_DWARFLINKERPARALLEL_DWARFLINKERUNIT_H
-#define LLVM_LIB_DWARFLINKERPARALLEL_DWARFLINKERUNIT_H
+#ifndef LLVM_LIB_DWARFLINKER_LLVM_DWARFLINKERUNIT_H
+#define LLVM_LIB_DWARFLINKER_LLVM_DWARFLINKERUNIT_H
 
 #include "DWARFLinkerGlobalData.h"
-#include "IndexedValuesMap.h"
 #include "OutputSections.h"
 #include "llvm/CodeGen/DIE.h"
-#include "llvm/DWARFLinkerParallel/DWARFLinker.h"
-#include "llvm/DWARFLinkerParallel/StringPool.h"
+#include "llvm/DWARFLinker/IndexedValuesMap.h"
+#include "llvm/DWARFLinker/LLVM/DWARFLinker.h"
+#include "llvm/DWARFLinker/StringPool.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
 #include "llvm/Support/LEB128.h"
 
 namespace llvm {
+namespace dwarflinker {
 namespace dwarflinker_parallel {
 
 class DwarfUnit;
@@ -216,6 +217,7 @@ inline bool isODRLanguage(uint16_t Language) {
 }
 
 } // end of namespace dwarflinker_parallel
+} // end of namespace dwarflinker
 } // end namespace llvm
 
-#endif // LLVM_LIB_DWARFLINKERPARALLEL_DWARFLINKERUNIT_H
+#endif // LLVM_LIB_DWARFLINKER_LLVM_DWARFLINKERUNIT_H
diff --git a/llvm/lib/DWARFLinkerParallel/DebugLineSectionEmitter.h b/llvm/lib/DWARFLinker/LLVM/DebugLineSectionEmitter.h
similarity index 97%
rename from llvm/lib/DWARFLinkerParallel/DebugLineSectionEmitter.h
rename to llvm/lib/DWARFLinker/LLVM/DebugLineSectionEmitter.h
index fc7f8cbc4a8e7b..213d7a555a1484 100644
--- a/llvm/lib/DWARFLinkerParallel/DebugLineSectionEmitter.h
+++ b/llvm/lib/DWARFLinker/LLVM/DebugLineSectionEmitter.h
@@ -6,17 +6,18 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_LIB_DWARFLINKERPARALLEL_DEBUGLINESECTIONEMITTER_H
-#define LLVM_LIB_DWARFLINKERPARALLEL_DEBUGLINESECTIONEMITTER_H
+#ifndef LLVM_LIB_DWARFLINKER_LLVM_DEBUGLINESECTIONEMITTER_H
+#define LLVM_LIB_DWARFLINKER_LLVM_DEBUGLINESECTIONEMITTER_H
 
 #include "DWARFEmitterImpl.h"
-#include "llvm/DWARFLinkerParallel/AddressesMap.h"
-#include "llvm/DWARFLinkerParallel/DWARFLinker.h"
+#include "llvm/DWARFLinker/AddressesMap.h"
+#include "llvm/DWARFLinker/LLVM/DWARFLinker.h"
 #include "llvm/DebugInfo/DWARF/DWARFObject.h"
 #include "llvm/MC/MCTargetOptionsCommandFlags.h"
 #include "llvm/MC/TargetRegistry.h"
 
 namespace llvm {
+namespace dwarflinker {
 namespace dwarflinker_parallel {
 
 /// This class emits specified line table into the .debug_line section.
@@ -379,6 +380,7 @@ class DebugLineSectionEmitter {
 };
 
 } // end of namespace dwarflinker_parallel
+} // end of namespace dwarflinker
 } // end namespace llvm
 
-#endif // LLVM_LIB_DWARFLINKERPARALLEL_DEBUGLINESECTIONEMITTER_H
+#endif // LLVM_LIB_DWARFLINKER_LLVM_DEBUGLINESECTIONEMITTER_H
diff --git a/llvm/lib/DWARFLinkerParallel/DependencyTracker.cpp b/llvm/lib/DWARFLinker/LLVM/DependencyTracker.cpp
similarity index 99%
rename from llvm/lib/DWARFLinkerParallel/DependencyTracker.cpp
rename to llvm/lib/DWARFLinker/LLVM/DependencyTracker.cpp
index 052eb6cf57d41e..f5f44978dc83d9 100644
--- a/llvm/lib/DWARFLinkerParallel/DependencyTracker.cpp
+++ b/llvm/lib/DWARFLinker/LLVM/DependencyTracker.cpp
@@ -9,8 +9,9 @@
 #include "DependencyTracker.h"
 #include "llvm/Support/FormatVariadic.h"
 
-namespace llvm {
-namespace dwarflinker_parallel {
+using namespace llvm;
+using namespace dwarflinker;
+using namespace dwarflinker_parallel;
 
 /// A broken link in the keep chain. By recording both the parent and the child
 /// we can show only broken links for DIEs with multiple children.
@@ -834,6 +835,3 @@ bool DependencyTracker::isLiveSubprogramEntry(const UnitEntryPairTy &Entry) {
   Entry.CU->addFunctionRange(*LowPc, *HighPc, *RelocAdjustment);
   return true;
 }
-
-} // end of namespace dwarflinker_parallel
-} // namespace llvm
diff --git a/llvm/lib/DWARFLinkerParallel/DependencyTracker.h b/llvm/lib/DWARFLinker/LLVM/DependencyTracker.h
similarity index 97%
rename from llvm/lib/DWARFLinkerParallel/DependencyTracker.h
rename to llvm/lib/DWARFLinker/LLVM/DependencyTracker.h
index b0b6ad3a1e8cfa..84247b6ba90167 100644
--- a/llvm/lib/DWARFLinkerParallel/DependencyTracker.h
+++ b/llvm/lib/DWARFLinker/LLVM/DependencyTracker.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_LIB_DWARFLINKERPARALLEL_DEPENDENCYTRACKER_H
-#define LLVM_LIB_DWARFLINKERPARALLEL_DEPENDENCYTRACKER_H
+#ifndef LLVM_LIB_DWARFLINKER_LLVM_DEPENDENCYTRACKER_H
+#define LLVM_LIB_DWARFLINKER_LLVM_DEPENDENCYTRACKER_H
 
 #include "DWARFLinkerCompileUnit.h"
 #include "llvm/ADT/PointerIntPair.h"
@@ -17,6 +17,7 @@ namespace llvm {
 class DWARFDebugInfoEntry;
 class DWARFDie;
 
+namespace dwarflinker {
 namespace dwarflinker_parallel {
 
 /// This class discovers DIEs dependencies: marks "live" DIEs, marks DIE
@@ -267,6 +268,7 @@ class DependencyTracker {
 };
 
 } // end namespace dwarflinker_parallel
+} // end namespace dwarflinker
 } // end namespace llvm
 
-#endif // LLVM_LIB_DWARFLINKERPARALLEL_DEPENDENCYTRACKER_H
+#endif // LLVM_LIB_DWARFLINKER_LLVM_DEPENDENCYTRACKER_H
diff --git a/llvm/lib/DWARFLinkerParallel/OutputSections.cpp b/llvm/lib/DWARFLinker/LLVM/OutputSections.cpp
similarity index 77%
rename from llvm/lib/DWARFLinkerParallel/OutputSections.cpp
rename to llvm/lib/DWARFLinker/LLVM/OutputSections.cpp
index 9c3e3ebd220aaf..ba1a387071d280 100644
--- a/llvm/lib/DWARFLinkerParallel/OutputSections.cpp
+++ b/llvm/lib/DWARFLinker/LLVM/OutputSections.cpp
@@ -9,74 +9,10 @@
 #include "OutputSections.h"
 #include "DWARFLinkerCompileUnit.h"
 #include "DWARFLinkerTypeUnit.h"
-#include "llvm/ADT/StringSwitch.h"
 
-namespace llvm {
-namespace dwarflinker_parallel {
-
-static constexpr StringLiteral SectionNames[SectionKindsNum] = {
-    "debug_info",     "debug_line",     "debug_frame",       "debug_ranges",
-    "debug_rnglists", "debug_loc",      "debug_loclists",    "debug_aranges",
-    "debug_abbrev",   "debug_macinfo",  "debug_macro",       "debug_addr",
-    "debug_str",      "debug_line_str", "debug_str_offsets", "debug_pubnames",
-    "debug_pubtypes", "debug_names",    "apple_names",       "apple_namespac",
-    "apple_objc",     "apple_types"};
-
-const StringLiteral &getSectionName(DebugSectionKind SectionKind) {
-  return SectionNames[static_cast<uint8_t>(SectionKind)];
-}
-
-std::optional<DebugSectionKind> parseDebugTableName(llvm::StringRef SecName) {
-  return llvm::StringSwitch<std::optional<DebugSectionKind>>(
-             SecName.substr(SecName.find_first_not_of("._")))
-      .Case(getSectionName(DebugSectionKind::DebugInfo),
-            DebugSectionKind::DebugInfo)
-      .Case(getSectionName(DebugSectionKind::DebugLine),
-            DebugSectionKind::DebugLine)
-      .Case(getSectionName(DebugSectionKind::DebugFrame),
-            DebugSectionKind::DebugFrame)
-      .Case(getSectionName(DebugSectionKind::DebugRange),
-            DebugSectionKind::DebugRange)
-      .Case(getSectionName(DebugSectionKind::DebugRngLists),
-            DebugSectionKind::DebugRngLists)
-      .Case(getSectionName(DebugSectionKind::DebugLoc),
-            DebugSectionKind::DebugLoc)
-      .Case(getSectionName(DebugSectionKind::DebugLocLists),
-            DebugSectionKind::DebugLocLists)
-      .Case(getSectionName(DebugSectionKind::DebugARanges),
-            DebugSectionKind::DebugARanges)
-      .Case(getSectionName(DebugSectionKind::DebugAbbrev),
-            DebugSectionKind::DebugAbbrev)
-      .Case(getSectionName(DebugSectionKind::DebugMacinfo),
-            DebugSectionKind::DebugMacinfo)
-      .Case(getSectionName(DebugSectionKind::DebugMacro),
-            DebugSectionKind::DebugMacro)
-      .Case(getSectionName(DebugSectionKind::DebugAddr),
-            DebugSectionKind::DebugAddr)
-      .Case(getSectionName(DebugSectionKind::DebugStr),
-            DebugSectionKind::DebugStr)
-      .Case(getSectionName(DebugSectionKind::DebugLineStr),
-            DebugSectionKind::DebugLineStr)
-      .Case(getSectionName(DebugSectionKind::DebugStrOffsets),
-            DebugSectionKind::DebugStrOffsets)
-      .Case(getSectionName(DebugSectionKind::DebugPubNames),
-            DebugSectionKind::DebugPubNames)
-      .Case(getSectionName(DebugSectionKind::DebugPubTypes),
-            DebugSectionKind::DebugPubTypes)
-      .Case(getSectionName(DebugSectionKind::DebugNames),
-            DebugSectionKind::DebugNames)
-      .Case(getSectionName(DebugSectionKind::AppleNames),
-            DebugSectionKind::AppleNames)
-      .Case(getSectionName(DebugSectionKind::AppleNamespaces),
-            DebugSectionKind::AppleNamespaces)
-      .Case(getSectionName(DebugSectionKind::AppleObjC),
-            DebugSectionKind::AppleObjC)
-      .Case(getSectionName(DebugSectionKind::AppleTypes),
-            DebugSectionKind::AppleTypes)
-      .Default(std::nullopt);
-
-  return std::nullopt;
-}
+using namespace llvm;
+using namespace dwarflinker;
+using namespace dwarflinker_parallel;
 
 DebugDieRefPatch::DebugDieRefPatch(uint64_t PatchOffset, CompileUnit *SrcCU,
                                    CompileUnit *RefCU, uint32_t RefIdx)
@@ -136,18 +72,18 @@ void SectionDescriptor::clearAllSectionData() {
   ListDebugTypeStrPatch.erase();
 }
 
-void SectionDescriptor::clearSectionContent() { Contents = OutSectionDataTy(); }
+void SectionDescriptor::clearSectionContent() { Content = OutSectionDataTy(); }
 
 void SectionDescriptor::setSizesForSectionCreatedByAsmPrinter() {
-  if (Contents.empty())
+  if (Content.empty())
     return;
 
-  MemoryBufferRef Mem(Contents, "obj");
+  MemoryBufferRef Mem(Content, "obj");
   Expected<std::unique_ptr<object::ObjectFile>> Obj =
       object::ObjectFile::createObjectFile(Mem);
   if (!Obj) {
     consumeError(Obj.takeError());
-    Contents.clear();
+    Content.clear();
     return;
   }
 
@@ -163,12 +99,12 @@ void SectionDescriptor::setSizesForSectionCreatedByAsmPrinter() {
         Expected<StringRef> Data = Sect.getContents();
         if (!Data) {
           consumeError(SectNameOrErr.takeError());
-          Contents.clear();
+          Content.clear();
           return;
         }
 
         SectionOffsetInsideAsmPrinterOutputStart =
-            Data->data() - Contents.data();
+            Data->data() - Content.data();
         SectionOffsetInsideAsmPrinterOutputEnd =
             SectionOffsetInsideAsmPrinterOutputStart + Data->size();
       }
@@ -283,22 +219,22 @@ void SectionDescriptor::apply(uint64_t PatchOffset, dwarf::Form AttrForm,
 }
 
 uint64_t SectionDescriptor::getIntVal(uint64_t PatchOffset, unsigned Size) {
-  assert(PatchOffset < getContents().size());
+  assert(PatchOffset < getContent().size());
   switch (Size) {
   case 1: {
     return *reinterpret_cast<const uint8_t *>(
-        (getContents().data() + PatchOffset));
+        (getContent().data() + PatchOffset));
   }
   case 2: {
-    return support::endian::read16(getContents().data() + PatchOffset,
+    return support::endian::read16(getContent().data() + PatchOffset,
                                    Endianess);
   }
   case 4: {
-    return support::endian::read32(getContents().data() + PatchOffset,
+    return support::endian::read32(getContent().data() + PatchOffset,
                                    Endianess);
   }
   case 8: {
-    return support::endian::read64(getContents().data() + PatchOffset,
+    return support::endian::read64(getContent().data() + PatchOffset,
                                    Endianess);
   }
   }
@@ -308,27 +244,27 @@ uint64_t SectionDescriptor::getIntVal(uint64_t PatchOffset, unsigned Size) {
 
 void SectionDescriptor::applyIntVal(uint64_t PatchOffset, uint64_t Val,
                                     unsigned Size) {
-  assert(PatchOffset < getContents().size());
+  assert(PatchOffset < getContent().size());
 
   switch (Size) {
   case 1: {
     support::endian::write(
-        const_cast<char *>(getContents().data() + PatchOffset),
+        const_cast<char *>(getContent().data() + PatchOffset),
         static_cast<uint8_t>(Val), Endianess);
   } break;
   case 2: {
     support::endian::write(
-        const_cast<char *>(getContents().data() + PatchOffset),
+        const_cast<char *>(getContent().data() + PatchOffset),
         static_cast<uint16_t>(Val), Endianess);
   } break;
   case 4: {
     support::endian::write(
-        const_cast<char *>(getContents().data() + PatchOffset),
+        const_cast<char *>(getContent().data() + PatchOffset),
         static_cast<uint32_t>(Val), Endianess);
   } break;
   case 8: {
     support::endian::write(
-        const_cast<char *>(getContents().data() + PatchOffset),
+        const_cast<char *>(getContent().data() + PatchOffset),
         static_cast<uint64_t>(Val), Endianess);
   } break;
   default:
@@ -337,26 +273,24 @@ void SectionDescriptor::applyIntVal(uint64_t PatchOffset, uint64_t Val,
 }
 
 void SectionDescriptor::applyULEB128(uint64_t PatchOffset, uint64_t Val) {
-  assert(PatchOffset < getContents().size());
+  assert(PatchOffset < getContent().size());
 
   uint8_t ULEB[16];
   uint8_t DestSize = Format.getDwarfOffsetByteSize() + 1;
   uint8_t RealSize = encodeULEB128(Val, ULEB, DestSize);
 
-  memcpy(const_cast<char *>(getContents().data() + PatchOffset), ULEB,
-         RealSize);
+  memcpy(const_cast<char *>(getContent().data() + PatchOffset), ULEB, RealSize);
 }
 
 /// Writes integer value \p Val of SLEB128 format by specified \p PatchOffset.
 void SectionDescriptor::applySLEB128(uint64_t PatchOffset, uint64_t Val) {
-  assert(PatchOffset < getContents().size());
+  assert(PatchOffset < getContent().size());
 
   uint8_t SLEB[16];
   uint8_t DestSize = Format.getDwarfOffsetByteSize() + 1;
   uint8_t RealSize = encodeSLEB128(Val, SLEB, DestSize);
 
-  memcpy(const_cast<char *>(getContents().data() + PatchOffset), SLEB,
-         RealSize);
+  memcpy(const_cast<char *>(getContent().data() + PatchOffset), SLEB, RealSize);
 }
 
 void OutputSections::applyPatches(
@@ -527,6 +461,3 @@ void OutputSections::applyPatches(
     Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);
   });
 }
-
-} // end of namespace dwarflinker_parallel
-} // end of namespace llvm
diff --git a/llvm/lib/DWARFLinkerParallel/OutputSections.h b/llvm/lib/DWARFLinker/LLVM/OutputSections.h
similarity index 84%
rename from llvm/lib/DWARFLinkerParallel/OutputSections.h
rename to llvm/lib/DWARFLinker/LLVM/OutputSections.h
index f23b2efb869da8..2ba17cef835f40 100644
--- a/llvm/lib/DWARFLinkerParallel/OutputSections.h
+++ b/llvm/lib/DWARFLinker/LLVM/OutputSections.h
@@ -6,16 +6,17 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_LIB_DWARFLINKERPARALLEL_OUTPUTSECTIONS_H
-#define LLVM_LIB_DWARFLINKERPARALLEL_OUTPUTSECTIONS_H
+#ifndef LLVM_LIB_DWARFLINKER_LLVM_OUTPUTSECTIONS_H
+#define LLVM_LIB_DWARFLINKER_LLVM_OUTPUTSECTIONS_H
 
-#include "ArrayList.h"
 #include "StringEntryToDwarfStringPoolEntryMap.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/CodeGen/DwarfStringPoolEntry.h"
-#include "llvm/DWARFLinkerParallel/StringPool.h"
+#include "llvm/DWARFLinker/ArrayList.h"
+#include "llvm/DWARFLinker/LLVM/DWARFLinker.h"
+#include "llvm/DWARFLinker/StringPool.h"
 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
 #include "llvm/DebugInfo/DWARF/DWARFObject.h"
 #include "llvm/Object/ObjectFile.h"
@@ -29,45 +30,11 @@
 #include <cstdint>
 
 namespace llvm {
+namespace dwarflinker {
 namespace dwarflinker_parallel {
 
 class TypeUnit;
 
-/// List of tracked debug tables.
-enum class DebugSectionKind : uint8_t {
-  DebugInfo = 0,
-  DebugLine,
-  DebugFrame,
-  DebugRange,
-  DebugRngLists,
-  DebugLoc,
-  DebugLocLists,
-  DebugARanges,
-  DebugAbbrev,
-  DebugMacinfo,
-  DebugMacro,
-  DebugAddr,
-  DebugStr,
-  DebugLineStr,
-  DebugStrOffsets,
-  DebugPubNames,
-  DebugPubTypes,
-  DebugNames,
-  AppleNames,
-  AppleNamespaces,
-  AppleObjC,
-  AppleTypes,
-  NumberOfEnumEntries // must be last
-};
-constexpr static size_t SectionKindsNum =
-    static_cast<size_t>(DebugSectionKind::NumberOfEnumEntries);
-
-/// Recognise the table name and match it with the DebugSectionKind.
-std::optional<DebugSectionKind> parseDebugTableName(StringRef Name);
-
-/// Return the name of the section.
-const StringLiteral &getSectionName(DebugSectionKind SectionKind);
-
 /// There are fields(sizes, offsets) which should be updated after
 /// sections are generated. To remember offsets and related data
 /// the descendants of SectionPatch structure should be used.
@@ -183,12 +150,13 @@ class OutputSections;
 
 /// This structure is used to keep data of the concrete section.
 /// Like data bits, list of patches, format.
-struct SectionDescriptor {
+struct SectionDescriptor : public SectionDescriptorBase {
   friend OutputSections;
 
   SectionDescriptor(DebugSectionKind SectionKind, LinkingGlobalData &GlobalData,
                     dwarf::FormParams Format, llvm::endianness Endianess)
-      : OS(Contents), ListDebugStrPatch(&GlobalData.getAllocator()),
+      : SectionDescriptorBase(SectionKind, Format, Endianess), OS(Content),
+        ListDebugStrPatch(&GlobalData.getAllocator()),
         ListDebugLineStrPatch(&GlobalData.getAllocator()),
         ListDebugRangePatch(&GlobalData.getAllocator()),
         ListDebugLocPatch(&GlobalData.getAllocator()),
@@ -200,10 +168,9 @@ struct SectionDescriptor {
         ListDebugTypeStrPatch(&GlobalData.getAllocator()),
         ListDebugTypeLineStrPatch(&GlobalData.getAllocator()),
         ListDebugTypeDeclFilePatch(&GlobalData.getAllocator()),
-        GlobalData(GlobalData), SectionKind(SectionKind), Format(Format),
-        Endianess(Endianess) {}
+        GlobalData(GlobalData) {}
 
-  /// Erase whole section contents(data bits, list of patches).
+  /// Erase whole section content(data bits, list of patches).
   void clearAllSectionData();
 
   /// Erase only section output data bits.
@@ -252,12 +219,12 @@ struct SectionDescriptor {
   void setSizesForSectionCreatedByAsmPrinter();
 
   /// Returns section content.
-  StringRef getContents() {
+  StringRef getContent() override {
     if (SectionOffsetInsideAsmPrinterOutputStart == 0)
-      return StringRef(Contents.data(), Contents.size());
+      return StringRef(Content.data(), Content.size());
 
-    return Contents.slice(SectionOffsetInsideAsmPrinterOutputStart,
-                          SectionOffsetInsideAsmPrinterOutputEnd);
+    return Content.slice(SectionOffsetInsideAsmPrinterOutputStart,
+                         SectionOffsetInsideAsmPrinterOutputEnd);
   }
 
   /// Emit unit length into the current section contents.
@@ -298,18 +265,6 @@ struct SectionDescriptor {
   /// Write specified \p Value of \p AttrForm to the \p PatchOffset.
   void apply(uint64_t PatchOffset, dwarf::Form AttrForm, uint64_t Val);
 
-  /// Returns section kind.
-  DebugSectionKind getKind() { return SectionKind; }
-
-  /// Returns section name.
-  const StringLiteral &getName() const { return getSectionName(SectionKind); }
-
-  /// Returns endianess used by section.
-  llvm::endianness getEndianess() const { return Endianess; }
-
-  /// Returns FormParams used by section.
-  dwarf::FormParams getFormParams() const { return Format; }
-
   /// Returns integer value of \p Size located by specified \p PatchOffset.
   uint64_t getIntVal(uint64_t PatchOffset, unsigned Size);
 
@@ -331,21 +286,14 @@ struct SectionDescriptor {
 
   LinkingGlobalData &GlobalData;
 
-  /// The section kind.
-  DebugSectionKind SectionKind = DebugSectionKind::NumberOfEnumEntries;
-
   /// Section data bits.
-  OutSectionDataTy Contents;
+  OutSectionDataTy Content;
 
   /// Some sections are generated using AsmPrinter. The real section data
   /// located inside elf file in that case. Following fields points to the
   /// real section content inside elf file.
   size_t SectionOffsetInsideAsmPrinterOutputStart = 0;
   size_t SectionOffsetInsideAsmPrinterOutputEnd = 0;
-
-  /// Output format.
-  dwarf::FormParams Format = {4, 4, dwarf::DWARF32};
-  llvm::endianness Endianess = llvm::endianness::little;
 };
 
 /// This class keeps contents and offsets to the debug sections. Any objects
@@ -374,7 +322,7 @@ class OutputSections {
               .str()
               .c_str());
 
-    return It->second;
+    return *It->second;
   }
 
   /// Returns descriptor for the specified section of \p SectionKind.
@@ -389,7 +337,9 @@ class OutputSections {
               .str()
               .c_str());
 
-    return It->second;
+    assert(It->second.get() != nullptr);
+
+    return *It->second;
   }
 
   /// Returns descriptor for the specified section of \p SectionKind.
@@ -401,7 +351,7 @@ class OutputSections {
     if (It == SectionDescriptors.end())
       return std::nullopt;
 
-    return &It->second;
+    return It->second.get();
   }
 
   /// Returns descriptor for the specified section of \p SectionKind.
@@ -413,26 +363,44 @@ class OutputSections {
     if (It == SectionDescriptors.end())
       return std::nullopt;
 
-    return &It->second;
+    return It->second.get();
   }
 
   /// Returns descriptor for the specified section of \p SectionKind.
   /// If descriptor does not exist then creates it.
   SectionDescriptor &
   getOrCreateSectionDescriptor(DebugSectionKind SectionKind) {
-    return SectionDescriptors
-        .try_emplace(SectionKind, SectionKind, GlobalData, Format, Endianness)
-        .first->second;
+    SectionsSetTy::iterator It = SectionDescriptors.find(SectionKind);
+
+    if (It == SectionDescriptors.end()) {
+      SectionDescriptor *Section =
+          new SectionDescriptor(SectionKind, GlobalData, Format, Endianness);
+      auto Result = SectionDescriptors.try_emplace(SectionKind, Section);
+      assert(Result.second);
+
+      It = Result.first;
+    }
+
+    return *It->second;
   }
 
   /// Erases data of all sections.
   void eraseSections() {
     for (auto &Section : SectionDescriptors)
-      Section.second.clearAllSectionData();
+      Section.second->clearAllSectionData();
   }
 
   /// Enumerate all sections and call \p Handler for each.
   void forEach(function_ref<void(SectionDescriptor &)> Handler) {
+    for (auto &Section : SectionDescriptors) {
+      assert(Section.second.get() != nullptr);
+      Handler(*(Section.second));
+    }
+  }
+
+  /// Enumerate all sections and call \p Handler for each.
+  void forEach(
+      function_ref<void(std::shared_ptr<SectionDescriptor> Section)> Handler) {
     for (auto &Section : SectionDescriptors)
       Handler(Section.second);
   }
@@ -443,10 +411,11 @@ class OutputSections {
   void assignSectionsOffsetAndAccumulateSize(
       std::array<uint64_t, SectionKindsNum> &SectionSizesAccumulator) {
     for (auto &Section : SectionDescriptors) {
-      Section.second.StartOffset = SectionSizesAccumulator[static_cast<uint8_t>(
-          Section.second.getKind())];
-      SectionSizesAccumulator[static_cast<uint8_t>(Section.second.getKind())] +=
-          Section.second.getContents().size();
+      Section.second->StartOffset =
+          SectionSizesAccumulator[static_cast<uint8_t>(
+              Section.second->getKind())];
+      SectionSizesAccumulator[static_cast<uint8_t>(
+          Section.second->getKind())] += Section.second->getContent().size();
     }
   }
 
@@ -492,11 +461,13 @@ class OutputSections {
   llvm::endianness Endianness = llvm::endianness::native;
 
   /// All keeping sections.
-  using SectionsSetTy = std::map<DebugSectionKind, SectionDescriptor>;
+  using SectionsSetTy =
+      std::map<DebugSectionKind, std::shared_ptr<SectionDescriptor>>;
   SectionsSetTy SectionDescriptors;
 };
 
 } // end of namespace dwarflinker_parallel
+} // end of namespace dwarflinker
 } // end namespace llvm
 
-#endif // LLVM_LIB_DWARFLINKERPARALLEL_OUTPUTSECTIONS_H
+#endif // LLVM_LIB_DWARFLINKER_LLVM_OUTPUTSECTIONS_H
diff --git a/llvm/lib/DWARFLinkerParallel/StringEntryToDwarfStringPoolEntryMap.h b/llvm/lib/DWARFLinker/LLVM/StringEntryToDwarfStringPoolEntryMap.h
similarity index 88%
rename from llvm/lib/DWARFLinkerParallel/StringEntryToDwarfStringPoolEntryMap.h
rename to llvm/lib/DWARFLinker/LLVM/StringEntryToDwarfStringPoolEntryMap.h
index b4c74d0adba970..ad68109172121c 100644
--- a/llvm/lib/DWARFLinkerParallel/StringEntryToDwarfStringPoolEntryMap.h
+++ b/llvm/lib/DWARFLinker/LLVM/StringEntryToDwarfStringPoolEntryMap.h
@@ -6,14 +6,15 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_LIB_DWARFLINKERPARALLEL_STRINGENTRYTODWARFSTRINGPOOLENTRYMAP_H
-#define LLVM_LIB_DWARFLINKERPARALLEL_STRINGENTRYTODWARFSTRINGPOOLENTRYMAP_H
+#ifndef LLVM_LIB_DWARFLINKER_LLVM_STRINGENTRYTODWARFSTRINGPOOLENTRYMAP_H
+#define LLVM_LIB_DWARFLINKER_LLVM_STRINGENTRYTODWARFSTRINGPOOLENTRYMAP_H
 
 #include "DWARFLinkerGlobalData.h"
 #include "llvm/ADT/SmallVector.h"
-#include "llvm/DWARFLinkerParallel/StringPool.h"
+#include "llvm/DWARFLinker/StringPool.h"
 
 namespace llvm {
+namespace dwarflinker {
 namespace dwarflinker_parallel {
 
 /// This class creates a DwarfStringPoolEntry for the corresponding StringEntry.
@@ -67,6 +68,7 @@ class StringEntryToDwarfStringPoolEntryMap {
 };
 
 } // end of namespace dwarflinker_parallel
+} // end of namespace dwarflinker
 } // end namespace llvm
 
-#endif // LLVM_LIB_DWARFLINKERPARALLEL_STRINGENTRYTODWARFSTRINGPOOLENTRYMAP_H
+#endif // LLVM_LIB_DWARFLINKER_LLVM_STRINGENTRYTODWARFSTRINGPOOLENTRYMAP_H
diff --git a/llvm/lib/DWARFLinkerParallel/SyntheticTypeNameBuilder.cpp b/llvm/lib/DWARFLinker/LLVM/SyntheticTypeNameBuilder.cpp
similarity index 99%
rename from llvm/lib/DWARFLinkerParallel/SyntheticTypeNameBuilder.cpp
rename to llvm/lib/DWARFLinker/LLVM/SyntheticTypeNameBuilder.cpp
index e0900f7a8e3d3e..c8becf692c62d5 100644
--- a/llvm/lib/DWARFLinkerParallel/SyntheticTypeNameBuilder.cpp
+++ b/llvm/lib/DWARFLinker/LLVM/SyntheticTypeNameBuilder.cpp
@@ -12,8 +12,9 @@
 #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
 #include "llvm/Support/ScopedPrinter.h"
 
-namespace llvm {
-namespace dwarflinker_parallel {
+using namespace llvm;
+using namespace dwarflinker;
+using namespace dwarflinker_parallel;
 
 Error SyntheticTypeNameBuilder::assignName(
     UnitEntryPairTy InputUnitEntryPair,
@@ -762,6 +763,3 @@ OrderedChildrenIndexAssigner::getChildIndex(
   OrderedChildIdxs[*ArrayIndex]++;
   return Result;
 }
-
-} // end of namespace dwarflinker_parallel
-} // namespace llvm
diff --git a/llvm/lib/DWARFLinkerParallel/SyntheticTypeNameBuilder.h b/llvm/lib/DWARFLinker/LLVM/SyntheticTypeNameBuilder.h
similarity index 96%
rename from llvm/lib/DWARFLinkerParallel/SyntheticTypeNameBuilder.h
rename to llvm/lib/DWARFLinker/LLVM/SyntheticTypeNameBuilder.h
index c9dce4e94fb0dc..2eef161076d805 100644
--- a/llvm/lib/DWARFLinkerParallel/SyntheticTypeNameBuilder.h
+++ b/llvm/lib/DWARFLinker/LLVM/SyntheticTypeNameBuilder.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===/
 
-#ifndef LLVM_LIB_DWARFLINKERNEXT_SYNTHETICTYPENAMEBUILDER_H
-#define LLVM_LIB_DWARFLINKERNEXT_SYNTHETICTYPENAMEBUILDER_H
+#ifndef LLVM_LIB_DWARFLINKER_LLVM_SYNTHETICTYPENAMEBUILDER_H
+#define LLVM_LIB_DWARFLINKER_LLVM_SYNTHETICTYPENAMEBUILDER_H
 
 #include "DWARFLinkerCompileUnit.h"
 #include "DWARFLinkerGlobalData.h"
@@ -17,6 +17,7 @@
 namespace llvm {
 class DWARFDebugInfoEntry;
 
+namespace dwarflinker {
 namespace dwarflinker_parallel {
 struct LinkContext;
 class TypeTableUnit;
@@ -150,6 +151,7 @@ class OrderedChildrenIndexAssigner {
 };
 
 } // end namespace dwarflinker_parallel
+} // end namespace dwarflinker
 } // end namespace llvm
 
-#endif // LLVM_LIB_DWARFLINKERNEXT_SYNTHETICTYPENAMEBUILDER_H
+#endif // LLVM_LIB_DWARFLINKER_LLVM_SYNTHETICTYPENAMEBUILDER_H
diff --git a/llvm/lib/DWARFLinkerParallel/TypePool.h b/llvm/lib/DWARFLinker/LLVM/TypePool.h
similarity index 95%
rename from llvm/lib/DWARFLinkerParallel/TypePool.h
rename to llvm/lib/DWARFLinker/LLVM/TypePool.h
index bbb3261027ce89..5924504425b87e 100644
--- a/llvm/lib/DWARFLinkerParallel/TypePool.h
+++ b/llvm/lib/DWARFLinker/LLVM/TypePool.h
@@ -6,17 +6,18 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_DWARFLINKERPARALLEL_TYPEPOOL_H
-#define LLVM_DWARFLINKERPARALLEL_TYPEPOOL_H
+#ifndef LLVM_LIB_DWARFLINKER_LLVM_TYPEPOOL_H
+#define LLVM_LIB_DWARFLINKER_LLVM_TYPEPOOL_H
 
-#include "ArrayList.h"
 #include "llvm/ADT/ConcurrentHashtable.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/CodeGen/DIE.h"
+#include "llvm/DWARFLinker/ArrayList.h"
 #include "llvm/Support/Allocator.h"
 #include <atomic>
 
 namespace llvm {
+namespace dwarflinker {
 namespace dwarflinker_parallel {
 
 class TypePool;
@@ -172,6 +173,7 @@ class TypePool : ConcurrentHashTableByPtr<StringRef, TypeEntry,
 };
 
 } // end of namespace dwarflinker_parallel
+} // end of namespace dwarflinker
 } // end namespace llvm
 
-#endif // LLVM_DWARFLINKERPARALLEL_TYPEPOOL_H
+#endif // LLVM_LIB_DWARFLINKER_LLVM_TYPEPOOL_H
diff --git a/llvm/lib/DWARFLinkerParallel/StringPool.cpp b/llvm/lib/DWARFLinker/Utils.cpp
similarity index 65%
rename from llvm/lib/DWARFLinkerParallel/StringPool.cpp
rename to llvm/lib/DWARFLinker/Utils.cpp
index fbff6b05e3a542..894c7dba2d44b0 100644
--- a/llvm/lib/DWARFLinkerParallel/StringPool.cpp
+++ b/llvm/lib/DWARFLinker/Utils.cpp
@@ -1,4 +1,4 @@
-//=== StringPool.cpp ------------------------------------------------------===//
+//=== Utils.cpp -----------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,4 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/DWARFLinkerParallel/StringPool.h"
+#include "llvm/DWARFLinker/Utils.h"
+
+using namespace llvm;
+using namespace llvm::dwarflinker;
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFFile.cpp b/llvm/lib/DWARFLinkerParallel/DWARFFile.cpp
deleted file mode 100644
index 5a3486e6398d4c..00000000000000
--- a/llvm/lib/DWARFLinkerParallel/DWARFFile.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-//=== DWARFFile.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 "llvm/DWARFLinkerParallel/DWARFFile.h"
-#include "DWARFLinkerGlobalData.h"
-
-llvm::dwarflinker_parallel::DWARFFile::DWARFFile(
-    StringRef Name, std::unique_ptr<DWARFContext> Dwarf,
-    std::unique_ptr<AddressesMap> Addresses,
-    DWARFFile::UnloadCallbackTy UnloadFunc)
-    : FileName(Name), Dwarf(std::move(Dwarf)), Addresses(std::move(Addresses)),
-      UnloadFunc(UnloadFunc) {}
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFLinker.cpp b/llvm/lib/DWARFLinkerParallel/DWARFLinker.cpp
deleted file mode 100644
index 269f24b1a13b9a..00000000000000
--- a/llvm/lib/DWARFLinkerParallel/DWARFLinker.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-//=== DWARFLinker.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 "DWARFLinkerImpl.h"
-#include "DependencyTracker.h"
-
-std::unique_ptr<llvm::dwarflinker_parallel::DWARFLinker>
-llvm::dwarflinker_parallel::DWARFLinker::createLinker(
-    MessageHandlerTy ErrorHandler, MessageHandlerTy WarningHandler,
-    TranslatorFuncTy StringsTranslator) {
-  return std::make_unique<DWARFLinkerImpl>(ErrorHandler, WarningHandler,
-                                           StringsTranslator);
-}
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
index 78792cf8389167..48f6a405afbae8 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
@@ -11,6 +11,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DWARFLinker/Utils.h"
 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
@@ -27,6 +28,7 @@
 
 using namespace llvm;
 using namespace dwarf;
+using namespace dwarflinker;
 
 using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind;
 
@@ -1399,14 +1401,6 @@ DWARFDebugLine::LineTable::getSourceByIndex(uint64_t FileIndex,
   return std::nullopt;
 }
 
-static bool isPathAbsoluteOnWindowsOrPosix(const Twine &Path) {
-  // Debug info can contain paths from any OS, not necessarily
-  // an OS we're currently running on. Moreover different compilation units can
-  // be compiled on different operating systems and linked together later.
-  return sys::path::is_absolute(Path, sys::path::Style::posix) ||
-         sys::path::is_absolute(Path, sys::path::Style::windows);
-}
-
 bool DWARFDebugLine::Prologue::getFileNameByIndex(
     uint64_t FileIndex, StringRef CompDir, FileLineInfoKind Kind,
     std::string &Result, sys::path::Style Style) const {
diff --git a/llvm/tools/dsymutil/CMakeLists.txt b/llvm/tools/dsymutil/CMakeLists.txt
index c612bfd9150c47..0e407f6fa1db43 100644
--- a/llvm/tools/dsymutil/CMakeLists.txt
+++ b/llvm/tools/dsymutil/CMakeLists.txt
@@ -9,6 +9,7 @@ set(LLVM_LINK_COMPONENTS
   AsmPrinter
   CodeGen
   CodeGenTypes
+  DWARFLinkerBase
   DWARFLinker
   DWARFLinkerParallel
   DebugInfoDWARF
diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
index d00ef1a8c228b0..926de320f49639 100644
--- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
+++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
@@ -27,8 +27,10 @@
 #include "llvm/CodeGen/DIE.h"
 #include "llvm/CodeGen/NonRelocatableStringpool.h"
 #include "llvm/Config/config.h"
-#include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
-#include "llvm/DWARFLinkerParallel/DWARFLinker.h"
+#include "llvm/DWARFLinker/Apple/DWARFLinker.h"
+#include "llvm/DWARFLinker/Apple/DWARFLinkerDeclContext.h"
+#include "llvm/DWARFLinker/Apple/DWARFStreamer.h"
+#include "llvm/DWARFLinker/LLVM/DWARFLinker.h"
 #include "llvm/DebugInfo/DIContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
@@ -100,6 +102,8 @@ namespace llvm {
 
 static mc::RegisterMCTargetOptionsFlags MOF;
 
+using namespace dwarflinker;
+
 namespace dsymutil {
 
 static void dumpDIE(const DWARFDie *DIE, bool Verbose) {
@@ -185,10 +189,9 @@ static Error remarksErrorHandler(const DebugMapObject &DMO,
 
   return createFileError(FE->getFileName(), std::move(NewE));
 }
-template <typename OutDwarfFile, typename AddressMap>
 Error DwarfLinkerForBinary::emitRelocations(
     const DebugMap &DM,
-    std::vector<ObjectWithRelocMap<OutDwarfFile>> &ObjectsForLinking) {
+    std::vector<ObjectWithRelocMap<DWARFFile>> &ObjectsForLinking) {
   // Return early if the "Resources" directory is not being written to.
   if (!Options.ResourceDir)
     return Error::success();
@@ -262,13 +265,13 @@ static Error emitRemarks(const LinkOptions &Options, StringRef BinaryPath,
   return Error::success();
 }
 
-template <typename OutDWARFFile, typename AddressesMap>
-ErrorOr<std::unique_ptr<OutDWARFFile>> DwarfLinkerForBinary::loadObject(
+ErrorOr<std::unique_ptr<dwarflinker::DWARFFile>>
+DwarfLinkerForBinary::loadObject(
     const DebugMapObject &Obj, const DebugMap &DebugMap,
     remarks::RemarkLinker &RL,
     std::shared_ptr<DwarfLinkerForBinaryRelocationMap> DLBRM) {
   auto ErrorOrObj = loadObject(Obj, DebugMap.getTriple());
-  std::unique_ptr<OutDWARFFile> Res;
+  std::unique_ptr<DWARFFile> Res;
 
   if (ErrorOrObj) {
     auto Context = DWARFContext::create(
@@ -285,9 +288,9 @@ ErrorOr<std::unique_ptr<OutDWARFFile>> DwarfLinkerForBinary::loadObject(
           });
         });
     DLBRM->init(*Context);
-    Res = std::make_unique<OutDWARFFile>(
+    Res = std::make_unique<DWARFFile>(
         Obj.getObjectFilename(), std::move(Context),
-        std::make_unique<AddressesMap>(*this, *ErrorOrObj, Obj, DLBRM),
+        std::make_unique<AddressManager>(*this, *ErrorOrObj, Obj, DLBRM),
         [&](StringRef FileName) { BinHolder.eraseObjectEntry(FileName); });
 
     Error E = RL.link(*ErrorOrObj);
@@ -594,27 +597,10 @@ void DwarfLinkerForBinary::copySwiftReflectionMetadata(
 
 bool DwarfLinkerForBinary::link(const DebugMap &Map) {
   if (Options.DWARFLinkerType == DsymutilDWARFLinkerType::LLVM) {
-    dwarflinker_parallel::DWARFLinker::OutputFileType DWARFLinkerOutputType;
-    switch (Options.FileType) {
-    case DWARFLinker::OutputFileType::Object:
-      DWARFLinkerOutputType =
-          dwarflinker_parallel::DWARFLinker::OutputFileType::Object;
-      break;
-
-    case DWARFLinker::OutputFileType::Assembly:
-      DWARFLinkerOutputType =
-          dwarflinker_parallel::DWARFLinker::OutputFileType::Assembly;
-      break;
-    }
-
-    return linkImpl<dwarflinker_parallel::DWARFLinker,
-                    dwarflinker_parallel::DWARFFile,
-                    AddressManager<dwarflinker_parallel::AddressesMap>>(
-        Map, DWARFLinkerOutputType);
+    return linkImpl<dwarflinker_parallel::DWARFLinker>(Map, Options.FileType);
   }
 
-  return linkImpl<DWARFLinker, DWARFFile, AddressManager<AddressesMap>>(
-      Map, Options.FileType);
+  return linkImpl<DWARFLinker>(Map, Options.FileType);
 }
 
 template <typename Linker>
@@ -645,11 +631,11 @@ void setAcceleratorTables(Linker &GeneralLinker,
   llvm_unreachable("All cases handled above!");
 }
 
-template <typename Linker, typename OutDwarfFile, typename AddressMap>
+template <typename Linker>
 bool DwarfLinkerForBinary::linkImpl(
-    const DebugMap &Map, typename Linker::OutputFileType ObjectType) {
+    const DebugMap &Map, DWARFLinkerBase::OutputFileType ObjectType) {
 
-  std::vector<ObjectWithRelocMap<OutDwarfFile>> ObjectsForLinking;
+  std::vector<ObjectWithRelocMap<DWARFFile>> ObjectsForLinking;
 
   DebugMap DebugMap(Map.getTriple(), Map.getBinaryPath());
 
@@ -667,14 +653,31 @@ bool DwarfLinkerForBinary::linkImpl(
       },
       Options.Translator ? TranslationLambda : nullptr);
 
+  std::unique_ptr<DwarfStreamer> Streamer;
   if (!Options.NoOutput) {
-    if (Error Err = GeneralLinker->createEmitter(Map.getTriple(), ObjectType,
-                                                 OutFile)) {
-      handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) {
+    Expected<DwarfStreamer *> StreamerOrErr = DwarfStreamer::createStreamer(
+        Map.getTriple(), ObjectType, OutFile, Options.Translator,
+        [&](const Twine &Warning, StringRef Context, const DWARFDie *DIE) {
+          reportWarning(Warning, Context, DIE);
+        });
+    if (!StreamerOrErr) {
+      handleAllErrors(StreamerOrErr.takeError(), [&](const ErrorInfoBase &EI) {
         reportError(EI.message(), "dwarf streamer init");
       });
       return false;
     }
+    Streamer.reset(*StreamerOrErr);
+
+    if constexpr (std::is_same<Linker, DWARFLinker>::value)
+      GeneralLinker->setOutputDWARFStreamer(Streamer.get());
+    else
+      GeneralLinker->setOutputDWARFHandler(
+          Map.getTriple(),
+          [&](std::shared_ptr<dwarflinker_parallel::SectionDescriptorBase>
+                  Section) {
+            Streamer->emitSectionContents(Section->getContent(),
+                                          Section->getName());
+          });
   }
 
   remarks::RemarkLinker RL;
@@ -691,22 +694,22 @@ bool DwarfLinkerForBinary::linkImpl(
   GeneralLinker->setNumThreads(Options.Threads);
   GeneralLinker->setPrependPath(Options.PrependPath);
   GeneralLinker->setKeepFunctionForStatic(Options.KeepFunctionForStatic);
-  GeneralLinker->setInputVerificationHandler([&](const OutDwarfFile &File, llvm::StringRef Output) {
-    std::lock_guard<std::mutex> Guard(ErrorHandlerMutex);
-    if (Options.Verbose)
-      errs() << Output;
-    warn("input verification failed", File.FileName);
-    HasVerificationErrors = true;
-  });
+  GeneralLinker->setInputVerificationHandler(
+      [&](const DWARFFile &File, llvm::StringRef Output) {
+        std::lock_guard<std::mutex> Guard(ErrorHandlerMutex);
+        if (Options.Verbose)
+          errs() << Output;
+        warn("input verification failed", File.FileName);
+        HasVerificationErrors = true;
+      });
   auto Loader = [&](StringRef ContainerName,
-                    StringRef Path) -> ErrorOr<OutDwarfFile &> {
+                    StringRef Path) -> ErrorOr<DWARFFile &> {
     auto &Obj = DebugMap.addDebugMapObject(
         Path, sys::TimePoint<std::chrono::seconds>(), MachO::N_OSO);
 
     auto DLBRelocMap = std::make_shared<DwarfLinkerForBinaryRelocationMap>();
-    if (ErrorOr<std::unique_ptr<OutDwarfFile>> ErrorOrObj =
-            loadObject<OutDwarfFile, AddressMap>(Obj, DebugMap, RL,
-                                                 DLBRelocMap)) {
+    if (ErrorOr<std::unique_ptr<DWARFFile>> ErrorOrObj =
+            loadObject(Obj, DebugMap, RL, DLBRelocMap)) {
       ObjectsForLinking.emplace_back(std::move(*ErrorOrObj), DLBRelocMap);
       return *ObjectsForLinking.back().Object;
     } else {
@@ -767,7 +770,7 @@ bool DwarfLinkerForBinary::linkImpl(
     auto SectionToOffsetInDwarf =
         calculateStartOfStrippableReflectionSections(Map);
     for (const auto &Obj : Map.objects())
-      copySwiftReflectionMetadata(Obj.get(), GeneralLinker->getEmitter(),
+      copySwiftReflectionMetadata(Obj.get(), Streamer.get(),
                                   SectionToOffsetInDwarf, RelocationsToApply);
   }
 
@@ -814,21 +817,21 @@ bool DwarfLinkerForBinary::linkImpl(
 
       // Copy the module into the .swift_ast section.
       if (!Options.NoOutput)
-        GeneralLinker->getEmitter()->emitSwiftAST((*ErrorOrMem)->getBuffer());
+        Streamer->emitSwiftAST((*ErrorOrMem)->getBuffer());
 
       continue;
     }
 
     auto DLBRelocMap = std::make_shared<DwarfLinkerForBinaryRelocationMap>();
-    if (ErrorOr<std::unique_ptr<OutDwarfFile>> ErrorOrObj =
-            loadObject<OutDwarfFile, AddressMap>(*Obj, Map, RL, DLBRelocMap)) {
+    if (ErrorOr<std::unique_ptr<DWARFFile>> ErrorOrObj =
+            loadObject(*Obj, Map, RL, DLBRelocMap)) {
       ObjectsForLinking.emplace_back(std::move(*ErrorOrObj), DLBRelocMap);
       GeneralLinker->addObjectFile(*ObjectsForLinking.back().Object, Loader,
                                    OnCUDieLoaded);
     } else {
       ObjectsForLinking.push_back(
-          {std::make_unique<OutDwarfFile>(Obj->getObjectFilename(), nullptr,
-                                          nullptr),
+          {std::make_unique<DWARFFile>(Obj->getObjectFilename(), nullptr,
+                                       nullptr),
            DLBRelocMap});
       GeneralLinker->addObjectFile(*ObjectsForLinking.back().Object);
     }
@@ -855,8 +858,7 @@ bool DwarfLinkerForBinary::linkImpl(
   if (Options.NoOutput)
     return true;
 
-  if (Error E =
-          emitRelocations<OutDwarfFile, AddressMap>(Map, ObjectsForLinking))
+  if (Error E = emitRelocations(Map, ObjectsForLinking))
     return error(toString(std::move(E)));
 
   if (Options.ResourceDir && !ParseableSwiftInterfaces.empty()) {
@@ -866,25 +868,21 @@ bool DwarfLinkerForBinary::linkImpl(
   }
 
   if (Map.getTriple().isOSDarwin() && !Map.getBinaryPath().empty() &&
-      ObjectType == Linker::OutputFileType::Object)
+      ObjectType == DWARFLinkerBase::OutputFileType::Object)
     return MachOUtils::generateDsymCompanion(
         Options.VFS, Map, Options.Translator,
-        *GeneralLinker->getEmitter()->getAsmPrinter().OutStreamer, OutFile,
-        RelocationsToApply);
+        *Streamer->getAsmPrinter().OutStreamer, OutFile, RelocationsToApply);
 
-  GeneralLinker->getEmitter()->finish();
+  Streamer->finish();
   return true;
 }
 
 /// Iterate over the relocations of the given \p Section and
 /// store the ones that correspond to debug map entries into the
 /// ValidRelocs array.
-template <typename AddressesMapBase>
-void DwarfLinkerForBinary::AddressManager<AddressesMapBase>::
-    findValidRelocsMachO(const object::SectionRef &Section,
-                         const object::MachOObjectFile &Obj,
-                         const DebugMapObject &DMO,
-                         std::vector<ValidReloc> &ValidRelocs) {
+void DwarfLinkerForBinary::AddressManager::findValidRelocsMachO(
+    const object::SectionRef &Section, const object::MachOObjectFile &Obj,
+    const DebugMapObject &DMO, std::vector<ValidReloc> &ValidRelocs) {
   Expected<StringRef> ContentsOrErr = Section.getContents();
   if (!ContentsOrErr) {
     consumeError(ContentsOrErr.takeError());
@@ -961,8 +959,7 @@ void DwarfLinkerForBinary::AddressManager<AddressesMapBase>::
 
 /// Dispatch the valid relocation finding logic to the
 /// appropriate handler depending on the object file format.
-template <typename AddressesMapBase>
-bool DwarfLinkerForBinary::AddressManager<AddressesMapBase>::findValidRelocs(
+bool DwarfLinkerForBinary::AddressManager::findValidRelocs(
     const object::SectionRef &Section, const object::ObjectFile &Obj,
     const DebugMapObject &DMO, std::vector<ValidReloc> &Relocs) {
   // Dispatch to the right handler depending on the file type.
@@ -987,10 +984,8 @@ bool DwarfLinkerForBinary::AddressManager<AddressesMapBase>::findValidRelocs(
 /// entries in the debug map. These relocations will drive the Dwarf link by
 /// indicating which DIEs refer to symbols present in the linked binary.
 /// \returns whether there are any valid relocations in the debug info.
-template <typename AddressesMapBase>
-bool DwarfLinkerForBinary::AddressManager<AddressesMapBase>::
-    findValidRelocsInDebugSections(const object::ObjectFile &Obj,
-                                   const DebugMapObject &DMO) {
+bool DwarfLinkerForBinary::AddressManager::findValidRelocsInDebugSections(
+    const object::ObjectFile &Obj, const DebugMapObject &DMO) {
   // Find the debug_info section.
   bool FoundValidRelocs = false;
   for (const object::SectionRef &Section : Obj.sections()) {
@@ -1011,9 +1006,7 @@ bool DwarfLinkerForBinary::AddressManager<AddressesMapBase>::
   return FoundValidRelocs;
 }
 
-template <typename AddressesMapBase>
-std::vector<ValidReloc>
-DwarfLinkerForBinary::AddressManager<AddressesMapBase>::getRelocations(
+std::vector<ValidReloc> DwarfLinkerForBinary::AddressManager::getRelocations(
     const std::vector<ValidReloc> &Relocs, uint64_t StartPos, uint64_t EndPos) {
   std::vector<ValidReloc> Res;
 
@@ -1030,9 +1023,7 @@ DwarfLinkerForBinary::AddressManager<AddressesMapBase>::getRelocations(
   return Res;
 }
 
-template <typename AddressesMapBase>
-void DwarfLinkerForBinary::AddressManager<AddressesMapBase>::printReloc(
-    const ValidReloc &Reloc) {
+void DwarfLinkerForBinary::AddressManager::printReloc(const ValidReloc &Reloc) {
   const auto &Mapping = Reloc.SymbolMapping;
   const uint64_t ObjectAddress = Mapping.ObjectAddress
                                      ? uint64_t(*Mapping.ObjectAddress)
@@ -1043,18 +1034,16 @@ void DwarfLinkerForBinary::AddressManager<AddressesMapBase>::printReloc(
                    uint64_t(Mapping.BinaryAddress));
 }
 
-template <typename AddressesMapBase>
-int64_t DwarfLinkerForBinary::AddressManager<AddressesMapBase>::getRelocValue(
-    const ValidReloc &Reloc) {
+int64_t
+DwarfLinkerForBinary::AddressManager::getRelocValue(const ValidReloc &Reloc) {
   int64_t AddrAdjust = relocate(Reloc);
   if (Reloc.SymbolMapping.ObjectAddress)
     AddrAdjust -= uint64_t(*Reloc.SymbolMapping.ObjectAddress);
   return AddrAdjust;
 }
 
-template <typename AddressesMapBase>
 std::optional<int64_t>
-DwarfLinkerForBinary::AddressManager<AddressesMapBase>::hasValidRelocationAt(
+DwarfLinkerForBinary::AddressManager::hasValidRelocationAt(
     const std::vector<ValidReloc> &AllRelocs, uint64_t StartOffset,
     uint64_t EndOffset) {
   std::vector<ValidReloc> Relocs =
@@ -1089,11 +1078,10 @@ getAttributeOffsets(const DWARFAbbreviationDeclaration *Abbrev, unsigned Idx,
   return std::make_pair(Offset, End);
 }
 
-template <typename AddressesMapBase>
-std::optional<int64_t> DwarfLinkerForBinary::AddressManager<AddressesMapBase>::
-    getExprOpAddressRelocAdjustment(DWARFUnit &U,
-                                    const DWARFExpression::Operation &Op,
-                                    uint64_t StartOffset, uint64_t EndOffset) {
+std::optional<int64_t>
+DwarfLinkerForBinary::AddressManager::getExprOpAddressRelocAdjustment(
+    DWARFUnit &U, const DWARFExpression::Operation &Op, uint64_t StartOffset,
+    uint64_t EndOffset) {
   switch (Op.getCode()) {
   default: {
     assert(false && "Specified operation does not have address operand");
@@ -1116,9 +1104,9 @@ std::optional<int64_t> DwarfLinkerForBinary::AddressManager<AddressesMapBase>::
   return std::nullopt;
 }
 
-template <typename AddressesMapBase>
-std::optional<int64_t> DwarfLinkerForBinary::AddressManager<
-    AddressesMapBase>::getSubprogramRelocAdjustment(const DWARFDie &DIE) {
+std::optional<int64_t>
+DwarfLinkerForBinary::AddressManager::getSubprogramRelocAdjustment(
+    const DWARFDie &DIE) {
   const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
 
   std::optional<uint32_t> LowPcIdx =
@@ -1158,25 +1146,19 @@ std::optional<int64_t> DwarfLinkerForBinary::AddressManager<
   }
 }
 
-template <typename AddressesMapBase>
-std::optional<StringRef> DwarfLinkerForBinary::AddressManager<
-    AddressesMapBase>::getLibraryInstallName() {
+std::optional<StringRef>
+DwarfLinkerForBinary::AddressManager::getLibraryInstallName() {
   return LibInstallName;
 }
 
-template <typename AddressesMapBase>
-uint64_t DwarfLinkerForBinary::AddressManager<AddressesMapBase>::relocate(
-    const ValidReloc &Reloc) const {
+uint64_t
+DwarfLinkerForBinary::AddressManager::relocate(const ValidReloc &Reloc) const {
   return Reloc.SymbolMapping.BinaryAddress + Reloc.Addend;
 }
 
-template <typename AddressesMapBase>
-void DwarfLinkerForBinary::AddressManager<
-    AddressesMapBase>::updateAndSaveValidRelocs(bool IsDWARF5,
-                                                uint64_t OriginalUnitOffset,
-                                                int64_t LinkedOffset,
-                                                uint64_t StartOffset,
-                                                uint64_t EndOffset) {
+void DwarfLinkerForBinary::AddressManager::updateAndSaveValidRelocs(
+    bool IsDWARF5, uint64_t OriginalUnitOffset, int64_t LinkedOffset,
+    uint64_t StartOffset, uint64_t EndOffset) {
   std::vector<ValidReloc> InRelocs =
       getRelocations(ValidDebugInfoRelocs, StartOffset, EndOffset);
   if (IsDWARF5)
@@ -1185,10 +1167,8 @@ void DwarfLinkerForBinary::AddressManager<
       IsDWARF5, InRelocs, OriginalUnitOffset, LinkedOffset);
 }
 
-template <typename AddressesMapBase>
-void DwarfLinkerForBinary::AddressManager<AddressesMapBase>::
-    updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,
-                                    uint64_t OutputUnitOffset) {
+void DwarfLinkerForBinary::AddressManager::updateRelocationsWithUnitOffset(
+    uint64_t OriginalUnitOffset, uint64_t OutputUnitOffset) {
   DwarfLinkerRelocMap->updateRelocationsWithUnitOffset(OriginalUnitOffset,
                                                        OutputUnitOffset);
 }
@@ -1200,8 +1180,7 @@ void DwarfLinkerForBinary::AddressManager<AddressesMapBase>::
 /// monotonic \p BaseOffset values.
 ///
 /// \returns whether any reloc has been applied.
-template <typename AddressesMapBase>
-bool DwarfLinkerForBinary::AddressManager<AddressesMapBase>::applyValidRelocs(
+bool DwarfLinkerForBinary::AddressManager::applyValidRelocs(
     MutableArrayRef<char> Data, uint64_t BaseOffset, bool IsLittleEndian) {
 
   std::vector<ValidReloc> Relocs = getRelocations(
diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.h b/llvm/tools/dsymutil/DwarfLinkerForBinary.h
index 328cd9197d0d17..b17cd5c92bcc98 100644
--- a/llvm/tools/dsymutil/DwarfLinkerForBinary.h
+++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.h
@@ -14,10 +14,6 @@
 #include "LinkUtils.h"
 #include "MachOUtils.h"
 #include "RelocationMap.h"
-#include "llvm/DWARFLinker/DWARFLinker.h"
-#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
-#include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
-#include "llvm/DWARFLinker/DWARFStreamer.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/Remarks/RemarkFormat.h"
 #include "llvm/Remarks/RemarkLinker.h"
@@ -104,8 +100,7 @@ class DwarfLinkerForBinary {
 private:
 
   /// Keeps track of relocations.
-  template <typename AddressesMapBase>
-  class AddressManager : public AddressesMapBase {
+  class AddressManager : public dwarflinker::AddressesMap {
 
     const DwarfLinkerForBinary &Linker;
 
@@ -241,8 +236,7 @@ class DwarfLinkerForBinary {
   /// Attempt to load a debug object from disk.
   ErrorOr<const object::ObjectFile &> loadObject(const DebugMapObject &Obj,
                                                  const Triple &triple);
-  template <typename OutDWARFFile, typename AddressesMap>
-  ErrorOr<std::unique_ptr<OutDWARFFile>>
+  ErrorOr<std::unique_ptr<dwarflinker::DWARFFile>>
   loadObject(const DebugMapObject &Obj, const DebugMap &DebugMap,
              remarks::RemarkLinker &RL,
              std::shared_ptr<DwarfLinkerForBinaryRelocationMap> DLBRM);
@@ -264,14 +258,13 @@ class DwarfLinkerForBinary {
       std::vector<MachOUtils::DwarfRelocationApplicationInfo>
           &RelocationsToApply);
 
-  template <typename Linker, typename OutDwarfFile, typename AddressMapBase>
+  template <typename Linker>
   bool linkImpl(const DebugMap &Map,
-                typename Linker::OutputFileType ObjectType);
+                dwarflinker::DWARFLinkerBase::OutputFileType ObjectType);
 
-  template <typename OutDwarfFile, typename AddressMap>
-  Error emitRelocations(
-      const DebugMap &DM,
-      std::vector<ObjectWithRelocMap<OutDwarfFile>> &ObjectsForLinking);
+  Error emitRelocations(const DebugMap &DM,
+                        std::vector<ObjectWithRelocMap<dwarflinker::DWARFFile>>
+                            &ObjectsForLinking);
 
   raw_fd_ostream &OutFile;
   BinaryHolder &BinHolder;
diff --git a/llvm/tools/dsymutil/LinkUtils.h b/llvm/tools/dsymutil/LinkUtils.h
index 0bf6d9aac1a3f3..26d0d09021ca14 100644
--- a/llvm/tools/dsymutil/LinkUtils.h
+++ b/llvm/tools/dsymutil/LinkUtils.h
@@ -16,8 +16,7 @@
 #include "llvm/Support/VirtualFileSystem.h"
 #include "llvm/Support/WithColor.h"
 
-#include "llvm/DWARFLinker/DWARFLinker.h"
-#include "llvm/DWARFLinker/DWARFStreamer.h"
+#include "llvm/DWARFLinker/LLVM/DWARFLinker.h"
 #include <string>
 
 namespace llvm {
@@ -72,7 +71,8 @@ struct LinkOptions {
   unsigned Threads = 1;
 
   // Output file type.
-  DWARFLinker::OutputFileType FileType = DWARFLinker::OutputFileType::Object;
+  dwarflinker::DWARFLinkerBase::OutputFileType FileType =
+      dwarflinker::DWARFLinkerBase::OutputFileType::Object;
 
   /// The accelerator table kind
   DsymutilAccelTableKind TheAccelTableKind;
diff --git a/llvm/tools/dsymutil/dsymutil.cpp b/llvm/tools/dsymutil/dsymutil.cpp
index 2dd123318e00bd..8fdd00a18e39f2 100644
--- a/llvm/tools/dsymutil/dsymutil.cpp
+++ b/llvm/tools/dsymutil/dsymutil.cpp
@@ -373,7 +373,8 @@ static Expected<DsymutilOptions> getOptions(opt::InputArgList &Args) {
     Options.Toolchain = Toolchain->getValue();
 
   if (Args.hasArg(OPT_assembly))
-    Options.LinkOpts.FileType = DWARFLinker::OutputFileType::Assembly;
+    Options.LinkOpts.FileType =
+        dwarflinker::DWARFLinkerBase::OutputFileType::Assembly;
 
   if (opt::Arg *NumThreads = Args.getLastArg(OPT_threads))
     Options.LinkOpts.Threads = atoi(NumThreads->getValue());
diff --git a/llvm/tools/llvm-dwarfutil/CMakeLists.txt b/llvm/tools/llvm-dwarfutil/CMakeLists.txt
index b2585799b10c13..91b25207b4f728 100644
--- a/llvm/tools/llvm-dwarfutil/CMakeLists.txt
+++ b/llvm/tools/llvm-dwarfutil/CMakeLists.txt
@@ -7,6 +7,7 @@ set(LLVM_LINK_COMPONENTS
   AllTargetsDescs
   AllTargetsInfos
   CodeGenTypes
+  DWARFLinkerBase
   DWARFLinker
   DWARFLinkerParallel
   DebugInfoDWARF
diff --git a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
index 02a94596ec7644..8ef425a9fe35da 100644
--- a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
+++ b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
@@ -9,9 +9,10 @@
 #include "DebugInfoLinker.h"
 #include "Error.h"
 #include "llvm/ADT/StringSwitch.h"
-#include "llvm/DWARFLinker/DWARFLinker.h"
-#include "llvm/DWARFLinker/DWARFStreamer.h"
-#include "llvm/DWARFLinkerParallel/DWARFLinker.h"
+#include "llvm/DWARFLinker/AddressesMap.h"
+#include "llvm/DWARFLinker/Apple/DWARFLinker.h"
+#include "llvm/DWARFLinker/Apple/DWARFStreamer.h"
+#include "llvm/DWARFLinker/LLVM/DWARFLinker.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/Object/ObjectFile.h"
@@ -37,8 +38,7 @@ namespace dwarfutil {
 // exec: [LowPC, HighPC] is not inside address ranges of .text sections
 //
 // universal: maxpc and bfd
-template <typename AddressMapBase>
-class ObjFileAddressMap : public AddressMapBase {
+class ObjFileAddressMap : public dwarflinker::AddressesMap {
 public:
   ObjFileAddressMap(DWARFContext &Context, const Options &Options,
                     object::ObjectFile &ObjFile)
@@ -298,7 +298,7 @@ static std::string getMessageForDeletedAcceleratorTables(
   return Message;
 }
 
-template <typename Linker, typename OutDwarfFile, typename AddressMapBase>
+template <typename Linker>
 Error linkDebugInfoImpl(object::ObjectFile &File, const Options &Options,
                         raw_pwrite_stream &OutStream) {
   std::mutex ErrorHandlerMutex;
@@ -335,9 +335,25 @@ Error linkDebugInfoImpl(object::ObjectFile &File, const Options &Options,
       Linker::createLinker(ReportErr, ReportWarn);
 
   Triple TargetTriple = File.makeTriple();
-  if (Error Err = DebugInfoLinker->createEmitter(
-          TargetTriple, Linker::OutputFileType::Object, OutStream))
-    return Err;
+
+  Expected<dwarflinker::DwarfStreamer *> Streamer =
+      dwarflinker::DwarfStreamer::createStreamer(
+          TargetTriple, Linker::OutputFileType::Object, OutStream, nullptr,
+          ReportWarn);
+  if (!Streamer)
+    return Streamer.takeError();
+
+  if constexpr (std::is_same<Linker, dwarflinker::DWARFLinker>::value)
+    DebugInfoLinker->setOutputDWARFStreamer(Streamer.get());
+  else
+    DebugInfoLinker->setOutputDWARFHandler(
+        TargetTriple,
+        [&](std::shared_ptr<
+            dwarflinker::dwarflinker_parallel::SectionDescriptorBase>
+                Section) {
+          (*Streamer)->emitSectionContents(Section->getContent(),
+                                           Section->getName());
+        });
 
   DebugInfoLinker->setEstimatedObjfilesAmount(1);
   DebugInfoLinker->setNumThreads(Options.NumThreads);
@@ -345,7 +361,7 @@ Error linkDebugInfoImpl(object::ObjectFile &File, const Options &Options,
   DebugInfoLinker->setVerbosity(Options.Verbose);
   DebugInfoLinker->setUpdateIndexTablesOnly(!Options.DoGarbageCollection);
 
-  std::vector<std::unique_ptr<OutDwarfFile>> ObjectsForLinking(1);
+  std::vector<std::unique_ptr<dwarflinker::DWARFFile>> ObjectsForLinking(1);
 
   // Add object files to the DWARFLinker.
   std::unique_ptr<DWARFContext> Context = DWARFContext::create(
@@ -360,11 +376,10 @@ Error linkDebugInfoImpl(object::ObjectFile &File, const Options &Options,
           ReportWarn(Info.message(), "", nullptr);
         });
       });
-  std::unique_ptr<ObjFileAddressMap<AddressMapBase>> AddressesMap(
-      std::make_unique<ObjFileAddressMap<AddressMapBase>>(*Context, Options,
-                                                          File));
+  std::unique_ptr<dwarflinker::AddressesMap> AddressesMap(
+      std::make_unique<ObjFileAddressMap>(*Context, Options, File));
 
-  ObjectsForLinking[0] = std::make_unique<OutDwarfFile>(
+  ObjectsForLinking[0] = std::make_unique<dwarflinker::DWARFFile>(
       File.getFileName(), std::move(Context), std::move(AddressesMap));
 
   uint16_t MaxDWARFVersion = 0;
@@ -400,7 +415,7 @@ Error linkDebugInfoImpl(object::ObjectFile &File, const Options &Options,
   for (typename Linker::AccelTableKind Table : AccelTables)
     DebugInfoLinker->addAccelTableKind(Table);
 
-  for (std::unique_ptr<OutDwarfFile> &CurFile : ObjectsForLinking) {
+  for (std::unique_ptr<dwarflinker::DWARFFile> &CurFile : ObjectsForLinking) {
     SmallVector<StringRef> AccelTableNamesToReplace;
     SmallVector<StringRef> AccelTableNamesToDelete;
 
@@ -445,20 +460,18 @@ Error linkDebugInfoImpl(object::ObjectFile &File, const Options &Options,
   if (Error Err = DebugInfoLinker->link())
     return Err;
 
-  DebugInfoLinker->getEmitter()->finish();
+  (*Streamer)->finish();
   return Error::success();
 }
 
 Error linkDebugInfo(object::ObjectFile &File, const Options &Options,
                     raw_pwrite_stream &OutStream) {
   if (Options.UseLLVMDWARFLinker)
-    return linkDebugInfoImpl<dwarflinker_parallel::DWARFLinker,
-                             dwarflinker_parallel::DWARFFile,
-                             dwarflinker_parallel::AddressesMap>(File, Options,
-                                                                 OutStream);
-  else
-    return linkDebugInfoImpl<DWARFLinker, DWARFFile, AddressesMap>(
+    return linkDebugInfoImpl<dwarflinker::dwarflinker_parallel::DWARFLinker>(
         File, Options, OutStream);
+  else
+    return linkDebugInfoImpl<dwarflinker::DWARFLinker>(File, Options,
+                                                       OutStream);
 }
 
 } // end of namespace dwarfutil
diff --git a/llvm/unittests/DWARFLinkerParallel/StringPoolTest.cpp b/llvm/unittests/DWARFLinkerParallel/StringPoolTest.cpp
index 84199f696a59de..b3a6c674d2e5da 100644
--- a/llvm/unittests/DWARFLinkerParallel/StringPoolTest.cpp
+++ b/llvm/unittests/DWARFLinkerParallel/StringPoolTest.cpp
@@ -6,13 +6,13 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/DWARFLinkerParallel/StringPool.h"
+#include "llvm/DWARFLinker/StringPool.h"
 #include "llvm/Support/Parallel.h"
 #include "gtest/gtest.h"
 #include <cstdlib>
 
 using namespace llvm;
-using namespace dwarflinker_parallel;
+using namespace dwarflinker;
 
 namespace {
 

>From 27f717a4b2c2c10f3481efa36b0790ad35dc9ce5 Mon Sep 17 00:00:00 2001
From: Alexey Lapshin <a.v.lapshin at mail.ru>
Date: Thu, 7 Dec 2023 19:32:44 +0300
Subject: [PATCH 2/4] fix building BOLT.

---
 bolt/lib/Rewrite/DWARFRewriter.cpp | 15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp
index 5580d85e3fa771..830d43f7819893 100644
--- a/bolt/lib/Rewrite/DWARFRewriter.cpp
+++ b/bolt/lib/Rewrite/DWARFRewriter.cpp
@@ -21,7 +21,7 @@
 #include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/CodeGen/AsmPrinter.h"
 #include "llvm/CodeGen/DIE.h"
-#include "llvm/DWARFLinker/DWARFStreamer.h"
+#include "llvm/DWARFLinker/Apple/DWARFStreamer.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
@@ -181,7 +181,7 @@ translateInputToOutputLocationList(const BinaryFunction &BF,
 namespace llvm {
 namespace bolt {
 /// Emits debug information into .debug_info or .debug_types section.
-class DIEStreamer : public DwarfStreamer {
+class DIEStreamer : public dwarflinker::DwarfStreamer {
   DIEBuilder *DIEBldr;
   DWARFRewriter &Rewriter;
 
@@ -271,17 +271,12 @@ class DIEStreamer : public DwarfStreamer {
       emitCompileUnitHeader(Unit, UnitDIE, Unit.getVersion());
   }
 
-  void emitDIE(DIE &Die) override {
-    AsmPrinter &Asm = getAsmPrinter();
-    Asm.emitDwarfDIE(Die);
-  }
-
 public:
   DIEStreamer(DIEBuilder *DIEBldr, DWARFRewriter &Rewriter,
-              DWARFLinker::OutputFileType OutFileType,
+              dwarflinker::DWARFLinkerBase::OutputFileType OutFileType,
               raw_pwrite_stream &OutFile,
               std::function<StringRef(StringRef Input)> Translator,
-              DWARFLinker::messageHandler Warning)
+              dwarflinker::DWARFLinker::MessageHandlerTy Warning)
       : DwarfStreamer(OutFileType, OutFile, Translator, Warning),
         DIEBldr(DIEBldr), Rewriter(Rewriter){};
 
@@ -457,7 +452,7 @@ createDIEStreamer(const Triple &TheTriple, raw_pwrite_stream &OutFile,
                   DWARFRewriter &Rewriter) {
 
   std::unique_ptr<DIEStreamer> Streamer = std::make_unique<DIEStreamer>(
-      &DIEBldr, Rewriter, llvm::DWARFLinker::OutputFileType::Object, OutFile,
+      &DIEBldr, Rewriter, llvm::dwarflinker::DWARFLinker::OutputFileType::Object, OutFile,
       [](StringRef Input) -> StringRef { return Input; },
       [&](const Twine &Warning, StringRef Context, const DWARFDie *) {});
   Error Err = Streamer->init(TheTriple, Swift5ReflectionSegmentName);

>From b160276aaa300e2752dfde1a581b31e7f3750c09 Mon Sep 17 00:00:00 2001
From: Alexey Lapshin <a.v.lapshin at mail.ru>
Date: Thu, 7 Dec 2023 19:39:06 +0300
Subject: [PATCH 3/4] apply clang-format.

---
 bolt/lib/Rewrite/DWARFRewriter.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp
index 830d43f7819893..c8c04c7ebbf815 100644
--- a/bolt/lib/Rewrite/DWARFRewriter.cpp
+++ b/bolt/lib/Rewrite/DWARFRewriter.cpp
@@ -452,7 +452,8 @@ createDIEStreamer(const Triple &TheTriple, raw_pwrite_stream &OutFile,
                   DWARFRewriter &Rewriter) {
 
   std::unique_ptr<DIEStreamer> Streamer = std::make_unique<DIEStreamer>(
-      &DIEBldr, Rewriter, llvm::dwarflinker::DWARFLinker::OutputFileType::Object, OutFile,
+      &DIEBldr, Rewriter,
+      llvm::dwarflinker::DWARFLinker::OutputFileType::Object, OutFile,
       [](StringRef Input) -> StringRef { return Input; },
       [&](const Twine &Warning, StringRef Context, const DWARFDie *) {});
   Error Err = Streamer->init(TheTriple, Swift5ReflectionSegmentName);

>From 930d82e3cbdf0774e1413e98b0325e4f64906cc2 Mon Sep 17 00:00:00 2001
From: Alexey Lapshin <a.v.lapshin at mail.ru>
Date: Fri, 8 Dec 2023 12:21:26 +0300
Subject: [PATCH 4/4] fix BOLT tests.

---
 bolt/lib/Rewrite/DWARFRewriter.cpp                  | 2 +-
 llvm/include/llvm/DWARFLinker/Apple/DWARFStreamer.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp
index c8c04c7ebbf815..99dfaac7bb3a09 100644
--- a/bolt/lib/Rewrite/DWARFRewriter.cpp
+++ b/bolt/lib/Rewrite/DWARFRewriter.cpp
@@ -284,7 +284,7 @@ class DIEStreamer : public dwarflinker::DwarfStreamer {
 
   void emitUnit(DWARFUnit &Unit, DIE &UnitDIE) {
     emitUnitHeader(Unit, UnitDIE);
-    emitDIE(UnitDIE);
+    Asm->emitDwarfDIE(UnitDIE);
   }
 };
 
diff --git a/llvm/include/llvm/DWARFLinker/Apple/DWARFStreamer.h b/llvm/include/llvm/DWARFLinker/Apple/DWARFStreamer.h
index fa2c0c30ed6832..4ace0e5dbd6c35 100644
--- a/llvm/include/llvm/DWARFLinker/Apple/DWARFStreamer.h
+++ b/llvm/include/llvm/DWARFLinker/Apple/DWARFStreamer.h
@@ -201,7 +201,7 @@ class DwarfStreamer {
                        const Offset2UnitMap &UnitMacroMap,
                        OffsetsStringPool &StringPool);
 
-private:
+protected:
   inline void warn(const Twine &Warning, StringRef Context = "") {
     if (WarningHandler)
       WarningHandler(Warning, Context, nullptr);



More information about the llvm-commits mailing list