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/codegen/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 constexpr MachineType MachineTypeForC() {
32   static_assert(std::is_convertible<T, Object>::value,
33                 "all non-specialized types must be convertible to Object");
34   return MachineType::AnyTagged();
35 }
36 
37 #define DECLARE_TEMPLATE_SPECIALIZATION(ctype, mtype)     \
38   template <>                                             \
39   inline MachineType constexpr MachineTypeForC<ctype>() { \
40     return mtype;                                         \
41   }
FOREACH_CTYPE_MACHINE_TYPE_MAPPING(DECLARE_TEMPLATE_SPECIALIZATION)42 FOREACH_CTYPE_MACHINE_TYPE_MAPPING(DECLARE_TEMPLATE_SPECIALIZATION)
43 #undef DECLARE_TEMPLATE_SPECIALIZATION
44 
45 // Helper for building machine signatures from C types.
46 class CSignature : public MachineSignature {
47  protected:
48   CSignature(size_t return_count, size_t parameter_count, MachineType* reps)
49       : MachineSignature(return_count, parameter_count, reps) {}
50 
51  public:
52   friend Zone;
53 
54   template <typename... Params>
55   static void VerifyParams(MachineSignature* sig) {
56     // Verifies the C signature against the machine types.
57     std::array<MachineType, sizeof...(Params)> params{
58         {MachineTypeForC<Params>()...}};
59     for (size_t p = 0; p < params.size(); ++p) {
60       CHECK_EQ(sig->GetParam(p), params[p]);
61     }
62   }
63 
64   static CSignature* FromMachine(Zone* zone, MachineSignature* msig) {
65     return reinterpret_cast<CSignature*>(msig);
66   }
67 
68   template <typename... ParamMachineTypes>
69   static CSignature* New(Zone* zone, MachineType ret,
70                          ParamMachineTypes... params) {
71     constexpr size_t param_count = sizeof...(params);
72     std::array<MachineType, param_count> param_arr{{params...}};
73     const size_t buffer_size =
74         param_count + (ret == MachineType::None() ? 0 : 1);
75     MachineType* buffer = zone->NewArray<MachineType>(buffer_size);
76     size_t pos = 0;
77     size_t return_count = 0;
78     if (ret != MachineType::None()) {
79       buffer[pos++] = ret;
80       return_count++;
81     }
82     for (MachineType p : param_arr) {
83       // Check that there are no MachineType::None()'s in the parameters.
84       CHECK_NE(MachineType::None(), p);
85       buffer[pos++] = p;
86     }
87     DCHECK_EQ(buffer_size, pos);
88     return zone->New<CSignature>(return_count, param_count, buffer);
89   }
90 };
91 
92 // Helper classes for instantiating Signature objects to be callable from C.
93 template <typename Ret, typename... Params>
94 class CSignatureOf : public CSignature {
95  public:
CSignatureOf()96   CSignatureOf() : CSignature(kReturnCount, kParamCount, storage_) {
97     constexpr std::array<MachineType, kParamCount> param_types{
98         MachineTypeForC<Params>()...};
99     if (kReturnCount == 1) storage_[0] = MachineTypeForC<Ret>();
100     static_assert(
101         std::is_same<decltype(*reps_), decltype(*param_types.data())>::value,
102         "type mismatch, cannot memcpy");
103     if (kParamCount > 0) {
104       memcpy(storage_ + kReturnCount, param_types.data(),
105              sizeof(*storage_) * kParamCount);
106     }
107   }
108 
109  private:
110   static constexpr size_t kReturnCount =
111       MachineTypeForC<Ret>() == MachineType::None() ? 0 : 1;
112   static constexpr size_t kParamCount = sizeof...(Params);
113 
114   MachineType storage_[kReturnCount + kParamCount];
115 };
116 
117 using CSignature_i_ii = CSignatureOf<int32_t, int32_t, int32_t>;
118 using CSignature_u_uu = CSignatureOf<uint32_t, uint32_t, uint32_t>;
119 using CSignature_f_ff = CSignatureOf<float, float, float>;
120 using CSignature_d_dd = CSignatureOf<double, double, double>;
121 using CSignature_o_oo = CSignatureOf<Object, Object, Object>;
122 
123 }  // namespace compiler
124 }  // namespace internal
125 }  // namespace v8
126 
127 #endif  // V8_COMPILER_C_SIGNATURE_H_
128