//=== DWARFLinkerCompileUnit.cpp ------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "DWARFLinkerCompileUnit.h"
#include "AcceleratorRecordsSaver.h"
#include "DIEAttributeCloner.h"
#include "DIEGenerator.h"
#include "DependencyTracker.h"
#include "SyntheticTypeNameBuilder.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
#include "llvm/Support/DJB.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/Path.h"
#include <utility>

using namespace llvm;
using namespace llvm::dwarflinker_parallel;

CompileUnit::CompileUnit(LinkingGlobalData &GlobalData, unsigned ID,
                         StringRef ClangModuleName, DWARFFile &File,
                         OffsetToUnitTy UnitFromOffset,
                         dwarf::FormParams Format, llvm::endianness Endianess)
    : DwarfUnit(GlobalData, ID, ClangModuleName), File(File),
      getUnitFromOffset(UnitFromOffset), Stage(Stage::CreatedNotLoaded),
      AcceleratorRecords(&GlobalData.getAllocator()) {
  UnitName = File.FileName;
  setOutputFormat(Format, Endianess);
  getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);
}

CompileUnit::CompileUnit(LinkingGlobalData &GlobalData, DWARFUnit &OrigUnit,
                         unsigned ID, StringRef ClangModuleName,
                         DWARFFile &File, OffsetToUnitTy UnitFromOffset,
                         dwarf::FormParams Format, llvm::endianness Endianess)
    : DwarfUnit(GlobalData, ID, ClangModuleName), File(File),
      OrigUnit(&OrigUnit), getUnitFromOffset(UnitFromOffset),
      Stage(Stage::CreatedNotLoaded),
      AcceleratorRecords(&GlobalData.getAllocator()) {
  setOutputFormat(Format, Endianess);
  getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);

  DWARFDie CUDie = OrigUnit.getUnitDIE();
  if (!CUDie)
    return;

  if (std::optional<DWARFFormValue> Val = CUDie.find(dwarf::DW_AT_language)) {
    uint16_t LangVal = dwarf::toUnsigned(Val, 0);
    if (isODRLanguage(LangVal))
      Language = LangVal;
  }

  if (!GlobalData.getOptions().NoODR && Language.has_value())
    NoODR = false;

  if (const char *CUName = CUDie.getName(DINameKind::ShortName))
    UnitName = CUName;
  else
    UnitName = File.FileName;
  SysRoot = dwarf::toStringRef(CUDie.find(dwarf::DW_AT_LLVM_sysroot)).str();
}

void CompileUnit::loadLineTable() {
  LineTablePtr = File.Dwarf->getLineTableForUnit(&getOrigUnit());
}

void CompileUnit::maybeResetToLoadedStage() {
  // Nothing to reset if stage is less than "Loaded".
  if (getStage() < Stage::Loaded)
    return;

  // Note: We need to do erasing for "Loaded" stage because
  // if live analysys failed then we will have "Loaded" stage
  // with marking from "LivenessAnalysisDone" stage partially
  // done. That marking should be cleared.

  for (DIEInfo &Info : DieInfoArray)
    Info.unsetFlagsWhichSetDuringLiveAnalysis();

  LowPc = std::nullopt;
  HighPc = 0;
  Labels.clear();
  Ranges.clear();
  Dependencies.reset(nullptr);

  if (getStage() < Stage::Cloned) {
    setStage(Stage::Loaded);
    return;
  }

  AcceleratorRecords.erase();
  AbbreviationsSet.clear();
  Abbreviations.clear();
  OutUnitDIE = nullptr;
  DebugAddrIndexMap.clear();

  for (uint64_t &Offset : OutDieOffsetArray)
    Offset = 0;
  for (TypeEntry *&Name : TypeEntries)
    Name = nullptr;
  eraseSections();

  setStage(Stage::CreatedNotLoaded);
}

bool CompileUnit::loadInputDIEs() {
  DWARFDie InputUnitDIE = getUnitDIE(false);
  if (!InputUnitDIE)
    return false;

  // load input dies, resize Info structures array.
  DieInfoArray.resize(getOrigUnit().getNumDIEs());
  OutDieOffsetArray.resize(getOrigUnit().getNumDIEs(), 0);
  if (!NoODR)
    TypeEntries.resize(getOrigUnit().getNumDIEs());
  return true;
}

void CompileUnit::analyzeDWARFStructureRec(const DWARFDebugInfoEntry *DieEntry,
                                           bool IsODRUnavailableFunctionScope) {
  CompileUnit::DIEInfo &DieInfo = getDIEInfo(DieEntry);

  for (const DWARFDebugInfoEntry *CurChild = getFirstChildEntry(DieEntry);
       CurChild && CurChild->getAbbreviationDeclarationPtr();
       CurChild = getSiblingEntry(CurChild)) {
    CompileUnit::DIEInfo &ChildInfo = getDIEInfo(CurChild);
    bool ChildIsODRUnavailableFunctionScope = IsODRUnavailableFunctionScope;

    if (DieInfo.getIsInMouduleScope())
      ChildInfo.setIsInMouduleScope();

    if (DieInfo.getIsInFunctionScope())
      ChildInfo.setIsInFunctionScope();

    if (DieInfo.getIsInAnonNamespaceScope())
      ChildInfo.setIsInAnonNamespaceScope();

    switch (CurChild->getTag()) {
    case dwarf::DW_TAG_module:
      ChildInfo.setIsInMouduleScope();
      if (DieEntry->getTag() == dwarf::DW_TAG_compile_unit &&
          dwarf::toString(find(CurChild, dwarf::DW_AT_name), "") !=
              getClangModuleName())
        analyzeImportedModule(CurChild);
      break;
    case dwarf::DW_TAG_subprogram:
      ChildInfo.setIsInFunctionScope();
      if (!ChildIsODRUnavailableFunctionScope &&
          !ChildInfo.getIsInMouduleScope()) {
        if (find(CurChild,
                 {dwarf::DW_AT_abstract_origin, dwarf::DW_AT_specification}))
          ChildIsODRUnavailableFunctionScope = true;
      }
      break;
    case dwarf::DW_TAG_namespace: {
      UnitEntryPairTy NamespaceEntry = {this, CurChild};

      if (find(CurChild, dwarf::DW_AT_extension))
        NamespaceEntry = NamespaceEntry.getNamespaceOrigin();

      if (!NamespaceEntry.CU->find(NamespaceEntry.DieEntry, dwarf::DW_AT_name))
        ChildInfo.setIsInAnonNamespaceScope();
    } break;
    default:
      break;
    }

    if (!isClangModule() && !getGlobalData().getOptions().UpdateIndexTablesOnly)
      ChildInfo.setTrackLiveness();

    if ((!ChildInfo.getIsInAnonNamespaceScope() &&
         !ChildIsODRUnavailableFunctionScope && !NoODR))
      ChildInfo.setODRAvailable();

    if (CurChild->hasChildren())
      analyzeDWARFStructureRec(CurChild, ChildIsODRUnavailableFunctionScope);
  }
}

StringEntry *CompileUnit::getFileName(unsigned FileIdx,
                                      StringPool &GlobalStrings) {
  if (LineTablePtr) {
    if (LineTablePtr->hasFileAtIndex(FileIdx)) {
      // Cache the resolved paths based on the index in the line table,
      // because calling realpath is expensive.
      ResolvedPathsMap::const_iterator It = ResolvedFullPaths.find(FileIdx);
      if (It == ResolvedFullPaths.end()) {
        std::string OrigFileName;
        bool FoundFileName = LineTablePtr->getFileNameByIndex(
            FileIdx, getOrigUnit().getCompilationDir(),
            DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
            OrigFileName);
        (void)FoundFileName;
        assert(FoundFileName && "Must get file name from line table");

        // Second level of caching, this time based on the file's parent
        // path.
        StringRef FileName = sys::path::filename(OrigFileName);
        StringRef ParentPath = sys::path::parent_path(OrigFileName);

        // If the ParentPath has not yet been resolved, resolve and cache it for
        // future look-ups.
        StringMap<StringEntry *>::iterator ParentIt =
            ResolvedParentPaths.find(ParentPath);
        if (ParentIt == ResolvedParentPaths.end()) {
          SmallString<256> RealPath;
          sys::fs::real_path(ParentPath, RealPath);
          ParentIt =
              ResolvedParentPaths
                  .insert({ParentPath, GlobalStrings.insert(RealPath).first})
                  .first;
        }

        // Join the file name again with the resolved path.
        SmallString<256> ResolvedPath(ParentIt->second->first());
        sys::path::append(ResolvedPath, FileName);

        It = ResolvedFullPaths
                 .insert(std::make_pair(
                     FileIdx, GlobalStrings.insert(ResolvedPath).first))
                 .first;
      }

      return It->second;
    }
  }

  return nullptr;
}

void CompileUnit::cleanupDataAfterClonning() {
  AbbreviationsSet.clear();
  ResolvedFullPaths.shrink_and_clear();
  ResolvedParentPaths.clear();
  FileNames.shrink_and_clear();
  DieInfoArray = SmallVector<DIEInfo>();
  OutDieOffsetArray = SmallVector<uint64_t>();
  TypeEntries = SmallVector<TypeEntry *>();
  Dependencies.reset(nullptr);
  getOrigUnit().clear();
}

/// Make a best effort to guess the
/// Xcode.app/Contents/Developer/Toolchains/ path from an SDK path.
static SmallString<128> guessToolchainBaseDir(StringRef SysRoot) {
  SmallString<128> Result;
  // Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk
  StringRef Base = sys::path::parent_path(SysRoot);
  if (sys::path::filename(Base) != "SDKs")
    return Result;
  Base = sys::path::parent_path(Base);
  Result = Base;
  Result += "/Toolchains";
  return Result;
}

/// Collect references to parseable Swift interfaces in imported
/// DW_TAG_module blocks.
void CompileUnit::analyzeImportedModule(const DWARFDebugInfoEntry *DieEntry) {
  if (!Language || Language != dwarf::DW_LANG_Swift)
    return;

  if (!GlobalData.getOptions().ParseableSwiftInterfaces)
    return;

  StringRef Path =
      dwarf::toStringRef(find(DieEntry, dwarf::DW_AT_LLVM_include_path));
  if (!Path.ends_with(".swiftinterface"))
    return;
  // Don't track interfaces that are part of the SDK.
  StringRef SysRoot =
      dwarf::toStringRef(find(DieEntry, dwarf::DW_AT_LLVM_sysroot));
  if (SysRoot.empty())
    SysRoot = getSysRoot();
  if (!SysRoot.empty() && Path.starts_with(SysRoot))
    return;
  // Don't track interfaces that are part of the toolchain.
  // For example: Swift, _Concurrency, ...
  SmallString<128> Toolchain = guessToolchainBaseDir(SysRoot);
  if (!Toolchain.empty() && Path.starts_with(Toolchain))
    return;
  if (std::optional<DWARFFormValue> Val = find(DieEntry, dwarf::DW_AT_name)) {
    Expected<const char *> Name = Val->getAsCString();
    if (!Name) {
      warn(Name.takeError());
      return;
    }

    auto &Entry = (*GlobalData.getOptions().ParseableSwiftInterfaces)[*Name];
    // The prepend path is applied later when copying.
    SmallString<128> ResolvedPath;
    if (sys::path::is_relative(Path))
      sys::path::append(
          ResolvedPath,
          dwarf::toString(getUnitDIE().find(dwarf::DW_AT_comp_dir), ""));
    sys::path::append(ResolvedPath, Path);
    if (!Entry.empty() && Entry != ResolvedPath) {
      DWARFDie Die = getDIE(DieEntry);
      warn(Twine("conflicting parseable interfaces for Swift Module ") + *Name +
               ": " + Entry + " and " + Path + ".",
           &Die);
    }
    Entry = std::string(ResolvedPath.str());
  }
}

Error CompileUnit::assignTypeNames(TypePool &TypePoolRef) {
  if (!getUnitDIE().isValid())
    return Error::success();

  SyntheticTypeNameBuilder NameBuilder(TypePoolRef);
  return assignTypeNamesRec(getDebugInfoEntry(0), NameBuilder);
}

Error CompileUnit::assignTypeNamesRec(const DWARFDebugInfoEntry *DieEntry,
                                      SyntheticTypeNameBuilder &NameBuilder) {
  OrderedChildrenIndexAssigner ChildrenIndexAssigner(*this, DieEntry);
  for (const DWARFDebugInfoEntry *CurChild = getFirstChildEntry(DieEntry);
       CurChild && CurChild->getAbbreviationDeclarationPtr();
       CurChild = getSiblingEntry(CurChild)) {
    CompileUnit::DIEInfo &ChildInfo = getDIEInfo(CurChild);
    if (!ChildInfo.needToPlaceInTypeTable())
      continue;

    assert(ChildInfo.getODRAvailable());
    if (Error Err = NameBuilder.assignName(
            {this, CurChild},
            ChildrenIndexAssigner.getChildIndex(*this, CurChild)))
      return Err;

    if (Error Err = assignTypeNamesRec(CurChild, NameBuilder))
      return Err;
  }

  return Error::success();
}

void CompileUnit::updateDieRefPatchesWithClonedOffsets() {
  if (std::optional<SectionDescriptor *> DebugInfoSection =
          tryGetSectionDescriptor(DebugSectionKind::DebugInfo)) {

    (*DebugInfoSection)
        ->ListDebugDieRefPatch.forEach([&](DebugDieRefPatch &Patch) {
          /// Replace stored DIE indexes with DIE output offsets.
          Patch.RefDieIdxOrClonedOffset =
              Patch.RefCU.getPointer()->getDieOutOffset(
                  Patch.RefDieIdxOrClonedOffset);
        });

    (*DebugInfoSection)
        ->ListDebugULEB128DieRefPatch.forEach(
            [&](DebugULEB128DieRefPatch &Patch) {
              /// Replace stored DIE indexes with DIE output offsets.
              Patch.RefDieIdxOrClonedOffset =
                  Patch.RefCU.getPointer()->getDieOutOffset(
                      Patch.RefDieIdxOrClonedOffset);
            });
  }

  if (std::optional<SectionDescriptor *> DebugLocSection =
          tryGetSectionDescriptor(DebugSectionKind::DebugLoc)) {
    (*DebugLocSection)
        ->ListDebugULEB128DieRefPatch.forEach(
            [](DebugULEB128DieRefPatch &Patch) {
              /// Replace stored DIE indexes with DIE output offsets.
              Patch.RefDieIdxOrClonedOffset =
                  Patch.RefCU.getPointer()->getDieOutOffset(
                      Patch.RefDieIdxOrClonedOffset);
            });
  }

  if (std::optional<SectionDescriptor *> DebugLocListsSection =
          tryGetSectionDescriptor(DebugSectionKind::DebugLocLists)) {
    (*DebugLocListsSection)
        ->ListDebugULEB128DieRefPatch.forEach(
            [](DebugULEB128DieRefPatch &Patch) {
              /// Replace stored DIE indexes with DIE output offsets.
              Patch.RefDieIdxOrClonedOffset =
                  Patch.RefCU.getPointer()->getDieOutOffset(
                      Patch.RefDieIdxOrClonedOffset);
            });
  }
}

std::optional<UnitEntryPairTy> CompileUnit::resolveDIEReference(
    const DWARFFormValue &RefValue,
    ResolveInterCUReferencesMode CanResolveInterCUReferences) {
  if (std::optional<DWARFFormValue::UnitOffset> Ref =
          *RefValue.getAsRelativeReference()) {
    if (Ref->Unit == OrigUnit) {
      // Referenced DIE is in current compile unit.
      if (std::optional<uint32_t> RefDieIdx =
              getDIEIndexForOffset(OrigUnit->getOffset() + Ref->Offset))
        return UnitEntryPairTy{this, OrigUnit->getDebugInfoEntry(*RefDieIdx)};
    }
    uint64_t RefDIEOffset =
        Ref->Unit ? Ref->Unit->getOffset() + Ref->Offset : Ref->Offset;
    if (CompileUnit *RefCU = getUnitFromOffset(RefDIEOffset)) {
      if (RefCU == this) {
        // Referenced DIE is in current compile unit.
        if (std::optional<uint32_t> RefDieIdx =
                getDIEIndexForOffset(RefDIEOffset))
          return UnitEntryPairTy{this, getDebugInfoEntry(*RefDieIdx)};
      } else if (CanResolveInterCUReferences) {
        // Referenced DIE is in other compile unit.

        // Check whether DIEs are loaded for that compile unit.
        enum Stage ReferredCUStage = RefCU->getStage();
        if (ReferredCUStage < Stage::Loaded || ReferredCUStage > Stage::Cloned)
          return UnitEntryPairTy{RefCU, nullptr};

        if (std::optional<uint32_t> RefDieIdx =
                RefCU->getDIEIndexForOffset(RefDIEOffset))
          return UnitEntryPairTy{RefCU, RefCU->getDebugInfoEntry(*RefDieIdx)};
      } else
        return UnitEntryPairTy{RefCU, nullptr};
    }
  }

  return std::nullopt;
}

std::optional<UnitEntryPairTy> CompileUnit::resolveDIEReference(
    const DWARFDebugInfoEntry *DieEntry, dwarf::Attribute Attr,
    ResolveInterCUReferencesMode CanResolveInterCUReferences) {
  if (std::optional<DWARFFormValue> AttrVal = find(DieEntry, Attr))
    return resolveDIEReference(*AttrVal, CanResolveInterCUReferences);

  return std::nullopt;
}

void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc,
                                   int64_t PcOffset) {
  std::lock_guard<std::mutex> Guard(RangesMutex);

  Ranges.insert({FuncLowPc, FuncHighPc}, PcOffset);
  if (LowPc)
    LowPc = std::min(*LowPc, FuncLowPc + PcOffset);
  else
    LowPc = FuncLowPc + PcOffset;
  this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);
}

void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {
  std::lock_guard<std::mutex> Guard(LabelsMutex);
  Labels.insert({LabelLowPc, PcOffset});
}

Error CompileUnit::cloneAndEmitDebugLocations() {
  if (getGlobalData().getOptions().UpdateIndexTablesOnly)
    return Error::success();

  if (getOrigUnit().getVersion() < 5) {
    emitLocations(DebugSectionKind::DebugLoc);
    return Error::success();
  }

  emitLocations(DebugSectionKind::DebugLocLists);
  return Error::success();
}

void CompileUnit::emitLocations(DebugSectionKind LocationSectionKind) {
  SectionDescriptor &DebugInfoSection =
      getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);

  if (!DebugInfoSection.ListDebugLocPatch.empty()) {
    SectionDescriptor &OutLocationSection =
        getOrCreateSectionDescriptor(LocationSectionKind);
    DWARFUnit &OrigUnit = getOrigUnit();

    uint64_t OffsetAfterUnitLength = emitLocListHeader(OutLocationSection);

    DebugInfoSection.ListDebugLocPatch.forEach([&](DebugLocPatch &Patch) {
      // Get location expressions vector corresponding to the current
      // attribute from the source DWARF.
      uint64_t InputDebugLocSectionOffset = DebugInfoSection.getIntVal(
          Patch.PatchOffset,
          DebugInfoSection.getFormParams().getDwarfOffsetByteSize());
      Expected<DWARFLocationExpressionsVector> OriginalLocations =
          OrigUnit.findLoclistFromOffset(InputDebugLocSectionOffset);

      if (!OriginalLocations) {
        warn(OriginalLocations.takeError());
        return;
      }

      LinkedLocationExpressionsVector LinkedLocationExpressions;
      for (DWARFLocationExpression &CurExpression : *OriginalLocations) {
        LinkedLocationExpressionsWithOffsetPatches LinkedExpression;

        if (CurExpression.Range) {
          // Relocate address range.
          LinkedExpression.Expression.Range = {
              CurExpression.Range->LowPC + Patch.AddrAdjustmentValue,
              CurExpression.Range->HighPC + Patch.AddrAdjustmentValue};
        }

        DataExtractor Data(CurExpression.Expr, OrigUnit.isLittleEndian(),
                           OrigUnit.getAddressByteSize());

        DWARFExpression InputExpression(Data, OrigUnit.getAddressByteSize(),
                                        OrigUnit.getFormParams().Format);
        cloneDieAttrExpression(InputExpression,
                               LinkedExpression.Expression.Expr,
                               OutLocationSection, Patch.AddrAdjustmentValue,
                               LinkedExpression.Patches);

        LinkedLocationExpressions.push_back({LinkedExpression});
      }

      // Emit locations list table fragment corresponding to the CurLocAttr.
      DebugInfoSection.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset,
                             OutLocationSection.OS.tell());
      emitLocListFragment(LinkedLocationExpressions, OutLocationSection);
    });

    if (OffsetAfterUnitLength > 0) {
      assert(OffsetAfterUnitLength -
                 OutLocationSection.getFormParams().getDwarfOffsetByteSize() <
             OffsetAfterUnitLength);
      OutLocationSection.apply(
          OffsetAfterUnitLength -
              OutLocationSection.getFormParams().getDwarfOffsetByteSize(),
          dwarf::DW_FORM_sec_offset,
          OutLocationSection.OS.tell() - OffsetAfterUnitLength);
    }
  }
}

/// Emit debug locations(.debug_loc, .debug_loclists) header.
uint64_t CompileUnit::emitLocListHeader(SectionDescriptor &OutLocationSection) {
  if (getOrigUnit().getVersion() < 5)
    return 0;

  // unit_length.
  OutLocationSection.emitUnitLength(0xBADDEF);
  uint64_t OffsetAfterUnitLength = OutLocationSection.OS.tell();

  // Version.
  OutLocationSection.emitIntVal(5, 2);

  // Address size.
  OutLocationSection.emitIntVal(OutLocationSection.getFormParams().AddrSize, 1);

  // Seg_size
  OutLocationSection.emitIntVal(0, 1);

  // Offset entry count
  OutLocationSection.emitIntVal(0, 4);

  return OffsetAfterUnitLength;
}

/// Emit debug locations(.debug_loc, .debug_loclists) fragment.
uint64_t CompileUnit::emitLocListFragment(
    const LinkedLocationExpressionsVector &LinkedLocationExpression,
    SectionDescriptor &OutLocationSection) {
  uint64_t OffsetBeforeLocationExpression = 0;

  if (getOrigUnit().getVersion() < 5) {
    uint64_t BaseAddress = 0;
    if (std::optional<uint64_t> LowPC = getLowPc())
      BaseAddress = *LowPC;

    for (const LinkedLocationExpressionsWithOffsetPatches &LocExpression :
         LinkedLocationExpression) {
      if (LocExpression.Expression.Range) {
        OutLocationSection.emitIntVal(
            LocExpression.Expression.Range->LowPC - BaseAddress,
            OutLocationSection.getFormParams().AddrSize);
        OutLocationSection.emitIntVal(
            LocExpression.Expression.Range->HighPC - BaseAddress,
            OutLocationSection.getFormParams().AddrSize);
      }

      OutLocationSection.emitIntVal(LocExpression.Expression.Expr.size(), 2);
      OffsetBeforeLocationExpression = OutLocationSection.OS.tell();
      for (uint64_t *OffsetPtr : LocExpression.Patches)
        *OffsetPtr += OffsetBeforeLocationExpression;

      OutLocationSection.OS
          << StringRef((const char *)LocExpression.Expression.Expr.data(),
                       LocExpression.Expression.Expr.size());
    }

    // Emit the terminator entry.
    OutLocationSection.emitIntVal(0,
                                  OutLocationSection.getFormParams().AddrSize);
    OutLocationSection.emitIntVal(0,
                                  OutLocationSection.getFormParams().AddrSize);
    return OffsetBeforeLocationExpression;
  }

  std::optional<uint64_t> BaseAddress;
  for (const LinkedLocationExpressionsWithOffsetPatches &LocExpression :
       LinkedLocationExpression) {
    if (LocExpression.Expression.Range) {
      // Check whether base address is set. If it is not set yet
      // then set current base address and emit base address selection entry.
      if (!BaseAddress) {
        BaseAddress = LocExpression.Expression.Range->LowPC;

        // Emit base address.
        OutLocationSection.emitIntVal(dwarf::DW_LLE_base_addressx, 1);
        encodeULEB128(DebugAddrIndexMap.getValueIndex(*BaseAddress),
                      OutLocationSection.OS);
      }

      // Emit type of entry.
      OutLocationSection.emitIntVal(dwarf::DW_LLE_offset_pair, 1);

      // Emit start offset relative to base address.
      encodeULEB128(LocExpression.Expression.Range->LowPC - *BaseAddress,
                    OutLocationSection.OS);

      // Emit end offset relative to base address.
      encodeULEB128(LocExpression.Expression.Range->HighPC - *BaseAddress,
                    OutLocationSection.OS);
    } else
      // Emit type of entry.
      OutLocationSection.emitIntVal(dwarf::DW_LLE_default_location, 1);

    encodeULEB128(LocExpression.Expression.Expr.size(), OutLocationSection.OS);
    OffsetBeforeLocationExpression = OutLocationSection.OS.tell();
    for (uint64_t *OffsetPtr : LocExpression.Patches)
      *OffsetPtr += OffsetBeforeLocationExpression;

    OutLocationSection.OS << StringRef(
        (const char *)LocExpression.Expression.Expr.data(),
        LocExpression.Expression.Expr.size());
  }

  // Emit the terminator entry.
  OutLocationSection.emitIntVal(dwarf::DW_LLE_end_of_list, 1);
  return OffsetBeforeLocationExpression;
}

Error CompileUnit::emitDebugAddrSection() {
  if (GlobalData.getOptions().UpdateIndexTablesOnly)
    return Error::success();

  if (getVersion() < 5)
    return Error::success();

  if (DebugAddrIndexMap.empty())
    return Error::success();

  SectionDescriptor &OutAddrSection =
      getOrCreateSectionDescriptor(DebugSectionKind::DebugAddr);

  // Emit section header.

  //   Emit length.
  OutAddrSection.emitUnitLength(0xBADDEF);
  uint64_t OffsetAfterSectionLength = OutAddrSection.OS.tell();

  //   Emit version.
  OutAddrSection.emitIntVal(5, 2);

  //   Emit address size.
  OutAddrSection.emitIntVal(getFormParams().AddrSize, 1);

  //   Emit segment size.
  OutAddrSection.emitIntVal(0, 1);

  // Emit addresses.
  for (uint64_t AddrValue : DebugAddrIndexMap.getValues())
    OutAddrSection.emitIntVal(AddrValue, getFormParams().AddrSize);

  // Patch section length.
  OutAddrSection.apply(
      OffsetAfterSectionLength -
          OutAddrSection.getFormParams().getDwarfOffsetByteSize(),
      dwarf::DW_FORM_sec_offset,
      OutAddrSection.OS.tell() - OffsetAfterSectionLength);

  return Error::success();
}

Error CompileUnit::cloneAndEmitRanges() {
  if (getGlobalData().getOptions().UpdateIndexTablesOnly)
    return Error::success();

  // Build set of linked address ranges for unit function ranges.
  AddressRanges LinkedFunctionRanges;
  for (const AddressRangeValuePair &Range : getFunctionRanges())
    LinkedFunctionRanges.insert(
        {Range.Range.start() + Range.Value, Range.Range.end() + Range.Value});

  emitAranges(LinkedFunctionRanges);

  if (getOrigUnit().getVersion() < 5) {
    cloneAndEmitRangeList(DebugSectionKind::DebugRange, LinkedFunctionRanges);
    return Error::success();
  }

  cloneAndEmitRangeList(DebugSectionKind::DebugRngLists, LinkedFunctionRanges);
  return Error::success();
}

void CompileUnit::cloneAndEmitRangeList(DebugSectionKind RngSectionKind,
                                        AddressRanges &LinkedFunctionRanges) {
  SectionDescriptor &DebugInfoSection =
      getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);
  SectionDescriptor &OutRangeSection =
      getOrCreateSectionDescriptor(RngSectionKind);

  if (!DebugInfoSection.ListDebugRangePatch.empty()) {
    std::optional<AddressRangeValuePair> CachedRange;
    uint64_t OffsetAfterUnitLength = emitRangeListHeader(OutRangeSection);

    DebugRangePatch *CompileUnitRangePtr = nullptr;
    DebugInfoSection.ListDebugRangePatch.forEach([&](DebugRangePatch &Patch) {
      if (Patch.IsCompileUnitRanges) {
        CompileUnitRangePtr = &Patch;
      } else {
        // Get ranges from the source DWARF corresponding to the current
        // attribute.
        AddressRanges LinkedRanges;
        uint64_t InputDebugRangesSectionOffset = DebugInfoSection.getIntVal(
            Patch.PatchOffset,
            DebugInfoSection.getFormParams().getDwarfOffsetByteSize());
        if (Expected<DWARFAddressRangesVector> InputRanges =
                getOrigUnit().findRnglistFromOffset(
                    InputDebugRangesSectionOffset)) {
          // Apply relocation adjustment.
          for (const auto &Range : *InputRanges) {
            if (!CachedRange || !CachedRange->Range.contains(Range.LowPC))
              CachedRange =
                  getFunctionRanges().getRangeThatContains(Range.LowPC);

            // All range entries should lie in the function range.
            if (!CachedRange) {
              warn("inconsistent range data.");
              continue;
            }

            // Store range for emiting.
            LinkedRanges.insert({Range.LowPC + CachedRange->Value,
                                 Range.HighPC + CachedRange->Value});
          }
        } else {
          llvm::consumeError(InputRanges.takeError());
          warn("invalid range list ignored.");
        }

        // Emit linked ranges.
        DebugInfoSection.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset,
                               OutRangeSection.OS.tell());
        emitRangeListFragment(LinkedRanges, OutRangeSection);
      }
    });

    if (CompileUnitRangePtr != nullptr) {
      // Emit compile unit ranges last to be binary compatible with classic
      // dsymutil.
      DebugInfoSection.apply(CompileUnitRangePtr->PatchOffset,
                             dwarf::DW_FORM_sec_offset,
                             OutRangeSection.OS.tell());
      emitRangeListFragment(LinkedFunctionRanges, OutRangeSection);
    }

    if (OffsetAfterUnitLength > 0) {
      assert(OffsetAfterUnitLength -
                 OutRangeSection.getFormParams().getDwarfOffsetByteSize() <
             OffsetAfterUnitLength);
      OutRangeSection.apply(
          OffsetAfterUnitLength -
              OutRangeSection.getFormParams().getDwarfOffsetByteSize(),
          dwarf::DW_FORM_sec_offset,
          OutRangeSection.OS.tell() - OffsetAfterUnitLength);
    }
  }
}

uint64_t CompileUnit::emitRangeListHeader(SectionDescriptor &OutRangeSection) {
  if (OutRangeSection.getFormParams().Version < 5)
    return 0;

  // unit_length.
  OutRangeSection.emitUnitLength(0xBADDEF);
  uint64_t OffsetAfterUnitLength = OutRangeSection.OS.tell();

  // Version.
  OutRangeSection.emitIntVal(5, 2);

  // Address size.
  OutRangeSection.emitIntVal(OutRangeSection.getFormParams().AddrSize, 1);

  // Seg_size
  OutRangeSection.emitIntVal(0, 1);

  // Offset entry count
  OutRangeSection.emitIntVal(0, 4);

  return OffsetAfterUnitLength;
}

void CompileUnit::emitRangeListFragment(const AddressRanges &LinkedRanges,
                                        SectionDescriptor &OutRangeSection) {
  if (OutRangeSection.getFormParams().Version < 5) {
    // Emit ranges.
    uint64_t BaseAddress = 0;
    if (std::optional<uint64_t> LowPC = getLowPc())
      BaseAddress = *LowPC;

    for (const AddressRange &Range : LinkedRanges) {
      OutRangeSection.emitIntVal(Range.start() - BaseAddress,
                                 OutRangeSection.getFormParams().AddrSize);
      OutRangeSection.emitIntVal(Range.end() - BaseAddress,
                                 OutRangeSection.getFormParams().AddrSize);
    }

    // Add the terminator entry.
    OutRangeSection.emitIntVal(0, OutRangeSection.getFormParams().AddrSize);
    OutRangeSection.emitIntVal(0, OutRangeSection.getFormParams().AddrSize);
    return;
  }

  std::optional<uint64_t> BaseAddress;
  for (const AddressRange &Range : LinkedRanges) {
    if (!BaseAddress) {
      BaseAddress = Range.start();

      // Emit base address.
      OutRangeSection.emitIntVal(dwarf::DW_RLE_base_addressx, 1);
      encodeULEB128(getDebugAddrIndex(*BaseAddress), OutRangeSection.OS);
    }

    // Emit type of entry.
    OutRangeSection.emitIntVal(dwarf::DW_RLE_offset_pair, 1);

    // Emit start offset relative to base address.
    encodeULEB128(Range.start() - *BaseAddress, OutRangeSection.OS);

    // Emit end offset relative to base address.
    encodeULEB128(Range.end() - *BaseAddress, OutRangeSection.OS);
  }

  // Emit the terminator entry.
  OutRangeSection.emitIntVal(dwarf::DW_RLE_end_of_list, 1);
}

void CompileUnit::emitAranges(AddressRanges &LinkedFunctionRanges) {
  if (LinkedFunctionRanges.empty())
    return;

  SectionDescriptor &DebugInfoSection =
      getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);
  SectionDescriptor &OutArangesSection =
      getOrCreateSectionDescriptor(DebugSectionKind::DebugARanges);

  // Emit Header.
  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 = OutArangesSection.getFormParams().AddrSize * 2;
  unsigned Padding = offsetToAlignment(HeaderSize, Align(TupleSize));

  OutArangesSection.emitOffset(0xBADDEF); // Aranges length
  uint64_t OffsetAfterArangesLengthField = OutArangesSection.OS.tell();

  OutArangesSection.emitIntVal(dwarf::DW_ARANGES_VERSION, 2); // Version number
  OutArangesSection.notePatch(
      DebugOffsetPatch{OutArangesSection.OS.tell(), &DebugInfoSection});
  OutArangesSection.emitOffset(0xBADDEF); // Corresponding unit's offset
  OutArangesSection.emitIntVal(OutArangesSection.getFormParams().AddrSize,
                               1);    // Address size
  OutArangesSection.emitIntVal(0, 1); // Segment size

  for (size_t Idx = 0; Idx < Padding; Idx++)
    OutArangesSection.emitIntVal(0, 1); // Padding

  // Emit linked ranges.
  for (const AddressRange &Range : LinkedFunctionRanges) {
    OutArangesSection.emitIntVal(Range.start(),
                                 OutArangesSection.getFormParams().AddrSize);
    OutArangesSection.emitIntVal(Range.end() - Range.start(),
                                 OutArangesSection.getFormParams().AddrSize);
  }

  // Emit terminator.
  OutArangesSection.emitIntVal(0, OutArangesSection.getFormParams().AddrSize);
  OutArangesSection.emitIntVal(0, OutArangesSection.getFormParams().AddrSize);

  uint64_t OffsetAfterArangesEnd = OutArangesSection.OS.tell();

  // Update Aranges lentgh.
  OutArangesSection.apply(
      OffsetAfterArangesLengthField -
          OutArangesSection.getFormParams().getDwarfOffsetByteSize(),
      dwarf::DW_FORM_sec_offset,
      OffsetAfterArangesEnd - OffsetAfterArangesLengthField);
}

Error CompileUnit::cloneAndEmitDebugMacro() {
  if (getOutUnitDIE() == nullptr)
    return Error::success();

  DWARFUnit &OrigUnit = getOrigUnit();
  DWARFDie OrigUnitDie = OrigUnit.getUnitDIE();

  // Check for .debug_macro table.
  if (std::optional<uint64_t> MacroAttr =
          dwarf::toSectionOffset(OrigUnitDie.find(dwarf::DW_AT_macros))) {
    if (const DWARFDebugMacro *Table =
            getContaingFile().Dwarf->getDebugMacro()) {
      emitMacroTableImpl(Table, *MacroAttr, true);
    }
  }

  // Check for .debug_macinfo table.
  if (std::optional<uint64_t> MacroAttr =
          dwarf::toSectionOffset(OrigUnitDie.find(dwarf::DW_AT_macro_info))) {
    if (const DWARFDebugMacro *Table =
            getContaingFile().Dwarf->getDebugMacinfo()) {
      emitMacroTableImpl(Table, *MacroAttr, false);
    }
  }

  return Error::success();
}

void CompileUnit::emitMacroTableImpl(const DWARFDebugMacro *MacroTable,
                                     uint64_t OffsetToMacroTable,
                                     bool hasDWARFv5Header) {
  SectionDescriptor &OutSection =
      hasDWARFv5Header
          ? getOrCreateSectionDescriptor(DebugSectionKind::DebugMacro)
          : getOrCreateSectionDescriptor(DebugSectionKind::DebugMacinfo);

  bool DefAttributeIsReported = false;
  bool UndefAttributeIsReported = false;
  bool ImportAttributeIsReported = false;

  for (const DWARFDebugMacro::MacroList &List : MacroTable->MacroLists) {
    if (OffsetToMacroTable == List.Offset) {
      // Write DWARFv5 header.
      if (hasDWARFv5Header) {
        // Write header version.
        OutSection.emitIntVal(List.Header.Version, sizeof(List.Header.Version));

        uint8_t Flags = List.Header.Flags;

        // Check for OPCODE_OPERANDS_TABLE.
        if (Flags &
            DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE) {
          Flags &=
              ~DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE;
          warn("opcode_operands_table is not supported yet.");
        }

        // Check for DEBUG_LINE_OFFSET.
        std::optional<uint64_t> StmtListOffset;
        if (Flags & DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET) {
          // Get offset to the line table from the cloned compile unit.
          for (auto &V : getOutUnitDIE()->values()) {
            if (V.getAttribute() == dwarf::DW_AT_stmt_list) {
              StmtListOffset = V.getDIEInteger().getValue();
              break;
            }
          }

          if (!StmtListOffset) {
            Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET;
            warn("couldn`t find line table for macro table.");
          }
        }

        // Write flags.
        OutSection.emitIntVal(Flags, sizeof(Flags));

        // Write offset to line table.
        if (StmtListOffset) {
          OutSection.notePatch(DebugOffsetPatch{
              OutSection.OS.tell(),
              &getOrCreateSectionDescriptor(DebugSectionKind::DebugLine)});
          // TODO: check that List.Header.getOffsetByteSize() and
          // DebugOffsetPatch agree on size.
          OutSection.emitIntVal(0xBADDEF, List.Header.getOffsetByteSize());
        }
      }

      // Write macro entries.
      for (const DWARFDebugMacro::Entry &MacroEntry : List.Macros) {
        if (MacroEntry.Type == 0) {
          encodeULEB128(MacroEntry.Type, OutSection.OS);
          continue;
        }

        uint8_t MacroType = MacroEntry.Type;
        switch (MacroType) {
        default: {
          bool HasVendorSpecificExtension =
              (!hasDWARFv5Header &&
               MacroType == dwarf::DW_MACINFO_vendor_ext) ||
              (hasDWARFv5Header && (MacroType >= dwarf::DW_MACRO_lo_user &&
                                    MacroType <= dwarf::DW_MACRO_hi_user));

          if (HasVendorSpecificExtension) {
            // Write macinfo type.
            OutSection.emitIntVal(MacroType, 1);

            // Write vendor extension constant.
            encodeULEB128(MacroEntry.ExtConstant, OutSection.OS);

            // Write vendor extension string.
            OutSection.emitString(dwarf::DW_FORM_string, MacroEntry.ExtStr);
          } else
            warn("unknown macro type. skip.");
        } break;
        // debug_macro and debug_macinfo share some common encodings.
        // DW_MACRO_define     == DW_MACINFO_define
        // DW_MACRO_undef      == DW_MACINFO_undef
        // DW_MACRO_start_file == DW_MACINFO_start_file
        // DW_MACRO_end_file   == DW_MACINFO_end_file
        // For readibility/uniformity we are using DW_MACRO_*.
        case dwarf::DW_MACRO_define:
        case dwarf::DW_MACRO_undef: {
          // Write macinfo type.
          OutSection.emitIntVal(MacroType, 1);

          // Write source line.
          encodeULEB128(MacroEntry.Line, OutSection.OS);

          // Write macro string.
          OutSection.emitString(dwarf::DW_FORM_string, MacroEntry.MacroStr);
        } break;
        case dwarf::DW_MACRO_define_strp:
        case dwarf::DW_MACRO_undef_strp:
        case dwarf::DW_MACRO_define_strx:
        case dwarf::DW_MACRO_undef_strx: {
          // DW_MACRO_*_strx forms are not supported currently.
          // Convert to *_strp.
          switch (MacroType) {
          case dwarf::DW_MACRO_define_strx: {
            MacroType = dwarf::DW_MACRO_define_strp;
            if (!DefAttributeIsReported) {
              warn("DW_MACRO_define_strx unsupported yet. Convert to "
                   "DW_MACRO_define_strp.");
              DefAttributeIsReported = true;
            }
          } break;
          case dwarf::DW_MACRO_undef_strx: {
            MacroType = dwarf::DW_MACRO_undef_strp;
            if (!UndefAttributeIsReported) {
              warn("DW_MACRO_undef_strx unsupported yet. Convert to "
                   "DW_MACRO_undef_strp.");
              UndefAttributeIsReported = true;
            }
          } break;
          default:
            // Nothing to do.
            break;
          }

          // Write macinfo type.
          OutSection.emitIntVal(MacroType, 1);

          // Write source line.
          encodeULEB128(MacroEntry.Line, OutSection.OS);

          // Write macro string.
          OutSection.emitString(dwarf::DW_FORM_strp, MacroEntry.MacroStr);
          break;
        }
        case dwarf::DW_MACRO_start_file: {
          // Write macinfo type.
          OutSection.emitIntVal(MacroType, 1);
          // Write source line.
          encodeULEB128(MacroEntry.Line, OutSection.OS);
          // Write source file id.
          encodeULEB128(MacroEntry.File, OutSection.OS);
        } break;
        case dwarf::DW_MACRO_end_file: {
          // Write macinfo type.
          OutSection.emitIntVal(MacroType, 1);
        } break;
        case dwarf::DW_MACRO_import:
        case dwarf::DW_MACRO_import_sup: {
          if (!ImportAttributeIsReported) {
            warn("DW_MACRO_import and DW_MACRO_import_sup are unsupported "
                 "yet. remove.");
            ImportAttributeIsReported = true;
          }
        } break;
        }
      }

      return;
    }
  }
}

void CompileUnit::cloneDieAttrExpression(
    const DWARFExpression &InputExpression,
    SmallVectorImpl<uint8_t> &OutputExpression, SectionDescriptor &Section,
    std::optional<int64_t> VarAddressAdjustment,
    OffsetsPtrVector &PatchesOffsets) {
  using Encoding = DWARFExpression::Operation::Encoding;

  DWARFUnit &OrigUnit = getOrigUnit();
  uint8_t OrigAddressByteSize = OrigUnit.getAddressByteSize();

  uint64_t OpOffset = 0;
  for (auto &Op : InputExpression) {
    auto Desc = Op.getDescription();
    // DW_OP_const_type is variable-length and has 3
    // operands. Thus far we only support 2.
    if ((Desc.Op.size() == 2 && Desc.Op[0] == Encoding::BaseTypeRef) ||
        (Desc.Op.size() == 2 && Desc.Op[1] == Encoding::BaseTypeRef &&
         Desc.Op[0] != Encoding::Size1))
      warn("unsupported DW_OP encoding.");

    if ((Desc.Op.size() == 1 && Desc.Op[0] == Encoding::BaseTypeRef) ||
        (Desc.Op.size() == 2 && Desc.Op[1] == Encoding::BaseTypeRef &&
         Desc.Op[0] == Encoding::Size1)) {
      // This code assumes that the other non-typeref operand fits into 1 byte.
      assert(OpOffset < Op.getEndOffset());
      uint32_t ULEBsize = Op.getEndOffset() - OpOffset - 1;
      assert(ULEBsize <= 16);

      // Copy over the operation.
      assert(!Op.getSubCode() && "SubOps not yet supported");
      OutputExpression.push_back(Op.getCode());
      uint64_t RefOffset;
      if (Desc.Op.size() == 1) {
        RefOffset = Op.getRawOperand(0);
      } else {
        OutputExpression.push_back(Op.getRawOperand(0));
        RefOffset = Op.getRawOperand(1);
      }
      uint8_t ULEB[16];
      uint32_t Offset = 0;
      unsigned RealSize = 0;
      // Look up the base type. For DW_OP_convert, the operand may be 0 to
      // instead indicate the generic type. The same holds for
      // DW_OP_reinterpret, which is currently not supported.
      if (RefOffset > 0 || Op.getCode() != dwarf::DW_OP_convert) {
        RefOffset += OrigUnit.getOffset();
        uint32_t RefDieIdx = 0;
        if (std::optional<uint32_t> Idx =
                OrigUnit.getDIEIndexForOffset(RefOffset))
          RefDieIdx = *Idx;

        // Use fixed size for ULEB128 data, since we need to update that size
        // later with the proper offsets. Use 5 for DWARF32, 9 for DWARF64.
        ULEBsize = getFormParams().getDwarfOffsetByteSize() + 1;

        RealSize = encodeULEB128(0xBADDEF, ULEB, ULEBsize);

        Section.notePatchWithOffsetUpdate(
            DebugULEB128DieRefPatch(OutputExpression.size(), this, this,
                                    RefDieIdx),
            PatchesOffsets);
      } else
        RealSize = encodeULEB128(Offset, ULEB, ULEBsize);

      if (RealSize > ULEBsize) {
        // Emit the generic type as a fallback.
        RealSize = encodeULEB128(0, ULEB, ULEBsize);
        warn("base type ref doesn't fit.");
      }
      assert(RealSize == ULEBsize && "padding failed");
      ArrayRef<uint8_t> ULEBbytes(ULEB, ULEBsize);
      OutputExpression.append(ULEBbytes.begin(), ULEBbytes.end());
    } else if (!getGlobalData().getOptions().UpdateIndexTablesOnly &&
               Op.getCode() == dwarf::DW_OP_addrx) {
      if (std::optional<object::SectionedAddress> SA =
              OrigUnit.getAddrOffsetSectionItem(Op.getRawOperand(0))) {
        // DWARFLinker does not use addrx forms since it generates relocated
        // addresses. Replace DW_OP_addrx with DW_OP_addr here.
        // Argument of DW_OP_addrx should be relocated here as it is not
        // processed by applyValidRelocs.
        OutputExpression.push_back(dwarf::DW_OP_addr);
        uint64_t LinkedAddress =
            SA->Address + (VarAddressAdjustment ? *VarAddressAdjustment : 0);
        if (getEndianness() != llvm::endianness::native)
          sys::swapByteOrder(LinkedAddress);
        ArrayRef<uint8_t> AddressBytes(
            reinterpret_cast<const uint8_t *>(&LinkedAddress),
            OrigAddressByteSize);
        OutputExpression.append(AddressBytes.begin(), AddressBytes.end());
      } else
        warn("cann't read DW_OP_addrx operand.");
    } else if (!getGlobalData().getOptions().UpdateIndexTablesOnly &&
               Op.getCode() == dwarf::DW_OP_constx) {
      if (std::optional<object::SectionedAddress> SA =
              OrigUnit.getAddrOffsetSectionItem(Op.getRawOperand(0))) {
        // DWARFLinker does not use constx forms since it generates relocated
        // addresses. Replace DW_OP_constx with DW_OP_const[*]u here.
        // Argument of DW_OP_constx should be relocated here as it is not
        // processed by applyValidRelocs.
        std::optional<uint8_t> OutOperandKind;
        switch (OrigAddressByteSize) {
        case 2:
          OutOperandKind = dwarf::DW_OP_const2u;
          break;
        case 4:
          OutOperandKind = dwarf::DW_OP_const4u;
          break;
        case 8:
          OutOperandKind = dwarf::DW_OP_const8u;
          break;
        default:
          warn(
              formatv(("unsupported address size: {0}."), OrigAddressByteSize));
          break;
        }

        if (OutOperandKind) {
          OutputExpression.push_back(*OutOperandKind);
          uint64_t LinkedAddress =
              SA->Address + (VarAddressAdjustment ? *VarAddressAdjustment : 0);
          if (getEndianness() != llvm::endianness::native)
            sys::swapByteOrder(LinkedAddress);
          ArrayRef<uint8_t> AddressBytes(
              reinterpret_cast<const uint8_t *>(&LinkedAddress),
              OrigAddressByteSize);
          OutputExpression.append(AddressBytes.begin(), AddressBytes.end());
        }
      } else
        warn("cann't read DW_OP_constx operand.");
    } else {
      // Copy over everything else unmodified.
      StringRef Bytes =
          InputExpression.getData().slice(OpOffset, Op.getEndOffset());
      OutputExpression.append(Bytes.begin(), Bytes.end());
    }
    OpOffset = Op.getEndOffset();
  }
}

Error CompileUnit::cloneAndEmit(std::optional<Triple> TargetTriple,
                                TypeUnit *ArtificialTypeUnit) {
  BumpPtrAllocator Allocator;

  DWARFDie OrigUnitDIE = getOrigUnit().getUnitDIE();
  if (!OrigUnitDIE.isValid())
    return Error::success();

  TypeEntry *RootEntry = nullptr;
  if (ArtificialTypeUnit)
    RootEntry = ArtificialTypeUnit->getTypePool().getRoot();

  // Clone input DIE entry recursively.
  std::pair<DIE *, TypeEntry *> OutCUDie = cloneDIE(
      OrigUnitDIE.getDebugInfoEntry(), RootEntry, getDebugInfoHeaderSize(),
      std::nullopt, std::nullopt, Allocator, ArtificialTypeUnit);
  setOutUnitDIE(OutCUDie.first);

  if (getGlobalData().getOptions().NoOutput || (OutCUDie.first == nullptr))
    return Error::success();

  assert(TargetTriple.has_value());
  if (Error Err = cloneAndEmitLineTable(*TargetTriple))
    return Err;

  if (Error Err = cloneAndEmitDebugMacro())
    return Err;

  getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);
  if (Error Err = emitDebugInfo(*TargetTriple))
    return Err;

  // ASSUMPTION: .debug_info section should already be emitted at this point.
  // cloneAndEmitRanges & cloneAndEmitDebugLocations use .debug_info section
  // data.

  if (Error Err = cloneAndEmitRanges())
    return Err;

  if (Error Err = cloneAndEmitDebugLocations())
    return Err;

  if (Error Err = emitDebugAddrSection())
    return Err;

  // Generate Pub accelerator tables.
  if (llvm::is_contained(GlobalData.getOptions().AccelTables,
                         DWARFLinker::AccelTableKind::Pub))
    emitPubAccelerators();

  if (Error Err = emitDebugStringOffsetSection())
    return Err;

  return emitAbbreviations();
}

std::pair<DIE *, TypeEntry *> CompileUnit::cloneDIE(
    const DWARFDebugInfoEntry *InputDieEntry, TypeEntry *ClonedParentTypeDIE,
    uint64_t OutOffset, std::optional<int64_t> FuncAddressAdjustment,
    std::optional<int64_t> VarAddressAdjustment, BumpPtrAllocator &Allocator,
    TypeUnit *ArtificialTypeUnit) {
  uint32_t InputDieIdx = getDIEIndex(InputDieEntry);
  CompileUnit::DIEInfo &Info = getDIEInfo(InputDieIdx);

  bool NeedToClonePlainDIE = Info.needToKeepInPlainDwarf();
  bool NeedToCloneTypeDIE =
      (InputDieEntry->getTag() != dwarf::DW_TAG_compile_unit) &&
      Info.needToPlaceInTypeTable();
  std::pair<DIE *, TypeEntry *> ClonedDIE;

  DIEGenerator PlainDIEGenerator(Allocator, *this);

  if (NeedToClonePlainDIE)
    // Create a cloned DIE which would be placed into the cloned version
    // of input compile unit.
    ClonedDIE.first = createPlainDIEandCloneAttributes(
        InputDieEntry, PlainDIEGenerator, OutOffset, FuncAddressAdjustment,
        VarAddressAdjustment);
  if (NeedToCloneTypeDIE) {
    // Create a cloned DIE which would be placed into the artificial type
    // unit.
    assert(ArtificialTypeUnit != nullptr);
    DIEGenerator TypeDIEGenerator(
        ArtificialTypeUnit->getTypePool().getThreadLocalAllocator(), *this);

    ClonedDIE.second = createTypeDIEandCloneAttributes(
        InputDieEntry, TypeDIEGenerator, ClonedParentTypeDIE,
        ArtificialTypeUnit);
  }
  TypeEntry *TypeParentForChild =
      ClonedDIE.second ? ClonedDIE.second : ClonedParentTypeDIE;

  bool HasPlainChildrenToClone =
      (ClonedDIE.first && Info.getKeepPlainChildren());

  bool HasTypeChildrenToClone =
      ((ClonedDIE.second ||
        InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit) &&
       Info.getKeepTypeChildren());

  // Recursively clone children.
  if (HasPlainChildrenToClone || HasTypeChildrenToClone) {
    for (const DWARFDebugInfoEntry *CurChild =
             getFirstChildEntry(InputDieEntry);
         CurChild && CurChild->getAbbreviationDeclarationPtr();
         CurChild = getSiblingEntry(CurChild)) {
      std::pair<DIE *, TypeEntry *> ClonedChild = cloneDIE(
          CurChild, TypeParentForChild, OutOffset, FuncAddressAdjustment,
          VarAddressAdjustment, Allocator, ArtificialTypeUnit);

      if (ClonedChild.first) {
        OutOffset =
            ClonedChild.first->getOffset() + ClonedChild.first->getSize();
        PlainDIEGenerator.addChild(ClonedChild.first);
      }
    }
    assert(ClonedDIE.first == nullptr ||
           HasPlainChildrenToClone == ClonedDIE.first->hasChildren());

    // Account for the end of children marker.
    if (HasPlainChildrenToClone)
      OutOffset += sizeof(int8_t);
  }

  // Update our size.
  if (ClonedDIE.first != nullptr)
    ClonedDIE.first->setSize(OutOffset - ClonedDIE.first->getOffset());

  return ClonedDIE;
}

DIE *CompileUnit::createPlainDIEandCloneAttributes(
    const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &PlainDIEGenerator,
    uint64_t &OutOffset, std::optional<int64_t> &FuncAddressAdjustment,
    std::optional<int64_t> &VarAddressAdjustment) {
  uint32_t InputDieIdx = getDIEIndex(InputDieEntry);
  CompileUnit::DIEInfo &Info = getDIEInfo(InputDieIdx);
  DIE *ClonedDIE = nullptr;
  bool HasLocationExpressionAddress = false;
  if (InputDieEntry->getTag() == dwarf::DW_TAG_subprogram) {
    // Get relocation adjustment value for the current function.
    FuncAddressAdjustment =
        getContaingFile().Addresses->getSubprogramRelocAdjustment(
            getDIE(InputDieEntry));
  } else if (InputDieEntry->getTag() == dwarf::DW_TAG_label) {
    // Get relocation adjustment value for the current label.
    std::optional<uint64_t> lowPC =
        dwarf::toAddress(find(InputDieEntry, dwarf::DW_AT_low_pc));
    if (lowPC) {
      LabelMapTy::iterator It = Labels.find(*lowPC);
      if (It != Labels.end())
        FuncAddressAdjustment = It->second;
    }
  } else if (InputDieEntry->getTag() == dwarf::DW_TAG_variable) {
    // Get relocation adjustment value for the current variable.
    std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment =
        getContaingFile().Addresses->getVariableRelocAdjustment(
            getDIE(InputDieEntry));

    HasLocationExpressionAddress = LocExprAddrAndRelocAdjustment.first;
    if (LocExprAddrAndRelocAdjustment.first &&
        LocExprAddrAndRelocAdjustment.second)
      VarAddressAdjustment = *LocExprAddrAndRelocAdjustment.second;
  }

  ClonedDIE = PlainDIEGenerator.createDIE(InputDieEntry->getTag(), OutOffset);

  // Offset to the DIE would be used after output DIE tree is deleted.
  // Thus we need to remember DIE offset separately.
  rememberDieOutOffset(InputDieIdx, OutOffset);

  // Clone Attributes.
  DIEAttributeCloner AttributesCloner(ClonedDIE, *this, this, InputDieEntry,
                                      PlainDIEGenerator, FuncAddressAdjustment,
                                      VarAddressAdjustment,
                                      HasLocationExpressionAddress);
  AttributesCloner.clone();

  // Remember accelerator info.
  AcceleratorRecordsSaver AccelRecordsSaver(getGlobalData(), *this, this);
  AccelRecordsSaver.save(InputDieEntry, ClonedDIE, AttributesCloner.AttrInfo,
                         nullptr);

  OutOffset =
      AttributesCloner.finalizeAbbreviations(Info.getKeepPlainChildren());

  return ClonedDIE;
}

/// Allocates output DIE for the specified \p TypeDescriptor.
DIE *CompileUnit::allocateTypeDie(TypeEntryBody *TypeDescriptor,
                                  DIEGenerator &TypeDIEGenerator,
                                  dwarf::Tag DieTag, bool IsDeclaration,
                                  bool IsParentDeclaration) {
  DIE *DefinitionDie = TypeDescriptor->Die;
  // Do not allocate any new DIE if definition DIE is already met.
  if (DefinitionDie)
    return nullptr;

  DIE *DeclarationDie = TypeDescriptor->DeclarationDie;
  bool OldParentIsDeclaration = TypeDescriptor->ParentIsDeclaration;

  if (IsDeclaration && !DeclarationDie) {
    // Alocate declaration DIE.
    DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
    if (TypeDescriptor->DeclarationDie.compare_exchange_weak(DeclarationDie,
                                                             NewDie))
      return NewDie;
  } else if (IsDeclaration && !IsParentDeclaration && OldParentIsDeclaration) {
    // Overwrite existing declaration DIE if it's parent is also an declaration
    // while parent of current declaration DIE is a definition.
    if (TypeDescriptor->ParentIsDeclaration.compare_exchange_weak(
            OldParentIsDeclaration, false)) {
      DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
      TypeDescriptor->DeclarationDie = NewDie;
      return NewDie;
    }
  } else if (!IsDeclaration && IsParentDeclaration && !DeclarationDie) {
    // Alocate declaration DIE since parent of current DIE is marked as
    // declaration.
    DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
    if (TypeDescriptor->DeclarationDie.compare_exchange_weak(DeclarationDie,
                                                             NewDie))
      return NewDie;
  } else if (!IsDeclaration && !IsParentDeclaration) {
    // Allocate definition DIE.
    DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
    if (TypeDescriptor->Die.compare_exchange_weak(DefinitionDie, NewDie)) {
      TypeDescriptor->ParentIsDeclaration = false;
      return NewDie;
    }
  }

  return nullptr;
}

TypeEntry *CompileUnit::createTypeDIEandCloneAttributes(
    const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &TypeDIEGenerator,
    TypeEntry *ClonedParentTypeDIE, TypeUnit *ArtificialTypeUnit) {
  assert(ArtificialTypeUnit != nullptr);
  uint32_t InputDieIdx = getDIEIndex(InputDieEntry);

  TypeEntry *Entry = getDieTypeEntry(InputDieIdx);
  assert(Entry != nullptr);
  assert(ClonedParentTypeDIE != nullptr);
  TypeEntryBody *EntryBody =
      ArtificialTypeUnit->getTypePool().getOrCreateTypeEntryBody(
          Entry, ClonedParentTypeDIE);
  assert(EntryBody);

  bool IsDeclaration =
      dwarf::toUnsigned(find(InputDieEntry, dwarf::DW_AT_declaration), 0);

  bool ParentIsDeclaration = false;
  if (std::optional<uint32_t> ParentIdx = InputDieEntry->getParentIdx())
    ParentIsDeclaration =
        dwarf::toUnsigned(find(*ParentIdx, dwarf::DW_AT_declaration), 0);

  DIE *OutDIE =
      allocateTypeDie(EntryBody, TypeDIEGenerator, InputDieEntry->getTag(),
                      IsDeclaration, ParentIsDeclaration);

  if (OutDIE != nullptr) {
    assert(ArtificialTypeUnit != nullptr);
    ArtificialTypeUnit->getSectionDescriptor(DebugSectionKind::DebugInfo);

    DIEAttributeCloner AttributesCloner(OutDIE, *this, ArtificialTypeUnit,
                                        InputDieEntry, TypeDIEGenerator,
                                        std::nullopt, std::nullopt, false);
    AttributesCloner.clone();

    // Remember accelerator info.
    AcceleratorRecordsSaver AccelRecordsSaver(getGlobalData(), *this,
                                              ArtificialTypeUnit);
    AccelRecordsSaver.save(InputDieEntry, OutDIE, AttributesCloner.AttrInfo,
                           Entry);

    // if AttributesCloner.getOutOffset() == 0 then we need to add
    // 1 to avoid assertion for zero size. We will subtract it back later.
    OutDIE->setSize(AttributesCloner.getOutOffset() + 1);
  }

  return Entry;
}

Error CompileUnit::cloneAndEmitLineTable(Triple &TargetTriple) {
  const DWARFDebugLine::LineTable *InputLineTable =
      getContaingFile().Dwarf->getLineTableForUnit(&getOrigUnit());
  if (InputLineTable == nullptr) {
    if (getOrigUnit().getUnitDIE().find(dwarf::DW_AT_stmt_list))
      warn("cann't load line table.");
    return Error::success();
  }

  DWARFDebugLine::LineTable OutLineTable;

  // Set Line Table header.
  OutLineTable.Prologue = InputLineTable->Prologue;
  OutLineTable.Prologue.FormParams.AddrSize = getFormParams().AddrSize;

  // Set Line Table Rows.
  if (getGlobalData().getOptions().UpdateIndexTablesOnly) {
    OutLineTable.Rows = InputLineTable->Rows;
    // If all the line table contains is a DW_LNE_end_sequence, clear the line
    // table rows, it will be inserted again in the DWARFStreamer.
    if (OutLineTable.Rows.size() == 1 && OutLineTable.Rows[0].EndSequence)
      OutLineTable.Rows.clear();

    OutLineTable.Sequences = InputLineTable->Sequences;
  } else {
    // This vector is the output line table.
    std::vector<DWARFDebugLine::Row> NewRows;
    NewRows.reserve(InputLineTable->Rows.size());

    // Current sequence of rows being extracted, before being inserted
    // in NewRows.
    std::vector<DWARFDebugLine::Row> Seq;

    const auto &FunctionRanges = getFunctionRanges();
    std::optional<AddressRangeValuePair> CurrRange;

    // FIXME: This logic is meant to generate exactly the same output as
    // Darwin's classic dsymutil. There is a nicer way to implement this
    // by simply putting all the relocated line info in NewRows and simply
    // sorting NewRows before passing it to emitLineTableForUnit. This
    // should be correct as sequences for a function should stay
    // together in the sorted output. There are a few corner cases that
    // look suspicious though, and that required to implement the logic
    // this way. Revisit that once initial validation is finished.

    // Iterate over the object file line info and extract the sequences
    // that correspond to linked functions.
    for (DWARFDebugLine::Row Row : InputLineTable->Rows) {
      // Check whether we stepped out of the range. The range is
      // half-open, but consider accept the end address of the range if
      // it is marked as end_sequence in the input (because in that
      // case, the relocation offset is accurate and that entry won't
      // serve as the start of another function).
      if (!CurrRange || !CurrRange->Range.contains(Row.Address.Address)) {
        // We just stepped out of a known range. Insert a end_sequence
        // corresponding to the end of the range.
        uint64_t StopAddress =
            CurrRange ? CurrRange->Range.end() + CurrRange->Value : -1ULL;
        CurrRange = FunctionRanges.getRangeThatContains(Row.Address.Address);
        if (StopAddress != -1ULL && !Seq.empty()) {
          // Insert end sequence row with the computed end address, but
          // the same line as the previous one.
          auto NextLine = Seq.back();
          NextLine.Address.Address = StopAddress;
          NextLine.EndSequence = 1;
          NextLine.PrologueEnd = 0;
          NextLine.BasicBlock = 0;
          NextLine.EpilogueBegin = 0;
          Seq.push_back(NextLine);
          insertLineSequence(Seq, NewRows);
        }

        if (!CurrRange)
          continue;
      }

      // Ignore empty sequences.
      if (Row.EndSequence && Seq.empty())
        continue;

      // Relocate row address and add it to the current sequence.
      Row.Address.Address += CurrRange->Value;
      Seq.emplace_back(Row);

      if (Row.EndSequence)
        insertLineSequence(Seq, NewRows);
    }

    OutLineTable.Rows = std::move(NewRows);
  }

  return emitDebugLine(TargetTriple, OutLineTable);
}

void CompileUnit::insertLineSequence(std::vector<DWARFDebugLine::Row> &Seq,
                                     std::vector<DWARFDebugLine::Row> &Rows) {
  if (Seq.empty())
    return;

  if (!Rows.empty() && Rows.back().Address < Seq.front().Address) {
    llvm::append_range(Rows, Seq);
    Seq.clear();
    return;
  }

  object::SectionedAddress Front = Seq.front().Address;
  auto InsertPoint = partition_point(
      Rows, [=](const DWARFDebugLine::Row &O) { return O.Address < Front; });

  // FIXME: this only removes the unneeded end_sequence if the
  // sequences have been inserted in order. Using a global sort like
  // described in cloneAndEmitLineTable() and delaying the end_sequene
  // elimination to DebugLineEmitter::emit() we can get rid of all of them.
  if (InsertPoint != Rows.end() && InsertPoint->Address == Front &&
      InsertPoint->EndSequence) {
    *InsertPoint = Seq.front();
    Rows.insert(InsertPoint + 1, Seq.begin() + 1, Seq.end());
  } else {
    Rows.insert(InsertPoint, Seq.begin(), Seq.end());
  }

  Seq.clear();
}

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void CompileUnit::DIEInfo::dump() {
  llvm::errs() << "{";
  llvm::errs() << "  Placement: ";
  switch (getPlacement()) {
  case NotSet:
    llvm::errs() << "NotSet";
    break;
  case TypeTable:
    llvm::errs() << "TypeTable";
    break;
  case PlainDwarf:
    llvm::errs() << "PlainDwarf";
    break;
  case Both:
    llvm::errs() << "Both";
    break;
  }

  llvm::errs() << "  Keep: " << getKeep();
  llvm::errs() << "  KeepPlainChildren: " << getKeepPlainChildren();
  llvm::errs() << "  KeepTypeChildren: " << getKeepTypeChildren();
  llvm::errs() << "  IsInMouduleScope: " << getIsInMouduleScope();
  llvm::errs() << "  IsInFunctionScope: " << getIsInFunctionScope();
  llvm::errs() << "  IsInAnonNamespaceScope: " << getIsInAnonNamespaceScope();
  llvm::errs() << "  ODRAvailable: " << getODRAvailable();
  llvm::errs() << "  TrackLiveness: " << getTrackLiveness();
  llvm::errs() << "}\n";
}
#endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

std::optional<std::pair<StringRef, StringRef>>
CompileUnit::getDirAndFilenameFromLineTable(
    const DWARFFormValue &FileIdxValue) {
  uint64_t FileIdx;
  if (std::optional<uint64_t> Val = FileIdxValue.getAsUnsignedConstant())
    FileIdx = *Val;
  else if (std::optional<int64_t> Val = FileIdxValue.getAsSignedConstant())
    FileIdx = *Val;
  else if (std::optional<uint64_t> Val = FileIdxValue.getAsSectionOffset())
    FileIdx = *Val;
  else
    return std::nullopt;

  return getDirAndFilenameFromLineTable(FileIdx);
}

static bool isPathAbsoluteOnWindowsOrPosix(const Twine &Path) {
  // Debug info can contain paths from any OS, not necessarily
  // an OS we're currently running on. Moreover different compilation units can
  // be compiled on different operating systems and linked together later.
  return sys::path::is_absolute(Path, sys::path::Style::posix) ||
         sys::path::is_absolute(Path, sys::path::Style::windows);
}

std::optional<std::pair<StringRef, StringRef>>
CompileUnit::getDirAndFilenameFromLineTable(uint64_t FileIdx) {
  FileNamesCache::iterator FileData = FileNames.find(FileIdx);
  if (FileData != FileNames.end())
    return std::make_pair(StringRef(FileData->second.first),
                          StringRef(FileData->second.second));

  if (const DWARFDebugLine::LineTable *LineTable =
          getOrigUnit().getContext().getLineTableForUnit(&getOrigUnit())) {
    if (LineTable->hasFileAtIndex(FileIdx)) {

      const llvm::DWARFDebugLine::FileNameEntry &Entry =
          LineTable->Prologue.getFileNameEntry(FileIdx);

      Expected<const char *> Name = Entry.Name.getAsCString();
      if (!Name) {
        warn(Name.takeError());
        return std::nullopt;
      }

      std::string FileName = *Name;
      if (isPathAbsoluteOnWindowsOrPosix(FileName)) {
        FileNamesCache::iterator FileData =
            FileNames
                .insert(std::make_pair(
                    FileIdx,
                    std::make_pair(std::string(""), std::move(FileName))))
                .first;
        return std::make_pair(StringRef(FileData->second.first),
                              StringRef(FileData->second.second));
      }

      SmallString<256> FilePath;
      StringRef IncludeDir;
      // Be defensive about the contents of Entry.
      if (getVersion() >= 5) {
        // DirIdx 0 is the compilation directory, so don't include it for
        // relative names.
        if ((Entry.DirIdx != 0) &&
            Entry.DirIdx < LineTable->Prologue.IncludeDirectories.size()) {
          Expected<const char *> DirName =
              LineTable->Prologue.IncludeDirectories[Entry.DirIdx]
                  .getAsCString();
          if (DirName)
            IncludeDir = *DirName;
          else {
            warn(DirName.takeError());
            return std::nullopt;
          }
        }
      } else {
        if (0 < Entry.DirIdx &&
            Entry.DirIdx <= LineTable->Prologue.IncludeDirectories.size()) {
          Expected<const char *> DirName =
              LineTable->Prologue.IncludeDirectories[Entry.DirIdx - 1]
                  .getAsCString();
          if (DirName)
            IncludeDir = *DirName;
          else {
            warn(DirName.takeError());
            return std::nullopt;
          }
        }
      }

      StringRef CompDir = getOrigUnit().getCompilationDir();

      if (!CompDir.empty() && !isPathAbsoluteOnWindowsOrPosix(IncludeDir)) {
        sys::path::append(FilePath, sys::path::Style::native, CompDir);
      }

      sys::path::append(FilePath, sys::path::Style::native, IncludeDir);

      FileNamesCache::iterator FileData =
          FileNames
              .insert(
                  std::make_pair(FileIdx, std::make_pair(std::string(FilePath),
                                                         std::move(FileName))))
              .first;
      return std::make_pair(StringRef(FileData->second.first),
                            StringRef(FileData->second.second));
    }
  }

  return std::nullopt;
}

#define MAX_REFERENCIES_DEPTH 1000
UnitEntryPairTy UnitEntryPairTy::getNamespaceOrigin() {
  UnitEntryPairTy CUDiePair(*this);
  std::optional<UnitEntryPairTy> RefDiePair;
  int refDepth = 0;
  do {
    RefDiePair = CUDiePair.CU->resolveDIEReference(
        CUDiePair.DieEntry, dwarf::DW_AT_extension,
        ResolveInterCUReferencesMode::Resolve);
    if (!RefDiePair || !RefDiePair->DieEntry)
      return CUDiePair;

    CUDiePair = *RefDiePair;
  } while (refDepth++ < MAX_REFERENCIES_DEPTH);

  return CUDiePair;
}

std::optional<UnitEntryPairTy> UnitEntryPairTy::getParent() {
  if (std::optional<uint32_t> ParentIdx = DieEntry->getParentIdx())
    return UnitEntryPairTy{CU, CU->getDebugInfoEntry(*ParentIdx)};

  return std::nullopt;
}

CompileUnit::OutputUnitVariantPtr::OutputUnitVariantPtr(CompileUnit *U)
    : Ptr(U) {
  assert(U != nullptr);
}

CompileUnit::OutputUnitVariantPtr::OutputUnitVariantPtr(TypeUnit *U) : Ptr(U) {
  assert(U != nullptr);
}

DwarfUnit *CompileUnit::OutputUnitVariantPtr::operator->() {
  if (isCompileUnit())
    return getAsCompileUnit();
  else
    return getAsTypeUnit();
}

bool CompileUnit::OutputUnitVariantPtr::isCompileUnit() {
  return Ptr.is<CompileUnit *>();
}

bool CompileUnit::OutputUnitVariantPtr::isTypeUnit() {
  return Ptr.is<TypeUnit *>();
}

CompileUnit *CompileUnit::OutputUnitVariantPtr::getAsCompileUnit() {
  return Ptr.get<CompileUnit *>();
}

TypeUnit *CompileUnit::OutputUnitVariantPtr::getAsTypeUnit() {
  return Ptr.get<TypeUnit *>();
}

bool CompileUnit::resolveDependenciesAndMarkLiveness(
    bool InterCUProcessingStarted, std::atomic<bool> &HasNewInterconnectedCUs) {
  if (!Dependencies.get())
    Dependencies.reset(new DependencyTracker(*this));

  return Dependencies->resolveDependenciesAndMarkLiveness(
      InterCUProcessingStarted, HasNewInterconnectedCUs);
}

bool CompileUnit::updateDependenciesCompleteness() {
  assert(Dependencies.get());

  return Dependencies.get()->updateDependenciesCompleteness();
}

void CompileUnit::verifyDependencies() {
  assert(Dependencies.get());

  Dependencies.get()->verifyKeepChain();
}

ArrayRef<dwarf::Attribute> llvm::dwarflinker_parallel::getODRAttributes() {
  static dwarf::Attribute ODRAttributes[] = {
      dwarf::DW_AT_type, dwarf::DW_AT_specification,
      dwarf::DW_AT_abstract_origin, dwarf::DW_AT_import};

  return ODRAttributes;
}
