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 #ifndef SRC_WASM_ASM_TYPES_H_ | |
6 #define SRC_WASM_ASM_TYPES_H_ | |
7 | |
8 #include <string> | |
9 #include <type_traits> | |
10 | |
11 #include "src/base/macros.h" | |
12 #include "src/zone-containers.h" | |
13 #include "src/zone.h" | |
14 | |
15 namespace v8 { | |
16 namespace internal { | |
17 namespace wasm { | |
18 | |
19 class AsmType; | |
20 class AsmFunctionType; | |
21 class AsmOverloadedFunctionType; | |
22 | |
23 // List of V(CamelName, string_name, number, parent_types) | |
24 #define FOR_EACH_ASM_VALUE_TYPE_LIST(V) \ | |
25 /* These tags are not types that are expressable in the asm source. They */ \ | |
26 /* are used to express semantic information about the types they tag. */ \ | |
27 V(Heap, "[]", 1, 0) \ | |
28 /*The following are actual types that appear in the asm source. */ \ | |
29 V(Void, "void", 2, 0) \ | |
30 V(Extern, "extern", 3, 0) \ | |
31 V(DoubleQ, "double?", 4, 0) \ | |
32 V(Double, "double", 5, kAsmDoubleQ | kAsmExtern) \ | |
33 V(Intish, "intish", 6, 0) \ | |
34 V(Int, "int", 7, kAsmIntish) \ | |
35 V(Signed, "signed", 8, kAsmInt | kAsmExtern) \ | |
36 V(Unsigned, "unsigned", 9, kAsmInt) \ | |
37 V(FixNum, "fixnum", 10, kAsmSigned | kAsmUnsigned) \ | |
38 V(Floatish, "floatish", 11, 0) \ | |
39 V(FloatQ, "float?", 12, kAsmFloatish) \ | |
40 V(Float, "float", 13, kAsmFloatQ) \ | |
41 /* Types used for expressing the Heap accesses. */ \ | |
42 V(Uint8Array, "Uint8Array", 14, kAsmHeap) \ | |
43 V(Int8Array, "Int8Array", 15, kAsmHeap) \ | |
44 V(Uint16Array, "Uint16Array", 16, kAsmHeap) \ | |
45 V(Int16Array, "Int16Array", 17, kAsmHeap) \ | |
46 V(Uint32Array, "Uint32Array", 18, kAsmHeap) \ | |
47 V(Int32Array, "Int32Array", 19, kAsmHeap) \ | |
48 V(Float32Array, "Float32Array", 20, kAsmHeap) \ | |
49 V(Float64Array, "Float64Array", 21, kAsmHeap) \ | |
50 V(FloatishDoubleQ, "floatish|double?", 22, kAsmFloatish | kAsmDoubleQ) \ | |
51 V(FloatQDoubleQ, "float?|double?", 23, kAsmFloatQ | kAsmDoubleQ) \ | |
52 /* None is used to represent errors in the type checker. */ \ | |
53 V(None, "<none>", 31, 0) | |
54 | |
55 // List of V(CamelName) | |
56 #define FOR_EACH_ASM_CALLABLE_TYPE_LIST(V) \ | |
57 V(FunctionType) \ | |
58 V(OverloadedFunctionType) | |
59 | |
60 class AsmValueType { | |
61 public: | |
62 typedef uint32_t bitset_t; | |
ahaas
2016/06/13 16:27:03
is it necessary/helpful to introduce this type her
John
2016/06/13 17:32:27
It is a personal decision: I personally prefer typ
| |
63 | |
64 static constexpr uint32_t kAsmUnknown = 0; | |
65 static constexpr uint32_t kAsmValueTypeTag = 1u << 0; | |
ahaas
2016/06/13 16:27:03
Why do you shift by 0?
John
2016/06/13 17:32:27
Because this is a sequence of related constants, a
| |
66 #define DEFINE_TAG(CamelName, string_name, number, parent_types) \ | |
67 static constexpr uint32_t kAsm##CamelName = \ | |
68 ((1 << (number)) | (parent_types)); | |
69 FOR_EACH_ASM_VALUE_TYPE_LIST(DEFINE_TAG) | |
70 #undef DEFINE_TAG | |
71 | |
72 private: | |
73 friend class AsmType; | |
74 | |
75 static AsmValueType* AsValueType(AsmType* type) { | |
76 if ((reinterpret_cast<uintptr_t>(type) & kAsmValueTypeTag) == | |
77 kAsmValueTypeTag) { | |
78 return reinterpret_cast<AsmValueType*>(type); | |
79 } | |
80 return nullptr; | |
81 } | |
82 | |
83 bitset_t Bitset() const { | |
84 DCHECK((reinterpret_cast<uintptr_t>(this) & kAsmValueTypeTag) == | |
85 kAsmValueTypeTag); | |
86 return static_cast<bitset_t>(reinterpret_cast<uintptr_t>(this) & | |
87 ~kAsmValueTypeTag); | |
88 } | |
89 | |
90 static AsmType* New(bitset_t bits) { | |
91 DCHECK_EQ((bits & kAsmValueTypeTag), 0); | |
92 return reinterpret_cast<AsmType*>( | |
93 static_cast<uintptr_t>(bits | kAsmValueTypeTag)); | |
94 } | |
95 | |
96 // AsmValueTypes can't be created except through AsmValueType::New. | |
97 DISALLOW_IMPLICIT_CONSTRUCTORS(AsmValueType); | |
98 }; | |
99 // No destructors for AsmValueType. | |
100 STATIC_ASSERT(std::is_trivially_destructible<AsmValueType>::value); | |
101 | |
102 class AsmCallableType : public ZoneObject { | |
103 public: | |
104 virtual std::string Name() = 0; | |
105 virtual AsmType* ValidateCall(AsmType* function_type) = 0; | |
106 | |
107 #define DECLARE_CAST(CamelName) \ | |
108 virtual Asm##CamelName* As##CamelName() { return nullptr; } | |
109 FOR_EACH_ASM_CALLABLE_TYPE_LIST(DECLARE_CAST) | |
110 #undef DECLARE_CAST | |
111 | |
112 protected: | |
113 AsmCallableType() = default; | |
114 virtual ~AsmCallableType() = default; | |
115 | |
116 private: | |
117 DISALLOW_COPY_AND_ASSIGN(AsmCallableType); | |
118 }; | |
119 | |
120 class AsmFunctionType : public AsmCallableType { | |
121 public: | |
122 AsmFunctionType* AsFunctionType() final { return this; } | |
123 | |
124 void AddArgument(AsmType* type) { args_.push_back(type); } | |
125 const ZoneVector<AsmType*> Arguments() const { return args_; } | |
126 AsmType* ReturnType() const { return return_type_; } | |
127 | |
128 virtual bool IsMinMaxType() const { return false; } | |
129 virtual bool IsFroundType() const { return false; } | |
130 | |
131 protected: | |
132 AsmFunctionType(Zone* zone, AsmType* return_type) | |
133 : return_type_(return_type), args_(zone) {} | |
134 | |
135 private: | |
136 friend AsmType; | |
137 | |
138 std::string Name() override; | |
139 AsmType* ValidateCall(AsmType* function_type) override; | |
140 | |
141 AsmType* return_type_; | |
142 ZoneVector<AsmType*> args_; | |
143 | |
144 DISALLOW_COPY_AND_ASSIGN(AsmFunctionType); | |
145 }; | |
146 | |
147 class AsmOverloadedFunctionType final : public AsmCallableType { | |
148 public: | |
149 AsmOverloadedFunctionType* AsOverloadedFunctionType() override { | |
150 return this; | |
151 } | |
152 | |
153 void AddOverload(AsmType* overload); | |
154 | |
155 private: | |
156 friend AsmType; | |
157 | |
158 explicit AsmOverloadedFunctionType(Zone* zone) : overloads_(zone) {} | |
159 | |
160 std::string Name() override; | |
161 AsmType* ValidateCall(AsmType* function_type) override; | |
162 | |
163 ZoneVector<AsmType*> overloads_; | |
164 | |
165 DISALLOW_IMPLICIT_CONSTRUCTORS(AsmOverloadedFunctionType); | |
166 }; | |
167 | |
168 class AsmType { | |
169 public: | |
170 #define DEFINE_CONSTRUCTOR(CamelName, string_name, number, parent_types) \ | |
171 static AsmType* CamelName() { \ | |
172 return AsmValueType::New(AsmValueType::kAsm##CamelName); \ | |
173 } | |
174 FOR_EACH_ASM_VALUE_TYPE_LIST(DEFINE_CONSTRUCTOR) | |
175 #undef DEFINE_CONSTRUCTOR | |
176 | |
177 #define DEFINE_CAST(CamelCase) \ | |
178 Asm##CamelCase* As##CamelCase() { \ | |
179 if (AsValueType() != nullptr) { \ | |
180 return nullptr; \ | |
181 } \ | |
182 return reinterpret_cast<AsmCallableType*>(this)->As##CamelCase(); \ | |
183 } | |
184 FOR_EACH_ASM_CALLABLE_TYPE_LIST(DEFINE_CAST) | |
185 #undef DEFINE_CAST | |
186 AsmValueType* AsValueType() { return AsmValueType::AsValueType(this); } | |
187 AsmCallableType* AsCallableType(); | |
188 | |
189 // A function returning ret. Callers still need to invoke AddArgument with the | |
190 // returned type to fully create this type. | |
191 static AsmType* Function(Zone* zone, AsmType* ret) { | |
192 AsmFunctionType* f = new (zone) AsmFunctionType(zone, ret); | |
193 return reinterpret_cast<AsmType*>(f); | |
194 } | |
195 | |
196 // Overloaded function types. Not creatable by asm source, but useful to | |
197 // represent the overloaded stdlib functions. | |
198 static AsmType* OverloadedFunction(Zone* zone) { | |
199 auto* f = new (zone) AsmOverloadedFunctionType(zone); | |
200 return reinterpret_cast<AsmType*>(f); | |
201 } | |
202 | |
203 // The type for fround(src). | |
204 static AsmType* FroundType(Zone* zone, AsmType* src); | |
205 | |
206 // The (variadic) type for min and max. | |
207 static AsmType* MinMaxType(Zone* zone, AsmType* type); | |
208 | |
209 std::string Name(); | |
210 // IsExactly returns true if this is the exact same type as that. For | |
211 // non-value types (e.g., callables), this returns this == that. | |
212 bool IsExactly(AsmType* that); | |
213 // IsA is used to query whether this is an instance of that (i.e., if this is | |
214 // a type derived from that.) For non-value types (e.g., callables), this | |
215 // returns this == that. | |
216 bool IsA(AsmType* that); | |
217 | |
218 // Types allowed in return statements. void is the type for returns without | |
219 // an expression. | |
220 bool IsReturnType() { | |
221 return this == AsmType::Void() || this == AsmType::Double() || | |
222 this == AsmType::Signed() || this == AsmType::Float(); | |
223 } | |
224 | |
225 // Types allowed to be parameters in asm functions. | |
226 bool IsParameterType() { | |
227 return this == AsmType::Double() || this == AsmType::Int() || | |
228 this == AsmType::Float(); | |
229 } | |
230 | |
231 // Types allowed to be compared using the comparison operators. | |
232 bool IsComparableType() { | |
233 return this == AsmType::Double() || this == AsmType::Signed() || | |
234 this == AsmType::Unsigned() || this == AsmType::Float(); | |
235 } | |
236 | |
237 // The following methods are meant to be used for inspecting the traits of | |
238 // element types for the heap view types. | |
239 static constexpr int32_t kNotHeapType = -1; | |
240 // Returns the element size if this is a heap type. Otherwise returns | |
241 // kNotHeapType. | |
242 int32_t ElementSizeInBytes(); | |
243 // Returns the load type if this is a heap type. AsmType::None is returned if | |
244 // this is not a heap type. | |
245 AsmType* LoadType(); | |
246 // Returns the store type if this is a heap type. AsmType::None is returned if | |
247 // this is not a heap type. | |
248 AsmType* StoreType(); | |
249 }; | |
250 | |
251 } // namespace wasm | |
252 } // namespace internal | |
253 } // namespace v8 | |
254 | |
255 #endif // SRC_WASM_ASM_TYPES_H_ | |
OLD | NEW |