Line data Source code
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 43814 : AsmCallableType* AsmType::AsCallableType() {
17 237316 : if (AsValueType() != nullptr) {
18 : return nullptr;
19 : }
20 :
21 43814 : return reinterpret_cast<AsmCallableType*>(this);
22 : }
23 :
24 49 : std::string AsmType::Name() {
25 : AsmValueType* avt = this->AsValueType();
26 49 : if (avt != nullptr) {
27 41 : switch (avt->Bitset()) {
28 : #define RETURN_TYPE_NAME(CamelName, string_name, number, parent_types) \
29 : case AsmValueType::kAsm##CamelName: \
30 : return string_name;
31 1 : FOR_EACH_ASM_VALUE_TYPE_LIST(RETURN_TYPE_NAME)
32 : #undef RETURN_TYPE_NAME
33 : default:
34 0 : UNREACHABLE();
35 : }
36 : }
37 :
38 8 : return this->AsCallableType()->Name();
39 : }
40 :
41 312416 : bool AsmType::IsExactly(AsmType* that) {
42 : // TODO(jpp): maybe this can become this == that.
43 : AsmValueType* avt = this->AsValueType();
44 390027 : if (avt != nullptr) {
45 : AsmValueType* tavt = that->AsValueType();
46 104555 : if (tavt == nullptr) {
47 : return false;
48 : }
49 104387 : 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 285472 : return that == this;
55 : }
56 :
57 6776329 : bool AsmType::IsA(AsmType* that) {
58 : // IsA is used for querying inheritance relationships. Therefore it is only
59 : // meaningful for basic types.
60 6776329 : if (auto* avt = this->AsValueType()) {
61 6589893 : if (auto* tavt = that->AsValueType()) {
62 6342011 : return (avt->Bitset() & tavt->Bitset()) == tavt->Bitset();
63 : }
64 : return false;
65 : }
66 :
67 186436 : if (auto* as_callable = this->AsCallableType()) {
68 186436 : return as_callable->IsA(that);
69 : }
70 :
71 0 : UNREACHABLE();
72 : }
73 :
74 211606 : int32_t AsmType::ElementSizeInBytes() {
75 : auto* value = AsValueType();
76 211606 : if (value == nullptr) {
77 : return AsmType::kNotHeapType;
78 : }
79 211599 : switch (value->Bitset()) {
80 : case AsmValueType::kAsmInt8Array:
81 : case AsmValueType::kAsmUint8Array:
82 : return 1;
83 : case AsmValueType::kAsmInt16Array:
84 : case AsmValueType::kAsmUint16Array:
85 5858 : return 2;
86 : case AsmValueType::kAsmInt32Array:
87 : case AsmValueType::kAsmUint32Array:
88 : case AsmValueType::kAsmFloat32Array:
89 178128 : return 4;
90 : case AsmValueType::kAsmFloat64Array:
91 5984 : return 8;
92 : default:
93 16 : return AsmType::kNotHeapType;
94 : }
95 : }
96 :
97 128690 : AsmType* AsmType::LoadType() {
98 : auto* value = AsValueType();
99 128690 : if (value == nullptr) {
100 : return AsmType::None();
101 : }
102 128683 : 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 8274 : return AsmType::FloatQ();
112 : case AsmValueType::kAsmFloat64Array:
113 3216 : return AsmType::DoubleQ();
114 : default:
115 16 : return AsmType::None();
116 : }
117 : }
118 :
119 82905 : AsmType* AsmType::StoreType() {
120 : auto* value = AsValueType();
121 82905 : if (value == nullptr) {
122 : return AsmType::None();
123 : }
124 82898 : 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 4895 : return AsmType::FloatishDoubleQ();
134 : case AsmValueType::kAsmFloat64Array:
135 2769 : return AsmType::FloatQDoubleQ();
136 : default:
137 16 : return AsmType::None();
138 : }
139 : }
140 :
141 4370 : bool AsmCallableType::IsA(AsmType* other) {
142 4370 : return other->AsCallableType() == this;
143 : }
144 :
145 3 : std::string AsmFunctionType::Name() {
146 : std::string ret;
147 : ret += "(";
148 16 : for (size_t ii = 0; ii < args_.size(); ++ii) {
149 18 : ret += args_[ii]->Name();
150 5 : if (ii != args_.size() - 1) {
151 : ret += ", ";
152 : }
153 : }
154 : ret += ") -> ";
155 6 : ret += return_type_->Name();
156 3 : return ret;
157 : }
158 :
159 : namespace {
160 0 : class AsmFroundType final : public AsmCallableType {
161 : public:
162 : friend AsmType;
163 :
164 346055 : AsmFroundType() : AsmCallableType() {}
165 :
166 : bool CanBeInvokedWith(AsmType* return_type,
167 : const ZoneVector<AsmType*>& args) override;
168 :
169 1 : std::string Name() override { return "fround"; }
170 : };
171 : } // namespace
172 :
173 346054 : AsmType* AsmType::FroundType(Zone* zone) {
174 : auto* Fround = new (zone) AsmFroundType();
175 346055 : return reinterpret_cast<AsmType*>(Fround);
176 : }
177 :
178 8 : bool AsmFroundType::CanBeInvokedWith(AsmType* return_type,
179 : const ZoneVector<AsmType*>& args) {
180 16 : if (args.size() != 1) {
181 : return false;
182 : }
183 :
184 8 : auto* arg = args[0];
185 24 : if (!arg->IsA(AsmType::Floatish()) && !arg->IsA(AsmType::DoubleQ()) &&
186 12 : !arg->IsA(AsmType::Signed()) && !arg->IsA(AsmType::Unsigned())) {
187 : return false;
188 : }
189 :
190 8 : return true;
191 : }
192 :
193 : namespace {
194 0 : class AsmMinMaxType final : public AsmCallableType {
195 : private:
196 : friend AsmType;
197 :
198 : AsmMinMaxType(AsmType* dest, AsmType* src)
199 1038153 : : AsmCallableType(), return_type_(dest), arg_(src) {}
200 :
201 971 : bool CanBeInvokedWith(AsmType* return_type,
202 : const ZoneVector<AsmType*>& args) override {
203 1942 : if (!return_type_->IsExactly(return_type)) {
204 : return false;
205 : }
206 :
207 1038 : if (args.size() < 2) {
208 : return false;
209 : }
210 :
211 830 : for (size_t ii = 0; ii < args.size(); ++ii) {
212 808 : if (!args[ii]->IsA(arg_)) {
213 : return false;
214 : }
215 : }
216 :
217 : return true;
218 : }
219 :
220 3 : std::string Name() override {
221 24 : return "(" + arg_->Name() + ", " + arg_->Name() + "...) -> " +
222 9 : return_type_->Name();
223 : }
224 :
225 : AsmType* return_type_;
226 : AsmType* arg_;
227 : };
228 : } // namespace
229 :
230 1038149 : 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 1038153 : return reinterpret_cast<AsmType*>(MinMax);
235 : }
236 :
237 182066 : bool AsmFunctionType::IsA(AsmType* other) {
238 : auto* that = other->AsFunctionType();
239 182066 : if (that == nullptr) {
240 : return false;
241 : }
242 17768 : if (!return_type_->IsExactly(that->return_type_)) {
243 : return false;
244 : }
245 :
246 26613 : if (args_.size() != that->args_.size()) {
247 : return false;
248 : }
249 :
250 46259 : for (size_t ii = 0; ii < args_.size(); ++ii) {
251 56157 : if (!args_[ii]->IsExactly(that->args_[ii])) {
252 : return false;
253 : }
254 : }
255 :
256 : return true;
257 : }
258 :
259 49037 : bool AsmFunctionType::CanBeInvokedWith(AsmType* return_type,
260 : const ZoneVector<AsmType*>& args) {
261 98074 : if (!return_type_->IsExactly(return_type)) {
262 : return false;
263 : }
264 :
265 377547 : if (args_.size() != args.size()) {
266 : return false;
267 : }
268 :
269 246310 : for (size_t ii = 0; ii < args_.size(); ++ii) {
270 202756 : if (!args[ii]->IsA(args_[ii])) {
271 : return false;
272 : }
273 : }
274 :
275 : return true;
276 : }
277 :
278 1 : std::string AsmOverloadedFunctionType::Name() {
279 : std::string ret;
280 :
281 6 : for (size_t ii = 0; ii < overloads_.size(); ++ii) {
282 2 : if (ii != 0) {
283 : ret += " /\\ ";
284 : }
285 9 : ret += overloads_[ii]->Name();
286 : }
287 :
288 1 : return ret;
289 : }
290 :
291 1353 : bool AsmOverloadedFunctionType::CanBeInvokedWith(
292 : AsmType* return_type, const ZoneVector<AsmType*>& args) {
293 6574 : for (size_t ii = 0; ii < overloads_.size(); ++ii) {
294 8663 : if (overloads_[ii]->AsCallableType()->CanBeInvokedWith(return_type, args)) {
295 : return true;
296 : }
297 : }
298 :
299 : return false;
300 : }
301 :
302 2768392 : void AsmOverloadedFunctionType::AddOverload(AsmType* overload) {
303 : DCHECK_NOT_NULL(overload->AsCallableType());
304 2768392 : overloads_.push_back(overload);
305 2768396 : }
306 :
307 : } // namespace wasm
308 : } // namespace internal
309 : } // namespace v8
|