OLD | NEW |
| (Empty) |
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 | |
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 | |
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 | |
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 | |
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 | |
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 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: | |
166 bool IsFroundType() const override { return true; } | |
167 | |
168 private: | |
169 friend AsmType; | |
170 | |
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 | |
179 AsmType* AsmType::FroundType(Zone* zone) { | |
180 auto* Fround = new (zone) AsmFroundType(zone); | |
181 return reinterpret_cast<AsmType*>(Fround); | |
182 } | |
183 | |
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: | |
202 bool IsMinMaxType() const override { return true; } | |
203 | |
204 private: | |
205 friend AsmType; | |
206 | |
207 AsmMinMaxType(Zone* zone, AsmType* dest, AsmType* src) | |
208 : AsmFunctionType(zone, dest) { | |
209 AddArgument(src); | |
210 AddArgument(src); | |
211 } | |
212 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
297 void AsmOverloadedFunctionType::AddOverload(AsmType* overload) { | |
298 DCHECK(overload->AsFunctionType() != nullptr); | |
299 overloads_.push_back(overload); | |
300 } | |
301 | |
302 AsmFunctionTableType::AsmFunctionTableType(size_t length, AsmType* signature) | |
303 : length_(length), signature_(signature) { | |
304 DCHECK(signature_ != nullptr); | |
305 DCHECK(signature_->AsFunctionType() != nullptr); | |
306 } | |
307 | |
308 std::string AsmFunctionTableType::Name() { | |
309 return signature_->Name() + "[" + std::to_string(length_) + "]"; | |
310 } | |
311 | |
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 | |
OLD | NEW |