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_COMPILER_C_SIGNATURE_H_
6 #define V8_COMPILER_C_SIGNATURE_H_
7 
8 #include "src/machine-type.h"
9 
10 namespace v8 {
11 namespace internal {
12 namespace compiler {
13 
14 #define FOREACH_CTYPE_MACHINE_TYPE_MAPPING(V) \
15   V(void, MachineType::None())                \
16   V(bool, MachineType::Uint8())               \
17   V(int8_t, MachineType::Int8())              \
18   V(uint8_t, MachineType::Uint8())            \
19   V(int16_t, MachineType::Int16())            \
20   V(uint16_t, MachineType::Uint16())          \
21   V(int32_t, MachineType::Int32())            \
22   V(uint32_t, MachineType::Uint32())          \
23   V(int64_t, MachineType::Int64())            \
24   V(uint64_t, MachineType::Uint64())          \
25   V(float, MachineType::Float32())            \
26   V(double, MachineType::Float64())           \
27   V(void*, MachineType::Pointer())            \
28   V(int*, MachineType::Pointer())
29 
30 template <typename T>
MachineTypeForC()31 inline MachineType MachineTypeForC() {
32   while (false) {
33     // All other types T must be assignable to Object*
34     *(static_cast<Object* volatile*>(0)) = static_cast<T>(0);
35   }
36   return MachineType::AnyTagged();
37 }
38 
39 #define DECLARE_TEMPLATE_SPECIALIZATION(ctype, mtype) \
40   template <>                                         \
41   inline MachineType MachineTypeForC<ctype>() {       \
42     return mtype;                                     \
43   }
FOREACH_CTYPE_MACHINE_TYPE_MAPPING(DECLARE_TEMPLATE_SPECIALIZATION)44 FOREACH_CTYPE_MACHINE_TYPE_MAPPING(DECLARE_TEMPLATE_SPECIALIZATION)
45 #undef DECLARE_TEMPLATE_SPECIALIZATION
46 
47 // Helper for building machine signatures from C types.
48 class CSignature : public MachineSignature {
49  protected:
50   CSignature(size_t return_count, size_t parameter_count, MachineType* reps)
51       : MachineSignature(return_count, parameter_count, reps) {}
52 
53  public:
54   template <typename P1 = void, typename P2 = void, typename P3 = void,
55             typename P4 = void, typename P5 = void>
56   void VerifyParams() {
57     // Verifies the C signature against the machine types. Maximum {5} params.
58     CHECK_LT(parameter_count(), 6u);
59     const int kMax = 5;
60     MachineType params[] = {MachineTypeForC<P1>(), MachineTypeForC<P2>(),
61                             MachineTypeForC<P3>(), MachineTypeForC<P4>(),
62                             MachineTypeForC<P5>()};
63     for (int p = kMax - 1; p >= 0; p--) {
64       if (p < static_cast<int>(parameter_count())) {
65         CHECK_EQ(GetParam(p), params[p]);
66       } else {
67         CHECK_EQ(MachineType::None(), params[p]);
68       }
69     }
70   }
71 
72   static CSignature* FromMachine(Zone* zone, MachineSignature* msig) {
73     return reinterpret_cast<CSignature*>(msig);
74   }
75 
76   static CSignature* New(Zone* zone, MachineType ret,
77                          MachineType p1 = MachineType::None(),
78                          MachineType p2 = MachineType::None(),
79                          MachineType p3 = MachineType::None(),
80                          MachineType p4 = MachineType::None(),
81                          MachineType p5 = MachineType::None()) {
82     MachineType* buffer = zone->NewArray<MachineType>(6);
83     int pos = 0;
84     size_t return_count = 0;
85     if (ret != MachineType::None()) {
86       buffer[pos++] = ret;
87       return_count++;
88     }
89     buffer[pos++] = p1;
90     buffer[pos++] = p2;
91     buffer[pos++] = p3;
92     buffer[pos++] = p4;
93     buffer[pos++] = p5;
94     size_t param_count = 5;
95     if (p5 == MachineType::None()) param_count--;
96     if (p4 == MachineType::None()) param_count--;
97     if (p3 == MachineType::None()) param_count--;
98     if (p2 == MachineType::None()) param_count--;
99     if (p1 == MachineType::None()) param_count--;
100     for (size_t i = 0; i < param_count; i++) {
101       // Check that there are no MachineType::None()'s in the middle of
102       // parameters.
103       CHECK_NE(MachineType::None(), buffer[return_count + i]);
104     }
105     return new (zone) CSignature(return_count, param_count, buffer);
106   }
107 };
108 
109 
110 template <typename Ret, uint16_t kParamCount>
111 class CSignatureOf : public CSignature {
112  protected:
113   MachineType storage_[1 + kParamCount];
114 
CSignatureOf()115   CSignatureOf()
116       : CSignature(MachineTypeForC<Ret>() != MachineType::None() ? 1 : 0,
117                    kParamCount, reinterpret_cast<MachineType*>(&storage_)) {
118     if (return_count_ == 1) storage_[0] = MachineTypeForC<Ret>();
119   }
Set(int index,MachineType type)120   void Set(int index, MachineType type) {
121     CHECK_LE(0, index);
122     CHECK_LT(index, kParamCount);
123     reps_[return_count_ + index] = type;
124   }
125 };
126 
127 // Helper classes for instantiating Signature objects to be callable from C.
128 template <typename Ret>
129 class CSignature0 : public CSignatureOf<Ret, 0> {
130  public:
CSignature0()131   CSignature0() : CSignatureOf<Ret, 0>() {}
132 };
133 
134 template <typename Ret, typename P1>
135 class CSignature1 : public CSignatureOf<Ret, 1> {
136  public:
CSignature1()137   CSignature1() : CSignatureOf<Ret, 1>() {
138     this->Set(0, MachineTypeForC<P1>());
139   }
140 };
141 
142 template <typename Ret, typename P1, typename P2>
143 class CSignature2 : public CSignatureOf<Ret, 2> {
144  public:
CSignature2()145   CSignature2() : CSignatureOf<Ret, 2>() {
146     this->Set(0, MachineTypeForC<P1>());
147     this->Set(1, MachineTypeForC<P2>());
148   }
149 };
150 
151 template <typename Ret, typename P1, typename P2, typename P3>
152 class CSignature3 : public CSignatureOf<Ret, 3> {
153  public:
CSignature3()154   CSignature3() : CSignatureOf<Ret, 3>() {
155     this->Set(0, MachineTypeForC<P1>());
156     this->Set(1, MachineTypeForC<P2>());
157     this->Set(2, MachineTypeForC<P3>());
158   }
159 };
160 
161 typedef CSignature2<int32_t, int32_t, int32_t> CSignature_i_ii;
162 typedef CSignature2<uint32_t, uint32_t, uint32_t> CSignature_u_uu;
163 typedef CSignature2<float, float, float> CSignature_f_ff;
164 typedef CSignature2<double, double, double> CSignature_d_dd;
165 typedef CSignature2<Object*, Object*, Object*> CSignature_o_oo;
166 }  // namespace compiler
167 }  // namespace internal
168 }  // namespace v8
169 
170 #endif  // V8_COMPILER_C_SIGNATURE_H_
171