/*
 * 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 dex::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;

      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 dex::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
