[llvm] r335749 - [dsymutil] Move abstractions into separate files (NFC)

Jonas Devlieghere via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 27 09:13:40 PDT 2018


Author: jdevlieghere
Date: Wed Jun 27 09:13:40 2018
New Revision: 335749

URL: http://llvm.org/viewvc/llvm-project?rev=335749&view=rev
Log:
[dsymutil] Move abstractions into separate files (NFC)

This patch splits off some abstractions used by dsymutil's dwarf linker
and moves them into separate header and implementation files. This
almost halves the number of LOC in DwarfLinker.cpp and makes it a lot
easier to understand what functionality lives where.

Differential revision: https://reviews.llvm.org/D48647

Added:
    llvm/trunk/tools/dsymutil/CompileUnit.cpp
    llvm/trunk/tools/dsymutil/CompileUnit.h
    llvm/trunk/tools/dsymutil/DeclContext.cpp
    llvm/trunk/tools/dsymutil/DeclContext.h
    llvm/trunk/tools/dsymutil/DwarfLinker.h
    llvm/trunk/tools/dsymutil/DwarfStreamer.cpp
    llvm/trunk/tools/dsymutil/DwarfStreamer.h
    llvm/trunk/tools/dsymutil/LinkUtils.h
Modified:
    llvm/trunk/tools/dsymutil/CMakeLists.txt
    llvm/trunk/tools/dsymutil/DebugMap.cpp
    llvm/trunk/tools/dsymutil/DebugMap.h
    llvm/trunk/tools/dsymutil/DwarfLinker.cpp
    llvm/trunk/tools/dsymutil/MachODebugMapParser.cpp
    llvm/trunk/tools/dsymutil/MachOUtils.cpp
    llvm/trunk/tools/dsymutil/NonRelocatableStringpool.h
    llvm/trunk/tools/dsymutil/dsymutil.cpp
    llvm/trunk/tools/dsymutil/dsymutil.h

Modified: llvm/trunk/tools/dsymutil/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/CMakeLists.txt?rev=335749&r1=335748&r2=335749&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/CMakeLists.txt (original)
+++ llvm/trunk/tools/dsymutil/CMakeLists.txt Wed Jun 27 09:13:40 2018
@@ -12,8 +12,11 @@ add_llvm_tool(dsymutil
   dsymutil.cpp
   BinaryHolder.cpp
   CFBundle.cpp
+  CompileUnit.cpp
   DebugMap.cpp
+  DeclContext.cpp
   DwarfLinker.cpp
+  DwarfStreamer.cpp
   MachODebugMapParser.cpp
   MachOUtils.cpp
   NonRelocatableStringpool.cpp

Added: llvm/trunk/tools/dsymutil/CompileUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/CompileUnit.cpp?rev=335749&view=auto
==============================================================================
--- llvm/trunk/tools/dsymutil/CompileUnit.cpp (added)
+++ llvm/trunk/tools/dsymutil/CompileUnit.cpp Wed Jun 27 09:13:40 2018
@@ -0,0 +1,136 @@
+//===- tools/dsymutil/CompileUnit.h - Dwarf compile unit ------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CompileUnit.h"
+#include "DeclContext.h"
+
+namespace llvm {
+namespace dsymutil {
+
+/// Check if the DIE at \p Idx is in the scope of a function.
+static bool inFunctionScope(CompileUnit &U, unsigned Idx) {
+  while (Idx) {
+    if (U.getOrigUnit().getDIEAtIndex(Idx).getTag() == dwarf::DW_TAG_subprogram)
+      return true;
+    Idx = U.getInfo(Idx).ParentIdx;
+  }
+  return false;
+}
+
+void CompileUnit::markEverythingAsKept() {
+  unsigned Idx = 0;
+
+  setHasInterestingContent();
+
+  for (auto &I : Info) {
+    // Mark everything that wasn't explicit marked for pruning.
+    I.Keep = !I.Prune;
+    auto DIE = OrigUnit.getDIEAtIndex(Idx++);
+
+    // Try to guess which DIEs must go to the accelerator tables. We do that
+    // just for variables, because functions will be handled depending on
+    // whether they carry a DW_AT_low_pc attribute or not.
+    if (DIE.getTag() != dwarf::DW_TAG_variable &&
+        DIE.getTag() != dwarf::DW_TAG_constant)
+      continue;
+
+    Optional<DWARFFormValue> Value;
+    if (!(Value = DIE.find(dwarf::DW_AT_location))) {
+      if ((Value = DIE.find(dwarf::DW_AT_const_value)) &&
+          !inFunctionScope(*this, I.ParentIdx))
+        I.InDebugMap = true;
+      continue;
+    }
+    if (auto Block = Value->getAsBlock()) {
+      if (Block->size() > OrigUnit.getAddressByteSize() &&
+          (*Block)[0] == dwarf::DW_OP_addr)
+        I.InDebugMap = true;
+    }
+  }
+}
+
+uint64_t CompileUnit::computeNextUnitOffset() {
+  NextUnitOffset = StartOffset + 11 /* Header size */;
+  // The root DIE might be null, meaning that the Unit had nothing to
+  // contribute to the linked output. In that case, we will emit the
+  // unit header without any actual DIE.
+  if (NewUnit)
+    NextUnitOffset += NewUnit->getUnitDie().getSize();
+  return NextUnitOffset;
+}
+
+/// Keep track of a forward cross-cu reference from this unit
+/// to \p Die that lives in \p RefUnit.
+void CompileUnit::noteForwardReference(DIE *Die, const CompileUnit *RefUnit,
+                                       DeclContext *Ctxt, PatchLocation Attr) {
+  ForwardDIEReferences.emplace_back(Die, RefUnit, Ctxt, Attr);
+}
+
+void CompileUnit::fixupForwardReferences() {
+  for (const auto &Ref : ForwardDIEReferences) {
+    DIE *RefDie;
+    const CompileUnit *RefUnit;
+    PatchLocation Attr;
+    DeclContext *Ctxt;
+    std::tie(RefDie, RefUnit, Ctxt, Attr) = Ref;
+    if (Ctxt && Ctxt->getCanonicalDIEOffset())
+      Attr.set(Ctxt->getCanonicalDIEOffset());
+    else
+      Attr.set(RefDie->getOffset() + RefUnit->getStartOffset());
+  }
+}
+
+void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {
+  Labels.insert({LabelLowPc, PcOffset});
+}
+
+void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc,
+                                   int64_t PcOffset) {
+  Ranges.insert(FuncLowPc, FuncHighPc, PcOffset);
+  this->LowPc = std::min(LowPc, FuncLowPc + PcOffset);
+  this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);
+}
+
+void CompileUnit::noteRangeAttribute(const DIE &Die, PatchLocation Attr) {
+  if (Die.getTag() != dwarf::DW_TAG_compile_unit)
+    RangeAttributes.push_back(Attr);
+  else
+    UnitRangeAttribute = Attr;
+}
+
+void CompileUnit::noteLocationAttribute(PatchLocation Attr, int64_t PcOffset) {
+  LocationAttributes.emplace_back(Attr, PcOffset);
+}
+
+void CompileUnit::addNamespaceAccelerator(const DIE *Die,
+                                          DwarfStringPoolEntryRef Name) {
+  Namespaces.emplace_back(Name, Die);
+}
+
+void CompileUnit::addObjCAccelerator(const DIE *Die,
+                                     DwarfStringPoolEntryRef Name,
+                                     bool SkipPubSection) {
+  ObjC.emplace_back(Name, Die, SkipPubSection);
+}
+
+void CompileUnit::addNameAccelerator(const DIE *Die,
+                                     DwarfStringPoolEntryRef Name,
+                                     bool SkipPubSection) {
+  Pubnames.emplace_back(Name, Die, SkipPubSection);
+}
+
+void CompileUnit::addTypeAccelerator(const DIE *Die,
+                                     DwarfStringPoolEntryRef Name,
+                                     bool ObjcClassImplementation,
+                                     uint32_t QualifiedNameHash) {
+  Pubtypes.emplace_back(Name, Die, QualifiedNameHash, ObjcClassImplementation);
+}
+
+} // namespace dsymutil
+} // namespace llvm

Added: llvm/trunk/tools/dsymutil/CompileUnit.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/CompileUnit.h?rev=335749&view=auto
==============================================================================
--- llvm/trunk/tools/dsymutil/CompileUnit.h (added)
+++ llvm/trunk/tools/dsymutil/CompileUnit.h Wed Jun 27 09:13:40 2018
@@ -0,0 +1,323 @@
+//===- tools/dsymutil/CompileUnit.h - Dwarf debug info linker ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/IntervalMap.h"
+#include "llvm/CodeGen/DIE.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+
+#ifndef LLVM_TOOLS_DSYMUTIL_COMPILEUNIT_H
+#define LLVM_TOOLS_DSYMUTIL_COMPILEUNIT_H
+
+namespace llvm {
+namespace dsymutil {
+
+class DeclContext;
+
+template <typename KeyT, typename ValT>
+using HalfOpenIntervalMap =
+    IntervalMap<KeyT, ValT, IntervalMapImpl::NodeSizer<KeyT, ValT>::LeafSize,
+                IntervalMapHalfOpenInfo<KeyT>>;
+
+using FunctionIntervals = HalfOpenIntervalMap<uint64_t, int64_t>;
+
+// FIXME: Delete this structure.
+struct PatchLocation {
+  DIE::value_iterator I;
+
+  PatchLocation() = default;
+  PatchLocation(DIE::value_iterator I) : I(I) {}
+
+  void set(uint64_t New) const {
+    assert(I);
+    const auto &Old = *I;
+    assert(Old.getType() == DIEValue::isInteger);
+    *I = DIEValue(Old.getAttribute(), Old.getForm(), DIEInteger(New));
+  }
+
+  uint64_t get() const {
+    assert(I);
+    return I->getDIEInteger().getValue();
+  }
+};
+
+/// Stores all information relating to a compile unit, be it in its original
+/// instance in the object file to its brand new cloned and linked DIE tree.
+class CompileUnit {
+public:
+  /// Information gathered about a DIE in the object file.
+  struct DIEInfo {
+    /// Address offset to apply to the described entity.
+    int64_t AddrAdjust;
+
+    /// ODR Declaration context.
+    DeclContext *Ctxt;
+
+    /// Cloned version of that DIE.
+    DIE *Clone;
+
+    /// The index of this DIE's parent.
+    uint32_t ParentIdx;
+
+    /// Is the DIE part of the linked output?
+    bool Keep : 1;
+
+    /// Was this DIE's entity found in the map?
+    bool InDebugMap : 1;
+
+    /// Is this a pure forward declaration we can strip?
+    bool Prune : 1;
+
+    /// Does DIE transitively refer an incomplete decl?
+    bool Incomplete : 1;
+  };
+
+  CompileUnit(DWARFUnit &OrigUnit, unsigned ID, bool CanUseODR,
+              StringRef ClangModuleName)
+      : OrigUnit(OrigUnit), ID(ID), Ranges(RangeAlloc),
+        ClangModuleName(ClangModuleName) {
+    Info.resize(OrigUnit.getNumDIEs());
+
+    auto CUDie = OrigUnit.getUnitDIE(false);
+    if (!CUDie) {
+      HasODR = false;
+      return;
+    }
+    if (auto Lang = dwarf::toUnsigned(CUDie.find(dwarf::DW_AT_language)))
+      HasODR = CanUseODR && (*Lang == dwarf::DW_LANG_C_plus_plus ||
+                             *Lang == dwarf::DW_LANG_C_plus_plus_03 ||
+                             *Lang == dwarf::DW_LANG_C_plus_plus_11 ||
+                             *Lang == dwarf::DW_LANG_C_plus_plus_14 ||
+                             *Lang == dwarf::DW_LANG_ObjC_plus_plus);
+    else
+      HasODR = false;
+  }
+
+  DWARFUnit &getOrigUnit() const { return OrigUnit; }
+
+  unsigned getUniqueID() const { return ID; }
+
+  void createOutputDIE() {
+    NewUnit.emplace(OrigUnit.getVersion(), OrigUnit.getAddressByteSize(),
+                    OrigUnit.getUnitDIE().getTag());
+  }
+
+  DIE *getOutputUnitDIE() const {
+    if (NewUnit)
+      return &const_cast<BasicDIEUnit &>(*NewUnit).getUnitDie();
+    return nullptr;
+  }
+
+  bool hasODR() const { return HasODR; }
+  bool isClangModule() const { return !ClangModuleName.empty(); }
+  const std::string &getClangModuleName() const { return ClangModuleName; }
+
+  DIEInfo &getInfo(unsigned Idx) { return Info[Idx]; }
+  const DIEInfo &getInfo(unsigned Idx) const { return Info[Idx]; }
+
+  uint64_t getStartOffset() const { return StartOffset; }
+  uint64_t getNextUnitOffset() const { return NextUnitOffset; }
+  void setStartOffset(uint64_t DebugInfoSize) { StartOffset = DebugInfoSize; }
+
+  uint64_t getLowPc() const { return LowPc; }
+  uint64_t getHighPc() const { return HighPc; }
+  bool hasLabelAt(uint64_t Addr) const { return Labels.count(Addr); }
+
+  Optional<PatchLocation> getUnitRangesAttribute() const {
+    return UnitRangeAttribute;
+  }
+
+  const FunctionIntervals &getFunctionRanges() const { return Ranges; }
+
+  const std::vector<PatchLocation> &getRangesAttributes() const {
+    return RangeAttributes;
+  }
+
+  const std::vector<std::pair<PatchLocation, int64_t>> &
+  getLocationAttributes() const {
+    return LocationAttributes;
+  }
+
+  void setHasInterestingContent() { HasInterestingContent = true; }
+  bool hasInterestingContent() { return HasInterestingContent; }
+
+  /// Mark every DIE in this unit as kept. This function also
+  /// marks variables as InDebugMap so that they appear in the
+  /// reconstructed accelerator tables.
+  void markEverythingAsKept();
+
+  /// Compute the end offset for this unit. Must be called after the CU's DIEs
+  /// have been cloned.  \returns the next unit offset (which is also the
+  /// current debug_info section size).
+  uint64_t computeNextUnitOffset();
+
+  /// Keep track of a forward reference to DIE \p Die in \p RefUnit by \p
+  /// Attr. The attribute should be fixed up later to point to the absolute
+  /// offset of \p Die in the debug_info section or to the canonical offset of
+  /// \p Ctxt if it is non-null.
+  void noteForwardReference(DIE *Die, const CompileUnit *RefUnit,
+                            DeclContext *Ctxt, PatchLocation Attr);
+
+  /// Apply all fixups recorded by noteForwardReference().
+  void fixupForwardReferences();
+
+  /// Add the low_pc of a label that is relocated by applying
+  /// offset \p PCOffset.
+  void addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset);
+
+  /// Add a function range [\p LowPC, \p HighPC) that is relocated by applying
+  /// offset \p PCOffset.
+  void addFunctionRange(uint64_t LowPC, uint64_t HighPC, int64_t PCOffset);
+
+  /// Keep track of a DW_AT_range attribute that we will need to patch up later.
+  void noteRangeAttribute(const DIE &Die, PatchLocation Attr);
+
+  /// Keep track of a location attribute pointing to a location list in the
+  /// debug_loc section.
+  void noteLocationAttribute(PatchLocation Attr, int64_t PcOffset);
+
+  /// Add a name accelerator entry for \a Die with \a Name.
+  void addNamespaceAccelerator(const DIE *Die, DwarfStringPoolEntryRef Name);
+
+  /// Add a name accelerator entry for \a Die with \a Name.
+  void addNameAccelerator(const DIE *Die, DwarfStringPoolEntryRef Name,
+                          bool SkipPubnamesSection = false);
+
+  /// Add various accelerator entries for \p Die with \p Name which is stored
+  /// in the string table at \p Offset. \p Name must be an Objective-C
+  /// selector.
+  void addObjCAccelerator(const DIE *Die, DwarfStringPoolEntryRef Name,
+                          bool SkipPubnamesSection = false);
+
+  /// Add a type accelerator entry for \p Die with \p Name which is stored in
+  /// the string table at \p Offset.
+  void addTypeAccelerator(const DIE *Die, DwarfStringPoolEntryRef Name,
+                          bool ObjcClassImplementation,
+                          uint32_t QualifiedNameHash);
+
+  struct AccelInfo {
+    /// Name of the entry.
+    DwarfStringPoolEntryRef Name;
+
+    /// DIE this entry describes.
+    const DIE *Die;
+
+    /// Hash of the fully qualified name.
+    uint32_t QualifiedNameHash;
+
+    /// Emit this entry only in the apple_* sections.
+    bool SkipPubSection;
+
+    /// Is this an ObjC class implementation?
+    bool ObjcClassImplementation;
+
+    AccelInfo(DwarfStringPoolEntryRef Name, const DIE *Die,
+              bool SkipPubSection = false)
+        : Name(Name), Die(Die), SkipPubSection(SkipPubSection) {}
+
+    AccelInfo(DwarfStringPoolEntryRef Name, const DIE *Die,
+              uint32_t QualifiedNameHash, bool ObjCClassIsImplementation)
+        : Name(Name), Die(Die), QualifiedNameHash(QualifiedNameHash),
+          SkipPubSection(false),
+          ObjcClassImplementation(ObjCClassIsImplementation) {}
+  };
+
+  const std::vector<AccelInfo> &getPubnames() const { return Pubnames; }
+  const std::vector<AccelInfo> &getPubtypes() const { return Pubtypes; }
+  const std::vector<AccelInfo> &getNamespaces() const { return Namespaces; }
+  const std::vector<AccelInfo> &getObjC() const { return ObjC; }
+
+  /// Get the full path for file \a FileNum in the line table
+  StringRef getResolvedPath(unsigned FileNum) {
+    if (FileNum >= ResolvedPaths.size())
+      return StringRef();
+    return ResolvedPaths[FileNum];
+  }
+
+  /// Set the fully resolved path for the line-table's file \a FileNum
+  /// to \a Path.
+  void setResolvedPath(unsigned FileNum, StringRef Path) {
+    if (ResolvedPaths.size() <= FileNum)
+      ResolvedPaths.resize(FileNum + 1);
+    ResolvedPaths[FileNum] = Path;
+  }
+
+private:
+  DWARFUnit &OrigUnit;
+  unsigned ID;
+  std::vector<DIEInfo> Info; ///< DIE info indexed by DIE index.
+  Optional<BasicDIEUnit> NewUnit;
+
+  uint64_t StartOffset;
+  uint64_t NextUnitOffset;
+
+  uint64_t LowPc = std::numeric_limits<uint64_t>::max();
+  uint64_t HighPc = 0;
+
+  /// A list of attributes to fixup with the absolute offset of
+  /// a DIE in the debug_info section.
+  ///
+  /// The offsets for the attributes in this array couldn't be set while
+  /// cloning because for cross-cu forward references the target DIE's offset
+  /// isn't known you emit the reference attribute.
+  std::vector<
+      std::tuple<DIE *, const CompileUnit *, DeclContext *, PatchLocation>>
+      ForwardDIEReferences;
+
+  FunctionIntervals::Allocator RangeAlloc;
+
+  /// The ranges in that interval map are the PC ranges for
+  /// functions in this unit, associated with the PC offset to apply
+  /// to the addresses to get the linked address.
+  FunctionIntervals Ranges;
+
+  /// The DW_AT_low_pc of each DW_TAG_label.
+  SmallDenseMap<uint64_t, uint64_t, 1> Labels;
+
+  /// DW_AT_ranges attributes to patch after we have gathered
+  /// all the unit's function addresses.
+  /// @{
+  std::vector<PatchLocation> RangeAttributes;
+  Optional<PatchLocation> UnitRangeAttribute;
+  /// @}
+
+  /// Location attributes that need to be transferred from the
+  /// original debug_loc section to the liked one. They are stored
+  /// along with the PC offset that is to be applied to their
+  /// function's address.
+  std::vector<std::pair<PatchLocation, int64_t>> LocationAttributes;
+
+  /// Accelerator entries for the unit, both for the pub*
+  /// sections and the apple* ones.
+  /// @{
+  std::vector<AccelInfo> Pubnames;
+  std::vector<AccelInfo> Pubtypes;
+  std::vector<AccelInfo> Namespaces;
+  std::vector<AccelInfo> ObjC;
+  /// @}
+
+  /// Cached resolved paths from the line table.
+  /// Note, the StringRefs here point in to the intern (uniquing) string pool.
+  /// This means that a StringRef returned here doesn't need to then be uniqued
+  /// for the purposes of getting a unique address for each string.
+  std::vector<StringRef> ResolvedPaths;
+
+  /// Is this unit subject to the ODR rule?
+  bool HasODR;
+
+  /// Did a DIE actually contain a valid reloc?
+  bool HasInterestingContent;
+
+  /// If this is a Clang module, this holds the module's name.
+  std::string ClangModuleName;
+};
+
+} // end namespace dsymutil
+} // end namespace llvm
+
+#endif // LLVM_TOOLS_DSYMUTIL_COMPILEUNIT_H

Modified: llvm/trunk/tools/dsymutil/DebugMap.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DebugMap.cpp?rev=335749&r1=335748&r2=335749&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/DebugMap.cpp (original)
+++ llvm/trunk/tools/dsymutil/DebugMap.cpp Wed Jun 27 09:13:40 2018
@@ -1,6 +1,6 @@
 //===- tools/dsymutil/DebugMap.cpp - Generic debug map representation -----===//
 //
-//                             The LLVM Linker
+//                     The LLVM Compiler Infrastructure
 //
 // This file is distributed under the University of Illinois Open Source
 // License. See LICENSE.TXT for details.

Modified: llvm/trunk/tools/dsymutil/DebugMap.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DebugMap.h?rev=335749&r1=335748&r2=335749&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/DebugMap.h (original)
+++ llvm/trunk/tools/dsymutil/DebugMap.h Wed Jun 27 09:13:40 2018
@@ -1,6 +1,6 @@
 //=- tools/dsymutil/DebugMap.h - Generic debug map representation -*- C++ -*-=//
 //
-//                             The LLVM Linker
+//                     The LLVM Compiler Infrastructure
 //
 // This file is distributed under the University of Illinois Open Source
 // License. See LICENSE.TXT for details.

Added: llvm/trunk/tools/dsymutil/DeclContext.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DeclContext.cpp?rev=335749&view=auto
==============================================================================
--- llvm/trunk/tools/dsymutil/DeclContext.cpp (added)
+++ llvm/trunk/tools/dsymutil/DeclContext.cpp Wed Jun 27 09:13:40 2018
@@ -0,0 +1,211 @@
+//===- tools/dsymutil/DeclContext.cpp - Declaration context ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DeclContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+
+namespace llvm {
+namespace dsymutil {
+
+/// Set the last DIE/CU a context was seen in and, possibly invalidate the
+/// context if it is ambiguous.
+///
+/// In the current implementation, we don't handle overloaded functions well,
+/// because the argument types are not taken into account when computing the
+/// DeclContext tree.
+///
+/// Some of this is mitigated byt using mangled names that do contain the
+/// arguments types, but sometimes (e.g. with function templates) we don't have
+/// that. In that case, just do not unique anything that refers to the contexts
+/// we are not able to distinguish.
+///
+/// If a context that is not a namespace appears twice in the same CU, we know
+/// it is ambiguous. Make it invalid.
+bool DeclContext::setLastSeenDIE(CompileUnit &U, const DWARFDie &Die) {
+  if (LastSeenCompileUnitID == U.getUniqueID()) {
+    DWARFUnit &OrigUnit = U.getOrigUnit();
+    uint32_t FirstIdx = OrigUnit.getDIEIndex(LastSeenDIE);
+    U.getInfo(FirstIdx).Ctxt = nullptr;
+    return false;
+  }
+
+  LastSeenCompileUnitID = U.getUniqueID();
+  LastSeenDIE = Die;
+  return true;
+}
+
+PointerIntPair<DeclContext *, 1> DeclContextTree::getChildDeclContext(
+    DeclContext &Context, const DWARFDie &DIE, CompileUnit &U,
+    UniquingStringPool &StringPool, bool InClangModule) {
+  unsigned Tag = DIE.getTag();
+
+  // FIXME: dsymutil-classic compat: We should bail out here if we
+  // have a specification or an abstract_origin. We will get the
+  // parent context wrong here.
+
+  switch (Tag) {
+  default:
+    // By default stop gathering child contexts.
+    return PointerIntPair<DeclContext *, 1>(nullptr);
+  case dwarf::DW_TAG_module:
+    break;
+  case dwarf::DW_TAG_compile_unit:
+    return PointerIntPair<DeclContext *, 1>(&Context);
+  case dwarf::DW_TAG_subprogram:
+    // Do not unique anything inside CU local functions.
+    if ((Context.getTag() == dwarf::DW_TAG_namespace ||
+         Context.getTag() == dwarf::DW_TAG_compile_unit) &&
+        !dwarf::toUnsigned(DIE.find(dwarf::DW_AT_external), 0))
+      return PointerIntPair<DeclContext *, 1>(nullptr);
+    LLVM_FALLTHROUGH;
+  case dwarf::DW_TAG_member:
+  case dwarf::DW_TAG_namespace:
+  case dwarf::DW_TAG_structure_type:
+  case dwarf::DW_TAG_class_type:
+  case dwarf::DW_TAG_union_type:
+  case dwarf::DW_TAG_enumeration_type:
+  case dwarf::DW_TAG_typedef:
+    // Artificial things might be ambiguous, because they might be created on
+    // demand. For example implicitly defined constructors are ambiguous
+    // because of the way we identify contexts, and they won't be generated
+    // every time everywhere.
+    if (dwarf::toUnsigned(DIE.find(dwarf::DW_AT_artificial), 0))
+      return PointerIntPair<DeclContext *, 1>(nullptr);
+    break;
+  }
+
+  const char *Name = DIE.getName(DINameKind::LinkageName);
+  const char *ShortName = DIE.getName(DINameKind::ShortName);
+  StringRef NameRef;
+  StringRef ShortNameRef;
+  StringRef FileRef;
+
+  if (Name)
+    NameRef = StringPool.internString(Name);
+  else if (Tag == dwarf::DW_TAG_namespace)
+    // FIXME: For dsymutil-classic compatibility. I think uniquing within
+    // anonymous namespaces is wrong. There is no ODR guarantee there.
+    NameRef = StringPool.internString("(anonymous namespace)");
+
+  if (ShortName && ShortName != Name)
+    ShortNameRef = StringPool.internString(ShortName);
+  else
+    ShortNameRef = NameRef;
+
+  if (Tag != dwarf::DW_TAG_class_type && Tag != dwarf::DW_TAG_structure_type &&
+      Tag != dwarf::DW_TAG_union_type &&
+      Tag != dwarf::DW_TAG_enumeration_type && NameRef.empty())
+    return PointerIntPair<DeclContext *, 1>(nullptr);
+
+  unsigned Line = 0;
+  unsigned ByteSize = std::numeric_limits<uint32_t>::max();
+
+  if (!InClangModule) {
+    // Gather some discriminating data about the DeclContext we will be
+    // creating: File, line number and byte size. This shouldn't be necessary,
+    // because the ODR is just about names, but given that we do some
+    // approximations with overloaded functions and anonymous namespaces, use
+    // these additional data points to make the process safer.
+    //
+    // This is disabled for clang modules, because forward declarations of
+    // module-defined types do not have a file and line.
+    ByteSize = dwarf::toUnsigned(DIE.find(dwarf::DW_AT_byte_size),
+                                 std::numeric_limits<uint64_t>::max());
+    if (Tag != dwarf::DW_TAG_namespace || !Name) {
+      if (unsigned FileNum =
+              dwarf::toUnsigned(DIE.find(dwarf::DW_AT_decl_file), 0)) {
+        if (const auto *LT = U.getOrigUnit().getContext().getLineTableForUnit(
+                &U.getOrigUnit())) {
+          // FIXME: dsymutil-classic compatibility. I'd rather not
+          // unique anything in anonymous namespaces, but if we do, then
+          // verify that the file and line correspond.
+          if (!Name && Tag == dwarf::DW_TAG_namespace)
+            FileNum = 1;
+
+          if (LT->hasFileAtIndex(FileNum)) {
+            Line = dwarf::toUnsigned(DIE.find(dwarf::DW_AT_decl_line), 0);
+            // Cache the resolved paths based on the index in the line table,
+            // because calling realpath is expansive.
+            StringRef ResolvedPath = U.getResolvedPath(FileNum);
+            if (!ResolvedPath.empty()) {
+              FileRef = ResolvedPath;
+            } else {
+              std::string File;
+              bool FoundFileName = LT->getFileNameByIndex(
+                  FileNum, U.getOrigUnit().getCompilationDir(),
+                  DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
+                  File);
+              (void)FoundFileName;
+              assert(FoundFileName && "Must get file name from line table");
+              // Second level of caching, this time based on the file's parent
+              // path.
+              FileRef = PathResolver.resolve(File, StringPool);
+              U.setResolvedPath(FileNum, FileRef);
+            }
+          }
+        }
+      }
+    }
+  }
+
+  if (!Line && NameRef.empty())
+    return PointerIntPair<DeclContext *, 1>(nullptr);
+
+  // We hash NameRef, which is the mangled name, in order to get most
+  // overloaded functions resolve correctly.
+  //
+  // Strictly speaking, hashing the Tag is only necessary for a
+  // DW_TAG_module, to prevent uniquing of a module and a namespace
+  // with the same name.
+  //
+  // FIXME: dsymutil-classic won't unique the same type presented
+  // once as a struct and once as a class. Using the Tag in the fully
+  // qualified name hash to get the same effect.
+  unsigned Hash = hash_combine(Context.getQualifiedNameHash(), Tag, NameRef);
+
+  // FIXME: dsymutil-classic compatibility: when we don't have a name,
+  // use the filename.
+  if (Tag == dwarf::DW_TAG_namespace && NameRef == "(anonymous namespace)")
+    Hash = hash_combine(Hash, FileRef);
+
+  // Now look if this context already exists.
+  DeclContext Key(Hash, Line, ByteSize, Tag, NameRef, FileRef, Context);
+  auto ContextIter = Contexts.find(&Key);
+
+  if (ContextIter == Contexts.end()) {
+    // The context wasn't found.
+    bool Inserted;
+    DeclContext *NewContext =
+        new (Allocator) DeclContext(Hash, Line, ByteSize, Tag, NameRef, FileRef,
+                                    Context, DIE, U.getUniqueID());
+    std::tie(ContextIter, Inserted) = Contexts.insert(NewContext);
+    assert(Inserted && "Failed to insert DeclContext");
+    (void)Inserted;
+  } else if (Tag != dwarf::DW_TAG_namespace &&
+             !(*ContextIter)->setLastSeenDIE(U, DIE)) {
+    // The context was found, but it is ambiguous with another context
+    // in the same file. Mark it invalid.
+    return PointerIntPair<DeclContext *, 1>(*ContextIter, /* Invalid= */ 1);
+  }
+
+  assert(ContextIter != Contexts.end());
+  // FIXME: dsymutil-classic compatibility. Union types aren't
+  // uniques, but their children might be.
+  if ((Tag == dwarf::DW_TAG_subprogram &&
+       Context.getTag() != dwarf::DW_TAG_structure_type &&
+       Context.getTag() != dwarf::DW_TAG_class_type) ||
+      (Tag == dwarf::DW_TAG_union_type))
+    return PointerIntPair<DeclContext *, 1>(*ContextIter, /* Invalid= */ 1);
+
+  return PointerIntPair<DeclContext *, 1>(*ContextIter);
+}
+} // namespace dsymutil
+} // namespace llvm

Added: llvm/trunk/tools/dsymutil/DeclContext.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DeclContext.h?rev=335749&view=auto
==============================================================================
--- llvm/trunk/tools/dsymutil/DeclContext.h (added)
+++ llvm/trunk/tools/dsymutil/DeclContext.h Wed Jun 27 09:13:40 2018
@@ -0,0 +1,172 @@
+//===- tools/dsymutil/DeclContext.h - Dwarf debug info linker ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CompileUnit.h"
+#include "NonRelocatableStringpool.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/Support/Path.h"
+
+#ifndef LLVM_TOOLS_DSYMUTIL_DECLCONTEXT_H
+#define LLVM_TOOLS_DSYMUTIL_DECLCONTEXT_H
+
+namespace llvm {
+namespace dsymutil {
+
+struct DeclMapInfo;
+
+/// Small helper that resolves and caches file paths. This helps reduce the
+/// number of calls to realpath which is expensive. We assume the input are
+/// files, and cache the realpath of their parent. This way we can quickly
+/// resolve different files under the same path.
+class CachedPathResolver {
+public:
+  /// Resolve a path by calling realpath and cache its result. The returned
+  /// StringRef is interned in the given \p StringPool.
+  StringRef resolve(std::string Path, NonRelocatableStringpool &StringPool) {
+    StringRef FileName = sys::path::filename(Path);
+    SmallString<256> ParentPath = sys::path::parent_path(Path);
+
+    // If the ParentPath has not yet been resolved, resolve and cache it for
+    // future look-ups.
+    if (!ResolvedPaths.count(ParentPath)) {
+      SmallString<256> RealPath;
+      sys::fs::real_path(ParentPath, RealPath);
+      ResolvedPaths.insert({ParentPath, StringRef(RealPath).str()});
+    }
+
+    // Join the file name again with the resolved path.
+    SmallString<256> ResolvedPath(ResolvedPaths[ParentPath]);
+    sys::path::append(ResolvedPath, FileName);
+    return StringPool.internString(ResolvedPath);
+  }
+
+private:
+  StringMap<std::string> ResolvedPaths;
+};
+
+/// A DeclContext is a named program scope that is used for ODR uniquing of
+/// types.
+///
+/// The set of DeclContext for the ODR-subject parts of a Dwarf link is
+/// expanded (and uniqued) with each new object file processed. We need to
+/// determine the context of each DIE in an linked object file to see if the
+/// corresponding type has already been emitted.
+///
+/// The contexts are conceptually organized as a tree (eg. a function scope is
+/// contained in a namespace scope that contains other scopes), but
+/// storing/accessing them in an actual tree is too inefficient: we need to be
+/// able to very quickly query a context for a given child context by name.
+/// Storing a StringMap in each DeclContext would be too space inefficient.
+///
+/// The solution here is to give each DeclContext a link to its parent (this
+/// allows to walk up the tree), but to query the existence of a specific
+/// DeclContext using a separate DenseMap keyed on the hash of the fully
+/// qualified name of the context.
+class DeclContext {
+public:
+  using Map = DenseSet<DeclContext *, DeclMapInfo>;
+
+  DeclContext() : DefinedInClangModule(0), Parent(*this) {}
+
+  DeclContext(unsigned Hash, uint32_t Line, uint32_t ByteSize, uint16_t Tag,
+              StringRef Name, StringRef File, const DeclContext &Parent,
+              DWARFDie LastSeenDIE = DWARFDie(), unsigned CUId = 0)
+      : QualifiedNameHash(Hash), Line(Line), ByteSize(ByteSize), Tag(Tag),
+        DefinedInClangModule(0), Name(Name), File(File), Parent(Parent),
+        LastSeenDIE(LastSeenDIE), LastSeenCompileUnitID(CUId) {}
+
+  uint32_t getQualifiedNameHash() const { return QualifiedNameHash; }
+
+  bool setLastSeenDIE(CompileUnit &U, const DWARFDie &Die);
+
+  uint32_t getCanonicalDIEOffset() const { return CanonicalDIEOffset; }
+  void setCanonicalDIEOffset(uint32_t Offset) { CanonicalDIEOffset = Offset; }
+
+  bool isDefinedInClangModule() const { return DefinedInClangModule; }
+  void setDefinedInClangModule(bool Val) { DefinedInClangModule = Val; }
+
+  uint16_t getTag() const { return Tag; }
+  StringRef getName() const { return Name; }
+
+private:
+  friend DeclMapInfo;
+
+  unsigned QualifiedNameHash = 0;
+  uint32_t Line = 0;
+  uint32_t ByteSize = 0;
+  uint16_t Tag = dwarf::DW_TAG_compile_unit;
+  unsigned DefinedInClangModule : 1;
+  StringRef Name;
+  StringRef File;
+  const DeclContext &Parent;
+  DWARFDie LastSeenDIE;
+  uint32_t LastSeenCompileUnitID = 0;
+  uint32_t CanonicalDIEOffset = 0;
+};
+
+/// This class gives a tree-like API to the DenseMap that stores the
+/// DeclContext objects. It holds the BumpPtrAllocator where these objects will
+/// be allocated.
+class DeclContextTree {
+public:
+  /// Get the child of \a Context described by \a DIE in \a Unit. The
+  /// required strings will be interned in \a StringPool.
+  /// \returns The child DeclContext along with one bit that is set if
+  /// this context is invalid.
+  ///
+  /// An invalid context means it shouldn't be considered for uniquing, but its
+  /// not returning null, because some children of that context might be
+  /// uniquing candidates.
+  ///
+  /// FIXME: The invalid bit along the return value is to emulate some
+  /// dsymutil-classic functionality.
+  PointerIntPair<DeclContext *, 1>
+  getChildDeclContext(DeclContext &Context, const DWARFDie &DIE,
+                      CompileUnit &Unit, UniquingStringPool &StringPool,
+                      bool InClangModule);
+
+  DeclContext &getRoot() { return Root; }
+
+private:
+  BumpPtrAllocator Allocator;
+  DeclContext Root;
+  DeclContext::Map Contexts;
+
+  /// Cache resolved paths from the line table.
+  CachedPathResolver PathResolver;
+};
+
+/// Info type for the DenseMap storing the DeclContext pointers.
+struct DeclMapInfo : private DenseMapInfo<DeclContext *> {
+  using DenseMapInfo<DeclContext *>::getEmptyKey;
+  using DenseMapInfo<DeclContext *>::getTombstoneKey;
+
+  static unsigned getHashValue(const DeclContext *Ctxt) {
+    return Ctxt->QualifiedNameHash;
+  }
+
+  static bool isEqual(const DeclContext *LHS, const DeclContext *RHS) {
+    if (RHS == getEmptyKey() || RHS == getTombstoneKey())
+      return RHS == LHS;
+    return LHS->QualifiedNameHash == RHS->QualifiedNameHash &&
+           LHS->Line == RHS->Line && LHS->ByteSize == RHS->ByteSize &&
+           LHS->Name.data() == RHS->Name.data() &&
+           LHS->File.data() == RHS->File.data() &&
+           LHS->Parent.QualifiedNameHash == RHS->Parent.QualifiedNameHash;
+  }
+};
+
+} // end namespace dsymutil
+} // end namespace llvm
+
+#endif // LLVM_TOOLS_DSYMUTIL_DECLCONTEXT_H

Modified: llvm/trunk/tools/dsymutil/DwarfLinker.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DwarfLinker.cpp?rev=335749&r1=335748&r2=335749&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/DwarfLinker.cpp (original)
+++ llvm/trunk/tools/dsymutil/DwarfLinker.cpp Wed Jun 27 09:13:40 2018
@@ -1,14 +1,17 @@
 //===- tools/dsymutil/DwarfLinker.cpp - Dwarf debug info linker -----------===//
 //
-//                             The LLVM Linker
+//                     The LLVM Compiler Infrastructure
 //
 // This file is distributed under the University of Illinois Open Source
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 
+#include "DwarfLinker.h"
 #include "BinaryHolder.h"
 #include "DebugMap.h"
+#include "DeclContext.h"
+#include "DwarfStreamer.h"
 #include "MachOUtils.h"
 #include "NonRelocatableStringpool.h"
 #include "dsymutil.h"
@@ -58,7 +61,6 @@
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/MC/MCTargetOptions.h"
-#include "llvm/MC/MCTargetOptionsCommandFlags.inc"
 #include "llvm/Object/MachO.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Object/SymbolicFile.h"
@@ -102,1794 +104,6 @@
 namespace llvm {
 namespace dsymutil {
 
-namespace {
-
-/// Helper for making strong types.
-template <typename T, typename S> class StrongType : public T {
-public:
-  template <typename... Args>
-  explicit StrongType(Args... A) : T(std::forward<Args>(A)...) {}
-};
-
-/// It's very easy to introduce bugs by passing the wrong string pool. By using
-/// strong types the interface enforces that the right kind of pool is used.
-struct UniqueTag {};
-struct OffsetsTag {};
-using UniquingStringPool = StrongType<NonRelocatableStringpool, UniqueTag>;
-using OffsetsStringPool = StrongType<NonRelocatableStringpool, OffsetsTag>;
-
-/// Small helper that resolves and caches file paths. This helps reduce the
-/// number of calls to realpath which is expensive. We assume the input are
-/// files, and cache the realpath of their parent. This way we can quickly
-/// resolve different files under the same path.
-class CachedPathResolver {
-public:
-  /// Resolve a path by calling realpath and cache its result. The returned
-  /// StringRef is interned in the given \p StringPool.
-  StringRef resolve(std::string Path, NonRelocatableStringpool &StringPool) {
-    StringRef FileName = sys::path::filename(Path);
-    SmallString<256> ParentPath = sys::path::parent_path(Path);
-
-    // If the ParentPath has not yet been resolved, resolve and cache it for
-    // future look-ups.
-    if (!ResolvedPaths.count(ParentPath)) {
-      SmallString<256> RealPath;
-      sys::fs::real_path(ParentPath, RealPath);
-      ResolvedPaths.insert({ParentPath, StringRef(RealPath).str()});
-    }
-
-    // Join the file name again with the resolved path.
-    SmallString<256> ResolvedPath(ResolvedPaths[ParentPath]);
-    sys::path::append(ResolvedPath, FileName);
-    return StringPool.internString(ResolvedPath);
-  }
-
-private:
-  StringMap<std::string> ResolvedPaths;
-};
-
-/// Retrieve the section named \a SecName in \a Obj.
-///
-/// To accommodate for platform discrepancies, the name passed should be
-/// (for example) 'debug_info' to match either '__debug_info' or '.debug_info'.
-/// This function will strip the initial platform-specific characters.
-static Optional<object::SectionRef>
-getSectionByName(const object::ObjectFile &Obj, StringRef SecName) {
-  for (const object::SectionRef &Section : Obj.sections()) {
-    StringRef SectionName;
-    Section.getName(SectionName);
-    SectionName = SectionName.substr(SectionName.find_first_not_of("._"));
-    if (SectionName != SecName)
-      continue;
-    return Section;
-  }
-  return None;
-}
-
-template <typename KeyT, typename ValT>
-using HalfOpenIntervalMap =
-    IntervalMap<KeyT, ValT, IntervalMapImpl::NodeSizer<KeyT, ValT>::LeafSize,
-                IntervalMapHalfOpenInfo<KeyT>>;
-
-using FunctionIntervals = HalfOpenIntervalMap<uint64_t, int64_t>;
-
-// FIXME: Delete this structure.
-struct PatchLocation {
-  DIE::value_iterator I;
-
-  PatchLocation() = default;
-  PatchLocation(DIE::value_iterator I) : I(I) {}
-
-  void set(uint64_t New) const {
-    assert(I);
-    const auto &Old = *I;
-    assert(Old.getType() == DIEValue::isInteger);
-    *I = DIEValue(Old.getAttribute(), Old.getForm(), DIEInteger(New));
-  }
-
-  uint64_t get() const {
-    assert(I);
-    return I->getDIEInteger().getValue();
-  }
-};
-
-class CompileUnit;
-struct DeclMapInfo;
-
-/// A DeclContext is a named program scope that is used for ODR
-/// uniquing of types.
-/// The set of DeclContext for the ODR-subject parts of a Dwarf link
-/// is expanded (and uniqued) with each new object file processed. We
-/// need to determine the context of each DIE in an linked object file
-/// to see if the corresponding type has already been emitted.
-///
-/// The contexts are conceptually organized as a tree (eg. a function
-/// scope is contained in a namespace scope that contains other
-/// scopes), but storing/accessing them in an actual tree is too
-/// inefficient: we need to be able to very quickly query a context
-/// for a given child context by name. Storing a StringMap in each
-/// DeclContext would be too space inefficient.
-/// The solution here is to give each DeclContext a link to its parent
-/// (this allows to walk up the tree), but to query the existence of a
-/// specific DeclContext using a separate DenseMap keyed on the hash
-/// of the fully qualified name of the context.
-class DeclContext {
-  friend DeclMapInfo;
-
-  unsigned QualifiedNameHash = 0;
-  uint32_t Line = 0;
-  uint32_t ByteSize = 0;
-  uint16_t Tag = dwarf::DW_TAG_compile_unit;
-  unsigned DefinedInClangModule : 1;
-  StringRef Name;
-  StringRef File;
-  const DeclContext &Parent;
-  DWARFDie LastSeenDIE;
-  uint32_t LastSeenCompileUnitID = 0;
-  uint32_t CanonicalDIEOffset = 0;
-
-public:
-  using Map = DenseSet<DeclContext *, DeclMapInfo>;
-
-  DeclContext() : DefinedInClangModule(0), Parent(*this) {}
-
-  DeclContext(unsigned Hash, uint32_t Line, uint32_t ByteSize, uint16_t Tag,
-              StringRef Name, StringRef File, const DeclContext &Parent,
-              DWARFDie LastSeenDIE = DWARFDie(), unsigned CUId = 0)
-      : QualifiedNameHash(Hash), Line(Line), ByteSize(ByteSize), Tag(Tag),
-        DefinedInClangModule(0), Name(Name), File(File), Parent(Parent),
-        LastSeenDIE(LastSeenDIE), LastSeenCompileUnitID(CUId) {}
-
-  uint32_t getQualifiedNameHash() const { return QualifiedNameHash; }
-
-  bool setLastSeenDIE(CompileUnit &U, const DWARFDie &Die);
-
-  uint32_t getCanonicalDIEOffset() const { return CanonicalDIEOffset; }
-  void setCanonicalDIEOffset(uint32_t Offset) { CanonicalDIEOffset = Offset; }
-
-  bool isDefinedInClangModule() const { return DefinedInClangModule; }
-  void setDefinedInClangModule(bool Val) { DefinedInClangModule = Val; }
-
-  uint16_t getTag() const { return Tag; }
-  StringRef getName() const { return Name; }
-};
-
-/// Info type for the DenseMap storing the DeclContext pointers.
-struct DeclMapInfo : private DenseMapInfo<DeclContext *> {
-  using DenseMapInfo<DeclContext *>::getEmptyKey;
-  using DenseMapInfo<DeclContext *>::getTombstoneKey;
-
-  static unsigned getHashValue(const DeclContext *Ctxt) {
-    return Ctxt->QualifiedNameHash;
-  }
-
-  static bool isEqual(const DeclContext *LHS, const DeclContext *RHS) {
-    if (RHS == getEmptyKey() || RHS == getTombstoneKey())
-      return RHS == LHS;
-    return LHS->QualifiedNameHash == RHS->QualifiedNameHash &&
-           LHS->Line == RHS->Line && LHS->ByteSize == RHS->ByteSize &&
-           LHS->Name.data() == RHS->Name.data() &&
-           LHS->File.data() == RHS->File.data() &&
-           LHS->Parent.QualifiedNameHash == RHS->Parent.QualifiedNameHash;
-  }
-};
-
-/// This class gives a tree-like API to the DenseMap that stores the
-/// DeclContext objects. It also holds the BumpPtrAllocator where
-/// these objects will be allocated.
-class DeclContextTree {
-  BumpPtrAllocator Allocator;
-  DeclContext Root;
-  DeclContext::Map Contexts;
-
-  /// Cache resolved paths from the line table.
-  CachedPathResolver PathResolver;
-
-public:
-  /// Get the child of \a Context described by \a DIE in \a Unit. The
-  /// required strings will be interned in \a StringPool.
-  /// \returns The child DeclContext along with one bit that is set if
-  /// this context is invalid.
-  ///
-  /// An invalid context means it shouldn't be considered for uniquing, but its
-  /// not returning null, because some children of that context might be
-  /// uniquing candidates.
-  ///
-  /// FIXME: The invalid bit along the return value is to emulate some
-  /// dsymutil-classic functionality.
-  PointerIntPair<DeclContext *, 1>
-  getChildDeclContext(DeclContext &Context, const DWARFDie &DIE,
-                      CompileUnit &Unit, UniquingStringPool &StringPool,
-                      bool InClangModule);
-
-  DeclContext &getRoot() { return Root; }
-};
-
-/// Stores all information relating to a compile unit, be it in its original
-/// instance in the object file to its brand new cloned and linked DIE tree.
-class CompileUnit {
-public:
-  /// Information gathered about a DIE in the object file.
-  struct DIEInfo {
-    /// Address offset to apply to the described entity.
-    int64_t AddrAdjust;
-
-    /// ODR Declaration context.
-    DeclContext *Ctxt;
-
-    /// Cloned version of that DIE.
-    DIE *Clone;
-
-    /// The index of this DIE's parent.
-    uint32_t ParentIdx;
-
-    /// Is the DIE part of the linked output?
-    bool Keep : 1;
-
-    /// Was this DIE's entity found in the map?
-    bool InDebugMap : 1;
-
-    /// Is this a pure forward declaration we can strip?
-    bool Prune : 1;
-
-    /// Does DIE transitively refer an incomplete decl?
-    bool Incomplete : 1;
-  };
-
-  CompileUnit(DWARFUnit &OrigUnit, unsigned ID, bool CanUseODR,
-              StringRef ClangModuleName)
-      : OrigUnit(OrigUnit), ID(ID), Ranges(RangeAlloc),
-        ClangModuleName(ClangModuleName) {
-    Info.resize(OrigUnit.getNumDIEs());
-
-    auto CUDie = OrigUnit.getUnitDIE(false);
-    if (!CUDie) {
-      HasODR = false;
-      return;
-    }
-    if (auto Lang = dwarf::toUnsigned(CUDie.find(dwarf::DW_AT_language)))
-      HasODR = CanUseODR && (*Lang == dwarf::DW_LANG_C_plus_plus ||
-                             *Lang == dwarf::DW_LANG_C_plus_plus_03 ||
-                             *Lang == dwarf::DW_LANG_C_plus_plus_11 ||
-                             *Lang == dwarf::DW_LANG_C_plus_plus_14 ||
-                             *Lang == dwarf::DW_LANG_ObjC_plus_plus);
-    else
-      HasODR = false;
-  }
-
-  DWARFUnit &getOrigUnit() const { return OrigUnit; }
-
-  unsigned getUniqueID() const { return ID; }
-
-  void createOutputDIE() {
-    NewUnit.emplace(OrigUnit.getVersion(), OrigUnit.getAddressByteSize(),
-                    OrigUnit.getUnitDIE().getTag());
-  }
-
-  DIE *getOutputUnitDIE() const {
-    if (NewUnit)
-      return &const_cast<BasicDIEUnit &>(*NewUnit).getUnitDie();
-    return nullptr;
-  }
-
-  bool hasODR() const { return HasODR; }
-  bool isClangModule() const { return !ClangModuleName.empty(); }
-  const std::string &getClangModuleName() const { return ClangModuleName; }
-
-  DIEInfo &getInfo(unsigned Idx) { return Info[Idx]; }
-  const DIEInfo &getInfo(unsigned Idx) const { return Info[Idx]; }
-
-  uint64_t getStartOffset() const { return StartOffset; }
-  uint64_t getNextUnitOffset() const { return NextUnitOffset; }
-  void setStartOffset(uint64_t DebugInfoSize) { StartOffset = DebugInfoSize; }
-
-  uint64_t getLowPc() const { return LowPc; }
-  uint64_t getHighPc() const { return HighPc; }
-  bool hasLabelAt(uint64_t Addr) const { return Labels.count(Addr); }
-
-  Optional<PatchLocation> getUnitRangesAttribute() const {
-    return UnitRangeAttribute;
-  }
-
-  const FunctionIntervals &getFunctionRanges() const { return Ranges; }
-
-  const std::vector<PatchLocation> &getRangesAttributes() const {
-    return RangeAttributes;
-  }
-
-  const std::vector<std::pair<PatchLocation, int64_t>> &
-  getLocationAttributes() const {
-    return LocationAttributes;
-  }
-
-  void setHasInterestingContent() { HasInterestingContent = true; }
-  bool hasInterestingContent() { return HasInterestingContent; }
-
-  /// Mark every DIE in this unit as kept. This function also
-  /// marks variables as InDebugMap so that they appear in the
-  /// reconstructed accelerator tables.
-  void markEverythingAsKept();
-
-  /// Compute the end offset for this unit. Must be called after the CU's DIEs
-  /// have been cloned.  \returns the next unit offset (which is also the
-  /// current debug_info section size).
-  uint64_t computeNextUnitOffset();
-
-  /// Keep track of a forward reference to DIE \p Die in \p RefUnit by \p
-  /// Attr. The attribute should be fixed up later to point to the absolute
-  /// offset of \p Die in the debug_info section or to the canonical offset of
-  /// \p Ctxt if it is non-null.
-  void noteForwardReference(DIE *Die, const CompileUnit *RefUnit,
-                            DeclContext *Ctxt, PatchLocation Attr);
-
-  /// Apply all fixups recorded by noteForwardReference().
-  void fixupForwardReferences();
-
-  /// Add the low_pc of a label that is relocated by applying
-  /// offset \p PCOffset.
-  void addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset);
-
-  /// Add a function range [\p LowPC, \p HighPC) that is relocated by applying
-  /// offset \p PCOffset.
-  void addFunctionRange(uint64_t LowPC, uint64_t HighPC, int64_t PCOffset);
-
-  /// Keep track of a DW_AT_range attribute that we will need to patch up later.
-  void noteRangeAttribute(const DIE &Die, PatchLocation Attr);
-
-  /// Keep track of a location attribute pointing to a location list in the
-  /// debug_loc section.
-  void noteLocationAttribute(PatchLocation Attr, int64_t PcOffset);
-
-  /// Add a name accelerator entry for \a Die with \a Name.
-  void addNamespaceAccelerator(const DIE *Die, DwarfStringPoolEntryRef Name);
-
-  /// Add a name accelerator entry for \a Die with \a Name.
-  void addNameAccelerator(const DIE *Die, DwarfStringPoolEntryRef Name,
-                          bool SkipPubnamesSection = false);
-
-  /// Add various accelerator entries for \p Die with \p Name which is stored
-  /// in the string table at \p Offset. \p Name must be an Objective-C
-  /// selector.
-  void addObjCAccelerator(const DIE *Die, DwarfStringPoolEntryRef Name,
-                          bool SkipPubnamesSection = false);
-
-  /// Add a type accelerator entry for \p Die with \p Name which is stored in
-  /// the string table at \p Offset.
-  void addTypeAccelerator(const DIE *Die, DwarfStringPoolEntryRef Name,
-                          bool ObjcClassImplementation,
-                          uint32_t QualifiedNameHash);
-
-  struct AccelInfo {
-    /// Name of the entry.
-    DwarfStringPoolEntryRef Name;
-
-    /// DIE this entry describes.
-    const DIE *Die;
-
-    /// Hash of the fully qualified name.
-    uint32_t QualifiedNameHash;
-
-    /// Emit this entry only in the apple_* sections.
-    bool SkipPubSection;
-
-    /// Is this an ObjC class implementation?
-    bool ObjcClassImplementation;
-
-    AccelInfo(DwarfStringPoolEntryRef Name, const DIE *Die,
-              bool SkipPubSection = false)
-        : Name(Name), Die(Die), SkipPubSection(SkipPubSection) {}
-
-    AccelInfo(DwarfStringPoolEntryRef Name, const DIE *Die,
-              uint32_t QualifiedNameHash, bool ObjCClassIsImplementation)
-        : Name(Name), Die(Die), QualifiedNameHash(QualifiedNameHash),
-          SkipPubSection(false),
-          ObjcClassImplementation(ObjCClassIsImplementation) {}
-  };
-
-  const std::vector<AccelInfo> &getPubnames() const { return Pubnames; }
-  const std::vector<AccelInfo> &getPubtypes() const { return Pubtypes; }
-  const std::vector<AccelInfo> &getNamespaces() const { return Namespaces; }
-  const std::vector<AccelInfo> &getObjC() const { return ObjC; }
-
-  /// Get the full path for file \a FileNum in the line table
-  StringRef getResolvedPath(unsigned FileNum) {
-    if (FileNum >= ResolvedPaths.size())
-      return StringRef();
-    return ResolvedPaths[FileNum];
-  }
-
-  /// Set the fully resolved path for the line-table's file \a FileNum
-  /// to \a Path.
-  void setResolvedPath(unsigned FileNum, StringRef Path) {
-    if (ResolvedPaths.size() <= FileNum)
-      ResolvedPaths.resize(FileNum + 1);
-    ResolvedPaths[FileNum] = Path;
-  }
-
-private:
-  DWARFUnit &OrigUnit;
-  unsigned ID;
-  std::vector<DIEInfo> Info; ///< DIE info indexed by DIE index.
-  Optional<BasicDIEUnit> NewUnit;
-
-  uint64_t StartOffset;
-  uint64_t NextUnitOffset;
-
-  uint64_t LowPc = std::numeric_limits<uint64_t>::max();
-  uint64_t HighPc = 0;
-
-  /// A list of attributes to fixup with the absolute offset of
-  /// a DIE in the debug_info section.
-  ///
-  /// The offsets for the attributes in this array couldn't be set while
-  /// cloning because for cross-cu forward references the target DIE's offset
-  /// isn't known you emit the reference attribute.
-  std::vector<
-      std::tuple<DIE *, const CompileUnit *, DeclContext *, PatchLocation>>
-      ForwardDIEReferences;
-
-  FunctionIntervals::Allocator RangeAlloc;
-
-  /// The ranges in that interval map are the PC ranges for
-  /// functions in this unit, associated with the PC offset to apply
-  /// to the addresses to get the linked address.
-  FunctionIntervals Ranges;
-
-  /// The DW_AT_low_pc of each DW_TAG_label.
-  SmallDenseMap<uint64_t, uint64_t, 1> Labels;
-
-  /// DW_AT_ranges attributes to patch after we have gathered
-  /// all the unit's function addresses.
-  /// @{
-  std::vector<PatchLocation> RangeAttributes;
-  Optional<PatchLocation> UnitRangeAttribute;
-  /// @}
-
-  /// Location attributes that need to be transferred from the
-  /// original debug_loc section to the liked one. They are stored
-  /// along with the PC offset that is to be applied to their
-  /// function's address.
-  std::vector<std::pair<PatchLocation, int64_t>> LocationAttributes;
-
-  /// Accelerator entries for the unit, both for the pub*
-  /// sections and the apple* ones.
-  /// @{
-  std::vector<AccelInfo> Pubnames;
-  std::vector<AccelInfo> Pubtypes;
-  std::vector<AccelInfo> Namespaces;
-  std::vector<AccelInfo> ObjC;
-  /// @}
-
-  /// Cached resolved paths from the line table.
-  /// Note, the StringRefs here point in to the intern (uniquing) string pool.
-  /// This means that a StringRef returned here doesn't need to then be uniqued
-  /// for the purposes of getting a unique address for each string.
-  std::vector<StringRef> ResolvedPaths;
-
-  /// Is this unit subject to the ODR rule?
-  bool HasODR;
-
-  /// Did a DIE actually contain a valid reloc?
-  bool HasInterestingContent;
-
-  /// If this is a Clang module, this holds the module's name.
-  std::string ClangModuleName;
-};
-
-/// Check if the DIE at \p Idx is in the scope of a function.
-static bool inFunctionScope(CompileUnit &U, unsigned Idx) {
-  while (Idx) {
-    if (U.getOrigUnit().getDIEAtIndex(Idx).getTag() == dwarf::DW_TAG_subprogram)
-      return true;
-    Idx = U.getInfo(Idx).ParentIdx;
-  }
-  return false;
-}
-} // namespace
-
-void warn(Twine Warning, Twine Context) {
-  WithColor::warning() << Warning + "\n";
-  if (!Context.isTriviallyEmpty())
-    WithColor::note() << Twine("while processing ") + Context + "\n";
-}
-
-bool error(Twine Error, Twine Context) {
-  WithColor::error() << Error + "\n";
-  if (!Context.isTriviallyEmpty())
-    WithColor::note() << Twine("while processing ") + Context + "\n";
-  return false;
-}
-
-void CompileUnit::markEverythingAsKept() {
-  unsigned Idx = 0;
-
-  setHasInterestingContent();
-
-  for (auto &I : Info) {
-    // Mark everything that wasn't explicit marked for pruning.
-    I.Keep = !I.Prune;
-    auto DIE = OrigUnit.getDIEAtIndex(Idx++);
-
-    // Try to guess which DIEs must go to the accelerator tables. We do that
-    // just for variables, because functions will be handled depending on
-    // whether they carry a DW_AT_low_pc attribute or not.
-    if (DIE.getTag() != dwarf::DW_TAG_variable &&
-        DIE.getTag() != dwarf::DW_TAG_constant)
-      continue;
-
-    Optional<DWARFFormValue> Value;
-    if (!(Value = DIE.find(dwarf::DW_AT_location))) {
-      if ((Value = DIE.find(dwarf::DW_AT_const_value)) &&
-          !inFunctionScope(*this, I.ParentIdx))
-        I.InDebugMap = true;
-      continue;
-    }
-    if (auto Block = Value->getAsBlock()) {
-      if (Block->size() > OrigUnit.getAddressByteSize() &&
-          (*Block)[0] == dwarf::DW_OP_addr)
-        I.InDebugMap = true;
-    }
-  }
-}
-
-uint64_t CompileUnit::computeNextUnitOffset() {
-  NextUnitOffset = StartOffset + 11 /* Header size */;
-  // The root DIE might be null, meaning that the Unit had nothing to
-  // contribute to the linked output. In that case, we will emit the
-  // unit header without any actual DIE.
-  if (NewUnit)
-    NextUnitOffset += NewUnit->getUnitDie().getSize();
-  return NextUnitOffset;
-}
-
-/// Keep track of a forward cross-cu reference from this unit
-/// to \p Die that lives in \p RefUnit.
-void CompileUnit::noteForwardReference(DIE *Die, const CompileUnit *RefUnit,
-                                       DeclContext *Ctxt, PatchLocation Attr) {
-  ForwardDIEReferences.emplace_back(Die, RefUnit, Ctxt, Attr);
-}
-
-void CompileUnit::fixupForwardReferences() {
-  for (const auto &Ref : ForwardDIEReferences) {
-    DIE *RefDie;
-    const CompileUnit *RefUnit;
-    PatchLocation Attr;
-    DeclContext *Ctxt;
-    std::tie(RefDie, RefUnit, Ctxt, Attr) = Ref;
-    if (Ctxt && Ctxt->getCanonicalDIEOffset())
-      Attr.set(Ctxt->getCanonicalDIEOffset());
-    else
-      Attr.set(RefDie->getOffset() + RefUnit->getStartOffset());
-  }
-}
-
-void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {
-  Labels.insert({LabelLowPc, PcOffset});
-}
-
-void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc,
-                                   int64_t PcOffset) {
-  Ranges.insert(FuncLowPc, FuncHighPc, PcOffset);
-  this->LowPc = std::min(LowPc, FuncLowPc + PcOffset);
-  this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);
-}
-
-void CompileUnit::noteRangeAttribute(const DIE &Die, PatchLocation Attr) {
-  if (Die.getTag() != dwarf::DW_TAG_compile_unit)
-    RangeAttributes.push_back(Attr);
-  else
-    UnitRangeAttribute = Attr;
-}
-
-void CompileUnit::noteLocationAttribute(PatchLocation Attr, int64_t PcOffset) {
-  LocationAttributes.emplace_back(Attr, PcOffset);
-}
-
-void CompileUnit::addNamespaceAccelerator(const DIE *Die,
-                                          DwarfStringPoolEntryRef Name) {
-  Namespaces.emplace_back(Name, Die);
-}
-
-void CompileUnit::addObjCAccelerator(const DIE *Die,
-                                     DwarfStringPoolEntryRef Name,
-                                     bool SkipPubSection) {
-  ObjC.emplace_back(Name, Die, SkipPubSection);
-}
-
-void CompileUnit::addNameAccelerator(const DIE *Die,
-                                     DwarfStringPoolEntryRef Name,
-                                     bool SkipPubSection) {
-  Pubnames.emplace_back(Name, Die, SkipPubSection);
-}
-
-void CompileUnit::addTypeAccelerator(const DIE *Die,
-                                     DwarfStringPoolEntryRef Name,
-                                     bool ObjcClassImplementation,
-                                     uint32_t QualifiedNameHash) {
-  Pubtypes.emplace_back(Name, Die, QualifiedNameHash, ObjcClassImplementation);
-}
-
-namespace {
-
-/// 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 {
-  /// \defgroup MCObjects MC layer objects constructed by the streamer
-  /// @{
-  std::unique_ptr<MCRegisterInfo> MRI;
-  std::unique_ptr<MCAsmInfo> MAI;
-  std::unique_ptr<MCObjectFileInfo> MOFI;
-  std::unique_ptr<MCContext> MC;
-  MCAsmBackend *MAB; // Owned by MCStreamer
-  std::unique_ptr<MCInstrInfo> MII;
-  std::unique_ptr<MCSubtargetInfo> MSTI;
-  MCCodeEmitter *MCE; // Owned by MCStreamer
-  MCStreamer *MS;     // Owned by AsmPrinter
-  std::unique_ptr<TargetMachine> TM;
-  std::unique_ptr<AsmPrinter> Asm;
-  /// @}
-
-  /// The file we stream the linked Dwarf to.
-  raw_fd_ostream &OutFile;
-
-  uint32_t RangesSectionSize;
-  uint32_t LocSectionSize;
-  uint32_t LineSectionSize;
-  uint32_t FrameSectionSize;
-
-  /// Emit the pubnames or pubtypes section contribution for \p
-  /// Unit into \p Sec. The data is provided in \p Names.
-  void emitPubSectionForUnit(MCSection *Sec, StringRef Name,
-                             const CompileUnit &Unit,
-                             const std::vector<CompileUnit::AccelInfo> &Names);
-
-public:
-  DwarfStreamer(raw_fd_ostream &OutFile) : OutFile(OutFile) {}
-  bool init(Triple TheTriple);
-
-  /// Dump the file to the disk.
-  bool finish(const DebugMap &);
-
-  AsmPrinter &getAsmPrinter() const { return *Asm; }
-
-  /// Set the current output section to debug_info and change
-  /// the MC Dwarf version to \p DwarfVersion.
-  void switchToDebugInfoSection(unsigned DwarfVersion);
-
-  /// 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().
-  void emitCompileUnitHeader(CompileUnit &Unit);
-
-  /// Recursively emit the DIE tree rooted at \p Die.
-  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);
-
-  /// Emit the string table described by \p Pool.
-  void emitStrings(const NonRelocatableStringpool &Pool);
-
-  /// Emit the swift_ast section stored in \p Buffer.
-  void emitSwiftAST(StringRef Buffer);
-
-  /// Emit debug_ranges for \p FuncRange by translating the
-  /// original \p Entries.
-  void emitRangesEntries(
-      int64_t UnitPcOffset, uint64_t OrigLowPc,
-      const FunctionIntervals::const_iterator &FuncRange,
-      const std::vector<DWARFDebugRangeList::RangeListEntry> &Entries,
-      unsigned AddressSize);
-
-  /// Emit debug_aranges entries for \p Unit and if \p DoRangesSection is true,
-  /// also emit the debug_ranges entries for the DW_TAG_compile_unit's
-  /// DW_AT_ranges attribute.
-  void emitUnitRangesEntries(CompileUnit &Unit, bool DoRangesSection);
-
-  uint32_t getRangesSectionSize() const { return RangesSectionSize; }
-
-  /// Emit the debug_loc contribution for \p Unit by copying the entries from
-  /// \p Dwarf and offsetting them. Update the location attributes to point to
-  /// the new entries.
-  void emitLocationsForUnit(const CompileUnit &Unit, DWARFContext &Dwarf);
-
-  /// Emit the line table described in \p Rows into the debug_line section.
-  void emitLineTableForUnit(MCDwarfLineTableParams Params,
-                            StringRef PrologueBytes, unsigned MinInstLength,
-                            std::vector<DWARFDebugLine::Row> &Rows,
-                            unsigned AdddressSize);
-
-  /// Copy over the debug sections that are not modified when updating.
-  void copyInvariantDebugSection(const object::ObjectFile &Obj, LinkOptions &);
-
-  uint32_t getLineSectionSize() const { return LineSectionSize; }
-
-  /// Emit the .debug_pubnames contribution for \p Unit.
-  void emitPubNamesForUnit(const CompileUnit &Unit);
-
-  /// Emit the .debug_pubtypes contribution for \p Unit.
-  void emitPubTypesForUnit(const CompileUnit &Unit);
-
-  /// Emit a CIE.
-  void emitCIE(StringRef CIEBytes);
-
-  /// Emit an FDE with data \p Bytes.
-  void emitFDE(uint32_t CIEOffset, uint32_t AddreSize, uint32_t Address,
-               StringRef Bytes);
-
-  /// Emit Apple namespaces accelerator table.
-  void emitAppleNamespaces(AccelTable<AppleAccelTableStaticOffsetData> &Table);
-
-  /// Emit Apple names accelerator table.
-  void emitAppleNames(AccelTable<AppleAccelTableStaticOffsetData> &Table);
-
-  /// Emit Apple Objective-C accelerator table.
-  void emitAppleObjc(AccelTable<AppleAccelTableStaticOffsetData> &Table);
-
-  /// Emit Apple type accelerator table.
-  void emitAppleTypes(AccelTable<AppleAccelTableStaticTypeData> &Table);
-
-  uint32_t getFrameSectionSize() const { return FrameSectionSize; }
-};
-
-} // end anonymous namespace
-
-bool DwarfStreamer::init(Triple TheTriple) {
-  std::string ErrorStr;
-  std::string TripleName;
-  StringRef Context = "dwarf streamer init";
-
-  // Get the target.
-  const Target *TheTarget =
-      TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr);
-  if (!TheTarget)
-    return error(ErrorStr, Context);
-  TripleName = TheTriple.getTriple();
-
-  // Create all the MC Objects.
-  MRI.reset(TheTarget->createMCRegInfo(TripleName));
-  if (!MRI)
-    return error(Twine("no register info for target ") + TripleName, Context);
-
-  MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName));
-  if (!MAI)
-    return error("no asm info for target " + TripleName, Context);
-
-  MOFI.reset(new MCObjectFileInfo);
-  MC.reset(new MCContext(MAI.get(), MRI.get(), MOFI.get()));
-  MOFI->InitMCObjectFileInfo(TheTriple, /*PIC*/ false, *MC);
-
-  MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
-  if (!MSTI)
-    return error("no subtarget info for target " + TripleName, Context);
-
-  MCTargetOptions Options;
-  MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, Options);
-  if (!MAB)
-    return error("no asm backend for target " + TripleName, Context);
-
-  MII.reset(TheTarget->createMCInstrInfo());
-  if (!MII)
-    return error("no instr info info for target " + TripleName, Context);
-
-  MCE = TheTarget->createMCCodeEmitter(*MII, *MRI, *MC);
-  if (!MCE)
-    return error("no code emitter for target " + TripleName, Context);
-
-  MCTargetOptions MCOptions = InitMCTargetOptionsFromFlags();
-  MS = TheTarget->createMCObjectStreamer(
-      TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB),
-      MAB->createObjectWriter(OutFile), std::unique_ptr<MCCodeEmitter>(MCE),
-      *MSTI, MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible,
-      /*DWARFMustBeAtTheEnd*/ false);
-  if (!MS)
-    return error("no object streamer for target " + TripleName, Context);
-
-  // Finally create the AsmPrinter we'll use to emit the DIEs.
-  TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions(),
-                                          None));
-  if (!TM)
-    return error("no target machine for target " + TripleName, Context);
-
-  Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS)));
-  if (!Asm)
-    return error("no asm printer for target " + TripleName, Context);
-
-  RangesSectionSize = 0;
-  LocSectionSize = 0;
-  LineSectionSize = 0;
-  FrameSectionSize = 0;
-
-  return true;
-}
-
-bool DwarfStreamer::finish(const DebugMap &DM) {
-  bool Result = true;
-  if (DM.getTriple().isOSDarwin() && !DM.getBinaryPath().empty())
-    Result = MachOUtils::generateDsymCompanion(DM, *MS, OutFile);
-  else
-    MS->Finish();
-  return Result;
-}
-
-void DwarfStreamer::switchToDebugInfoSection(unsigned DwarfVersion) {
-  MS->SwitchSection(MOFI->getDwarfInfoSection());
-  MC->setDwarfVersion(DwarfVersion);
-}
-
-/// Emit the compilation unit header for \p Unit in the debug_info section.
-///
-/// A Dwarf section header is encoded as:
-///  uint32_t   Unit length (omitting this field)
-///  uint16_t   Version
-///  uint32_t   Abbreviation table offset
-///  uint8_t    Address size
-///
-/// Leading to a total of 11 bytes.
-void DwarfStreamer::emitCompileUnitHeader(CompileUnit &Unit) {
-  unsigned Version = Unit.getOrigUnit().getVersion();
-  switchToDebugInfoSection(Version);
-
-  // Emit size of content not including length itself. The size has already
-  // been computed in CompileUnit::computeOffsets(). Subtract 4 to that size to
-  // account for the length field.
-  Asm->emitInt32(Unit.getNextUnitOffset() - Unit.getStartOffset() - 4);
-  Asm->emitInt16(Version);
-  // We share one abbreviations table across all units so it's always at the
-  // start of the section.
-  Asm->emitInt32(0);
-  Asm->emitInt8(Unit.getOrigUnit().getAddressByteSize());
-}
-
-/// Emit the \p Abbrevs array as the shared abbreviation table
-/// for the linked Dwarf file.
-void DwarfStreamer::emitAbbrevs(
-    const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs,
-    unsigned DwarfVersion) {
-  MS->SwitchSection(MOFI->getDwarfAbbrevSection());
-  MC->setDwarfVersion(DwarfVersion);
-  Asm->emitDwarfAbbrevs(Abbrevs);
-}
-
-/// Recursively emit the DIE tree rooted at \p Die.
-void DwarfStreamer::emitDIE(DIE &Die) {
-  MS->SwitchSection(MOFI->getDwarfInfoSection());
-  Asm->emitDwarfDIE(Die);
-}
-
-/// Emit the debug_str section stored in \p Pool.
-void DwarfStreamer::emitStrings(const NonRelocatableStringpool &Pool) {
-  Asm->OutStreamer->SwitchSection(MOFI->getDwarfStrSection());
-  std::vector<DwarfStringPoolEntryRef> Entries = Pool.getEntries();
-  for (auto Entry : Entries) {
-    if (Entry.getIndex() == -1U)
-      break;
-    // Emit the string itself.
-    Asm->OutStreamer->EmitBytes(Entry.getString());
-    // Emit a null terminator.
-    Asm->emitInt8(0);
-  }
-}
-
-void DwarfStreamer::emitAppleNamespaces(
-    AccelTable<AppleAccelTableStaticOffsetData> &Table) {
-  Asm->OutStreamer->SwitchSection(MOFI->getDwarfAccelNamespaceSection());
-  auto *SectionBegin = Asm->createTempSymbol("namespac_begin");
-  Asm->OutStreamer->EmitLabel(SectionBegin);
-  emitAppleAccelTable(Asm.get(), Table, "namespac", SectionBegin);
-}
-
-void DwarfStreamer::emitAppleNames(
-    AccelTable<AppleAccelTableStaticOffsetData> &Table) {
-  Asm->OutStreamer->SwitchSection(MOFI->getDwarfAccelNamesSection());
-  auto *SectionBegin = Asm->createTempSymbol("names_begin");
-  Asm->OutStreamer->EmitLabel(SectionBegin);
-  emitAppleAccelTable(Asm.get(), Table, "names", SectionBegin);
-}
-
-void DwarfStreamer::emitAppleObjc(
-    AccelTable<AppleAccelTableStaticOffsetData> &Table) {
-  Asm->OutStreamer->SwitchSection(MOFI->getDwarfAccelObjCSection());
-  auto *SectionBegin = Asm->createTempSymbol("objc_begin");
-  Asm->OutStreamer->EmitLabel(SectionBegin);
-  emitAppleAccelTable(Asm.get(), Table, "objc", SectionBegin);
-}
-
-void DwarfStreamer::emitAppleTypes(
-    AccelTable<AppleAccelTableStaticTypeData> &Table) {
-  Asm->OutStreamer->SwitchSection(MOFI->getDwarfAccelTypesSection());
-  auto *SectionBegin = Asm->createTempSymbol("types_begin");
-  Asm->OutStreamer->EmitLabel(SectionBegin);
-  emitAppleAccelTable(Asm.get(), Table, "types", SectionBegin);
-}
-
-/// Emit the swift_ast section stored in \p Buffers.
-void DwarfStreamer::emitSwiftAST(StringRef Buffer) {
-  MCSection *SwiftASTSection = MOFI->getDwarfSwiftASTSection();
-  SwiftASTSection->setAlignment(1 << 5);
-  MS->SwitchSection(SwiftASTSection);
-  MS->EmitBytes(Buffer);
-}
-
-/// Emit the debug_range section contents for \p FuncRange by
-/// translating the original \p Entries. The debug_range section
-/// format is totally trivial, consisting just of pairs of address
-/// sized addresses describing the ranges.
-void DwarfStreamer::emitRangesEntries(
-    int64_t UnitPcOffset, uint64_t OrigLowPc,
-    const FunctionIntervals::const_iterator &FuncRange,
-    const std::vector<DWARFDebugRangeList::RangeListEntry> &Entries,
-    unsigned AddressSize) {
-  MS->SwitchSection(MC->getObjectFileInfo()->getDwarfRangesSection());
-
-  // Offset each range by the right amount.
-  int64_t PcOffset = Entries.empty() ? 0 : FuncRange.value() + UnitPcOffset;
-  for (const auto &Range : Entries) {
-    if (Range.isBaseAddressSelectionEntry(AddressSize)) {
-      warn("unsupported base address selection operation",
-           "emitting debug_ranges");
-      break;
-    }
-    // Do not emit empty ranges.
-    if (Range.StartAddress == Range.EndAddress)
-      continue;
-
-    // All range entries should lie in the function range.
-    if (!(Range.StartAddress + OrigLowPc >= FuncRange.start() &&
-          Range.EndAddress + OrigLowPc <= FuncRange.stop()))
-      warn("inconsistent range data.", "emitting debug_ranges");
-    MS->EmitIntValue(Range.StartAddress + PcOffset, AddressSize);
-    MS->EmitIntValue(Range.EndAddress + PcOffset, AddressSize);
-    RangesSectionSize += 2 * AddressSize;
-  }
-
-  // Add the terminator entry.
-  MS->EmitIntValue(0, AddressSize);
-  MS->EmitIntValue(0, AddressSize);
-  RangesSectionSize += 2 * AddressSize;
-}
-
-/// Emit the debug_aranges contribution of a unit and
-/// if \p DoDebugRanges is true the debug_range contents for a
-/// compile_unit level DW_AT_ranges attribute (Which are basically the
-/// same thing with a different base address).
-/// Just aggregate all the ranges gathered inside that unit.
-void DwarfStreamer::emitUnitRangesEntries(CompileUnit &Unit,
-                                          bool DoDebugRanges) {
-  unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
-  // Gather the ranges in a vector, so that we can simplify them. The
-  // IntervalMap will have coalesced the non-linked ranges, but here
-  // we want to coalesce the linked addresses.
-  std::vector<std::pair<uint64_t, uint64_t>> Ranges;
-  const auto &FunctionRanges = Unit.getFunctionRanges();
-  for (auto Range = FunctionRanges.begin(), End = FunctionRanges.end();
-       Range != End; ++Range)
-    Ranges.push_back(std::make_pair(Range.start() + Range.value(),
-                                    Range.stop() + Range.value()));
-
-  // The object addresses where sorted, but again, the linked
-  // addresses might end up in a different order.
-  llvm::sort(Ranges.begin(), Ranges.end());
-
-  if (!Ranges.empty()) {
-    MS->SwitchSection(MC->getObjectFileInfo()->getDwarfARangesSection());
-
-    MCSymbol *BeginLabel = Asm->createTempSymbol("Barange");
-    MCSymbol *EndLabel = Asm->createTempSymbol("Earange");
-
-    unsigned HeaderSize =
-        sizeof(int32_t) + // Size of contents (w/o this field
-        sizeof(int16_t) + // DWARF ARange version number
-        sizeof(int32_t) + // Offset of CU in the .debug_info section
-        sizeof(int8_t) +  // Pointer Size (in bytes)
-        sizeof(int8_t);   // Segment Size (in bytes)
-
-    unsigned TupleSize = AddressSize * 2;
-    unsigned Padding = OffsetToAlignment(HeaderSize, TupleSize);
-
-    Asm->EmitLabelDifference(EndLabel, BeginLabel, 4); // Arange length
-    Asm->OutStreamer->EmitLabel(BeginLabel);
-    Asm->emitInt16(dwarf::DW_ARANGES_VERSION); // Version number
-    Asm->emitInt32(Unit.getStartOffset());     // Corresponding unit's offset
-    Asm->emitInt8(AddressSize);                // Address size
-    Asm->emitInt8(0);                          // Segment size
-
-    Asm->OutStreamer->emitFill(Padding, 0x0);
-
-    for (auto Range = Ranges.begin(), End = Ranges.end(); Range != End;
-         ++Range) {
-      uint64_t RangeStart = Range->first;
-      MS->EmitIntValue(RangeStart, AddressSize);
-      while ((Range + 1) != End && Range->second == (Range + 1)->first)
-        ++Range;
-      MS->EmitIntValue(Range->second - RangeStart, AddressSize);
-    }
-
-    // Emit terminator
-    Asm->OutStreamer->EmitIntValue(0, AddressSize);
-    Asm->OutStreamer->EmitIntValue(0, AddressSize);
-    Asm->OutStreamer->EmitLabel(EndLabel);
-  }
-
-  if (!DoDebugRanges)
-    return;
-
-  MS->SwitchSection(MC->getObjectFileInfo()->getDwarfRangesSection());
-  // Offset each range by the right amount.
-  int64_t PcOffset = -Unit.getLowPc();
-  // Emit coalesced ranges.
-  for (auto Range = Ranges.begin(), End = Ranges.end(); Range != End; ++Range) {
-    MS->EmitIntValue(Range->first + PcOffset, AddressSize);
-    while (Range + 1 != End && Range->second == (Range + 1)->first)
-      ++Range;
-    MS->EmitIntValue(Range->second + PcOffset, AddressSize);
-    RangesSectionSize += 2 * AddressSize;
-  }
-
-  // Add the terminator entry.
-  MS->EmitIntValue(0, AddressSize);
-  MS->EmitIntValue(0, AddressSize);
-  RangesSectionSize += 2 * AddressSize;
-}
-
-/// Emit location lists for \p Unit and update attributes to point to the new
-/// entries.
-void DwarfStreamer::emitLocationsForUnit(const CompileUnit &Unit,
-                                         DWARFContext &Dwarf) {
-  const auto &Attributes = Unit.getLocationAttributes();
-
-  if (Attributes.empty())
-    return;
-
-  MS->SwitchSection(MC->getObjectFileInfo()->getDwarfLocSection());
-
-  unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
-  const DWARFSection &InputSec = Dwarf.getDWARFObj().getLocSection();
-  DataExtractor Data(InputSec.Data, Dwarf.isLittleEndian(), AddressSize);
-  DWARFUnit &OrigUnit = Unit.getOrigUnit();
-  auto OrigUnitDie = OrigUnit.getUnitDIE(false);
-  int64_t UnitPcOffset = 0;
-  if (auto OrigLowPc = dwarf::toAddress(OrigUnitDie.find(dwarf::DW_AT_low_pc)))
-    UnitPcOffset = int64_t(*OrigLowPc) - Unit.getLowPc();
-
-  for (const auto &Attr : Attributes) {
-    uint32_t Offset = Attr.first.get();
-    Attr.first.set(LocSectionSize);
-    // This is the quantity to add to the old location address to get
-    // the correct address for the new one.
-    int64_t LocPcOffset = Attr.second + UnitPcOffset;
-    while (Data.isValidOffset(Offset)) {
-      uint64_t Low = Data.getUnsigned(&Offset, AddressSize);
-      uint64_t High = Data.getUnsigned(&Offset, AddressSize);
-      LocSectionSize += 2 * AddressSize;
-      if (Low == 0 && High == 0) {
-        Asm->OutStreamer->EmitIntValue(0, AddressSize);
-        Asm->OutStreamer->EmitIntValue(0, AddressSize);
-        break;
-      }
-      Asm->OutStreamer->EmitIntValue(Low + LocPcOffset, AddressSize);
-      Asm->OutStreamer->EmitIntValue(High + LocPcOffset, AddressSize);
-      uint64_t Length = Data.getU16(&Offset);
-      Asm->OutStreamer->EmitIntValue(Length, 2);
-      // Just copy the bytes over.
-      Asm->OutStreamer->EmitBytes(
-          StringRef(InputSec.Data.substr(Offset, Length)));
-      Offset += Length;
-      LocSectionSize += Length + 2;
-    }
-  }
-}
-
-void DwarfStreamer::emitLineTableForUnit(MCDwarfLineTableParams Params,
-                                         StringRef PrologueBytes,
-                                         unsigned MinInstLength,
-                                         std::vector<DWARFDebugLine::Row> &Rows,
-                                         unsigned PointerSize) {
-  // Switch to the section where the table will be emitted into.
-  MS->SwitchSection(MC->getObjectFileInfo()->getDwarfLineSection());
-  MCSymbol *LineStartSym = MC->createTempSymbol();
-  MCSymbol *LineEndSym = MC->createTempSymbol();
-
-  // The first 4 bytes is the total length of the information for this
-  // compilation unit (not including these 4 bytes for the length).
-  Asm->EmitLabelDifference(LineEndSym, LineStartSym, 4);
-  Asm->OutStreamer->EmitLabel(LineStartSym);
-  // Copy Prologue.
-  MS->EmitBytes(PrologueBytes);
-  LineSectionSize += PrologueBytes.size() + 4;
-
-  SmallString<128> EncodingBuffer;
-  raw_svector_ostream EncodingOS(EncodingBuffer);
-
-  if (Rows.empty()) {
-    // We only have the dummy entry, dsymutil emits an entry with a 0
-    // address in that case.
-    MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0,
-                            EncodingOS);
-    MS->EmitBytes(EncodingOS.str());
-    LineSectionSize += EncodingBuffer.size();
-    MS->EmitLabel(LineEndSym);
-    return;
-  }
-
-  // Line table state machine fields
-  unsigned FileNum = 1;
-  unsigned LastLine = 1;
-  unsigned Column = 0;
-  unsigned IsStatement = 1;
-  unsigned Isa = 0;
-  uint64_t Address = -1ULL;
-
-  unsigned RowsSinceLastSequence = 0;
-
-  for (unsigned Idx = 0; Idx < Rows.size(); ++Idx) {
-    auto &Row = Rows[Idx];
-
-    int64_t AddressDelta;
-    if (Address == -1ULL) {
-      MS->EmitIntValue(dwarf::DW_LNS_extended_op, 1);
-      MS->EmitULEB128IntValue(PointerSize + 1);
-      MS->EmitIntValue(dwarf::DW_LNE_set_address, 1);
-      MS->EmitIntValue(Row.Address, PointerSize);
-      LineSectionSize += 2 + PointerSize + getULEB128Size(PointerSize + 1);
-      AddressDelta = 0;
-    } else {
-      AddressDelta = (Row.Address - Address) / MinInstLength;
-    }
-
-    // FIXME: code copied and transformed from MCDwarf.cpp::EmitDwarfLineTable.
-    // We should find a way to share this code, but the current compatibility
-    // requirement with classic dsymutil makes it hard. Revisit that once this
-    // requirement is dropped.
-
-    if (FileNum != Row.File) {
-      FileNum = Row.File;
-      MS->EmitIntValue(dwarf::DW_LNS_set_file, 1);
-      MS->EmitULEB128IntValue(FileNum);
-      LineSectionSize += 1 + getULEB128Size(FileNum);
-    }
-    if (Column != Row.Column) {
-      Column = Row.Column;
-      MS->EmitIntValue(dwarf::DW_LNS_set_column, 1);
-      MS->EmitULEB128IntValue(Column);
-      LineSectionSize += 1 + getULEB128Size(Column);
-    }
-
-    // FIXME: We should handle the discriminator here, but dsymutil doesn't
-    // consider it, thus ignore it for now.
-
-    if (Isa != Row.Isa) {
-      Isa = Row.Isa;
-      MS->EmitIntValue(dwarf::DW_LNS_set_isa, 1);
-      MS->EmitULEB128IntValue(Isa);
-      LineSectionSize += 1 + getULEB128Size(Isa);
-    }
-    if (IsStatement != Row.IsStmt) {
-      IsStatement = Row.IsStmt;
-      MS->EmitIntValue(dwarf::DW_LNS_negate_stmt, 1);
-      LineSectionSize += 1;
-    }
-    if (Row.BasicBlock) {
-      MS->EmitIntValue(dwarf::DW_LNS_set_basic_block, 1);
-      LineSectionSize += 1;
-    }
-
-    if (Row.PrologueEnd) {
-      MS->EmitIntValue(dwarf::DW_LNS_set_prologue_end, 1);
-      LineSectionSize += 1;
-    }
-
-    if (Row.EpilogueBegin) {
-      MS->EmitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1);
-      LineSectionSize += 1;
-    }
-
-    int64_t LineDelta = int64_t(Row.Line) - LastLine;
-    if (!Row.EndSequence) {
-      MCDwarfLineAddr::Encode(*MC, Params, LineDelta, AddressDelta, EncodingOS);
-      MS->EmitBytes(EncodingOS.str());
-      LineSectionSize += EncodingBuffer.size();
-      EncodingBuffer.resize(0);
-      Address = Row.Address;
-      LastLine = Row.Line;
-      RowsSinceLastSequence++;
-    } else {
-      if (LineDelta) {
-        MS->EmitIntValue(dwarf::DW_LNS_advance_line, 1);
-        MS->EmitSLEB128IntValue(LineDelta);
-        LineSectionSize += 1 + getSLEB128Size(LineDelta);
-      }
-      if (AddressDelta) {
-        MS->EmitIntValue(dwarf::DW_LNS_advance_pc, 1);
-        MS->EmitULEB128IntValue(AddressDelta);
-        LineSectionSize += 1 + getULEB128Size(AddressDelta);
-      }
-      MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(),
-                              0, EncodingOS);
-      MS->EmitBytes(EncodingOS.str());
-      LineSectionSize += EncodingBuffer.size();
-      EncodingBuffer.resize(0);
-      Address = -1ULL;
-      LastLine = FileNum = IsStatement = 1;
-      RowsSinceLastSequence = Column = Isa = 0;
-    }
-  }
-
-  if (RowsSinceLastSequence) {
-    MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0,
-                            EncodingOS);
-    MS->EmitBytes(EncodingOS.str());
-    LineSectionSize += EncodingBuffer.size();
-    EncodingBuffer.resize(0);
-  }
-
-  MS->EmitLabel(LineEndSym);
-}
-
-static void emitSectionContents(const object::ObjectFile &Obj,
-                                StringRef SecName, MCStreamer *MS) {
-  StringRef Contents;
-  if (auto Sec = getSectionByName(Obj, SecName))
-    if (!Sec->getContents(Contents))
-      MS->EmitBytes(Contents);
-}
-
-void DwarfStreamer::copyInvariantDebugSection(const object::ObjectFile &Obj,
-                                              LinkOptions &Options) {
-  MS->SwitchSection(MC->getObjectFileInfo()->getDwarfLineSection());
-  emitSectionContents(Obj, "debug_line", MS);
-
-  MS->SwitchSection(MC->getObjectFileInfo()->getDwarfLocSection());
-  emitSectionContents(Obj, "debug_loc", MS);
-
-  MS->SwitchSection(MC->getObjectFileInfo()->getDwarfRangesSection());
-  emitSectionContents(Obj, "debug_ranges", MS);
-
-  MS->SwitchSection(MC->getObjectFileInfo()->getDwarfFrameSection());
-  emitSectionContents(Obj, "debug_frame", MS);
-
-  MS->SwitchSection(MC->getObjectFileInfo()->getDwarfARangesSection());
-  emitSectionContents(Obj, "debug_aranges", MS);
-}
-
-/// Emit the pubnames or pubtypes section contribution for \p
-/// Unit into \p Sec. The data is provided in \p Names.
-void DwarfStreamer::emitPubSectionForUnit(
-    MCSection *Sec, StringRef SecName, const CompileUnit &Unit,
-    const std::vector<CompileUnit::AccelInfo> &Names) {
-  if (Names.empty())
-    return;
-
-  // Start the dwarf pubnames section.
-  Asm->OutStreamer->SwitchSection(Sec);
-  MCSymbol *BeginLabel = Asm->createTempSymbol("pub" + SecName + "_begin");
-  MCSymbol *EndLabel = Asm->createTempSymbol("pub" + SecName + "_end");
-
-  bool HeaderEmitted = false;
-  // Emit the pubnames for this compilation unit.
-  for (const auto &Name : Names) {
-    if (Name.SkipPubSection)
-      continue;
-
-    if (!HeaderEmitted) {
-      // Emit the header.
-      Asm->EmitLabelDifference(EndLabel, BeginLabel, 4); // Length
-      Asm->OutStreamer->EmitLabel(BeginLabel);
-      Asm->emitInt16(dwarf::DW_PUBNAMES_VERSION); // Version
-      Asm->emitInt32(Unit.getStartOffset());      // Unit offset
-      Asm->emitInt32(Unit.getNextUnitOffset() - Unit.getStartOffset()); // Size
-      HeaderEmitted = true;
-    }
-    Asm->emitInt32(Name.Die->getOffset());
-
-    // Emit the string itself.
-    Asm->OutStreamer->EmitBytes(Name.Name.getString());
-    // Emit a null terminator.
-    Asm->emitInt8(0);
-  }
-
-  if (!HeaderEmitted)
-    return;
-  Asm->emitInt32(0); // End marker.
-  Asm->OutStreamer->EmitLabel(EndLabel);
-}
-
-/// Emit .debug_pubnames for \p Unit.
-void DwarfStreamer::emitPubNamesForUnit(const CompileUnit &Unit) {
-  emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubNamesSection(),
-                        "names", Unit, Unit.getPubnames());
-}
-
-/// Emit .debug_pubtypes for \p Unit.
-void DwarfStreamer::emitPubTypesForUnit(const CompileUnit &Unit) {
-  emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubTypesSection(),
-                        "types", Unit, Unit.getPubtypes());
-}
-
-/// Emit a CIE into the debug_frame section.
-void DwarfStreamer::emitCIE(StringRef CIEBytes) {
-  MS->SwitchSection(MC->getObjectFileInfo()->getDwarfFrameSection());
-
-  MS->EmitBytes(CIEBytes);
-  FrameSectionSize += CIEBytes.size();
-}
-
-/// Emit a FDE into the debug_frame section. \p FDEBytes
-/// contains the FDE data without the length, CIE offset and address
-/// which will be replaced with the parameter values.
-void DwarfStreamer::emitFDE(uint32_t CIEOffset, uint32_t AddrSize,
-                            uint32_t Address, StringRef FDEBytes) {
-  MS->SwitchSection(MC->getObjectFileInfo()->getDwarfFrameSection());
-
-  MS->EmitIntValue(FDEBytes.size() + 4 + AddrSize, 4);
-  MS->EmitIntValue(CIEOffset, 4);
-  MS->EmitIntValue(Address, AddrSize);
-  MS->EmitBytes(FDEBytes);
-  FrameSectionSize += FDEBytes.size() + 8 + AddrSize;
-}
-
-namespace {
-
-/// Partial address range for debug map objects. Besides an offset, only the
-/// HighPC is stored. The structure is stored in a map where the LowPC is the
-/// key.
-struct DebugMapObjectRange {
-  /// Function HighPC.
-  uint64_t HighPC;
-  /// Offset to apply to the linked address.
-  int64_t Offset;
-
-  DebugMapObjectRange(uint64_t EndPC, int64_t Offset)
-      : HighPC(EndPC), Offset(Offset) {}
-
-  DebugMapObjectRange() : HighPC(0), Offset(0) {}
-};
-
-/// Map LowPC to DebugMapObjectRange.
-using RangesTy = std::map<uint64_t, DebugMapObjectRange>;
-using UnitListTy = std::vector<std::unique_ptr<CompileUnit>>;
-
-/// The core of the Dwarf linking logic.
-///
-/// The link 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 are present in the linked
-/// binary (and thus have entries in the debug map). All the debug
-/// information that will be linked (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
-/// correspond to a debug map entry at specific places (the low_pc for
-/// a function, the location for a variable). These relocations are
-/// called ValidRelocs in the DwarfLinker and are gathered as a very
-/// first step when we start processing a DebugMapObject.
-class DwarfLinker {
-public:
-  DwarfLinker(raw_fd_ostream &OutFile, const LinkOptions &Options)
-      : OutFile(OutFile), Options(Options) {}
-
-  /// Link the contents of the DebugMap.
-  bool link(const DebugMap &);
-
-  void reportWarning(const Twine &Warning, const DebugMapObject &DMO,
-                     const DWARFDie *DIE = nullptr) const;
-
-private:
-  /// Remembers the newest DWARF version we've seen in a unit.
-  void maybeUpdateMaxDwarfVersion(unsigned Version) {
-    if (MaxDwarfVersion < Version)
-      MaxDwarfVersion = Version;
-  }
-
-  /// Emit warnings as Dwarf compile units to leave a trail after linking.
-  bool emitPaperTrailWarnings(const DebugMapObject &DMO, const DebugMap &Map,
-                              OffsetsStringPool &StringPool);
-
-  /// Keeps track of relocations.
-  class RelocationManager {
-    struct ValidReloc {
-      uint32_t Offset;
-      uint32_t Size;
-      uint64_t Addend;
-      const DebugMapObject::DebugMapEntry *Mapping;
-
-      ValidReloc(uint32_t Offset, uint32_t Size, uint64_t Addend,
-                 const DebugMapObject::DebugMapEntry *Mapping)
-          : Offset(Offset), Size(Size), Addend(Addend), Mapping(Mapping) {}
-
-      bool operator<(const ValidReloc &RHS) const {
-        return Offset < RHS.Offset;
-      }
-    };
-
-    const DwarfLinker &Linker;
-
-    /// The valid relocations for the current DebugMapObject.
-    /// This vector is sorted by relocation offset.
-    std::vector<ValidReloc> ValidRelocs;
-
-    /// Index into ValidRelocs of the next relocation to consider. As we walk
-    /// the DIEs in acsending file offset and as ValidRelocs is sorted by file
-    /// offset, keeping this index up to date is all we have to do to have a
-    /// cheap lookup during the root DIE selection and during DIE cloning.
-    unsigned NextValidReloc = 0;
-
-  public:
-    RelocationManager(DwarfLinker &Linker) : Linker(Linker) {}
-
-    bool hasValidRelocs() const { return !ValidRelocs.empty(); }
-
-    /// Reset the NextValidReloc counter.
-    void resetValidRelocs() { NextValidReloc = 0; }
-
-    /// \defgroup FindValidRelocations Translate debug map into a list
-    /// of relevant relocations
-    ///
-    /// @{
-    bool findValidRelocsInDebugInfo(const object::ObjectFile &Obj,
-                                    const DebugMapObject &DMO);
-
-    bool findValidRelocs(const object::SectionRef &Section,
-                         const object::ObjectFile &Obj,
-                         const DebugMapObject &DMO);
-
-    void findValidRelocsMachO(const object::SectionRef &Section,
-                              const object::MachOObjectFile &Obj,
-                              const DebugMapObject &DMO);
-    /// @}
-
-    bool hasValidRelocation(uint32_t StartOffset, uint32_t EndOffset,
-                            CompileUnit::DIEInfo &Info);
-
-    bool applyValidRelocs(MutableArrayRef<char> Data, uint32_t BaseOffset,
-                          bool isLittleEndian);
-  };
-
-  /// Keeps track of data associated with one object during linking.
-  struct LinkContext {
-    DebugMapObject &DMO;
-    BinaryHolder BinHolder;
-    const object::ObjectFile *ObjectFile;
-    RelocationManager RelocMgr;
-    std::unique_ptr<DWARFContext> DwarfContext;
-    RangesTy Ranges;
-    UnitListTy CompileUnits;
-
-    LinkContext(const DebugMap &Map, DwarfLinker &Linker, DebugMapObject &DMO,
-                bool Verbose = false)
-        : DMO(DMO), BinHolder(Verbose), RelocMgr(Linker) {
-      // Swift ASTs are not object files.
-      if (DMO.getType() == MachO::N_AST) {
-        ObjectFile = nullptr;
-        return;
-      }
-      auto ErrOrObj = Linker.loadObject(BinHolder, DMO, Map);
-      ObjectFile = ErrOrObj ? &*ErrOrObj : nullptr;
-      DwarfContext = ObjectFile ? DWARFContext::create(*ObjectFile) : nullptr;
-    }
-
-    /// Clear compile units and ranges.
-    void Clear() {
-      CompileUnits.clear();
-      Ranges.clear();
-    }
-  };
-
-  /// Called at the start of a debug object link.
-  void startDebugObject(LinkContext &Context);
-
-  /// Called at the end of a debug object link.
-  void endDebugObject(LinkContext &Context);
-
-  /// \defgroup FindRootDIEs Find DIEs corresponding to debug map entries.
-  ///
-  /// @{
-  /// Recursively walk the \p DIE tree and look for DIEs to
-  /// keep. Store that information in \p CU's DIEInfo.
-  ///
-  /// The return value indicates whether the DIE is incomplete.
-  bool lookForDIEsToKeep(RelocationManager &RelocMgr, RangesTy &Ranges,
-                         UnitListTy &Units, const DWARFDie &DIE,
-                         const DebugMapObject &DMO, CompileUnit &CU,
-                         unsigned Flags);
-
-  /// If this compile unit is really a skeleton CU that points to a
-  /// clang module, register it in ClangModules and return true.
-  ///
-  /// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name
-  /// pointing to the module, and a DW_AT_gnu_dwo_id with the module
-  /// hash.
-  bool registerModuleReference(const DWARFDie &CUDie, const DWARFUnit &Unit,
-                               DebugMap &ModuleMap, const DebugMapObject &DMO,
-                               RangesTy &Ranges,
-                               OffsetsStringPool &OffsetsStringPool,
-                               UniquingStringPool &UniquingStringPoolStringPool,
-                               DeclContextTree &ODRContexts, unsigned &UnitID,
-                               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 Units.
-  Error loadClangModule(StringRef Filename, StringRef ModulePath,
-                        StringRef ModuleName, uint64_t DwoId,
-                        DebugMap &ModuleMap, const DebugMapObject &DMO,
-                        RangesTy &Ranges, OffsetsStringPool &OffsetsStringPool,
-                        UniquingStringPool &UniquingStringPool,
-                        DeclContextTree &ODRContexts, unsigned &UnitID,
-                        unsigned Indent = 0);
-
-  /// Flags passed to DwarfLinker::lookForDIEsToKeep
-  enum TraversalFlags {
-    TF_Keep = 1 << 0,            ///< Mark the traversed DIEs as kept.
-    TF_InFunctionScope = 1 << 1, ///< Current scope is a function scope.
-    TF_DependencyWalk = 1 << 2,  ///< Walking the dependencies of a kept DIE.
-    TF_ParentWalk = 1 << 3,      ///< Walking up the parents of a kept DIE.
-    TF_ODR = 1 << 4,             ///< Use the ODR while keeping dependents.
-    TF_SkipPC = 1 << 5,          ///< Skip all location attributes.
-  };
-
-  /// Mark the passed DIE as well as all the ones it depends on as kept.
-  void keepDIEAndDependencies(RelocationManager &RelocMgr, RangesTy &Ranges,
-                              UnitListTy &Units, const DWARFDie &DIE,
-                              CompileUnit::DIEInfo &MyInfo,
-                              const DebugMapObject &DMO, CompileUnit &CU,
-                              bool UseODR);
-
-  unsigned shouldKeepDIE(RelocationManager &RelocMgr, RangesTy &Ranges,
-                         const DWARFDie &DIE, const DebugMapObject &DMO,
-                         CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo,
-                         unsigned Flags);
-
-  unsigned shouldKeepVariableDIE(RelocationManager &RelocMgr,
-                                 const DWARFDie &DIE, CompileUnit &Unit,
-                                 CompileUnit::DIEInfo &MyInfo, unsigned Flags);
-
-  unsigned shouldKeepSubprogramDIE(RelocationManager &RelocMgr,
-                                   RangesTy &Ranges, const DWARFDie &DIE,
-                                   const DebugMapObject &DMO, CompileUnit &Unit,
-                                   CompileUnit::DIEInfo &MyInfo,
-                                   unsigned Flags);
-
-  bool hasValidRelocation(uint32_t StartOffset, uint32_t EndOffset,
-                          CompileUnit::DIEInfo &Info);
-  /// @}
-
-  /// \defgroup Linking Methods used to link the debug information
-  ///
-  /// @{
-
-  class DIECloner {
-    DwarfLinker &Linker;
-    RelocationManager &RelocMgr;
-
-    /// Allocator used for all the DIEValue objects.
-    BumpPtrAllocator &DIEAlloc;
-
-    std::vector<std::unique_ptr<CompileUnit>> &CompileUnits;
-    LinkOptions Options;
-
-  public:
-    DIECloner(DwarfLinker &Linker, RelocationManager &RelocMgr,
-              BumpPtrAllocator &DIEAlloc,
-              std::vector<std::unique_ptr<CompileUnit>> &CompileUnits,
-              LinkOptions &Options)
-        : Linker(Linker), RelocMgr(RelocMgr), DIEAlloc(DIEAlloc),
-          CompileUnits(CompileUnits), Options(Options) {}
-
-    /// Recursively clone \p InputDIE into an tree of DIE objects
-    /// where useless (as decided by lookForDIEsToKeep()) bits have been
-    /// stripped out and addresses have been rewritten according to the
-    /// debug map.
-    ///
-    /// \param OutOffset is the offset the cloned DIE in the output
-    /// compile unit.
-    /// \param PCOffset (while cloning a function scope) is the offset
-    /// applied to the entry point of the function to get the linked address.
-    /// \param Die the output DIE to use, pass NULL to create one.
-    /// \returns the root of the cloned tree or null if nothing was selected.
-    DIE *cloneDIE(const DWARFDie &InputDIE, const DebugMapObject &DMO,
-                  CompileUnit &U, OffsetsStringPool &StringPool,
-                  int64_t PCOffset, uint32_t OutOffset, unsigned Flags,
-                  DIE *Die = nullptr);
-
-    /// Construct the output DIE tree by cloning the DIEs we
-    /// chose to keep above. If there are no valid relocs, then there's
-    /// nothing to clone/emit.
-    void cloneAllCompileUnits(DWARFContext &DwarfContext,
-                              const DebugMapObject &DMO, RangesTy &Ranges,
-                              OffsetsStringPool &StringPool);
-
-  private:
-    using AttributeSpec = DWARFAbbreviationDeclaration::AttributeSpec;
-
-    /// Information gathered and exchanged between the various
-    /// clone*Attributes helpers about the attributes of a particular DIE.
-    struct AttributesInfo {
-      /// Names.
-      DwarfStringPoolEntryRef Name, MangledName, NameWithoutTemplate;
-
-      /// Offsets in the string pool.
-      uint32_t NameOffset = 0;
-      uint32_t MangledNameOffset = 0;
-
-      /// Value of AT_low_pc in the input DIE
-      uint64_t OrigLowPc = std::numeric_limits<uint64_t>::max();
-
-      /// Value of AT_high_pc in the input DIE
-      uint64_t OrigHighPc = 0;
-
-      /// Offset to apply to PC addresses inside a function.
-      int64_t PCOffset = 0;
-
-      /// Does the DIE have a low_pc attribute?
-      bool HasLowPc = false;
-
-      /// Does the DIE have a ranges attribute?
-      bool HasRanges = false;
-
-      /// Is this DIE only a declaration?
-      bool IsDeclaration = false;
-
-      AttributesInfo() = default;
-    };
-
-    /// Helper for cloneDIE.
-    unsigned cloneAttribute(DIE &Die, const DWARFDie &InputDIE,
-                            const DebugMapObject &DMO, CompileUnit &U,
-                            OffsetsStringPool &StringPool,
-                            const DWARFFormValue &Val,
-                            const AttributeSpec AttrSpec, unsigned AttrSize,
-                            AttributesInfo &AttrInfo);
-
-    /// Clone a string attribute described by \p AttrSpec and add
-    /// it to \p Die.
-    /// \returns the size of the new attribute.
-    unsigned cloneStringAttribute(DIE &Die, AttributeSpec AttrSpec,
-                                  const DWARFFormValue &Val, const DWARFUnit &U,
-                                  OffsetsStringPool &StringPool,
-                                  AttributesInfo &Info);
-
-    /// Clone an attribute referencing another DIE and add
-    /// it to \p Die.
-    /// \returns the size of the new attribute.
-    unsigned cloneDieReferenceAttribute(DIE &Die, const DWARFDie &InputDIE,
-                                        AttributeSpec AttrSpec,
-                                        unsigned AttrSize,
-                                        const DWARFFormValue &Val,
-                                        const DebugMapObject &DMO,
-                                        CompileUnit &Unit);
-
-    /// Clone an attribute referencing another DIE and add
-    /// it to \p Die.
-    /// \returns the size of the new attribute.
-    unsigned cloneBlockAttribute(DIE &Die, AttributeSpec AttrSpec,
-                                 const DWARFFormValue &Val, unsigned AttrSize);
-
-    /// Clone an attribute referencing another DIE and add
-    /// it to \p Die.
-    /// \returns the size of the new attribute.
-    unsigned cloneAddressAttribute(DIE &Die, AttributeSpec AttrSpec,
-                                   const DWARFFormValue &Val,
-                                   const CompileUnit &Unit,
-                                   AttributesInfo &Info);
-
-    /// Clone a scalar attribute  and add it to \p Die.
-    /// \returns the size of the new attribute.
-    unsigned cloneScalarAttribute(DIE &Die, const DWARFDie &InputDIE,
-                                  const DebugMapObject &DMO, CompileUnit &U,
-                                  AttributeSpec AttrSpec,
-                                  const DWARFFormValue &Val, unsigned AttrSize,
-                                  AttributesInfo &Info);
-
-    /// Get the potential name and mangled name for the entity
-    /// described by \p Die and store them in \Info if they are not
-    /// already there.
-    /// \returns is a name was found.
-    bool getDIENames(const DWARFDie &Die, AttributesInfo &Info,
-                     OffsetsStringPool &StringPool, bool StripTemplate = false);
-
-    /// Create a copy of abbreviation Abbrev.
-    void copyAbbrev(const DWARFAbbreviationDeclaration &Abbrev, bool hasODR);
-
-    uint32_t hashFullyQualifiedName(DWARFDie DIE, CompileUnit &U,
-                                    const DebugMapObject &DMO,
-                                    int RecurseDepth = 0);
-
-    /// Helper for cloneDIE.
-    void addObjCAccelerator(CompileUnit &Unit, const DIE *Die,
-                            DwarfStringPoolEntryRef Name,
-                            OffsetsStringPool &StringPool, bool SkipPubSection);
-  };
-
-  /// Assign an abbreviation number to \p Abbrev
-  void AssignAbbrev(DIEAbbrev &Abbrev);
-
-  /// Compute and emit debug_ranges section for \p Unit, and
-  /// patch the attributes referencing it.
-  void patchRangesForUnit(const CompileUnit &Unit, DWARFContext &Dwarf,
-                          const DebugMapObject &DMO) const;
-
-  /// Generate and emit the DW_AT_ranges attribute for a compile_unit if it had
-  /// one.
-  void generateUnitRanges(CompileUnit &Unit) const;
-
-  /// Extract the line tables from the original dwarf, extract the relevant
-  /// parts according to the linked function ranges and emit the result in the
-  /// debug_line section.
-  void patchLineTableForUnit(CompileUnit &Unit, DWARFContext &OrigDwarf,
-                             RangesTy &Ranges, const DebugMapObject &DMO);
-
-  /// Emit the accelerator entries for \p Unit.
-  void emitAcceleratorEntriesForUnit(CompileUnit &Unit);
-
-  /// Patch the frame info for an object file and emit it.
-  void patchFrameInfoForObject(const DebugMapObject &, RangesTy &Ranges,
-                               DWARFContext &, unsigned AddressSize);
-
-  /// FoldingSet that uniques the abbreviations.
-  FoldingSet<DIEAbbrev> AbbreviationsSet;
-
-  /// Storage for the unique Abbreviations.
-  /// This is passed to AsmPrinter::emitDwarfAbbrevs(), thus it cannot be
-  /// changed to a vector of unique_ptrs.
-  std::vector<std::unique_ptr<DIEAbbrev>> Abbreviations;
-
-  /// DIELoc objects that need to be destructed (but not freed!).
-  std::vector<DIELoc *> DIELocs;
-
-  /// DIEBlock objects that need to be destructed (but not freed!).
-  std::vector<DIEBlock *> DIEBlocks;
-
-  /// Allocator used for all the DIEValue objects.
-  BumpPtrAllocator DIEAlloc;
-  /// @}
-
-  /// \defgroup Helpers Various helper methods.
-  ///
-  /// @{
-  bool createStreamer(const Triple &TheTriple, raw_fd_ostream &OutFile);
-
-  /// Attempt to load a debug object from disk.
-  ErrorOr<const object::ObjectFile &> loadObject(BinaryHolder &BinaryHolder,
-                                                 const DebugMapObject &Obj,
-                                                 const DebugMap &Map);
-  /// @}
-
-  raw_fd_ostream &OutFile;
-  LinkOptions Options;
-  std::unique_ptr<DwarfStreamer> Streamer;
-  uint64_t OutputDebugInfoSize;
-  unsigned MaxDwarfVersion = 0;
-
-  /// The CIEs that have been emitted in the output section. The actual CIE
-  /// data serves a the key to this StringMap, this takes care of comparing the
-  /// semantics of CIEs defined in different object files.
-  StringMap<uint32_t> EmittedCIEs;
-
-  /// Offset of the last CIE that has been emitted in the output
-  /// debug_frame section.
-  uint32_t LastCIEOffset = 0;
-
-  /// Apple accelerator tables.
-  AccelTable<AppleAccelTableStaticOffsetData> AppleNames;
-  AccelTable<AppleAccelTableStaticOffsetData> AppleNamespaces;
-  AccelTable<AppleAccelTableStaticOffsetData> AppleObjc;
-  AccelTable<AppleAccelTableStaticTypeData> AppleTypes;
-
-  /// Mapping the PCM filename to the DwoId.
-  StringMap<uint64_t> ClangModules;
-
-  bool ModuleCacheHintDisplayed = false;
-  bool ArchiveHintDisplayed = false;
-};
-
-} // end anonymous namespace
-
 /// Similar to DWARFUnitSection::getUnitForOffset(), but returning our
 /// CompileUnit object instead.
 static CompileUnit *
@@ -1942,199 +156,6 @@ static bool isODRAttribute(uint16_t Attr
   llvm_unreachable("Improper attribute.");
 }
 
-/// Set the last DIE/CU a context was seen in and, possibly invalidate the
-/// context if it is ambiguous.
-///
-/// In the current implementation, we don't handle overloaded functions well,
-/// because the argument types are not taken into account when computing the
-/// DeclContext tree.
-///
-/// Some of this is mitigated byt using mangled names that do contain the
-/// arguments types, but sometimes (e.g. with function templates) we don't have
-/// that. In that case, just do not unique anything that refers to the contexts
-/// we are not able to distinguish.
-///
-/// If a context that is not a namespace appears twice in the same CU, we know
-/// it is ambiguous. Make it invalid.
-bool DeclContext::setLastSeenDIE(CompileUnit &U, const DWARFDie &Die) {
-  if (LastSeenCompileUnitID == U.getUniqueID()) {
-    DWARFUnit &OrigUnit = U.getOrigUnit();
-    uint32_t FirstIdx = OrigUnit.getDIEIndex(LastSeenDIE);
-    U.getInfo(FirstIdx).Ctxt = nullptr;
-    return false;
-  }
-
-  LastSeenCompileUnitID = U.getUniqueID();
-  LastSeenDIE = Die;
-  return true;
-}
-
-PointerIntPair<DeclContext *, 1> DeclContextTree::getChildDeclContext(
-    DeclContext &Context, const DWARFDie &DIE, CompileUnit &U,
-    UniquingStringPool &StringPool, bool InClangModule) {
-  unsigned Tag = DIE.getTag();
-
-  // FIXME: dsymutil-classic compat: We should bail out here if we
-  // have a specification or an abstract_origin. We will get the
-  // parent context wrong here.
-
-  switch (Tag) {
-  default:
-    // By default stop gathering child contexts.
-    return PointerIntPair<DeclContext *, 1>(nullptr);
-  case dwarf::DW_TAG_module:
-    break;
-  case dwarf::DW_TAG_compile_unit:
-    return PointerIntPair<DeclContext *, 1>(&Context);
-  case dwarf::DW_TAG_subprogram:
-    // Do not unique anything inside CU local functions.
-    if ((Context.getTag() == dwarf::DW_TAG_namespace ||
-         Context.getTag() == dwarf::DW_TAG_compile_unit) &&
-        !dwarf::toUnsigned(DIE.find(dwarf::DW_AT_external), 0))
-      return PointerIntPair<DeclContext *, 1>(nullptr);
-    LLVM_FALLTHROUGH;
-  case dwarf::DW_TAG_member:
-  case dwarf::DW_TAG_namespace:
-  case dwarf::DW_TAG_structure_type:
-  case dwarf::DW_TAG_class_type:
-  case dwarf::DW_TAG_union_type:
-  case dwarf::DW_TAG_enumeration_type:
-  case dwarf::DW_TAG_typedef:
-    // Artificial things might be ambiguous, because they might be created on
-    // demand. For example implicitly defined constructors are ambiguous
-    // because of the way we identify contexts, and they won't be generated
-    // every time everywhere.
-    if (dwarf::toUnsigned(DIE.find(dwarf::DW_AT_artificial), 0))
-      return PointerIntPair<DeclContext *, 1>(nullptr);
-    break;
-  }
-
-  const char *Name = DIE.getName(DINameKind::LinkageName);
-  const char *ShortName = DIE.getName(DINameKind::ShortName);
-  StringRef NameRef;
-  StringRef ShortNameRef;
-  StringRef FileRef;
-
-  if (Name)
-    NameRef = StringPool.internString(Name);
-  else if (Tag == dwarf::DW_TAG_namespace)
-    // FIXME: For dsymutil-classic compatibility. I think uniquing within
-    // anonymous namespaces is wrong. There is no ODR guarantee there.
-    NameRef = StringPool.internString("(anonymous namespace)");
-
-  if (ShortName && ShortName != Name)
-    ShortNameRef = StringPool.internString(ShortName);
-  else
-    ShortNameRef = NameRef;
-
-  if (Tag != dwarf::DW_TAG_class_type && Tag != dwarf::DW_TAG_structure_type &&
-      Tag != dwarf::DW_TAG_union_type &&
-      Tag != dwarf::DW_TAG_enumeration_type && NameRef.empty())
-    return PointerIntPair<DeclContext *, 1>(nullptr);
-
-  unsigned Line = 0;
-  unsigned ByteSize = std::numeric_limits<uint32_t>::max();
-
-  if (!InClangModule) {
-    // Gather some discriminating data about the DeclContext we will be
-    // creating: File, line number and byte size. This shouldn't be necessary,
-    // because the ODR is just about names, but given that we do some
-    // approximations with overloaded functions and anonymous namespaces, use
-    // these additional data points to make the process safer.
-    //
-    // This is disabled for clang modules, because forward declarations of
-    // module-defined types do not have a file and line.
-    ByteSize = dwarf::toUnsigned(DIE.find(dwarf::DW_AT_byte_size),
-                                 std::numeric_limits<uint64_t>::max());
-    if (Tag != dwarf::DW_TAG_namespace || !Name) {
-      if (unsigned FileNum =
-              dwarf::toUnsigned(DIE.find(dwarf::DW_AT_decl_file), 0)) {
-        if (const auto *LT = U.getOrigUnit().getContext().getLineTableForUnit(
-                &U.getOrigUnit())) {
-          // FIXME: dsymutil-classic compatibility. I'd rather not
-          // unique anything in anonymous namespaces, but if we do, then
-          // verify that the file and line correspond.
-          if (!Name && Tag == dwarf::DW_TAG_namespace)
-            FileNum = 1;
-
-          if (LT->hasFileAtIndex(FileNum)) {
-            Line = dwarf::toUnsigned(DIE.find(dwarf::DW_AT_decl_line), 0);
-            // Cache the resolved paths based on the index in the line table,
-            // because calling realpath is expansive.
-            StringRef ResolvedPath = U.getResolvedPath(FileNum);
-            if (!ResolvedPath.empty()) {
-              FileRef = ResolvedPath;
-            } else {
-              std::string File;
-              bool FoundFileName = LT->getFileNameByIndex(
-                  FileNum, U.getOrigUnit().getCompilationDir(),
-                  DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
-                  File);
-              (void)FoundFileName;
-              assert(FoundFileName && "Must get file name from line table");
-              // Second level of caching, this time based on the file's parent
-              // path.
-              FileRef = PathResolver.resolve(File, StringPool);
-              U.setResolvedPath(FileNum, FileRef);
-            }
-          }
-        }
-      }
-    }
-  }
-
-  if (!Line && NameRef.empty())
-    return PointerIntPair<DeclContext *, 1>(nullptr);
-
-  // We hash NameRef, which is the mangled name, in order to get most
-  // overloaded functions resolve correctly.
-  //
-  // Strictly speaking, hashing the Tag is only necessary for a
-  // DW_TAG_module, to prevent uniquing of a module and a namespace
-  // with the same name.
-  //
-  // FIXME: dsymutil-classic won't unique the same type presented
-  // once as a struct and once as a class. Using the Tag in the fully
-  // qualified name hash to get the same effect.
-  unsigned Hash = hash_combine(Context.getQualifiedNameHash(), Tag, NameRef);
-
-  // FIXME: dsymutil-classic compatibility: when we don't have a name,
-  // use the filename.
-  if (Tag == dwarf::DW_TAG_namespace && NameRef == "(anonymous namespace)")
-    Hash = hash_combine(Hash, FileRef);
-
-  // Now look if this context already exists.
-  DeclContext Key(Hash, Line, ByteSize, Tag, NameRef, FileRef, Context);
-  auto ContextIter = Contexts.find(&Key);
-
-  if (ContextIter == Contexts.end()) {
-    // The context wasn't found.
-    bool Inserted;
-    DeclContext *NewContext =
-        new (Allocator) DeclContext(Hash, Line, ByteSize, Tag, NameRef, FileRef,
-                                    Context, DIE, U.getUniqueID());
-    std::tie(ContextIter, Inserted) = Contexts.insert(NewContext);
-    assert(Inserted && "Failed to insert DeclContext");
-    (void)Inserted;
-  } else if (Tag != dwarf::DW_TAG_namespace &&
-             !(*ContextIter)->setLastSeenDIE(U, DIE)) {
-    // The context was found, but it is ambiguous with another context
-    // in the same file. Mark it invalid.
-    return PointerIntPair<DeclContext *, 1>(*ContextIter, /* Invalid= */ 1);
-  }
-
-  assert(ContextIter != Contexts.end());
-  // FIXME: dsymutil-classic compatibility. Union types aren't
-  // uniques, but their children might be.
-  if ((Tag == dwarf::DW_TAG_subprogram &&
-       Context.getTag() != dwarf::DW_TAG_structure_type &&
-       Context.getTag() != dwarf::DW_TAG_class_type) ||
-      (Tag == dwarf::DW_TAG_union_type))
-    return PointerIntPair<DeclContext *, 1>(*ContextIter, /* Invalid= */ 1);
-
-  return PointerIntPair<DeclContext *, 1>(*ContextIter);
-}
-
 bool DwarfLinker::DIECloner::getDIENames(const DWARFDie &Die,
                                          AttributesInfo &Info,
                                          OffsetsStringPool &StringPool,

Added: llvm/trunk/tools/dsymutil/DwarfLinker.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DwarfLinker.h?rev=335749&view=auto
==============================================================================
--- llvm/trunk/tools/dsymutil/DwarfLinker.h (added)
+++ llvm/trunk/tools/dsymutil/DwarfLinker.h Wed Jun 27 09:13:40 2018
@@ -0,0 +1,480 @@
+//===- tools/dsymutil/DwarfLinker.h - Dwarf debug info linker ---*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H
+#define LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H
+
+#include "BinaryHolder.h"
+#include "CompileUnit.h"
+#include "DebugMap.h"
+#include "DeclContext.h"
+#include "DwarfStreamer.h"
+#include "LinkUtils.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+
+namespace llvm {
+namespace dsymutil {
+
+/// Partial address range for debug map objects. Besides an offset, only the
+/// HighPC is stored. The structure is stored in a map where the LowPC is the
+/// key.
+struct DebugMapObjectRange {
+  /// Function HighPC.
+  uint64_t HighPC;
+  /// Offset to apply to the linked address.
+  int64_t Offset;
+
+  DebugMapObjectRange(uint64_t EndPC, int64_t Offset)
+      : HighPC(EndPC), Offset(Offset) {}
+
+  DebugMapObjectRange() : HighPC(0), Offset(0) {}
+};
+
+/// Map LowPC to DebugMapObjectRange.
+using RangesTy = std::map<uint64_t, DebugMapObjectRange>;
+using UnitListTy = std::vector<std::unique_ptr<CompileUnit>>;
+
+/// The core of the Dwarf linking logic.
+///
+/// The link 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 are present in the linked
+/// binary (and thus have entries in the debug map). All the debug
+/// information that will be linked (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
+/// correspond to a debug map entry at specific places (the low_pc for
+/// a function, the location for a variable). These relocations are
+/// called ValidRelocs in the DwarfLinker and are gathered as a very
+/// first step when we start processing a DebugMapObject.
+class DwarfLinker {
+public:
+  DwarfLinker(raw_fd_ostream &OutFile, const LinkOptions &Options)
+      : OutFile(OutFile), Options(Options) {}
+
+  /// Link the contents of the DebugMap.
+  bool link(const DebugMap &);
+
+  void reportWarning(const Twine &Warning, const DebugMapObject &DMO,
+                     const DWARFDie *DIE = nullptr) const;
+
+private:
+  /// Remembers the newest DWARF version we've seen in a unit.
+  void maybeUpdateMaxDwarfVersion(unsigned Version) {
+    if (MaxDwarfVersion < Version)
+      MaxDwarfVersion = Version;
+  }
+
+  /// Emit warnings as Dwarf compile units to leave a trail after linking.
+  bool emitPaperTrailWarnings(const DebugMapObject &DMO, const DebugMap &Map,
+                              OffsetsStringPool &StringPool);
+
+  /// Keeps track of relocations.
+  class RelocationManager {
+    struct ValidReloc {
+      uint32_t Offset;
+      uint32_t Size;
+      uint64_t Addend;
+      const DebugMapObject::DebugMapEntry *Mapping;
+
+      ValidReloc(uint32_t Offset, uint32_t Size, uint64_t Addend,
+                 const DebugMapObject::DebugMapEntry *Mapping)
+          : Offset(Offset), Size(Size), Addend(Addend), Mapping(Mapping) {}
+
+      bool operator<(const ValidReloc &RHS) const {
+        return Offset < RHS.Offset;
+      }
+    };
+
+    const DwarfLinker &Linker;
+
+    /// The valid relocations for the current DebugMapObject.
+    /// This vector is sorted by relocation offset.
+    std::vector<ValidReloc> ValidRelocs;
+
+    /// Index into ValidRelocs of the next relocation to consider. As we walk
+    /// the DIEs in acsending file offset and as ValidRelocs is sorted by file
+    /// offset, keeping this index up to date is all we have to do to have a
+    /// cheap lookup during the root DIE selection and during DIE cloning.
+    unsigned NextValidReloc = 0;
+
+  public:
+    RelocationManager(DwarfLinker &Linker) : Linker(Linker) {}
+
+    bool hasValidRelocs() const { return !ValidRelocs.empty(); }
+
+    /// Reset the NextValidReloc counter.
+    void resetValidRelocs() { NextValidReloc = 0; }
+
+    /// \defgroup FindValidRelocations Translate debug map into a list
+    /// of relevant relocations
+    ///
+    /// @{
+    bool findValidRelocsInDebugInfo(const object::ObjectFile &Obj,
+                                    const DebugMapObject &DMO);
+
+    bool findValidRelocs(const object::SectionRef &Section,
+                         const object::ObjectFile &Obj,
+                         const DebugMapObject &DMO);
+
+    void findValidRelocsMachO(const object::SectionRef &Section,
+                              const object::MachOObjectFile &Obj,
+                              const DebugMapObject &DMO);
+    /// @}
+
+    bool hasValidRelocation(uint32_t StartOffset, uint32_t EndOffset,
+                            CompileUnit::DIEInfo &Info);
+
+    bool applyValidRelocs(MutableArrayRef<char> Data, uint32_t BaseOffset,
+                          bool isLittleEndian);
+  };
+
+  /// Keeps track of data associated with one object during linking.
+  struct LinkContext {
+    DebugMapObject &DMO;
+    BinaryHolder BinHolder;
+    const object::ObjectFile *ObjectFile;
+    RelocationManager RelocMgr;
+    std::unique_ptr<DWARFContext> DwarfContext;
+    RangesTy Ranges;
+    UnitListTy CompileUnits;
+
+    LinkContext(const DebugMap &Map, DwarfLinker &Linker, DebugMapObject &DMO,
+                bool Verbose = false)
+        : DMO(DMO), BinHolder(Verbose), RelocMgr(Linker) {
+      // Swift ASTs are not object files.
+      if (DMO.getType() == MachO::N_AST) {
+        ObjectFile = nullptr;
+        return;
+      }
+      auto ErrOrObj = Linker.loadObject(BinHolder, DMO, Map);
+      ObjectFile = ErrOrObj ? &*ErrOrObj : nullptr;
+      DwarfContext = ObjectFile ? DWARFContext::create(*ObjectFile) : nullptr;
+    }
+
+    /// Clear compile units and ranges.
+    void Clear() {
+      CompileUnits.clear();
+      Ranges.clear();
+    }
+  };
+
+  /// Called at the start of a debug object link.
+  void startDebugObject(LinkContext &Context);
+
+  /// Called at the end of a debug object link.
+  void endDebugObject(LinkContext &Context);
+
+  /// \defgroup FindRootDIEs Find DIEs corresponding to debug map entries.
+  ///
+  /// @{
+  /// Recursively walk the \p DIE tree and look for DIEs to
+  /// keep. Store that information in \p CU's DIEInfo.
+  ///
+  /// The return value indicates whether the DIE is incomplete.
+  bool lookForDIEsToKeep(RelocationManager &RelocMgr, RangesTy &Ranges,
+                         UnitListTy &Units, const DWARFDie &DIE,
+                         const DebugMapObject &DMO, CompileUnit &CU,
+                         unsigned Flags);
+
+  /// If this compile unit is really a skeleton CU that points to a
+  /// clang module, register it in ClangModules and return true.
+  ///
+  /// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name
+  /// pointing to the module, and a DW_AT_gnu_dwo_id with the module
+  /// hash.
+  bool registerModuleReference(const DWARFDie &CUDie, const DWARFUnit &Unit,
+                               DebugMap &ModuleMap, const DebugMapObject &DMO,
+                               RangesTy &Ranges,
+                               OffsetsStringPool &OffsetsStringPool,
+                               UniquingStringPool &UniquingStringPoolStringPool,
+                               DeclContextTree &ODRContexts, unsigned &UnitID,
+                               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 Units.
+  Error loadClangModule(StringRef Filename, StringRef ModulePath,
+                        StringRef ModuleName, uint64_t DwoId,
+                        DebugMap &ModuleMap, const DebugMapObject &DMO,
+                        RangesTy &Ranges, OffsetsStringPool &OffsetsStringPool,
+                        UniquingStringPool &UniquingStringPool,
+                        DeclContextTree &ODRContexts, unsigned &UnitID,
+                        unsigned Indent = 0);
+
+  /// Flags passed to DwarfLinker::lookForDIEsToKeep
+  enum TraversalFlags {
+    TF_Keep = 1 << 0,            ///< Mark the traversed DIEs as kept.
+    TF_InFunctionScope = 1 << 1, ///< Current scope is a function scope.
+    TF_DependencyWalk = 1 << 2,  ///< Walking the dependencies of a kept DIE.
+    TF_ParentWalk = 1 << 3,      ///< Walking up the parents of a kept DIE.
+    TF_ODR = 1 << 4,             ///< Use the ODR while keeping dependents.
+    TF_SkipPC = 1 << 5,          ///< Skip all location attributes.
+  };
+
+  /// Mark the passed DIE as well as all the ones it depends on as kept.
+  void keepDIEAndDependencies(RelocationManager &RelocMgr, RangesTy &Ranges,
+                              UnitListTy &Units, const DWARFDie &DIE,
+                              CompileUnit::DIEInfo &MyInfo,
+                              const DebugMapObject &DMO, CompileUnit &CU,
+                              bool UseODR);
+
+  unsigned shouldKeepDIE(RelocationManager &RelocMgr, RangesTy &Ranges,
+                         const DWARFDie &DIE, const DebugMapObject &DMO,
+                         CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo,
+                         unsigned Flags);
+
+  unsigned shouldKeepVariableDIE(RelocationManager &RelocMgr,
+                                 const DWARFDie &DIE, CompileUnit &Unit,
+                                 CompileUnit::DIEInfo &MyInfo, unsigned Flags);
+
+  unsigned shouldKeepSubprogramDIE(RelocationManager &RelocMgr,
+                                   RangesTy &Ranges, const DWARFDie &DIE,
+                                   const DebugMapObject &DMO, CompileUnit &Unit,
+                                   CompileUnit::DIEInfo &MyInfo,
+                                   unsigned Flags);
+
+  bool hasValidRelocation(uint32_t StartOffset, uint32_t EndOffset,
+                          CompileUnit::DIEInfo &Info);
+  /// @}
+
+  /// \defgroup Linking Methods used to link the debug information
+  ///
+  /// @{
+
+  class DIECloner {
+    DwarfLinker &Linker;
+    RelocationManager &RelocMgr;
+
+    /// Allocator used for all the DIEValue objects.
+    BumpPtrAllocator &DIEAlloc;
+
+    std::vector<std::unique_ptr<CompileUnit>> &CompileUnits;
+    LinkOptions Options;
+
+  public:
+    DIECloner(DwarfLinker &Linker, RelocationManager &RelocMgr,
+              BumpPtrAllocator &DIEAlloc,
+              std::vector<std::unique_ptr<CompileUnit>> &CompileUnits,
+              LinkOptions &Options)
+        : Linker(Linker), RelocMgr(RelocMgr), DIEAlloc(DIEAlloc),
+          CompileUnits(CompileUnits), Options(Options) {}
+
+    /// Recursively clone \p InputDIE into an tree of DIE objects
+    /// where useless (as decided by lookForDIEsToKeep()) bits have been
+    /// stripped out and addresses have been rewritten according to the
+    /// debug map.
+    ///
+    /// \param OutOffset is the offset the cloned DIE in the output
+    /// compile unit.
+    /// \param PCOffset (while cloning a function scope) is the offset
+    /// applied to the entry point of the function to get the linked address.
+    /// \param Die the output DIE to use, pass NULL to create one.
+    /// \returns the root of the cloned tree or null if nothing was selected.
+    DIE *cloneDIE(const DWARFDie &InputDIE, const DebugMapObject &DMO,
+                  CompileUnit &U, OffsetsStringPool &StringPool,
+                  int64_t PCOffset, uint32_t OutOffset, unsigned Flags,
+                  DIE *Die = nullptr);
+
+    /// Construct the output DIE tree by cloning the DIEs we
+    /// chose to keep above. If there are no valid relocs, then there's
+    /// nothing to clone/emit.
+    void cloneAllCompileUnits(DWARFContext &DwarfContext,
+                              const DebugMapObject &DMO, RangesTy &Ranges,
+                              OffsetsStringPool &StringPool);
+
+  private:
+    using AttributeSpec = DWARFAbbreviationDeclaration::AttributeSpec;
+
+    /// Information gathered and exchanged between the various
+    /// clone*Attributes helpers about the attributes of a particular DIE.
+    struct AttributesInfo {
+      /// Names.
+      DwarfStringPoolEntryRef Name, MangledName, NameWithoutTemplate;
+
+      /// Offsets in the string pool.
+      uint32_t NameOffset = 0;
+      uint32_t MangledNameOffset = 0;
+
+      /// Value of AT_low_pc in the input DIE
+      uint64_t OrigLowPc = std::numeric_limits<uint64_t>::max();
+
+      /// Value of AT_high_pc in the input DIE
+      uint64_t OrigHighPc = 0;
+
+      /// Offset to apply to PC addresses inside a function.
+      int64_t PCOffset = 0;
+
+      /// Does the DIE have a low_pc attribute?
+      bool HasLowPc = false;
+
+      /// Does the DIE have a ranges attribute?
+      bool HasRanges = false;
+
+      /// Is this DIE only a declaration?
+      bool IsDeclaration = false;
+
+      AttributesInfo() = default;
+    };
+
+    /// Helper for cloneDIE.
+    unsigned cloneAttribute(DIE &Die, const DWARFDie &InputDIE,
+                            const DebugMapObject &DMO, CompileUnit &U,
+                            OffsetsStringPool &StringPool,
+                            const DWARFFormValue &Val,
+                            const AttributeSpec AttrSpec, unsigned AttrSize,
+                            AttributesInfo &AttrInfo);
+
+    /// Clone a string attribute described by \p AttrSpec and add
+    /// it to \p Die.
+    /// \returns the size of the new attribute.
+    unsigned cloneStringAttribute(DIE &Die, AttributeSpec AttrSpec,
+                                  const DWARFFormValue &Val, const DWARFUnit &U,
+                                  OffsetsStringPool &StringPool,
+                                  AttributesInfo &Info);
+
+    /// Clone an attribute referencing another DIE and add
+    /// it to \p Die.
+    /// \returns the size of the new attribute.
+    unsigned cloneDieReferenceAttribute(DIE &Die, const DWARFDie &InputDIE,
+                                        AttributeSpec AttrSpec,
+                                        unsigned AttrSize,
+                                        const DWARFFormValue &Val,
+                                        const DebugMapObject &DMO,
+                                        CompileUnit &Unit);
+
+    /// Clone an attribute referencing another DIE and add
+    /// it to \p Die.
+    /// \returns the size of the new attribute.
+    unsigned cloneBlockAttribute(DIE &Die, AttributeSpec AttrSpec,
+                                 const DWARFFormValue &Val, unsigned AttrSize);
+
+    /// Clone an attribute referencing another DIE and add
+    /// it to \p Die.
+    /// \returns the size of the new attribute.
+    unsigned cloneAddressAttribute(DIE &Die, AttributeSpec AttrSpec,
+                                   const DWARFFormValue &Val,
+                                   const CompileUnit &Unit,
+                                   AttributesInfo &Info);
+
+    /// Clone a scalar attribute  and add it to \p Die.
+    /// \returns the size of the new attribute.
+    unsigned cloneScalarAttribute(DIE &Die, const DWARFDie &InputDIE,
+                                  const DebugMapObject &DMO, CompileUnit &U,
+                                  AttributeSpec AttrSpec,
+                                  const DWARFFormValue &Val, unsigned AttrSize,
+                                  AttributesInfo &Info);
+
+    /// Get the potential name and mangled name for the entity
+    /// described by \p Die and store them in \Info if they are not
+    /// already there.
+    /// \returns is a name was found.
+    bool getDIENames(const DWARFDie &Die, AttributesInfo &Info,
+                     OffsetsStringPool &StringPool, bool StripTemplate = false);
+
+    /// Create a copy of abbreviation Abbrev.
+    void copyAbbrev(const DWARFAbbreviationDeclaration &Abbrev, bool hasODR);
+
+    uint32_t hashFullyQualifiedName(DWARFDie DIE, CompileUnit &U,
+                                    const DebugMapObject &DMO,
+                                    int RecurseDepth = 0);
+
+    /// Helper for cloneDIE.
+    void addObjCAccelerator(CompileUnit &Unit, const DIE *Die,
+                            DwarfStringPoolEntryRef Name,
+                            OffsetsStringPool &StringPool, bool SkipPubSection);
+  };
+
+  /// Assign an abbreviation number to \p Abbrev
+  void AssignAbbrev(DIEAbbrev &Abbrev);
+
+  /// Compute and emit debug_ranges section for \p Unit, and
+  /// patch the attributes referencing it.
+  void patchRangesForUnit(const CompileUnit &Unit, DWARFContext &Dwarf,
+                          const DebugMapObject &DMO) const;
+
+  /// Generate and emit the DW_AT_ranges attribute for a compile_unit if it had
+  /// one.
+  void generateUnitRanges(CompileUnit &Unit) const;
+
+  /// Extract the line tables from the original dwarf, extract the relevant
+  /// parts according to the linked function ranges and emit the result in the
+  /// debug_line section.
+  void patchLineTableForUnit(CompileUnit &Unit, DWARFContext &OrigDwarf,
+                             RangesTy &Ranges, const DebugMapObject &DMO);
+
+  /// Emit the accelerator entries for \p Unit.
+  void emitAcceleratorEntriesForUnit(CompileUnit &Unit);
+
+  /// Patch the frame info for an object file and emit it.
+  void patchFrameInfoForObject(const DebugMapObject &, RangesTy &Ranges,
+                               DWARFContext &, unsigned AddressSize);
+
+  /// FoldingSet that uniques the abbreviations.
+  FoldingSet<DIEAbbrev> AbbreviationsSet;
+
+  /// Storage for the unique Abbreviations.
+  /// This is passed to AsmPrinter::emitDwarfAbbrevs(), thus it cannot be
+  /// changed to a vector of unique_ptrs.
+  std::vector<std::unique_ptr<DIEAbbrev>> Abbreviations;
+
+  /// DIELoc objects that need to be destructed (but not freed!).
+  std::vector<DIELoc *> DIELocs;
+
+  /// DIEBlock objects that need to be destructed (but not freed!).
+  std::vector<DIEBlock *> DIEBlocks;
+
+  /// Allocator used for all the DIEValue objects.
+  BumpPtrAllocator DIEAlloc;
+  /// @}
+
+  /// \defgroup Helpers Various helper methods.
+  ///
+  /// @{
+  bool createStreamer(const Triple &TheTriple, raw_fd_ostream &OutFile);
+
+  /// Attempt to load a debug object from disk.
+  ErrorOr<const object::ObjectFile &> loadObject(BinaryHolder &BinaryHolder,
+                                                 const DebugMapObject &Obj,
+                                                 const DebugMap &Map);
+  /// @}
+
+  raw_fd_ostream &OutFile;
+  LinkOptions Options;
+  std::unique_ptr<DwarfStreamer> Streamer;
+  uint64_t OutputDebugInfoSize;
+  unsigned MaxDwarfVersion = 0;
+
+  /// The CIEs that have been emitted in the output section. The actual CIE
+  /// data serves a the key to this StringMap, this takes care of comparing the
+  /// semantics of CIEs defined in different object files.
+  StringMap<uint32_t> EmittedCIEs;
+
+  /// Offset of the last CIE that has been emitted in the output
+  /// debug_frame section.
+  uint32_t LastCIEOffset = 0;
+
+  /// Apple accelerator tables.
+  AccelTable<AppleAccelTableStaticOffsetData> AppleNames;
+  AccelTable<AppleAccelTableStaticOffsetData> AppleNamespaces;
+  AccelTable<AppleAccelTableStaticOffsetData> AppleObjc;
+  AccelTable<AppleAccelTableStaticTypeData> AppleTypes;
+
+  /// Mapping the PCM filename to the DwoId.
+  StringMap<uint64_t> ClangModules;
+
+  bool ModuleCacheHintDisplayed = false;
+  bool ArchiveHintDisplayed = false;
+};
+
+} // end namespace dsymutil
+} // end namespace llvm
+
+#endif // LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H

Added: llvm/trunk/tools/dsymutil/DwarfStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DwarfStreamer.cpp?rev=335749&view=auto
==============================================================================
--- llvm/trunk/tools/dsymutil/DwarfStreamer.cpp (added)
+++ llvm/trunk/tools/dsymutil/DwarfStreamer.cpp Wed Jun 27 09:13:40 2018
@@ -0,0 +1,638 @@
+//===- tools/dsymutil/DwarfStreamer.cpp - Dwarf Streamer ------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DwarfStreamer.h"
+#include "LinkUtils.h"
+#include "MachOUtils.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/MC/MCTargetOptions.h"
+#include "llvm/MC/MCTargetOptionsCommandFlags.inc"
+#include "llvm/Support/LEB128.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
+
+namespace llvm {
+namespace dsymutil {
+
+/// Retrieve the section named \a SecName in \a Obj.
+///
+/// To accommodate for platform discrepancies, the name passed should be
+/// (for example) 'debug_info' to match either '__debug_info' or '.debug_info'.
+/// This function will strip the initial platform-specific characters.
+static Optional<object::SectionRef>
+getSectionByName(const object::ObjectFile &Obj, StringRef SecName) {
+  for (const object::SectionRef &Section : Obj.sections()) {
+    StringRef SectionName;
+    Section.getName(SectionName);
+    SectionName = SectionName.substr(SectionName.find_first_not_of("._"));
+    if (SectionName != SecName)
+      continue;
+    return Section;
+  }
+  return None;
+}
+
+bool DwarfStreamer::init(Triple TheTriple) {
+  std::string ErrorStr;
+  std::string TripleName;
+  StringRef Context = "dwarf streamer init";
+
+  // Get the target.
+  const Target *TheTarget =
+      TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr);
+  if (!TheTarget)
+    return error(ErrorStr, Context);
+  TripleName = TheTriple.getTriple();
+
+  // Create all the MC Objects.
+  MRI.reset(TheTarget->createMCRegInfo(TripleName));
+  if (!MRI)
+    return error(Twine("no register info for target ") + TripleName, Context);
+
+  MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName));
+  if (!MAI)
+    return error("no asm info for target " + TripleName, Context);
+
+  MOFI.reset(new MCObjectFileInfo);
+  MC.reset(new MCContext(MAI.get(), MRI.get(), MOFI.get()));
+  MOFI->InitMCObjectFileInfo(TheTriple, /*PIC*/ false, *MC);
+
+  MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
+  if (!MSTI)
+    return error("no subtarget info for target " + TripleName, Context);
+
+  MCTargetOptions Options;
+  MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, Options);
+  if (!MAB)
+    return error("no asm backend for target " + TripleName, Context);
+
+  MII.reset(TheTarget->createMCInstrInfo());
+  if (!MII)
+    return error("no instr info info for target " + TripleName, Context);
+
+  MCE = TheTarget->createMCCodeEmitter(*MII, *MRI, *MC);
+  if (!MCE)
+    return error("no code emitter for target " + TripleName, Context);
+
+  MCTargetOptions MCOptions = InitMCTargetOptionsFromFlags();
+  MS = TheTarget->createMCObjectStreamer(
+      TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB),
+      MAB->createObjectWriter(OutFile), std::unique_ptr<MCCodeEmitter>(MCE),
+      *MSTI, MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible,
+      /*DWARFMustBeAtTheEnd*/ false);
+  if (!MS)
+    return error("no object streamer for target " + TripleName, Context);
+
+  // Finally create the AsmPrinter we'll use to emit the DIEs.
+  TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions(),
+                                          None));
+  if (!TM)
+    return error("no target machine for target " + TripleName, Context);
+
+  Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS)));
+  if (!Asm)
+    return error("no asm printer for target " + TripleName, Context);
+
+  RangesSectionSize = 0;
+  LocSectionSize = 0;
+  LineSectionSize = 0;
+  FrameSectionSize = 0;
+
+  return true;
+}
+
+bool DwarfStreamer::finish(const DebugMap &DM) {
+  bool Result = true;
+  if (DM.getTriple().isOSDarwin() && !DM.getBinaryPath().empty())
+    Result = MachOUtils::generateDsymCompanion(DM, *MS, OutFile);
+  else
+    MS->Finish();
+  return Result;
+}
+
+void DwarfStreamer::switchToDebugInfoSection(unsigned DwarfVersion) {
+  MS->SwitchSection(MOFI->getDwarfInfoSection());
+  MC->setDwarfVersion(DwarfVersion);
+}
+
+/// Emit the compilation unit header for \p Unit in the debug_info section.
+///
+/// A Dwarf section header is encoded as:
+///  uint32_t   Unit length (omitting this field)
+///  uint16_t   Version
+///  uint32_t   Abbreviation table offset
+///  uint8_t    Address size
+///
+/// Leading to a total of 11 bytes.
+void DwarfStreamer::emitCompileUnitHeader(CompileUnit &Unit) {
+  unsigned Version = Unit.getOrigUnit().getVersion();
+  switchToDebugInfoSection(Version);
+
+  // Emit size of content not including length itself. The size has already
+  // been computed in CompileUnit::computeOffsets(). Subtract 4 to that size to
+  // account for the length field.
+  Asm->emitInt32(Unit.getNextUnitOffset() - Unit.getStartOffset() - 4);
+  Asm->emitInt16(Version);
+  // We share one abbreviations table across all units so it's always at the
+  // start of the section.
+  Asm->emitInt32(0);
+  Asm->emitInt8(Unit.getOrigUnit().getAddressByteSize());
+}
+
+/// Emit the \p Abbrevs array as the shared abbreviation table
+/// for the linked Dwarf file.
+void DwarfStreamer::emitAbbrevs(
+    const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs,
+    unsigned DwarfVersion) {
+  MS->SwitchSection(MOFI->getDwarfAbbrevSection());
+  MC->setDwarfVersion(DwarfVersion);
+  Asm->emitDwarfAbbrevs(Abbrevs);
+}
+
+/// Recursively emit the DIE tree rooted at \p Die.
+void DwarfStreamer::emitDIE(DIE &Die) {
+  MS->SwitchSection(MOFI->getDwarfInfoSection());
+  Asm->emitDwarfDIE(Die);
+}
+
+/// Emit the debug_str section stored in \p Pool.
+void DwarfStreamer::emitStrings(const NonRelocatableStringpool &Pool) {
+  Asm->OutStreamer->SwitchSection(MOFI->getDwarfStrSection());
+  std::vector<DwarfStringPoolEntryRef> Entries = Pool.getEntries();
+  for (auto Entry : Entries) {
+    if (Entry.getIndex() == -1U)
+      break;
+    // Emit the string itself.
+    Asm->OutStreamer->EmitBytes(Entry.getString());
+    // Emit a null terminator.
+    Asm->emitInt8(0);
+  }
+}
+
+void DwarfStreamer::emitAppleNamespaces(
+    AccelTable<AppleAccelTableStaticOffsetData> &Table) {
+  Asm->OutStreamer->SwitchSection(MOFI->getDwarfAccelNamespaceSection());
+  auto *SectionBegin = Asm->createTempSymbol("namespac_begin");
+  Asm->OutStreamer->EmitLabel(SectionBegin);
+  emitAppleAccelTable(Asm.get(), Table, "namespac", SectionBegin);
+}
+
+void DwarfStreamer::emitAppleNames(
+    AccelTable<AppleAccelTableStaticOffsetData> &Table) {
+  Asm->OutStreamer->SwitchSection(MOFI->getDwarfAccelNamesSection());
+  auto *SectionBegin = Asm->createTempSymbol("names_begin");
+  Asm->OutStreamer->EmitLabel(SectionBegin);
+  emitAppleAccelTable(Asm.get(), Table, "names", SectionBegin);
+}
+
+void DwarfStreamer::emitAppleObjc(
+    AccelTable<AppleAccelTableStaticOffsetData> &Table) {
+  Asm->OutStreamer->SwitchSection(MOFI->getDwarfAccelObjCSection());
+  auto *SectionBegin = Asm->createTempSymbol("objc_begin");
+  Asm->OutStreamer->EmitLabel(SectionBegin);
+  emitAppleAccelTable(Asm.get(), Table, "objc", SectionBegin);
+}
+
+void DwarfStreamer::emitAppleTypes(
+    AccelTable<AppleAccelTableStaticTypeData> &Table) {
+  Asm->OutStreamer->SwitchSection(MOFI->getDwarfAccelTypesSection());
+  auto *SectionBegin = Asm->createTempSymbol("types_begin");
+  Asm->OutStreamer->EmitLabel(SectionBegin);
+  emitAppleAccelTable(Asm.get(), Table, "types", SectionBegin);
+}
+
+/// Emit the swift_ast section stored in \p Buffers.
+void DwarfStreamer::emitSwiftAST(StringRef Buffer) {
+  MCSection *SwiftASTSection = MOFI->getDwarfSwiftASTSection();
+  SwiftASTSection->setAlignment(1 << 5);
+  MS->SwitchSection(SwiftASTSection);
+  MS->EmitBytes(Buffer);
+}
+
+/// Emit the debug_range section contents for \p FuncRange by
+/// translating the original \p Entries. The debug_range section
+/// format is totally trivial, consisting just of pairs of address
+/// sized addresses describing the ranges.
+void DwarfStreamer::emitRangesEntries(
+    int64_t UnitPcOffset, uint64_t OrigLowPc,
+    const FunctionIntervals::const_iterator &FuncRange,
+    const std::vector<DWARFDebugRangeList::RangeListEntry> &Entries,
+    unsigned AddressSize) {
+  MS->SwitchSection(MC->getObjectFileInfo()->getDwarfRangesSection());
+
+  // Offset each range by the right amount.
+  int64_t PcOffset = Entries.empty() ? 0 : FuncRange.value() + UnitPcOffset;
+  for (const auto &Range : Entries) {
+    if (Range.isBaseAddressSelectionEntry(AddressSize)) {
+      warn("unsupported base address selection operation",
+           "emitting debug_ranges");
+      break;
+    }
+    // Do not emit empty ranges.
+    if (Range.StartAddress == Range.EndAddress)
+      continue;
+
+    // All range entries should lie in the function range.
+    if (!(Range.StartAddress + OrigLowPc >= FuncRange.start() &&
+          Range.EndAddress + OrigLowPc <= FuncRange.stop()))
+      warn("inconsistent range data.", "emitting debug_ranges");
+    MS->EmitIntValue(Range.StartAddress + PcOffset, AddressSize);
+    MS->EmitIntValue(Range.EndAddress + PcOffset, AddressSize);
+    RangesSectionSize += 2 * AddressSize;
+  }
+
+  // Add the terminator entry.
+  MS->EmitIntValue(0, AddressSize);
+  MS->EmitIntValue(0, AddressSize);
+  RangesSectionSize += 2 * AddressSize;
+}
+
+/// Emit the debug_aranges contribution of a unit and
+/// if \p DoDebugRanges is true the debug_range contents for a
+/// compile_unit level DW_AT_ranges attribute (Which are basically the
+/// same thing with a different base address).
+/// Just aggregate all the ranges gathered inside that unit.
+void DwarfStreamer::emitUnitRangesEntries(CompileUnit &Unit,
+                                          bool DoDebugRanges) {
+  unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
+  // Gather the ranges in a vector, so that we can simplify them. The
+  // IntervalMap will have coalesced the non-linked ranges, but here
+  // we want to coalesce the linked addresses.
+  std::vector<std::pair<uint64_t, uint64_t>> Ranges;
+  const auto &FunctionRanges = Unit.getFunctionRanges();
+  for (auto Range = FunctionRanges.begin(), End = FunctionRanges.end();
+       Range != End; ++Range)
+    Ranges.push_back(std::make_pair(Range.start() + Range.value(),
+                                    Range.stop() + Range.value()));
+
+  // The object addresses where sorted, but again, the linked
+  // addresses might end up in a different order.
+  llvm::sort(Ranges.begin(), Ranges.end());
+
+  if (!Ranges.empty()) {
+    MS->SwitchSection(MC->getObjectFileInfo()->getDwarfARangesSection());
+
+    MCSymbol *BeginLabel = Asm->createTempSymbol("Barange");
+    MCSymbol *EndLabel = Asm->createTempSymbol("Earange");
+
+    unsigned HeaderSize =
+        sizeof(int32_t) + // Size of contents (w/o this field
+        sizeof(int16_t) + // DWARF ARange version number
+        sizeof(int32_t) + // Offset of CU in the .debug_info section
+        sizeof(int8_t) +  // Pointer Size (in bytes)
+        sizeof(int8_t);   // Segment Size (in bytes)
+
+    unsigned TupleSize = AddressSize * 2;
+    unsigned Padding = OffsetToAlignment(HeaderSize, TupleSize);
+
+    Asm->EmitLabelDifference(EndLabel, BeginLabel, 4); // Arange length
+    Asm->OutStreamer->EmitLabel(BeginLabel);
+    Asm->emitInt16(dwarf::DW_ARANGES_VERSION); // Version number
+    Asm->emitInt32(Unit.getStartOffset());     // Corresponding unit's offset
+    Asm->emitInt8(AddressSize);                // Address size
+    Asm->emitInt8(0);                          // Segment size
+
+    Asm->OutStreamer->emitFill(Padding, 0x0);
+
+    for (auto Range = Ranges.begin(), End = Ranges.end(); Range != End;
+         ++Range) {
+      uint64_t RangeStart = Range->first;
+      MS->EmitIntValue(RangeStart, AddressSize);
+      while ((Range + 1) != End && Range->second == (Range + 1)->first)
+        ++Range;
+      MS->EmitIntValue(Range->second - RangeStart, AddressSize);
+    }
+
+    // Emit terminator
+    Asm->OutStreamer->EmitIntValue(0, AddressSize);
+    Asm->OutStreamer->EmitIntValue(0, AddressSize);
+    Asm->OutStreamer->EmitLabel(EndLabel);
+  }
+
+  if (!DoDebugRanges)
+    return;
+
+  MS->SwitchSection(MC->getObjectFileInfo()->getDwarfRangesSection());
+  // Offset each range by the right amount.
+  int64_t PcOffset = -Unit.getLowPc();
+  // Emit coalesced ranges.
+  for (auto Range = Ranges.begin(), End = Ranges.end(); Range != End; ++Range) {
+    MS->EmitIntValue(Range->first + PcOffset, AddressSize);
+    while (Range + 1 != End && Range->second == (Range + 1)->first)
+      ++Range;
+    MS->EmitIntValue(Range->second + PcOffset, AddressSize);
+    RangesSectionSize += 2 * AddressSize;
+  }
+
+  // Add the terminator entry.
+  MS->EmitIntValue(0, AddressSize);
+  MS->EmitIntValue(0, AddressSize);
+  RangesSectionSize += 2 * AddressSize;
+}
+
+/// Emit location lists for \p Unit and update attributes to point to the new
+/// entries.
+void DwarfStreamer::emitLocationsForUnit(const CompileUnit &Unit,
+                                         DWARFContext &Dwarf) {
+  const auto &Attributes = Unit.getLocationAttributes();
+
+  if (Attributes.empty())
+    return;
+
+  MS->SwitchSection(MC->getObjectFileInfo()->getDwarfLocSection());
+
+  unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
+  const DWARFSection &InputSec = Dwarf.getDWARFObj().getLocSection();
+  DataExtractor Data(InputSec.Data, Dwarf.isLittleEndian(), AddressSize);
+  DWARFUnit &OrigUnit = Unit.getOrigUnit();
+  auto OrigUnitDie = OrigUnit.getUnitDIE(false);
+  int64_t UnitPcOffset = 0;
+  if (auto OrigLowPc = dwarf::toAddress(OrigUnitDie.find(dwarf::DW_AT_low_pc)))
+    UnitPcOffset = int64_t(*OrigLowPc) - Unit.getLowPc();
+
+  for (const auto &Attr : Attributes) {
+    uint32_t Offset = Attr.first.get();
+    Attr.first.set(LocSectionSize);
+    // This is the quantity to add to the old location address to get
+    // the correct address for the new one.
+    int64_t LocPcOffset = Attr.second + UnitPcOffset;
+    while (Data.isValidOffset(Offset)) {
+      uint64_t Low = Data.getUnsigned(&Offset, AddressSize);
+      uint64_t High = Data.getUnsigned(&Offset, AddressSize);
+      LocSectionSize += 2 * AddressSize;
+      if (Low == 0 && High == 0) {
+        Asm->OutStreamer->EmitIntValue(0, AddressSize);
+        Asm->OutStreamer->EmitIntValue(0, AddressSize);
+        break;
+      }
+      Asm->OutStreamer->EmitIntValue(Low + LocPcOffset, AddressSize);
+      Asm->OutStreamer->EmitIntValue(High + LocPcOffset, AddressSize);
+      uint64_t Length = Data.getU16(&Offset);
+      Asm->OutStreamer->EmitIntValue(Length, 2);
+      // Just copy the bytes over.
+      Asm->OutStreamer->EmitBytes(
+          StringRef(InputSec.Data.substr(Offset, Length)));
+      Offset += Length;
+      LocSectionSize += Length + 2;
+    }
+  }
+}
+
+void DwarfStreamer::emitLineTableForUnit(MCDwarfLineTableParams Params,
+                                         StringRef PrologueBytes,
+                                         unsigned MinInstLength,
+                                         std::vector<DWARFDebugLine::Row> &Rows,
+                                         unsigned PointerSize) {
+  // Switch to the section where the table will be emitted into.
+  MS->SwitchSection(MC->getObjectFileInfo()->getDwarfLineSection());
+  MCSymbol *LineStartSym = MC->createTempSymbol();
+  MCSymbol *LineEndSym = MC->createTempSymbol();
+
+  // The first 4 bytes is the total length of the information for this
+  // compilation unit (not including these 4 bytes for the length).
+  Asm->EmitLabelDifference(LineEndSym, LineStartSym, 4);
+  Asm->OutStreamer->EmitLabel(LineStartSym);
+  // Copy Prologue.
+  MS->EmitBytes(PrologueBytes);
+  LineSectionSize += PrologueBytes.size() + 4;
+
+  SmallString<128> EncodingBuffer;
+  raw_svector_ostream EncodingOS(EncodingBuffer);
+
+  if (Rows.empty()) {
+    // We only have the dummy entry, dsymutil emits an entry with a 0
+    // address in that case.
+    MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0,
+                            EncodingOS);
+    MS->EmitBytes(EncodingOS.str());
+    LineSectionSize += EncodingBuffer.size();
+    MS->EmitLabel(LineEndSym);
+    return;
+  }
+
+  // Line table state machine fields
+  unsigned FileNum = 1;
+  unsigned LastLine = 1;
+  unsigned Column = 0;
+  unsigned IsStatement = 1;
+  unsigned Isa = 0;
+  uint64_t Address = -1ULL;
+
+  unsigned RowsSinceLastSequence = 0;
+
+  for (unsigned Idx = 0; Idx < Rows.size(); ++Idx) {
+    auto &Row = Rows[Idx];
+
+    int64_t AddressDelta;
+    if (Address == -1ULL) {
+      MS->EmitIntValue(dwarf::DW_LNS_extended_op, 1);
+      MS->EmitULEB128IntValue(PointerSize + 1);
+      MS->EmitIntValue(dwarf::DW_LNE_set_address, 1);
+      MS->EmitIntValue(Row.Address, PointerSize);
+      LineSectionSize += 2 + PointerSize + getULEB128Size(PointerSize + 1);
+      AddressDelta = 0;
+    } else {
+      AddressDelta = (Row.Address - Address) / MinInstLength;
+    }
+
+    // FIXME: code copied and transformed from MCDwarf.cpp::EmitDwarfLineTable.
+    // We should find a way to share this code, but the current compatibility
+    // requirement with classic dsymutil makes it hard. Revisit that once this
+    // requirement is dropped.
+
+    if (FileNum != Row.File) {
+      FileNum = Row.File;
+      MS->EmitIntValue(dwarf::DW_LNS_set_file, 1);
+      MS->EmitULEB128IntValue(FileNum);
+      LineSectionSize += 1 + getULEB128Size(FileNum);
+    }
+    if (Column != Row.Column) {
+      Column = Row.Column;
+      MS->EmitIntValue(dwarf::DW_LNS_set_column, 1);
+      MS->EmitULEB128IntValue(Column);
+      LineSectionSize += 1 + getULEB128Size(Column);
+    }
+
+    // FIXME: We should handle the discriminator here, but dsymutil doesn't
+    // consider it, thus ignore it for now.
+
+    if (Isa != Row.Isa) {
+      Isa = Row.Isa;
+      MS->EmitIntValue(dwarf::DW_LNS_set_isa, 1);
+      MS->EmitULEB128IntValue(Isa);
+      LineSectionSize += 1 + getULEB128Size(Isa);
+    }
+    if (IsStatement != Row.IsStmt) {
+      IsStatement = Row.IsStmt;
+      MS->EmitIntValue(dwarf::DW_LNS_negate_stmt, 1);
+      LineSectionSize += 1;
+    }
+    if (Row.BasicBlock) {
+      MS->EmitIntValue(dwarf::DW_LNS_set_basic_block, 1);
+      LineSectionSize += 1;
+    }
+
+    if (Row.PrologueEnd) {
+      MS->EmitIntValue(dwarf::DW_LNS_set_prologue_end, 1);
+      LineSectionSize += 1;
+    }
+
+    if (Row.EpilogueBegin) {
+      MS->EmitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1);
+      LineSectionSize += 1;
+    }
+
+    int64_t LineDelta = int64_t(Row.Line) - LastLine;
+    if (!Row.EndSequence) {
+      MCDwarfLineAddr::Encode(*MC, Params, LineDelta, AddressDelta, EncodingOS);
+      MS->EmitBytes(EncodingOS.str());
+      LineSectionSize += EncodingBuffer.size();
+      EncodingBuffer.resize(0);
+      Address = Row.Address;
+      LastLine = Row.Line;
+      RowsSinceLastSequence++;
+    } else {
+      if (LineDelta) {
+        MS->EmitIntValue(dwarf::DW_LNS_advance_line, 1);
+        MS->EmitSLEB128IntValue(LineDelta);
+        LineSectionSize += 1 + getSLEB128Size(LineDelta);
+      }
+      if (AddressDelta) {
+        MS->EmitIntValue(dwarf::DW_LNS_advance_pc, 1);
+        MS->EmitULEB128IntValue(AddressDelta);
+        LineSectionSize += 1 + getULEB128Size(AddressDelta);
+      }
+      MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(),
+                              0, EncodingOS);
+      MS->EmitBytes(EncodingOS.str());
+      LineSectionSize += EncodingBuffer.size();
+      EncodingBuffer.resize(0);
+      Address = -1ULL;
+      LastLine = FileNum = IsStatement = 1;
+      RowsSinceLastSequence = Column = Isa = 0;
+    }
+  }
+
+  if (RowsSinceLastSequence) {
+    MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0,
+                            EncodingOS);
+    MS->EmitBytes(EncodingOS.str());
+    LineSectionSize += EncodingBuffer.size();
+    EncodingBuffer.resize(0);
+  }
+
+  MS->EmitLabel(LineEndSym);
+}
+
+static void emitSectionContents(const object::ObjectFile &Obj,
+                                StringRef SecName, MCStreamer *MS) {
+  StringRef Contents;
+  if (auto Sec = getSectionByName(Obj, SecName))
+    if (!Sec->getContents(Contents))
+      MS->EmitBytes(Contents);
+}
+
+void DwarfStreamer::copyInvariantDebugSection(const object::ObjectFile &Obj,
+                                              LinkOptions &Options) {
+  MS->SwitchSection(MC->getObjectFileInfo()->getDwarfLineSection());
+  emitSectionContents(Obj, "debug_line", MS);
+
+  MS->SwitchSection(MC->getObjectFileInfo()->getDwarfLocSection());
+  emitSectionContents(Obj, "debug_loc", MS);
+
+  MS->SwitchSection(MC->getObjectFileInfo()->getDwarfRangesSection());
+  emitSectionContents(Obj, "debug_ranges", MS);
+
+  MS->SwitchSection(MC->getObjectFileInfo()->getDwarfFrameSection());
+  emitSectionContents(Obj, "debug_frame", MS);
+
+  MS->SwitchSection(MC->getObjectFileInfo()->getDwarfARangesSection());
+  emitSectionContents(Obj, "debug_aranges", MS);
+}
+
+/// Emit the pubnames or pubtypes section contribution for \p
+/// Unit into \p Sec. The data is provided in \p Names.
+void DwarfStreamer::emitPubSectionForUnit(
+    MCSection *Sec, StringRef SecName, const CompileUnit &Unit,
+    const std::vector<CompileUnit::AccelInfo> &Names) {
+  if (Names.empty())
+    return;
+
+  // Start the dwarf pubnames section.
+  Asm->OutStreamer->SwitchSection(Sec);
+  MCSymbol *BeginLabel = Asm->createTempSymbol("pub" + SecName + "_begin");
+  MCSymbol *EndLabel = Asm->createTempSymbol("pub" + SecName + "_end");
+
+  bool HeaderEmitted = false;
+  // Emit the pubnames for this compilation unit.
+  for (const auto &Name : Names) {
+    if (Name.SkipPubSection)
+      continue;
+
+    if (!HeaderEmitted) {
+      // Emit the header.
+      Asm->EmitLabelDifference(EndLabel, BeginLabel, 4); // Length
+      Asm->OutStreamer->EmitLabel(BeginLabel);
+      Asm->emitInt16(dwarf::DW_PUBNAMES_VERSION); // Version
+      Asm->emitInt32(Unit.getStartOffset());      // Unit offset
+      Asm->emitInt32(Unit.getNextUnitOffset() - Unit.getStartOffset()); // Size
+      HeaderEmitted = true;
+    }
+    Asm->emitInt32(Name.Die->getOffset());
+
+    // Emit the string itself.
+    Asm->OutStreamer->EmitBytes(Name.Name.getString());
+    // Emit a null terminator.
+    Asm->emitInt8(0);
+  }
+
+  if (!HeaderEmitted)
+    return;
+  Asm->emitInt32(0); // End marker.
+  Asm->OutStreamer->EmitLabel(EndLabel);
+}
+
+/// Emit .debug_pubnames for \p Unit.
+void DwarfStreamer::emitPubNamesForUnit(const CompileUnit &Unit) {
+  emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubNamesSection(),
+                        "names", Unit, Unit.getPubnames());
+}
+
+/// Emit .debug_pubtypes for \p Unit.
+void DwarfStreamer::emitPubTypesForUnit(const CompileUnit &Unit) {
+  emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubTypesSection(),
+                        "types", Unit, Unit.getPubtypes());
+}
+
+/// Emit a CIE into the debug_frame section.
+void DwarfStreamer::emitCIE(StringRef CIEBytes) {
+  MS->SwitchSection(MC->getObjectFileInfo()->getDwarfFrameSection());
+
+  MS->EmitBytes(CIEBytes);
+  FrameSectionSize += CIEBytes.size();
+}
+
+/// Emit a FDE into the debug_frame section. \p FDEBytes
+/// contains the FDE data without the length, CIE offset and address
+/// which will be replaced with the parameter values.
+void DwarfStreamer::emitFDE(uint32_t CIEOffset, uint32_t AddrSize,
+                            uint32_t Address, StringRef FDEBytes) {
+  MS->SwitchSection(MC->getObjectFileInfo()->getDwarfFrameSection());
+
+  MS->EmitIntValue(FDEBytes.size() + 4 + AddrSize, 4);
+  MS->EmitIntValue(CIEOffset, 4);
+  MS->EmitIntValue(Address, AddrSize);
+  MS->EmitBytes(FDEBytes);
+  FrameSectionSize += FDEBytes.size() + 8 + AddrSize;
+}
+
+} // namespace dsymutil
+} // namespace llvm

Added: llvm/trunk/tools/dsymutil/DwarfStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DwarfStreamer.h?rev=335749&view=auto
==============================================================================
--- llvm/trunk/tools/dsymutil/DwarfStreamer.h (added)
+++ llvm/trunk/tools/dsymutil/DwarfStreamer.h Wed Jun 27 09:13:40 2018
@@ -0,0 +1,171 @@
+//===- tools/dsymutil/DwarfStreamer.h - Dwarf Streamer ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CompileUnit.h"
+#include "DebugMap.h"
+#include "NonRelocatableStringpool.h"
+#include "llvm/CodeGen/AccelTable.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
+#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDwarf.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCTargetOptions.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
+
+#ifndef LLVM_TOOLS_DSYMUTIL_DWARFSTREAMER_H
+#define LLVM_TOOLS_DSYMUTIL_DWARFSTREAMER_H
+
+namespace llvm {
+namespace dsymutil {
+
+struct LinkOptions;
+
+/// 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:
+  DwarfStreamer(raw_fd_ostream &OutFile) : OutFile(OutFile) {}
+  bool init(Triple TheTriple);
+
+  /// Dump the file to the disk.
+  bool finish(const DebugMap &);
+
+  AsmPrinter &getAsmPrinter() const { return *Asm; }
+
+  /// Set the current output section to debug_info and change
+  /// the MC Dwarf version to \p DwarfVersion.
+  void switchToDebugInfoSection(unsigned DwarfVersion);
+
+  /// 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().
+  void emitCompileUnitHeader(CompileUnit &Unit);
+
+  /// Recursively emit the DIE tree rooted at \p Die.
+  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);
+
+  /// Emit the string table described by \p Pool.
+  void emitStrings(const NonRelocatableStringpool &Pool);
+
+  /// Emit the swift_ast section stored in \p Buffer.
+  void emitSwiftAST(StringRef Buffer);
+
+  /// Emit debug_ranges for \p FuncRange by translating the
+  /// original \p Entries.
+  void emitRangesEntries(
+      int64_t UnitPcOffset, uint64_t OrigLowPc,
+      const FunctionIntervals::const_iterator &FuncRange,
+      const std::vector<DWARFDebugRangeList::RangeListEntry> &Entries,
+      unsigned AddressSize);
+
+  /// Emit debug_aranges entries for \p Unit and if \p DoRangesSection is true,
+  /// also emit the debug_ranges entries for the DW_TAG_compile_unit's
+  /// DW_AT_ranges attribute.
+  void emitUnitRangesEntries(CompileUnit &Unit, bool DoRangesSection);
+
+  uint32_t getRangesSectionSize() const { return RangesSectionSize; }
+
+  /// Emit the debug_loc contribution for \p Unit by copying the entries from
+  /// \p Dwarf and offsetting them. Update the location attributes to point to
+  /// the new entries.
+  void emitLocationsForUnit(const CompileUnit &Unit, DWARFContext &Dwarf);
+
+  /// Emit the line table described in \p Rows into the debug_line section.
+  void emitLineTableForUnit(MCDwarfLineTableParams Params,
+                            StringRef PrologueBytes, unsigned MinInstLength,
+                            std::vector<DWARFDebugLine::Row> &Rows,
+                            unsigned AdddressSize);
+
+  /// Copy over the debug sections that are not modified when updating.
+  void copyInvariantDebugSection(const object::ObjectFile &Obj, LinkOptions &);
+
+  uint32_t getLineSectionSize() const { return LineSectionSize; }
+
+  /// Emit the .debug_pubnames contribution for \p Unit.
+  void emitPubNamesForUnit(const CompileUnit &Unit);
+
+  /// Emit the .debug_pubtypes contribution for \p Unit.
+  void emitPubTypesForUnit(const CompileUnit &Unit);
+
+  /// Emit a CIE.
+  void emitCIE(StringRef CIEBytes);
+
+  /// Emit an FDE with data \p Bytes.
+  void emitFDE(uint32_t CIEOffset, uint32_t AddreSize, uint32_t Address,
+               StringRef Bytes);
+
+  /// Emit Apple namespaces accelerator table.
+  void emitAppleNamespaces(AccelTable<AppleAccelTableStaticOffsetData> &Table);
+
+  /// Emit Apple names accelerator table.
+  void emitAppleNames(AccelTable<AppleAccelTableStaticOffsetData> &Table);
+
+  /// Emit Apple Objective-C accelerator table.
+  void emitAppleObjc(AccelTable<AppleAccelTableStaticOffsetData> &Table);
+
+  /// Emit Apple type accelerator table.
+  void emitAppleTypes(AccelTable<AppleAccelTableStaticTypeData> &Table);
+
+  uint32_t getFrameSectionSize() const { return FrameSectionSize; }
+
+private:
+  /// \defgroup MCObjects MC layer objects constructed by the streamer
+  /// @{
+  std::unique_ptr<MCRegisterInfo> MRI;
+  std::unique_ptr<MCAsmInfo> MAI;
+  std::unique_ptr<MCObjectFileInfo> MOFI;
+  std::unique_ptr<MCContext> MC;
+  MCAsmBackend *MAB; // Owned by MCStreamer
+  std::unique_ptr<MCInstrInfo> MII;
+  std::unique_ptr<MCSubtargetInfo> MSTI;
+  MCCodeEmitter *MCE; // Owned by MCStreamer
+  MCStreamer *MS;     // Owned by AsmPrinter
+  std::unique_ptr<TargetMachine> TM;
+  std::unique_ptr<AsmPrinter> Asm;
+  /// @}
+
+  /// The file we stream the linked Dwarf to.
+  raw_fd_ostream &OutFile;
+
+  uint32_t RangesSectionSize;
+  uint32_t LocSectionSize;
+  uint32_t LineSectionSize;
+  uint32_t FrameSectionSize;
+
+  /// Emit the pubnames or pubtypes section contribution for \p
+  /// Unit into \p Sec. The data is provided in \p Names.
+  void emitPubSectionForUnit(MCSection *Sec, StringRef Name,
+                             const CompileUnit &Unit,
+                             const std::vector<CompileUnit::AccelInfo> &Names);
+};
+
+} // end namespace dsymutil
+} // end namespace llvm
+
+#endif // LLVM_TOOLS_DSYMUTIL_DWARFSTREAMER_H

Added: llvm/trunk/tools/dsymutil/LinkUtils.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/LinkUtils.h?rev=335749&view=auto
==============================================================================
--- llvm/trunk/tools/dsymutil/LinkUtils.h (added)
+++ llvm/trunk/tools/dsymutil/LinkUtils.h Wed Jun 27 09:13:40 2018
@@ -0,0 +1,64 @@
+//===- tools/dsymutil/LinkUtils.h - Dwarf linker utilities ------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_DSYMUTIL_LINKOPTIONS_H
+#define LLVM_TOOLS_DSYMUTIL_LINKOPTIONS_H
+
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/WithColor.h"
+#include <string>
+
+namespace llvm {
+namespace dsymutil {
+
+struct LinkOptions {
+  /// Verbosity
+  bool Verbose = false;
+
+  /// Skip emitting output
+  bool NoOutput = false;
+
+  /// Do not unique types according to ODR
+  bool NoODR = false;
+
+  /// Update
+  bool Update = false;
+
+  /// Minimize
+  bool Minimize = false;
+
+  /// Do not check swiftmodule timestamp
+  bool NoTimestamp = false;
+
+  /// Number of threads.
+  unsigned Threads = 1;
+
+  /// -oso-prepend-path
+  std::string PrependPath;
+
+  LinkOptions() = default;
+};
+
+inline void warn(Twine Warning, Twine Context = {}) {
+  WithColor::warning() << Warning + "\n";
+  if (!Context.isTriviallyEmpty())
+    WithColor::note() << Twine("while processing ") + Context + "\n";
+}
+
+inline bool error(Twine Error, Twine Context = {}) {
+  WithColor::error() << Error + "\n";
+  if (!Context.isTriviallyEmpty())
+    WithColor::note() << Twine("while processing ") + Context + "\n";
+  return false;
+}
+
+} // end namespace dsymutil
+} // end namespace llvm
+
+#endif // LLVM_TOOLS_DSYMUTIL_LINKOPTIONS_H

Modified: llvm/trunk/tools/dsymutil/MachODebugMapParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/MachODebugMapParser.cpp?rev=335749&r1=335748&r2=335749&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/MachODebugMapParser.cpp (original)
+++ llvm/trunk/tools/dsymutil/MachODebugMapParser.cpp Wed Jun 27 09:13:40 2018
@@ -1,6 +1,6 @@
 //===- tools/dsymutil/MachODebugMapParser.cpp - Parse STABS debug maps ----===//
 //
-//                             The LLVM Linker
+//                     The LLVM Compiler Infrastructure
 //
 // This file is distributed under the University of Illinois Open Source
 // License. See LICENSE.TXT for details.

Modified: llvm/trunk/tools/dsymutil/MachOUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/MachOUtils.cpp?rev=335749&r1=335748&r2=335749&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/MachOUtils.cpp (original)
+++ llvm/trunk/tools/dsymutil/MachOUtils.cpp Wed Jun 27 09:13:40 2018
@@ -1,4 +1,4 @@
-//===-- MachOUtils.h - Mach-o specific helpers for dsymutil  --------------===//
+//===-- MachOUtils.cpp - Mach-o specific helpers for dsymutil  ------------===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -10,8 +10,8 @@
 #include "MachOUtils.h"
 #include "BinaryHolder.h"
 #include "DebugMap.h"
+#include "LinkUtils.h"
 #include "NonRelocatableStringpool.h"
-#include "dsymutil.h"
 #include "llvm/MC/MCAsmLayout.h"
 #include "llvm/MC/MCMachObjectWriter.h"
 #include "llvm/MC/MCObjectStreamer.h"

Modified: llvm/trunk/tools/dsymutil/NonRelocatableStringpool.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/NonRelocatableStringpool.h?rev=335749&r1=335748&r2=335749&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/NonRelocatableStringpool.h (original)
+++ llvm/trunk/tools/dsymutil/NonRelocatableStringpool.h Wed Jun 27 09:13:40 2018
@@ -62,6 +62,21 @@ private:
   DwarfStringPoolEntryRef EmptyString;
 };
 
+/// Helper for making strong types.
+template <typename T, typename S> class StrongType : public T {
+public:
+  template <typename... Args>
+  explicit StrongType(Args... A) : T(std::forward<Args>(A)...) {}
+};
+
+/// It's very easy to introduce bugs by passing the wrong string pool in the
+/// dwarf linker. By using strong types the interface enforces that the right
+/// kind of pool is used.
+struct UniqueTag {};
+struct OffsetsTag {};
+using UniquingStringPool = StrongType<NonRelocatableStringpool, UniqueTag>;
+using OffsetsStringPool = StrongType<NonRelocatableStringpool, OffsetsTag>;
+
 } // end namespace dsymutil
 } // end namespace llvm
 

Modified: llvm/trunk/tools/dsymutil/dsymutil.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/dsymutil.cpp?rev=335749&r1=335748&r2=335749&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/dsymutil.cpp (original)
+++ llvm/trunk/tools/dsymutil/dsymutil.cpp Wed Jun 27 09:13:40 2018
@@ -15,6 +15,7 @@
 #include "dsymutil.h"
 #include "CFBundle.h"
 #include "DebugMap.h"
+#include "LinkUtils.h"
 #include "MachOUtils.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"

Modified: llvm/trunk/tools/dsymutil/dsymutil.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/dsymutil.h?rev=335749&r1=335748&r2=335749&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/dsymutil.h (original)
+++ llvm/trunk/tools/dsymutil/dsymutil.h Wed Jun 27 09:13:40 2018
@@ -1,6 +1,6 @@
 //===- tools/dsymutil/dsymutil.h - dsymutil high-level functionality ------===//
 //
-//                             The LLVM Linker
+//                     The LLVM Compiler Infrastructure
 //
 // This file is distributed under the University of Illinois Open Source
 // License. See LICENSE.TXT for details.
@@ -18,6 +18,7 @@
 #define LLVM_TOOLS_DSYMUTIL_DSYMUTIL_H
 
 #include "DebugMap.h"
+#include "LinkUtils.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Compiler.h"
@@ -29,34 +30,6 @@
 namespace llvm {
 namespace dsymutil {
 
-struct LinkOptions {
-  /// Verbosity
-  bool Verbose = false;
-
-  /// Skip emitting output
-  bool NoOutput = false;
-
-  /// Do not unique types according to ODR
-  bool NoODR = false;
-
-  /// Update
-  bool Update = false;
-
-  /// Minimize
-  bool Minimize = false;
-
-  /// Do not check swiftmodule timestamp
-  bool NoTimestamp = false;
-
-  /// Number of threads.
-  unsigned Threads = 1;
-
-  /// -oso-prepend-path
-  std::string PrependPath;
-
-  LinkOptions() = default;
-};
-
 /// Extract the DebugMaps from the given file.
 /// The file has to be a MachO object file. Multiple debug maps can be
 /// returned when the file is universal (aka fat) binary.
@@ -74,9 +47,6 @@ bool dumpStab(StringRef InputFile, Array
 bool linkDwarf(raw_fd_ostream &OutFile, const DebugMap &DM,
                const LinkOptions &Options);
 
-void warn(Twine Warning, Twine Context = {});
-bool error(Twine Error, Twine Context = {});
-
 } // end namespace dsymutil
 } // end namespace llvm
 




More information about the llvm-commits mailing list