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_MIPS64 || V8_TARGET_ARCH_PPC64)
211 uintptr_t CallSimulator(byte* f, int64_t p1 = 0, int64_t p2 = 0,
212 int64_t p3 = 0, int64_t p4 = 0) {
213 Simulator* simulator = Simulator::current(isolate_);
214 return static_cast<uintptr_t>(simulator->Call(f, 4, p1, p2, p3, p4));
217 template <typename R, typename F>
219 return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f)));
221 template <typename R, typename F, typename P1>
222 R DoCall(F* f, P1 p1) {
223 return ReturnValueTraits<R>::Cast(
224 CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1)));
226 template <typename R, typename F, typename P1, typename P2>
227 R DoCall(F* f, P1 p1, P2 p2) {
228 return ReturnValueTraits<R>::Cast(
229 CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
230 ParameterTraits<P2>::Cast(p2)));
232 template <typename R, typename F, typename P1, typename P2, typename P3>
233 R DoCall(F* f, P1 p1, P2 p2, P3 p3) {
234 return ReturnValueTraits<R>::Cast(CallSimulator(
235 FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
236 ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3)));
238 template <typename R, typename F, typename P1, typename P2, typename P3,
240 R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) {
241 return ReturnValueTraits<R>::Cast(CallSimulator(
242 FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
243 ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3),
244 ParameterTraits<P4>::Cast(p4)));
246 #elif USE_SIMULATOR && \
247 (V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_PPC)
248 uintptr_t CallSimulator(byte* f, int32_t p1 = 0, int32_t p2 = 0,
249 int32_t p3 = 0, int32_t p4 = 0) {
250 Simulator* simulator = Simulator::current(isolate_);
251 return static_cast<uintptr_t>(simulator->Call(f, 4, p1, p2, p3, p4));
253 template <typename R, typename F>
255 return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f)));
257 template <typename R, typename F, typename P1>
258 R DoCall(F* f, P1 p1) {
259 return ReturnValueTraits<R>::Cast(
260 CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1)));
262 template <typename R, typename F, typename P1, typename P2>
263 R DoCall(F* f, P1 p1, P2 p2) {
264 return ReturnValueTraits<R>::Cast(
265 CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
266 ParameterTraits<P2>::Cast(p2)));
268 template <typename R, typename F, typename P1, typename P2, typename P3>
269 R DoCall(F* f, P1 p1, P2 p2, P3 p3) {
270 return ReturnValueTraits<R>::Cast(CallSimulator(
271 FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
272 ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3)));
274 template <typename R, typename F, typename P1, typename P2, typename P3,
276 R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) {
277 return ReturnValueTraits<R>::Cast(CallSimulator(
278 FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
279 ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3),
280 ParameterTraits<P4>::Cast(p4)));
283 template <typename R, typename F>
287 template <typename R, typename F, typename P1>
288 R DoCall(F* f, P1 p1) {
291 template <typename R, typename F, typename P1, typename P2>
292 R DoCall(F* f, P1 p1, P2 p2) {
295 template <typename R, typename F, typename P1, typename P2, typename P3>
296 R DoCall(F* f, P1 p1, P2 p2, P3 p3) {
297 return f(p1, p2, p3);
299 template <typename R, typename F, typename P1, typename P2, typename P3,
301 R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) {
302 return f(p1, p2, p3, p4);
307 void VerifyParameters0() {}
309 template <typename P1>
310 void VerifyParameters1() {}
312 template <typename P1, typename P2>
313 void VerifyParameters2() {}
315 template <typename P1, typename P2, typename P3>
316 void VerifyParameters3() {}
318 template <typename P1, typename P2, typename P3, typename P4>
319 void VerifyParameters4() {}
321 void VerifyParameters0() { VerifyParameters(0, NULL); }
323 template <typename P1>
324 void VerifyParameters1() {
325 MachineType parameters[] = {ReturnValueTraits<P1>::Representation()};
326 VerifyParameters(arraysize(parameters), parameters);
329 template <typename P1, typename P2>
330 void VerifyParameters2() {
331 MachineType parameters[] = {ReturnValueTraits<P1>::Representation(),
332 ReturnValueTraits<P2>::Representation()};
333 VerifyParameters(arraysize(parameters), parameters);
336 template <typename P1, typename P2, typename P3>
337 void VerifyParameters3() {
338 MachineType parameters[] = {ReturnValueTraits<P1>::Representation(),
339 ReturnValueTraits<P2>::Representation(),
340 ReturnValueTraits<P3>::Representation()};
341 VerifyParameters(arraysize(parameters), parameters);
344 template <typename P1, typename P2, typename P3, typename P4>
345 void VerifyParameters4() {
346 MachineType parameters[] = {ReturnValueTraits<P1>::Representation(),
347 ReturnValueTraits<P2>::Representation(),
348 ReturnValueTraits<P3>::Representation(),
349 ReturnValueTraits<P4>::Representation()};
350 VerifyParameters(arraysize(parameters), parameters);
354 // TODO(dcarney): replace Call() in CallHelper2 with these.
355 template <typename R>
357 typedef R V8_CDECL FType();
359 return DoCall<R>(FUNCTION_CAST<FType*>(Generate()));
362 template <typename R, typename P1>
364 typedef R V8_CDECL FType(P1);
365 VerifyParameters1<P1>();
366 return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1);
369 template <typename R, typename P1, typename P2>
370 R Call2(P1 p1, P2 p2) {
371 typedef R V8_CDECL FType(P1, P2);
372 VerifyParameters2<P1, P2>();
373 return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1, p2);
376 template <typename R, typename P1, typename P2, typename P3>
377 R Call3(P1 p1, P2 p2, P3 p3) {
378 typedef R V8_CDECL FType(P1, P2, P3);
379 VerifyParameters3<P1, P2, P3>();
380 return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3);
383 template <typename R, typename P1, typename P2, typename P3, typename P4>
384 R Call4(P1 p1, P2 p2, P3 p3, P4 p4) {
385 typedef R V8_CDECL FType(P1, P2, P3, P4);
386 VerifyParameters4<P1, P2, P3, P4>();
387 return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3, p4);
390 template <typename R, typename C>
391 friend class CallHelper2;
396 // TODO(dcarney): replace CallHelper with CallHelper2 and rename.
397 template <typename R, typename C>
400 R Call() { return helper()->template Call0<R>(); }
402 template <typename P1>
404 return helper()->template Call1<R>(p1);
407 template <typename P1, typename P2>
408 R Call(P1 p1, P2 p2) {
409 return helper()->template Call2<R>(p1, p2);
412 template <typename P1, typename P2, typename P3>
413 R Call(P1 p1, P2 p2, P3 p3) {
414 return helper()->template Call3<R>(p1, p2, p3);
417 template <typename P1, typename P2, typename P3, typename P4>
418 R Call(P1 p1, P2 p2, P3 p3, P4 p4) {
419 return helper()->template Call4<R>(p1, p2, p3, p4);
423 CallHelper* helper() { return static_cast<C*>(this); }
426 } // namespace compiler
427 } // namespace internal
430 #endif // V8_CCTEST_COMPILER_CALL_TESTER_H_