/*
 * 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 <android-base/logging.h>

#include "base/macros.h"
#include "base/mutex.h"
#include "dex/bytecode_utils.h"
#include "dex/code_item_accessors-inl.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_instruction-inl.h"
#include "quicken_info.h"

namespace art {
namespace optimizer {

class DexDecompiler {
 public:
  DexDecompiler(const DexFile& dex_file,
                const DexFile::CodeItem& code_item,
                const ArrayRef<const uint8_t>& quickened_info,
                bool decompile_return_instruction)
    : code_item_accessor_(dex_file, &code_item),
      quicken_info_(quickened_info),
      decompile_return_instruction_(decompile_return_instruction) {}

  bool Decompile();

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

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

  void DecompileNop(Instruction* inst) {
    const uint16_t reference_index = NextIndex();
    if (reference_index == DexFile::kDexNoIndex16) {
      // This means it was a normal nop and not a check-cast.
      return;
    }
    const uint16_t type_index = NextIndex();
    inst->SetOpcode(Instruction::CHECK_CAST);
    inst->SetVRegA_21c(reference_index);
    inst->SetVRegB_21c(type_index);
  }

  uint16_t NextIndex() {
    DCHECK_LT(quicken_index_, quicken_info_.NumIndices());
    const uint16_t ret = quicken_info_.GetData(quicken_index_);
    quicken_index_++;
    return ret;
  }

  const CodeItemInstructionAccessor code_item_accessor_;
  const QuickenInfoTable quicken_info_;
  const bool decompile_return_instruction_;

  size_t quicken_index_ = 0u;

  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 (const DexInstructionPcPair& pair : code_item_accessor_) {
    Instruction* inst = const_cast<Instruction*>(&pair.Inst());

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

      case Instruction::NOP:
        if (quicken_info_.NumIndices() > 0) {
          // Only try to decompile NOP if there are more than 0 indices. Not having
          // any index happens when we unquicken a code item that only has
          // RETURN_VOID_NO_BARRIER as quickened instruction.
          DecompileNop(inst);
        }
        break;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      default:
        break;
    }
  }

  if (quicken_index_ != quicken_info_.NumIndices()) {
    if (quicken_index_ == 0) {
      LOG(WARNING) << "Failed to use any value in quickening info,"
                   << " potentially due to duplicate methods.";
    } else {
      LOG(FATAL) << "Failed to use all values in quickening info."
                 << " Actual: " << std::hex << quicken_index_
                 << " Expected: " << quicken_info_.NumIndices();
    }
  }

  return true;
}

bool ArtDecompileDEX(const DexFile& dex_file,
                     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(dex_file, code_item, quickened_info, decompile_return_instruction);
  return decompiler.Decompile();
}

}  // namespace optimizer
}  // namespace art
