//===- 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/ADT/Triple.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"

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;
  LocSectionSize = 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())
          .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);
  }

#if 0
  if (DwarfVersion >= 5) {
    // Emit an empty string offset section.
    Asm->OutStreamer->switchSection(MOFI->getDwarfStrOffSection());
    Asm->emitDwarfUnitLength(4, "Length of String Offsets Set");
    Asm->emitInt16(DwarfVersion);
    Asm->emitInt16(0);
  }
#endif
}

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) {
  unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();

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

  // 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;
}

/// Emit the debug_aranges contribution of a unit and
/// if \p DoDebugRanges is true the debug_range contents for a
/// compile_unit level DW_AT_ranges attribute (Which are basically the
/// same thing with a different base address).
/// Just aggregate all the ranges gathered inside that unit.
void DwarfStreamer::emitUnitRangesEntries(CompileUnit &Unit,
                                          bool DoDebugRanges) {
  const RangesTy &FunctionRanges = Unit.getFunctionRanges();

  // Linked addresses might end up in a different order.
  // Build linked address ranges.
  AddressRanges LinkedRanges;
  for (size_t Idx = 0; Idx < FunctionRanges.size(); Idx++)
    LinkedRanges.insert(
        {FunctionRanges[Idx].first.start() + FunctionRanges[Idx].second,
         FunctionRanges[Idx].first.end() + FunctionRanges[Idx].second});

  if (!FunctionRanges.empty())
    emitDwarfDebugArangesTable(Unit, LinkedRanges);

  if (DoDebugRanges)
    emitDwarfDebugRangesTableFragment(Unit, LinkedRanges);
}

/// Emit location lists for \p Unit and update attributes to point to the new
/// entries.
void DwarfStreamer::emitLocationsForUnit(
    const CompileUnit &Unit, DWARFContext &Dwarf,
    std::function<void(StringRef, SmallVectorImpl<uint8_t> &)> ProcessExpr) {
  const auto &Attributes = Unit.getLocationAttributes();

  if (Attributes.empty())
    return;

  MS->switchSection(MC->getObjectFileInfo()->getDwarfLocSection());

  unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
  uint64_t BaseAddressMarker = (AddressSize == 8)
                                   ? std::numeric_limits<uint64_t>::max()
                                   : std::numeric_limits<uint32_t>::max();
  const DWARFSection &InputSec = Dwarf.getDWARFObj().getLocSection();
  DataExtractor Data(InputSec.Data, Dwarf.isLittleEndian(), AddressSize);
  DWARFUnit &OrigUnit = Unit.getOrigUnit();
  auto OrigUnitDie = OrigUnit.getUnitDIE(false);
  int64_t UnitPcOffset = 0;
  if (auto OrigLowPc =
          dwarf::toAddress(OrigUnitDie.find(dwarf::DW_AT_low_pc))) {
    assert(Unit.getLowPc());
    UnitPcOffset = int64_t(*OrigLowPc) - *Unit.getLowPc();
  }

  SmallVector<uint8_t, 32> Buffer;
  for (const auto &Attr : Attributes) {
    uint64_t Offset = Attr.first.get();
    Attr.first.set(LocSectionSize);
    // This is the quantity to add to the old location address to get
    // the correct address for the new one.
    int64_t LocPcOffset = Attr.second + UnitPcOffset;
    while (Data.isValidOffset(Offset)) {
      uint64_t Low = Data.getUnsigned(&Offset, AddressSize);
      uint64_t High = Data.getUnsigned(&Offset, AddressSize);
      LocSectionSize += 2 * AddressSize;
      // End of list entry.
      if (Low == 0 && High == 0) {
        Asm->OutStreamer->emitIntValue(0, AddressSize);
        Asm->OutStreamer->emitIntValue(0, AddressSize);
        break;
      }
      // Base address selection entry.
      if (Low == BaseAddressMarker) {
        Asm->OutStreamer->emitIntValue(BaseAddressMarker, AddressSize);
        Asm->OutStreamer->emitIntValue(High + Attr.second, AddressSize);
        LocPcOffset = 0;
        continue;
      }
      // Location list entry.
      Asm->OutStreamer->emitIntValue(Low + LocPcOffset, AddressSize);
      Asm->OutStreamer->emitIntValue(High + LocPcOffset, AddressSize);
      uint64_t Length = Data.getU16(&Offset);
      Asm->OutStreamer->emitIntValue(Length, 2);
      // Copy the bytes into to the buffer, process them, emit them.
      Buffer.reserve(Length);
      Buffer.resize(0);
      StringRef Input = InputSec.Data.substr(Offset, Length);
      ProcessExpr(Input, Buffer);
      Asm->OutStreamer->emitBytes(
          StringRef((const char *)Buffer.data(), Length));
      Offset += Length;
      LocSectionSize += Length + 2;
    }
  }
}

void DwarfStreamer::emitLineTableForUnit(MCDwarfLineTableParams Params,
                                         StringRef PrologueBytes,
                                         unsigned MinInstLength,
                                         std::vector<DWARFDebugLine::Row> &Rows,
                                         unsigned PointerSize) {
  // Switch to the section where the table will be emitted into.
  MS->switchSection(MC->getObjectFileInfo()->getDwarfLineSection());
  MCSymbol *LineStartSym = MC->createTempSymbol();
  MCSymbol *LineEndSym = MC->createTempSymbol();

  // The first 4 bytes is the total length of the information for this
  // compilation unit (not including these 4 bytes for the length).
  Asm->emitLabelDifference(LineEndSym, LineStartSym, 4);
  Asm->OutStreamer->emitLabel(LineStartSym);
  // Copy Prologue.
  MS->emitBytes(PrologueBytes);
  LineSectionSize += PrologueBytes.size() + 4;

  SmallString<128> EncodingBuffer;
  raw_svector_ostream EncodingOS(EncodingBuffer);

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

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

  unsigned RowsSinceLastSequence = 0;

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

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

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

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

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

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

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

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

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

  MS->emitLabel(LineEndSym);
}

/// Copy the debug_line over to the updated binary while unobfuscating the file
/// names and directories.
void DwarfStreamer::translateLineTable(DataExtractor Data, uint64_t Offset) {
  MS->switchSection(MC->getObjectFileInfo()->getDwarfLineSection());
  StringRef Contents = Data.getData();

  // We have to deconstruct the line table header, because it contains to
  // length fields that will need to be updated when we change the length of
  // the files and directories in there.
  unsigned UnitLength = Data.getU32(&Offset);
  uint64_t UnitEnd = Offset + UnitLength;
  MCSymbol *BeginLabel = MC->createTempSymbol();
  MCSymbol *EndLabel = MC->createTempSymbol();
  unsigned Version = Data.getU16(&Offset);

  if (Version > 5) {
    warn("Unsupported line table version: dropping contents and not "
         "unobfsucating line table.");
    return;
  }

  Asm->emitLabelDifference(EndLabel, BeginLabel, 4);
  Asm->OutStreamer->emitLabel(BeginLabel);
  Asm->emitInt16(Version);
  LineSectionSize += 6;

  MCSymbol *HeaderBeginLabel = MC->createTempSymbol();
  MCSymbol *HeaderEndLabel = MC->createTempSymbol();
  Asm->emitLabelDifference(HeaderEndLabel, HeaderBeginLabel, 4);
  Asm->OutStreamer->emitLabel(HeaderBeginLabel);
  Offset += 4;
  LineSectionSize += 4;

  uint64_t AfterHeaderLengthOffset = Offset;
  // Skip to the directories.
  Offset += (Version >= 4) ? 5 : 4;
  unsigned OpcodeBase = Data.getU8(&Offset);
  Offset += OpcodeBase - 1;
  Asm->OutStreamer->emitBytes(Contents.slice(AfterHeaderLengthOffset, Offset));
  LineSectionSize += Offset - AfterHeaderLengthOffset;

  // Offset points to the first directory.
  while (const char *Dir = Data.getCStr(&Offset)) {
    if (Dir[0] == 0)
      break;

    StringRef Translated = Translator(Dir);
    Asm->OutStreamer->emitBytes(Translated);
    Asm->emitInt8(0);
    LineSectionSize += Translated.size() + 1;
  }
  Asm->emitInt8(0);
  LineSectionSize += 1;

  while (const char *File = Data.getCStr(&Offset)) {
    if (File[0] == 0)
      break;

    StringRef Translated = Translator(File);
    Asm->OutStreamer->emitBytes(Translated);
    Asm->emitInt8(0);
    LineSectionSize += Translated.size() + 1;

    uint64_t OffsetBeforeLEBs = Offset;
    Asm->emitULEB128(Data.getULEB128(&Offset));
    Asm->emitULEB128(Data.getULEB128(&Offset));
    Asm->emitULEB128(Data.getULEB128(&Offset));
    LineSectionSize += Offset - OffsetBeforeLEBs;
  }
  Asm->emitInt8(0);
  LineSectionSize += 1;

  Asm->OutStreamer->emitLabel(HeaderEndLabel);

  // Copy the actual line table program over.
  Asm->OutStreamer->emitBytes(Contents.slice(Offset, UnitEnd));
  LineSectionSize += UnitEnd - Offset;

  Asm->OutStreamer->emitLabel(EndLabel);
  Offset = UnitEnd;
}

/// 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
