blob: a102fc856ff6061c5ada57c6c5dd59cacb666980 [file] [log] [blame]
Ben Murdoch61f157c2016-09-16 13:49:30 +01001// 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#ifndef SRC_WASM_ASM_TYPES_H_
6#define SRC_WASM_ASM_TYPES_H_
7
8#include <string>
9
10#include "src/base/macros.h"
11#include "src/zone-containers.h"
12#include "src/zone.h"
13
14namespace v8 {
15namespace internal {
16namespace wasm {
17
18class AsmType;
19class AsmFFIType;
20class AsmFunctionType;
21class AsmOverloadedFunctionType;
22class AsmFunctionTableType;
23
24// List of V(CamelName, string_name, number, parent_types)
25#define FOR_EACH_ASM_VALUE_TYPE_LIST(V) \
26 /* These tags are not types that are expressable in the asm source. They */ \
27 /* are used to express semantic information about the types they tag. */ \
28 V(Heap, "[]", 1, 0) \
29 /*The following are actual types that appear in the asm source. */ \
30 V(Void, "void", 2, 0) \
31 V(Extern, "extern", 3, 0) \
32 V(DoubleQ, "double?", 4, 0) \
33 V(Double, "double", 5, kAsmDoubleQ | kAsmExtern) \
34 V(Intish, "intish", 6, 0) \
35 V(Int, "int", 7, kAsmIntish) \
36 V(Signed, "signed", 8, kAsmInt | kAsmExtern) \
37 V(Unsigned, "unsigned", 9, kAsmInt) \
38 V(FixNum, "fixnum", 10, kAsmSigned | kAsmUnsigned) \
39 V(Floatish, "floatish", 11, 0) \
40 V(FloatQ, "float?", 12, kAsmFloatish) \
41 V(Float, "float", 13, kAsmFloatQ) \
42 /* Types used for expressing the Heap accesses. */ \
43 V(Uint8Array, "Uint8Array", 14, kAsmHeap) \
44 V(Int8Array, "Int8Array", 15, kAsmHeap) \
45 V(Uint16Array, "Uint16Array", 16, kAsmHeap) \
46 V(Int16Array, "Int16Array", 17, kAsmHeap) \
47 V(Uint32Array, "Uint32Array", 18, kAsmHeap) \
48 V(Int32Array, "Int32Array", 19, kAsmHeap) \
49 V(Float32Array, "Float32Array", 20, kAsmHeap) \
50 V(Float64Array, "Float64Array", 21, kAsmHeap) \
51 /* Pseudo-types used in representing heap access for fp types.*/ \
52 V(FloatishDoubleQ, "floatish|double?", 22, kAsmFloatish | kAsmDoubleQ) \
53 V(FloatQDoubleQ, "float?|double?", 23, kAsmFloatQ | kAsmDoubleQ) \
54 /* None is used to represent errors in the type checker. */ \
55 V(None, "<none>", 31, 0)
56
57// List of V(CamelName)
58#define FOR_EACH_ASM_CALLABLE_TYPE_LIST(V) \
59 V(FunctionType) \
60 V(FFIType) \
61 V(OverloadedFunctionType) \
62 V(FunctionTableType)
63
64class AsmValueType {
65 public:
66 typedef uint32_t bitset_t;
67
68 enum : uint32_t {
69#define DEFINE_TAG(CamelName, string_name, number, parent_types) \
70 kAsm##CamelName = ((1u << (number)) | (parent_types)),
71 FOR_EACH_ASM_VALUE_TYPE_LIST(DEFINE_TAG)
72#undef DEFINE_TAG
73 kAsmUnknown = 0,
74 kAsmValueTypeTag = 1u
75 };
76
77 private:
78 friend class AsmType;
79
80 static AsmValueType* AsValueType(AsmType* type) {
81 if ((reinterpret_cast<uintptr_t>(type) & kAsmValueTypeTag) ==
82 kAsmValueTypeTag) {
83 return reinterpret_cast<AsmValueType*>(type);
84 }
85 return nullptr;
86 }
87
88 bitset_t Bitset() const {
89 DCHECK((reinterpret_cast<uintptr_t>(this) & kAsmValueTypeTag) ==
90 kAsmValueTypeTag);
91 return static_cast<bitset_t>(reinterpret_cast<uintptr_t>(this) &
92 ~kAsmValueTypeTag);
93 }
94
95 static AsmType* New(bitset_t bits) {
96 DCHECK_EQ((bits & kAsmValueTypeTag), 0);
97 return reinterpret_cast<AsmType*>(
98 static_cast<uintptr_t>(bits | kAsmValueTypeTag));
99 }
100
101 // AsmValueTypes can't be created except through AsmValueType::New.
102 DISALLOW_IMPLICIT_CONSTRUCTORS(AsmValueType);
103};
104
105class AsmCallableType : public ZoneObject {
106 public:
107 virtual std::string Name() = 0;
108 virtual AsmType* ValidateCall(AsmType* return_type,
109 const ZoneVector<AsmType*>& args) = 0;
110
111#define DECLARE_CAST(CamelName) \
112 virtual Asm##CamelName* As##CamelName() { return nullptr; }
113 FOR_EACH_ASM_CALLABLE_TYPE_LIST(DECLARE_CAST)
114#undef DECLARE_CAST
115
116 protected:
117 AsmCallableType() = default;
118 virtual ~AsmCallableType() = default;
119
120 private:
121 DISALLOW_COPY_AND_ASSIGN(AsmCallableType);
122};
123
124class AsmFunctionType : public AsmCallableType {
125 public:
126 AsmFunctionType* AsFunctionType() final { return this; }
127
128 void AddArgument(AsmType* type) { args_.push_back(type); }
129 const ZoneVector<AsmType*> Arguments() const { return args_; }
130 AsmType* ReturnType() const { return return_type_; }
131
132 virtual bool IsMinMaxType() const { return false; }
133 virtual bool IsFroundType() const { return false; }
134
135 protected:
136 AsmFunctionType(Zone* zone, AsmType* return_type)
137 : return_type_(return_type), args_(zone) {}
138
139 private:
140 friend AsmType;
141
142 std::string Name() override;
143 AsmType* ValidateCall(AsmType* return_type,
144 const ZoneVector<AsmType*>& args) override;
145
146 AsmType* return_type_;
147 ZoneVector<AsmType*> args_;
148
149 DISALLOW_COPY_AND_ASSIGN(AsmFunctionType);
150};
151
152class AsmOverloadedFunctionType final : public AsmCallableType {
153 public:
154 AsmOverloadedFunctionType* AsOverloadedFunctionType() override {
155 return this;
156 }
157
158 void AddOverload(AsmType* overload);
159
160 private:
161 friend AsmType;
162
163 explicit AsmOverloadedFunctionType(Zone* zone) : overloads_(zone) {}
164
165 std::string Name() override;
166 AsmType* ValidateCall(AsmType* return_type,
167 const ZoneVector<AsmType*>& args) override;
168
169 ZoneVector<AsmType*> overloads_;
170
171 DISALLOW_IMPLICIT_CONSTRUCTORS(AsmOverloadedFunctionType);
172};
173
174class AsmFFIType final : public AsmCallableType {
175 public:
176 AsmFFIType* AsFFIType() override { return this; }
177
178 std::string Name() override { return "Function"; }
179 AsmType* ValidateCall(AsmType* return_type,
180 const ZoneVector<AsmType*>& args) override;
181
182 private:
183 friend AsmType;
184
185 AsmFFIType() = default;
186
187 DISALLOW_COPY_AND_ASSIGN(AsmFFIType);
188};
189
190class AsmFunctionTableType : public AsmCallableType {
191 public:
192 AsmFunctionTableType* AsFunctionTableType() override { return this; }
193
194 std::string Name() override;
195
196 AsmType* ValidateCall(AsmType* return_type,
197 const ZoneVector<AsmType*>& args) override;
198
199 size_t length() const { return length_; }
200
201 private:
202 friend class AsmType;
203
204 AsmFunctionTableType(size_t length, AsmType* signature);
205
206 size_t length_;
207 AsmType* signature_;
208
209 DISALLOW_IMPLICIT_CONSTRUCTORS(AsmFunctionTableType);
210};
211
212class AsmType {
213 public:
214#define DEFINE_CONSTRUCTOR(CamelName, string_name, number, parent_types) \
215 static AsmType* CamelName() { \
216 return AsmValueType::New(AsmValueType::kAsm##CamelName); \
217 }
218 FOR_EACH_ASM_VALUE_TYPE_LIST(DEFINE_CONSTRUCTOR)
219#undef DEFINE_CONSTRUCTOR
220
221#define DEFINE_CAST(CamelCase) \
222 Asm##CamelCase* As##CamelCase() { \
223 if (AsValueType() != nullptr) { \
224 return nullptr; \
225 } \
226 return reinterpret_cast<AsmCallableType*>(this)->As##CamelCase(); \
227 }
228 FOR_EACH_ASM_CALLABLE_TYPE_LIST(DEFINE_CAST)
229#undef DEFINE_CAST
230 AsmValueType* AsValueType() { return AsmValueType::AsValueType(this); }
231 AsmCallableType* AsCallableType();
232
233 // A function returning ret. Callers still need to invoke AddArgument with the
234 // returned type to fully create this type.
235 static AsmType* Function(Zone* zone, AsmType* ret) {
236 AsmFunctionType* f = new (zone) AsmFunctionType(zone, ret);
237 return reinterpret_cast<AsmType*>(f);
238 }
239
240 // Overloaded function types. Not creatable by asm source, but useful to
241 // represent the overloaded stdlib functions.
242 static AsmType* OverloadedFunction(Zone* zone) {
243 auto* f = new (zone) AsmOverloadedFunctionType(zone);
244 return reinterpret_cast<AsmType*>(f);
245 }
246
247 // The type for fround(src).
248 static AsmType* FroundType(Zone* zone);
249
250 // The (variadic) type for min and max.
251 static AsmType* MinMaxType(Zone* zone, AsmType* dest, AsmType* src);
252
253 // The type for foreign functions.
254 static AsmType* FFIType(Zone* zone) {
255 auto* f = new (zone) AsmFFIType();
256 return reinterpret_cast<AsmType*>(f);
257 }
258
259 // The type for function tables.
260 static AsmType* FunctionTableType(Zone* zone, size_t length,
261 AsmType* signature) {
262 auto* f = new (zone) AsmFunctionTableType(length, signature);
263 return reinterpret_cast<AsmType*>(f);
264 }
265
266 std::string Name();
267 // IsExactly returns true if this is the exact same type as that. For
268 // non-value types (e.g., callables), this returns this == that.
269 bool IsExactly(AsmType* that);
270 // IsA is used to query whether this is an instance of that (i.e., if this is
271 // a type derived from that.) For non-value types (e.g., callables), this
272 // returns this == that.
273 bool IsA(AsmType* that);
274
275 // Types allowed in return statements. void is the type for returns without
276 // an expression.
277 bool IsReturnType() {
278 return this == AsmType::Void() || this == AsmType::Double() ||
279 this == AsmType::Signed() || this == AsmType::Float();
280 }
281
282 // Converts this to the corresponding valid argument type.
283 AsmType* ToReturnType() {
284 if (this->IsA(AsmType::Signed())) {
285 return AsmType::Signed();
286 }
287 if (this->IsA(AsmType::Double())) {
288 return AsmType::Double();
289 }
290 if (this->IsA(AsmType::Float())) {
291 return AsmType::Float();
292 }
293 if (this->IsA(AsmType::Void())) {
294 return AsmType::Void();
295 }
296 return AsmType::None();
297 }
298
299 // Types allowed to be parameters in asm functions.
300 bool IsParameterType() {
301 return this == AsmType::Double() || this == AsmType::Int() ||
302 this == AsmType::Float();
303 }
304
305 // Converts this to the corresponding valid argument type.
306 AsmType* ToParameterType() {
307 if (this->IsA(AsmType::Int())) {
308 return AsmType::Int();
309 }
310 if (this->IsA(AsmType::Double())) {
311 return AsmType::Double();
312 }
313 if (this->IsA(AsmType::Float())) {
314 return AsmType::Float();
315 }
316 return AsmType::None();
317 }
318
319 // Types allowed to be compared using the comparison operators.
320 bool IsComparableType() {
321 return this == AsmType::Double() || this == AsmType::Signed() ||
322 this == AsmType::Unsigned() || this == AsmType::Float();
323 }
324
325 // The following methods are meant to be used for inspecting the traits of
326 // element types for the heap view types.
327 enum : int32_t { kNotHeapType = -1 };
328
329 // Returns the element size if this is a heap type. Otherwise returns
330 // kNotHeapType.
331 int32_t ElementSizeInBytes();
332 // Returns the load type if this is a heap type. AsmType::None is returned if
333 // this is not a heap type.
334 AsmType* LoadType();
335 // Returns the store type if this is a heap type. AsmType::None is returned if
336 // this is not a heap type.
337 AsmType* StoreType();
338};
339
340} // namespace wasm
341} // namespace internal
342} // namespace v8
343
344#endif // SRC_WASM_ASM_TYPES_H_