/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_COMPILER_DEBUG_ELF_DEBUG_LOC_WRITER_H_
#define ART_COMPILER_DEBUG_ELF_DEBUG_LOC_WRITER_H_

#include <cstring>
#include <map>

#include "arch/instruction_set.h"
#include "base/macros.h"
#include "debug/method_debug_info.h"
#include "dwarf/debug_info_entry_writer.h"
#include "dwarf/register.h"
#include "stack_map.h"

namespace art HIDDEN {
namespace debug {
using Reg = dwarf::Reg;

static Reg GetDwarfCoreReg(InstructionSet isa, int machine_reg) {
  switch (isa) {
    case InstructionSet::kArm:
    case InstructionSet::kThumb2:
      return Reg::ArmCore(machine_reg);
    case InstructionSet::kArm64:
      return Reg::Arm64Core(machine_reg);
    case InstructionSet::kRiscv64:
      return Reg::Riscv64Core(machine_reg);
    case InstructionSet::kX86:
      return Reg::X86Core(machine_reg);
    case InstructionSet::kX86_64:
      return Reg::X86_64Core(machine_reg);
    case InstructionSet::kNone:
      LOG(FATAL) << "No instruction set";
  }
  UNREACHABLE();
}

static Reg GetDwarfFpReg(InstructionSet isa, int machine_reg) {
  switch (isa) {
    case InstructionSet::kArm:
    case InstructionSet::kThumb2:
      return Reg::ArmFp(machine_reg);
    case InstructionSet::kArm64:
      return Reg::Arm64Fp(machine_reg);
    case InstructionSet::kRiscv64:
      return Reg::Riscv64Fp(machine_reg);
    case InstructionSet::kX86:
      return Reg::X86Fp(machine_reg);
    case InstructionSet::kX86_64:
      return Reg::X86_64Fp(machine_reg);
    case InstructionSet::kNone:
      LOG(FATAL) << "No instruction set";
  }
  UNREACHABLE();
}

struct VariableLocation {
  uint32_t low_pc;  // Relative to compilation unit.
  uint32_t high_pc;  // Relative to compilation unit.
  DexRegisterLocation reg_lo;  // May be None if the location is unknown.
  DexRegisterLocation reg_hi;  // Most significant bits of 64-bit value.
};

// Get the location of given dex register (e.g. stack or machine register).
// Note that the location might be different based on the current pc.
// The result will cover all ranges where the variable is in scope.
// PCs corresponding to stackmap with dex register map are accurate,
// all other PCs are best-effort only.
static std::vector<VariableLocation> GetVariableLocations(
    const MethodDebugInfo* method_info,
    const std::vector<DexRegisterMap>& dex_register_maps,
    uint16_t vreg,
    bool is64bitValue,
    uint64_t compilation_unit_code_address,
    uint32_t dex_pc_low,
    uint32_t dex_pc_high,
    InstructionSet isa) {
  std::vector<VariableLocation> variable_locations;

  // Get stack maps sorted by pc (they might not be sorted internally).
  // TODO(dsrbecky) Remove this once stackmaps get sorted by pc.
  const CodeInfo code_info(method_info->code_info);
  std::map<uint32_t, uint32_t> stack_maps;  // low_pc -> stack_map_index.
  for (uint32_t s = 0; s < code_info.GetNumberOfStackMaps(); s++) {
    StackMap stack_map = code_info.GetStackMapAt(s);
    DCHECK(stack_map.IsValid());
    if (!stack_map.HasDexRegisterMap()) {
      // The compiler creates stackmaps without register maps at the start of
      // basic blocks in order to keep instruction-accurate line number mapping.
      // However, we never stop at those (breakpoint locations always have map).
      // Therefore, for the purpose of local variables, we ignore them.
      // The main reason for this is to save space by avoiding undefined gaps.
      continue;
    }
    const uint32_t pc_offset = stack_map.GetNativePcOffset(isa);
    DCHECK_LE(pc_offset, method_info->code_size);
    DCHECK_LE(compilation_unit_code_address, method_info->code_address);
    const uint32_t low_pc = dchecked_integral_cast<uint32_t>(
        method_info->code_address + pc_offset - compilation_unit_code_address);
    stack_maps.emplace(low_pc, s);
  }

  // Create entries for the requested register based on stack map data.
  for (auto it = stack_maps.begin(); it != stack_maps.end(); it++) {
    const uint32_t low_pc = it->first;
    const uint32_t stack_map_index = it->second;
    const StackMap stack_map = code_info.GetStackMapAt(stack_map_index);
    auto next_it = it;
    next_it++;
    const uint32_t high_pc = next_it != stack_maps.end()
      ? next_it->first
      : method_info->code_address + method_info->code_size - compilation_unit_code_address;
    DCHECK_LE(low_pc, high_pc);
    if (low_pc == high_pc) {
      continue;  // Ignore if the address range is empty.
    }

    // Check that the stack map is in the requested range.
    uint32_t dex_pc = stack_map.GetDexPc();
    if (!(dex_pc_low <= dex_pc && dex_pc < dex_pc_high)) {
      // The variable is not in scope at this PC. Therefore omit the entry.
      // Note that this is different to None() entry which means in scope, but unknown location.
      continue;
    }

    // Find the location of the dex register.
    DexRegisterLocation reg_lo = DexRegisterLocation::None();
    DexRegisterLocation reg_hi = DexRegisterLocation::None();
    DCHECK_LT(stack_map_index, dex_register_maps.size());
    DexRegisterMap dex_register_map = dex_register_maps[stack_map_index];
    DCHECK(!dex_register_map.empty());
    CodeItemDataAccessor accessor(*method_info->dex_file, method_info->code_item);
    reg_lo = dex_register_map[vreg];
    if (is64bitValue) {
      reg_hi = dex_register_map[vreg + 1];
    }

    // Add location entry for this address range.
    if (!variable_locations.empty() &&
        variable_locations.back().reg_lo == reg_lo &&
        variable_locations.back().reg_hi == reg_hi &&
        variable_locations.back().high_pc == low_pc) {
      // Merge with the previous entry (extend its range).
      variable_locations.back().high_pc = high_pc;
    } else {
      variable_locations.push_back({low_pc, high_pc, reg_lo, reg_hi});
    }
  }

  return variable_locations;
}

// Write table into .debug_loc which describes location of dex register.
// The dex register might be valid only at some points and it might
// move between machine registers and stack.
static void WriteDebugLocEntry(const MethodDebugInfo* method_info,
                               const std::vector<DexRegisterMap>& dex_register_maps,
                               uint16_t vreg,
                               bool is64bitValue,
                               uint64_t compilation_unit_code_address,
                               uint32_t dex_pc_low,
                               uint32_t dex_pc_high,
                               InstructionSet isa,
                               dwarf::DebugInfoEntryWriter<>* debug_info,
                               std::vector<uint8_t>* debug_loc_buffer,
                               std::vector<uint8_t>* debug_ranges_buffer) {
  using Kind = DexRegisterLocation::Kind;
  if (method_info->code_info == nullptr || dex_register_maps.empty()) {
    return;
  }

  std::vector<VariableLocation> variable_locations = GetVariableLocations(
      method_info,
      dex_register_maps,
      vreg,
      is64bitValue,
      compilation_unit_code_address,
      dex_pc_low,
      dex_pc_high,
      isa);

  // Write .debug_loc entries.
  dwarf::Writer<> debug_loc(debug_loc_buffer);
  const size_t debug_loc_offset = debug_loc.size();
  const bool is64bit = Is64BitInstructionSet(isa);
  std::vector<uint8_t> expr_buffer;
  for (const VariableLocation& variable_location : variable_locations) {
    // Translate dex register location to DWARF expression.
    // Note that 64-bit value might be split to two distinct locations.
    // (for example, two 32-bit machine registers, or even stack and register)
    dwarf::Expression expr(&expr_buffer);
    DexRegisterLocation reg_lo = variable_location.reg_lo;
    DexRegisterLocation reg_hi = variable_location.reg_hi;
    for (int piece = 0; piece < (is64bitValue ? 2 : 1); piece++) {
      DexRegisterLocation reg_loc = (piece == 0 ? reg_lo : reg_hi);
      const Kind kind = reg_loc.GetKind();
      const int32_t value = reg_loc.GetValue();
      if (kind == Kind::kInStack) {
        // The stack offset is relative to SP. Make it relative to CFA.
        expr.WriteOpFbreg(value - method_info->frame_size_in_bytes);
        if (piece == 0 && reg_hi.GetKind() == Kind::kInStack &&
            reg_hi.GetValue() == value + 4) {
          break;  // the high word is correctly implied by the low word.
        }
      } else if (kind == Kind::kInRegister) {
        expr.WriteOpReg(GetDwarfCoreReg(isa, value).num());
        if (piece == 0 && reg_hi.GetKind() == Kind::kInRegisterHigh &&
            reg_hi.GetValue() == value) {
          break;  // the high word is correctly implied by the low word.
        }
      } else if (kind == Kind::kInFpuRegister) {
        if ((isa == InstructionSet::kArm || isa == InstructionSet::kThumb2) &&
            piece == 0 && reg_hi.GetKind() == Kind::kInFpuRegister &&
            reg_hi.GetValue() == value + 1 && value % 2 == 0) {
          // Translate S register pair to D register (e.g. S4+S5 to D2).
          expr.WriteOpReg(Reg::ArmDp(value / 2).num());
          break;
        }
        expr.WriteOpReg(GetDwarfFpReg(isa, value).num());
        if (piece == 0 && reg_hi.GetKind() == Kind::kInFpuRegisterHigh &&
            reg_hi.GetValue() == reg_lo.GetValue()) {
          break;  // the high word is correctly implied by the low word.
        }
      } else if (kind == Kind::kConstant) {
        expr.WriteOpConsts(value);
        expr.WriteOpStackValue();
      } else if (kind == Kind::kNone) {
        break;
      } else {
        // kInStackLargeOffset and kConstantLargeValue are hidden by GetKind().
        // kInRegisterHigh and kInFpuRegisterHigh should be handled by
        // the special cases above and they should not occur alone.
        LOG(WARNING) << "Unexpected register location: " << kind
                     << " (This can indicate either a bug in the dexer when generating"
                     << " local variable information, or a bug in ART compiler."
                     << " Please file a bug at go/art-bug)";
        break;
      }
      if (is64bitValue) {
        // Write the marker which is needed by split 64-bit values.
        // This code is skipped by the special cases.
        expr.WriteOpPiece(4);
      }
    }

    if (expr.size() > 0) {
      if (is64bit) {
        debug_loc.PushUint64(variable_location.low_pc);
        debug_loc.PushUint64(variable_location.high_pc);
      } else {
        debug_loc.PushUint32(variable_location.low_pc);
        debug_loc.PushUint32(variable_location.high_pc);
      }
      // Write the expression.
      debug_loc.PushUint16(expr.size());
      debug_loc.PushData(expr.data());
    } else {
      // Do not generate .debug_loc if the location is not known.
    }
  }
  // Write end-of-list entry.
  if (is64bit) {
    debug_loc.PushUint64(0);
    debug_loc.PushUint64(0);
  } else {
    debug_loc.PushUint32(0);
    debug_loc.PushUint32(0);
  }

  // Write .debug_ranges entries.
  // This includes ranges where the variable is in scope but the location is not known.
  dwarf::Writer<> debug_ranges(debug_ranges_buffer);
  size_t debug_ranges_offset = debug_ranges.size();
  for (size_t i = 0; i < variable_locations.size(); i++) {
    uint32_t low_pc = variable_locations[i].low_pc;
    uint32_t high_pc = variable_locations[i].high_pc;
    while (i + 1 < variable_locations.size() && variable_locations[i+1].low_pc == high_pc) {
      // Merge address range with the next entry.
      high_pc = variable_locations[++i].high_pc;
    }
    if (is64bit) {
      debug_ranges.PushUint64(low_pc);
      debug_ranges.PushUint64(high_pc);
    } else {
      debug_ranges.PushUint32(low_pc);
      debug_ranges.PushUint32(high_pc);
    }
  }
  // Write end-of-list entry.
  if (is64bit) {
    debug_ranges.PushUint64(0);
    debug_ranges.PushUint64(0);
  } else {
    debug_ranges.PushUint32(0);
    debug_ranges.PushUint32(0);
  }

  // Simple de-duplication - check whether this entry is same as the last one (or tail of it).
  size_t debug_ranges_entry_size = debug_ranges.size() - debug_ranges_offset;
  if (debug_ranges_offset >= debug_ranges_entry_size) {
    size_t previous_offset = debug_ranges_offset - debug_ranges_entry_size;
    if (memcmp(debug_ranges_buffer->data() + previous_offset,
               debug_ranges_buffer->data() + debug_ranges_offset,
               debug_ranges_entry_size) == 0) {
      // Remove what we have just written and use the last entry instead.
      debug_ranges_buffer->resize(debug_ranges_offset);
      debug_ranges_offset = previous_offset;
    }
  }

  // Write attributes to .debug_info.
  debug_info->WriteSecOffset(dwarf::DW_AT_location, debug_loc_offset);
  debug_info->WriteSecOffset(dwarf::DW_AT_start_scope, debug_ranges_offset);
}

}  // namespace debug
}  // namespace art

#endif  // ART_COMPILER_DEBUG_ELF_DEBUG_LOC_WRITER_H_

