// Copyright (c) 2019, 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/compiler/frontend/bytecode_fingerprints.h"

#include "vm/compiler/frontend/bytecode_reader.h"
#include "vm/constants_kbc.h"
#include "vm/hash.h"

#if !defined(DART_PRECOMPILED_RUNTIME)

namespace dart {
namespace kernel {

static uint32_t CombineObject(uint32_t hash, const Object& obj) {
  if (obj.IsAbstractType()) {
    return CombineHashes(hash, AbstractType::Cast(obj).Hash());
  } else if (obj.IsClass()) {
    return CombineHashes(hash, Class::Cast(obj).id());
  } else if (obj.IsFunction()) {
    return CombineHashes(
        hash, AbstractType::Handle(Function::Cast(obj).result_type()).Hash());
  } else if (obj.IsField()) {
    return CombineHashes(hash,
                         AbstractType::Handle(Field::Cast(obj).type()).Hash());
  } else {
    return CombineHashes(hash, static_cast<uint32_t>(obj.GetClassId()));
  }
}

typedef uint32_t (*Fp)(uint32_t fp,
                       const KBCInstr* instr,
                       const ObjectPool& pool,
                       int32_t value);

static uint32_t Fp___(uint32_t fp,
                      const KBCInstr* instr,
                      const ObjectPool& pool,
                      int32_t value) {
  return fp;
}

static uint32_t Fptgt(uint32_t fp,
                      const KBCInstr* instr,
                      const ObjectPool& pool,
                      int32_t value) {
  return CombineHashes(fp, value);
}

static uint32_t Fplit(uint32_t fp,
                      const KBCInstr* instr,
                      const ObjectPool& pool,
                      int32_t value) {
  return CombineObject(fp, Object::Handle(pool.ObjectAt(value)));
}

static uint32_t Fpreg(uint32_t fp,
                      const KBCInstr* instr,
                      const ObjectPool& pool,
                      int32_t value) {
  return CombineHashes(fp, value);
}

static uint32_t Fpxeg(uint32_t fp,
                      const KBCInstr* instr,
                      const ObjectPool& pool,
                      int32_t value) {
  return CombineHashes(fp, value);
}

static uint32_t Fpnum(uint32_t fp,
                      const KBCInstr* instr,
                      const ObjectPool& pool,
                      int32_t value) {
  return CombineHashes(fp, value);
}

static uint32_t Fingerprint0(uint32_t fp,
                             const KBCInstr* instr,
                             const ObjectPool& pool,
                             Fp op1,
                             Fp op2,
                             Fp op3) {
  return fp;
}

static uint32_t FingerprintA(uint32_t fp,
                             const KBCInstr* instr,
                             const ObjectPool& pool,
                             Fp op1,
                             Fp op2,
                             Fp op3) {
  fp = op1(fp, instr, pool, KernelBytecode::DecodeA(instr));
  return fp;
}

static uint32_t FingerprintD(uint32_t fp,
                             const KBCInstr* instr,
                             const ObjectPool& pool,
                             Fp op1,
                             Fp op2,
                             Fp op3) {
  fp = op1(fp, instr, pool, KernelBytecode::DecodeD(instr));
  return fp;
}

static uint32_t FingerprintX(uint32_t fp,
                             const KBCInstr* instr,
                             const ObjectPool& pool,
                             Fp op1,
                             Fp op2,
                             Fp op3) {
  fp = op1(fp, instr, pool, KernelBytecode::DecodeX(instr));
  return fp;
}

static uint32_t FingerprintT(uint32_t fp,
                             const KBCInstr* instr,
                             const ObjectPool& pool,
                             Fp op1,
                             Fp op2,
                             Fp op3) {
  fp = op1(fp, instr, pool, KernelBytecode::DecodeT(instr));
  return fp;
}

static uint32_t FingerprintA_E(uint32_t fp,
                               const KBCInstr* instr,
                               const ObjectPool& pool,
                               Fp op1,
                               Fp op2,
                               Fp op3) {
  fp = op1(fp, instr, pool, KernelBytecode::DecodeA(instr));
  fp = op2(fp, instr, pool, KernelBytecode::DecodeE(instr));
  return fp;
}

static uint32_t FingerprintA_Y(uint32_t fp,
                               const KBCInstr* instr,
                               const ObjectPool& pool,
                               Fp op1,
                               Fp op2,
                               Fp op3) {
  fp = op1(fp, instr, pool, KernelBytecode::DecodeA(instr));
  fp = op2(fp, instr, pool, KernelBytecode::DecodeY(instr));
  return fp;
}

static uint32_t FingerprintD_F(uint32_t fp,
                               const KBCInstr* instr,
                               const ObjectPool& pool,
                               Fp op1,
                               Fp op2,
                               Fp op3) {
  fp = op1(fp, instr, pool, KernelBytecode::DecodeD(instr));
  fp = op2(fp, instr, pool, KernelBytecode::DecodeF(instr));
  return fp;
}

static uint32_t FingerprintA_B_C(uint32_t fp,
                                 const KBCInstr* instr,
                                 const ObjectPool& pool,
                                 Fp op1,
                                 Fp op2,
                                 Fp op3) {
  fp = op1(fp, instr, pool, KernelBytecode::DecodeA(instr));
  fp = op2(fp, instr, pool, KernelBytecode::DecodeB(instr));
  fp = op3(fp, instr, pool, KernelBytecode::DecodeC(instr));
  return fp;
}

uint32_t BytecodeFingerprintHelper::CalculateFunctionFingerprint(
    const Function& function) {
  ASSERT(function.is_declared_in_bytecode());
  if (function.is_abstract()) {
    return 0;
  }
  if (!function.HasBytecode()) {
    kernel::BytecodeReader::ReadFunctionBytecode(Thread::Current(), function);
  }
  const Bytecode& code = Bytecode::Handle(function.bytecode());
  const ObjectPool& pool = ObjectPool::Handle(code.object_pool());
  uint32_t fp = 0;
  const KBCInstr* const start =
      reinterpret_cast<const KBCInstr*>(code.instructions());
  for (const KBCInstr* instr = start; (instr - start) < code.Size();
       instr = KernelBytecode::Next(instr)) {
    const KernelBytecode::Opcode opcode = KernelBytecode::DecodeOpcode(instr);
    fp = CombineHashes(fp, opcode);
    switch (opcode) {
#define FINGERPRINT_BYTECODE(name, encoding, kind, op1, op2, op3)              \
  case KernelBytecode::k##name:                                                \
    fp = Fingerprint##encoding(fp, instr, pool, Fp##op1, Fp##op2, Fp##op3);    \
    break;
      KERNEL_BYTECODES_LIST(FINGERPRINT_BYTECODE)
#undef FINGERPRINT_BYTECODE
      default:
        UNREACHABLE();
    }
  }

  return FinalizeHash(fp, 30);
}

}  // namespace kernel
}  // namespace dart

#endif  // !defined(DART_PRECOMPILED_RUNTIME)
