/*
 * 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 "oat/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_

