/*
 * 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,
                bool decompile_return_instruction)
    : code_item_(code_item),
      quickened_info_ptr_(quickened_info.data()),
      quickened_info_end_(quickened_info.data() + quickened_info.size()),
      decompile_return_instruction_(decompile_return_instruction) {}

  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_;
  const bool decompile_return_instruction_;

  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:
        if (decompile_return_instruction_) {
          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,
                     bool decompile_return_instruction) {
  if (quickened_info.size() == 0 && !decompile_return_instruction) {
    return true;
  }
  DexDecompiler decompiler(code_item, quickened_info, decompile_return_instruction);
  return decompiler.Decompile();
}

}  // namespace optimizer
}  // namespace art
