//===- llvm/CodeGen/DwarfCompileUnit.cpp - Dwarf Compile Units ------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file contains support for constructing a dwarf compile unit.
//
//===----------------------------------------------------------------------===//

#include "DwarfCompileUnit.h"
#include "AddressPool.h"
#include "DwarfExpression.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DIE.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCSymbolWasm.h"
#include "llvm/MC/MachineLocation.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/NVPTXAddrSpace.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include <optional>
#include <string>
#include <utility>

using namespace llvm;

/// Query value using AddLinkageNamesToDeclCallOriginsForTuning.
static cl::opt<cl::boolOrDefault> AddLinkageNamesToDeclCallOrigins(
    "add-linkage-names-to-declaration-call-origins", cl::Hidden,
    cl::desc("Add DW_AT_linkage_name to function declaration DIEs "
             "referenced by DW_AT_call_origin attributes. Enabled by default "
             "for -gsce debugger tuning."));

static cl::opt<bool> EmitFuncLineTableOffsetsOption(
    "emit-func-debug-line-table-offsets", cl::Hidden,
    cl::desc("Include line table offset in function's debug info and emit end "
             "sequence after each function's line data."),
    cl::init(false));

static bool AddLinkageNamesToDeclCallOriginsForTuning(const DwarfDebug *DD) {
  bool EnabledByDefault = DD->tuneForSCE();
  if (EnabledByDefault)
    return AddLinkageNamesToDeclCallOrigins != cl::boolOrDefault::BOU_FALSE;
  return AddLinkageNamesToDeclCallOrigins == cl::boolOrDefault::BOU_TRUE;
}

static dwarf::Tag GetCompileUnitType(UnitKind Kind, DwarfDebug *DW) {

  //  According to DWARF Debugging Information Format Version 5,
  //  3.1.2 Skeleton Compilation Unit Entries:
  //  "When generating a split DWARF object file (see Section 7.3.2
  //  on page 187), the compilation unit in the .debug_info section
  //  is a "skeleton" compilation unit with the tag DW_TAG_skeleton_unit"
  if (DW->getDwarfVersion() >= 5 && Kind == UnitKind::Skeleton)
    return dwarf::DW_TAG_skeleton_unit;

  return dwarf::DW_TAG_compile_unit;
}

/// Translate NVVM IR address space code to DWARF correspondent value
static unsigned translateToNVVMDWARFAddrSpace(unsigned AddrSpace) {
  switch (AddrSpace) {
  case NVPTXAS::ADDRESS_SPACE_GENERIC:
    return NVPTXAS::DWARF_ADDR_generic_space;
  case NVPTXAS::ADDRESS_SPACE_GLOBAL:
    return NVPTXAS::DWARF_ADDR_global_space;
  case NVPTXAS::ADDRESS_SPACE_SHARED:
    return NVPTXAS::DWARF_ADDR_shared_space;
  case NVPTXAS::ADDRESS_SPACE_CONST:
    return NVPTXAS::DWARF_ADDR_const_space;
  case NVPTXAS::ADDRESS_SPACE_LOCAL:
    return NVPTXAS::DWARF_ADDR_local_space;
  default:
    llvm_unreachable(
        "Cannot translate unknown address space to DWARF address space");
    return AddrSpace;
  }
}

DwarfCompileUnit::DwarfCompileUnit(unsigned UID, const DICompileUnit *Node,
                                   AsmPrinter *A, DwarfDebug *DW,
                                   DwarfFile *DWU, UnitKind Kind)
    : DwarfUnit(GetCompileUnitType(Kind, DW), Node, A, DW, DWU, UID) {
  insertDIE(Node, &getUnitDie());
  MacroLabelBegin = Asm->createTempSymbol("cu_macro_begin");
}

/// addLabelAddress - Add a dwarf label attribute data and value using
/// DW_FORM_addr or DW_FORM_GNU_addr_index.
void DwarfCompileUnit::addLabelAddress(DIE &Die, dwarf::Attribute Attribute,
                                       const MCSymbol *Label) {
  if ((Skeleton || !DD->useSplitDwarf()) && Label)
    DD->addArangeLabel(SymbolCU(this, Label));

  // Don't use the address pool in non-fission or in the skeleton unit itself.
  if ((!DD->useSplitDwarf() || !Skeleton) && DD->getDwarfVersion() < 5)
    return addLocalLabelAddress(Die, Attribute, Label);

  bool UseAddrOffsetFormOrExpressions =
      DD->useAddrOffsetForm() || DD->useAddrOffsetExpressions();

  const MCSymbol *Base = nullptr;
  if (Label->isInSection() && UseAddrOffsetFormOrExpressions)
    Base = DD->getSectionLabel(&Label->getSection());

  if (!Base || Base == Label) {
    unsigned idx = DD->getAddressPool().getIndex(Label);
    addAttribute(Die, Attribute,
                 DD->getDwarfVersion() >= 5 ? dwarf::DW_FORM_addrx
                                            : dwarf::DW_FORM_GNU_addr_index,
                 DIEInteger(idx));
    return;
  }

  // Could be extended to work with DWARFv4 Split DWARF if that's important for
  // someone. In that case DW_FORM_data would be used.
  assert(DD->getDwarfVersion() >= 5 &&
         "Addr+offset expressions are only valuable when using debug_addr (to "
         "reduce relocations) available in DWARFv5 or higher");
  if (DD->useAddrOffsetExpressions()) {
    auto *Loc = new (DIEValueAllocator) DIEBlock();
    addPoolOpAddress(*Loc, Label);
    addBlock(Die, Attribute, dwarf::DW_FORM_exprloc, Loc);
  } else
    addAttribute(Die, Attribute, dwarf::DW_FORM_LLVM_addrx_offset,
                 new (DIEValueAllocator) DIEAddrOffset(
                     DD->getAddressPool().getIndex(Base), Label, Base));
}

void DwarfCompileUnit::addLocalLabelAddress(DIE &Die,
                                            dwarf::Attribute Attribute,
                                            const MCSymbol *Label) {
  if (Label)
    addAttribute(Die, Attribute, dwarf::DW_FORM_addr, DIELabel(Label));
  else
    addAttribute(Die, Attribute, dwarf::DW_FORM_addr, DIEInteger(0));
}

unsigned DwarfCompileUnit::getOrCreateSourceID(const DIFile *File) {
  // If we print assembly, we can't separate .file entries according to
  // compile units. Thus all files will belong to the default compile unit.

  // FIXME: add a better feature test than hasRawTextSupport. Even better,
  // extend .file to support this.
  unsigned CUID = Asm->OutStreamer->hasRawTextSupport() ? 0 : getUniqueID();
  if (!File)
    return Asm->OutStreamer->emitDwarfFileDirective(0, "", "", std::nullopt,
                                                    std::nullopt, CUID);

  if (LastFile != File) {
    LastFile = File;
    LastFileID = Asm->OutStreamer->emitDwarfFileDirective(
        0, File->getDirectory(), File->getFilename(), DD->getMD5AsBytes(File),
        File->getSource(), CUID);
  }
  return LastFileID;
}

DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
    const DIGlobalVariable *GV, ArrayRef<GlobalExpr> GlobalExprs) {
  // Check for pre-existence.
  if (DIE *Die = getDIE(GV))
    return Die;

  assert(GV);

  auto *GVContext = GV->getScope();
  const DIType *GTy = GV->getType();

  auto *CB = GVContext ? dyn_cast<DICommonBlock>(GVContext) : nullptr;
  DIE *ContextDIE = CB ? getOrCreateCommonBlock(CB, GlobalExprs)
    : getOrCreateContextDIE(GVContext);

  // Add to map.
  DIE *VariableDIE = &createAndAddDIE(GV->getTag(), *ContextDIE, GV);
  DIScope *DeclContext;
  if (auto *SDMDecl = GV->getStaticDataMemberDeclaration()) {
    DeclContext = SDMDecl->getScope();
    assert(SDMDecl->isStaticMember() && "Expected static member decl");
    assert(GV->isDefinition());
    // We need the declaration DIE that is in the static member's class.
    DIE *VariableSpecDIE = getOrCreateStaticMemberDIE(SDMDecl);
    addDIEEntry(*VariableDIE, dwarf::DW_AT_specification, *VariableSpecDIE);
    // If the global variable's type is different from the one in the class
    // member type, assume that it's more specific and also emit it.
    if (GTy != SDMDecl->getBaseType())
      addType(*VariableDIE, GTy);
  } else {
    DeclContext = GV->getScope();
    // Add name and type.
    StringRef DisplayName = GV->getDisplayName();
    if (!DisplayName.empty())
      addString(*VariableDIE, dwarf::DW_AT_name, GV->getDisplayName());
    if (GTy)
      addType(*VariableDIE, GTy);

    // Add scoping info.
    if (!GV->isLocalToUnit())
      addFlag(*VariableDIE, dwarf::DW_AT_external);

    // Add line number info.
    addSourceLine(*VariableDIE, GV);
  }

  if (!GV->isDefinition())
    addFlag(*VariableDIE, dwarf::DW_AT_declaration);
  else
    addGlobalName(GV->getName(), *VariableDIE, DeclContext);

  addAnnotation(*VariableDIE, GV->getAnnotations());

  if (uint32_t AlignInBytes = GV->getAlignInBytes())
    addUInt(*VariableDIE, dwarf::DW_AT_alignment, dwarf::DW_FORM_udata,
            AlignInBytes);

  if (MDTuple *TP = GV->getTemplateParams())
    addTemplateParams(*VariableDIE, DINodeArray(TP));

  // Add location.
  addLocationAttribute(VariableDIE, GV, GlobalExprs);

  return VariableDIE;
}

void DwarfCompileUnit::addLocationAttribute(
    DIE *VariableDIE, const DIGlobalVariable *GV, ArrayRef<GlobalExpr> GlobalExprs) {
  bool addToAccelTable = false;
  DIELoc *Loc = nullptr;
  std::optional<unsigned> NVPTXAddressSpace;
  std::unique_ptr<DIEDwarfExpression> DwarfExpr;
  for (const auto &GE : GlobalExprs) {
    const GlobalVariable *Global = GE.Var;
    const DIExpression *Expr = GE.Expr;

    // For compatibility with DWARF 3 and earlier,
    // DW_AT_location(DW_OP_constu, X, DW_OP_stack_value) or
    // DW_AT_location(DW_OP_consts, X, DW_OP_stack_value) becomes
    // DW_AT_const_value(X).
    if (GlobalExprs.size() == 1 && Expr && Expr->isConstant()) {
      addToAccelTable = true;
      addConstantValue(
          *VariableDIE,
          DIExpression::SignedOrUnsignedConstant::UnsignedConstant ==
              *Expr->isConstant(),
          Expr->getElement(1));
      break;
    }

    // We cannot describe the location of dllimport'd variables: the
    // computation of their address requires loads from the IAT.
    if (Global && Global->hasDLLImportStorageClass())
      continue;

    // Nothing to describe without address or constant.
    if (!Global && (!Expr || !Expr->isConstant()))
      continue;

    if (Global && Global->isThreadLocal() &&
        !Asm->getObjFileLowering().supportDebugThreadLocalLocation())
      continue;

    if (!Loc) {
      addToAccelTable = true;
      Loc = new (DIEValueAllocator) DIELoc;
      DwarfExpr = std::make_unique<DIEDwarfExpression>(*Asm, *this, *Loc);
    }

    if (Expr) {
      // cuda-gdb special requirement. See NVPTXAS::DWARF_AddressSpace
      // Decode DW_OP_constu <DWARF Address Space> DW_OP_swap DW_OP_xderef
      // sequence to specify corresponding address space.
      if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB()) {
        unsigned LocalNVPTXAddressSpace;
        const DIExpression *NewExpr =
            DIExpression::extractAddressClass(Expr, LocalNVPTXAddressSpace);
        if (NewExpr != Expr) {
          Expr = NewExpr;
          NVPTXAddressSpace = LocalNVPTXAddressSpace;
        }
      }
      DwarfExpr->addFragmentOffset(Expr);
    }

    if (Global) {
      const MCSymbol *Sym = Asm->getSymbol(Global);
      // 16-bit platforms like MSP430 and AVR take this path, so sink this
      // assert to platforms that use it.
      auto GetPointerSizedFormAndOp = [this]() {
        unsigned PointerSize = Asm->MAI->getCodePointerSize();
        assert((PointerSize == 4 || PointerSize == 8) &&
               "Add support for other sizes if necessary");
        struct FormAndOp {
          dwarf::Form Form;
          dwarf::LocationAtom Op;
        };
        return PointerSize == 4
                   ? FormAndOp{dwarf::DW_FORM_data4, dwarf::DW_OP_const4u}
                   : FormAndOp{dwarf::DW_FORM_data8, dwarf::DW_OP_const8u};
      };
      if (Global->isThreadLocal()) {
        if (Asm->TM.getTargetTriple().isWasm()) {
          // FIXME This is not guaranteed, but in practice, in static linking,
          // if present, __tls_base's index is 1. This doesn't hold for dynamic
          // linking, so TLS variables used in dynamic linking won't have
          // correct debug info for now. See
          // https://github.com/llvm/llvm-project/blob/19afbfe33156d211fa959dadeea46cd17b9c723c/lld/wasm/Driver.cpp#L786-L823
          addWasmRelocBaseGlobal(Loc, "__tls_base", 1);
          addOpAddress(*Loc, Sym);
          addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus);
        } else if (Asm->TM.useEmulatedTLS()) {
          // TODO: add debug info for emulated thread local mode.
        } else {
          // FIXME: Make this work with -gsplit-dwarf.
          // Based on GCC's support for TLS:
          if (!DD->useSplitDwarf()) {
            auto FormAndOp = GetPointerSizedFormAndOp();
            // 1) Start with a constNu of the appropriate pointer size
            addUInt(*Loc, dwarf::DW_FORM_data1, FormAndOp.Op);
            // 2) containing the (relocated) offset of the TLS variable
            //    within the module's TLS block.
            addExpr(*Loc, FormAndOp.Form,
                    Asm->getObjFileLowering().getDebugThreadLocalSymbol(Sym));
          } else {
            addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_const_index);
            addUInt(*Loc, dwarf::DW_FORM_udata,
                    DD->getAddressPool().getIndex(Sym, /* TLS */ true));
          }
          // 3) followed by an OP to make the debugger do a TLS lookup.
          addUInt(*Loc, dwarf::DW_FORM_data1,
                  DD->useGNUTLSOpcode() ? dwarf::DW_OP_GNU_push_tls_address
                                        : dwarf::DW_OP_form_tls_address);
        }
      } else if (Asm->TM.getTargetTriple().isWasm() &&
                 Asm->TM.getRelocationModel() == Reloc::PIC_) {
        // FIXME This is not guaranteed, but in practice, if present,
        // __memory_base's index is 1. See
        // https://github.com/llvm/llvm-project/blob/19afbfe33156d211fa959dadeea46cd17b9c723c/lld/wasm/Driver.cpp#L786-L823
        addWasmRelocBaseGlobal(Loc, "__memory_base", 1);
        addOpAddress(*Loc, Sym);
        addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus);
      } else if ((Asm->TM.getRelocationModel() == Reloc::RWPI ||
                  Asm->TM.getRelocationModel() == Reloc::ROPI_RWPI) &&
                 !Asm->getObjFileLowering()
                      .getKindForGlobal(Global, Asm->TM)
                      .isReadOnly()) {
        auto FormAndOp = GetPointerSizedFormAndOp();
        // Constant
        addUInt(*Loc, dwarf::DW_FORM_data1, FormAndOp.Op);
        // Relocation offset
        addExpr(*Loc, FormAndOp.Form,
                Asm->getObjFileLowering().getIndirectSymViaRWPI(Sym));
        // Base register
        Register BaseReg = Asm->getObjFileLowering().getStaticBase();
        unsigned DwarfBaseReg =
            Asm->TM.getMCRegisterInfo()->getDwarfRegNum(BaseReg, false);
        addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + DwarfBaseReg);
        // Offset from base register
        addSInt(*Loc, dwarf::DW_FORM_sdata, 0);
        // Operation
        addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus);
      } else {
        DD->addArangeLabel(SymbolCU(this, Sym));
        addOpAddress(*Loc, Sym);
      }
      if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB() &&
          !NVPTXAddressSpace)
        NVPTXAddressSpace =
            translateToNVVMDWARFAddrSpace(Global->getType()->getAddressSpace());
    }
    // Global variables attached to symbols are memory locations.
    // It would be better if this were unconditional, but malformed input that
    // mixes non-fragments and fragments for the same variable is too expensive
    // to detect in the verifier.
    if (DwarfExpr->isUnknownLocation())
      DwarfExpr->setMemoryLocationKind();
    DwarfExpr->addExpression(Expr);
  }
  if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB()) {
    // cuda-gdb special requirement. See NVPTXAS::DWARF_AddressSpace
    addUInt(*VariableDIE, dwarf::DW_AT_address_class, dwarf::DW_FORM_data1,
            NVPTXAddressSpace.value_or(NVPTXAS::DWARF_ADDR_global_space));
  }
  if (Loc)
    addBlock(*VariableDIE, dwarf::DW_AT_location, DwarfExpr->finalize());

  if (DD->useAllLinkageNames())
    addLinkageName(*VariableDIE, GV->getLinkageName());

  if (addToAccelTable) {
    DD->addAccelName(*this, CUNode->getNameTableKind(), GV->getName(),
                     *VariableDIE);

    // If the linkage name is different than the name, go ahead and output
    // that as well into the name table.
    if (GV->getLinkageName() != "" && GV->getName() != GV->getLinkageName() &&
        DD->useAllLinkageNames())
      DD->addAccelName(*this, CUNode->getNameTableKind(), GV->getLinkageName(),
                       *VariableDIE);
  }
}

DIE *DwarfCompileUnit::getOrCreateCommonBlock(
    const DICommonBlock *CB, ArrayRef<GlobalExpr> GlobalExprs) {
  // Check for pre-existence.
  if (DIE *NDie = getDIE(CB))
    return NDie;
  DIE *ContextDIE = getOrCreateContextDIE(CB->getScope());
  DIE &NDie = createAndAddDIE(dwarf::DW_TAG_common_block, *ContextDIE, CB);
  StringRef Name = CB->getName().empty() ? "_BLNK_" : CB->getName();
  addString(NDie, dwarf::DW_AT_name, Name);
  addGlobalName(Name, NDie, CB->getScope());
  if (CB->getFile())
    addSourceLine(NDie, CB->getLineNo(), /*Column*/ 0, CB->getFile());
  if (DIGlobalVariable *V = CB->getDecl())
    getCU().addLocationAttribute(&NDie, V, GlobalExprs);
  return &NDie;
}

void DwarfCompileUnit::addRange(RangeSpan Range) {
  DD->insertSectionLabel(Range.Begin);

  auto *PrevCU = DD->getPrevCU();
  bool SameAsPrevCU = this == PrevCU;
  DD->setPrevCU(this);
  // If we have no current ranges just add the range and return, otherwise,
  // check the current section and CU against the previous section and CU we
  // emitted into and the subprogram was contained within. If these are the
  // same then extend our current range, otherwise add this as a new range.
  if (CURanges.empty() || !SameAsPrevCU ||
      (&CURanges.back().End->getSection() !=
       &Range.End->getSection())) {
    // Before a new range is added, always terminate the prior line table.
    if (PrevCU)
      DD->terminateLineTable(PrevCU);
    CURanges.push_back(Range);
    return;
  }

  CURanges.back().End = Range.End;
}

void DwarfCompileUnit::initStmtList() {
  if (CUNode->isDebugDirectivesOnly())
    return;

  const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
  if (DD->useSectionsAsReferences()) {
    LineTableStartSym = TLOF.getDwarfLineSection()->getBeginSymbol();
  } else {
    LineTableStartSym =
        Asm->OutStreamer->getDwarfLineTableSymbol(getUniqueID());
  }

  // DW_AT_stmt_list is a offset of line number information for this
  // compile unit in debug_line section. For split dwarf this is
  // left in the skeleton CU and so not included.
  // The line table entries are not always emitted in assembly, so it
  // is not okay to use line_table_start here.
      addSectionLabel(getUnitDie(), dwarf::DW_AT_stmt_list, LineTableStartSym,
                      TLOF.getDwarfLineSection()->getBeginSymbol());
}

void DwarfCompileUnit::applyStmtList(DIE &D) {
  const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
  addSectionLabel(D, dwarf::DW_AT_stmt_list, LineTableStartSym,
                  TLOF.getDwarfLineSection()->getBeginSymbol());
}

void DwarfCompileUnit::attachLowHighPC(DIE &D, const MCSymbol *Begin,
                                       const MCSymbol *End) {
  assert(Begin && "Begin label should not be null!");
  assert(End && "End label should not be null!");
  assert(Begin->isDefined() && "Invalid starting label");
  assert(End->isDefined() && "Invalid end label");

  addLabelAddress(D, dwarf::DW_AT_low_pc, Begin);
  if (DD->getDwarfVersion() < 4)
    addLabelAddress(D, dwarf::DW_AT_high_pc, End);
  else
    addLabelDelta(D, dwarf::DW_AT_high_pc, End, Begin);
}

// Add info for Wasm-global-based relocation.
// 'GlobalIndex' is used for split dwarf, which currently relies on a few
// assumptions that are not guaranteed in a formal way but work in practice.
void DwarfCompileUnit::addWasmRelocBaseGlobal(DIELoc *Loc, StringRef GlobalName,
                                              uint64_t GlobalIndex) {
  // FIXME: duplicated from Target/WebAssembly/WebAssembly.h
  // don't want to depend on target specific headers in this code?
  const unsigned TI_GLOBAL_RELOC = 3;
  unsigned PointerSize = Asm->getDataLayout().getPointerSize();
  auto *Sym =
      static_cast<MCSymbolWasm *>(Asm->GetExternalSymbolSymbol(GlobalName));
  // FIXME: this repeats what WebAssemblyMCInstLower::
  // GetExternalSymbolSymbol does, since if there's no code that
  // refers to this symbol, we have to set it here.
  Sym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
  Sym->setGlobalType(wasm::WasmGlobalType{
      static_cast<uint8_t>(PointerSize == 4 ? wasm::WASM_TYPE_I32
                                            : wasm::WASM_TYPE_I64),
      true});
  addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_WASM_location);
  addSInt(*Loc, dwarf::DW_FORM_sdata, TI_GLOBAL_RELOC);
  if (!isDwoUnit()) {
    addLabel(*Loc, dwarf::DW_FORM_data4, Sym);
  } else {
    // FIXME: when writing dwo, we need to avoid relocations. Probably
    // the "right" solution is to treat globals the way func and data
    // symbols are (with entries in .debug_addr).
    // For now we hardcode the indices in the callsites. Global indices are not
    // fixed, but in practice a few are fixed; for example, __stack_pointer is
    // always index 0.
    addUInt(*Loc, dwarf::DW_FORM_data4, GlobalIndex);
  }
}

// Find DIE for the given subprogram and attach appropriate DW_AT_low_pc
// and DW_AT_high_pc attributes. If there are global variables in this
// scope then create and insert DIEs for these variables.
DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP,
                                                MCSymbol *LineTableSym) {
  DIE *SPDie = getOrCreateSubprogramDIE(SP, includeMinimalInlineScopes());
  SmallVector<RangeSpan, 2> BB_List;
  // If basic block sections are on, ranges for each basic block section has
  // to be emitted separately.
  for (const auto &R : Asm->MBBSectionRanges)
    BB_List.push_back({R.second.BeginLabel, R.second.EndLabel});

  attachRangesOrLowHighPC(*SPDie, BB_List);

  if (DD->useAppleExtensionAttributes() &&
      !DD->getCurrentFunction()->getTarget().Options.DisableFramePointerElim(
          *DD->getCurrentFunction()))
    addFlag(*SPDie, dwarf::DW_AT_APPLE_omit_frame_ptr);

  if (emitFuncLineTableOffsets() && LineTableSym) {
    addSectionLabel(
        *SPDie, dwarf::DW_AT_LLVM_stmt_sequence, LineTableSym,
        Asm->getObjFileLowering().getDwarfLineSection()->getBeginSymbol());
  }

  // Only include DW_AT_frame_base in full debug info
  if (!includeMinimalInlineScopes()) {
    const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering();
    TargetFrameLowering::DwarfFrameBase FrameBase =
        TFI->getDwarfFrameBase(*Asm->MF);
    switch (FrameBase.Kind) {
    case TargetFrameLowering::DwarfFrameBase::Register: {
      if (Register::isPhysicalRegister(FrameBase.Location.Reg)) {
        MachineLocation Location(FrameBase.Location.Reg);
        addAddress(*SPDie, dwarf::DW_AT_frame_base, Location);
      }
      break;
    }
    case TargetFrameLowering::DwarfFrameBase::CFA: {
      DIELoc *Loc = new (DIEValueAllocator) DIELoc;
      addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_call_frame_cfa);
      if (FrameBase.Location.Offset != 0) {
        addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_consts);
        addSInt(*Loc, dwarf::DW_FORM_sdata, FrameBase.Location.Offset);
        addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus);
      }
      addBlock(*SPDie, dwarf::DW_AT_frame_base, Loc);
      break;
    }
    case TargetFrameLowering::DwarfFrameBase::WasmFrameBase: {
      // FIXME: duplicated from Target/WebAssembly/WebAssembly.h
      const unsigned TI_GLOBAL_RELOC = 3;
      if (FrameBase.Location.WasmLoc.Kind == TI_GLOBAL_RELOC) {
        // These need to be relocatable.
        DIELoc *Loc = new (DIEValueAllocator) DIELoc;
        assert(FrameBase.Location.WasmLoc.Index == 0); // Only SP so far.
        // For now, since we only ever use index 0, this should work as-is.
        addWasmRelocBaseGlobal(Loc, "__stack_pointer",
                               FrameBase.Location.WasmLoc.Index);
        addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_stack_value);
        addBlock(*SPDie, dwarf::DW_AT_frame_base, Loc);
      } else {
        DIELoc *Loc = new (DIEValueAllocator) DIELoc;
        DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
        DIExpressionCursor Cursor({});
        DwarfExpr.addWasmLocation(FrameBase.Location.WasmLoc.Kind,
            FrameBase.Location.WasmLoc.Index);
        DwarfExpr.addExpression(std::move(Cursor));
        addBlock(*SPDie, dwarf::DW_AT_frame_base, DwarfExpr.finalize());
      }
      break;
    }
    }
  }

  // Add name to the name table, we do this here because we're guaranteed
  // to have concrete versions of our DW_TAG_subprogram nodes.
  DD->addSubprogramNames(*this, CUNode->getNameTableKind(), SP, *SPDie);

  return *SPDie;
}

// Construct a DIE for this scope.
void DwarfCompileUnit::constructScopeDIE(LexicalScope *Scope,
                                         DIE &ParentScopeDIE) {
  if (!Scope || !Scope->getScopeNode())
    return;

  auto *DS = Scope->getScopeNode();

  assert((Scope->getInlinedAt() || !isa<DISubprogram>(DS)) &&
         "Only handle inlined subprograms here, use "
         "constructSubprogramScopeDIE for non-inlined "
         "subprograms");

  // Emit inlined subprograms.
  if (Scope->getParent() && isa<DISubprogram>(DS)) {
    DIE *ScopeDIE = constructInlinedScopeDIE(Scope, ParentScopeDIE);
    assert(ScopeDIE && "Scope DIE should not be null.");
    createAndAddScopeChildren(Scope, *ScopeDIE);
    return;
  }

  // Early exit when we know the scope DIE is going to be null.
  if (DD->isLexicalScopeDIENull(Scope))
    return;

  // Emit lexical blocks.
  DIE *ScopeDIE = constructLexicalScopeDIE(Scope);
  assert(ScopeDIE && "Scope DIE should not be null.");

  ParentScopeDIE.addChild(ScopeDIE);
  createAndAddScopeChildren(Scope, *ScopeDIE);
}

void DwarfCompileUnit::addScopeRangeList(DIE &ScopeDIE,
                                         SmallVector<RangeSpan, 2> Range) {

  HasRangeLists = true;

  // Add the range list to the set of ranges to be emitted.
  auto IndexAndList =
      (DD->getDwarfVersion() < 5 && Skeleton ? Skeleton->DU : DU)
          ->addRange(*(Skeleton ? Skeleton : this), std::move(Range));

  uint32_t Index = IndexAndList.first;
  auto &List = *IndexAndList.second;

  // Under fission, ranges are specified by constant offsets relative to the
  // CU's DW_AT_GNU_ranges_base.
  // FIXME: For DWARF v5, do not generate the DW_AT_ranges attribute under
  // fission until we support the forms using the .debug_addr section
  // (DW_RLE_startx_endx etc.).
  if (DD->getDwarfVersion() >= 5)
    addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_rnglistx, Index);
  else {
    const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
    const MCSymbol *RangeSectionSym =
        TLOF.getDwarfRangesSection()->getBeginSymbol();
    if (isDwoUnit())
      addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, List.Label,
                      RangeSectionSym);
    else
      addSectionLabel(ScopeDIE, dwarf::DW_AT_ranges, List.Label,
                      RangeSectionSym);
  }
}

void DwarfCompileUnit::attachRangesOrLowHighPC(
    DIE &Die, SmallVector<RangeSpan, 2> Ranges) {
  assert(!Ranges.empty());
  if (!DD->useRangesSection() ||
      (Ranges.size() == 1 &&
       (!DD->alwaysUseRanges(*this) ||
        DD->getSectionLabel(&Ranges.front().Begin->getSection()) ==
            Ranges.front().Begin))) {
    const RangeSpan &Front = Ranges.front();
    const RangeSpan &Back = Ranges.back();
    attachLowHighPC(Die, Front.Begin, Back.End);
  } else
    addScopeRangeList(Die, std::move(Ranges));
}

void DwarfCompileUnit::attachRangesOrLowHighPC(
    DIE &Die, const SmallVectorImpl<InsnRange> &Ranges) {
  SmallVector<RangeSpan, 2> List;
  List.reserve(Ranges.size());
  for (const InsnRange &R : Ranges) {
    auto *BeginLabel = DD->getLabelBeforeInsn(R.first);
    auto *EndLabel = DD->getLabelAfterInsn(R.second);

    const auto *BeginMBB = R.first->getParent();
    const auto *EndMBB = R.second->getParent();

    const auto *MBB = BeginMBB;
    // Basic block sections allows basic block subsets to be placed in unique
    // sections. For each section, the begin and end label must be added to the
    // list. If there is more than one range, debug ranges must be used.
    // Otherwise, low/high PC can be used.
    // FIXME: Debug Info Emission depends on block order and this assumes that
    // the order of blocks will be frozen beyond this point.
    do {
      if (MBB->sameSection(EndMBB) || MBB->isEndSection()) {
        auto MBBSectionRange = Asm->MBBSectionRanges[MBB->getSectionID()];
        List.push_back(
            {MBB->sameSection(BeginMBB) ? BeginLabel
                                        : MBBSectionRange.BeginLabel,
             MBB->sameSection(EndMBB) ? EndLabel : MBBSectionRange.EndLabel});
      }
      if (MBB->sameSection(EndMBB))
        break;
      MBB = MBB->getNextNode();
    } while (true);
  }
  attachRangesOrLowHighPC(Die, std::move(List));
}

DIE *DwarfCompileUnit::constructInlinedScopeDIE(LexicalScope *Scope,
                                                DIE &ParentScopeDIE) {
  assert(Scope->getScopeNode());
  auto *DS = Scope->getScopeNode();
  auto *InlinedSP = getDISubprogram(DS);
  // Find the subprogram's DwarfCompileUnit in the SPMap in case the subprogram
  // was inlined from another compile unit.
  DIE *OriginDIE = getAbstractScopeDIEs()[InlinedSP];
  assert(OriginDIE && "Unable to find original DIE for an inlined subprogram.");

  auto ScopeDIE = DIE::get(DIEValueAllocator, dwarf::DW_TAG_inlined_subroutine);
  ParentScopeDIE.addChild(ScopeDIE);
  addDIEEntry(*ScopeDIE, dwarf::DW_AT_abstract_origin, *OriginDIE);

  attachRangesOrLowHighPC(*ScopeDIE, Scope->getRanges());

  // Add the call site information to the DIE.
  const DILocation *IA = Scope->getInlinedAt();
  addUInt(*ScopeDIE, dwarf::DW_AT_call_file, std::nullopt,
          getOrCreateSourceID(IA->getFile()));
  addUInt(*ScopeDIE, dwarf::DW_AT_call_line, std::nullopt, IA->getLine());
  if (IA->getColumn())
    addUInt(*ScopeDIE, dwarf::DW_AT_call_column, std::nullopt, IA->getColumn());
  if (IA->getDiscriminator() && DD->getDwarfVersion() >= 4)
    addUInt(*ScopeDIE, dwarf::DW_AT_GNU_discriminator, std::nullopt,
            IA->getDiscriminator());

  // Add name to the name table, we do this here because we're guaranteed
  // to have concrete versions of our DW_TAG_inlined_subprogram nodes.
  DD->addSubprogramNames(*this, CUNode->getNameTableKind(), InlinedSP,
                         *ScopeDIE);

  return ScopeDIE;
}

// Construct new DW_TAG_lexical_block for this scope and attach
// DW_AT_low_pc/DW_AT_high_pc labels.
DIE *DwarfCompileUnit::constructLexicalScopeDIE(LexicalScope *Scope) {
  if (DD->isLexicalScopeDIENull(Scope))
    return nullptr;
  const auto *DS = Scope->getScopeNode();

  auto ScopeDIE = DIE::get(DIEValueAllocator, dwarf::DW_TAG_lexical_block);
  if (Scope->isAbstractScope()) {
    assert(!getAbstractScopeDIEs().count(DS) &&
           "Abstract DIE for this scope exists!");
    getAbstractScopeDIEs()[DS] = ScopeDIE;
    return ScopeDIE;
  }
  if (!Scope->getInlinedAt()) {
    assert(!LexicalBlockDIEs.count(DS) &&
           "Concrete out-of-line DIE for this scope exists!");
    LexicalBlockDIEs[DS] = ScopeDIE;
  } else {
    InlinedLocalScopeDIEs[DS].push_back(ScopeDIE);
  }

  attachRangesOrLowHighPC(*ScopeDIE, Scope->getRanges());

  return ScopeDIE;
}

DIE *DwarfCompileUnit::constructVariableDIE(DbgVariable &DV, bool Abstract) {
  auto *VariableDie = DIE::get(DIEValueAllocator, DV.getTag());
  insertDIE(DV.getVariable(), VariableDie);
  DV.setDIE(*VariableDie);
  // Abstract variables don't get common attributes later, so apply them now.
  if (Abstract) {
    applyCommonDbgVariableAttributes(DV, *VariableDie);
  } else {
    std::visit(
        [&](const auto &V) {
          applyConcreteDbgVariableAttributes(V, DV, *VariableDie);
        },
        DV.asVariant());
  }
  return VariableDie;
}

void DwarfCompileUnit::applyConcreteDbgVariableAttributes(
    const Loc::Single &Single, const DbgVariable &DV, DIE &VariableDie) {
  const DbgValueLoc *DVal = &Single.getValueLoc();
  if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB() &&
      !Single.getExpr()) {
    // cuda-gdb special requirement. See NVPTXAS::DWARF_AddressSpace
    // Lack of expression means it is a register.
    addUInt(VariableDie, dwarf::DW_AT_address_class, dwarf::DW_FORM_data1,
            NVPTXAS::DWARF_ADDR_reg_space);
  }
  if (!DVal->isVariadic()) {
    const DbgValueLocEntry *Entry = DVal->getLocEntries().begin();
    if (Entry->isLocation()) {
      addVariableAddress(DV, VariableDie, Entry->getLoc());
    } else if (Entry->isInt()) {
      auto *Expr = Single.getExpr();
      if (Expr && Expr->getNumElements()) {
        DIELoc *Loc = new (DIEValueAllocator) DIELoc;
        DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
        // If there is an expression, emit raw unsigned bytes.
        DwarfExpr.addFragmentOffset(Expr);
        DwarfExpr.addUnsignedConstant(Entry->getInt());
        DwarfExpr.addExpression(Expr);
        addBlock(VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize());
        if (DwarfExpr.TagOffset)
          addUInt(VariableDie, dwarf::DW_AT_LLVM_tag_offset,
                  dwarf::DW_FORM_data1, *DwarfExpr.TagOffset);
      } else
        addConstantValue(VariableDie, Entry->getInt(), DV.getType());
    } else if (Entry->isConstantFP()) {
      addConstantFPValue(VariableDie, Entry->getConstantFP());
    } else if (Entry->isConstantInt()) {
      addConstantValue(VariableDie, Entry->getConstantInt(), DV.getType());
    } else if (Entry->isTargetIndexLocation()) {
      DIELoc *Loc = new (DIEValueAllocator) DIELoc;
      DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
      const DIBasicType *BT = dyn_cast<DIBasicType>(
          static_cast<const Metadata *>(DV.getVariable()->getType()));
      DwarfDebug::emitDebugLocValue(*Asm, BT, *DVal, DwarfExpr);
      addBlock(VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize());
    }
    return;
  }
  // If any of the location entries are registers with the value 0,
  // then the location is undefined.
  if (any_of(DVal->getLocEntries(), [](const DbgValueLocEntry &Entry) {
        return Entry.isLocation() && !Entry.getLoc().getReg();
      }))
    return;
  const DIExpression *Expr = Single.getExpr();
  assert(Expr && "Variadic Debug Value must have an Expression.");
  DIELoc *Loc = new (DIEValueAllocator) DIELoc;
  DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
  DwarfExpr.addFragmentOffset(Expr);
  DIExpressionCursor Cursor(Expr);
  const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo();

  auto AddEntry = [&](const DbgValueLocEntry &Entry,
                      DIExpressionCursor &Cursor) {
    if (Entry.isLocation()) {
      if (!DwarfExpr.addMachineRegExpression(TRI, Cursor,
                                             Entry.getLoc().getReg()))
        return false;
    } else if (Entry.isInt()) {
      // If there is an expression, emit raw unsigned bytes.
      DwarfExpr.addUnsignedConstant(Entry.getInt());
    } else if (Entry.isConstantFP()) {
      // DwarfExpression does not support arguments wider than 64 bits
      // (see PR52584).
      // TODO: Consider chunking expressions containing overly wide
      // arguments into separate pointer-sized fragment expressions.
      APInt RawBytes = Entry.getConstantFP()->getValueAPF().bitcastToAPInt();
      if (RawBytes.getBitWidth() > 64)
        return false;
      DwarfExpr.addUnsignedConstant(RawBytes.getZExtValue());
    } else if (Entry.isConstantInt()) {
      APInt RawBytes = Entry.getConstantInt()->getValue();
      if (RawBytes.getBitWidth() > 64)
        return false;
      DwarfExpr.addUnsignedConstant(RawBytes.getZExtValue());
    } else if (Entry.isTargetIndexLocation()) {
      TargetIndexLocation Loc = Entry.getTargetIndexLocation();
      // TODO TargetIndexLocation is a target-independent. Currently
      // only the WebAssembly-specific encoding is supported.
      assert(Asm->TM.getTargetTriple().isWasm());
      DwarfExpr.addWasmLocation(Loc.Index, static_cast<uint64_t>(Loc.Offset));
    } else {
      llvm_unreachable("Unsupported Entry type.");
    }
    return true;
  };

  if (!DwarfExpr.addExpression(
          std::move(Cursor),
          [&](unsigned Idx, DIExpressionCursor &Cursor) -> bool {
            return AddEntry(DVal->getLocEntries()[Idx], Cursor);
          }))
    return;

  // Now attach the location information to the DIE.
  addBlock(VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize());
  if (DwarfExpr.TagOffset)
    addUInt(VariableDie, dwarf::DW_AT_LLVM_tag_offset, dwarf::DW_FORM_data1,
            *DwarfExpr.TagOffset);
}

void DwarfCompileUnit::applyConcreteDbgVariableAttributes(
    const Loc::Multi &Multi, const DbgVariable &DV, DIE &VariableDie) {
  addLocationList(VariableDie, dwarf::DW_AT_location,
                  Multi.getDebugLocListIndex());
  auto TagOffset = Multi.getDebugLocListTagOffset();
  if (TagOffset)
    addUInt(VariableDie, dwarf::DW_AT_LLVM_tag_offset, dwarf::DW_FORM_data1,
            *TagOffset);
}

void DwarfCompileUnit::applyConcreteDbgVariableAttributes(const Loc::MMI &MMI,
                                                          const DbgVariable &DV,
                                                          DIE &VariableDie) {
  std::optional<unsigned> NVPTXAddressSpace;
  DIELoc *Loc = new (DIEValueAllocator) DIELoc;
  DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
  for (const auto &Fragment : MMI.getFrameIndexExprs()) {
    Register FrameReg;
    const DIExpression *Expr = Fragment.Expr;
    const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering();
    StackOffset Offset =
        TFI->getFrameIndexReference(*Asm->MF, Fragment.FI, FrameReg);
    DwarfExpr.addFragmentOffset(Expr);

    auto *TRI = Asm->MF->getSubtarget().getRegisterInfo();
    SmallVector<uint64_t, 8> Ops;
    TRI->getOffsetOpcodes(Offset, Ops);

    // cuda-gdb special requirement. See NVPTXAS::DWARF_AddressSpace.
    // Decode DW_OP_constu <DWARF Address Space> DW_OP_swap
    // DW_OP_xderef sequence to specify address space.
    if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB()) {
      unsigned LocalNVPTXAddressSpace;
      const DIExpression *NewExpr =
          DIExpression::extractAddressClass(Expr, LocalNVPTXAddressSpace);
      if (NewExpr != Expr) {
        Expr = NewExpr;
        NVPTXAddressSpace = LocalNVPTXAddressSpace;
      }
    }
    if (Expr)
      Ops.append(Expr->elements_begin(), Expr->elements_end());
    DIExpressionCursor Cursor(Ops);
    DwarfExpr.setMemoryLocationKind();
    if (const MCSymbol *FrameSymbol = Asm->getFunctionFrameSymbol())
      addOpAddress(*Loc, FrameSymbol);
    else
      DwarfExpr.addMachineRegExpression(
          *Asm->MF->getSubtarget().getRegisterInfo(), Cursor, FrameReg);
    DwarfExpr.addExpression(std::move(Cursor));
  }
  if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB()) {
    // cuda-gdb special requirement. See NVPTXAS::DWARF_AddressSpace.
    addUInt(VariableDie, dwarf::DW_AT_address_class, dwarf::DW_FORM_data1,
            NVPTXAddressSpace.value_or(NVPTXAS::DWARF_ADDR_local_space));
  }
  addBlock(VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize());
  if (DwarfExpr.TagOffset)
    addUInt(VariableDie, dwarf::DW_AT_LLVM_tag_offset, dwarf::DW_FORM_data1,
            *DwarfExpr.TagOffset);
}

void DwarfCompileUnit::applyConcreteDbgVariableAttributes(
    const Loc::EntryValue &EntryValue, const DbgVariable &DV,
    DIE &VariableDie) {
  DIELoc *Loc = new (DIEValueAllocator) DIELoc;
  DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
  // Emit each expression as: EntryValue(Register) <other ops> <Fragment>.
  for (auto [Register, Expr] : EntryValue.EntryValues) {
    DwarfExpr.addFragmentOffset(&Expr);
    DIExpressionCursor Cursor(Expr.getElements());
    DwarfExpr.beginEntryValueExpression(Cursor);
    DwarfExpr.addMachineRegExpression(
        *Asm->MF->getSubtarget().getRegisterInfo(), Cursor, Register);
    DwarfExpr.addExpression(std::move(Cursor));
  }
  addBlock(VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize());
}

void DwarfCompileUnit::applyConcreteDbgVariableAttributes(
    const std::monostate &, const DbgVariable &DV, DIE &VariableDie) {}

DIE *DwarfCompileUnit::constructVariableDIE(DbgVariable &DV,
                                            const LexicalScope &Scope,
                                            DIE *&ObjectPointer) {
  auto Var = constructVariableDIE(DV, Scope.isAbstractScope());
  if (DV.isObjectPointer())
    ObjectPointer = Var;
  return Var;
}

DIE *DwarfCompileUnit::constructLabelDIE(DbgLabel &DL,
                                         const LexicalScope &Scope) {
  auto LabelDie = DIE::get(DIEValueAllocator, DL.getTag());
  insertDIE(DL.getLabel(), LabelDie);
  DL.setDIE(*LabelDie);

  if (Scope.isAbstractScope())
    applyLabelAttributes(DL, *LabelDie);

  return LabelDie;
}

/// Return all DIVariables that appear in count: expressions.
static SmallVector<const DIVariable *, 2> dependencies(DbgVariable *Var) {
  SmallVector<const DIVariable *, 2> Result;
  auto *Array = dyn_cast<DICompositeType>(Var->getType());
  if (!Array || Array->getTag() != dwarf::DW_TAG_array_type)
    return Result;
  if (auto *DLVar = Array->getDataLocation())
    Result.push_back(DLVar);
  if (auto *AsVar = Array->getAssociated())
    Result.push_back(AsVar);
  if (auto *AlVar = Array->getAllocated())
    Result.push_back(AlVar);
  for (auto *El : Array->getElements()) {
    if (auto *Subrange = dyn_cast<DISubrange>(El)) {
      if (auto Count = Subrange->getCount())
        if (auto *Dependency = dyn_cast_if_present<DIVariable *>(Count))
          Result.push_back(Dependency);
      if (auto LB = Subrange->getLowerBound())
        if (auto *Dependency = dyn_cast_if_present<DIVariable *>(LB))
          Result.push_back(Dependency);
      if (auto UB = Subrange->getUpperBound())
        if (auto *Dependency = dyn_cast_if_present<DIVariable *>(UB))
          Result.push_back(Dependency);
      if (auto ST = Subrange->getStride())
        if (auto *Dependency = dyn_cast_if_present<DIVariable *>(ST))
          Result.push_back(Dependency);
    } else if (auto *GenericSubrange = dyn_cast<DIGenericSubrange>(El)) {
      if (auto Count = GenericSubrange->getCount())
        if (auto *Dependency = dyn_cast_if_present<DIVariable *>(Count))
          Result.push_back(Dependency);
      if (auto LB = GenericSubrange->getLowerBound())
        if (auto *Dependency = dyn_cast_if_present<DIVariable *>(LB))
          Result.push_back(Dependency);
      if (auto UB = GenericSubrange->getUpperBound())
        if (auto *Dependency = dyn_cast_if_present<DIVariable *>(UB))
          Result.push_back(Dependency);
      if (auto ST = GenericSubrange->getStride())
        if (auto *Dependency = dyn_cast_if_present<DIVariable *>(ST))
          Result.push_back(Dependency);
    }
  }
  return Result;
}

/// Sort local variables so that variables appearing inside of helper
/// expressions come first.
static SmallVector<DbgVariable *, 8>
sortLocalVars(SmallVectorImpl<DbgVariable *> &Input) {
  SmallVector<DbgVariable *, 8> Result;
  SmallVector<PointerIntPair<DbgVariable *, 1>, 8> WorkList;
  // Map back from a DIVariable to its containing DbgVariable.
  SmallDenseMap<const DILocalVariable *, DbgVariable *> DbgVar;
  // Set of DbgVariables in Result.
  SmallDenseSet<DbgVariable *, 8> Visited;
  // For cycle detection.
  SmallDenseSet<DbgVariable *, 8> Visiting;

  // Initialize the worklist and the DIVariable lookup table.
  for (auto *Var : reverse(Input)) {
    DbgVar.insert({Var->getVariable(), Var});
    WorkList.push_back({Var, 0});
  }

  // Perform a stable topological sort by doing a DFS.
  while (!WorkList.empty()) {
    auto Item = WorkList.back();
    DbgVariable *Var = Item.getPointer();
    bool visitedAllDependencies = Item.getInt();
    WorkList.pop_back();

    assert(Var);

    // Already handled.
    if (Visited.count(Var))
      continue;

    // Add to Result if all dependencies are visited.
    if (visitedAllDependencies) {
      Visited.insert(Var);
      Result.push_back(Var);
      continue;
    }

    // Detect cycles.
    auto Res = Visiting.insert(Var);
    if (!Res.second) {
      assert(false && "dependency cycle in local variables");
      return Result;
    }

    // Push dependencies and this node onto the worklist, so that this node is
    // visited again after all of its dependencies are handled.
    WorkList.push_back({Var, 1});
    for (const auto *Dependency : dependencies(Var)) {
      // Don't add dependency if it is in a different lexical scope or a global.
      if (const auto *Dep = dyn_cast<const DILocalVariable>(Dependency))
        if (DbgVariable *Var = DbgVar.lookup(Dep))
          WorkList.push_back({Var, 0});
    }
  }
  return Result;
}

DIE &DwarfCompileUnit::constructSubprogramScopeDIE(const DISubprogram *Sub,
                                                   LexicalScope *Scope,
                                                   MCSymbol *LineTableSym) {
  DIE &ScopeDIE = updateSubprogramScopeDIE(Sub, LineTableSym);

  if (Scope) {
    assert(!Scope->getInlinedAt());
    assert(!Scope->isAbstractScope());
    // Collect lexical scope children first.
    // ObjectPointer might be a local (non-argument) local variable if it's a
    // block's synthetic this pointer.
    if (DIE *ObjectPointer = createAndAddScopeChildren(Scope, ScopeDIE))
      addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, *ObjectPointer);
  }

  // If this is a variadic function, add an unspecified parameter.
  DITypeRefArray FnArgs = Sub->getType()->getTypeArray();

  // If we have a single element of null, it is a function that returns void.
  // If we have more than one elements and the last one is null, it is a
  // variadic function.
  if (FnArgs.size() > 1 && !FnArgs[FnArgs.size() - 1] &&
      !includeMinimalInlineScopes())
    ScopeDIE.addChild(
        DIE::get(DIEValueAllocator, dwarf::DW_TAG_unspecified_parameters));

  return ScopeDIE;
}

DIE *DwarfCompileUnit::createAndAddScopeChildren(LexicalScope *Scope,
                                                 DIE &ScopeDIE) {
  DIE *ObjectPointer = nullptr;

  // Emit function arguments (order is significant).
  auto Vars = DU->getScopeVariables().lookup(Scope);
  for (auto &DV : Vars.Args)
    ScopeDIE.addChild(constructVariableDIE(*DV.second, *Scope, ObjectPointer));

  // Emit local variables.
  auto Locals = sortLocalVars(Vars.Locals);
  for (DbgVariable *DV : Locals)
    ScopeDIE.addChild(constructVariableDIE(*DV, *Scope, ObjectPointer));

  // Emit labels.
  for (DbgLabel *DL : DU->getScopeLabels().lookup(Scope))
    ScopeDIE.addChild(constructLabelDIE(*DL, *Scope));

  // Track other local entities (skipped in gmlt-like data).
  // This creates mapping between CU and a set of local declarations that
  // should be emitted for subprograms in this CU.
  if (!includeMinimalInlineScopes() && !Scope->getInlinedAt()) {
    auto &LocalDecls = DD->getLocalDeclsForScope(Scope->getScopeNode());
    DeferredLocalDecls.insert_range(LocalDecls);
  }

  // Emit inner lexical scopes.
  auto skipLexicalScope = [this](LexicalScope *S) -> bool {
    if (isa<DISubprogram>(S->getScopeNode()))
      return false;
    auto Vars = DU->getScopeVariables().lookup(S);
    if (!Vars.Args.empty() || !Vars.Locals.empty())
      return false;
    return includeMinimalInlineScopes() ||
           DD->getLocalDeclsForScope(S->getScopeNode()).empty();
  };
  for (LexicalScope *LS : Scope->getChildren()) {
    // If the lexical block doesn't have non-scope children, skip
    // its emission and put its children directly to the parent scope.
    if (skipLexicalScope(LS))
      createAndAddScopeChildren(LS, ScopeDIE);
    else
      constructScopeDIE(LS, ScopeDIE);
  }

  return ObjectPointer;
}

void DwarfCompileUnit::constructAbstractSubprogramScopeDIE(
    LexicalScope *Scope) {
  auto *SP = cast<DISubprogram>(Scope->getScopeNode());
  if (getAbstractScopeDIEs().count(SP))
    return;

  DIE *ContextDIE;
  DwarfCompileUnit *ContextCU = this;

  if (includeMinimalInlineScopes())
    ContextDIE = &getUnitDie();
  // Some of this is duplicated from DwarfUnit::getOrCreateSubprogramDIE, with
  // the important distinction that the debug node is not associated with the
  // DIE (since the debug node will be associated with the concrete DIE, if
  // any). It could be refactored to some common utility function.
  else if (auto *SPDecl = SP->getDeclaration()) {
    ContextDIE = &getUnitDie();
    getOrCreateSubprogramDIE(SPDecl);
  } else {
    ContextDIE = getOrCreateContextDIE(SP->getScope());
    // The scope may be shared with a subprogram that has already been
    // constructed in another CU, in which case we need to construct this
    // subprogram in the same CU.
    ContextCU = DD->lookupCU(ContextDIE->getUnitDie());
  }

  // Passing null as the associated node because the abstract definition
  // shouldn't be found by lookup.
  DIE &AbsDef = ContextCU->createAndAddDIE(dwarf::DW_TAG_subprogram,
                                           *ContextDIE, nullptr);

  // Store the DIE before creating children.
  ContextCU->getAbstractScopeDIEs()[SP] = &AbsDef;

  ContextCU->applySubprogramAttributesToDefinition(SP, AbsDef);
  ContextCU->addSInt(AbsDef, dwarf::DW_AT_inline,
                     DD->getDwarfVersion() <= 4 ? std::optional<dwarf::Form>()
                                                : dwarf::DW_FORM_implicit_const,
                     dwarf::DW_INL_inlined);
  if (DIE *ObjectPointer = ContextCU->createAndAddScopeChildren(Scope, AbsDef))
    ContextCU->addDIEEntry(AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer);
}

bool DwarfCompileUnit::useGNUAnalogForDwarf5Feature() const {
  return DD->getDwarfVersion() <= 4 && !DD->tuneForLLDB();
}

dwarf::Tag DwarfCompileUnit::getDwarf5OrGNUTag(dwarf::Tag Tag) const {
  if (!useGNUAnalogForDwarf5Feature())
    return Tag;
  switch (Tag) {
  case dwarf::DW_TAG_call_site:
    return dwarf::DW_TAG_GNU_call_site;
  case dwarf::DW_TAG_call_site_parameter:
    return dwarf::DW_TAG_GNU_call_site_parameter;
  default:
    llvm_unreachable("DWARF5 tag with no GNU analog");
  }
}

dwarf::Attribute
DwarfCompileUnit::getDwarf5OrGNUAttr(dwarf::Attribute Attr) const {
  if (!useGNUAnalogForDwarf5Feature())
    return Attr;
  switch (Attr) {
  case dwarf::DW_AT_call_all_calls:
    return dwarf::DW_AT_GNU_all_call_sites;
  case dwarf::DW_AT_call_target:
    return dwarf::DW_AT_GNU_call_site_target;
  case dwarf::DW_AT_call_origin:
    return dwarf::DW_AT_abstract_origin;
  case dwarf::DW_AT_call_return_pc:
    return dwarf::DW_AT_low_pc;
  case dwarf::DW_AT_call_value:
    return dwarf::DW_AT_GNU_call_site_value;
  case dwarf::DW_AT_call_tail_call:
    return dwarf::DW_AT_GNU_tail_call;
  default:
    llvm_unreachable("DWARF5 attribute with no GNU analog");
  }
}

dwarf::LocationAtom
DwarfCompileUnit::getDwarf5OrGNULocationAtom(dwarf::LocationAtom Loc) const {
  if (!useGNUAnalogForDwarf5Feature())
    return Loc;
  switch (Loc) {
  case dwarf::DW_OP_entry_value:
    return dwarf::DW_OP_GNU_entry_value;
  default:
    llvm_unreachable("DWARF5 location atom with no GNU analog");
  }
}

DIE &DwarfCompileUnit::constructCallSiteEntryDIE(DIE &ScopeDIE,
                                                 const DISubprogram *CalleeSP,
                                                 bool IsTail,
                                                 const MCSymbol *PCAddr,
                                                 const MCSymbol *CallAddr,
                                                 unsigned CallReg) {
  // Insert a call site entry DIE within ScopeDIE.
  DIE &CallSiteDIE = createAndAddDIE(getDwarf5OrGNUTag(dwarf::DW_TAG_call_site),
                                     ScopeDIE, nullptr);

  if (CallReg) {
    // Indirect call.
    addAddress(CallSiteDIE, getDwarf5OrGNUAttr(dwarf::DW_AT_call_target),
               MachineLocation(CallReg));
  } else {
    DIE *CalleeDIE = getOrCreateSubprogramDIE(CalleeSP);
    assert(CalleeDIE && "Could not create DIE for call site entry origin");
    if (AddLinkageNamesToDeclCallOriginsForTuning(DD) &&
        !CalleeSP->isDefinition() &&
        !CalleeDIE->findAttribute(dwarf::DW_AT_linkage_name)) {
      addLinkageName(*CalleeDIE, CalleeSP->getLinkageName());
    }

    addDIEEntry(CallSiteDIE, getDwarf5OrGNUAttr(dwarf::DW_AT_call_origin),
                *CalleeDIE);
  }

  if (IsTail) {
    // Attach DW_AT_call_tail_call to tail calls for standards compliance.
    addFlag(CallSiteDIE, getDwarf5OrGNUAttr(dwarf::DW_AT_call_tail_call));

    // Attach the address of the branch instruction to allow the debugger to
    // show where the tail call occurred. This attribute has no GNU analog.
    //
    // GDB works backwards from non-standard usage of DW_AT_low_pc (in DWARF4
    // mode -- equivalently, in DWARF5 mode, DW_AT_call_return_pc) at tail-call
    // site entries to figure out the PC of tail-calling branch instructions.
    // This means it doesn't need the compiler to emit DW_AT_call_pc, so we
    // don't emit it here.
    //
    // There's no need to tie non-GDB debuggers to this non-standardness, as it
    // adds unnecessary complexity to the debugger. For non-GDB debuggers, emit
    // the standard DW_AT_call_pc info.
    if (!useGNUAnalogForDwarf5Feature())
      addLabelAddress(CallSiteDIE, dwarf::DW_AT_call_pc, CallAddr);
  }

  // Attach the return PC to allow the debugger to disambiguate call paths
  // from one function to another.
  //
  // The return PC is only really needed when the call /isn't/ a tail call, but
  // GDB expects it in DWARF4 mode, even for tail calls (see the comment above
  // the DW_AT_call_pc emission logic for an explanation).
  if (!IsTail || useGNUAnalogForDwarf5Feature()) {
    assert(PCAddr && "Missing return PC information for a call");
    addLabelAddress(CallSiteDIE,
                    getDwarf5OrGNUAttr(dwarf::DW_AT_call_return_pc), PCAddr);
  }

  return CallSiteDIE;
}

void DwarfCompileUnit::constructCallSiteParmEntryDIEs(
    DIE &CallSiteDIE, SmallVector<DbgCallSiteParam, 4> &Params) {
  for (const auto &Param : Params) {
    unsigned Register = Param.getRegister();
    auto CallSiteDieParam =
        DIE::get(DIEValueAllocator,
                 getDwarf5OrGNUTag(dwarf::DW_TAG_call_site_parameter));
    insertDIE(CallSiteDieParam);
    addAddress(*CallSiteDieParam, dwarf::DW_AT_location,
               MachineLocation(Register));

    DIELoc *Loc = new (DIEValueAllocator) DIELoc;
    DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
    DwarfExpr.setCallSiteParamValueFlag();

    DwarfDebug::emitDebugLocValue(*Asm, nullptr, Param.getValue(), DwarfExpr);

    addBlock(*CallSiteDieParam, getDwarf5OrGNUAttr(dwarf::DW_AT_call_value),
             DwarfExpr.finalize());

    CallSiteDIE.addChild(CallSiteDieParam);
  }
}

DIE *DwarfCompileUnit::constructImportedEntityDIE(
    const DIImportedEntity *Module) {
  DIE *IMDie = DIE::get(DIEValueAllocator, Module->getTag());
  insertDIE(Module, IMDie);
  DIE *EntityDie;
  auto *Entity = Module->getEntity();
  if (auto *NS = dyn_cast<DINamespace>(Entity))
    EntityDie = getOrCreateNameSpace(NS);
  else if (auto *M = dyn_cast<DIModule>(Entity))
    EntityDie = getOrCreateModule(M);
  else if (auto *SP = dyn_cast<DISubprogram>(Entity)) {
    // If there is an abstract subprogram, refer to it. Note that this assumes
    // that all the abstract subprograms have been already created (which is
    // correct until imported entities get emitted in DwarfDebug::endModule()).
    if (auto *AbsSPDie = getAbstractScopeDIEs().lookup(SP))
      EntityDie = AbsSPDie;
    else
      EntityDie = getOrCreateSubprogramDIE(SP);
  } else if (auto *T = dyn_cast<DIType>(Entity))
    EntityDie = getOrCreateTypeDIE(T);
  else if (auto *GV = dyn_cast<DIGlobalVariable>(Entity))
    EntityDie = getOrCreateGlobalVariableDIE(GV, {});
  else if (auto *IE = dyn_cast<DIImportedEntity>(Entity))
    EntityDie = getOrCreateImportedEntityDIE(IE);
  else
    EntityDie = getDIE(Entity);
  assert(EntityDie);
  addSourceLine(*IMDie, Module->getLine(), /*Column*/ 0, Module->getFile());
  addDIEEntry(*IMDie, dwarf::DW_AT_import, *EntityDie);
  StringRef Name = Module->getName();
  if (!Name.empty()) {
    addString(*IMDie, dwarf::DW_AT_name, Name);

    // FIXME: if consumers ever start caring about handling
    // unnamed import declarations such as `using ::nullptr_t`
    // or `using namespace std::ranges`, we could add the
    // import declaration into the accelerator table with the
    // name being the one of the entity being imported.
    DD->addAccelNamespace(*this, CUNode->getNameTableKind(), Name, *IMDie);
  }

  // This is for imported module with renamed entities (such as variables and
  // subprograms).
  DINodeArray Elements = Module->getElements();
  for (const auto *Element : Elements) {
    if (!Element)
      continue;
    IMDie->addChild(
        constructImportedEntityDIE(cast<DIImportedEntity>(Element)));
  }

  return IMDie;
}

DIE *DwarfCompileUnit::getOrCreateImportedEntityDIE(
    const DIImportedEntity *IE) {

  // Check for pre-existence.
  if (DIE *Die = getDIE(IE))
    return Die;

  DIE *ContextDIE = getOrCreateContextDIE(IE->getScope());
  assert(ContextDIE && "Empty scope for the imported entity!");

  DIE *IMDie = constructImportedEntityDIE(IE);
  ContextDIE->addChild(IMDie);
  return IMDie;
}

void DwarfCompileUnit::finishSubprogramDefinition(const DISubprogram *SP) {
  DIE *D = getDIE(SP);
  if (DIE *AbsSPDIE = getAbstractScopeDIEs().lookup(SP)) {
    if (D)
      // If this subprogram has an abstract definition, reference that
      addDIEEntry(*D, dwarf::DW_AT_abstract_origin, *AbsSPDIE);
  } else {
    assert(D || includeMinimalInlineScopes());
    if (D)
      // And attach the attributes
      applySubprogramAttributesToDefinition(SP, *D);
  }
}

void DwarfCompileUnit::finishEntityDefinition(const DbgEntity *Entity) {
  DbgEntity *AbsEntity = getExistingAbstractEntity(Entity->getEntity());

  auto *Die = Entity->getDIE();
  /// Label may be used to generate DW_AT_low_pc, so put it outside
  /// if/else block.
  const DbgLabel *Label = nullptr;
  if (AbsEntity && AbsEntity->getDIE()) {
    addDIEEntry(*Die, dwarf::DW_AT_abstract_origin, *AbsEntity->getDIE());
    Label = dyn_cast<const DbgLabel>(Entity);
  } else {
    if (const DbgVariable *Var = dyn_cast<const DbgVariable>(Entity))
      applyCommonDbgVariableAttributes(*Var, *Die);
    else if ((Label = dyn_cast<const DbgLabel>(Entity)))
      applyLabelAttributes(*Label, *Die);
    else
      llvm_unreachable("DbgEntity must be DbgVariable or DbgLabel.");
  }

  if (!Label)
    return;

  const auto *Sym = Label->getSymbol();
  if (!Sym)
    return;

  addLabelAddress(*Die, dwarf::DW_AT_low_pc, Sym);

  // A TAG_label with a name and an AT_low_pc must be placed in debug_names.
  if (StringRef Name = Label->getName(); !Name.empty())
    getDwarfDebug().addAccelName(*this, CUNode->getNameTableKind(), Name, *Die);
}

void DwarfCompileUnit::attachLexicalScopesAbstractOrigins() {
  auto AttachAO = [&](const DILocalScope *LS, DIE *ScopeDIE) {
    if (auto *AbsLSDie = getAbstractScopeDIEs().lookup(LS))
      addDIEEntry(*ScopeDIE, dwarf::DW_AT_abstract_origin, *AbsLSDie);
  };

  for (auto [LScope, ScopeDIE] : LexicalBlockDIEs)
    AttachAO(LScope, ScopeDIE);
  for (auto &[LScope, ScopeDIEs] : InlinedLocalScopeDIEs)
    for (auto *ScopeDIE : ScopeDIEs)
      AttachAO(LScope, ScopeDIE);
}

DbgEntity *DwarfCompileUnit::getExistingAbstractEntity(const DINode *Node) {
  auto &AbstractEntities = getAbstractEntities();
  auto I = AbstractEntities.find(Node);
  if (I != AbstractEntities.end())
    return I->second.get();
  return nullptr;
}

void DwarfCompileUnit::createAbstractEntity(const DINode *Node,
                                            LexicalScope *Scope) {
  assert(Scope && Scope->isAbstractScope());
  auto &Entity = getAbstractEntities()[Node];
  if (isa<const DILocalVariable>(Node)) {
    Entity = std::make_unique<DbgVariable>(cast<const DILocalVariable>(Node),
                                           nullptr /* IA */);
    DU->addScopeVariable(Scope, cast<DbgVariable>(Entity.get()));
  } else if (isa<const DILabel>(Node)) {
    Entity = std::make_unique<DbgLabel>(
                        cast<const DILabel>(Node), nullptr /* IA */);
    DU->addScopeLabel(Scope, cast<DbgLabel>(Entity.get()));
  }
}

void DwarfCompileUnit::emitHeader(bool UseOffsets) {
  // Don't bother labeling the .dwo unit, as its offset isn't used.
  if (!Skeleton && !DD->useSectionsAsReferences()) {
    LabelBegin = Asm->createTempSymbol("cu_begin");
    Asm->OutStreamer->emitLabel(LabelBegin);
  }

  dwarf::UnitType UT = Skeleton ? dwarf::DW_UT_split_compile
                                : DD->useSplitDwarf() ? dwarf::DW_UT_skeleton
                                                      : dwarf::DW_UT_compile;
  DwarfUnit::emitCommonHeader(UseOffsets, UT);
  if (DD->getDwarfVersion() >= 5 && UT != dwarf::DW_UT_compile)
    Asm->emitInt64(getDWOId());
}

bool DwarfCompileUnit::hasDwarfPubSections() const {
  switch (CUNode->getNameTableKind()) {
  case DICompileUnit::DebugNameTableKind::None:
    return false;
    // Opting in to GNU Pubnames/types overrides the default to ensure these are
    // generated for things like Gold's gdb_index generation.
  case DICompileUnit::DebugNameTableKind::GNU:
    return true;
  case DICompileUnit::DebugNameTableKind::Apple:
    return false;
  case DICompileUnit::DebugNameTableKind::Default:
    return DD->tuneForGDB() && !includeMinimalInlineScopes() &&
           !CUNode->isDebugDirectivesOnly() &&
           DD->getAccelTableKind() != AccelTableKind::Apple &&
           DD->getDwarfVersion() < 5;
  }
  llvm_unreachable("Unhandled DICompileUnit::DebugNameTableKind enum");
}

/// addGlobalName - Add a new global name to the compile unit.
void DwarfCompileUnit::addGlobalName(StringRef Name, const DIE &Die,
                                     const DIScope *Context) {
  if (!hasDwarfPubSections())
    return;
  std::string FullName = getParentContextString(Context) + Name.str();
  GlobalNames[FullName] = &Die;
}

void DwarfCompileUnit::addGlobalNameForTypeUnit(StringRef Name,
                                                const DIScope *Context) {
  if (!hasDwarfPubSections())
    return;
  std::string FullName = getParentContextString(Context) + Name.str();
  // Insert, allowing the entry to remain as-is if it's already present
  // This way the CU-level type DIE is preferred over the "can't describe this
  // type as a unit offset because it's not really in the CU at all, it's only
  // in a type unit"
  GlobalNames.insert(std::make_pair(std::move(FullName), &getUnitDie()));
}

/// Add a new global type to the unit.
void DwarfCompileUnit::addGlobalTypeImpl(const DIType *Ty, const DIE &Die,
                                         const DIScope *Context) {
  if (!hasDwarfPubSections())
    return;
  std::string FullName = getParentContextString(Context) + Ty->getName().str();
  GlobalTypes[FullName] = &Die;
}

void DwarfCompileUnit::addGlobalTypeUnitType(const DIType *Ty,
                                             const DIScope *Context) {
  if (!hasDwarfPubSections())
    return;
  std::string FullName = getParentContextString(Context) + Ty->getName().str();
  // Insert, allowing the entry to remain as-is if it's already present
  // This way the CU-level type DIE is preferred over the "can't describe this
  // type as a unit offset because it's not really in the CU at all, it's only
  // in a type unit"
  GlobalTypes.insert(std::make_pair(std::move(FullName), &getUnitDie()));
}

void DwarfCompileUnit::addVariableAddress(const DbgVariable &DV, DIE &Die,
                                          MachineLocation Location) {
  auto *Single = std::get_if<Loc::Single>(&DV);
  if (Single && Single->getExpr())
    addComplexAddress(Single->getExpr(), Die, dwarf::DW_AT_location, Location);
  else
    addAddress(Die, dwarf::DW_AT_location, Location);
}

/// Add an address attribute to a die based on the location provided.
void DwarfCompileUnit::addAddress(DIE &Die, dwarf::Attribute Attribute,
                                  const MachineLocation &Location) {
  DIELoc *Loc = new (DIEValueAllocator) DIELoc;
  DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
  if (Location.isIndirect())
    DwarfExpr.setMemoryLocationKind();

  DIExpressionCursor Cursor({});
  const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo();
  if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, Location.getReg()))
    return;
  DwarfExpr.addExpression(std::move(Cursor));

  // Now attach the location information to the DIE.
  addBlock(Die, Attribute, DwarfExpr.finalize());

  if (DwarfExpr.TagOffset)
    addUInt(Die, dwarf::DW_AT_LLVM_tag_offset, dwarf::DW_FORM_data1,
            *DwarfExpr.TagOffset);
}

/// Start with the address based on the location provided, and generate the
/// DWARF information necessary to find the actual variable given the extra
/// address information encoded in the DbgVariable, starting from the starting
/// location.  Add the DWARF information to the die.
void DwarfCompileUnit::addComplexAddress(const DIExpression *DIExpr, DIE &Die,
                                         dwarf::Attribute Attribute,
                                         const MachineLocation &Location) {
  DIELoc *Loc = new (DIEValueAllocator) DIELoc;
  DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
  DwarfExpr.addFragmentOffset(DIExpr);
  DwarfExpr.setLocation(Location, DIExpr);

  DIExpressionCursor Cursor(DIExpr);

  if (DIExpr->isEntryValue())
    DwarfExpr.beginEntryValueExpression(Cursor);

  const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo();
  if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, Location.getReg()))
    return;
  DwarfExpr.addExpression(std::move(Cursor));

  // Now attach the location information to the DIE.
  addBlock(Die, Attribute, DwarfExpr.finalize());

  if (DwarfExpr.TagOffset)
    addUInt(Die, dwarf::DW_AT_LLVM_tag_offset, dwarf::DW_FORM_data1,
            *DwarfExpr.TagOffset);
}

/// Add a Dwarf loclistptr attribute data and value.
void DwarfCompileUnit::addLocationList(DIE &Die, dwarf::Attribute Attribute,
                                       unsigned Index) {
  dwarf::Form Form = (DD->getDwarfVersion() >= 5)
                         ? dwarf::DW_FORM_loclistx
                         : DD->getDwarfSectionOffsetForm();
  addAttribute(Die, Attribute, Form, DIELocList(Index));
}

void DwarfCompileUnit::applyCommonDbgVariableAttributes(const DbgVariable &Var,
                                                        DIE &VariableDie) {
  StringRef Name = Var.getName();
  if (!Name.empty())
    addString(VariableDie, dwarf::DW_AT_name, Name);
  const auto *DIVar = Var.getVariable();
  if (DIVar) {
    if (uint32_t AlignInBytes = DIVar->getAlignInBytes())
      addUInt(VariableDie, dwarf::DW_AT_alignment, dwarf::DW_FORM_udata,
              AlignInBytes);
    addAnnotation(VariableDie, DIVar->getAnnotations());
  }

  addSourceLine(VariableDie, DIVar);
  addType(VariableDie, Var.getType());
  if (Var.isArtificial())
    addFlag(VariableDie, dwarf::DW_AT_artificial);
}

void DwarfCompileUnit::applyLabelAttributes(const DbgLabel &Label,
                                            DIE &LabelDie) {
  StringRef Name = Label.getName();
  if (!Name.empty())
    addString(LabelDie, dwarf::DW_AT_name, Name);
  const auto *DILabel = Label.getLabel();
  addSourceLine(LabelDie, DILabel);
  if (DILabel->isArtificial())
    addFlag(LabelDie, dwarf::DW_AT_artificial);
  if (DILabel->getCoroSuspendIdx())
    addUInt(LabelDie, dwarf::DW_AT_LLVM_coro_suspend_idx, std::nullopt,
            *DILabel->getCoroSuspendIdx());
}

/// Add a Dwarf expression attribute data and value.
void DwarfCompileUnit::addExpr(DIELoc &Die, dwarf::Form Form,
                               const MCExpr *Expr) {
  addAttribute(Die, (dwarf::Attribute)0, Form, DIEExpr(Expr));
}

void DwarfCompileUnit::applySubprogramAttributesToDefinition(
    const DISubprogram *SP, DIE &SPDie) {
  auto *SPDecl = SP->getDeclaration();
  auto *Context = SPDecl ? SPDecl->getScope() : SP->getScope();
  applySubprogramAttributes(SP, SPDie, includeMinimalInlineScopes());
  addGlobalName(SP->getName(), SPDie, Context);
}

bool DwarfCompileUnit::isDwoUnit() const {
  return DD->useSplitDwarf() && Skeleton;
}

void DwarfCompileUnit::finishNonUnitTypeDIE(DIE& D, const DICompositeType *CTy) {
  constructTypeDIE(D, CTy);
}

bool DwarfCompileUnit::includeMinimalInlineScopes() const {
  return getCUNode()->getEmissionKind() == DICompileUnit::LineTablesOnly ||
         (DD->useSplitDwarf() && !Skeleton);
}

bool DwarfCompileUnit::emitFuncLineTableOffsets() const {
  return EmitFuncLineTableOffsetsOption;
}

void DwarfCompileUnit::addAddrTableBase() {
  const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
  MCSymbol *Label = DD->getAddressPool().getLabel();
  addSectionLabel(getUnitDie(),
                  DD->getDwarfVersion() >= 5 ? dwarf::DW_AT_addr_base
                                             : dwarf::DW_AT_GNU_addr_base,
                  Label, TLOF.getDwarfAddrSection()->getBeginSymbol());
}

void DwarfCompileUnit::addBaseTypeRef(DIEValueList &Die, int64_t Idx) {
  addAttribute(Die, (dwarf::Attribute)0, dwarf::DW_FORM_udata,
               new (DIEValueAllocator) DIEBaseTypeRef(this, Idx));
}

void DwarfCompileUnit::createBaseTypeDIEs() {
  // Insert the base_type DIEs directly after the CU so that their offsets will
  // fit in the fixed size ULEB128 used inside the location expressions.
  // Maintain order by iterating backwards and inserting to the front of CU
  // child list.
  for (auto &Btr : reverse(ExprRefedBaseTypes)) {
    DIE &Die = getUnitDie().addChildFront(
      DIE::get(DIEValueAllocator, dwarf::DW_TAG_base_type));
    SmallString<32> Str;
    addString(Die, dwarf::DW_AT_name,
              Twine(dwarf::AttributeEncodingString(Btr.Encoding) +
                    "_" + Twine(Btr.BitSize)).toStringRef(Str));
    addUInt(Die, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, Btr.Encoding);
    // Round up to smallest number of bytes that contains this number of bits.
    addUInt(Die, dwarf::DW_AT_byte_size, std::nullopt,
            divideCeil(Btr.BitSize, 8));

    Btr.Die = &Die;
  }
}

DIE *DwarfCompileUnit::getLexicalBlockDIE(const DILexicalBlock *LB) {
  // Assume if there is an abstract tree all the DIEs are already emitted.
  bool isAbstract = getAbstractScopeDIEs().count(LB->getSubprogram());
  if (isAbstract) {
    auto &DIEs = getAbstractScopeDIEs();
    if (auto It = DIEs.find(LB); It != DIEs.end())
      return It->second;
  }
  assert(!isAbstract && "Missed lexical block DIE in abstract tree!");

  // Return a concrete DIE if it exists or nullptr otherwise.
  return LexicalBlockDIEs.lookup(LB);
}

DIE *DwarfCompileUnit::getOrCreateContextDIE(const DIScope *Context) {
  if (isa_and_nonnull<DILocalScope>(Context)) {
    if (auto *LFScope = dyn_cast<DILexicalBlockFile>(Context))
      Context = LFScope->getNonLexicalBlockFileScope();
    if (auto *LScope = dyn_cast<DILexicalBlock>(Context))
      return getLexicalBlockDIE(LScope);

    // Otherwise the context must be a DISubprogram.
    auto *SPScope = cast<DISubprogram>(Context);
    const auto &DIEs = getAbstractScopeDIEs();
    if (auto It = DIEs.find(SPScope); It != DIEs.end())
      return It->second;
  }
  return DwarfUnit::getOrCreateContextDIE(Context);
}
