ffafaf08039224f16422364ad5cec2612ccf422a
[platform/upstream/nodejs.git] / deps / v8 / test / cctest / compiler / call-tester.h
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.
4
5 #ifndef V8_CCTEST_COMPILER_CALL_TESTER_H_
6 #define V8_CCTEST_COMPILER_CALL_TESTER_H_
7
8 #include "src/v8.h"
9
10 #include "src/simulator.h"
11
12 #if V8_TARGET_ARCH_IA32
13 #if __GNUC__
14 #define V8_CDECL __attribute__((cdecl))
15 #else
16 #define V8_CDECL __cdecl
17 #endif
18 #else
19 #define V8_CDECL
20 #endif
21
22 namespace v8 {
23 namespace internal {
24 namespace compiler {
25
26 // TODO(titzer): use c-signature.h instead of ReturnValueTraits
27 template <typename R>
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
32     // type check.
33     while (false) {
34       *(static_cast<Object* volatile*>(0)) = static_cast<R>(0);
35     }
36     return kMachAnyTagged;
37   }
38 };
39
40 template <>
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; }
44 };
45
46 template <>
47 struct ReturnValueTraits<void> {
48   static void Cast(uintptr_t r) {}
49   static MachineType Representation() { return kMachPtr; }
50 };
51
52 template <>
53 struct ReturnValueTraits<bool> {
54   static bool Cast(uintptr_t r) { return static_cast<bool>(r); }
55   static MachineType Representation() { return kRepBit; }
56 };
57
58 template <>
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; }
62 };
63
64 template <>
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; }
68 };
69
70 template <>
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; }
74 };
75
76 template <>
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; }
80 };
81
82 template <>
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; }
86 };
87
88 template <>
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; }
92 };
93
94 template <>
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; }
98 };
99
100 template <>
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; }
104 };
105
106 template <>
107 struct ReturnValueTraits<double> {
108   static double Cast(uintptr_t r) {
109     UNREACHABLE();
110     return 0.0;
111   }
112   static MachineType Representation() { return kMachFloat64; }
113 };
114
115
116 template <typename R>
117 struct ParameterTraits {
118   static uintptr_t Cast(R r) { return static_cast<uintptr_t>(r); }
119 };
120
121 template <>
122 struct ParameterTraits<int*> {
123   static uintptr_t Cast(int* r) { return reinterpret_cast<uintptr_t>(r); }
124 };
125
126 template <typename T>
127 struct ParameterTraits<T*> {
128   static uintptr_t Cast(void* r) { return reinterpret_cast<uintptr_t>(r); }
129 };
130
131 class CallHelper {
132  public:
133   explicit CallHelper(Isolate* isolate, MachineSignature* machine_sig)
134       : machine_sig_(machine_sig), isolate_(isolate) {
135     USE(isolate_);
136   }
137   virtual ~CallHelper() {}
138
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)
147       param_count--;
148     size_t return_count = return_type == kMachNone ? 0 : 1;
149
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]);
155     }
156     return builder.Build();
157   }
158
159  protected:
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]);
165     }
166   }
167   virtual byte* Generate() = 0;
168
169  private:
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));
174   }
175
176   template <typename R, typename F>
177   R DoCall(F* f) {
178     Simulator::CallArgument args[] = {Simulator::CallArgument::End()};
179     return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args));
180   }
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));
186   }
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));
193   }
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));
200   }
201   template <typename R, typename F, typename P1, typename P2, typename P3,
202             typename P4>
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));
209   }
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));
215   }
216
217   template <typename R, typename F>
218   R DoCall(F* f) {
219     return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f)));
220   }
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)));
225   }
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)));
231   }
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)));
237   }
238   template <typename R, typename F, typename P1, typename P2, typename P3,
239             typename P4>
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)));
245   }
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));
252   }
253   template <typename R, typename F>
254   R DoCall(F* f) {
255     return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f)));
256   }
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)));
261   }
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)));
267   }
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)));
273   }
274   template <typename R, typename F, typename P1, typename P2, typename P3,
275             typename P4>
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)));
281   }
282 #else
283   template <typename R, typename F>
284   R DoCall(F* f) {
285     return f();
286   }
287   template <typename R, typename F, typename P1>
288   R DoCall(F* f, P1 p1) {
289     return f(p1);
290   }
291   template <typename R, typename F, typename P1, typename P2>
292   R DoCall(F* f, P1 p1, P2 p2) {
293     return f(p1, p2);
294   }
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);
298   }
299   template <typename R, typename F, typename P1, typename P2, typename P3,
300             typename P4>
301   R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) {
302     return f(p1, p2, p3, p4);
303   }
304 #endif
305
306 #ifndef DEBUG
307   void VerifyParameters0() {}
308
309   template <typename P1>
310   void VerifyParameters1() {}
311
312   template <typename P1, typename P2>
313   void VerifyParameters2() {}
314
315   template <typename P1, typename P2, typename P3>
316   void VerifyParameters3() {}
317
318   template <typename P1, typename P2, typename P3, typename P4>
319   void VerifyParameters4() {}
320 #else
321   void VerifyParameters0() { VerifyParameters(0, NULL); }
322
323   template <typename P1>
324   void VerifyParameters1() {
325     MachineType parameters[] = {ReturnValueTraits<P1>::Representation()};
326     VerifyParameters(arraysize(parameters), parameters);
327   }
328
329   template <typename P1, typename P2>
330   void VerifyParameters2() {
331     MachineType parameters[] = {ReturnValueTraits<P1>::Representation(),
332                                 ReturnValueTraits<P2>::Representation()};
333     VerifyParameters(arraysize(parameters), parameters);
334   }
335
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);
342   }
343
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);
351   }
352 #endif
353
354   // TODO(dcarney): replace Call() in CallHelper2 with these.
355   template <typename R>
356   R Call0() {
357     typedef R V8_CDECL FType();
358     VerifyParameters0();
359     return DoCall<R>(FUNCTION_CAST<FType*>(Generate()));
360   }
361
362   template <typename R, typename P1>
363   R Call1(P1 p1) {
364     typedef R V8_CDECL FType(P1);
365     VerifyParameters1<P1>();
366     return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1);
367   }
368
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);
374   }
375
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);
381   }
382
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);
388   }
389
390   template <typename R, typename C>
391   friend class CallHelper2;
392   Isolate* isolate_;
393 };
394
395
396 // TODO(dcarney): replace CallHelper with CallHelper2 and rename.
397 template <typename R, typename C>
398 class CallHelper2 {
399  public:
400   R Call() { return helper()->template Call0<R>(); }
401
402   template <typename P1>
403   R Call(P1 p1) {
404     return helper()->template Call1<R>(p1);
405   }
406
407   template <typename P1, typename P2>
408   R Call(P1 p1, P2 p2) {
409     return helper()->template Call2<R>(p1, p2);
410   }
411
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);
415   }
416
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);
420   }
421
422  private:
423   CallHelper* helper() { return static_cast<C*>(this); }
424 };
425
426 }  // namespace compiler
427 }  // namespace internal
428 }  // namespace v8
429
430 #endif  // V8_CCTEST_COMPILER_CALL_TESTER_H_