2014-07-30 13:54:45 +00:00
|
|
|
// 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_
|
|
|
|
|
2017-05-04 14:19:04 +00:00
|
|
|
#include "src/handles.h"
|
2014-07-30 13:54:45 +00:00
|
|
|
#include "src/simulator.h"
|
2015-06-01 15:54:53 +00:00
|
|
|
#include "test/cctest/compiler/c-signature.h"
|
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
#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>
|
2015-06-01 15:54:53 +00:00
|
|
|
inline R CastReturnValue(uintptr_t r) {
|
|
|
|
return reinterpret_cast<R>(r);
|
|
|
|
}
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
template <>
|
2015-06-01 15:54:53 +00:00
|
|
|
inline void CastReturnValue(uintptr_t r) {}
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
template <>
|
2015-06-01 15:54:53 +00:00
|
|
|
inline bool CastReturnValue(uintptr_t r) {
|
|
|
|
return static_cast<bool>(r);
|
|
|
|
}
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
template <>
|
2015-06-01 15:54:53 +00:00
|
|
|
inline int32_t CastReturnValue(uintptr_t r) {
|
|
|
|
return static_cast<int32_t>(r);
|
|
|
|
}
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
template <>
|
2015-06-01 15:54:53 +00:00
|
|
|
inline uint32_t CastReturnValue(uintptr_t r) {
|
|
|
|
return static_cast<uint32_t>(r);
|
|
|
|
}
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
template <>
|
2015-06-01 15:54:53 +00:00
|
|
|
inline int64_t CastReturnValue(uintptr_t r) {
|
|
|
|
return static_cast<int64_t>(r);
|
|
|
|
}
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
template <>
|
2015-06-01 15:54:53 +00:00
|
|
|
inline uint64_t CastReturnValue(uintptr_t r) {
|
|
|
|
return static_cast<uint64_t>(r);
|
|
|
|
}
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
template <>
|
2015-06-01 15:54:53 +00:00
|
|
|
inline int16_t CastReturnValue(uintptr_t r) {
|
|
|
|
return static_cast<int16_t>(r);
|
|
|
|
}
|
2014-07-30 13:54:45 +00:00
|
|
|
|
2014-08-25 10:35:38 +00:00
|
|
|
template <>
|
2015-06-01 15:54:53 +00:00
|
|
|
inline uint16_t CastReturnValue(uintptr_t r) {
|
|
|
|
return static_cast<uint16_t>(r);
|
|
|
|
}
|
2014-08-25 10:35:38 +00:00
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
template <>
|
2015-06-01 15:54:53 +00:00
|
|
|
inline int8_t CastReturnValue(uintptr_t r) {
|
|
|
|
return static_cast<int8_t>(r);
|
|
|
|
}
|
2014-07-30 13:54:45 +00:00
|
|
|
|
2014-08-25 10:35:38 +00:00
|
|
|
template <>
|
2015-06-01 15:54:53 +00:00
|
|
|
inline uint8_t CastReturnValue(uintptr_t r) {
|
|
|
|
return static_cast<uint8_t>(r);
|
|
|
|
}
|
2014-08-25 10:35:38 +00:00
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
template <>
|
2015-06-01 15:54:53 +00:00
|
|
|
inline double CastReturnValue(uintptr_t r) {
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
2014-07-30 13:54:45 +00:00
|
|
|
|
|
|
|
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); }
|
|
|
|
};
|
|
|
|
|
2015-04-28 06:54:08 +00:00
|
|
|
|
|
|
|
#if !V8_TARGET_ARCH_32_BIT
|
|
|
|
|
2015-03-16 11:00:00 +00:00
|
|
|
// 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); }
|
|
|
|
};
|
|
|
|
|
2016-04-25 14:03:42 +00:00
|
|
|
#if !V8_TARGET_ARCH_PPC64
|
2015-03-16 11:00:00 +00:00
|
|
|
template <>
|
|
|
|
struct ParameterTraits<uint32_t> {
|
|
|
|
static int64_t Cast(uint32_t r) {
|
|
|
|
return static_cast<int64_t>(static_cast<int32_t>(r));
|
|
|
|
}
|
|
|
|
};
|
2016-04-25 14:03:42 +00:00
|
|
|
#endif
|
2015-03-16 11:00:00 +00:00
|
|
|
|
2015-04-28 06:54:08 +00:00
|
|
|
#endif // !V8_TARGET_ARCH_64_BIT
|
|
|
|
|
|
|
|
|
2015-05-29 14:05:39 +00:00
|
|
|
template <typename R>
|
2014-07-30 13:54:45 +00:00
|
|
|
class CallHelper {
|
|
|
|
public:
|
2016-02-18 09:55:25 +00:00
|
|
|
explicit CallHelper(Isolate* isolate, MachineSignature* csig)
|
2015-06-02 15:00:55 +00:00
|
|
|
: csig_(csig), isolate_(isolate) {
|
2014-09-03 10:13:21 +00:00
|
|
|
USE(isolate_);
|
|
|
|
}
|
2014-07-30 13:54:45 +00:00
|
|
|
virtual ~CallHelper() {}
|
|
|
|
|
2017-05-04 14:19:04 +00:00
|
|
|
template <typename... Params>
|
|
|
|
R Call(Params... args) {
|
|
|
|
using FType = R(V8_CDECL*)(Params...);
|
|
|
|
CSignature::VerifyParams<Params...>(csig_);
|
|
|
|
return DoCall(FUNCTION_CAST<FType>(Generate()), args...);
|
2015-10-30 21:32:35 +00:00
|
|
|
}
|
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
protected:
|
2016-02-18 09:55:25 +00:00
|
|
|
MachineSignature* csig_;
|
2015-05-29 14:05:39 +00:00
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2017-05-04 14:19:04 +00:00
|
|
|
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));
|
2015-10-30 21:32:35 +00:00
|
|
|
}
|
2016-03-15 18:07:43 +00:00
|
|
|
#elif USE_SIMULATOR && \
|
|
|
|
(V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_PPC64 || V8_TARGET_ARCH_S390X)
|
2014-11-19 15:44:39 +00:00
|
|
|
uintptr_t CallSimulator(byte* f, int64_t p1 = 0, int64_t p2 = 0,
|
2015-10-30 21:32:35 +00:00
|
|
|
int64_t p3 = 0, int64_t p4 = 0, int64_t p5 = 0) {
|
2014-11-19 15:44:39 +00:00
|
|
|
Simulator* simulator = Simulator::current(isolate_);
|
2015-10-30 21:32:35 +00:00
|
|
|
return static_cast<uintptr_t>(simulator->Call(f, 5, p1, p2, p3, p4, p5));
|
2014-11-19 15:44:39 +00:00
|
|
|
}
|
|
|
|
|
2017-05-04 14:19:04 +00:00
|
|
|
template <typename F, typename... Params>
|
|
|
|
R DoCall(F* f, Params... args) {
|
2015-10-30 21:32:35 +00:00
|
|
|
return CastReturnValue<R>(CallSimulator(
|
2017-05-04 14:19:04 +00:00
|
|
|
FUNCTION_ADDR(f), ParameterTraits<Params>::Cast(args)...));
|
2015-10-30 21:32:35 +00:00
|
|
|
}
|
2016-03-15 18:07:43 +00:00
|
|
|
#elif USE_SIMULATOR && (V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS || \
|
|
|
|
V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_S390)
|
2014-07-30 13:54:45 +00:00
|
|
|
uintptr_t CallSimulator(byte* f, int32_t p1 = 0, int32_t p2 = 0,
|
2015-10-30 21:32:35 +00:00
|
|
|
int32_t p3 = 0, int32_t p4 = 0, int32_t p5 = 0) {
|
2014-07-30 13:54:45 +00:00
|
|
|
Simulator* simulator = Simulator::current(isolate_);
|
2015-10-30 21:32:35 +00:00
|
|
|
return static_cast<uintptr_t>(simulator->Call(f, 5, p1, p2, p3, p4, p5));
|
2014-07-30 13:54:45 +00:00
|
|
|
}
|
2017-05-04 14:19:04 +00:00
|
|
|
|
|
|
|
template <typename F, typename... Params>
|
|
|
|
R DoCall(F* f, Params... args) {
|
2015-10-30 21:32:35 +00:00
|
|
|
return CastReturnValue<R>(CallSimulator(
|
2017-05-04 14:19:04 +00:00
|
|
|
FUNCTION_ADDR(f), ParameterTraits<Params>::Cast(args)...));
|
2015-10-30 21:32:35 +00:00
|
|
|
}
|
2014-07-30 13:54:45 +00:00
|
|
|
#else
|
2017-05-04 14:19:04 +00:00
|
|
|
template <typename F, typename... Params>
|
|
|
|
R DoCall(F* f, Params... args) {
|
|
|
|
return f(args...);
|
2015-10-30 21:32:35 +00:00
|
|
|
}
|
2014-07-30 13:54:45 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
Isolate* isolate_;
|
|
|
|
};
|
|
|
|
|
2015-08-11 15:23:04 +00:00
|
|
|
// A call helper that calls the given code object assuming C calling convention.
|
|
|
|
template <typename T>
|
|
|
|
class CodeRunner : public CallHelper<T> {
|
|
|
|
public:
|
2016-02-18 09:55:25 +00:00
|
|
|
CodeRunner(Isolate* isolate, Handle<Code> code, MachineSignature* csig)
|
2015-08-11 15:23:04 +00:00
|
|
|
: CallHelper<T>(isolate, csig), code_(code) {}
|
|
|
|
virtual ~CodeRunner() {}
|
|
|
|
|
|
|
|
virtual byte* Generate() { return code_->entry(); }
|
|
|
|
|
|
|
|
private:
|
|
|
|
Handle<Code> code_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-07-30 13:54:45 +00:00
|
|
|
} // namespace compiler
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|
|
|
|
|
|
|
|
#endif // V8_CCTEST_COMPILER_CALL_TESTER_H_
|