summaryrefslogtreecommitdiff
path: root/deps/v8/test/cctest/compiler/c-signature.h
blob: 0aea6e938b1ed477831fa4889c108277a634089b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_COMPILER_C_SIGNATURE_H_
#define V8_COMPILER_C_SIGNATURE_H_

#include "src/machine-type.h"

namespace v8 {
namespace internal {
namespace compiler {

#define FOREACH_CTYPE_MACHINE_TYPE_MAPPING(V) \
  V(void, MachineType::None())                \
  V(bool, MachineType::Uint8())               \
  V(int8_t, MachineType::Int8())              \
  V(uint8_t, MachineType::Uint8())            \
  V(int16_t, MachineType::Int16())            \
  V(uint16_t, MachineType::Uint16())          \
  V(int32_t, MachineType::Int32())            \
  V(uint32_t, MachineType::Uint32())          \
  V(int64_t, MachineType::Int64())            \
  V(uint64_t, MachineType::Uint64())          \
  V(float, MachineType::Float32())            \
  V(double, MachineType::Float64())           \
  V(void*, MachineType::Pointer())            \
  V(int*, MachineType::Pointer())

template <typename T>
inline constexpr MachineType MachineTypeForC() {
  static_assert(std::is_convertible<T, Object*>::value,
                "all non-specialized types must be convertible to Object*");
  return MachineType::AnyTagged();
}

#define DECLARE_TEMPLATE_SPECIALIZATION(ctype, mtype)     \
  template <>                                             \
  inline MachineType constexpr MachineTypeForC<ctype>() { \
    return mtype;                                         \
  }
FOREACH_CTYPE_MACHINE_TYPE_MAPPING(DECLARE_TEMPLATE_SPECIALIZATION)
#undef DECLARE_TEMPLATE_SPECIALIZATION

// Helper for building machine signatures from C types.
class CSignature : public MachineSignature {
 protected:
  CSignature(size_t return_count, size_t parameter_count, MachineType* reps)
      : MachineSignature(return_count, parameter_count, reps) {}

 public:
  template <typename... Params>
  static void VerifyParams(MachineSignature* sig) {
    // Verifies the C signature against the machine types.
    std::array<MachineType, sizeof...(Params)> params{
        {MachineTypeForC<Params>()...}};
    for (size_t p = 0; p < params.size(); ++p) {
      CHECK_EQ(sig->GetParam(p), params[p]);
    }
  }

  static CSignature* FromMachine(Zone* zone, MachineSignature* msig) {
    return reinterpret_cast<CSignature*>(msig);
  }

  template <typename... ParamMachineTypes>
  static CSignature* New(Zone* zone, MachineType ret,
                         ParamMachineTypes... params) {
    constexpr size_t param_count = sizeof...(params);
    std::array<MachineType, param_count> param_arr{{params...}};
    const size_t buffer_size =
        param_count + (ret == MachineType::None() ? 0 : 1);
    MachineType* buffer = zone->NewArray<MachineType>(buffer_size);
    size_t pos = 0;
    size_t return_count = 0;
    if (ret != MachineType::None()) {
      buffer[pos++] = ret;
      return_count++;
    }
    for (MachineType p : param_arr) {
      // Check that there are no MachineType::None()'s in the parameters.
      CHECK_NE(MachineType::None(), p);
      buffer[pos++] = p;
    }
    DCHECK_EQ(buffer_size, pos);
    return new (zone) CSignature(return_count, param_count, buffer);
  }
};

// Helper classes for instantiating Signature objects to be callable from C.
template <typename Ret, typename... Params>
class CSignatureOf : public CSignature {
 public:
  CSignatureOf() : CSignature(kReturnCount, kParamCount, storage_) {
    constexpr std::array<MachineType, kParamCount> param_types{
        MachineTypeForC<Params>()...};
    if (kReturnCount == 1) storage_[0] = MachineTypeForC<Ret>();
    static_assert(
        std::is_same<decltype(*reps_), decltype(*param_types.data())>::value,
        "type mismatch, cannot memcpy");
    memcpy(storage_ + kReturnCount, param_types.data(),
           sizeof(*storage_) * kParamCount);
  }

 private:
  static constexpr size_t kReturnCount =
      MachineTypeForC<Ret>() == MachineType::None() ? 0 : 1;
  static constexpr size_t kParamCount = sizeof...(Params);

  MachineType storage_[kReturnCount + kParamCount];
};

typedef CSignatureOf<int32_t, int32_t, int32_t> CSignature_i_ii;
typedef CSignatureOf<uint32_t, uint32_t, uint32_t> CSignature_u_uu;
typedef CSignatureOf<float, float, float> CSignature_f_ff;
typedef CSignatureOf<double, double, double> CSignature_d_dd;
typedef CSignatureOf<Object*, Object*, Object*> CSignature_o_oo;

}  // namespace compiler
}  // namespace internal
}  // namespace v8

#endif  // V8_COMPILER_C_SIGNATURE_H_