1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef V8_CCTEST_COMPILER_CALL_TESTER_H_
6 #define V8_CCTEST_COMPILER_CALL_TESTER_H_
10 #include "src/simulator.h"
12 #if V8_TARGET_ARCH_IA32
14 #define V8_CDECL __attribute__((cdecl))
16 #define V8_CDECL __cdecl
26 // TODO(titzer): use c-signature.h instead of ReturnValueTraits
28 struct ReturnValueTraits {
29 static R Cast(uintptr_t r) { return reinterpret_cast<R>(r); }
30 static MachineType Representation() {
31 // TODO(dcarney): detect when R is of a subclass of Object* instead of this
34 *(static_cast<Object* volatile*>(0)) = static_cast<R>(0);
36 return kMachAnyTagged;
41 struct ReturnValueTraits<int32_t*> {
42 static int32_t* Cast(uintptr_t r) { return reinterpret_cast<int32_t*>(r); }
43 static MachineType Representation() { return kMachPtr; }
47 struct ReturnValueTraits<void> {
48 static void Cast(uintptr_t r) {}
49 static MachineType Representation() { return kMachPtr; }
53 struct ReturnValueTraits<bool> {
54 static bool Cast(uintptr_t r) { return static_cast<bool>(r); }
55 static MachineType Representation() { return kRepBit; }
59 struct ReturnValueTraits<int32_t> {
60 static int32_t Cast(uintptr_t r) { return static_cast<int32_t>(r); }
61 static MachineType Representation() { return kMachInt32; }
65 struct ReturnValueTraits<uint32_t> {
66 static uint32_t Cast(uintptr_t r) { return static_cast<uint32_t>(r); }
67 static MachineType Representation() { return kMachUint32; }
71 struct ReturnValueTraits<int64_t> {
72 static int64_t Cast(uintptr_t r) { return static_cast<int64_t>(r); }
73 static MachineType Representation() { return kMachInt64; }
77 struct ReturnValueTraits<uint64_t> {
78 static uint64_t Cast(uintptr_t r) { return static_cast<uint64_t>(r); }
79 static MachineType Representation() { return kMachUint64; }
83 struct ReturnValueTraits<int16_t> {
84 static int16_t Cast(uintptr_t r) { return static_cast<int16_t>(r); }
85 static MachineType Representation() { return kMachInt16; }
89 struct ReturnValueTraits<uint16_t> {
90 static uint16_t Cast(uintptr_t r) { return static_cast<uint16_t>(r); }
91 static MachineType Representation() { return kMachUint16; }
95 struct ReturnValueTraits<int8_t> {
96 static int8_t Cast(uintptr_t r) { return static_cast<int8_t>(r); }
97 static MachineType Representation() { return kMachInt8; }
101 struct ReturnValueTraits<uint8_t> {
102 static uint8_t Cast(uintptr_t r) { return static_cast<uint8_t>(r); }
103 static MachineType Representation() { return kMachUint8; }
107 struct ReturnValueTraits<double> {
108 static double Cast(uintptr_t r) {
112 static MachineType Representation() { return kMachFloat64; }
116 template <typename R>
117 struct ParameterTraits {
118 static uintptr_t Cast(R r) { return static_cast<uintptr_t>(r); }
122 struct ParameterTraits<int*> {
123 static uintptr_t Cast(int* r) { return reinterpret_cast<uintptr_t>(r); }
126 template <typename T>
127 struct ParameterTraits<T*> {
128 static uintptr_t Cast(void* r) { return reinterpret_cast<uintptr_t>(r); }
131 // Additional template specialization required for mips64 to sign-extend
132 // parameters defined by calling convention.
134 struct ParameterTraits<int32_t> {
135 static int64_t Cast(int32_t r) { return static_cast<int64_t>(r); }
139 struct ParameterTraits<uint32_t> {
140 static int64_t Cast(uint32_t r) {
141 return static_cast<int64_t>(static_cast<int32_t>(r));
147 explicit CallHelper(Isolate* isolate, MachineSignature* machine_sig)
148 : machine_sig_(machine_sig), isolate_(isolate) {
151 virtual ~CallHelper() {}
153 static MachineSignature* MakeMachineSignature(
154 Zone* zone, MachineType return_type, MachineType p0 = kMachNone,
155 MachineType p1 = kMachNone, MachineType p2 = kMachNone,
156 MachineType p3 = kMachNone, MachineType p4 = kMachNone) {
157 // Count the number of parameters.
158 size_t param_count = 5;
159 MachineType types[] = {p0, p1, p2, p3, p4};
160 while (param_count > 0 && types[param_count - 1] == kMachNone)
162 size_t return_count = return_type == kMachNone ? 0 : 1;
164 // Build the machine signature.
165 MachineSignature::Builder builder(zone, return_count, param_count);
166 if (return_count > 0) builder.AddReturn(return_type);
167 for (size_t i = 0; i < param_count; i++) {
168 builder.AddParam(types[i]);
170 return builder.Build();
174 MachineSignature* machine_sig_;
175 void VerifyParameters(size_t parameter_count, MachineType* parameter_types) {
176 CHECK(machine_sig_->parameter_count() == parameter_count);
177 for (size_t i = 0; i < parameter_count; i++) {
178 CHECK_EQ(machine_sig_->GetParam(i), parameter_types[i]);
181 virtual byte* Generate() = 0;
184 #if USE_SIMULATOR && V8_TARGET_ARCH_ARM64
185 uintptr_t CallSimulator(byte* f, Simulator::CallArgument* args) {
186 Simulator* simulator = Simulator::current(isolate_);
187 return static_cast<uintptr_t>(simulator->CallInt64(f, args));
190 template <typename R, typename F>
192 Simulator::CallArgument args[] = {Simulator::CallArgument::End()};
193 return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args));
195 template <typename R, typename F, typename P1>
196 R DoCall(F* f, P1 p1) {
197 Simulator::CallArgument args[] = {Simulator::CallArgument(p1),
198 Simulator::CallArgument::End()};
199 return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args));
201 template <typename R, typename F, typename P1, typename P2>
202 R DoCall(F* f, P1 p1, P2 p2) {
203 Simulator::CallArgument args[] = {Simulator::CallArgument(p1),
204 Simulator::CallArgument(p2),
205 Simulator::CallArgument::End()};
206 return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args));
208 template <typename R, typename F, typename P1, typename P2, typename P3>
209 R DoCall(F* f, P1 p1, P2 p2, P3 p3) {
210 Simulator::CallArgument args[] = {
211 Simulator::CallArgument(p1), Simulator::CallArgument(p2),
212 Simulator::CallArgument(p3), Simulator::CallArgument::End()};
213 return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args));
215 template <typename R, typename F, typename P1, typename P2, typename P3,
217 R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) {
218 Simulator::CallArgument args[] = {
219 Simulator::CallArgument(p1), Simulator::CallArgument(p2),
220 Simulator::CallArgument(p3), Simulator::CallArgument(p4),
221 Simulator::CallArgument::End()};
222 return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args));
224 #elif USE_SIMULATOR && (V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_PPC64)
225 uintptr_t CallSimulator(byte* f, int64_t p1 = 0, int64_t p2 = 0,
226 int64_t p3 = 0, int64_t p4 = 0) {
227 Simulator* simulator = Simulator::current(isolate_);
228 return static_cast<uintptr_t>(simulator->Call(f, 4, p1, p2, p3, p4));
232 template <typename R, typename F>
234 return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f)));
236 template <typename R, typename F, typename P1>
237 R DoCall(F* f, P1 p1) {
238 return ReturnValueTraits<R>::Cast(
239 CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1)));
241 template <typename R, typename F, typename P1, typename P2>
242 R DoCall(F* f, P1 p1, P2 p2) {
243 return ReturnValueTraits<R>::Cast(
244 CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
245 ParameterTraits<P2>::Cast(p2)));
247 template <typename R, typename F, typename P1, typename P2, typename P3>
248 R DoCall(F* f, P1 p1, P2 p2, P3 p3) {
249 return ReturnValueTraits<R>::Cast(CallSimulator(
250 FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
251 ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3)));
253 template <typename R, typename F, typename P1, typename P2, typename P3,
255 R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) {
256 return ReturnValueTraits<R>::Cast(CallSimulator(
257 FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
258 ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3),
259 ParameterTraits<P4>::Cast(p4)));
261 #elif USE_SIMULATOR && \
262 (V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_PPC)
263 uintptr_t CallSimulator(byte* f, int32_t p1 = 0, int32_t p2 = 0,
264 int32_t p3 = 0, int32_t p4 = 0) {
265 Simulator* simulator = Simulator::current(isolate_);
266 return static_cast<uintptr_t>(simulator->Call(f, 4, p1, p2, p3, p4));
268 template <typename R, typename F>
270 return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f)));
272 template <typename R, typename F, typename P1>
273 R DoCall(F* f, P1 p1) {
274 return ReturnValueTraits<R>::Cast(
275 CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1)));
277 template <typename R, typename F, typename P1, typename P2>
278 R DoCall(F* f, P1 p1, P2 p2) {
279 return ReturnValueTraits<R>::Cast(
280 CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
281 ParameterTraits<P2>::Cast(p2)));
283 template <typename R, typename F, typename P1, typename P2, typename P3>
284 R DoCall(F* f, P1 p1, P2 p2, P3 p3) {
285 return ReturnValueTraits<R>::Cast(CallSimulator(
286 FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
287 ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3)));
289 template <typename R, typename F, typename P1, typename P2, typename P3,
291 R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) {
292 return ReturnValueTraits<R>::Cast(CallSimulator(
293 FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
294 ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3),
295 ParameterTraits<P4>::Cast(p4)));
298 template <typename R, typename F>
302 template <typename R, typename F, typename P1>
303 R DoCall(F* f, P1 p1) {
306 template <typename R, typename F, typename P1, typename P2>
307 R DoCall(F* f, P1 p1, P2 p2) {
310 template <typename R, typename F, typename P1, typename P2, typename P3>
311 R DoCall(F* f, P1 p1, P2 p2, P3 p3) {
312 return f(p1, p2, p3);
314 template <typename R, typename F, typename P1, typename P2, typename P3,
316 R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) {
317 return f(p1, p2, p3, p4);
322 void VerifyParameters0() {}
324 template <typename P1>
325 void VerifyParameters1() {}
327 template <typename P1, typename P2>
328 void VerifyParameters2() {}
330 template <typename P1, typename P2, typename P3>
331 void VerifyParameters3() {}
333 template <typename P1, typename P2, typename P3, typename P4>
334 void VerifyParameters4() {}
336 void VerifyParameters0() { VerifyParameters(0, NULL); }
338 template <typename P1>
339 void VerifyParameters1() {
340 MachineType parameters[] = {ReturnValueTraits<P1>::Representation()};
341 VerifyParameters(arraysize(parameters), parameters);
344 template <typename P1, typename P2>
345 void VerifyParameters2() {
346 MachineType parameters[] = {ReturnValueTraits<P1>::Representation(),
347 ReturnValueTraits<P2>::Representation()};
348 VerifyParameters(arraysize(parameters), parameters);
351 template <typename P1, typename P2, typename P3>
352 void VerifyParameters3() {
353 MachineType parameters[] = {ReturnValueTraits<P1>::Representation(),
354 ReturnValueTraits<P2>::Representation(),
355 ReturnValueTraits<P3>::Representation()};
356 VerifyParameters(arraysize(parameters), parameters);
359 template <typename P1, typename P2, typename P3, typename P4>
360 void VerifyParameters4() {
361 MachineType parameters[] = {ReturnValueTraits<P1>::Representation(),
362 ReturnValueTraits<P2>::Representation(),
363 ReturnValueTraits<P3>::Representation(),
364 ReturnValueTraits<P4>::Representation()};
365 VerifyParameters(arraysize(parameters), parameters);
369 // TODO(dcarney): replace Call() in CallHelper2 with these.
370 template <typename R>
372 typedef R V8_CDECL FType();
374 return DoCall<R>(FUNCTION_CAST<FType*>(Generate()));
377 template <typename R, typename P1>
379 typedef R V8_CDECL FType(P1);
380 VerifyParameters1<P1>();
381 return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1);
384 template <typename R, typename P1, typename P2>
385 R Call2(P1 p1, P2 p2) {
386 typedef R V8_CDECL FType(P1, P2);
387 VerifyParameters2<P1, P2>();
388 return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1, p2);
391 template <typename R, typename P1, typename P2, typename P3>
392 R Call3(P1 p1, P2 p2, P3 p3) {
393 typedef R V8_CDECL FType(P1, P2, P3);
394 VerifyParameters3<P1, P2, P3>();
395 return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3);
398 template <typename R, typename P1, typename P2, typename P3, typename P4>
399 R Call4(P1 p1, P2 p2, P3 p3, P4 p4) {
400 typedef R V8_CDECL FType(P1, P2, P3, P4);
401 VerifyParameters4<P1, P2, P3, P4>();
402 return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3, p4);
405 template <typename R, typename C>
406 friend class CallHelper2;
411 // TODO(dcarney): replace CallHelper with CallHelper2 and rename.
412 template <typename R, typename C>
415 R Call() { return helper()->template Call0<R>(); }
417 template <typename P1>
419 return helper()->template Call1<R>(p1);
422 template <typename P1, typename P2>
423 R Call(P1 p1, P2 p2) {
424 return helper()->template Call2<R>(p1, p2);
427 template <typename P1, typename P2, typename P3>
428 R Call(P1 p1, P2 p2, P3 p3) {
429 return helper()->template Call3<R>(p1, p2, p3);
432 template <typename P1, typename P2, typename P3, typename P4>
433 R Call(P1 p1, P2 p2, P3 p3, P4 p4) {
434 return helper()->template Call4<R>(p1, p2, p3, p4);
438 CallHelper* helper() { return static_cast<C*>(this); }
441 } // namespace compiler
442 } // namespace internal
445 #endif // V8_CCTEST_COMPILER_CALL_TESTER_H_