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

#include "llvm/DWARFLinker/DWARFStreamer.h"
#include "llvm/CodeGen/NonRelocatableStringpool.h"
#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/MC/MCTargetOptionsCommandFlags.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/TargetParser/Triple.h"

namespace llvm {

bool DwarfStreamer::init(Triple TheTriple,
                         StringRef Swift5ReflectionSegmentName) {
  std::string ErrorStr;
  std::string TripleName;
  StringRef Context = "dwarf streamer init";

  // Get the target.
  const Target *TheTarget =
      TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr);
  if (!TheTarget)
    return error(ErrorStr, Context), false;
  TripleName = TheTriple.getTriple();

  // Create all the MC Objects.
  MRI.reset(TheTarget->createMCRegInfo(TripleName));
  if (!MRI)
    return error(Twine("no register info for target ") + TripleName, Context),
           false;

  MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();
  MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
  if (!MAI)
    return error("no asm info for target " + TripleName, Context), false;

  MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
  if (!MSTI)
    return error("no subtarget info for target " + TripleName, Context), false;

  MC.reset(new MCContext(TheTriple, MAI.get(), MRI.get(), MSTI.get(), nullptr,
                         nullptr, true, Swift5ReflectionSegmentName));
  MOFI.reset(TheTarget->createMCObjectFileInfo(*MC, /*PIC=*/false, false));
  MC->setObjectFileInfo(MOFI.get());

  MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, MCOptions);
  if (!MAB)
    return error("no asm backend for target " + TripleName, Context), false;

  MII.reset(TheTarget->createMCInstrInfo());
  if (!MII)
    return error("no instr info info for target " + TripleName, Context), false;

  MCE = TheTarget->createMCCodeEmitter(*MII, *MC);
  if (!MCE)
    return error("no code emitter for target " + TripleName, Context), false;

  switch (OutFileType) {
  case OutputFileType::Assembly: {
    MIP = TheTarget->createMCInstPrinter(TheTriple, MAI->getAssemblerDialect(),
                                         *MAI, *MII, *MRI);
    MS = TheTarget->createAsmStreamer(
        *MC, std::make_unique<formatted_raw_ostream>(OutFile), true, true, MIP,
        std::unique_ptr<MCCodeEmitter>(MCE), std::unique_ptr<MCAsmBackend>(MAB),
        true);
    break;
  }
  case OutputFileType::Object: {
    MS = TheTarget->createMCObjectStreamer(
        TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB),
        MAB->createObjectWriter(OutFile), std::unique_ptr<MCCodeEmitter>(MCE),
        *MSTI, MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible,
        /*DWARFMustBeAtTheEnd*/ false);
    break;
  }
  }

  if (!MS)
    return error("no object streamer for target " + TripleName, Context), false;

  // Finally create the AsmPrinter we'll use to emit the DIEs.
  TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions(),
                                          std::nullopt));
  if (!TM)
    return error("no target machine for target " + TripleName, Context), false;

  Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS)));
  if (!Asm)
    return error("no asm printer for target " + TripleName, Context), false;
  Asm->setDwarfUsesRelocationsAcrossSections(false);

  RangesSectionSize = 0;
  RngListsSectionSize = 0;
  LocSectionSize = 0;
  LocListsSectionSize = 0;
  LineSectionSize = 0;
  FrameSectionSize = 0;
  DebugInfoSectionSize = 0;
  MacInfoSectionSize = 0;
  MacroSectionSize = 0;

  return true;
}

void DwarfStreamer::finish() { MS->finish(); }

void DwarfStreamer::switchToDebugInfoSection(unsigned DwarfVersion) {
  MS->switchSection(MOFI->getDwarfInfoSection());
  MC->setDwarfVersion(DwarfVersion);
}

/// Emit the compilation unit header for \p Unit in the debug_info section.
///
/// A Dwarf 4 section header is encoded as:
///  uint32_t   Unit length (omitting this field)
///  uint16_t   Version
///  uint32_t   Abbreviation table offset
///  uint8_t    Address size
/// Leading to a total of 11 bytes.
///
/// A Dwarf 5 section header is encoded as:
///  uint32_t   Unit length (omitting this field)
///  uint16_t   Version
///  uint8_t    Unit type
///  uint8_t    Address size
///  uint32_t   Abbreviation table offset
/// Leading to a total of 12 bytes.
void DwarfStreamer::emitCompileUnitHeader(CompileUnit &Unit,
                                          unsigned DwarfVersion) {
  switchToDebugInfoSection(DwarfVersion);

  /// The start of the unit within its section.
  Unit.setLabelBegin(Asm->createTempSymbol("cu_begin"));
  Asm->OutStreamer->emitLabel(Unit.getLabelBegin());

  // Emit size of content not including length itself. The size has already
  // been computed in CompileUnit::computeOffsets(). Subtract 4 to that size to
  // account for the length field.
  Asm->emitInt32(Unit.getNextUnitOffset() - Unit.getStartOffset() - 4);
  Asm->emitInt16(DwarfVersion);

  if (DwarfVersion >= 5) {
    Asm->emitInt8(dwarf::DW_UT_compile);
    Asm->emitInt8(Unit.getOrigUnit().getAddressByteSize());
    // We share one abbreviations table across all units so it's always at the
    // start of the section.
    Asm->emitInt32(0);
    DebugInfoSectionSize += 12;
  } else {
    // We share one abbreviations table across all units so it's always at the
    // start of the section.
    Asm->emitInt32(0);
    Asm->emitInt8(Unit.getOrigUnit().getAddressByteSize());
    DebugInfoSectionSize += 11;
  }

  // Remember this CU.
  EmittedUnits.push_back({Unit.getUniqueID(), Unit.getLabelBegin()});
}

/// Emit the \p Abbrevs array as the shared abbreviation table
/// for the linked Dwarf file.
void DwarfStreamer::emitAbbrevs(
    const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs,
    unsigned DwarfVersion) {
  MS->switchSection(MOFI->getDwarfAbbrevSection());
  MC->setDwarfVersion(DwarfVersion);
  Asm->emitDwarfAbbrevs(Abbrevs);
}

/// Recursively emit the DIE tree rooted at \p Die.
void DwarfStreamer::emitDIE(DIE &Die) {
  MS->switchSection(MOFI->getDwarfInfoSection());
  Asm->emitDwarfDIE(Die);
  DebugInfoSectionSize += Die.getSize();
}

/// Emit contents of section SecName From Obj.
void DwarfStreamer::emitSectionContents(StringRef SecData, StringRef SecName) {
  MCSection *Section =
      StringSwitch<MCSection *>(SecName)
          .Case("debug_line", MC->getObjectFileInfo()->getDwarfLineSection())
          .Case("debug_loc", MC->getObjectFileInfo()->getDwarfLocSection())
          .Case("debug_ranges",
                MC->getObjectFileInfo()->getDwarfRangesSection())
          .Case("debug_frame", MC->getObjectFileInfo()->getDwarfFrameSection())
          .Case("debug_aranges",
                MC->getObjectFileInfo()->getDwarfARangesSection())
          .Case("debug_addr", MC->getObjectFileInfo()->getDwarfAddrSection())
          .Case("debug_rnglists",
                MC->getObjectFileInfo()->getDwarfRnglistsSection())
          .Case("debug_loclists",
                MC->getObjectFileInfo()->getDwarfLoclistsSection())
          .Default(nullptr);

  if (Section) {
    MS->switchSection(Section);

    MS->emitBytes(SecData);
  }
}

/// Emit DIE containing warnings.
void DwarfStreamer::emitPaperTrailWarningsDie(DIE &Die) {
  switchToDebugInfoSection(/* Version */ 2);
  auto &Asm = getAsmPrinter();
  Asm.emitInt32(11 + Die.getSize() - 4);
  Asm.emitInt16(2);
  Asm.emitInt32(0);
  Asm.emitInt8(MC->getTargetTriple().isArch64Bit() ? 8 : 4);
  DebugInfoSectionSize += 11;
  emitDIE(Die);
}

/// Emit the debug_str section stored in \p Pool.
void DwarfStreamer::emitStrings(const NonRelocatableStringpool &Pool) {
  Asm->OutStreamer->switchSection(MOFI->getDwarfStrSection());
  std::vector<DwarfStringPoolEntryRef> Entries = Pool.getEntriesForEmission();
  for (auto Entry : Entries) {
    // Emit the string itself.
    Asm->OutStreamer->emitBytes(Entry.getString());
    // Emit a null terminator.
    Asm->emitInt8(0);
  }
}

/// Emit the debug_line_str section stored in \p Pool.
void DwarfStreamer::emitLineStrings(const NonRelocatableStringpool &Pool) {
  Asm->OutStreamer->switchSection(MOFI->getDwarfLineStrSection());
  std::vector<DwarfStringPoolEntryRef> Entries = Pool.getEntriesForEmission();
  for (auto Entry : Entries) {
    // Emit the string itself.
    Asm->OutStreamer->emitBytes(Entry.getString());
    // Emit a null terminator.
    Asm->emitInt8(0);
  }
}

void DwarfStreamer::emitDebugNames(
    AccelTable<DWARF5AccelTableStaticData> &Table) {
  if (EmittedUnits.empty())
    return;

  // Build up data structures needed to emit this section.
  std::vector<MCSymbol *> CompUnits;
  DenseMap<unsigned, size_t> UniqueIdToCuMap;
  unsigned Id = 0;
  for (auto &CU : EmittedUnits) {
    CompUnits.push_back(CU.LabelBegin);
    // We might be omitting CUs, so we need to remap them.
    UniqueIdToCuMap[CU.ID] = Id++;
  }

  Asm->OutStreamer->switchSection(MOFI->getDwarfDebugNamesSection());
  emitDWARF5AccelTable(
      Asm.get(), Table, CompUnits,
      [&UniqueIdToCuMap](const DWARF5AccelTableStaticData &Entry) {
        return UniqueIdToCuMap[Entry.getCUIndex()];
      });
}

void DwarfStreamer::emitAppleNamespaces(
    AccelTable<AppleAccelTableStaticOffsetData> &Table) {
  Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamespaceSection());
  auto *SectionBegin = Asm->createTempSymbol("namespac_begin");
  Asm->OutStreamer->emitLabel(SectionBegin);
  emitAppleAccelTable(Asm.get(), Table, "namespac", SectionBegin);
}

void DwarfStreamer::emitAppleNames(
    AccelTable<AppleAccelTableStaticOffsetData> &Table) {
  Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamesSection());
  auto *SectionBegin = Asm->createTempSymbol("names_begin");
  Asm->OutStreamer->emitLabel(SectionBegin);
  emitAppleAccelTable(Asm.get(), Table, "names", SectionBegin);
}

void DwarfStreamer::emitAppleObjc(
    AccelTable<AppleAccelTableStaticOffsetData> &Table) {
  Asm->OutStreamer->switchSection(MOFI->getDwarfAccelObjCSection());
  auto *SectionBegin = Asm->createTempSymbol("objc_begin");
  Asm->OutStreamer->emitLabel(SectionBegin);
  emitAppleAccelTable(Asm.get(), Table, "objc", SectionBegin);
}

void DwarfStreamer::emitAppleTypes(
    AccelTable<AppleAccelTableStaticTypeData> &Table) {
  Asm->OutStreamer->switchSection(MOFI->getDwarfAccelTypesSection());
  auto *SectionBegin = Asm->createTempSymbol("types_begin");
  Asm->OutStreamer->emitLabel(SectionBegin);
  emitAppleAccelTable(Asm.get(), Table, "types", SectionBegin);
}

/// Emit the swift_ast section stored in \p Buffers.
void DwarfStreamer::emitSwiftAST(StringRef Buffer) {
  MCSection *SwiftASTSection = MOFI->getDwarfSwiftASTSection();
  SwiftASTSection->setAlignment(Align(32));
  MS->switchSection(SwiftASTSection);
  MS->emitBytes(Buffer);
}

void DwarfStreamer::emitSwiftReflectionSection(
    llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind,
    StringRef Buffer, uint32_t Alignment, uint32_t Size) {
  MCSection *ReflectionSection =
      MOFI->getSwift5ReflectionSection(ReflSectionKind);
  if (ReflectionSection == nullptr)
    return;
  ReflectionSection->setAlignment(Align(Alignment));
  MS->switchSection(ReflectionSection);
  MS->emitBytes(Buffer);
}

void DwarfStreamer::emitDwarfDebugArangesTable(
    const CompileUnit &Unit, const AddressRanges &LinkedRanges) {
  unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();

  // Make .debug_aranges to be current section.
  MS->switchSection(MC->getObjectFileInfo()->getDwarfARangesSection());

  // Emit Header.
  MCSymbol *BeginLabel = Asm->createTempSymbol("Barange");
  MCSymbol *EndLabel = Asm->createTempSymbol("Earange");

  unsigned HeaderSize =
      sizeof(int32_t) + // Size of contents (w/o this field
      sizeof(int16_t) + // DWARF ARange version number
      sizeof(int32_t) + // Offset of CU in the .debug_info section
      sizeof(int8_t) +  // Pointer Size (in bytes)
      sizeof(int8_t);   // Segment Size (in bytes)

  unsigned TupleSize = AddressSize * 2;
  unsigned Padding = offsetToAlignment(HeaderSize, Align(TupleSize));

  Asm->emitLabelDifference(EndLabel, BeginLabel, 4); // Arange length
  Asm->OutStreamer->emitLabel(BeginLabel);
  Asm->emitInt16(dwarf::DW_ARANGES_VERSION); // Version number
  Asm->emitInt32(Unit.getStartOffset());     // Corresponding unit's offset
  Asm->emitInt8(AddressSize);                // Address size
  Asm->emitInt8(0);                          // Segment size

  Asm->OutStreamer->emitFill(Padding, 0x0);

  // Emit linked ranges.
  for (const AddressRange &Range : LinkedRanges) {
    MS->emitIntValue(Range.start(), AddressSize);
    MS->emitIntValue(Range.end() - Range.start(), AddressSize);
  }

  // Emit terminator.
  Asm->OutStreamer->emitIntValue(0, AddressSize);
  Asm->OutStreamer->emitIntValue(0, AddressSize);
  Asm->OutStreamer->emitLabel(EndLabel);
}

void DwarfStreamer::emitDwarfDebugRangesTableFragment(
    const CompileUnit &Unit, const AddressRanges &LinkedRanges,
    PatchLocation Patch) {
  Patch.set(RangesSectionSize);

  // Make .debug_ranges to be current section.
  MS->switchSection(MC->getObjectFileInfo()->getDwarfRangesSection());
  unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();

  // Emit ranges.
  uint64_t BaseAddress = 0;
  if (std::optional<uint64_t> LowPC = Unit.getLowPc())
    BaseAddress = *LowPC;

  for (const AddressRange &Range : LinkedRanges) {
    MS->emitIntValue(Range.start() - BaseAddress, AddressSize);
    MS->emitIntValue(Range.end() - BaseAddress, AddressSize);

    RangesSectionSize += AddressSize;
    RangesSectionSize += AddressSize;
  }

  // Add the terminator entry.
  MS->emitIntValue(0, AddressSize);
  MS->emitIntValue(0, AddressSize);

  RangesSectionSize += AddressSize;
  RangesSectionSize += AddressSize;
}

MCSymbol *
DwarfStreamer::emitDwarfDebugRangeListHeader(const CompileUnit &Unit) {
  if (Unit.getOrigUnit().getVersion() < 5)
    return nullptr;

  // Make .debug_rnglists to be current section.
  MS->switchSection(MC->getObjectFileInfo()->getDwarfRnglistsSection());

  MCSymbol *BeginLabel = Asm->createTempSymbol("Brnglists");
  MCSymbol *EndLabel = Asm->createTempSymbol("Ernglists");
  unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();

  // Length
  Asm->emitLabelDifference(EndLabel, BeginLabel, sizeof(uint32_t));
  Asm->OutStreamer->emitLabel(BeginLabel);
  RngListsSectionSize += sizeof(uint32_t);

  // Version.
  MS->emitInt16(5);
  RngListsSectionSize += sizeof(uint16_t);

  // Address size.
  MS->emitInt8(AddressSize);
  RngListsSectionSize++;

  // Seg_size
  MS->emitInt8(0);
  RngListsSectionSize++;

  // Offset entry count
  MS->emitInt32(0);
  RngListsSectionSize += sizeof(uint32_t);

  return EndLabel;
}

void DwarfStreamer::emitDwarfDebugRangeListFragment(
    const CompileUnit &Unit, const AddressRanges &LinkedRanges,
    PatchLocation Patch) {
  if (Unit.getOrigUnit().getVersion() < 5) {
    emitDwarfDebugRangesTableFragment(Unit, LinkedRanges, Patch);
    return;
  }

  emitDwarfDebugRngListsTableFragment(Unit, LinkedRanges, Patch);
}

void DwarfStreamer::emitDwarfDebugRangeListFooter(const CompileUnit &Unit,
                                                  MCSymbol *EndLabel) {
  if (Unit.getOrigUnit().getVersion() < 5)
    return;

  // Make .debug_rnglists to be current section.
  MS->switchSection(MC->getObjectFileInfo()->getDwarfRnglistsSection());

  if (EndLabel != nullptr)
    Asm->OutStreamer->emitLabel(EndLabel);
}

void DwarfStreamer::emitDwarfDebugRngListsTableFragment(
    const CompileUnit &Unit, const AddressRanges &LinkedRanges,
    PatchLocation Patch) {
  Patch.set(RngListsSectionSize);

  // Make .debug_rnglists to be current section.
  MS->switchSection(MC->getObjectFileInfo()->getDwarfRnglistsSection());

  unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();

  for (const AddressRange &Range : LinkedRanges) {
    // Emit type of entry.
    MS->emitInt8(dwarf::DW_RLE_start_length);
    RngListsSectionSize += 1;

    // Emit start address.
    MS->emitIntValue(Range.start(), AddressSize);
    RngListsSectionSize += AddressSize;

    // Emit length of the range.
    RngListsSectionSize += MS->emitSLEB128IntValue(Range.end() - Range.start());
  }

  // Emit the terminator entry.
  MS->emitInt8(dwarf::DW_RLE_end_of_list);
  RngListsSectionSize += 1;
}

/// Emit debug locations(.debug_loc, .debug_loclists) header.
MCSymbol *DwarfStreamer::emitDwarfDebugLocListHeader(const CompileUnit &Unit) {
  if (Unit.getOrigUnit().getVersion() < 5)
    return nullptr;

  // Make .debug_loclists the current section.
  MS->switchSection(MC->getObjectFileInfo()->getDwarfLoclistsSection());

  MCSymbol *BeginLabel = Asm->createTempSymbol("Bloclists");
  MCSymbol *EndLabel = Asm->createTempSymbol("Eloclists");
  unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();

  // Length
  Asm->emitLabelDifference(EndLabel, BeginLabel, sizeof(uint32_t));
  Asm->OutStreamer->emitLabel(BeginLabel);
  LocListsSectionSize += sizeof(uint32_t);

  // Version.
  MS->emitInt16(5);
  LocListsSectionSize += sizeof(uint16_t);

  // Address size.
  MS->emitInt8(AddressSize);
  LocListsSectionSize++;

  // Seg_size
  MS->emitInt8(0);
  LocListsSectionSize++;

  // Offset entry count
  MS->emitInt32(0);
  LocListsSectionSize += sizeof(uint32_t);

  return EndLabel;
}

/// Emit debug locations(.debug_loc, .debug_loclists) fragment.
void DwarfStreamer::emitDwarfDebugLocListFragment(
    const CompileUnit &Unit,
    const DWARFLocationExpressionsVector &LinkedLocationExpression,
    PatchLocation Patch) {
  if (Unit.getOrigUnit().getVersion() < 5) {
    emitDwarfDebugLocTableFragment(Unit, LinkedLocationExpression, Patch);
    return;
  }

  emitDwarfDebugLocListsTableFragment(Unit, LinkedLocationExpression, Patch);
}

/// Emit debug locations(.debug_loc, .debug_loclists) footer.
void DwarfStreamer::emitDwarfDebugLocListFooter(const CompileUnit &Unit,
                                                MCSymbol *EndLabel) {
  if (Unit.getOrigUnit().getVersion() < 5)
    return;

  // Make .debug_loclists the current section.
  MS->switchSection(MC->getObjectFileInfo()->getDwarfLoclistsSection());

  if (EndLabel != nullptr)
    Asm->OutStreamer->emitLabel(EndLabel);
}

/// Emit piece of .debug_loc for \p LinkedLocationExpression.
void DwarfStreamer::emitDwarfDebugLocTableFragment(
    const CompileUnit &Unit,
    const DWARFLocationExpressionsVector &LinkedLocationExpression,
    PatchLocation Patch) {
  Patch.set(LocSectionSize);

  // Make .debug_loc to be current section.
  MS->switchSection(MC->getObjectFileInfo()->getDwarfLocSection());
  unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();

  // Emit ranges.
  uint64_t BaseAddress = 0;
  if (std::optional<uint64_t> LowPC = Unit.getLowPc())
    BaseAddress = *LowPC;

  for (const DWARFLocationExpression &LocExpression :
       LinkedLocationExpression) {
    if (LocExpression.Range) {
      MS->emitIntValue(LocExpression.Range->LowPC - BaseAddress, AddressSize);
      MS->emitIntValue(LocExpression.Range->HighPC - BaseAddress, AddressSize);

      LocSectionSize += AddressSize;
      LocSectionSize += AddressSize;
    }

    Asm->OutStreamer->emitIntValue(LocExpression.Expr.size(), 2);
    Asm->OutStreamer->emitBytes(StringRef(
        (const char *)LocExpression.Expr.data(), LocExpression.Expr.size()));
    LocSectionSize += LocExpression.Expr.size() + 2;
  }

  // Add the terminator entry.
  MS->emitIntValue(0, AddressSize);
  MS->emitIntValue(0, AddressSize);

  LocSectionSize += AddressSize;
  LocSectionSize += AddressSize;
}

/// Emit piece of .debug_loclists for \p LinkedLocationExpression.
void DwarfStreamer::emitDwarfDebugLocListsTableFragment(
    const CompileUnit &Unit,
    const DWARFLocationExpressionsVector &LinkedLocationExpression,
    PatchLocation Patch) {
  Patch.set(LocListsSectionSize);

  // Make .debug_loclists the current section.
  MS->switchSection(MC->getObjectFileInfo()->getDwarfLoclistsSection());

  unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();

  for (const DWARFLocationExpression &LocExpression :
       LinkedLocationExpression) {
    if (LocExpression.Range) {
      // Emit type of entry.
      MS->emitInt8(dwarf::DW_LLE_start_length);
      LocListsSectionSize += 1;

      // Emit start address.
      MS->emitIntValue(LocExpression.Range->LowPC, AddressSize);
      LocListsSectionSize += AddressSize;

      // Emit length of the range.
      LocListsSectionSize += MS->emitSLEB128IntValue(
          LocExpression.Range->HighPC - LocExpression.Range->LowPC);
    } else {
      // Emit type of entry.
      MS->emitInt8(dwarf::DW_LLE_default_location);
      LocListsSectionSize += 1;
    }

    LocListsSectionSize += MS->emitULEB128IntValue(LocExpression.Expr.size());
    Asm->OutStreamer->emitBytes(StringRef(
        (const char *)LocExpression.Expr.data(), LocExpression.Expr.size()));
    LocListsSectionSize += LocExpression.Expr.size();
  }

  // Emit the terminator entry.
  MS->emitInt8(dwarf::DW_LLE_end_of_list);
  LocListsSectionSize += 1;
}

void DwarfStreamer::emitLineTableForUnit(
    const DWARFDebugLine::LineTable &LineTable, const CompileUnit &Unit,
    OffsetsStringPool &DebugStrPool, OffsetsStringPool &DebugLineStrPool) {
  // Switch to the section where the table will be emitted into.
  MS->switchSection(MC->getObjectFileInfo()->getDwarfLineSection());

  MCSymbol *LineStartSym = MC->createTempSymbol();
  MCSymbol *LineEndSym = MC->createTempSymbol();

  // unit_length.
  if (LineTable.Prologue.FormParams.Format == dwarf::DwarfFormat::DWARF64) {
    MS->emitInt32(dwarf::DW_LENGTH_DWARF64);
    LineSectionSize += 4;
  }
  emitLabelDifference(LineEndSym, LineStartSym,
                      LineTable.Prologue.FormParams.Format, LineSectionSize);
  Asm->OutStreamer->emitLabel(LineStartSym);

  // Emit prologue.
  emitLineTablePrologue(LineTable.Prologue, DebugStrPool, DebugLineStrPool);

  // Emit rows.
  emitLineTableRows(LineTable, LineEndSym,
                    Unit.getOrigUnit().getAddressByteSize());
}

void DwarfStreamer::emitLineTablePrologue(const DWARFDebugLine::Prologue &P,
                                          OffsetsStringPool &DebugStrPool,
                                          OffsetsStringPool &DebugLineStrPool) {
  MCSymbol *PrologueStartSym = MC->createTempSymbol();
  MCSymbol *PrologueEndSym = MC->createTempSymbol();

  // version (uhalf).
  MS->emitInt16(P.getVersion());
  LineSectionSize += 2;
  if (P.getVersion() == 5) {
    // address_size (ubyte).
    MS->emitInt8(P.getAddressSize());
    LineSectionSize += 1;

    // segment_selector_size (ubyte).
    MS->emitInt8(P.SegSelectorSize);
    LineSectionSize += 1;
  }

  // header_length.
  emitLabelDifference(PrologueEndSym, PrologueStartSym, P.FormParams.Format,
                      LineSectionSize);

  Asm->OutStreamer->emitLabel(PrologueStartSym);
  emitLineTableProloguePayload(P, DebugStrPool, DebugLineStrPool);
  Asm->OutStreamer->emitLabel(PrologueEndSym);
}

void DwarfStreamer::emitLineTablePrologueV2IncludeAndFileTable(
    const DWARFDebugLine::Prologue &P, OffsetsStringPool &DebugStrPool,
    OffsetsStringPool &DebugLineStrPool) {
  // include_directories (sequence of path names).
  for (const DWARFFormValue &Include : P.IncludeDirectories)
    emitLineTableString(P, Include, DebugStrPool, DebugLineStrPool);
  // The last entry is followed by a single null byte.
  MS->emitInt8(0);
  LineSectionSize += 1;

  // file_names (sequence of file entries).
  for (const DWARFDebugLine::FileNameEntry &File : P.FileNames) {
    // A null-terminated string containing the full or relative path name of a
    // source file.
    emitLineTableString(P, File.Name, DebugStrPool, DebugLineStrPool);
    // An unsigned LEB128 number representing the directory index of a directory
    // in the include_directories section.
    LineSectionSize += MS->emitULEB128IntValue(File.DirIdx);
    // An unsigned LEB128 number representing the (implementation-defined) time
    // of last modification for the file, or 0 if not available.
    LineSectionSize += MS->emitULEB128IntValue(File.ModTime);
    // An unsigned LEB128 number representing the length in bytes of the file,
    // or 0 if not available.
    LineSectionSize += MS->emitULEB128IntValue(File.Length);
  }
  // The last entry is followed by a single null byte.
  MS->emitInt8(0);
  LineSectionSize += 1;
}

void DwarfStreamer::emitLineTablePrologueV5IncludeAndFileTable(
    const DWARFDebugLine::Prologue &P, OffsetsStringPool &DebugStrPool,
    OffsetsStringPool &DebugLineStrPool) {
  if (P.IncludeDirectories.empty()) {
    // directory_entry_format_count(ubyte).
    MS->emitInt8(0);
    LineSectionSize += 1;
  } else {
    // directory_entry_format_count(ubyte).
    MS->emitInt8(1);
    LineSectionSize += 1;

    // directory_entry_format (sequence of ULEB128 pairs).
    LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_path);
    LineSectionSize +=
        MS->emitULEB128IntValue(P.IncludeDirectories[0].getForm());
  }

  // directories_count (ULEB128).
  LineSectionSize += MS->emitULEB128IntValue(P.IncludeDirectories.size());
  // directories (sequence of directory names).
  for (auto Include : P.IncludeDirectories)
    emitLineTableString(P, Include, DebugStrPool, DebugLineStrPool);

  if (P.FileNames.empty()) {
    // file_name_entry_format_count (ubyte).
    MS->emitInt8(0);
    LineSectionSize += 1;
  } else {
    // file_name_entry_format_count (ubyte).
    MS->emitInt8(2);
    LineSectionSize += 1;

    // file_name_entry_format (sequence of ULEB128 pairs).
    LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_path);
    LineSectionSize += MS->emitULEB128IntValue(P.FileNames[0].Name.getForm());

    LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_directory_index);
    LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_FORM_data1);
  }

  // file_names_count (ULEB128).
  LineSectionSize += MS->emitULEB128IntValue(P.FileNames.size());

  // file_names (sequence of file name entries).
  for (auto File : P.FileNames) {
    emitLineTableString(P, File.Name, DebugStrPool, DebugLineStrPool);
    MS->emitInt8(File.DirIdx);
    LineSectionSize += 1;
  }
}

void DwarfStreamer::emitLineTableString(const DWARFDebugLine::Prologue &P,
                                        const DWARFFormValue &String,
                                        OffsetsStringPool &DebugStrPool,
                                        OffsetsStringPool &DebugLineStrPool) {
  std::optional<const char *> StringVal = dwarf::toString(String);
  if (!StringVal) {
    warn("Cann't read string from line table.");
    return;
  }

  switch (String.getForm()) {
  case dwarf::DW_FORM_string: {
    StringRef TranslatedString =
        (Translator) ? Translator(*StringVal) : *StringVal;
    Asm->OutStreamer->emitBytes(TranslatedString.data());
    Asm->emitInt8(0);
    LineSectionSize += TranslatedString.size() + 1;
  } break;
  case dwarf::DW_FORM_strp:
  case dwarf::DW_FORM_line_strp: {
    DwarfStringPoolEntryRef StringRef =
        String.getForm() == dwarf::DW_FORM_strp
            ? DebugStrPool.getEntry(*StringVal)
            : DebugLineStrPool.getEntry(*StringVal);

    emitIntOffset(StringRef.getOffset(), P.FormParams.Format, LineSectionSize);
  } break;
  default:
    warn("Unsupported string form inside line table.");
    break;
  };
}

void DwarfStreamer::emitLineTableProloguePayload(
    const DWARFDebugLine::Prologue &P, OffsetsStringPool &DebugStrPool,
    OffsetsStringPool &DebugLineStrPool) {
  // minimum_instruction_length (ubyte).
  MS->emitInt8(P.MinInstLength);
  LineSectionSize += 1;
  if (P.FormParams.Version >= 4) {
    // maximum_operations_per_instruction (ubyte).
    MS->emitInt8(P.MaxOpsPerInst);
    LineSectionSize += 1;
  }
  // default_is_stmt (ubyte).
  MS->emitInt8(P.DefaultIsStmt);
  LineSectionSize += 1;
  // line_base (sbyte).
  MS->emitInt8(P.LineBase);
  LineSectionSize += 1;
  // line_range (ubyte).
  MS->emitInt8(P.LineRange);
  LineSectionSize += 1;
  // opcode_base (ubyte).
  MS->emitInt8(P.OpcodeBase);
  LineSectionSize += 1;

  // standard_opcode_lengths (array of ubyte).
  for (auto Length : P.StandardOpcodeLengths) {
    MS->emitInt8(Length);
    LineSectionSize += 1;
  }

  if (P.FormParams.Version < 5)
    emitLineTablePrologueV2IncludeAndFileTable(P, DebugStrPool,
                                               DebugLineStrPool);
  else
    emitLineTablePrologueV5IncludeAndFileTable(P, DebugStrPool,
                                               DebugLineStrPool);
}

void DwarfStreamer::emitLineTableRows(
    const DWARFDebugLine::LineTable &LineTable, MCSymbol *LineEndSym,
    unsigned AddressByteSize) {

  MCDwarfLineTableParams Params;
  Params.DWARF2LineOpcodeBase = LineTable.Prologue.OpcodeBase;
  Params.DWARF2LineBase = LineTable.Prologue.LineBase;
  Params.DWARF2LineRange = LineTable.Prologue.LineRange;

  SmallString<128> EncodingBuffer;

  if (LineTable.Rows.empty()) {
    // We only have the dummy entry, dsymutil emits an entry with a 0
    // address in that case.
    MCDwarfLineAddr::encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0,
                            EncodingBuffer);
    MS->emitBytes(EncodingBuffer);
    LineSectionSize += EncodingBuffer.size();
    MS->emitLabel(LineEndSym);
    return;
  }

  // Line table state machine fields
  unsigned FileNum = 1;
  unsigned LastLine = 1;
  unsigned Column = 0;
  unsigned IsStatement = 1;
  unsigned Isa = 0;
  uint64_t Address = -1ULL;

  unsigned RowsSinceLastSequence = 0;

  for (const DWARFDebugLine::Row &Row : LineTable.Rows) {
    int64_t AddressDelta;
    if (Address == -1ULL) {
      MS->emitIntValue(dwarf::DW_LNS_extended_op, 1);
      MS->emitULEB128IntValue(AddressByteSize + 1);
      MS->emitIntValue(dwarf::DW_LNE_set_address, 1);
      MS->emitIntValue(Row.Address.Address, AddressByteSize);
      LineSectionSize +=
          2 + AddressByteSize + getULEB128Size(AddressByteSize + 1);
      AddressDelta = 0;
    } else {
      AddressDelta =
          (Row.Address.Address - Address) / LineTable.Prologue.MinInstLength;
    }

    // FIXME: code copied and transformed from MCDwarf.cpp::EmitDwarfLineTable.
    // We should find a way to share this code, but the current compatibility
    // requirement with classic dsymutil makes it hard. Revisit that once this
    // requirement is dropped.

    if (FileNum != Row.File) {
      FileNum = Row.File;
      MS->emitIntValue(dwarf::DW_LNS_set_file, 1);
      MS->emitULEB128IntValue(FileNum);
      LineSectionSize += 1 + getULEB128Size(FileNum);
    }
    if (Column != Row.Column) {
      Column = Row.Column;
      MS->emitIntValue(dwarf::DW_LNS_set_column, 1);
      MS->emitULEB128IntValue(Column);
      LineSectionSize += 1 + getULEB128Size(Column);
    }

    // FIXME: We should handle the discriminator here, but dsymutil doesn't
    // consider it, thus ignore it for now.

    if (Isa != Row.Isa) {
      Isa = Row.Isa;
      MS->emitIntValue(dwarf::DW_LNS_set_isa, 1);
      MS->emitULEB128IntValue(Isa);
      LineSectionSize += 1 + getULEB128Size(Isa);
    }
    if (IsStatement != Row.IsStmt) {
      IsStatement = Row.IsStmt;
      MS->emitIntValue(dwarf::DW_LNS_negate_stmt, 1);
      LineSectionSize += 1;
    }
    if (Row.BasicBlock) {
      MS->emitIntValue(dwarf::DW_LNS_set_basic_block, 1);
      LineSectionSize += 1;
    }

    if (Row.PrologueEnd) {
      MS->emitIntValue(dwarf::DW_LNS_set_prologue_end, 1);
      LineSectionSize += 1;
    }

    if (Row.EpilogueBegin) {
      MS->emitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1);
      LineSectionSize += 1;
    }

    int64_t LineDelta = int64_t(Row.Line) - LastLine;
    if (!Row.EndSequence) {
      MCDwarfLineAddr::encode(*MC, Params, LineDelta, AddressDelta,
                              EncodingBuffer);
      MS->emitBytes(EncodingBuffer);
      LineSectionSize += EncodingBuffer.size();
      EncodingBuffer.resize(0);
      Address = Row.Address.Address;
      LastLine = Row.Line;
      RowsSinceLastSequence++;
    } else {
      if (LineDelta) {
        MS->emitIntValue(dwarf::DW_LNS_advance_line, 1);
        MS->emitSLEB128IntValue(LineDelta);
        LineSectionSize += 1 + getSLEB128Size(LineDelta);
      }
      if (AddressDelta) {
        MS->emitIntValue(dwarf::DW_LNS_advance_pc, 1);
        MS->emitULEB128IntValue(AddressDelta);
        LineSectionSize += 1 + getULEB128Size(AddressDelta);
      }
      MCDwarfLineAddr::encode(*MC, Params, std::numeric_limits<int64_t>::max(),
                              0, EncodingBuffer);
      MS->emitBytes(EncodingBuffer);
      LineSectionSize += EncodingBuffer.size();
      EncodingBuffer.resize(0);
      Address = -1ULL;
      LastLine = FileNum = IsStatement = 1;
      RowsSinceLastSequence = Column = Isa = 0;
    }
  }

  if (RowsSinceLastSequence) {
    MCDwarfLineAddr::encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0,
                            EncodingBuffer);
    MS->emitBytes(EncodingBuffer);
    LineSectionSize += EncodingBuffer.size();
    EncodingBuffer.resize(0);
  }

  MS->emitLabel(LineEndSym);
}

void DwarfStreamer::emitIntOffset(uint64_t Offset, dwarf::DwarfFormat Format,
                                  uint64_t &SectionSize) {
  uint8_t Size = dwarf::getDwarfOffsetByteSize(Format);
  MS->emitIntValue(Offset, Size);
  SectionSize += Size;
}

void DwarfStreamer::emitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo,
                                        dwarf::DwarfFormat Format,
                                        uint64_t &SectionSize) {
  uint8_t Size = dwarf::getDwarfOffsetByteSize(Format);
  Asm->emitLabelDifference(Hi, Lo, Size);
  SectionSize += Size;
}

/// Emit the pubnames or pubtypes section contribution for \p
/// Unit into \p Sec. The data is provided in \p Names.
void DwarfStreamer::emitPubSectionForUnit(
    MCSection *Sec, StringRef SecName, const CompileUnit &Unit,
    const std::vector<CompileUnit::AccelInfo> &Names) {
  if (Names.empty())
    return;

  // Start the dwarf pubnames section.
  Asm->OutStreamer->switchSection(Sec);
  MCSymbol *BeginLabel = Asm->createTempSymbol("pub" + SecName + "_begin");
  MCSymbol *EndLabel = Asm->createTempSymbol("pub" + SecName + "_end");

  bool HeaderEmitted = false;
  // Emit the pubnames for this compilation unit.
  for (const auto &Name : Names) {
    if (Name.SkipPubSection)
      continue;

    if (!HeaderEmitted) {
      // Emit the header.
      Asm->emitLabelDifference(EndLabel, BeginLabel, 4); // Length
      Asm->OutStreamer->emitLabel(BeginLabel);
      Asm->emitInt16(dwarf::DW_PUBNAMES_VERSION); // Version
      Asm->emitInt32(Unit.getStartOffset());      // Unit offset
      Asm->emitInt32(Unit.getNextUnitOffset() - Unit.getStartOffset()); // Size
      HeaderEmitted = true;
    }
    Asm->emitInt32(Name.Die->getOffset());

    // Emit the string itself.
    Asm->OutStreamer->emitBytes(Name.Name.getString());
    // Emit a null terminator.
    Asm->emitInt8(0);
  }

  if (!HeaderEmitted)
    return;
  Asm->emitInt32(0); // End marker.
  Asm->OutStreamer->emitLabel(EndLabel);
}

/// Emit .debug_pubnames for \p Unit.
void DwarfStreamer::emitPubNamesForUnit(const CompileUnit &Unit) {
  emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubNamesSection(),
                        "names", Unit, Unit.getPubnames());
}

/// Emit .debug_pubtypes for \p Unit.
void DwarfStreamer::emitPubTypesForUnit(const CompileUnit &Unit) {
  emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubTypesSection(),
                        "types", Unit, Unit.getPubtypes());
}

/// Emit a CIE into the debug_frame section.
void DwarfStreamer::emitCIE(StringRef CIEBytes) {
  MS->switchSection(MC->getObjectFileInfo()->getDwarfFrameSection());

  MS->emitBytes(CIEBytes);
  FrameSectionSize += CIEBytes.size();
}

/// Emit a FDE into the debug_frame section. \p FDEBytes
/// contains the FDE data without the length, CIE offset and address
/// which will be replaced with the parameter values.
void DwarfStreamer::emitFDE(uint32_t CIEOffset, uint32_t AddrSize,
                            uint64_t Address, StringRef FDEBytes) {
  MS->switchSection(MC->getObjectFileInfo()->getDwarfFrameSection());

  MS->emitIntValue(FDEBytes.size() + 4 + AddrSize, 4);
  MS->emitIntValue(CIEOffset, 4);
  MS->emitIntValue(Address, AddrSize);
  MS->emitBytes(FDEBytes);
  FrameSectionSize += FDEBytes.size() + 8 + AddrSize;
}

void DwarfStreamer::emitMacroTables(DWARFContext *Context,
                                    const Offset2UnitMap &UnitMacroMap,
                                    OffsetsStringPool &StringPool) {
  assert(Context != nullptr && "Empty DWARF context");

  // Check for .debug_macinfo table.
  if (const DWARFDebugMacro *Table = Context->getDebugMacinfo()) {
    MS->switchSection(MC->getObjectFileInfo()->getDwarfMacinfoSection());
    emitMacroTableImpl(Table, UnitMacroMap, StringPool, MacInfoSectionSize);
  }

  // Check for .debug_macro table.
  if (const DWARFDebugMacro *Table = Context->getDebugMacro()) {
    MS->switchSection(MC->getObjectFileInfo()->getDwarfMacroSection());
    emitMacroTableImpl(Table, UnitMacroMap, StringPool, MacroSectionSize);
  }
}

void DwarfStreamer::emitMacroTableImpl(const DWARFDebugMacro *MacroTable,
                                       const Offset2UnitMap &UnitMacroMap,
                                       OffsetsStringPool &StringPool,
                                       uint64_t &OutOffset) {
  bool DefAttributeIsReported = false;
  bool UndefAttributeIsReported = false;
  bool ImportAttributeIsReported = false;
  for (const DWARFDebugMacro::MacroList &List : MacroTable->MacroLists) {
    Offset2UnitMap::const_iterator UnitIt = UnitMacroMap.find(List.Offset);
    if (UnitIt == UnitMacroMap.end()) {
      warn(formatv(
          "couldn`t find compile unit for the macro table with offset = {0:x}",
          List.Offset));
      continue;
    }

    // Skip macro table if the unit was not cloned.
    DIE *OutputUnitDIE = UnitIt->second->getOutputUnitDIE();
    if (OutputUnitDIE == nullptr)
      continue;

    // Update macro attribute of cloned compile unit with the proper offset to
    // the macro table.
    bool hasDWARFv5Header = false;
    for (auto &V : OutputUnitDIE->values()) {
      if (V.getAttribute() == dwarf::DW_AT_macro_info) {
        V = DIEValue(V.getAttribute(), V.getForm(), DIEInteger(OutOffset));
        break;
      } else if (V.getAttribute() == dwarf::DW_AT_macros) {
        hasDWARFv5Header = true;
        V = DIEValue(V.getAttribute(), V.getForm(), DIEInteger(OutOffset));
        break;
      }
    }

    // Write DWARFv5 header.
    if (hasDWARFv5Header) {
      // Write header version.
      MS->emitIntValue(List.Header.Version, sizeof(List.Header.Version));
      OutOffset += sizeof(List.Header.Version);

      uint8_t Flags = List.Header.Flags;

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

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

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

      // Write flags.
      MS->emitIntValue(Flags, sizeof(Flags));
      OutOffset += sizeof(Flags);

      // Write offset to line table.
      if (StmtListOffset) {
        MS->emitIntValue(*StmtListOffset, List.Header.getOffsetByteSize());
        OutOffset += List.Header.getOffsetByteSize();
      }
    }

    // Write macro entries.
    for (const DWARFDebugMacro::Entry &MacroEntry : List.Macros) {
      if (MacroEntry.Type == 0) {
        OutOffset += MS->emitULEB128IntValue(MacroEntry.Type);
        continue;
      }

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

        if (HasVendorSpecificExtension) {
          // Write macinfo type.
          MS->emitIntValue(MacroType, 1);
          OutOffset++;

          // Write vendor extension constant.
          OutOffset += MS->emitULEB128IntValue(MacroEntry.ExtConstant);

          // Write vendor extension string.
          StringRef String = MacroEntry.ExtStr;
          MS->emitBytes(String);
          MS->emitIntValue(0, 1);
          OutOffset += String.size() + 1;
        } else
          warn("unknown macro type. skip.");
      } break;
      // debug_macro and debug_macinfo share some common encodings.
      // DW_MACRO_define     == DW_MACINFO_define
      // DW_MACRO_undef      == DW_MACINFO_undef
      // DW_MACRO_start_file == DW_MACINFO_start_file
      // DW_MACRO_end_file   == DW_MACINFO_end_file
      // For readibility/uniformity we are using DW_MACRO_*.
      case dwarf::DW_MACRO_define:
      case dwarf::DW_MACRO_undef: {
        // Write macinfo type.
        MS->emitIntValue(MacroType, 1);
        OutOffset++;

        // Write source line.
        OutOffset += MS->emitULEB128IntValue(MacroEntry.Line);

        // Write macro string.
        StringRef String = MacroEntry.MacroStr;
        MS->emitBytes(String);
        MS->emitIntValue(0, 1);
        OutOffset += String.size() + 1;
      } break;
      case dwarf::DW_MACRO_define_strp:
      case dwarf::DW_MACRO_undef_strp:
      case dwarf::DW_MACRO_define_strx:
      case dwarf::DW_MACRO_undef_strx: {
        assert(UnitIt->second->getOrigUnit().getVersion() >= 5);

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

        // Write macinfo type.
        MS->emitIntValue(MacroType, 1);
        OutOffset++;

        // Write source line.
        OutOffset += MS->emitULEB128IntValue(MacroEntry.Line);

        // Write macro string.
        DwarfStringPoolEntryRef EntryRef =
            StringPool.getEntry(MacroEntry.MacroStr);
        MS->emitIntValue(EntryRef.getOffset(), List.Header.getOffsetByteSize());
        OutOffset += List.Header.getOffsetByteSize();
        break;
      }
      case dwarf::DW_MACRO_start_file: {
        // Write macinfo type.
        MS->emitIntValue(MacroType, 1);
        OutOffset++;
        // Write source line.
        OutOffset += MS->emitULEB128IntValue(MacroEntry.Line);
        // Write source file id.
        OutOffset += MS->emitULEB128IntValue(MacroEntry.File);
      } break;
      case dwarf::DW_MACRO_end_file: {
        // Write macinfo type.
        MS->emitIntValue(MacroType, 1);
        OutOffset++;
      } break;
      case dwarf::DW_MACRO_import:
      case dwarf::DW_MACRO_import_sup: {
        if (!ImportAttributeIsReported) {
          warn("DW_MACRO_import and DW_MACRO_import_sup are unsupported yet. "
               "remove.");
          ImportAttributeIsReported = true;
        }
      } break;
      }
    }
  }
}

} // namespace llvm
