• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/v8.h"
6 
7 #include "src/wasm/asm-types.h"
8 
9 namespace v8 {
10 namespace internal {
11 namespace wasm {
12 
AsCallableType()13 AsmCallableType* AsmType::AsCallableType() {
14   if (AsValueType() != nullptr) {
15     return nullptr;
16   }
17 
18   DCHECK(this->AsFunctionType() != nullptr ||
19          this->AsOverloadedFunctionType() != nullptr ||
20          this->AsFFIType() != nullptr ||
21          this->AsFunctionTableType() != nullptr);
22   return reinterpret_cast<AsmCallableType*>(this);
23 }
24 
Name()25 std::string AsmType::Name() {
26   AsmValueType* avt = this->AsValueType();
27   if (avt != nullptr) {
28     switch (avt->Bitset()) {
29 #define RETURN_TYPE_NAME(CamelName, string_name, number, parent_types) \
30   case AsmValueType::kAsm##CamelName:                                  \
31     return string_name;
32       FOR_EACH_ASM_VALUE_TYPE_LIST(RETURN_TYPE_NAME)
33 #undef RETURN_TYPE_NAME
34       default:
35         UNREACHABLE();
36     }
37   }
38 
39   return this->AsCallableType()->Name();
40 }
41 
IsExactly(AsmType * that)42 bool AsmType::IsExactly(AsmType* that) {
43   // TODO(jpp): maybe this can become this == that.
44   AsmValueType* avt = this->AsValueType();
45   if (avt != nullptr) {
46     AsmValueType* tavt = that->AsValueType();
47     if (tavt == nullptr) {
48       return false;
49     }
50     return avt->Bitset() == tavt->Bitset();
51   }
52 
53   // TODO(jpp): is it useful to allow non-value types to be tested with
54   // IsExactly?
55   return that == this;
56 }
57 
IsA(AsmType * that)58 bool AsmType::IsA(AsmType* that) {
59   // IsA is used for querying inheritance relationships. Therefore it is only
60   // meaningful for basic types.
61   AsmValueType* tavt = that->AsValueType();
62   if (tavt != nullptr) {
63     AsmValueType* avt = this->AsValueType();
64     if (avt == nullptr) {
65       return false;
66     }
67     return (avt->Bitset() & tavt->Bitset()) == tavt->Bitset();
68   }
69 
70   // TODO(jpp): is it useful to allow non-value types to be tested with IsA?
71   return that == this;
72 }
73 
ElementSizeInBytes()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 
LoadType()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 
StoreType()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 
Name()141 std::string AsmFunctionType::Name() {
142   if (IsFroundType()) {
143     return "fround";
144   }
145 
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   if (IsMinMaxType()) {
155     DCHECK_EQ(args_.size(), 2);
156     ret += "...";
157   }
158   ret += ") -> ";
159   ret += return_type_->Name();
160   return ret;
161 }
162 
163 namespace {
164 class AsmFroundType final : public AsmFunctionType {
165  public:
IsFroundType() const166   bool IsFroundType() const override { return true; }
167 
168  private:
169   friend AsmType;
170 
AsmFroundType(Zone * zone)171   explicit AsmFroundType(Zone* zone)
172       : AsmFunctionType(zone, AsmType::Float()) {}
173 
174   AsmType* ValidateCall(AsmType* return_type,
175                         const ZoneVector<AsmType*>& args) override;
176 };
177 }  // namespace
178 
FroundType(Zone * zone)179 AsmType* AsmType::FroundType(Zone* zone) {
180   auto* Fround = new (zone) AsmFroundType(zone);
181   return reinterpret_cast<AsmType*>(Fround);
182 }
183 
ValidateCall(AsmType * return_type,const ZoneVector<AsmType * > & args)184 AsmType* AsmFroundType::ValidateCall(AsmType* return_type,
185                                      const ZoneVector<AsmType*>& args) {
186   if (args.size() != 1) {
187     return AsmType::None();
188   }
189 
190   auto* arg = args[0];
191   if (!arg->IsA(AsmType::Floatish()) && !arg->IsA(AsmType::DoubleQ()) &&
192       !arg->IsA(AsmType::Signed()) && !arg->IsA(AsmType::Unsigned())) {
193     return AsmType::None();
194   }
195 
196   return AsmType::Float();
197 }
198 
199 namespace {
200 class AsmMinMaxType final : public AsmFunctionType {
201  public:
IsMinMaxType() const202   bool IsMinMaxType() const override { return true; }
203 
204  private:
205   friend AsmType;
206 
AsmMinMaxType(Zone * zone,AsmType * dest,AsmType * src)207   AsmMinMaxType(Zone* zone, AsmType* dest, AsmType* src)
208       : AsmFunctionType(zone, dest) {
209     AddArgument(src);
210     AddArgument(src);
211   }
212 
ValidateCall(AsmType * return_type,const ZoneVector<AsmType * > & args)213   AsmType* ValidateCall(AsmType* return_type,
214                         const ZoneVector<AsmType*>& args) override {
215     if (!ReturnType()->IsExactly(return_type)) {
216       return AsmType::None();
217     }
218 
219     if (args.size() < 2) {
220       return AsmType::None();
221     }
222 
223     for (size_t ii = 0; ii < Arguments().size(); ++ii) {
224       if (!Arguments()[0]->IsExactly(args[ii])) {
225         return AsmType::None();
226       }
227     }
228 
229     return ReturnType();
230   }
231 };
232 }  // namespace
233 
MinMaxType(Zone * zone,AsmType * dest,AsmType * src)234 AsmType* AsmType::MinMaxType(Zone* zone, AsmType* dest, AsmType* src) {
235   DCHECK(dest->AsValueType() != nullptr);
236   DCHECK(src->AsValueType() != nullptr);
237   auto* MinMax = new (zone) AsmMinMaxType(zone, dest, src);
238   return reinterpret_cast<AsmType*>(MinMax);
239 }
240 
ValidateCall(AsmType * return_type,const ZoneVector<AsmType * > & args)241 AsmType* AsmFFIType::ValidateCall(AsmType* return_type,
242                                   const ZoneVector<AsmType*>& args) {
243   for (size_t ii = 0; ii < args.size(); ++ii) {
244     if (!args[ii]->IsA(AsmType::Extern())) {
245       return AsmType::None();
246     }
247   }
248 
249   return return_type;
250 }
251 
ValidateCall(AsmType * return_type,const ZoneVector<AsmType * > & args)252 AsmType* AsmFunctionType::ValidateCall(AsmType* return_type,
253                                        const ZoneVector<AsmType*>& args) {
254   if (!return_type_->IsExactly(return_type)) {
255     return AsmType::None();
256   }
257 
258   if (args_.size() != args.size()) {
259     return AsmType::None();
260   }
261 
262   for (size_t ii = 0; ii < args_.size(); ++ii) {
263     if (!args_[ii]->IsExactly(args[ii])) {
264       return AsmType::None();
265     }
266   }
267 
268   return return_type_;
269 }
270 
Name()271 std::string AsmOverloadedFunctionType::Name() {
272   std::string ret;
273 
274   for (size_t ii = 0; ii < overloads_.size(); ++ii) {
275     if (ii != 0) {
276       ret += " /\\ ";
277     }
278     ret += overloads_[ii]->Name();
279   }
280 
281   return ret;
282 }
283 
ValidateCall(AsmType * return_type,const ZoneVector<AsmType * > & args)284 AsmType* AsmOverloadedFunctionType::ValidateCall(
285     AsmType* return_type, const ZoneVector<AsmType*>& args) {
286   for (size_t ii = 0; ii < overloads_.size(); ++ii) {
287     auto* validated_type =
288         overloads_[ii]->AsCallableType()->ValidateCall(return_type, args);
289     if (validated_type != AsmType::None()) {
290       return validated_type;
291     }
292   }
293 
294   return AsmType::None();
295 }
296 
AddOverload(AsmType * overload)297 void AsmOverloadedFunctionType::AddOverload(AsmType* overload) {
298   DCHECK(overload->AsFunctionType() != nullptr);
299   overloads_.push_back(overload);
300 }
301 
AsmFunctionTableType(size_t length,AsmType * signature)302 AsmFunctionTableType::AsmFunctionTableType(size_t length, AsmType* signature)
303     : length_(length), signature_(signature) {
304   DCHECK(signature_ != nullptr);
305   DCHECK(signature_->AsFunctionType() != nullptr);
306 }
307 
Name()308 std::string AsmFunctionTableType::Name() {
309   return signature_->Name() + "[" + std::to_string(length_) + "]";
310 }
311 
ValidateCall(AsmType * return_type,const ZoneVector<AsmType * > & args)312 AsmType* AsmFunctionTableType::ValidateCall(AsmType* return_type,
313                                             const ZoneVector<AsmType*>& args) {
314   return signature_->AsCallableType()->ValidateCall(return_type, args);
315 }
316 
317 }  // namespace wasm
318 }  // namespace internal
319 }  // namespace v8
320