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

#include "llvm/MC/MCDwarf.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/Config/config.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCObjectStreamer.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstdint>
#include <optional>
#include <string>
#include <utility>
#include <vector>

using namespace llvm;

MCSymbol *mcdwarf::emitListsTableHeaderStart(MCStreamer &S) {
  MCSymbol *Start = S.getContext().createTempSymbol("debug_list_header_start");
  MCSymbol *End = S.getContext().createTempSymbol("debug_list_header_end");
  auto DwarfFormat = S.getContext().getDwarfFormat();
  if (DwarfFormat == dwarf::DWARF64) {
    S.AddComment("DWARF64 mark");
    S.emitInt32(dwarf::DW_LENGTH_DWARF64);
  }
  S.AddComment("Length");
  S.emitAbsoluteSymbolDiff(End, Start,
                           dwarf::getDwarfOffsetByteSize(DwarfFormat));
  S.emitLabel(Start);
  S.AddComment("Version");
  S.emitInt16(S.getContext().getDwarfVersion());
  S.AddComment("Address size");
  S.emitInt8(S.getContext().getAsmInfo()->getCodePointerSize());
  S.AddComment("Segment selector size");
  S.emitInt8(0);
  return End;
}

static inline uint64_t ScaleAddrDelta(MCContext &Context, uint64_t AddrDelta) {
  unsigned MinInsnLength = Context.getAsmInfo()->getMinInstAlignment();
  if (MinInsnLength == 1)
    return AddrDelta;
  if (AddrDelta % MinInsnLength != 0) {
    // TODO: report this error, but really only once.
    ;
  }
  return AddrDelta / MinInsnLength;
}

MCDwarfLineStr::MCDwarfLineStr(MCContext &Ctx) {
  UseRelocs = Ctx.getAsmInfo()->doesDwarfUseRelocationsAcrossSections();
  if (UseRelocs) {
    MCSection *DwarfLineStrSection =
        Ctx.getObjectFileInfo()->getDwarfLineStrSection();
    assert(DwarfLineStrSection && "DwarfLineStrSection must not be NULL");
    LineStrLabel = DwarfLineStrSection->getBeginSymbol();
  }
}

//
// This is called when an instruction is assembled into the specified section
// and if there is information from the last .loc directive that has yet to have
// a line entry made for it is made.
//
void MCDwarfLineEntry::make(MCStreamer *MCOS, MCSection *Section) {
  if (!MCOS->getContext().getDwarfLocSeen())
    return;

  // Create a symbol at in the current section for use in the line entry.
  MCSymbol *LineSym = MCOS->getContext().createTempSymbol();
  // Set the value of the symbol to use for the MCDwarfLineEntry.
  MCOS->emitLabel(LineSym);

  // Get the current .loc info saved in the context.
  const MCDwarfLoc &DwarfLoc = MCOS->getContext().getCurrentDwarfLoc();

  // Create a (local) line entry with the symbol and the current .loc info.
  MCDwarfLineEntry LineEntry(LineSym, DwarfLoc);

  // clear DwarfLocSeen saying the current .loc info is now used.
  MCOS->getContext().clearDwarfLocSeen();

  // Add the line entry to this section's entries.
  MCOS->getContext()
      .getMCDwarfLineTable(MCOS->getContext().getDwarfCompileUnitID())
      .getMCLineSections()
      .addLineEntry(LineEntry, Section);
}

//
// This helper routine returns an expression of End - Start - IntVal .
//
static inline const MCExpr *makeEndMinusStartExpr(MCContext &Ctx,
                                                  const MCSymbol &Start,
                                                  const MCSymbol &End,
                                                  int IntVal) {
  const MCExpr *Res = MCSymbolRefExpr::create(&End, Ctx);
  const MCExpr *RHS = MCSymbolRefExpr::create(&Start, Ctx);
  const MCExpr *Res1 = MCBinaryExpr::create(MCBinaryExpr::Sub, Res, RHS, Ctx);
  const MCExpr *Res2 = MCConstantExpr::create(IntVal, Ctx);
  const MCExpr *Res3 = MCBinaryExpr::create(MCBinaryExpr::Sub, Res1, Res2, Ctx);
  return Res3;
}

//
// This helper routine returns an expression of Start + IntVal .
//
static inline const MCExpr *
makeStartPlusIntExpr(MCContext &Ctx, const MCSymbol &Start, int IntVal) {
  const MCExpr *LHS = MCSymbolRefExpr::create(&Start, Ctx);
  const MCExpr *RHS = MCConstantExpr::create(IntVal, Ctx);
  const MCExpr *Res = MCBinaryExpr::create(MCBinaryExpr::Add, LHS, RHS, Ctx);
  return Res;
}

void MCLineSection::addEndEntry(MCSymbol *EndLabel) {
  auto *Sec = &EndLabel->getSection();
  // The line table may be empty, which we should skip adding an end entry.
  // There are three cases:
  // (1) MCAsmStreamer - emitDwarfLocDirective emits a location directive in
  //     place instead of adding a line entry if the target has
  //     usesDwarfFileAndLocDirectives.
  // (2) MCObjectStreamer - if a function has incomplete debug info where
  //     instructions don't have DILocations, the line entries are missing.
  // (3) It's also possible that there are no prior line entries if the section
  //     itself is empty before this end label.
  auto I = MCLineDivisions.find(Sec);
  if (I == MCLineDivisions.end()) // If section not found, do nothing.
    return;

  auto &Entries = I->second;
  // If no entries in this section's list, nothing to base the end entry on.
  if (Entries.empty())
    return;

  // Create the end entry based on the last existing entry.
  MCDwarfLineEntry EndEntry = Entries.back();

  // An end entry is just for marking the end of a sequence of code locations.
  // It should not carry forward a LineStreamLabel from a previous special entry
  // if Entries.back() happened to be such an entry. So here we clear
  // LineStreamLabel.
  EndEntry.LineStreamLabel = nullptr;
  EndEntry.setEndLabel(EndLabel);
  Entries.push_back(EndEntry);
}

//
// This emits the Dwarf line table for the specified section from the entries
// in the LineSection.
//
void MCDwarfLineTable::emitOne(
    MCStreamer *MCOS, MCSection *Section,
    const MCLineSection::MCDwarfLineEntryCollection &LineEntries) {

  unsigned FileNum, LastLine, Column, Flags, Isa, Discriminator;
  bool IsAtStartSeq;
  MCSymbol *LastLabel;
  auto init = [&]() {
    FileNum = 1;
    LastLine = 1;
    Column = 0;
    Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
    Isa = 0;
    Discriminator = 0;
    LastLabel = nullptr;
    IsAtStartSeq = true;
  };
  init();

  // Loop through each MCDwarfLineEntry and encode the dwarf line number table.
  bool EndEntryEmitted = false;
  for (const MCDwarfLineEntry &LineEntry : LineEntries) {
    MCSymbol *Label = LineEntry.getLabel();
    const MCAsmInfo *asmInfo = MCOS->getContext().getAsmInfo();

    if (LineEntry.LineStreamLabel) {
      if (!IsAtStartSeq) {
        MCOS->emitDwarfLineEndEntry(Section, LastLabel,
                                    /*EndLabel =*/LastLabel);
        init();
      }
      MCOS->emitLabel(LineEntry.LineStreamLabel, LineEntry.StreamLabelDefLoc);
      continue;
    }

    if (LineEntry.IsEndEntry) {
      MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, Label,
                                     asmInfo->getCodePointerSize());
      init();
      EndEntryEmitted = true;
      continue;
    }

    int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine;

    if (FileNum != LineEntry.getFileNum()) {
      FileNum = LineEntry.getFileNum();
      MCOS->emitInt8(dwarf::DW_LNS_set_file);
      MCOS->emitULEB128IntValue(FileNum);
    }
    if (Column != LineEntry.getColumn()) {
      Column = LineEntry.getColumn();
      MCOS->emitInt8(dwarf::DW_LNS_set_column);
      MCOS->emitULEB128IntValue(Column);
    }
    if (Discriminator != LineEntry.getDiscriminator() &&
        MCOS->getContext().getDwarfVersion() >= 4) {
      Discriminator = LineEntry.getDiscriminator();
      unsigned Size = getULEB128Size(Discriminator);
      MCOS->emitInt8(dwarf::DW_LNS_extended_op);
      MCOS->emitULEB128IntValue(Size + 1);
      MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
      MCOS->emitULEB128IntValue(Discriminator);
    }
    if (Isa != LineEntry.getIsa()) {
      Isa = LineEntry.getIsa();
      MCOS->emitInt8(dwarf::DW_LNS_set_isa);
      MCOS->emitULEB128IntValue(Isa);
    }
    if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) {
      Flags = LineEntry.getFlags();
      MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
    }
    if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK)
      MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
    if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END)
      MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
    if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN)
      MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);

    // At this point we want to emit/create the sequence to encode the delta in
    // line numbers and the increment of the address from the previous Label
    // and the current Label.
    MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,
                                   asmInfo->getCodePointerSize());

    Discriminator = 0;
    LastLine = LineEntry.getLine();
    LastLabel = Label;
    IsAtStartSeq = false;
  }

  // Generate DWARF line end entry.
  // We do not need this for DwarfDebug that explicitly terminates the line
  // table using ranges whenever CU or section changes. However, the MC path
  // does not track ranges nor terminate the line table. In that case,
  // conservatively use the section end symbol to end the line table.
  if (!EndEntryEmitted && !IsAtStartSeq)
    MCOS->emitDwarfLineEndEntry(Section, LastLabel);
}

void MCDwarfLineTable::endCurrentSeqAndEmitLineStreamLabel(MCStreamer *MCOS,
                                                           SMLoc DefLoc,
                                                           StringRef Name) {
  auto &ctx = MCOS->getContext();
  auto *LineStreamLabel = ctx.getOrCreateSymbol(Name);
  auto *LineSym = ctx.createTempSymbol();
  MCOS->emitLabel(LineSym);
  const MCDwarfLoc &DwarfLoc = ctx.getCurrentDwarfLoc();

  // Create a 'fake' line entry by having LineStreamLabel be non-null. This
  // won't actually emit any line information, it will reset the line table
  // sequence and emit a label at the start of the new line table sequence.
  MCDwarfLineEntry LineEntry(LineSym, DwarfLoc, LineStreamLabel, DefLoc);
  getMCLineSections().addLineEntry(LineEntry, MCOS->getCurrentSectionOnly());
}

//
// This emits the Dwarf file and the line tables.
//
void MCDwarfLineTable::emit(MCStreamer *MCOS, MCDwarfLineTableParams Params) {
  MCContext &context = MCOS->getContext();

  auto &LineTables = context.getMCDwarfLineTables();

  // Bail out early so we don't switch to the debug_line section needlessly and
  // in doing so create an unnecessary (if empty) section.
  if (LineTables.empty())
    return;

  // In a v5 non-split line table, put the strings in a separate section.
  std::optional<MCDwarfLineStr> LineStr;
  if (context.getDwarfVersion() >= 5)
    LineStr.emplace(context);

  // Switch to the section where the table will be emitted into.
  MCOS->switchSection(context.getObjectFileInfo()->getDwarfLineSection());

  // Handle the rest of the Compile Units.
  for (const auto &CUIDTablePair : LineTables) {
    CUIDTablePair.second.emitCU(MCOS, Params, LineStr);
  }

  if (LineStr)
    LineStr->emitSection(MCOS);
}

void MCDwarfDwoLineTable::Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params,
                               MCSection *Section) const {
  if (!HasSplitLineTable)
    return;
  std::optional<MCDwarfLineStr> NoLineStr(std::nullopt);
  MCOS.switchSection(Section);
  MCOS.emitLabel(Header.Emit(&MCOS, Params, {}, NoLineStr).second);
}

std::pair<MCSymbol *, MCSymbol *>
MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
                             std::optional<MCDwarfLineStr> &LineStr) const {
  static const char StandardOpcodeLengths[] = {
      0, // length of DW_LNS_copy
      1, // length of DW_LNS_advance_pc
      1, // length of DW_LNS_advance_line
      1, // length of DW_LNS_set_file
      1, // length of DW_LNS_set_column
      0, // length of DW_LNS_negate_stmt
      0, // length of DW_LNS_set_basic_block
      0, // length of DW_LNS_const_add_pc
      1, // length of DW_LNS_fixed_advance_pc
      0, // length of DW_LNS_set_prologue_end
      0, // length of DW_LNS_set_epilogue_begin
      1  // DW_LNS_set_isa
  };
  assert(std::size(StandardOpcodeLengths) >=
         (Params.DWARF2LineOpcodeBase - 1U));
  return Emit(MCOS, Params,
              ArrayRef(StandardOpcodeLengths, Params.DWARF2LineOpcodeBase - 1),
              LineStr);
}

static const MCExpr *forceExpAbs(MCStreamer &OS, const MCExpr* Expr) {
  MCContext &Context = OS.getContext();
  assert(!isa<MCSymbolRefExpr>(Expr));
  if (!Context.getAsmInfo()->doesSetDirectiveSuppressReloc())
    return Expr;

  // On Mach-O, try to avoid a relocation by using a set directive.
  MCSymbol *ABS = Context.createTempSymbol();
  OS.emitAssignment(ABS, Expr);
  return MCSymbolRefExpr::create(ABS, Context);
}

static void emitAbsValue(MCStreamer &OS, const MCExpr *Value, unsigned Size) {
  const MCExpr *ABS = forceExpAbs(OS, Value);
  OS.emitValue(ABS, Size);
}

void MCDwarfLineStr::emitSection(MCStreamer *MCOS) {
  // Switch to the .debug_line_str section.
  MCOS->switchSection(
      MCOS->getContext().getObjectFileInfo()->getDwarfLineStrSection());
  SmallString<0> Data = getFinalizedData();
  MCOS->emitBinaryData(Data.str());
}

SmallString<0> MCDwarfLineStr::getFinalizedData() {
  // Emit the strings without perturbing the offsets we used.
  if (!LineStrings.isFinalized())
    LineStrings.finalizeInOrder();
  SmallString<0> Data;
  Data.resize(LineStrings.getSize());
  LineStrings.write((uint8_t *)Data.data());
  return Data;
}

size_t MCDwarfLineStr::addString(StringRef Path) {
  return LineStrings.add(Path);
}

void MCDwarfLineStr::emitRef(MCStreamer *MCOS, StringRef Path) {
  int RefSize =
      dwarf::getDwarfOffsetByteSize(MCOS->getContext().getDwarfFormat());
  size_t Offset = addString(Path);
  if (UseRelocs) {
    MCContext &Ctx = MCOS->getContext();
    if (Ctx.getAsmInfo()->needsDwarfSectionOffsetDirective()) {
      MCOS->emitCOFFSecRel32(LineStrLabel, Offset);
    } else {
      MCOS->emitValue(makeStartPlusIntExpr(Ctx, *LineStrLabel, Offset),
                      RefSize);
    }
  } else
    MCOS->emitIntValue(Offset, RefSize);
}

void MCDwarfLineTableHeader::emitV2FileDirTables(MCStreamer *MCOS) const {
  // First the directory table.
  for (auto &Dir : MCDwarfDirs) {
    MCOS->emitBytes(Dir);                // The DirectoryName, and...
    MCOS->emitBytes(StringRef("\0", 1)); // its null terminator.
  }
  MCOS->emitInt8(0); // Terminate the directory list.

  // Second the file table.
  for (unsigned i = 1; i < MCDwarfFiles.size(); i++) {
    assert(!MCDwarfFiles[i].Name.empty());
    MCOS->emitBytes(MCDwarfFiles[i].Name); // FileName and...
    MCOS->emitBytes(StringRef("\0", 1));   // its null terminator.
    MCOS->emitULEB128IntValue(MCDwarfFiles[i].DirIndex); // Directory number.
    MCOS->emitInt8(0); // Last modification timestamp (always 0).
    MCOS->emitInt8(0); // File size (always 0).
  }
  MCOS->emitInt8(0); // Terminate the file list.
}

static void emitOneV5FileEntry(MCStreamer *MCOS, const MCDwarfFile &DwarfFile,
                               bool EmitMD5, bool HasAnySource,
                               std::optional<MCDwarfLineStr> &LineStr) {
  assert(!DwarfFile.Name.empty());
  if (LineStr)
    LineStr->emitRef(MCOS, DwarfFile.Name);
  else {
    MCOS->emitBytes(DwarfFile.Name);     // FileName and...
    MCOS->emitBytes(StringRef("\0", 1)); // its null terminator.
  }
  MCOS->emitULEB128IntValue(DwarfFile.DirIndex); // Directory number.
  if (EmitMD5) {
    const MD5::MD5Result &Cksum = *DwarfFile.Checksum;
    MCOS->emitBinaryData(
        StringRef(reinterpret_cast<const char *>(Cksum.data()), Cksum.size()));
  }
  if (HasAnySource) {
    // From https://dwarfstd.org/issues/180201.1.html
    // * The value is an empty null-terminated string if no source is available
    StringRef Source = DwarfFile.Source.value_or(StringRef());
    // * If the source is available but is an empty file then the value is a
    // null-terminated single "\n".
    if (DwarfFile.Source && DwarfFile.Source->empty())
      Source = "\n";
    if (LineStr)
      LineStr->emitRef(MCOS, Source);
    else {
      MCOS->emitBytes(Source);             // Source and...
      MCOS->emitBytes(StringRef("\0", 1)); // its null terminator.
    }
  }
}

void MCDwarfLineTableHeader::emitV5FileDirTables(
    MCStreamer *MCOS, std::optional<MCDwarfLineStr> &LineStr) const {
  // The directory format, which is just a list of the directory paths.  In a
  // non-split object, these are references to .debug_line_str; in a split
  // object, they are inline strings.
  MCOS->emitInt8(1);
  MCOS->emitULEB128IntValue(dwarf::DW_LNCT_path);
  MCOS->emitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
                                    : dwarf::DW_FORM_string);
  MCOS->emitULEB128IntValue(MCDwarfDirs.size() + 1);
  // Try not to emit an empty compilation directory.
  SmallString<256> Dir;
  StringRef CompDir = MCOS->getContext().getCompilationDir();
  if (!CompilationDir.empty()) {
    Dir = CompilationDir;
    MCOS->getContext().remapDebugPath(Dir);
    CompDir = Dir.str();
    if (LineStr)
      CompDir = LineStr->getSaver().save(CompDir);
  }
  if (LineStr) {
    // Record path strings, emit references here.
    LineStr->emitRef(MCOS, CompDir);
    for (const auto &Dir : MCDwarfDirs)
      LineStr->emitRef(MCOS, Dir);
  } else {
    // The list of directory paths.  Compilation directory comes first.
    MCOS->emitBytes(CompDir);
    MCOS->emitBytes(StringRef("\0", 1));
    for (const auto &Dir : MCDwarfDirs) {
      MCOS->emitBytes(Dir);                // The DirectoryName, and...
      MCOS->emitBytes(StringRef("\0", 1)); // its null terminator.
    }
  }

  // The file format, which is the inline null-terminated filename and a
  // directory index.  We don't track file size/timestamp so don't emit them
  // in the v5 table.  Emit MD5 checksums and source if we have them.
  uint64_t Entries = 2;
  if (HasAllMD5)
    Entries += 1;
  if (HasAnySource)
    Entries += 1;
  MCOS->emitInt8(Entries);
  MCOS->emitULEB128IntValue(dwarf::DW_LNCT_path);
  MCOS->emitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
                                    : dwarf::DW_FORM_string);
  MCOS->emitULEB128IntValue(dwarf::DW_LNCT_directory_index);
  MCOS->emitULEB128IntValue(dwarf::DW_FORM_udata);
  if (HasAllMD5) {
    MCOS->emitULEB128IntValue(dwarf::DW_LNCT_MD5);
    MCOS->emitULEB128IntValue(dwarf::DW_FORM_data16);
  }
  if (HasAnySource) {
    MCOS->emitULEB128IntValue(dwarf::DW_LNCT_LLVM_source);
    MCOS->emitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
                                      : dwarf::DW_FORM_string);
  }
  // Then the counted list of files. The root file is file #0, then emit the
  // files as provide by .file directives.
  // MCDwarfFiles has an unused element [0] so use size() not size()+1.
  // But sometimes MCDwarfFiles is empty, in which case we still emit one file.
  MCOS->emitULEB128IntValue(MCDwarfFiles.empty() ? 1 : MCDwarfFiles.size());
  // To accommodate assembler source written for DWARF v4 but trying to emit
  // v5: If we didn't see a root file explicitly, replicate file #1.
  assert((!RootFile.Name.empty() || MCDwarfFiles.size() >= 1) &&
         "No root file and no .file directives");
  emitOneV5FileEntry(MCOS, RootFile.Name.empty() ? MCDwarfFiles[1] : RootFile,
                     HasAllMD5, HasAnySource, LineStr);
  for (unsigned i = 1; i < MCDwarfFiles.size(); ++i)
    emitOneV5FileEntry(MCOS, MCDwarfFiles[i], HasAllMD5, HasAnySource, LineStr);
}

std::pair<MCSymbol *, MCSymbol *>
MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
                             ArrayRef<char> StandardOpcodeLengths,
                             std::optional<MCDwarfLineStr> &LineStr) const {
  MCContext &context = MCOS->getContext();

  // Create a symbol at the beginning of the line table.
  MCSymbol *LineStartSym = Label;
  if (!LineStartSym)
    LineStartSym = context.createTempSymbol();

  // Set the value of the symbol, as we are at the start of the line table.
  MCOS->emitDwarfLineStartLabel(LineStartSym);

  unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(context.getDwarfFormat());

  MCSymbol *LineEndSym = MCOS->emitDwarfUnitLength("debug_line", "unit length");

  // Next 2 bytes is the Version.
  unsigned LineTableVersion = context.getDwarfVersion();
  MCOS->emitInt16(LineTableVersion);

  // In v5, we get address info next.
  if (LineTableVersion >= 5) {
    MCOS->emitInt8(context.getAsmInfo()->getCodePointerSize());
    MCOS->emitInt8(0); // Segment selector; same as EmitGenDwarfAranges.
  }

  // Create symbols for the start/end of the prologue.
  MCSymbol *ProStartSym = context.createTempSymbol("prologue_start");
  MCSymbol *ProEndSym = context.createTempSymbol("prologue_end");

  // Length of the prologue, is the next 4 bytes (8 bytes for DWARF64). This is
  // actually the length from after the length word, to the end of the prologue.
  MCOS->emitAbsoluteSymbolDiff(ProEndSym, ProStartSym, OffsetSize);

  MCOS->emitLabel(ProStartSym);

  // Parameters of the state machine, are next.
  MCOS->emitInt8(context.getAsmInfo()->getMinInstAlignment());
  // maximum_operations_per_instruction
  // For non-VLIW architectures this field is always 1.
  // FIXME: VLIW architectures need to update this field accordingly.
  if (LineTableVersion >= 4)
    MCOS->emitInt8(1);
  MCOS->emitInt8(DWARF2_LINE_DEFAULT_IS_STMT);
  MCOS->emitInt8(Params.DWARF2LineBase);
  MCOS->emitInt8(Params.DWARF2LineRange);
  MCOS->emitInt8(StandardOpcodeLengths.size() + 1);

  // Standard opcode lengths
  for (char Length : StandardOpcodeLengths)
    MCOS->emitInt8(Length);

  // Put out the directory and file tables.  The formats vary depending on
  // the version.
  if (LineTableVersion >= 5)
    emitV5FileDirTables(MCOS, LineStr);
  else
    emitV2FileDirTables(MCOS);

  // This is the end of the prologue, so set the value of the symbol at the
  // end of the prologue (that was used in a previous expression).
  MCOS->emitLabel(ProEndSym);

  return std::make_pair(LineStartSym, LineEndSym);
}

void MCDwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params,
                              std::optional<MCDwarfLineStr> &LineStr) const {
  MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second;

  // Put out the line tables.
  for (const auto &LineSec : MCLineSections.getMCLineEntries())
    emitOne(MCOS, LineSec.first, LineSec.second);

  // This is the end of the section, so set the value of the symbol at the end
  // of this section (that was used in a previous expression).
  MCOS->emitLabel(LineEndSym);
}

Expected<unsigned>
MCDwarfLineTable::tryGetFile(StringRef &Directory, StringRef &FileName,
                             std::optional<MD5::MD5Result> Checksum,
                             std::optional<StringRef> Source,
                             uint16_t DwarfVersion, unsigned FileNumber) {
  return Header.tryGetFile(Directory, FileName, Checksum, Source, DwarfVersion,
                           FileNumber);
}

static bool isRootFile(const MCDwarfFile &RootFile, StringRef &Directory,
                       StringRef &FileName,
                       std::optional<MD5::MD5Result> Checksum) {
  if (RootFile.Name.empty() || StringRef(RootFile.Name) != FileName)
    return false;
  return RootFile.Checksum == Checksum;
}

Expected<unsigned>
MCDwarfLineTableHeader::tryGetFile(StringRef &Directory, StringRef &FileName,
                                   std::optional<MD5::MD5Result> Checksum,
                                   std::optional<StringRef> Source,
                                   uint16_t DwarfVersion, unsigned FileNumber) {
  if (Directory == CompilationDir)
    Directory = "";
  if (FileName.empty()) {
    FileName = "<stdin>";
    Directory = "";
  }
  assert(!FileName.empty());
  // Keep track of whether any or all files have an MD5 checksum.
  // If any files have embedded source, they all must.
  if (MCDwarfFiles.empty()) {
    trackMD5Usage(Checksum.has_value());
    HasAnySource |= Source.has_value();
  }
  if (DwarfVersion >= 5 && isRootFile(RootFile, Directory, FileName, Checksum))
    return 0;
  if (FileNumber == 0) {
    // File numbers start with 1 and/or after any file numbers
    // allocated by inline-assembler .file directives.
    FileNumber = MCDwarfFiles.empty() ? 1 : MCDwarfFiles.size();
    SmallString<256> Buffer;
    auto IterBool = SourceIdMap.insert(
        std::make_pair((Directory + Twine('\0') + FileName).toStringRef(Buffer),
                       FileNumber));
    if (!IterBool.second)
      return IterBool.first->second;
  }
  // Make space for this FileNumber in the MCDwarfFiles vector if needed.
  if (FileNumber >= MCDwarfFiles.size())
    MCDwarfFiles.resize(FileNumber + 1);

  // Get the new MCDwarfFile slot for this FileNumber.
  MCDwarfFile &File = MCDwarfFiles[FileNumber];

  // It is an error to see the same number more than once.
  if (!File.Name.empty())
    return make_error<StringError>("file number already allocated",
                                   inconvertibleErrorCode());

  if (Directory.empty()) {
    // Separate the directory part from the basename of the FileName.
    StringRef tFileName = sys::path::filename(FileName);
    if (!tFileName.empty()) {
      Directory = sys::path::parent_path(FileName);
      if (!Directory.empty())
        FileName = tFileName;
    }
  }

  // Find or make an entry in the MCDwarfDirs vector for this Directory.
  // Capture directory name.
  unsigned DirIndex;
  if (Directory.empty()) {
    // For FileNames with no directories a DirIndex of 0 is used.
    DirIndex = 0;
  } else {
    DirIndex = llvm::find(MCDwarfDirs, Directory) - MCDwarfDirs.begin();
    if (DirIndex >= MCDwarfDirs.size())
      MCDwarfDirs.push_back(std::string(Directory));
    // The DirIndex is one based, as DirIndex of 0 is used for FileNames with
    // no directories.  MCDwarfDirs[] is unlike MCDwarfFiles[] in that the
    // directory names are stored at MCDwarfDirs[DirIndex-1] where FileNames
    // are stored at MCDwarfFiles[FileNumber].Name .
    DirIndex++;
  }

  File.Name = std::string(FileName);
  File.DirIndex = DirIndex;
  File.Checksum = Checksum;
  trackMD5Usage(Checksum.has_value());
  File.Source = Source;
  if (Source.has_value())
    HasAnySource = true;

  // return the allocated FileNumber.
  return FileNumber;
}

/// Utility function to emit the encoding to a streamer.
void MCDwarfLineAddr::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
                           int64_t LineDelta, uint64_t AddrDelta) {
  MCContext &Context = MCOS->getContext();
  SmallString<256> Tmp;
  MCDwarfLineAddr::encode(Context, Params, LineDelta, AddrDelta, Tmp);
  MCOS->emitBytes(Tmp);
}

/// Given a special op, return the address skip amount (in units of
/// DWARF2_LINE_MIN_INSN_LENGTH).
static uint64_t SpecialAddr(MCDwarfLineTableParams Params, uint64_t op) {
  return (op - Params.DWARF2LineOpcodeBase) / Params.DWARF2LineRange;
}

/// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas.
void MCDwarfLineAddr::encode(MCContext &Context, MCDwarfLineTableParams Params,
                             int64_t LineDelta, uint64_t AddrDelta,
                             SmallVectorImpl<char> &Out) {
  uint8_t Buf[16];
  uint64_t Temp, Opcode;
  bool NeedCopy = false;

  // The maximum address skip amount that can be encoded with a special op.
  uint64_t MaxSpecialAddrDelta = SpecialAddr(Params, 255);

  // Scale the address delta by the minimum instruction length.
  AddrDelta = ScaleAddrDelta(Context, AddrDelta);

  // A LineDelta of INT64_MAX is a signal that this is actually a
  // DW_LNE_end_sequence. We cannot use special opcodes here, since we want the
  // end_sequence to emit the matrix entry.
  if (LineDelta == INT64_MAX) {
    if (AddrDelta == MaxSpecialAddrDelta)
      Out.push_back(dwarf::DW_LNS_const_add_pc);
    else if (AddrDelta) {
      Out.push_back(dwarf::DW_LNS_advance_pc);
      Out.append(Buf, Buf + encodeULEB128(AddrDelta, Buf));
    }
    Out.push_back(dwarf::DW_LNS_extended_op);
    Out.push_back(1);
    Out.push_back(dwarf::DW_LNE_end_sequence);
    return;
  }

  // Bias the line delta by the base.
  Temp = LineDelta - Params.DWARF2LineBase;

  // If the line increment is out of range of a special opcode, we must encode
  // it with DW_LNS_advance_line.
  if (Temp >= Params.DWARF2LineRange ||
      Temp + Params.DWARF2LineOpcodeBase > 255) {
    Out.push_back(dwarf::DW_LNS_advance_line);
    Out.append(Buf, Buf + encodeSLEB128(LineDelta, Buf));

    LineDelta = 0;
    Temp = 0 - Params.DWARF2LineBase;
    NeedCopy = true;
  }

  // Use DW_LNS_copy instead of a "line +0, addr +0" special opcode.
  if (LineDelta == 0 && AddrDelta == 0) {
    Out.push_back(dwarf::DW_LNS_copy);
    return;
  }

  // Bias the opcode by the special opcode base.
  Temp += Params.DWARF2LineOpcodeBase;

  // Avoid overflow when addr_delta is large.
  if (AddrDelta < 256 + MaxSpecialAddrDelta) {
    // Try using a special opcode.
    Opcode = Temp + AddrDelta * Params.DWARF2LineRange;
    if (Opcode <= 255) {
      Out.push_back(Opcode);
      return;
    }

    // Try using DW_LNS_const_add_pc followed by special op.
    Opcode = Temp + (AddrDelta - MaxSpecialAddrDelta) * Params.DWARF2LineRange;
    if (Opcode <= 255) {
      Out.push_back(dwarf::DW_LNS_const_add_pc);
      Out.push_back(Opcode);
      return;
    }
  }

  // Otherwise use DW_LNS_advance_pc.
  Out.push_back(dwarf::DW_LNS_advance_pc);
  Out.append(Buf, Buf + encodeULEB128(AddrDelta, Buf));

  if (NeedCopy)
    Out.push_back(dwarf::DW_LNS_copy);
  else {
    assert(Temp <= 255 && "Buggy special opcode encoding.");
    Out.push_back(Temp);
  }
}

// Utility function to write a tuple for .debug_abbrev.
static void EmitAbbrev(MCStreamer *MCOS, uint64_t Name, uint64_t Form) {
  MCOS->emitULEB128IntValue(Name);
  MCOS->emitULEB128IntValue(Form);
}

// When generating dwarf for assembly source files this emits
// the data for .debug_abbrev section which contains three DIEs.
static void EmitGenDwarfAbbrev(MCStreamer *MCOS) {
  MCContext &context = MCOS->getContext();
  MCOS->switchSection(context.getObjectFileInfo()->getDwarfAbbrevSection());

  // DW_TAG_compile_unit DIE abbrev (1).
  MCOS->emitULEB128IntValue(1);
  MCOS->emitULEB128IntValue(dwarf::DW_TAG_compile_unit);
  MCOS->emitInt8(dwarf::DW_CHILDREN_yes);
  dwarf::Form SecOffsetForm =
      context.getDwarfVersion() >= 4
          ? dwarf::DW_FORM_sec_offset
          : (context.getDwarfFormat() == dwarf::DWARF64 ? dwarf::DW_FORM_data8
                                                        : dwarf::DW_FORM_data4);
  EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, SecOffsetForm);
  if (context.getGenDwarfSectionSyms().size() > 1 &&
      context.getDwarfVersion() >= 3) {
    EmitAbbrev(MCOS, dwarf::DW_AT_ranges, SecOffsetForm);
  } else {
    EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr);
    EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr);
  }
  EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string);
  if (!context.getCompilationDir().empty())
    EmitAbbrev(MCOS, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string);
  StringRef DwarfDebugFlags = context.getDwarfDebugFlags();
  if (!DwarfDebugFlags.empty())
    EmitAbbrev(MCOS, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string);
  EmitAbbrev(MCOS, dwarf::DW_AT_producer, dwarf::DW_FORM_string);
  EmitAbbrev(MCOS, dwarf::DW_AT_language, dwarf::DW_FORM_data2);
  EmitAbbrev(MCOS, 0, 0);

  // DW_TAG_label DIE abbrev (2).
  MCOS->emitULEB128IntValue(2);
  MCOS->emitULEB128IntValue(dwarf::DW_TAG_label);
  MCOS->emitInt8(dwarf::DW_CHILDREN_no);
  EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string);
  EmitAbbrev(MCOS, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data4);
  EmitAbbrev(MCOS, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data4);
  EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr);
  EmitAbbrev(MCOS, 0, 0);

  // Terminate the abbreviations for this compilation unit.
  MCOS->emitInt8(0);
}

// When generating dwarf for assembly source files this emits the data for
// .debug_aranges section. This section contains a header and a table of pairs
// of PointerSize'ed values for the address and size of section(s) with line
// table entries.
static void EmitGenDwarfAranges(MCStreamer *MCOS,
                                const MCSymbol *InfoSectionSymbol) {
  MCContext &context = MCOS->getContext();

  auto &Sections = context.getGenDwarfSectionSyms();

  MCOS->switchSection(context.getObjectFileInfo()->getDwarfARangesSection());

  unsigned UnitLengthBytes =
      dwarf::getUnitLengthFieldByteSize(context.getDwarfFormat());
  unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(context.getDwarfFormat());

  // This will be the length of the .debug_aranges section, first account for
  // the size of each item in the header (see below where we emit these items).
  int Length = UnitLengthBytes + 2 + OffsetSize + 1 + 1;

  // Figure the padding after the header before the table of address and size
  // pairs who's values are PointerSize'ed.
  const MCAsmInfo *asmInfo = context.getAsmInfo();
  int AddrSize = asmInfo->getCodePointerSize();
  int Pad = 2 * AddrSize - (Length & (2 * AddrSize - 1));
  if (Pad == 2 * AddrSize)
    Pad = 0;
  Length += Pad;

  // Add the size of the pair of PointerSize'ed values for the address and size
  // of each section we have in the table.
  Length += 2 * AddrSize * Sections.size();
  // And the pair of terminating zeros.
  Length += 2 * AddrSize;

  // Emit the header for this section.
  if (context.getDwarfFormat() == dwarf::DWARF64)
    // The DWARF64 mark.
    MCOS->emitInt32(dwarf::DW_LENGTH_DWARF64);
  // The 4 (8 for DWARF64) byte length not including the length of the unit
  // length field itself.
  MCOS->emitIntValue(Length - UnitLengthBytes, OffsetSize);
  // The 2 byte version, which is 2.
  MCOS->emitInt16(2);
  // The 4 (8 for DWARF64) byte offset to the compile unit in the .debug_info
  // from the start of the .debug_info.
  if (InfoSectionSymbol)
    MCOS->emitSymbolValue(InfoSectionSymbol, OffsetSize,
                          asmInfo->needsDwarfSectionOffsetDirective());
  else
    MCOS->emitIntValue(0, OffsetSize);
  // The 1 byte size of an address.
  MCOS->emitInt8(AddrSize);
  // The 1 byte size of a segment descriptor, we use a value of zero.
  MCOS->emitInt8(0);
  // Align the header with the padding if needed, before we put out the table.
  for(int i = 0; i < Pad; i++)
    MCOS->emitInt8(0);

  // Now emit the table of pairs of PointerSize'ed values for the section
  // addresses and sizes.
  for (MCSection *Sec : Sections) {
    const MCSymbol *StartSymbol = Sec->getBeginSymbol();
    MCSymbol *EndSymbol = Sec->getEndSymbol(context);
    assert(StartSymbol && "StartSymbol must not be NULL");
    assert(EndSymbol && "EndSymbol must not be NULL");

    const MCExpr *Addr = MCSymbolRefExpr::create(StartSymbol, context);
    const MCExpr *Size =
        makeEndMinusStartExpr(context, *StartSymbol, *EndSymbol, 0);
    MCOS->emitValue(Addr, AddrSize);
    emitAbsValue(*MCOS, Size, AddrSize);
  }

  // And finally the pair of terminating zeros.
  MCOS->emitIntValue(0, AddrSize);
  MCOS->emitIntValue(0, AddrSize);
}

// When generating dwarf for assembly source files this emits the data for
// .debug_info section which contains three parts.  The header, the compile_unit
// DIE and a list of label DIEs.
static void EmitGenDwarfInfo(MCStreamer *MCOS,
                             const MCSymbol *AbbrevSectionSymbol,
                             const MCSymbol *LineSectionSymbol,
                             const MCSymbol *RangesSymbol) {
  MCContext &context = MCOS->getContext();

  MCOS->switchSection(context.getObjectFileInfo()->getDwarfInfoSection());

  // Create a symbol at the start and end of this section used in here for the
  // expression to calculate the length in the header.
  MCSymbol *InfoStart = context.createTempSymbol();
  MCOS->emitLabel(InfoStart);
  MCSymbol *InfoEnd = context.createTempSymbol();

  // First part: the header.

  unsigned UnitLengthBytes =
      dwarf::getUnitLengthFieldByteSize(context.getDwarfFormat());
  unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(context.getDwarfFormat());

  if (context.getDwarfFormat() == dwarf::DWARF64)
    // Emit DWARF64 mark.
    MCOS->emitInt32(dwarf::DW_LENGTH_DWARF64);

  // The 4 (8 for DWARF64) byte total length of the information for this
  // compilation unit, not including the unit length field itself.
  const MCExpr *Length =
      makeEndMinusStartExpr(context, *InfoStart, *InfoEnd, UnitLengthBytes);
  emitAbsValue(*MCOS, Length, OffsetSize);

  // The 2 byte DWARF version.
  MCOS->emitInt16(context.getDwarfVersion());

  // The DWARF v5 header has unit type, address size, abbrev offset.
  // Earlier versions have abbrev offset, address size.
  const MCAsmInfo &AsmInfo = *context.getAsmInfo();
  int AddrSize = AsmInfo.getCodePointerSize();
  if (context.getDwarfVersion() >= 5) {
    MCOS->emitInt8(dwarf::DW_UT_compile);
    MCOS->emitInt8(AddrSize);
  }
  // The 4 (8 for DWARF64) byte offset to the debug abbrevs from the start of
  // the .debug_abbrev.
  if (AbbrevSectionSymbol)
    MCOS->emitSymbolValue(AbbrevSectionSymbol, OffsetSize,
                          AsmInfo.needsDwarfSectionOffsetDirective());
  else
    // Since the abbrevs are at the start of the section, the offset is zero.
    MCOS->emitIntValue(0, OffsetSize);
  if (context.getDwarfVersion() <= 4)
    MCOS->emitInt8(AddrSize);

  // Second part: the compile_unit DIE.

  // The DW_TAG_compile_unit DIE abbrev (1).
  MCOS->emitULEB128IntValue(1);

  // DW_AT_stmt_list, a 4 (8 for DWARF64) byte offset from the start of the
  // .debug_line section.
  if (LineSectionSymbol)
    MCOS->emitSymbolValue(LineSectionSymbol, OffsetSize,
                          AsmInfo.needsDwarfSectionOffsetDirective());
  else
    // The line table is at the start of the section, so the offset is zero.
    MCOS->emitIntValue(0, OffsetSize);

  if (RangesSymbol) {
    // There are multiple sections containing code, so we must use
    // .debug_ranges/.debug_rnglists. AT_ranges, the 4/8 byte offset from the
    // start of the .debug_ranges/.debug_rnglists.
    MCOS->emitSymbolValue(RangesSymbol, OffsetSize);
  } else {
    // If we only have one non-empty code section, we can use the simpler
    // AT_low_pc and AT_high_pc attributes.

    // Find the first (and only) non-empty text section
    auto &Sections = context.getGenDwarfSectionSyms();
    const auto TextSection = Sections.begin();
    assert(TextSection != Sections.end() && "No text section found");

    MCSymbol *StartSymbol = (*TextSection)->getBeginSymbol();
    MCSymbol *EndSymbol = (*TextSection)->getEndSymbol(context);
    assert(StartSymbol && "StartSymbol must not be NULL");
    assert(EndSymbol && "EndSymbol must not be NULL");

    // AT_low_pc, the first address of the default .text section.
    const MCExpr *Start = MCSymbolRefExpr::create(StartSymbol, context);
    MCOS->emitValue(Start, AddrSize);

    // AT_high_pc, the last address of the default .text section.
    const MCExpr *End = MCSymbolRefExpr::create(EndSymbol, context);
    MCOS->emitValue(End, AddrSize);
  }

  // AT_name, the name of the source file.  Reconstruct from the first directory
  // and file table entries.
  const SmallVectorImpl<std::string> &MCDwarfDirs = context.getMCDwarfDirs();
  if (MCDwarfDirs.size() > 0) {
    MCOS->emitBytes(MCDwarfDirs[0]);
    MCOS->emitBytes(sys::path::get_separator());
  }
  const SmallVectorImpl<MCDwarfFile> &MCDwarfFiles = context.getMCDwarfFiles();
  // MCDwarfFiles might be empty if we have an empty source file.
  // If it's not empty, [0] is unused and [1] is the first actual file.
  assert(MCDwarfFiles.empty() || MCDwarfFiles.size() >= 2);
  const MCDwarfFile &RootFile =
      MCDwarfFiles.empty()
          ? context.getMCDwarfLineTable(/*CUID=*/0).getRootFile()
          : MCDwarfFiles[1];
  MCOS->emitBytes(RootFile.Name);
  MCOS->emitInt8(0); // NULL byte to terminate the string.

  // AT_comp_dir, the working directory the assembly was done in.
  if (!context.getCompilationDir().empty()) {
    MCOS->emitBytes(context.getCompilationDir());
    MCOS->emitInt8(0); // NULL byte to terminate the string.
  }

  // AT_APPLE_flags, the command line arguments of the assembler tool.
  StringRef DwarfDebugFlags = context.getDwarfDebugFlags();
  if (!DwarfDebugFlags.empty()){
    MCOS->emitBytes(DwarfDebugFlags);
    MCOS->emitInt8(0); // NULL byte to terminate the string.
  }

  // AT_producer, the version of the assembler tool.
  StringRef DwarfDebugProducer = context.getDwarfDebugProducer();
  if (!DwarfDebugProducer.empty())
    MCOS->emitBytes(DwarfDebugProducer);
  else
    MCOS->emitBytes(StringRef("llvm-mc (based on LLVM " PACKAGE_VERSION ")"));
  MCOS->emitInt8(0); // NULL byte to terminate the string.

  // AT_language, a 4 byte value.  We use DW_LANG_Mips_Assembler as the dwarf2
  // draft has no standard code for assembler.
  MCOS->emitInt16(dwarf::DW_LANG_Mips_Assembler);

  // Third part: the list of label DIEs.

  // Loop on saved info for dwarf labels and create the DIEs for them.
  const std::vector<MCGenDwarfLabelEntry> &Entries =
      MCOS->getContext().getMCGenDwarfLabelEntries();
  for (const auto &Entry : Entries) {
    // The DW_TAG_label DIE abbrev (2).
    MCOS->emitULEB128IntValue(2);

    // AT_name, of the label without any leading underbar.
    MCOS->emitBytes(Entry.getName());
    MCOS->emitInt8(0); // NULL byte to terminate the string.

    // AT_decl_file, index into the file table.
    MCOS->emitInt32(Entry.getFileNumber());

    // AT_decl_line, source line number.
    MCOS->emitInt32(Entry.getLineNumber());

    // AT_low_pc, start address of the label.
    const auto *AT_low_pc = MCSymbolRefExpr::create(Entry.getLabel(), context);
    MCOS->emitValue(AT_low_pc, AddrSize);
  }

  // Add the NULL DIE terminating the Compile Unit DIE's.
  MCOS->emitInt8(0);

  // Now set the value of the symbol at the end of the info section.
  MCOS->emitLabel(InfoEnd);
}

// When generating dwarf for assembly source files this emits the data for
// .debug_ranges section. We only emit one range list, which spans all of the
// executable sections of this file.
static MCSymbol *emitGenDwarfRanges(MCStreamer *MCOS) {
  MCContext &context = MCOS->getContext();
  auto &Sections = context.getGenDwarfSectionSyms();

  const MCAsmInfo *AsmInfo = context.getAsmInfo();
  int AddrSize = AsmInfo->getCodePointerSize();
  MCSymbol *RangesSymbol;

  if (MCOS->getContext().getDwarfVersion() >= 5) {
    MCOS->switchSection(context.getObjectFileInfo()->getDwarfRnglistsSection());
    MCSymbol *EndSymbol = mcdwarf::emitListsTableHeaderStart(*MCOS);
    MCOS->AddComment("Offset entry count");
    MCOS->emitInt32(0);
    RangesSymbol = context.createTempSymbol("debug_rnglist0_start");
    MCOS->emitLabel(RangesSymbol);
    for (MCSection *Sec : Sections) {
      const MCSymbol *StartSymbol = Sec->getBeginSymbol();
      const MCSymbol *EndSymbol = Sec->getEndSymbol(context);
      const MCExpr *SectionStartAddr =
          MCSymbolRefExpr::create(StartSymbol, context);
      const MCExpr *SectionSize =
          makeEndMinusStartExpr(context, *StartSymbol, *EndSymbol, 0);
      MCOS->emitInt8(dwarf::DW_RLE_start_length);
      MCOS->emitValue(SectionStartAddr, AddrSize);
      MCOS->emitULEB128Value(SectionSize);
    }
    MCOS->emitInt8(dwarf::DW_RLE_end_of_list);
    MCOS->emitLabel(EndSymbol);
  } else {
    MCOS->switchSection(context.getObjectFileInfo()->getDwarfRangesSection());
    RangesSymbol = context.createTempSymbol("debug_ranges_start");
    MCOS->emitLabel(RangesSymbol);
    for (MCSection *Sec : Sections) {
      const MCSymbol *StartSymbol = Sec->getBeginSymbol();
      const MCSymbol *EndSymbol = Sec->getEndSymbol(context);

      // Emit a base address selection entry for the section start.
      const MCExpr *SectionStartAddr =
          MCSymbolRefExpr::create(StartSymbol, context);
      MCOS->emitFill(AddrSize, 0xFF);
      MCOS->emitValue(SectionStartAddr, AddrSize);

      // Emit a range list entry spanning this section.
      const MCExpr *SectionSize =
          makeEndMinusStartExpr(context, *StartSymbol, *EndSymbol, 0);
      MCOS->emitIntValue(0, AddrSize);
      emitAbsValue(*MCOS, SectionSize, AddrSize);
    }

    // Emit end of list entry
    MCOS->emitIntValue(0, AddrSize);
    MCOS->emitIntValue(0, AddrSize);
  }

  return RangesSymbol;
}

//
// When generating dwarf for assembly source files this emits the Dwarf
// sections.
//
void MCGenDwarfInfo::Emit(MCStreamer *MCOS) {
  MCContext &context = MCOS->getContext();

  // Create the dwarf sections in this order (.debug_line already created).
  const MCAsmInfo *AsmInfo = context.getAsmInfo();
  bool CreateDwarfSectionSymbols =
      AsmInfo->doesDwarfUseRelocationsAcrossSections();
  MCSymbol *LineSectionSymbol = nullptr;
  if (CreateDwarfSectionSymbols)
    LineSectionSymbol = MCOS->getDwarfLineTableSymbol(0);
  MCSymbol *AbbrevSectionSymbol = nullptr;
  MCSymbol *InfoSectionSymbol = nullptr;
  MCSymbol *RangesSymbol = nullptr;

  // Create end symbols for each section, and remove empty sections
  MCOS->getContext().finalizeDwarfSections(*MCOS);

  // If there are no sections to generate debug info for, we don't need
  // to do anything
  if (MCOS->getContext().getGenDwarfSectionSyms().empty())
    return;

  // We only use the .debug_ranges section if we have multiple code sections,
  // and we are emitting a DWARF version which supports it.
  const bool UseRangesSection =
      MCOS->getContext().getGenDwarfSectionSyms().size() > 1 &&
      MCOS->getContext().getDwarfVersion() >= 3;
  CreateDwarfSectionSymbols |= UseRangesSection;

  MCOS->switchSection(context.getObjectFileInfo()->getDwarfInfoSection());
  if (CreateDwarfSectionSymbols) {
    InfoSectionSymbol = context.createTempSymbol();
    MCOS->emitLabel(InfoSectionSymbol);
  }
  MCOS->switchSection(context.getObjectFileInfo()->getDwarfAbbrevSection());
  if (CreateDwarfSectionSymbols) {
    AbbrevSectionSymbol = context.createTempSymbol();
    MCOS->emitLabel(AbbrevSectionSymbol);
  }

  MCOS->switchSection(context.getObjectFileInfo()->getDwarfARangesSection());

  // Output the data for .debug_aranges section.
  EmitGenDwarfAranges(MCOS, InfoSectionSymbol);

  if (UseRangesSection) {
    RangesSymbol = emitGenDwarfRanges(MCOS);
    assert(RangesSymbol);
  }

  // Output the data for .debug_abbrev section.
  EmitGenDwarfAbbrev(MCOS);

  // Output the data for .debug_info section.
  EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol, RangesSymbol);
}

//
// When generating dwarf for assembly source files this is called when symbol
// for a label is created.  If this symbol is not a temporary and is in the
// section that dwarf is being generated for, save the needed info to create
// a dwarf label.
//
void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS,
                                SourceMgr &SrcMgr, SMLoc &Loc) {
  // We won't create dwarf labels for temporary symbols.
  if (Symbol->isTemporary())
    return;
  MCContext &context = MCOS->getContext();
  // We won't create dwarf labels for symbols in sections that we are not
  // generating debug info for.
  if (!context.getGenDwarfSectionSyms().count(MCOS->getCurrentSectionOnly()))
    return;

  // The dwarf label's name does not have the symbol name's leading
  // underbar if any.
  StringRef Name = Symbol->getName();
  if (Name.starts_with("_"))
    Name = Name.substr(1, Name.size()-1);

  // Get the dwarf file number to be used for the dwarf label.
  unsigned FileNumber = context.getGenDwarfFileNumber();

  // Finding the line number is the expensive part which is why we just don't
  // pass it in as for some symbols we won't create a dwarf label.
  unsigned CurBuffer = SrcMgr.FindBufferContainingLoc(Loc);
  unsigned LineNumber = SrcMgr.FindLineNumber(Loc, CurBuffer);

  // We create a temporary symbol for use for the AT_high_pc and AT_low_pc
  // values so that they don't have things like an ARM thumb bit from the
  // original symbol. So when used they won't get a low bit set after
  // relocation.
  MCSymbol *Label = context.createTempSymbol();
  MCOS->emitLabel(Label);

  // Create and entry for the info and add it to the other entries.
  MCOS->getContext().addMCGenDwarfLabelEntry(
      MCGenDwarfLabelEntry(Name, FileNumber, LineNumber, Label));
}

static int getDataAlignmentFactor(MCStreamer &streamer) {
  MCContext &context = streamer.getContext();
  const MCAsmInfo *asmInfo = context.getAsmInfo();
  int size = asmInfo->getCalleeSaveStackSlotSize();
  if (asmInfo->isStackGrowthDirectionUp())
    return size;
  else
    return -size;
}

static unsigned getSizeForEncoding(MCStreamer &streamer,
                                   unsigned symbolEncoding) {
  MCContext &context = streamer.getContext();
  unsigned format = symbolEncoding & 0x0f;
  switch (format) {
  default: llvm_unreachable("Unknown Encoding");
  case dwarf::DW_EH_PE_absptr:
  case dwarf::DW_EH_PE_signed:
    return context.getAsmInfo()->getCodePointerSize();
  case dwarf::DW_EH_PE_udata2:
  case dwarf::DW_EH_PE_sdata2:
    return 2;
  case dwarf::DW_EH_PE_udata4:
  case dwarf::DW_EH_PE_sdata4:
    return 4;
  case dwarf::DW_EH_PE_udata8:
  case dwarf::DW_EH_PE_sdata8:
    return 8;
  }
}

static void emitFDESymbol(MCObjectStreamer &streamer, const MCSymbol &symbol,
                          unsigned symbolEncoding, bool isEH) {
  MCContext &context = streamer.getContext();
  const MCAsmInfo *asmInfo = context.getAsmInfo();
  const MCExpr *v = asmInfo->getExprForFDESymbol(&symbol,
                                                 symbolEncoding,
                                                 streamer);
  unsigned size = getSizeForEncoding(streamer, symbolEncoding);
  if (asmInfo->doDwarfFDESymbolsUseAbsDiff() && isEH)
    emitAbsValue(streamer, v, size);
  else
    streamer.emitValue(v, size);
}

static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol,
                            unsigned symbolEncoding) {
  MCContext &context = streamer.getContext();
  const MCAsmInfo *asmInfo = context.getAsmInfo();
  const MCExpr *v = asmInfo->getExprForPersonalitySymbol(&symbol,
                                                         symbolEncoding,
                                                         streamer);
  unsigned size = getSizeForEncoding(streamer, symbolEncoding);
  streamer.emitValue(v, size);
}

namespace {

class FrameEmitterImpl {
  int64_t CFAOffset = 0;
  int64_t InitialCFAOffset = 0;
  bool IsEH;
  MCObjectStreamer &Streamer;

public:
  FrameEmitterImpl(bool IsEH, MCObjectStreamer &Streamer)
      : IsEH(IsEH), Streamer(Streamer) {}

  /// Emit the unwind information in a compact way.
  void EmitCompactUnwind(const MCDwarfFrameInfo &frame);

  const MCSymbol &EmitCIE(const MCDwarfFrameInfo &F);
  void EmitFDE(const MCSymbol &cieStart, const MCDwarfFrameInfo &frame,
               bool LastInSection, const MCSymbol &SectionStart);
  void emitCFIInstructions(ArrayRef<MCCFIInstruction> Instrs,
                           MCSymbol *BaseLabel);
  void emitCFIInstruction(const MCCFIInstruction &Instr);
};

} // end anonymous namespace

static void emitEncodingByte(MCObjectStreamer &Streamer, unsigned Encoding) {
  Streamer.emitInt8(Encoding);
}

void FrameEmitterImpl::emitCFIInstruction(const MCCFIInstruction &Instr) {
  int dataAlignmentFactor = getDataAlignmentFactor(Streamer);
  auto *MRI = Streamer.getContext().getRegisterInfo();

  switch (Instr.getOperation()) {
  case MCCFIInstruction::OpRegister: {
    unsigned Reg1 = Instr.getRegister();
    unsigned Reg2 = Instr.getRegister2();
    if (!IsEH) {
      Reg1 = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg1);
      Reg2 = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg2);
    }
    Streamer.emitInt8(dwarf::DW_CFA_register);
    Streamer.emitULEB128IntValue(Reg1);
    Streamer.emitULEB128IntValue(Reg2);
    return;
  }
  case MCCFIInstruction::OpWindowSave:
    Streamer.emitInt8(dwarf::DW_CFA_GNU_window_save);
    return;

  case MCCFIInstruction::OpNegateRAState:
    Streamer.emitInt8(dwarf::DW_CFA_AARCH64_negate_ra_state);
    return;

  case MCCFIInstruction::OpNegateRAStateWithPC:
    Streamer.emitInt8(dwarf::DW_CFA_AARCH64_negate_ra_state_with_pc);
    return;

  case MCCFIInstruction::OpUndefined: {
    unsigned Reg = Instr.getRegister();
    Streamer.emitInt8(dwarf::DW_CFA_undefined);
    Streamer.emitULEB128IntValue(Reg);
    return;
  }
  case MCCFIInstruction::OpAdjustCfaOffset:
  case MCCFIInstruction::OpDefCfaOffset: {
    const bool IsRelative =
      Instr.getOperation() == MCCFIInstruction::OpAdjustCfaOffset;

    Streamer.emitInt8(dwarf::DW_CFA_def_cfa_offset);

    if (IsRelative)
      CFAOffset += Instr.getOffset();
    else
      CFAOffset = Instr.getOffset();

    Streamer.emitULEB128IntValue(CFAOffset);

    return;
  }
  case MCCFIInstruction::OpDefCfa: {
    unsigned Reg = Instr.getRegister();
    if (!IsEH)
      Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
    Streamer.emitInt8(dwarf::DW_CFA_def_cfa);
    Streamer.emitULEB128IntValue(Reg);
    CFAOffset = Instr.getOffset();
    Streamer.emitULEB128IntValue(CFAOffset);

    return;
  }
  case MCCFIInstruction::OpDefCfaRegister: {
    unsigned Reg = Instr.getRegister();
    if (!IsEH)
      Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
    Streamer.emitInt8(dwarf::DW_CFA_def_cfa_register);
    Streamer.emitULEB128IntValue(Reg);

    return;
  }
  // TODO: Implement `_sf` variants if/when they need to be emitted.
  case MCCFIInstruction::OpLLVMDefAspaceCfa: {
    unsigned Reg = Instr.getRegister();
    if (!IsEH)
      Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
    Streamer.emitIntValue(dwarf::DW_CFA_LLVM_def_aspace_cfa, 1);
    Streamer.emitULEB128IntValue(Reg);
    CFAOffset = Instr.getOffset();
    Streamer.emitULEB128IntValue(CFAOffset);
    Streamer.emitULEB128IntValue(Instr.getAddressSpace());

    return;
  }
  case MCCFIInstruction::OpOffset:
  case MCCFIInstruction::OpRelOffset: {
    const bool IsRelative =
      Instr.getOperation() == MCCFIInstruction::OpRelOffset;

    unsigned Reg = Instr.getRegister();
    if (!IsEH)
      Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);

    int64_t Offset = Instr.getOffset();
    if (IsRelative)
      Offset -= CFAOffset;
    Offset = Offset / dataAlignmentFactor;

    if (Offset < 0) {
      Streamer.emitInt8(dwarf::DW_CFA_offset_extended_sf);
      Streamer.emitULEB128IntValue(Reg);
      Streamer.emitSLEB128IntValue(Offset);
    } else if (Reg < 64) {
      Streamer.emitInt8(dwarf::DW_CFA_offset + Reg);
      Streamer.emitULEB128IntValue(Offset);
    } else {
      Streamer.emitInt8(dwarf::DW_CFA_offset_extended);
      Streamer.emitULEB128IntValue(Reg);
      Streamer.emitULEB128IntValue(Offset);
    }
    return;
  }
  case MCCFIInstruction::OpRememberState:
    Streamer.emitInt8(dwarf::DW_CFA_remember_state);
    return;
  case MCCFIInstruction::OpRestoreState:
    Streamer.emitInt8(dwarf::DW_CFA_restore_state);
    return;
  case MCCFIInstruction::OpSameValue: {
    unsigned Reg = Instr.getRegister();
    Streamer.emitInt8(dwarf::DW_CFA_same_value);
    Streamer.emitULEB128IntValue(Reg);
    return;
  }
  case MCCFIInstruction::OpRestore: {
    unsigned Reg = Instr.getRegister();
    if (!IsEH)
      Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
    if (Reg < 64) {
      Streamer.emitInt8(dwarf::DW_CFA_restore | Reg);
    } else {
      Streamer.emitInt8(dwarf::DW_CFA_restore_extended);
      Streamer.emitULEB128IntValue(Reg);
    }
    return;
  }
  case MCCFIInstruction::OpGnuArgsSize:
    Streamer.emitInt8(dwarf::DW_CFA_GNU_args_size);
    Streamer.emitULEB128IntValue(Instr.getOffset());
    return;

  case MCCFIInstruction::OpEscape:
    Streamer.emitBytes(Instr.getValues());
    return;
  case MCCFIInstruction::OpLabel:
    Streamer.emitLabel(Instr.getCfiLabel(), Instr.getLoc());
    return;
  case MCCFIInstruction::OpValOffset: {
    unsigned Reg = Instr.getRegister();
    if (!IsEH)
      Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);

    int Offset = Instr.getOffset();
    Offset = Offset / dataAlignmentFactor;

    if (Offset < 0) {
      Streamer.emitInt8(dwarf::DW_CFA_val_offset_sf);
      Streamer.emitULEB128IntValue(Reg);
      Streamer.emitSLEB128IntValue(Offset);
    } else {
      Streamer.emitInt8(dwarf::DW_CFA_val_offset);
      Streamer.emitULEB128IntValue(Reg);
      Streamer.emitULEB128IntValue(Offset);
    }
    return;
  }
  }
  llvm_unreachable("Unhandled case in switch");
}

/// Emit frame instructions to describe the layout of the frame.
void FrameEmitterImpl::emitCFIInstructions(ArrayRef<MCCFIInstruction> Instrs,
                                           MCSymbol *BaseLabel) {
  for (const MCCFIInstruction &Instr : Instrs) {
    MCSymbol *Label = Instr.getLabel();
    // Throw out move if the label is invalid.
    if (Label && !Label->isDefined()) continue; // Not emitted, in dead code.

    // Advance row if new location.
    if (BaseLabel && Label) {
      MCSymbol *ThisSym = Label;
      if (ThisSym != BaseLabel) {
        Streamer.emitDwarfAdvanceFrameAddr(BaseLabel, ThisSym, Instr.getLoc());
        BaseLabel = ThisSym;
      }
    }

    emitCFIInstruction(Instr);
  }
}

/// Emit the unwind information in a compact way.
void FrameEmitterImpl::EmitCompactUnwind(const MCDwarfFrameInfo &Frame) {
  MCContext &Context = Streamer.getContext();
  const MCObjectFileInfo *MOFI = Context.getObjectFileInfo();

  // range-start range-length  compact-unwind-enc personality-func   lsda
  //  _foo       LfooEnd-_foo  0x00000023          0                 0
  //  _bar       LbarEnd-_bar  0x00000025         __gxx_personality  except_tab1
  //
  //   .section __LD,__compact_unwind,regular,debug
  //
  //   # compact unwind for _foo
  //   .quad _foo
  //   .set L1,LfooEnd-_foo
  //   .long L1
  //   .long 0x01010001
  //   .quad 0
  //   .quad 0
  //
  //   # compact unwind for _bar
  //   .quad _bar
  //   .set L2,LbarEnd-_bar
  //   .long L2
  //   .long 0x01020011
  //   .quad __gxx_personality
  //   .quad except_tab1

  uint32_t Encoding = Frame.CompactUnwindEncoding;
  if (!Encoding) return;
  bool DwarfEHFrameOnly = (Encoding == MOFI->getCompactUnwindDwarfEHFrameOnly());

  // The encoding needs to know we have an LSDA.
  if (!DwarfEHFrameOnly && Frame.Lsda)
    Encoding |= 0x40000000;

  // Range Start
  unsigned FDEEncoding = MOFI->getFDEEncoding();
  unsigned Size = getSizeForEncoding(Streamer, FDEEncoding);
  Streamer.emitSymbolValue(Frame.Begin, Size);

  // Range Length
  const MCExpr *Range =
      makeEndMinusStartExpr(Context, *Frame.Begin, *Frame.End, 0);
  emitAbsValue(Streamer, Range, 4);

  // Compact Encoding
  Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_udata4);
  Streamer.emitIntValue(Encoding, Size);

  // Personality Function
  Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_absptr);
  if (!DwarfEHFrameOnly && Frame.Personality)
    Streamer.emitSymbolValue(Frame.Personality, Size);
  else
    Streamer.emitIntValue(0, Size); // No personality fn

  // LSDA
  Size = getSizeForEncoding(Streamer, Frame.LsdaEncoding);
  if (!DwarfEHFrameOnly && Frame.Lsda)
    Streamer.emitSymbolValue(Frame.Lsda, Size);
  else
    Streamer.emitIntValue(0, Size); // No LSDA
}

static unsigned getCIEVersion(bool IsEH, unsigned DwarfVersion) {
  if (IsEH)
    return 1;
  switch (DwarfVersion) {
  case 2:
    return 1;
  case 3:
    return 3;
  case 4:
  case 5:
    return 4;
  }
  llvm_unreachable("Unknown version");
}

const MCSymbol &FrameEmitterImpl::EmitCIE(const MCDwarfFrameInfo &Frame) {
  MCContext &context = Streamer.getContext();
  const MCRegisterInfo *MRI = context.getRegisterInfo();
  const MCObjectFileInfo *MOFI = context.getObjectFileInfo();

  MCSymbol *sectionStart = context.createTempSymbol();
  Streamer.emitLabel(sectionStart);

  MCSymbol *sectionEnd = context.createTempSymbol();

  dwarf::DwarfFormat Format = IsEH ? dwarf::DWARF32 : context.getDwarfFormat();
  unsigned UnitLengthBytes = dwarf::getUnitLengthFieldByteSize(Format);
  unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(Format);
  bool IsDwarf64 = Format == dwarf::DWARF64;

  if (IsDwarf64)
    // DWARF64 mark
    Streamer.emitInt32(dwarf::DW_LENGTH_DWARF64);

  // Length
  const MCExpr *Length = makeEndMinusStartExpr(context, *sectionStart,
                                               *sectionEnd, UnitLengthBytes);
  emitAbsValue(Streamer, Length, OffsetSize);

  // CIE ID
  uint64_t CIE_ID =
      IsEH ? 0 : (IsDwarf64 ? dwarf::DW64_CIE_ID : dwarf::DW_CIE_ID);
  Streamer.emitIntValue(CIE_ID, OffsetSize);

  // Version
  uint8_t CIEVersion = getCIEVersion(IsEH, context.getDwarfVersion());
  Streamer.emitInt8(CIEVersion);

  if (IsEH) {
    SmallString<8> Augmentation;
    Augmentation += "z";
    if (Frame.Personality)
      Augmentation += "P";
    if (Frame.Lsda)
      Augmentation += "L";
    Augmentation += "R";
    if (Frame.IsSignalFrame)
      Augmentation += "S";
    if (Frame.IsBKeyFrame)
      Augmentation += "B";
    if (Frame.IsMTETaggedFrame)
      Augmentation += "G";
    Streamer.emitBytes(Augmentation);
  }
  Streamer.emitInt8(0);

  if (CIEVersion >= 4) {
    // Address Size
    Streamer.emitInt8(context.getAsmInfo()->getCodePointerSize());

    // Segment Descriptor Size
    Streamer.emitInt8(0);
  }

  // Code Alignment Factor
  Streamer.emitULEB128IntValue(context.getAsmInfo()->getMinInstAlignment());

  // Data Alignment Factor
  Streamer.emitSLEB128IntValue(getDataAlignmentFactor(Streamer));

  // Return Address Register
  unsigned RAReg = Frame.RAReg;
  if (RAReg == static_cast<unsigned>(INT_MAX))
    RAReg = MRI->getDwarfRegNum(MRI->getRARegister(), IsEH);

  if (CIEVersion == 1) {
    assert(RAReg <= 255 &&
           "DWARF 2 encodes return_address_register in one byte");
    Streamer.emitInt8(RAReg);
  } else {
    Streamer.emitULEB128IntValue(RAReg);
  }

  // Augmentation Data Length (optional)
  unsigned augmentationLength = 0;
  if (IsEH) {
    if (Frame.Personality) {
      // Personality Encoding
      augmentationLength += 1;
      // Personality
      augmentationLength +=
          getSizeForEncoding(Streamer, Frame.PersonalityEncoding);
    }
    if (Frame.Lsda)
      augmentationLength += 1;
    // Encoding of the FDE pointers
    augmentationLength += 1;

    Streamer.emitULEB128IntValue(augmentationLength);

    // Augmentation Data (optional)
    if (Frame.Personality) {
      // Personality Encoding
      emitEncodingByte(Streamer, Frame.PersonalityEncoding);
      // Personality
      EmitPersonality(Streamer, *Frame.Personality, Frame.PersonalityEncoding);
    }

    if (Frame.Lsda)
      emitEncodingByte(Streamer, Frame.LsdaEncoding);

    // Encoding of the FDE pointers
    emitEncodingByte(Streamer, MOFI->getFDEEncoding());
  }

  // Initial Instructions

  const MCAsmInfo *MAI = context.getAsmInfo();
  if (!Frame.IsSimple) {
    const std::vector<MCCFIInstruction> &Instructions =
        MAI->getInitialFrameState();
    emitCFIInstructions(Instructions, nullptr);
  }

  InitialCFAOffset = CFAOffset;

  // Padding
  Streamer.emitValueToAlignment(Align(IsEH ? 4 : MAI->getCodePointerSize()));

  Streamer.emitLabel(sectionEnd);
  return *sectionStart;
}

void FrameEmitterImpl::EmitFDE(const MCSymbol &cieStart,
                               const MCDwarfFrameInfo &frame,
                               bool LastInSection,
                               const MCSymbol &SectionStart) {
  MCContext &context = Streamer.getContext();
  MCSymbol *fdeStart = context.createTempSymbol();
  MCSymbol *fdeEnd = context.createTempSymbol();
  const MCObjectFileInfo *MOFI = context.getObjectFileInfo();

  CFAOffset = InitialCFAOffset;

  dwarf::DwarfFormat Format = IsEH ? dwarf::DWARF32 : context.getDwarfFormat();
  unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(Format);

  if (Format == dwarf::DWARF64)
    // DWARF64 mark
    Streamer.emitInt32(dwarf::DW_LENGTH_DWARF64);

  // Length
  const MCExpr *Length = makeEndMinusStartExpr(context, *fdeStart, *fdeEnd, 0);
  emitAbsValue(Streamer, Length, OffsetSize);

  Streamer.emitLabel(fdeStart);

  // CIE Pointer
  const MCAsmInfo *asmInfo = context.getAsmInfo();
  if (IsEH) {
    const MCExpr *offset =
        makeEndMinusStartExpr(context, cieStart, *fdeStart, 0);
    emitAbsValue(Streamer, offset, OffsetSize);
  } else if (!asmInfo->doesDwarfUseRelocationsAcrossSections()) {
    const MCExpr *offset =
        makeEndMinusStartExpr(context, SectionStart, cieStart, 0);
    emitAbsValue(Streamer, offset, OffsetSize);
  } else {
    Streamer.emitSymbolValue(&cieStart, OffsetSize,
                             asmInfo->needsDwarfSectionOffsetDirective());
  }

  // PC Begin
  unsigned PCEncoding =
      IsEH ? MOFI->getFDEEncoding() : (unsigned)dwarf::DW_EH_PE_absptr;
  unsigned PCSize = getSizeForEncoding(Streamer, PCEncoding);
  emitFDESymbol(Streamer, *frame.Begin, PCEncoding, IsEH);

  // PC Range
  const MCExpr *Range =
      makeEndMinusStartExpr(context, *frame.Begin, *frame.End, 0);
  emitAbsValue(Streamer, Range, PCSize);

  if (IsEH) {
    // Augmentation Data Length
    unsigned augmentationLength = 0;

    if (frame.Lsda)
      augmentationLength += getSizeForEncoding(Streamer, frame.LsdaEncoding);

    Streamer.emitULEB128IntValue(augmentationLength);

    // Augmentation Data
    if (frame.Lsda)
      emitFDESymbol(Streamer, *frame.Lsda, frame.LsdaEncoding, true);
  }

  // Call Frame Instructions
  emitCFIInstructions(frame.Instructions, frame.Begin);

  // Padding
  // The size of a .eh_frame section has to be a multiple of the alignment
  // since a null CIE is interpreted as the end. Old systems overaligned
  // .eh_frame, so we do too and account for it in the last FDE.
  unsigned Alignment = LastInSection ? asmInfo->getCodePointerSize() : PCSize;
  Streamer.emitValueToAlignment(Align(Alignment));

  Streamer.emitLabel(fdeEnd);
}

namespace {

struct CIEKey {
  CIEKey() = default;

  explicit CIEKey(const MCDwarfFrameInfo &Frame)
      : Personality(Frame.Personality),
        PersonalityEncoding(Frame.PersonalityEncoding),
        LsdaEncoding(Frame.LsdaEncoding), IsSignalFrame(Frame.IsSignalFrame),
        IsSimple(Frame.IsSimple), RAReg(Frame.RAReg),
        IsBKeyFrame(Frame.IsBKeyFrame),
        IsMTETaggedFrame(Frame.IsMTETaggedFrame) {}

  StringRef PersonalityName() const {
    if (!Personality)
      return StringRef();
    return Personality->getName();
  }

  bool operator<(const CIEKey &Other) const {
    return std::make_tuple(PersonalityName(), PersonalityEncoding, LsdaEncoding,
                           IsSignalFrame, IsSimple, RAReg, IsBKeyFrame,
                           IsMTETaggedFrame) <
           std::make_tuple(Other.PersonalityName(), Other.PersonalityEncoding,
                           Other.LsdaEncoding, Other.IsSignalFrame,
                           Other.IsSimple, Other.RAReg, Other.IsBKeyFrame,
                           Other.IsMTETaggedFrame);
  }

  bool operator==(const CIEKey &Other) const {
    return Personality == Other.Personality &&
           PersonalityEncoding == Other.PersonalityEncoding &&
           LsdaEncoding == Other.LsdaEncoding &&
           IsSignalFrame == Other.IsSignalFrame && IsSimple == Other.IsSimple &&
           RAReg == Other.RAReg && IsBKeyFrame == Other.IsBKeyFrame &&
           IsMTETaggedFrame == Other.IsMTETaggedFrame;
  }
  bool operator!=(const CIEKey &Other) const { return !(*this == Other); }

  const MCSymbol *Personality = nullptr;
  unsigned PersonalityEncoding = 0;
  unsigned LsdaEncoding = -1;
  bool IsSignalFrame = false;
  bool IsSimple = false;
  unsigned RAReg = UINT_MAX;
  bool IsBKeyFrame = false;
  bool IsMTETaggedFrame = false;
};

} // end anonymous namespace

void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB,
                               bool IsEH) {
  MCContext &Context = Streamer.getContext();
  const MCObjectFileInfo *MOFI = Context.getObjectFileInfo();
  const MCAsmInfo *AsmInfo = Context.getAsmInfo();
  FrameEmitterImpl Emitter(IsEH, Streamer);
  ArrayRef<MCDwarfFrameInfo> FrameArray = Streamer.getDwarfFrameInfos();

  // Emit the compact unwind info if available.
  bool NeedsEHFrameSection = !MOFI->getSupportsCompactUnwindWithoutEHFrame();
  if (IsEH && MOFI->getCompactUnwindSection()) {
    Streamer.generateCompactUnwindEncodings(MAB);
    bool SectionEmitted = false;
    for (const MCDwarfFrameInfo &Frame : FrameArray) {
      if (Frame.CompactUnwindEncoding == 0) continue;
      if (!SectionEmitted) {
        Streamer.switchSection(MOFI->getCompactUnwindSection());
        Streamer.emitValueToAlignment(Align(AsmInfo->getCodePointerSize()));
        SectionEmitted = true;
      }
      NeedsEHFrameSection |=
        Frame.CompactUnwindEncoding ==
          MOFI->getCompactUnwindDwarfEHFrameOnly();
      Emitter.EmitCompactUnwind(Frame);
    }
  }

  // Compact unwind information can be emitted in the eh_frame section or the
  // debug_frame section. Skip emitting FDEs and CIEs when the compact unwind
  // doesn't need an eh_frame section and the emission location is the eh_frame
  // section.
  if (!NeedsEHFrameSection && IsEH) return;

  MCSection &Section =
      IsEH ? *const_cast<MCObjectFileInfo *>(MOFI)->getEHFrameSection()
           : *MOFI->getDwarfFrameSection();

  Streamer.switchSection(&Section);
  MCSymbol *SectionStart = Context.createTempSymbol();
  Streamer.emitLabel(SectionStart);

  bool CanOmitDwarf = MOFI->getOmitDwarfIfHaveCompactUnwind();
  // Sort the FDEs by their corresponding CIE before we emit them.
  // This isn't technically necessary according to the DWARF standard,
  // but the Android libunwindstack rejects eh_frame sections where
  // an FDE refers to a CIE other than the closest previous CIE.
  std::vector<MCDwarfFrameInfo> FrameArrayX(FrameArray.begin(), FrameArray.end());
  llvm::stable_sort(FrameArrayX,
                    [](const MCDwarfFrameInfo &X, const MCDwarfFrameInfo &Y) {
                      return CIEKey(X) < CIEKey(Y);
                    });
  CIEKey LastKey;
  const MCSymbol *LastCIEStart = nullptr;
  for (auto I = FrameArrayX.begin(), E = FrameArrayX.end(); I != E;) {
    const MCDwarfFrameInfo &Frame = *I;
    ++I;
    if (CanOmitDwarf && Frame.CompactUnwindEncoding !=
          MOFI->getCompactUnwindDwarfEHFrameOnly() && IsEH)
      // CIEs and FDEs can be emitted in either the eh_frame section or the
      // debug_frame section, on some platforms (e.g. AArch64) the target object
      // file supports emitting a compact_unwind section without an associated
      // eh_frame section. If the eh_frame section is not needed, and the
      // location where the CIEs and FDEs are to be emitted is the eh_frame
      // section, do not emit anything.
      continue;

    CIEKey Key(Frame);
    if (!LastCIEStart || (IsEH && Key != LastKey)) {
      LastKey = Key;
      LastCIEStart = &Emitter.EmitCIE(Frame);
    }

    Emitter.EmitFDE(*LastCIEStart, Frame, I == E, *SectionStart);
  }
}

void MCDwarfFrameEmitter::encodeAdvanceLoc(MCContext &Context,
                                           uint64_t AddrDelta,
                                           SmallVectorImpl<char> &Out) {
  // Scale the address delta by the minimum instruction length.
  AddrDelta = ScaleAddrDelta(Context, AddrDelta);
  if (AddrDelta == 0)
    return;

  llvm::endianness E = Context.getAsmInfo()->isLittleEndian()
                           ? llvm::endianness::little
                           : llvm::endianness::big;

  if (isUIntN(6, AddrDelta)) {
    uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta;
    Out.push_back(Opcode);
  } else if (isUInt<8>(AddrDelta)) {
    Out.push_back(dwarf::DW_CFA_advance_loc1);
    Out.push_back(AddrDelta);
  } else if (isUInt<16>(AddrDelta)) {
    Out.push_back(dwarf::DW_CFA_advance_loc2);
    support::endian::write<uint16_t>(Out, AddrDelta, E);
  } else {
    assert(isUInt<32>(AddrDelta));
    Out.push_back(dwarf::DW_CFA_advance_loc4);
    support::endian::write<uint32_t>(Out, AddrDelta, E);
  }
}
