// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/globals.h"  // Needed here to get TARGET_ARCH_DBC.
#if defined(TARGET_ARCH_DBC)

#include "vm/instructions.h"
#include "vm/instructions_dbc.h"

#include "vm/compiler/assembler/assembler.h"
#include "vm/constants_dbc.h"
#include "vm/cpu.h"
#include "vm/object.h"

namespace dart {

static bool HasLoadFromPool(Instr instr) {
  switch (SimulatorBytecode::DecodeOpcode(instr)) {
    case SimulatorBytecode::kLoadConstant:
    case SimulatorBytecode::kPushConstant:
    case SimulatorBytecode::kStaticCall:
    case SimulatorBytecode::kIndirectStaticCall:
    case SimulatorBytecode::kInstanceCall1:
    case SimulatorBytecode::kInstanceCall2:
    case SimulatorBytecode::kInstanceCall1Opt:
    case SimulatorBytecode::kInstanceCall2Opt:
    case SimulatorBytecode::kStoreStaticTOS:
    case SimulatorBytecode::kPushStatic:
    case SimulatorBytecode::kAllocate:
    case SimulatorBytecode::kInstantiateType:
    case SimulatorBytecode::kInstantiateTypeArgumentsTOS:
    case SimulatorBytecode::kAssertAssignable:
      return true;
    default:
      return false;
  }
}

static bool GetLoadedObjectAt(uword pc,
                              const ObjectPool& object_pool,
                              Object* obj) {
  Instr instr = SimulatorBytecode::At(pc);
  if (HasLoadFromPool(instr)) {
    uint16_t index = SimulatorBytecode::DecodeD(instr);
    if (object_pool.TypeAt(index) == ObjectPool::kTaggedObject) {
      *obj = object_pool.ObjectAt(index);
      return true;
    }
  }
  return false;
}

CallPattern::CallPattern(uword pc, const Code& code)
    : object_pool_(ObjectPool::Handle(code.GetObjectPool())),
      end_(pc),
      ic_data_load_end_(0),
      target_code_pool_index_(-1),
      ic_data_(ICData::Handle()) {
  ASSERT(code.ContainsInstructionAt(end_));
  const uword call_pc = end_ - sizeof(Instr);
  Instr call_instr = SimulatorBytecode::At(call_pc);
  ASSERT(SimulatorBytecode::IsCallOpcode(call_instr));
  ic_data_load_end_ = call_pc;
  target_code_pool_index_ = SimulatorBytecode::DecodeD(call_instr);
}

NativeCallPattern::NativeCallPattern(uword pc, const Code& code)
    : object_pool_(ObjectPool::Handle(code.GetObjectPool())),
      end_(pc),
      native_function_pool_index_(-1),
      trampoline_pool_index_(-1) {
  ASSERT(code.ContainsInstructionAt(end_));
  const uword call_pc = end_ - sizeof(Instr);
  Instr call_instr = SimulatorBytecode::At(call_pc);
  ASSERT(SimulatorBytecode::DecodeOpcode(call_instr) ==
         SimulatorBytecode::kNativeCall);
  native_function_pool_index_ = SimulatorBytecode::DecodeB(call_instr);
  trampoline_pool_index_ = SimulatorBytecode::DecodeA(call_instr);
}

NativeFunctionWrapper NativeCallPattern::target() const {
  return reinterpret_cast<NativeFunctionWrapper>(
      object_pool_.ObjectAt(trampoline_pool_index_));
}

void NativeCallPattern::set_target(NativeFunctionWrapper new_target) const {
  object_pool_.SetRawValueAt(trampoline_pool_index_,
                             reinterpret_cast<uword>(new_target));
  // No need to flush the instruction cache, since the code is not modified.
}

NativeFunction NativeCallPattern::native_function() const {
  return reinterpret_cast<NativeFunction>(
      object_pool_.RawValueAt(native_function_pool_index_));
}

void NativeCallPattern::set_native_function(NativeFunction func) const {
  object_pool_.SetRawValueAt(native_function_pool_index_,
                             reinterpret_cast<uword>(func));
}

// Decodes a load sequence ending at 'end' (the last instruction of the load
// sequence is the instruction before the one at end).  Returns a pointer to
// the first instruction in the sequence.  Returns the register being loaded
// and the loaded object in the output parameters 'reg' and 'obj'
// respectively.
uword InstructionPattern::DecodeLoadObject(uword end,
                                           const ObjectPool& object_pool,
                                           Register* reg,
                                           Object* obj) {
  UNIMPLEMENTED();
  return 0;
}

// Decodes a load sequence ending at 'end' (the last instruction of the load
// sequence is the instruction before the one at end).  Returns a pointer to
// the first instruction in the sequence.  Returns the register being loaded
// and the loaded immediate value in the output parameters 'reg' and 'value'
// respectively.
uword InstructionPattern::DecodeLoadWordImmediate(uword end,
                                                  Register* reg,
                                                  intptr_t* value) {
  UNIMPLEMENTED();
  return 0;
}

// Decodes a load sequence ending at 'end' (the last instruction of the load
// sequence is the instruction before the one at end).  Returns a pointer to
// the first instruction in the sequence.  Returns the register being loaded
// and the index in the pool being read from in the output parameters 'reg'
// and 'index' respectively.
uword InstructionPattern::DecodeLoadWordFromPool(uword end,
                                                 Register* reg,
                                                 intptr_t* index) {
  UNIMPLEMENTED();
  return 0;
}

bool DecodeLoadObjectFromPoolOrThread(uword pc, const Code& code, Object* obj) {
  ASSERT(code.ContainsInstructionAt(pc));
  const ObjectPool& pool = ObjectPool::Handle(code.object_pool());
  return GetLoadedObjectAt(pc, pool, obj);
}

RawICData* CallPattern::IcData() {
  if (ic_data_.IsNull()) {
    bool found = GetLoadedObjectAt(ic_data_load_end_, object_pool_, &ic_data_);
    ASSERT(found);
  }
  return ic_data_.raw();
}

RawCode* CallPattern::TargetCode() const {
  return reinterpret_cast<RawCode*>(
      object_pool_.ObjectAt(target_code_pool_index_));
}

void CallPattern::SetTargetCode(const Code& target_code) const {
  object_pool_.SetObjectAt(target_code_pool_index_, target_code);
}

void CallPattern::InsertDeoptCallAt(uword pc) {
  const uint8_t argc =
      SimulatorBytecode::IsCallOpcode(SimulatorBytecode::At(pc))
          ? SimulatorBytecode::DecodeArgc(SimulatorBytecode::At(pc))
          : 0;
  *reinterpret_cast<Instr*>(pc) =
      SimulatorBytecode::Encode(SimulatorBytecode::kDeopt, argc, 0);
}

SwitchableCallPattern::SwitchableCallPattern(uword pc, const Code& code)
    : object_pool_(ObjectPool::Handle(code.GetObjectPool())),
      data_pool_index_(-1),
      target_pool_index_(-1) {
  UNIMPLEMENTED();
}

RawObject* SwitchableCallPattern::data() const {
  return object_pool_.ObjectAt(data_pool_index_);
}

RawCode* SwitchableCallPattern::target() const {
  return reinterpret_cast<RawCode*>(object_pool_.ObjectAt(target_pool_index_));
}

void SwitchableCallPattern::SetData(const Object& data) const {
  ASSERT(!Object::Handle(object_pool_.ObjectAt(data_pool_index_)).IsCode());
  object_pool_.SetObjectAt(data_pool_index_, data);
}

void SwitchableCallPattern::SetTarget(const Code& target) const {
  ASSERT(Object::Handle(object_pool_.ObjectAt(target_pool_index_)).IsCode());
  object_pool_.SetObjectAt(target_pool_index_, target);
}

ReturnPattern::ReturnPattern(uword pc) : pc_(pc) {
  USE(pc_);
}

bool ReturnPattern::IsValid() const {
  UNIMPLEMENTED();
  return false;
}

}  // namespace dart

#endif  // defined TARGET_ARCH_DBC
