/*
 * 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.
 */

#include "dex_to_dex_decompiler.h"

#include "base/logging.h"
#include "base/mutex.h"
#include "dex_file-inl.h"
#include "dex_instruction-inl.h"
#include "optimizing/bytecode_utils.h"

namespace art {
namespace optimizer {

class DexDecompiler {
 public:
  DexDecompiler(const DexFile::CodeItem& code_item, const ArrayRef<const uint8_t>& quickened_info)
    : code_item_(code_item),
      quickened_info_ptr_(quickened_info.data()),
      quickened_info_end_(quickened_info.data() + quickened_info.size()) {}

  bool Decompile();

 private:
  void DecompileInstanceFieldAccess(Instruction* inst,
                                    uint32_t dex_pc,
                                    Instruction::Code new_opcode) {
    uint16_t index = GetIndexAt(dex_pc);
    inst->SetOpcode(new_opcode);
    inst->SetVRegC_22c(index);
  }

  void DecompileInvokeVirtual(Instruction* inst,
                              uint32_t dex_pc,
                              Instruction::Code new_opcode,
                              bool is_range) {
    uint16_t index = GetIndexAt(dex_pc);
    inst->SetOpcode(new_opcode);
    if (is_range) {
      inst->SetVRegB_3rc(index);
    } else {
      inst->SetVRegB_35c(index);
    }
  }

  void DecompileNop(Instruction* inst, uint32_t dex_pc) {
    if (quickened_info_ptr_ == quickened_info_end_) {
      return;
    }
    const uint8_t* temporary_pointer = quickened_info_ptr_;
    uint32_t quickened_pc = DecodeUnsignedLeb128(&temporary_pointer);
    if (quickened_pc != dex_pc) {
      return;
    }
    uint16_t reference_index = GetIndexAt(dex_pc);
    uint16_t type_index = GetIndexAt(dex_pc);
    inst->SetOpcode(Instruction::CHECK_CAST);
    inst->SetVRegA_21c(reference_index);
    inst->SetVRegB_21c(type_index);
  }

  uint16_t GetIndexAt(uint32_t dex_pc) {
    // Note that as a side effect, DecodeUnsignedLeb128 update the given pointer
    // to the new position in the buffer.
    DCHECK_LT(quickened_info_ptr_, quickened_info_end_);
    uint32_t quickened_pc = DecodeUnsignedLeb128(&quickened_info_ptr_);
    DCHECK_LT(quickened_info_ptr_, quickened_info_end_);
    uint16_t index = DecodeUnsignedLeb128(&quickened_info_ptr_);
    DCHECK_LE(quickened_info_ptr_, quickened_info_end_);
    DCHECK_EQ(quickened_pc, dex_pc);
    return index;
  }

  const DexFile::CodeItem& code_item_;
  const uint8_t* quickened_info_ptr_;
  const uint8_t* const quickened_info_end_;

  DISALLOW_COPY_AND_ASSIGN(DexDecompiler);
};

bool DexDecompiler::Decompile() {
  // We need to iterate over the code item, and not over the quickening data,
  // because the RETURN_VOID quickening is not encoded in the quickening data. Because
  // unquickening is a rare need and not performance sensitive, it is not worth the
  // added storage to also add the RETURN_VOID quickening in the quickened data.
  for (CodeItemIterator it(code_item_); !it.Done(); it.Advance()) {
    uint32_t dex_pc = it.CurrentDexPc();
    Instruction* inst = const_cast<Instruction*>(&it.CurrentInstruction());

    switch (inst->Opcode()) {
      case Instruction::RETURN_VOID_NO_BARRIER:
        inst->SetOpcode(Instruction::RETURN_VOID);
        break;

      case Instruction::NOP:
        DecompileNop(inst, dex_pc);
        break;

      case Instruction::IGET_QUICK:
        DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET);
        break;

      case Instruction::IGET_WIDE_QUICK:
        DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_WIDE);
        break;

      case Instruction::IGET_OBJECT_QUICK:
        DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_OBJECT);
        break;

      case Instruction::IGET_BOOLEAN_QUICK:
        DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_BOOLEAN);
        break;

      case Instruction::IGET_BYTE_QUICK:
        DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_BYTE);
        break;

      case Instruction::IGET_CHAR_QUICK:
        DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_CHAR);
        break;

      case Instruction::IGET_SHORT_QUICK:
        DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_SHORT);
        break;

      case Instruction::IPUT_QUICK:
        DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT);
        break;

      case Instruction::IPUT_BOOLEAN_QUICK:
        DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_BOOLEAN);
        break;

      case Instruction::IPUT_BYTE_QUICK:
        DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_BYTE);
        break;

      case Instruction::IPUT_CHAR_QUICK:
        DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_CHAR);
        break;

      case Instruction::IPUT_SHORT_QUICK:
        DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_SHORT);
        break;

      case Instruction::IPUT_WIDE_QUICK:
        DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_WIDE);
        break;

      case Instruction::IPUT_OBJECT_QUICK:
        DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_OBJECT);
        break;

      case Instruction::INVOKE_VIRTUAL_QUICK:
        DecompileInvokeVirtual(inst, dex_pc, Instruction::INVOKE_VIRTUAL, false);
        break;

      case Instruction::INVOKE_VIRTUAL_RANGE_QUICK:
        DecompileInvokeVirtual(inst, dex_pc, Instruction::INVOKE_VIRTUAL_RANGE, true);
        break;

      default:
        break;
    }
  }

  if (quickened_info_ptr_ != quickened_info_end_) {
    LOG(ERROR) << "Failed to use all values in quickening info."
               << " Actual: " << std::hex << quickened_info_ptr_
               << " Expected: " << quickened_info_end_;
    return false;
  }

  return true;
}

bool ArtDecompileDEX(const DexFile::CodeItem& code_item,
                     const ArrayRef<const uint8_t>& quickened_info) {
  DexDecompiler decompiler(code_item, quickened_info);
  return decompiler.Decompile();
}

}  // namespace optimizer
}  // namespace art
