//===- DebugLineSectionEmitter.h --------------------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIB_DWARFLINKERPARALLEL_DEBUGLINESECTIONEMITTER_H
#define LLVM_LIB_DWARFLINKERPARALLEL_DEBUGLINESECTIONEMITTER_H

#include "DWARFEmitterImpl.h"
#include "llvm/DWARFLinkerParallel/AddressesMap.h"
#include "llvm/DWARFLinkerParallel/DWARFLinker.h"
#include "llvm/DebugInfo/DWARF/DWARFObject.h"
#include "llvm/MC/MCTargetOptionsCommandFlags.h"
#include "llvm/MC/TargetRegistry.h"

namespace llvm {
namespace dwarflinker_parallel {

/// This class emits specified line table into the .debug_line section.
class DebugLineSectionEmitter {
public:
  DebugLineSectionEmitter(const Triple &TheTriple, DwarfUnit &U)
      : TheTriple(TheTriple), U(U) {}

  Error emit(const DWARFDebugLine::LineTable &LineTable) {
    // FIXME: remove dependence on MCDwarfLineAddr::encode.
    // As we reuse MCDwarfLineAddr::encode, we need to create/initialize
    // some MC* classes.
    if (Error Err = init(TheTriple))
      return Err;

    // Get descriptor for output .debug_line section.
    SectionDescriptor &OutSection =
        U.getOrCreateSectionDescriptor(DebugSectionKind::DebugLine);

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

    // Emit prologue.
    emitLineTablePrologue(LineTable.Prologue, OutSection);

    // Emit rows.
    emitLineTableRows(LineTable, OutSection);
    uint64_t OffsetAfterEnd = OutSection.OS.tell();

    // Update unit length field with actual length value.
    assert(OffsetAfterUnitLength -
               OutSection.getFormParams().getDwarfOffsetByteSize() <
           OffsetAfterUnitLength);
    OutSection.apply(OffsetAfterUnitLength -
                         OutSection.getFormParams().getDwarfOffsetByteSize(),
                     dwarf::DW_FORM_sec_offset,
                     OffsetAfterEnd - OffsetAfterUnitLength);

    return Error::success();
  }

private:
  Error init(Triple TheTriple) {
    std::string ErrorStr;
    std::string TripleName;

    // Get the target.
    const Target *TheTarget =
        TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr);
    if (!TheTarget)
      return createStringError(std::errc::invalid_argument, ErrorStr.c_str());
    TripleName = TheTriple.getTriple();

    // Create all the MC Objects.
    MRI.reset(TheTarget->createMCRegInfo(TripleName));
    if (!MRI)
      return createStringError(std::errc::invalid_argument,
                               "no register info for target %s",
                               TripleName.c_str());

    MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();
    MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
    if (!MAI)
      return createStringError(std::errc::invalid_argument,
                               "no asm info for target %s", TripleName.c_str());

    MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
    if (!MSTI)
      return createStringError(std::errc::invalid_argument,
                               "no subtarget info for target %s",
                               TripleName.c_str());

    MC.reset(new MCContext(TheTriple, MAI.get(), MRI.get(), MSTI.get(), nullptr,
                           nullptr, true, "__DWARF"));

    return Error::success();
  }

  void emitLineTablePrologue(const DWARFDebugLine::Prologue &P,
                             SectionDescriptor &Section) {
    // version (uhalf).
    Section.emitIntVal(P.getVersion(), 2);
    if (P.getVersion() == 5) {
      // address_size (ubyte).
      Section.emitIntVal(P.getAddressSize(), 1);

      // segment_selector_size (ubyte).
      Section.emitIntVal(P.SegSelectorSize, 1);
    }

    // header_length.
    Section.emitOffset(0xBADDEF);

    uint64_t OffsetAfterPrologueLength = Section.OS.tell();
    emitLineTableProloguePayload(P, Section);
    uint64_t OffsetAfterPrologueEnd = Section.OS.tell();

    // Update prologue length field with actual length value.
    Section.apply(OffsetAfterPrologueLength -
                      Section.getFormParams().getDwarfOffsetByteSize(),
                  dwarf::DW_FORM_sec_offset,
                  OffsetAfterPrologueEnd - OffsetAfterPrologueLength);
  }

  void
  emitLineTablePrologueV2IncludeAndFileTable(const DWARFDebugLine::Prologue &P,
                                             SectionDescriptor &Section) {
    // include_directories (sequence of path names).
    for (const DWARFFormValue &Include : P.IncludeDirectories) {
      std::optional<const char *> IncludeStr = dwarf::toString(Include);
      if (!IncludeStr) {
        U.warn("cann't read string from line table.");
        return;
      }

      Section.emitString(Include.getForm(), *IncludeStr);
    }
    // The last entry is followed by a single null byte.
    Section.emitIntVal(0, 1);

    // file_names (sequence of file entries).
    for (const DWARFDebugLine::FileNameEntry &File : P.FileNames) {
      std::optional<const char *> FileNameStr = dwarf::toString(File.Name);
      if (!FileNameStr) {
        U.warn("cann't read string from line table.");
        return;
      }

      // A null-terminated string containing the full or relative path name of a
      // source file.
      Section.emitString(File.Name.getForm(), *FileNameStr);

      // An unsigned LEB128 number representing the directory index of a
      // directory in the include_directories section.
      encodeULEB128(File.DirIdx, Section.OS);
      // An unsigned LEB128 number representing the (implementation-defined)
      // time of last modification for the file, or 0 if not available.
      encodeULEB128(File.ModTime, Section.OS);
      // An unsigned LEB128 number representing the length in bytes of the file,
      // or 0 if not available.
      encodeULEB128(File.Length, Section.OS);
    }
    // The last entry is followed by a single null byte.
    Section.emitIntVal(0, 1);
  }

  void
  emitLineTablePrologueV5IncludeAndFileTable(const DWARFDebugLine::Prologue &P,
                                             SectionDescriptor &Section) {
    if (P.IncludeDirectories.empty()) {
      // directory_entry_format_count(ubyte).
      Section.emitIntVal(0, 1);
    } else {
      // directory_entry_format_count(ubyte).
      Section.emitIntVal(1, 1);

      // directory_entry_format (sequence of ULEB128 pairs).
      encodeULEB128(dwarf::DW_LNCT_path, Section.OS);
      encodeULEB128(P.IncludeDirectories[0].getForm(), Section.OS);
    }

    // directories_count (ULEB128).
    encodeULEB128(P.IncludeDirectories.size(), Section.OS);
    // directories (sequence of directory names).
    for (auto Include : P.IncludeDirectories) {
      std::optional<const char *> IncludeStr = dwarf::toString(Include);
      if (!IncludeStr) {
        U.warn("cann't read string from line table.");
        return;
      }

      Section.emitString(Include.getForm(), *IncludeStr);
    }

    if (P.FileNames.empty()) {
      // file_name_entry_format_count (ubyte).
      Section.emitIntVal(0, 1);
    } else {
      // file_name_entry_format_count (ubyte).
      Section.emitIntVal(2, 1);

      // file_name_entry_format (sequence of ULEB128 pairs).
      encodeULEB128(dwarf::DW_LNCT_path, Section.OS);
      encodeULEB128(P.FileNames[0].Name.getForm(), Section.OS);

      encodeULEB128(dwarf::DW_LNCT_directory_index, Section.OS);
      encodeULEB128(dwarf::DW_FORM_data1, Section.OS);
    }

    // file_names_count (ULEB128).
    encodeULEB128(P.FileNames.size(), Section.OS);

    // file_names (sequence of file name entries).
    for (auto File : P.FileNames) {
      std::optional<const char *> FileNameStr = dwarf::toString(File.Name);
      if (!FileNameStr) {
        U.warn("cann't read string from line table.");
        return;
      }

      // A null-terminated string containing the full or relative path name of a
      // source file.
      Section.emitString(File.Name.getForm(), *FileNameStr);
      Section.emitIntVal(File.DirIdx, 1);
    }
  }

  void emitLineTableProloguePayload(const DWARFDebugLine::Prologue &P,
                                    SectionDescriptor &Section) {
    // minimum_instruction_length (ubyte).
    Section.emitIntVal(P.MinInstLength, 1);
    if (P.FormParams.Version >= 4) {
      // maximum_operations_per_instruction (ubyte).
      Section.emitIntVal(P.MaxOpsPerInst, 1);
    }
    // default_is_stmt (ubyte).
    Section.emitIntVal(P.DefaultIsStmt, 1);
    // line_base (sbyte).
    Section.emitIntVal(P.LineBase, 1);
    // line_range (ubyte).
    Section.emitIntVal(P.LineRange, 1);
    // opcode_base (ubyte).
    Section.emitIntVal(P.OpcodeBase, 1);

    // standard_opcode_lengths (array of ubyte).
    for (auto Length : P.StandardOpcodeLengths)
      Section.emitIntVal(Length, 1);

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

  void emitLineTableRows(const DWARFDebugLine::LineTable &LineTable,
                         SectionDescriptor &Section) {

    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);
      Section.OS.write(EncodingBuffer.c_str(), EncodingBuffer.size());
      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) {
        Section.emitIntVal(dwarf::DW_LNS_extended_op, 1);
        encodeULEB128(Section.getFormParams().AddrSize + 1, Section.OS);
        Section.emitIntVal(dwarf::DW_LNE_set_address, 1);
        Section.emitIntVal(Row.Address.Address,
                           Section.getFormParams().AddrSize);
        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;
        Section.emitIntVal(dwarf::DW_LNS_set_file, 1);
        encodeULEB128(FileNum, Section.OS);
      }
      if (Column != Row.Column) {
        Column = Row.Column;
        Section.emitIntVal(dwarf::DW_LNS_set_column, 1);
        encodeULEB128(Column, Section.OS);
      }

      // 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;
        Section.emitIntVal(dwarf::DW_LNS_set_isa, 1);
        encodeULEB128(Isa, Section.OS);
      }
      if (IsStatement != Row.IsStmt) {
        IsStatement = Row.IsStmt;
        Section.emitIntVal(dwarf::DW_LNS_negate_stmt, 1);
      }
      if (Row.BasicBlock)
        Section.emitIntVal(dwarf::DW_LNS_set_basic_block, 1);

      if (Row.PrologueEnd)
        Section.emitIntVal(dwarf::DW_LNS_set_prologue_end, 1);

      if (Row.EpilogueBegin)
        Section.emitIntVal(dwarf::DW_LNS_set_epilogue_begin, 1);

      int64_t LineDelta = int64_t(Row.Line) - LastLine;
      if (!Row.EndSequence) {
        MCDwarfLineAddr::encode(*MC, Params, LineDelta, AddressDelta,
                                EncodingBuffer);
        Section.OS.write(EncodingBuffer.c_str(), EncodingBuffer.size());
        EncodingBuffer.resize(0);
        Address = Row.Address.Address;
        LastLine = Row.Line;
        RowsSinceLastSequence++;
      } else {
        if (LineDelta) {
          Section.emitIntVal(dwarf::DW_LNS_advance_line, 1);
          encodeSLEB128(LineDelta, Section.OS);
        }
        if (AddressDelta) {
          Section.emitIntVal(dwarf::DW_LNS_advance_pc, 1);
          encodeULEB128(AddressDelta, Section.OS);
        }
        MCDwarfLineAddr::encode(*MC, Params,
                                std::numeric_limits<int64_t>::max(), 0,
                                EncodingBuffer);
        Section.OS.write(EncodingBuffer.c_str(), 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);
      Section.OS.write(EncodingBuffer.c_str(), EncodingBuffer.size());
      EncodingBuffer.resize(0);
    }
  }

  Triple TheTriple;
  DwarfUnit &U;

  std::unique_ptr<MCRegisterInfo> MRI;
  std::unique_ptr<MCAsmInfo> MAI;
  std::unique_ptr<MCContext> MC;
  std::unique_ptr<MCSubtargetInfo> MSTI;
};

} // end of namespace dwarflinker_parallel
} // end namespace llvm

#endif // LLVM_LIB_DWARFLINKERPARALLEL_DEBUGLINESECTIONEMITTER_H
