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); }
133 explicit CallHelper(Isolate* isolate, MachineSignature* machine_sig)
134 : machine_sig_(machine_sig), isolate_(isolate) {
137 virtual ~CallHelper() {}
139 static MachineSignature* MakeMachineSignature(
140 Zone* zone, MachineType return_type, MachineType p0 = kMachNone,
141 MachineType p1 = kMachNone, MachineType p2 = kMachNone,
142 MachineType p3 = kMachNone, MachineType p4 = kMachNone) {
143 // Count the number of parameters.
144 size_t param_count = 5;
145 MachineType types[] = {p0, p1, p2, p3, p4};
146 while (param_count > 0 && types[param_count - 1] == kMachNone)
148 size_t return_count = return_type == kMachNone ? 0 : 1;
150 // Build the machine signature.
151 MachineSignature::Builder builder(zone, return_count, param_count);
152 if (return_count > 0) builder.AddReturn(return_type);
153 for (size_t i = 0; i < param_count; i++) {
154 builder.AddParam(types[i]);
156 return builder.Build();
160 MachineSignature* machine_sig_;
161 void VerifyParameters(size_t parameter_count, MachineType* parameter_types) {
162 CHECK(machine_sig_->parameter_count() == parameter_count);
163 for (size_t i = 0; i < parameter_count; i++) {
164 CHECK_EQ(machine_sig_->GetParam(i), parameter_types[i]);
167 virtual byte* Generate() = 0;
170 #if USE_SIMULATOR && V8_TARGET_ARCH_ARM64
171 uintptr_t CallSimulator(byte* f, Simulator::CallArgument* args) {
172 Simulator* simulator = Simulator::current(isolate_);
173 return static_cast<uintptr_t>(simulator->CallInt64(f, args));
176 template <typename R, typename F>
178 Simulator::CallArgument args[] = {Simulator::CallArgument::End()};
179 return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args));
181 template <typename R, typename F, typename P1>
182 R DoCall(F* f, P1 p1) {
183 Simulator::CallArgument args[] = {Simulator::CallArgument(p1),
184 Simulator::CallArgument::End()};
185 return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args));
187 template <typename R, typename F, typename P1, typename P2>
188 R DoCall(F* f, P1 p1, P2 p2) {
189 Simulator::CallArgument args[] = {Simulator::CallArgument(p1),
190 Simulator::CallArgument(p2),
191 Simulator::CallArgument::End()};
192 return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args));
194 template <typename R, typename F, typename P1, typename P2, typename P3>
195 R DoCall(F* f, P1 p1, P2 p2, P3 p3) {
196 Simulator::CallArgument args[] = {
197 Simulator::CallArgument(p1), Simulator::CallArgument(p2),
198 Simulator::CallArgument(p3), Simulator::CallArgument::End()};
199 return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args));
201 template <typename R, typename F, typename P1, typename P2, typename P3,
203 R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) {
204 Simulator::CallArgument args[] = {
205 Simulator::CallArgument(p1), Simulator::CallArgument(p2),
206 Simulator::CallArgument(p3), Simulator::CallArgument(p4),
207 Simulator::CallArgument::End()};
208 return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args));
210 #elif USE_SIMULATOR && (V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS)
211 uintptr_t CallSimulator(byte* f, int32_t p1 = 0, int32_t p2 = 0,
212 int32_t p3 = 0, int32_t p4 = 0) {
213 Simulator* simulator = Simulator::current(isolate_);
214 return static_cast<uintptr_t>(simulator->Call(f, 4, p1, p2, p3, p4));
216 template <typename R, typename F>
218 return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f)));
220 template <typename R, typename F, typename P1>
221 R DoCall(F* f, P1 p1) {
222 return ReturnValueTraits<R>::Cast(
223 CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1)));
225 template <typename R, typename F, typename P1, typename P2>
226 R DoCall(F* f, P1 p1, P2 p2) {
227 return ReturnValueTraits<R>::Cast(
228 CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
229 ParameterTraits<P2>::Cast(p2)));
231 template <typename R, typename F, typename P1, typename P2, typename P3>
232 R DoCall(F* f, P1 p1, P2 p2, P3 p3) {
233 return ReturnValueTraits<R>::Cast(CallSimulator(
234 FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
235 ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3)));
237 template <typename R, typename F, typename P1, typename P2, typename P3,
239 R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) {
240 return ReturnValueTraits<R>::Cast(CallSimulator(
241 FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
242 ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3),
243 ParameterTraits<P4>::Cast(p4)));
246 template <typename R, typename F>
250 template <typename R, typename F, typename P1>
251 R DoCall(F* f, P1 p1) {
254 template <typename R, typename F, typename P1, typename P2>
255 R DoCall(F* f, P1 p1, P2 p2) {
258 template <typename R, typename F, typename P1, typename P2, typename P3>
259 R DoCall(F* f, P1 p1, P2 p2, P3 p3) {
260 return f(p1, p2, p3);
262 template <typename R, typename F, typename P1, typename P2, typename P3,
264 R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) {
265 return f(p1, p2, p3, p4);
270 void VerifyParameters0() {}
272 template <typename P1>
273 void VerifyParameters1() {}
275 template <typename P1, typename P2>
276 void VerifyParameters2() {}
278 template <typename P1, typename P2, typename P3>
279 void VerifyParameters3() {}
281 template <typename P1, typename P2, typename P3, typename P4>
282 void VerifyParameters4() {}
284 void VerifyParameters0() { VerifyParameters(0, NULL); }
286 template <typename P1>
287 void VerifyParameters1() {
288 MachineType parameters[] = {ReturnValueTraits<P1>::Representation()};
289 VerifyParameters(arraysize(parameters), parameters);
292 template <typename P1, typename P2>
293 void VerifyParameters2() {
294 MachineType parameters[] = {ReturnValueTraits<P1>::Representation(),
295 ReturnValueTraits<P2>::Representation()};
296 VerifyParameters(arraysize(parameters), parameters);
299 template <typename P1, typename P2, typename P3>
300 void VerifyParameters3() {
301 MachineType parameters[] = {ReturnValueTraits<P1>::Representation(),
302 ReturnValueTraits<P2>::Representation(),
303 ReturnValueTraits<P3>::Representation()};
304 VerifyParameters(arraysize(parameters), parameters);
307 template <typename P1, typename P2, typename P3, typename P4>
308 void VerifyParameters4() {
309 MachineType parameters[] = {ReturnValueTraits<P1>::Representation(),
310 ReturnValueTraits<P2>::Representation(),
311 ReturnValueTraits<P3>::Representation(),
312 ReturnValueTraits<P4>::Representation()};
313 VerifyParameters(arraysize(parameters), parameters);
317 // TODO(dcarney): replace Call() in CallHelper2 with these.
318 template <typename R>
320 typedef R V8_CDECL FType();
322 return DoCall<R>(FUNCTION_CAST<FType*>(Generate()));
325 template <typename R, typename P1>
327 typedef R V8_CDECL FType(P1);
328 VerifyParameters1<P1>();
329 return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1);
332 template <typename R, typename P1, typename P2>
333 R Call2(P1 p1, P2 p2) {
334 typedef R V8_CDECL FType(P1, P2);
335 VerifyParameters2<P1, P2>();
336 return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1, p2);
339 template <typename R, typename P1, typename P2, typename P3>
340 R Call3(P1 p1, P2 p2, P3 p3) {
341 typedef R V8_CDECL FType(P1, P2, P3);
342 VerifyParameters3<P1, P2, P3>();
343 return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3);
346 template <typename R, typename P1, typename P2, typename P3, typename P4>
347 R Call4(P1 p1, P2 p2, P3 p3, P4 p4) {
348 typedef R V8_CDECL FType(P1, P2, P3, P4);
349 VerifyParameters4<P1, P2, P3, P4>();
350 return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3, p4);
353 template <typename R, typename C>
354 friend class CallHelper2;
359 // TODO(dcarney): replace CallHelper with CallHelper2 and rename.
360 template <typename R, typename C>
363 R Call() { return helper()->template Call0<R>(); }
365 template <typename P1>
367 return helper()->template Call1<R>(p1);
370 template <typename P1, typename P2>
371 R Call(P1 p1, P2 p2) {
372 return helper()->template Call2<R>(p1, p2);
375 template <typename P1, typename P2, typename P3>
376 R Call(P1 p1, P2 p2, P3 p3) {
377 return helper()->template Call3<R>(p1, p2, p3);
380 template <typename P1, typename P2, typename P3, typename P4>
381 R Call(P1 p1, P2 p2, P3 p3, P4 p4) {
382 return helper()->template Call4<R>(p1, p2, p3, p4);
386 CallHelper* helper() { return static_cast<C*>(this); }
389 } // namespace compiler
390 } // namespace internal
393 #endif // V8_CCTEST_COMPILER_CALL_TESTER_H_