V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
asm-types.cc
1 // Copyright 2016 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 #include "src/asmjs/asm-types.h"
6 
7 #include <cinttypes>
8 
9 #include "src/utils.h"
10 #include "src/v8.h"
11 
12 namespace v8 {
13 namespace internal {
14 namespace wasm {
15 
16 AsmCallableType* AsmType::AsCallableType() {
17  if (AsValueType() != nullptr) {
18  return nullptr;
19  }
20 
21  return reinterpret_cast<AsmCallableType*>(this);
22 }
23 
24 std::string AsmType::Name() {
25  AsmValueType* avt = this->AsValueType();
26  if (avt != nullptr) {
27  switch (avt->Bitset()) {
28 #define RETURN_TYPE_NAME(CamelName, string_name, number, parent_types) \
29  case AsmValueType::kAsm##CamelName: \
30  return string_name;
31  FOR_EACH_ASM_VALUE_TYPE_LIST(RETURN_TYPE_NAME)
32 #undef RETURN_TYPE_NAME
33  default:
34  UNREACHABLE();
35  }
36  }
37 
38  return this->AsCallableType()->Name();
39 }
40 
41 bool AsmType::IsExactly(AsmType* that) {
42  // TODO(jpp): maybe this can become this == that.
43  AsmValueType* avt = this->AsValueType();
44  if (avt != nullptr) {
45  AsmValueType* tavt = that->AsValueType();
46  if (tavt == nullptr) {
47  return false;
48  }
49  return avt->Bitset() == tavt->Bitset();
50  }
51 
52  // TODO(jpp): is it useful to allow non-value types to be tested with
53  // IsExactly?
54  return that == this;
55 }
56 
57 bool AsmType::IsA(AsmType* that) {
58  // IsA is used for querying inheritance relationships. Therefore it is only
59  // meaningful for basic types.
60  if (auto* avt = this->AsValueType()) {
61  if (auto* tavt = that->AsValueType()) {
62  return (avt->Bitset() & tavt->Bitset()) == tavt->Bitset();
63  }
64  return false;
65  }
66 
67  if (auto* as_callable = this->AsCallableType()) {
68  return as_callable->IsA(that);
69  }
70 
71  UNREACHABLE();
72 }
73 
74 int32_t AsmType::ElementSizeInBytes() {
75  auto* value = AsValueType();
76  if (value == nullptr) {
77  return AsmType::kNotHeapType;
78  }
79  switch (value->Bitset()) {
80  case AsmValueType::kAsmInt8Array:
81  case AsmValueType::kAsmUint8Array:
82  return 1;
83  case AsmValueType::kAsmInt16Array:
84  case AsmValueType::kAsmUint16Array:
85  return 2;
86  case AsmValueType::kAsmInt32Array:
87  case AsmValueType::kAsmUint32Array:
88  case AsmValueType::kAsmFloat32Array:
89  return 4;
90  case AsmValueType::kAsmFloat64Array:
91  return 8;
92  default:
93  return AsmType::kNotHeapType;
94  }
95 }
96 
97 AsmType* AsmType::LoadType() {
98  auto* value = AsValueType();
99  if (value == nullptr) {
100  return AsmType::None();
101  }
102  switch (value->Bitset()) {
103  case AsmValueType::kAsmInt8Array:
104  case AsmValueType::kAsmUint8Array:
105  case AsmValueType::kAsmInt16Array:
106  case AsmValueType::kAsmUint16Array:
107  case AsmValueType::kAsmInt32Array:
108  case AsmValueType::kAsmUint32Array:
109  return AsmType::Intish();
110  case AsmValueType::kAsmFloat32Array:
111  return AsmType::FloatQ();
112  case AsmValueType::kAsmFloat64Array:
113  return AsmType::DoubleQ();
114  default:
115  return AsmType::None();
116  }
117 }
118 
119 AsmType* AsmType::StoreType() {
120  auto* value = AsValueType();
121  if (value == nullptr) {
122  return AsmType::None();
123  }
124  switch (value->Bitset()) {
125  case AsmValueType::kAsmInt8Array:
126  case AsmValueType::kAsmUint8Array:
127  case AsmValueType::kAsmInt16Array:
128  case AsmValueType::kAsmUint16Array:
129  case AsmValueType::kAsmInt32Array:
130  case AsmValueType::kAsmUint32Array:
131  return AsmType::Intish();
132  case AsmValueType::kAsmFloat32Array:
133  return AsmType::FloatishDoubleQ();
134  case AsmValueType::kAsmFloat64Array:
135  return AsmType::FloatQDoubleQ();
136  default:
137  return AsmType::None();
138  }
139 }
140 
141 bool AsmCallableType::IsA(AsmType* other) {
142  return other->AsCallableType() == this;
143 }
144 
145 std::string AsmFunctionType::Name() {
146  std::string ret;
147  ret += "(";
148  for (size_t ii = 0; ii < args_.size(); ++ii) {
149  ret += args_[ii]->Name();
150  if (ii != args_.size() - 1) {
151  ret += ", ";
152  }
153  }
154  ret += ") -> ";
155  ret += return_type_->Name();
156  return ret;
157 }
158 
159 namespace {
160 class AsmFroundType final : public AsmCallableType {
161  public:
162  friend AsmType;
163 
164  AsmFroundType() : AsmCallableType() {}
165 
166  bool CanBeInvokedWith(AsmType* return_type,
167  const ZoneVector<AsmType*>& args) override;
168 
169  std::string Name() override { return "fround"; }
170 };
171 } // namespace
172 
173 AsmType* AsmType::FroundType(Zone* zone) {
174  auto* Fround = new (zone) AsmFroundType();
175  return reinterpret_cast<AsmType*>(Fround);
176 }
177 
178 bool AsmFroundType::CanBeInvokedWith(AsmType* return_type,
179  const ZoneVector<AsmType*>& args) {
180  if (args.size() != 1) {
181  return false;
182  }
183 
184  auto* arg = args[0];
185  if (!arg->IsA(AsmType::Floatish()) && !arg->IsA(AsmType::DoubleQ()) &&
186  !arg->IsA(AsmType::Signed()) && !arg->IsA(AsmType::Unsigned())) {
187  return false;
188  }
189 
190  return true;
191 }
192 
193 namespace {
194 class AsmMinMaxType final : public AsmCallableType {
195  private:
196  friend AsmType;
197 
198  AsmMinMaxType(AsmType* dest, AsmType* src)
199  : AsmCallableType(), return_type_(dest), arg_(src) {}
200 
201  bool CanBeInvokedWith(AsmType* return_type,
202  const ZoneVector<AsmType*>& args) override {
203  if (!return_type_->IsExactly(return_type)) {
204  return false;
205  }
206 
207  if (args.size() < 2) {
208  return false;
209  }
210 
211  for (size_t ii = 0; ii < args.size(); ++ii) {
212  if (!args[ii]->IsA(arg_)) {
213  return false;
214  }
215  }
216 
217  return true;
218  }
219 
220  std::string Name() override {
221  return "(" + arg_->Name() + ", " + arg_->Name() + "...) -> " +
222  return_type_->Name();
223  }
224 
225  AsmType* return_type_;
226  AsmType* arg_;
227 };
228 } // namespace
229 
230 AsmType* AsmType::MinMaxType(Zone* zone, AsmType* dest, AsmType* src) {
231  DCHECK_NOT_NULL(dest->AsValueType());
232  DCHECK_NOT_NULL(src->AsValueType());
233  auto* MinMax = new (zone) AsmMinMaxType(dest, src);
234  return reinterpret_cast<AsmType*>(MinMax);
235 }
236 
237 bool AsmFunctionType::IsA(AsmType* other) {
238  auto* that = other->AsFunctionType();
239  if (that == nullptr) {
240  return false;
241  }
242  if (!return_type_->IsExactly(that->return_type_)) {
243  return false;
244  }
245 
246  if (args_.size() != that->args_.size()) {
247  return false;
248  }
249 
250  for (size_t ii = 0; ii < args_.size(); ++ii) {
251  if (!args_[ii]->IsExactly(that->args_[ii])) {
252  return false;
253  }
254  }
255 
256  return true;
257 }
258 
259 bool AsmFunctionType::CanBeInvokedWith(AsmType* return_type,
260  const ZoneVector<AsmType*>& args) {
261  if (!return_type_->IsExactly(return_type)) {
262  return false;
263  }
264 
265  if (args_.size() != args.size()) {
266  return false;
267  }
268 
269  for (size_t ii = 0; ii < args_.size(); ++ii) {
270  if (!args[ii]->IsA(args_[ii])) {
271  return false;
272  }
273  }
274 
275  return true;
276 }
277 
278 std::string AsmOverloadedFunctionType::Name() {
279  std::string ret;
280 
281  for (size_t ii = 0; ii < overloads_.size(); ++ii) {
282  if (ii != 0) {
283  ret += " /\\ ";
284  }
285  ret += overloads_[ii]->Name();
286  }
287 
288  return ret;
289 }
290 
291 bool AsmOverloadedFunctionType::CanBeInvokedWith(
292  AsmType* return_type, const ZoneVector<AsmType*>& args) {
293  for (size_t ii = 0; ii < overloads_.size(); ++ii) {
294  if (overloads_[ii]->AsCallableType()->CanBeInvokedWith(return_type, args)) {
295  return true;
296  }
297  }
298 
299  return false;
300 }
301 
302 void AsmOverloadedFunctionType::AddOverload(AsmType* overload) {
303  DCHECK_NOT_NULL(overload->AsCallableType());
304  overloads_.push_back(overload);
305 }
306 
307 } // namespace wasm
308 } // namespace internal
309 } // namespace v8
Definition: libplatform.h:13