xref: /third_party/node/deps/v8/src/codegen/signature.h (revision 1cb0ef41)
1// Copyright 2015 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_CODEGEN_SIGNATURE_H_
6#define V8_CODEGEN_SIGNATURE_H_
7
8#include "src/base/functional.h"
9#include "src/base/iterator.h"
10#include "src/codegen/machine-type.h"
11#include "src/zone/zone.h"
12
13namespace v8 {
14namespace internal {
15
16// Describes the inputs and outputs of a function or call.
17template <typename T>
18class Signature : public ZoneObject {
19 public:
20  constexpr Signature(size_t return_count, size_t parameter_count,
21                      const T* reps)
22      : return_count_(return_count),
23        parameter_count_(parameter_count),
24        reps_(reps) {
25    DCHECK_EQ(kReturnCountOffset, offsetof(Signature, return_count_));
26    DCHECK_EQ(kParameterCountOffset, offsetof(Signature, parameter_count_));
27    DCHECK_EQ(kRepsOffset, offsetof(Signature, reps_));
28    STATIC_ASSERT(std::is_standard_layout<Signature<T>>::value);
29  }
30
31  size_t return_count() const { return return_count_; }
32  size_t parameter_count() const { return parameter_count_; }
33
34  T GetParam(size_t index) const {
35    DCHECK_LT(index, parameter_count_);
36    return reps_[return_count_ + index];
37  }
38
39  T GetReturn(size_t index = 0) const {
40    DCHECK_LT(index, return_count_);
41    return reps_[index];
42  }
43
44  // Iteration support.
45  base::iterator_range<const T*> parameters() const {
46    return {reps_ + return_count_, reps_ + return_count_ + parameter_count_};
47  }
48  base::iterator_range<const T*> returns() const {
49    return {reps_, reps_ + return_count_};
50  }
51  base::iterator_range<const T*> all() const {
52    return {reps_, reps_ + return_count_ + parameter_count_};
53  }
54
55  bool operator==(const Signature& other) const {
56    if (this == &other) return true;
57    if (parameter_count() != other.parameter_count()) return false;
58    if (return_count() != other.return_count()) return false;
59    return std::equal(all().begin(), all().end(), other.all().begin());
60  }
61  bool operator!=(const Signature& other) const { return !(*this == other); }
62
63  // For incrementally building signatures.
64  class Builder {
65   public:
66    Builder(Zone* zone, size_t return_count, size_t parameter_count)
67        : return_count_(return_count),
68          parameter_count_(parameter_count),
69          zone_(zone),
70          rcursor_(0),
71          pcursor_(0),
72          buffer_(zone->NewArray<T>(
73              static_cast<int>(return_count + parameter_count))) {}
74
75    const size_t return_count_;
76    const size_t parameter_count_;
77
78    void AddReturn(T val) {
79      DCHECK_LT(rcursor_, return_count_);
80      buffer_[rcursor_++] = val;
81    }
82
83    void AddParam(T val) {
84      DCHECK_LT(pcursor_, parameter_count_);
85      buffer_[return_count_ + pcursor_++] = val;
86    }
87
88    void AddParamAt(size_t index, T val) {
89      DCHECK_LT(index, parameter_count_);
90      buffer_[return_count_ + index] = val;
91      pcursor_ = std::max(pcursor_, index + 1);
92    }
93
94    Signature<T>* Build() {
95      DCHECK_EQ(rcursor_, return_count_);
96      DCHECK_EQ(pcursor_, parameter_count_);
97      return zone_->New<Signature<T>>(return_count_, parameter_count_, buffer_);
98    }
99
100   private:
101    Zone* zone_;
102    size_t rcursor_;
103    size_t pcursor_;
104    T* buffer_;
105  };
106
107  static Signature<T>* Build(Zone* zone, std::initializer_list<T> returns,
108                             std::initializer_list<T> params) {
109    Builder builder(zone, returns.size(), params.size());
110    for (T ret : returns) builder.AddReturn(ret);
111    for (T param : params) builder.AddParam(param);
112    return builder.Build();
113  }
114
115  static constexpr size_t kReturnCountOffset = 0;
116  static constexpr size_t kParameterCountOffset =
117      kReturnCountOffset + kSizetSize;
118  static constexpr size_t kRepsOffset = kParameterCountOffset + kSizetSize;
119
120 protected:
121  size_t return_count_;
122  size_t parameter_count_;
123  const T* reps_;
124};
125
126using MachineSignature = Signature<MachineType>;
127
128template <typename T>
129size_t hash_value(const Signature<T>& sig) {
130  // Hash over all contained representations, plus the parameter count to
131  // differentiate signatures with the same representation array but different
132  // parameter/return count.
133  size_t seed = base::hash_value(sig.parameter_count());
134  for (T rep : sig.all()) seed = base::hash_combine(seed, base::hash<T>{}(rep));
135  return seed;
136}
137
138template <typename T, size_t kNumReturns = 0, size_t kNumParams = 0>
139class FixedSizeSignature : public Signature<T> {
140 public:
141  // Add return types to this signature (only allowed if there are none yet).
142  template <typename... ReturnTypes>
143  auto Returns(ReturnTypes... return_types) const {
144    static_assert(kNumReturns == 0, "Please specify all return types at once");
145    return FixedSizeSignature<T, sizeof...(ReturnTypes), kNumParams>{
146        std::initializer_list<T>{return_types...}.begin(), reps_};
147  }
148
149  // Add parameters to this signature (only allowed if there are none yet).
150  template <typename... ParamTypes>
151  auto Params(ParamTypes... param_types) const {
152    static_assert(kNumParams == 0, "Please specify all parameters at once");
153    return FixedSizeSignature<T, kNumReturns, sizeof...(ParamTypes)>{
154        reps_, std::initializer_list<T>{param_types...}.begin()};
155  }
156
157 private:
158  // Other template instantiations can call the private constructor.
159  template <typename T2, size_t kNumReturns2, size_t kNumParams2>
160  friend class FixedSizeSignature;
161
162  FixedSizeSignature(const T* returns, const T* params)
163      : Signature<T>(kNumReturns, kNumParams, reps_) {
164    std::copy(returns, returns + kNumReturns, reps_);
165    std::copy(params, params + kNumParams, reps_ + kNumReturns);
166  }
167
168  T reps_[kNumReturns + kNumParams];
169};
170
171// Specialization for zero-sized signatures.
172template <typename T>
173class FixedSizeSignature<T, 0, 0> : public Signature<T> {
174 public:
175  constexpr FixedSizeSignature() : Signature<T>(0, 0, nullptr) {}
176
177  // Add return types.
178  template <typename... ReturnTypes>
179  static auto Returns(ReturnTypes... return_types) {
180    return FixedSizeSignature<T, sizeof...(ReturnTypes), 0>{
181        std::initializer_list<T>{return_types...}.begin(), nullptr};
182  }
183
184  // Add parameters.
185  template <typename... ParamTypes>
186  static auto Params(ParamTypes... param_types) {
187    return FixedSizeSignature<T, 0, sizeof...(ParamTypes)>{
188        nullptr, std::initializer_list<T>{param_types...}.begin()};
189  }
190};
191
192}  // namespace internal
193}  // namespace v8
194
195#endif  // V8_CODEGEN_SIGNATURE_H_
196