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 36289 : AsmCallableType* AsmType::AsCallableType() {
17 196046 : if (AsValueType() != nullptr) {
18 : return nullptr;
19 : }
20 :
21 36289 : 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 252031 : bool AsmType::IsExactly(AsmType* x, AsmType* y) {
42 : // TODO(jpp): maybe this can become x == y.
43 315958 : if (x == nullptr) return y == nullptr;
44 : AsmValueType* avt = x->AsValueType();
45 86400 : if (avt != nullptr) {
46 : AsmValueType* tavt = y->AsValueType();
47 86183 : if (tavt == nullptr) {
48 : return false;
49 : }
50 86015 : 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 217 : return x == y;
56 : }
57 :
58 15499980 : bool AsmType::IsA(AsmType* that) {
59 : // IsA is used for querying inheritance relationships. Therefore it is only
60 : // meaningful for basic types.
61 15499980 : if (auto* avt = this->AsValueType()) {
62 15345824 : if (auto* tavt = that->AsValueType()) {
63 15146048 : return (avt->Bitset() & tavt->Bitset()) == tavt->Bitset();
64 : }
65 : return false;
66 : }
67 :
68 154156 : if (auto* as_callable = this->AsCallableType()) {
69 154156 : return as_callable->IsA(that);
70 : }
71 :
72 0 : UNREACHABLE();
73 : }
74 :
75 169689 : int32_t AsmType::ElementSizeInBytes() {
76 : auto* value = AsValueType();
77 169689 : if (value == nullptr) {
78 : return AsmType::kNotHeapType;
79 : }
80 169682 : switch (value->Bitset()) {
81 : case AsmValueType::kAsmInt8Array:
82 : case AsmValueType::kAsmUint8Array:
83 : return 1;
84 : case AsmValueType::kAsmInt16Array:
85 : case AsmValueType::kAsmUint16Array:
86 4725 : return 2;
87 : case AsmValueType::kAsmInt32Array:
88 : case AsmValueType::kAsmUint32Array:
89 : case AsmValueType::kAsmFloat32Array:
90 141985 : return 4;
91 : case AsmValueType::kAsmFloat64Array:
92 5685 : return 8;
93 : default:
94 16 : return AsmType::kNotHeapType;
95 : }
96 : }
97 :
98 103763 : AsmType* AsmType::LoadType() {
99 : auto* value = AsValueType();
100 103763 : if (value == nullptr) {
101 : return AsmType::None();
102 : }
103 103756 : switch (value->Bitset()) {
104 : case AsmValueType::kAsmInt8Array:
105 : case AsmValueType::kAsmUint8Array:
106 : case AsmValueType::kAsmInt16Array:
107 : case AsmValueType::kAsmUint16Array:
108 : case AsmValueType::kAsmInt32Array:
109 : case AsmValueType::kAsmUint32Array:
110 : return AsmType::Intish();
111 : case AsmValueType::kAsmFloat32Array:
112 5914 : return AsmType::FloatQ();
113 : case AsmValueType::kAsmFloat64Array:
114 3068 : return AsmType::DoubleQ();
115 : default:
116 16 : return AsmType::None();
117 : }
118 : }
119 :
120 65932 : AsmType* AsmType::StoreType() {
121 : auto* value = AsValueType();
122 65932 : if (value == nullptr) {
123 : return AsmType::None();
124 : }
125 65925 : switch (value->Bitset()) {
126 : case AsmValueType::kAsmInt8Array:
127 : case AsmValueType::kAsmUint8Array:
128 : case AsmValueType::kAsmInt16Array:
129 : case AsmValueType::kAsmUint16Array:
130 : case AsmValueType::kAsmInt32Array:
131 : case AsmValueType::kAsmUint32Array:
132 : return AsmType::Intish();
133 : case AsmValueType::kAsmFloat32Array:
134 3501 : return AsmType::FloatishDoubleQ();
135 : case AsmValueType::kAsmFloat64Array:
136 2619 : return AsmType::FloatQDoubleQ();
137 : default:
138 16 : return AsmType::None();
139 : }
140 : }
141 :
142 3675 : bool AsmCallableType::IsA(AsmType* other) {
143 3675 : return other->AsCallableType() == this;
144 : }
145 :
146 3 : std::string AsmFunctionType::Name() {
147 : std::string ret;
148 : ret += "(";
149 13 : for (size_t ii = 0; ii < args_.size(); ++ii) {
150 10 : ret += args_[ii]->Name();
151 5 : if (ii != args_.size() - 1) {
152 : ret += ", ";
153 : }
154 : }
155 : ret += ") -> ";
156 6 : ret += return_type_->Name();
157 3 : return ret;
158 : }
159 :
160 : namespace {
161 0 : class AsmFroundType final : public AsmCallableType {
162 : public:
163 : friend AsmType;
164 :
165 3761 : AsmFroundType() : AsmCallableType() {}
166 :
167 : bool CanBeInvokedWith(AsmType* return_type,
168 : const ZoneVector<AsmType*>& args) override;
169 :
170 1 : std::string Name() override { return "fround"; }
171 : };
172 : } // namespace
173 :
174 3761 : AsmType* AsmType::FroundType(Zone* zone) {
175 : auto* Fround = new (zone) AsmFroundType();
176 3761 : return reinterpret_cast<AsmType*>(Fround);
177 : }
178 :
179 8 : bool AsmFroundType::CanBeInvokedWith(AsmType* return_type,
180 : const ZoneVector<AsmType*>& args) {
181 8 : if (args.size() != 1) {
182 : return false;
183 : }
184 :
185 8 : auto* arg = args[0];
186 24 : if (!arg->IsA(AsmType::Floatish()) && !arg->IsA(AsmType::DoubleQ()) &&
187 12 : !arg->IsA(AsmType::Signed()) && !arg->IsA(AsmType::Unsigned())) {
188 : return false;
189 : }
190 :
191 8 : return true;
192 : }
193 :
194 : namespace {
195 0 : class AsmMinMaxType final : public AsmCallableType {
196 : private:
197 : friend AsmType;
198 :
199 : AsmMinMaxType(AsmType* dest, AsmType* src)
200 11275 : : AsmCallableType(), return_type_(dest), arg_(src) {}
201 :
202 624 : bool CanBeInvokedWith(AsmType* return_type,
203 : const ZoneVector<AsmType*>& args) override {
204 1248 : if (!AsmType::IsExactly(return_type_, return_type)) {
205 : return false;
206 : }
207 :
208 181 : if (args.size() < 2) {
209 : return false;
210 : }
211 :
212 701 : for (size_t ii = 0; ii < args.size(); ++ii) {
213 636 : if (!args[ii]->IsA(arg_)) {
214 : return false;
215 : }
216 : }
217 :
218 : return true;
219 : }
220 :
221 3 : std::string Name() override {
222 21 : return "(" + arg_->Name() + ", " + arg_->Name() + "...) -> " +
223 9 : return_type_->Name();
224 : }
225 :
226 : AsmType* return_type_;
227 : AsmType* arg_;
228 : };
229 : } // namespace
230 :
231 11275 : AsmType* AsmType::MinMaxType(Zone* zone, AsmType* dest, AsmType* src) {
232 : DCHECK_NOT_NULL(dest->AsValueType());
233 : DCHECK_NOT_NULL(src->AsValueType());
234 : auto* MinMax = new (zone) AsmMinMaxType(dest, src);
235 11275 : return reinterpret_cast<AsmType*>(MinMax);
236 : }
237 :
238 150481 : bool AsmFunctionType::IsA(AsmType* other) {
239 : auto* that = other->AsFunctionType();
240 150481 : if (that == nullptr) {
241 : return false;
242 : }
243 14392 : if (!AsmType::IsExactly(return_type_, that->return_type_)) {
244 : return false;
245 : }
246 :
247 7187 : if (args_.size() != that->args_.size()) {
248 : return false;
249 : }
250 :
251 37839 : for (size_t ii = 0; ii < args_.size(); ++ii) {
252 46053 : if (!AsmType::IsExactly(args_[ii], that->args_[ii])) {
253 : return false;
254 : }
255 : }
256 :
257 : return true;
258 : }
259 :
260 40756 : bool AsmFunctionType::CanBeInvokedWith(AsmType* return_type,
261 : const ZoneVector<AsmType*>& args) {
262 81512 : if (!AsmType::IsExactly(return_type_, return_type)) {
263 : return false;
264 : }
265 :
266 36168 : if (args_.size() != args.size()) {
267 : return false;
268 : }
269 :
270 203017 : for (size_t ii = 0; ii < args_.size(); ++ii) {
271 166916 : if (!args[ii]->IsA(args_[ii])) {
272 : return false;
273 : }
274 : }
275 :
276 : return true;
277 : }
278 :
279 1 : std::string AsmOverloadedFunctionType::Name() {
280 : std::string ret;
281 :
282 5 : for (size_t ii = 0; ii < overloads_.size(); ++ii) {
283 2 : if (ii != 0) {
284 : ret += " /\\ ";
285 : }
286 4 : ret += overloads_[ii]->Name();
287 : }
288 :
289 1 : return ret;
290 : }
291 :
292 1010 : bool AsmOverloadedFunctionType::CanBeInvokedWith(
293 : AsmType* return_type, const ZoneVector<AsmType*>& args) {
294 3544 : for (size_t ii = 0; ii < overloads_.size(); ++ii) {
295 3836 : if (overloads_[ii]->AsCallableType()->CanBeInvokedWith(return_type, args)) {
296 : return true;
297 : }
298 : }
299 :
300 : return false;
301 : }
302 :
303 30055 : void AsmOverloadedFunctionType::AddOverload(AsmType* overload) {
304 : DCHECK_NOT_NULL(overload->AsCallableType());
305 30055 : overloads_.push_back(overload);
306 30059 : }
307 :
308 : } // namespace wasm
309 : } // namespace internal
310 122036 : } // namespace v8
|