//===-- DWARFDebugMacro.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 "DWARFDebugMacro.h"
#include "SymbolFileDWARF.h"

#include "lldb/Symbol/DebugMacros.h"

#include "DWARFDataExtractor.h"

using namespace lldb_private;
using namespace lldb_private::plugin::dwarf;
using namespace llvm::dwarf;

DWARFDebugMacroHeader
DWARFDebugMacroHeader::ParseHeader(const DWARFDataExtractor &debug_macro_data,
                                   lldb::offset_t *offset) {
  DWARFDebugMacroHeader header;

  // Skip over the version field in header.
  header.m_version = debug_macro_data.GetU16(offset);

  uint8_t flags = debug_macro_data.GetU8(offset);
  header.m_offset_is_64_bit = (flags & OFFSET_SIZE_MASK) != 0;

  if (flags & DEBUG_LINE_OFFSET_MASK) {
    if (header.m_offset_is_64_bit)
      header.m_debug_line_offset = debug_macro_data.GetU64(offset);
    else
      header.m_debug_line_offset = debug_macro_data.GetU32(offset);
  }

  // Skip over the operands table if it is present.
  if (flags & OPCODE_OPERANDS_TABLE_MASK)
    SkipOperandTable(debug_macro_data, offset);

  return header;
}

void DWARFDebugMacroHeader::SkipOperandTable(
    const DWARFDataExtractor &debug_macro_data, lldb::offset_t *offset) {
  uint8_t entry_count = debug_macro_data.GetU8(offset);
  for (uint8_t i = 0; i < entry_count; i++) {
    // Skip over the opcode number.
    debug_macro_data.GetU8(offset);

    uint64_t operand_count = debug_macro_data.GetULEB128(offset);

    for (uint64_t j = 0; j < operand_count; j++) {
      // Skip over the operand form
      debug_macro_data.GetU8(offset);
    }
  }
}

void DWARFDebugMacroEntry::ReadMacroEntries(
    const DWARFDataExtractor &debug_macro_data,
    const DWARFDataExtractor &debug_str_data, const bool offset_is_64_bit,
    lldb::offset_t *offset, SymbolFileDWARF *sym_file_dwarf,
    DebugMacrosSP &debug_macros_sp) {
  llvm::dwarf::MacroEntryType type =
      static_cast<llvm::dwarf::MacroEntryType>(debug_macro_data.GetU8(offset));
  while (type != 0) {
    lldb::offset_t new_offset = 0, str_offset = 0;
    uint32_t line = 0;
    const char *macro_str = nullptr;
    uint32_t debug_line_file_idx = 0;

    switch (type) {
    case DW_MACRO_define:
    case DW_MACRO_undef:
      line = debug_macro_data.GetULEB128(offset);
      macro_str = debug_macro_data.GetCStr(offset);
      if (type == DW_MACRO_define)
        debug_macros_sp->AddMacroEntry(
            DebugMacroEntry::CreateDefineEntry(line, macro_str));
      else
        debug_macros_sp->AddMacroEntry(
            DebugMacroEntry::CreateUndefEntry(line, macro_str));
      break;
    case DW_MACRO_define_strp:
    case DW_MACRO_undef_strp:
      line = debug_macro_data.GetULEB128(offset);
      if (offset_is_64_bit)
        str_offset = debug_macro_data.GetU64(offset);
      else
        str_offset = debug_macro_data.GetU32(offset);
      macro_str = debug_str_data.GetCStr(&str_offset);
      if (type == DW_MACRO_define_strp)
        debug_macros_sp->AddMacroEntry(
            DebugMacroEntry::CreateDefineEntry(line, macro_str));
      else
        debug_macros_sp->AddMacroEntry(
            DebugMacroEntry::CreateUndefEntry(line, macro_str));
      break;
    case DW_MACRO_start_file:
      line = debug_macro_data.GetULEB128(offset);
      debug_line_file_idx = debug_macro_data.GetULEB128(offset);
      debug_macros_sp->AddMacroEntry(
          DebugMacroEntry::CreateStartFileEntry(line, debug_line_file_idx));
      break;
    case DW_MACRO_end_file:
      // This operation has no operands.
      debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateEndFileEntry());
      break;
    case DW_MACRO_import:
      if (offset_is_64_bit)
        new_offset = debug_macro_data.GetU64(offset);
      else
        new_offset = debug_macro_data.GetU32(offset);
      debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateIndirectEntry(
          sym_file_dwarf->ParseDebugMacros(&new_offset)));
      break;
    default:
      // TODO: Add support for other standard operations.
      // TODO: Provide mechanism to hook handling of non-standard/extension
      // operands.
      return;
    }
    type = static_cast<llvm::dwarf::MacroEntryType>(
        debug_macro_data.GetU8(offset));
  }
}
