call-tester.h 5.28 KB
Newer Older
1 2 3 4 5 6 7
// Copyright 2014 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_CCTEST_COMPILER_CALL_TESTER_H_
#define V8_CCTEST_COMPILER_CALL_TESTER_H_

8
#include "src/handles.h"
9
#include "src/simulator.h"
10 11
#include "test/cctest/compiler/c-signature.h"

12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
#if V8_TARGET_ARCH_IA32
#if __GNUC__
#define V8_CDECL __attribute__((cdecl))
#else
#define V8_CDECL __cdecl
#endif
#else
#define V8_CDECL
#endif

namespace v8 {
namespace internal {
namespace compiler {

template <typename R>
27 28 29
inline R CastReturnValue(uintptr_t r) {
  return reinterpret_cast<R>(r);
}
30 31

template <>
32
inline void CastReturnValue(uintptr_t r) {}
33 34

template <>
35 36 37
inline bool CastReturnValue(uintptr_t r) {
  return static_cast<bool>(r);
}
38 39

template <>
40 41 42
inline int32_t CastReturnValue(uintptr_t r) {
  return static_cast<int32_t>(r);
}
43 44

template <>
45 46 47
inline uint32_t CastReturnValue(uintptr_t r) {
  return static_cast<uint32_t>(r);
}
48 49

template <>
50 51 52
inline int64_t CastReturnValue(uintptr_t r) {
  return static_cast<int64_t>(r);
}
53 54

template <>
55 56 57
inline uint64_t CastReturnValue(uintptr_t r) {
  return static_cast<uint64_t>(r);
}
58 59

template <>
60 61 62
inline int16_t CastReturnValue(uintptr_t r) {
  return static_cast<int16_t>(r);
}
63

64
template <>
65 66 67
inline uint16_t CastReturnValue(uintptr_t r) {
  return static_cast<uint16_t>(r);
}
68

69
template <>
70 71 72
inline int8_t CastReturnValue(uintptr_t r) {
  return static_cast<int8_t>(r);
}
73

74
template <>
75 76 77
inline uint8_t CastReturnValue(uintptr_t r) {
  return static_cast<uint8_t>(r);
}
78

79
template <>
80 81 82
inline double CastReturnValue(uintptr_t r) {
  UNREACHABLE();
}
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98

template <typename R>
struct ParameterTraits {
  static uintptr_t Cast(R r) { return static_cast<uintptr_t>(r); }
};

template <>
struct ParameterTraits<int*> {
  static uintptr_t Cast(int* r) { return reinterpret_cast<uintptr_t>(r); }
};

template <typename T>
struct ParameterTraits<T*> {
  static uintptr_t Cast(void* r) { return reinterpret_cast<uintptr_t>(r); }
};

99 100 101

#if !V8_TARGET_ARCH_32_BIT

102 103 104 105 106 107 108
// Additional template specialization required for mips64 to sign-extend
// parameters defined by calling convention.
template <>
struct ParameterTraits<int32_t> {
  static int64_t Cast(int32_t r) { return static_cast<int64_t>(r); }
};

109
#if !V8_TARGET_ARCH_PPC64
110 111 112 113 114 115
template <>
struct ParameterTraits<uint32_t> {
  static int64_t Cast(uint32_t r) {
    return static_cast<int64_t>(static_cast<int32_t>(r));
  }
};
116
#endif
117

118 119 120
#endif  // !V8_TARGET_ARCH_64_BIT


121
template <typename R>
122 123
class CallHelper {
 public:
124
  explicit CallHelper(Isolate* isolate, MachineSignature* csig)
125
      : csig_(csig), isolate_(isolate) {
126 127
    USE(isolate_);
  }
128 129
  virtual ~CallHelper() {}

130 131 132 133 134
  template <typename... Params>
  R Call(Params... args) {
    using FType = R(V8_CDECL*)(Params...);
    CSignature::VerifyParams<Params...>(csig_);
    return DoCall(FUNCTION_CAST<FType>(Generate()), args...);
135 136
  }

137
 protected:
138
  MachineSignature* csig_;
139

140 141 142 143 144 145 146 147 148
  virtual byte* Generate() = 0;

 private:
#if USE_SIMULATOR && V8_TARGET_ARCH_ARM64
  uintptr_t CallSimulator(byte* f, Simulator::CallArgument* args) {
    Simulator* simulator = Simulator::current(isolate_);
    return static_cast<uintptr_t>(simulator->CallInt64(f, args));
  }

149 150 151 152 153
  template <typename F, typename... Params>
  R DoCall(F* f, Params... args) {
    Simulator::CallArgument args_arr[] = {Simulator::CallArgument(args)...,
                                          Simulator::CallArgument::End()};
    return CastReturnValue<R>(CallSimulator(FUNCTION_ADDR(f), args_arr));
154
  }
155 156
#elif USE_SIMULATOR && \
    (V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_PPC64 || V8_TARGET_ARCH_S390X)
157
  uintptr_t CallSimulator(byte* f, int64_t p1 = 0, int64_t p2 = 0,
158
                          int64_t p3 = 0, int64_t p4 = 0, int64_t p5 = 0) {
159
    Simulator* simulator = Simulator::current(isolate_);
160
    return static_cast<uintptr_t>(simulator->Call(f, 5, p1, p2, p3, p4, p5));
161 162
  }

163 164
  template <typename F, typename... Params>
  R DoCall(F* f, Params... args) {
165
    return CastReturnValue<R>(CallSimulator(
166
        FUNCTION_ADDR(f), ParameterTraits<Params>::Cast(args)...));
167
  }
168 169
#elif USE_SIMULATOR && (V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS || \
                        V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_S390)
170
  uintptr_t CallSimulator(byte* f, int32_t p1 = 0, int32_t p2 = 0,
171
                          int32_t p3 = 0, int32_t p4 = 0, int32_t p5 = 0) {
172
    Simulator* simulator = Simulator::current(isolate_);
173
    return static_cast<uintptr_t>(simulator->Call(f, 5, p1, p2, p3, p4, p5));
174
  }
175 176 177

  template <typename F, typename... Params>
  R DoCall(F* f, Params... args) {
178
    return CastReturnValue<R>(CallSimulator(
179
        FUNCTION_ADDR(f), ParameterTraits<Params>::Cast(args)...));
180
  }
181
#else
182 183 184
  template <typename F, typename... Params>
  R DoCall(F* f, Params... args) {
    return f(args...);
185
  }
186 187 188 189 190
#endif

  Isolate* isolate_;
};

191 192 193 194
// A call helper that calls the given code object assuming C calling convention.
template <typename T>
class CodeRunner : public CallHelper<T> {
 public:
195
  CodeRunner(Isolate* isolate, Handle<Code> code, MachineSignature* csig)
196 197 198 199 200 201 202 203 204 205
      : CallHelper<T>(isolate, csig), code_(code) {}
  virtual ~CodeRunner() {}

  virtual byte* Generate() { return code_->entry(); }

 private:
  Handle<Code> code_;
};


206 207 208 209 210
}  // namespace compiler
}  // namespace internal
}  // namespace v8

#endif  // V8_CCTEST_COMPILER_CALL_TESTER_H_