/*
 * Copyright (C) 2017 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.
 */

#include "slicer/common.h"
#include "slicer/debuginfo_encoder.h"
#include "slicer/chronometer.h"

#include <assert.h>

namespace lir {

bool DebugInfoEncoder::Visit(DbgInfoHeader* dbg_header) {
  assert(param_names_ == nullptr);
  param_names_ = &dbg_header->param_names;
  return true;
}

bool DebugInfoEncoder::Visit(DbgInfoAnnotation* dbg_annotation) {
  // keep the address in sync
  if (last_address_ != dbg_annotation->offset) {
    SLICER_CHECK(dbg_annotation->offset > last_address_);
    dbginfo_.Push<dex::u1>(dex::DBG_ADVANCE_PC);
    dbginfo_.PushULeb128(dbg_annotation->offset - last_address_);
    last_address_ = dbg_annotation->offset;
  }

  // encode the annotation itself
  switch (dbg_annotation->dbg_opcode) {
    case dex::DBG_ADVANCE_LINE: {
      // DBG_ANDVANCE_LINE is used a bit differently in the code IR
      // vs the .dex image: the code IR uses it exclusively for source
      // location (the .line directive) while .dex format uses it to
      // advance the "line" register without emitting a "position entry"
      int line = dbg_annotation->CastOperand<LineNumber>(0)->line;
      if (line_start_ == 0) {
        // it's not perfectly clear from the .dex specification
        // if initial line == 0 is valid, but a number of existing
        // .dex files do this so we have to support it
        SLICER_CHECK(line >= 0);
        line_start_ = line;
      } else {
        SLICER_WEAK_CHECK(line > 0);
        int delta = line - last_line_;
        int adj_opcode = delta - dex::DBG_LINE_BASE;
        // out of range for special opcode?
        if (adj_opcode < 0 || adj_opcode >= dex::DBG_LINE_RANGE) {
          dbginfo_.Push<dex::u1>(dex::DBG_ADVANCE_LINE);
          dbginfo_.PushSLeb128(delta);
          adj_opcode = -dex::DBG_LINE_BASE;
        }
        assert(adj_opcode >= 0 && dex::DBG_FIRST_SPECIAL + adj_opcode < 256);
        dex::u1 special_opcode = dex::DBG_FIRST_SPECIAL + adj_opcode;
        dbginfo_.Push<dex::u1>(special_opcode);
      }
      last_line_ = line;
    } break;

    case dex::DBG_START_LOCAL: {
      auto reg = dbg_annotation->CastOperand<VReg>(0)->reg;
      auto name_index = dbg_annotation->CastOperand<String>(1)->index;
      auto type_index = dbg_annotation->CastOperand<Type>(2)->index;
      dbginfo_.Push<dex::u1>(dex::DBG_START_LOCAL);
      dbginfo_.PushULeb128(reg);
      dbginfo_.PushULeb128(name_index + 1);
      dbginfo_.PushULeb128(type_index + 1);
    } break;

    case dex::DBG_START_LOCAL_EXTENDED: {
      auto reg = dbg_annotation->CastOperand<VReg>(0)->reg;
      auto name_index = dbg_annotation->CastOperand<String>(1)->index;
      auto type_index = dbg_annotation->CastOperand<Type>(2)->index;
      auto sig_index = dbg_annotation->CastOperand<String>(3)->index;
      dbginfo_.Push<dex::u1>(dex::DBG_START_LOCAL_EXTENDED);
      dbginfo_.PushULeb128(reg);
      dbginfo_.PushULeb128(name_index + 1);
      dbginfo_.PushULeb128(type_index + 1);
      dbginfo_.PushULeb128(sig_index + 1);
    } break;

    case dex::DBG_END_LOCAL:
    case dex::DBG_RESTART_LOCAL: {
      auto reg = dbg_annotation->CastOperand<VReg>(0)->reg;
      dbginfo_.Push<dex::u1>(dbg_annotation->dbg_opcode);
      dbginfo_.PushULeb128(reg);
    } break;

    case dex::DBG_SET_PROLOGUE_END:
    case dex::DBG_SET_EPILOGUE_BEGIN:
      dbginfo_.Push<dex::u1>(dbg_annotation->dbg_opcode);
      break;

    case dex::DBG_SET_FILE: {
      auto file_name = dbg_annotation->CastOperand<String>(0);
      if (file_name->ir_string != source_file_) {
        source_file_ = file_name->ir_string;
        dbginfo_.Push<dex::u1>(dex::DBG_SET_FILE);
        dbginfo_.PushULeb128(file_name->index + 1);
      }
    } break;

    default:
      SLICER_FATAL("Unexpected debug info opcode: 0x%02x", dbg_annotation->dbg_opcode);
  }

  return true;
}

void DebugInfoEncoder::Encode(ir::EncodedMethod* ir_method, std::shared_ptr<ir::DexFile> dex_ir) {
  auto ir_debug_info = ir_method->code->debug_info;

  SLICER_CHECK(dbginfo_.empty());
  SLICER_CHECK(param_names_ == nullptr);
  SLICER_CHECK(line_start_ == 0);
  SLICER_CHECK(last_line_ == 0);
  SLICER_CHECK(last_address_ == 0);
  SLICER_CHECK(source_file_ == nullptr);

  // generate new debug info
  source_file_ = ir_method->decl->parent->class_def->source_file;
  for (auto instr : instructions_) {
    instr->Accept(this);
  }
  dbginfo_.Push<dex::u1>(dex::DBG_END_SEQUENCE);
  dbginfo_.Seal(1);

  SLICER_CHECK(!dbginfo_.empty());

  // update ir::DebugInfo
  ir_debug_info->line_start = line_start_;
  ir_debug_info->data = slicer::MemView(dbginfo_.data(), dbginfo_.size());

  if (param_names_ != nullptr) {
    ir_debug_info->param_names = *param_names_;
  } else {
    ir_debug_info->param_names = {};
  }

  // attach the debug info buffer to the dex IR
  dex_ir->AttachBuffer(std::move(dbginfo_));
}

}  // namespace lir
