// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_SIMULATOR_BASE_H_
#define V8_SIMULATOR_BASE_H_

#include <type_traits>

#include "src/globals.h"
#include "src/isolate.h"

#if defined(USE_SIMULATOR)

namespace v8 {
namespace internal {

class Instruction;
class Redirection;

class SimulatorBase {
 public:
  // Call on process start and exit.
  static void InitializeOncePerProcess();
  static void GlobalTearDown();

  static base::Mutex* redirection_mutex() { return redirection_mutex_; }
  static Redirection* redirection() { return redirection_; }
  static void set_redirection(Redirection* r) { redirection_ = r; }

  static base::Mutex* i_cache_mutex() { return i_cache_mutex_; }
  static base::CustomMatcherHashMap* i_cache() { return i_cache_; }

  // Runtime call support.
  static Address RedirectExternalReference(Address external_function,
                                           ExternalReference::Type type);

 protected:
  template <typename Return, typename SimT, typename CallImpl, typename... Args>
  static Return VariadicCall(SimT* sim, CallImpl call, Address entry,
                             Args... args) {
    // Convert all arguments to intptr_t. Fails if any argument is not integral
    // or pointer.
    std::array<intptr_t, sizeof...(args)> args_arr{{ConvertArg(args)...}};
    intptr_t ret = (sim->*call)(entry, args_arr.size(), args_arr.data());
    return ConvertReturn<Return>(ret);
  }

  // Convert back integral return types. This is always a narrowing conversion.
  template <typename T>
  static typename std::enable_if<std::is_integral<T>::value, T>::type
  ConvertReturn(intptr_t ret) {
    static_assert(sizeof(T) <= sizeof(intptr_t), "type bigger than ptrsize");
    return static_cast<T>(ret);
  }

  // Convert back pointer-typed return types.
  template <typename T>
  static typename std::enable_if<std::is_pointer<T>::value, T>::type
  ConvertReturn(intptr_t ret) {
    return reinterpret_cast<T>(ret);
  }

  template <typename T>
  static typename std::enable_if<std::is_base_of<Object, T>::value, T>::type
  ConvertReturn(intptr_t ret) {
    return Object(ret);
  }

  // Convert back void return type (i.e. no return).
  template <typename T>
  static typename std::enable_if<std::is_void<T>::value, T>::type ConvertReturn(
      intptr_t ret) {}

 private:
  static base::Mutex* redirection_mutex_;
  static Redirection* redirection_;

  static base::Mutex* i_cache_mutex_;
  static base::CustomMatcherHashMap* i_cache_;

  // Helper methods to convert arbitrary integer or pointer arguments to the
  // needed generic argument type intptr_t.

  // Convert integral argument to intptr_t.
  template <typename T>
  static typename std::enable_if<std::is_integral<T>::value, intptr_t>::type
  ConvertArg(T arg) {
    static_assert(sizeof(T) <= sizeof(intptr_t), "type bigger than ptrsize");
#if V8_TARGET_ARCH_MIPS64
    // The MIPS64 calling convention is to sign extend all values, even unsigned
    // ones.
    using signed_t = typename std::make_signed<T>::type;
    return static_cast<intptr_t>(static_cast<signed_t>(arg));
#else
    // Standard C++ convertion: Sign-extend signed values, zero-extend unsigned
    // values.
    return static_cast<intptr_t>(arg);
#endif
  }

  // Convert pointer-typed argument to intptr_t.
  template <typename T>
  static typename std::enable_if<std::is_pointer<T>::value, intptr_t>::type
  ConvertArg(T arg) {
    return reinterpret_cast<intptr_t>(arg);
  }
};

// When the generated code calls an external reference we need to catch that in
// the simulator.  The external reference will be a function compiled for the
// host architecture.  We need to call that function instead of trying to
// execute it with the simulator.  We do that by redirecting the external
// reference to a trapping instruction that is handled by the simulator.  We
// write the original destination of the jump just at a known offset from the
// trapping instruction so the simulator knows what to call.
//
// The following are trapping instructions used for various architectures:
//  - V8_TARGET_ARCH_ARM: svc (Supervisor Call)
//  - V8_TARGET_ARCH_ARM64: svc (Supervisor Call)
//  - V8_TARGET_ARCH_MIPS: swi (software-interrupt)
//  - V8_TARGET_ARCH_MIPS64: swi (software-interrupt)
//  - V8_TARGET_ARCH_PPC: svc (Supervisor Call)
//  - V8_TARGET_ARCH_S390: svc (Supervisor Call)
class Redirection {
 public:
  Redirection(Address external_function, ExternalReference::Type type);

  Address address_of_instruction() {
#if ABI_USES_FUNCTION_DESCRIPTORS
    return reinterpret_cast<Address>(function_descriptor_);
#else
    return reinterpret_cast<Address>(&instruction_);
#endif
  }

  void* external_function() {
    return reinterpret_cast<void*>(external_function_);
  }
  ExternalReference::Type type() { return type_; }

  static Redirection* Get(Address external_function,
                          ExternalReference::Type type);

  static Redirection* FromInstruction(Instruction* instruction) {
    Address addr_of_instruction = reinterpret_cast<Address>(instruction);
    Address addr_of_redirection =
        addr_of_instruction - offsetof(Redirection, instruction_);
    return reinterpret_cast<Redirection*>(addr_of_redirection);
  }

  static void* ReverseRedirection(intptr_t reg) {
    Redirection* redirection = FromInstruction(
        reinterpret_cast<Instruction*>(reinterpret_cast<void*>(reg)));
    return redirection->external_function();
  }

  static void DeleteChain(Redirection* redirection) {
    while (redirection != nullptr) {
      Redirection* next = redirection->next_;
      delete redirection;
      redirection = next;
    }
  }

 private:
  Address external_function_;
  uint32_t instruction_;
  ExternalReference::Type type_;
  Redirection* next_;
#if ABI_USES_FUNCTION_DESCRIPTORS
  intptr_t function_descriptor_[3];
#endif
};

}  // namespace internal
}  // namespace v8

#endif  // defined(USE_SIMULATOR)
#endif  // V8_SIMULATOR_BASE_H_
