Line data Source code
1 : // Copyright 2018 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 V8_WASM_VALUE_TYPE_H_
6 : #define V8_WASM_VALUE_TYPE_H_
7 :
8 : #include "src/machine-type.h"
9 : #include "src/wasm/wasm-constants.h"
10 :
11 : namespace v8 {
12 : namespace internal {
13 :
14 : template <typename T>
15 : class Signature;
16 :
17 : namespace wasm {
18 :
19 : enum ValueType : uint8_t {
20 : kWasmStmt,
21 : kWasmI32,
22 : kWasmI64,
23 : kWasmF32,
24 : kWasmF64,
25 : kWasmS128,
26 : kWasmAnyRef,
27 : kWasmAnyFunc,
28 : kWasmNullRef,
29 : kWasmExceptRef,
30 : kWasmVar,
31 : };
32 :
33 : using FunctionSig = Signature<ValueType>;
34 :
35 2232091 : inline size_t hash_value(ValueType type) { return static_cast<size_t>(type); }
36 :
37 : // TODO(clemensh): Compute memtype and size from ValueType once we have c++14
38 : // constexpr support.
39 : #define FOREACH_LOAD_TYPE(V) \
40 : V(I32, , Int32, 2) \
41 : V(I32, 8S, Int8, 0) \
42 : V(I32, 8U, Uint8, 0) \
43 : V(I32, 16S, Int16, 1) \
44 : V(I32, 16U, Uint16, 1) \
45 : V(I64, , Int64, 3) \
46 : V(I64, 8S, Int8, 0) \
47 : V(I64, 8U, Uint8, 0) \
48 : V(I64, 16S, Int16, 1) \
49 : V(I64, 16U, Uint16, 1) \
50 : V(I64, 32S, Int32, 2) \
51 : V(I64, 32U, Uint32, 2) \
52 : V(F32, , Float32, 2) \
53 : V(F64, , Float64, 3) \
54 : V(S128, , Simd128, 4)
55 :
56 : class LoadType {
57 : public:
58 : enum LoadTypeValue : uint8_t {
59 : #define DEF_ENUM(type, suffix, ...) k##type##Load##suffix,
60 : FOREACH_LOAD_TYPE(DEF_ENUM)
61 : #undef DEF_ENUM
62 : };
63 :
64 : // Allow implicit convertion of the enum value to this wrapper.
65 : constexpr LoadType(LoadTypeValue val) // NOLINT(runtime/explicit)
66 311052 : : val_(val) {}
67 :
68 203942 : constexpr LoadTypeValue value() const { return val_; }
69 277960 : constexpr unsigned size_log_2() const { return kLoadSizeLog2[val_]; }
70 85338 : constexpr unsigned size() const { return 1 << size_log_2(); }
71 371745 : constexpr ValueType value_type() const { return kValueType[val_]; }
72 93792 : constexpr MachineType mem_type() const { return kMemType[val_]; }
73 :
74 1092 : static LoadType ForValueType(ValueType type) {
75 1092 : switch (type) {
76 : case kWasmI32:
77 792 : return kI32Load;
78 : case kWasmI64:
79 52 : return kI64Load;
80 : case kWasmF32:
81 124 : return kF32Load;
82 : case kWasmF64:
83 124 : return kF64Load;
84 : default:
85 0 : UNREACHABLE();
86 : }
87 : }
88 :
89 : private:
90 : const LoadTypeValue val_;
91 :
92 : static constexpr uint8_t kLoadSizeLog2[] = {
93 : #define LOAD_SIZE(_, __, ___, size) size,
94 : FOREACH_LOAD_TYPE(LOAD_SIZE)
95 : #undef LOAD_SIZE
96 : };
97 :
98 : static constexpr ValueType kValueType[] = {
99 : #define VALUE_TYPE(type, ...) kWasm##type,
100 : FOREACH_LOAD_TYPE(VALUE_TYPE)
101 : #undef VALUE_TYPE
102 : };
103 :
104 : static constexpr MachineType kMemType[] = {
105 : #define MEMTYPE(_, __, memtype, ___) MachineType::memtype(),
106 : FOREACH_LOAD_TYPE(MEMTYPE)
107 : #undef MEMTYPE
108 : };
109 : };
110 :
111 : #define FOREACH_STORE_TYPE(V) \
112 : V(I32, , Word32, 2) \
113 : V(I32, 8, Word8, 0) \
114 : V(I32, 16, Word16, 1) \
115 : V(I64, , Word64, 3) \
116 : V(I64, 8, Word8, 0) \
117 : V(I64, 16, Word16, 1) \
118 : V(I64, 32, Word32, 2) \
119 : V(F32, , Float32, 2) \
120 : V(F64, , Float64, 3) \
121 : V(S128, , Simd128, 4)
122 :
123 : class StoreType {
124 : public:
125 : enum StoreTypeValue : uint8_t {
126 : #define DEF_ENUM(type, suffix, ...) k##type##Store##suffix,
127 : FOREACH_STORE_TYPE(DEF_ENUM)
128 : #undef DEF_ENUM
129 : };
130 :
131 : // Allow implicit convertion of the enum value to this wrapper.
132 : constexpr StoreType(StoreTypeValue val) // NOLINT(runtime/explicit)
133 269843 : : val_(val) {}
134 :
135 113328 : constexpr StoreTypeValue value() const { return val_; }
136 383276 : constexpr unsigned size_log_2() const { return kStoreSizeLog2[val_]; }
137 113535 : constexpr unsigned size() const { return 1 << size_log_2(); }
138 527219 : constexpr ValueType value_type() const { return kValueType[val_]; }
139 143865 : constexpr MachineRepresentation mem_rep() const { return kMemRep[val_]; }
140 :
141 387 : static StoreType ForValueType(ValueType type) {
142 387 : switch (type) {
143 : case kWasmI32:
144 239 : return kI32Store;
145 : case kWasmI64:
146 28 : return kI64Store;
147 : case kWasmF32:
148 56 : return kF32Store;
149 : case kWasmF64:
150 64 : return kF64Store;
151 : default:
152 0 : UNREACHABLE();
153 : }
154 : }
155 :
156 : private:
157 : const StoreTypeValue val_;
158 :
159 : static constexpr uint8_t kStoreSizeLog2[] = {
160 : #define STORE_SIZE(_, __, ___, size) size,
161 : FOREACH_STORE_TYPE(STORE_SIZE)
162 : #undef STORE_SIZE
163 : };
164 :
165 : static constexpr ValueType kValueType[] = {
166 : #define VALUE_TYPE(type, ...) kWasm##type,
167 : FOREACH_STORE_TYPE(VALUE_TYPE)
168 : #undef VALUE_TYPE
169 : };
170 :
171 : static constexpr MachineRepresentation kMemRep[] = {
172 : #define MEMREP(_, __, memrep, ___) MachineRepresentation::k##memrep,
173 : FOREACH_STORE_TYPE(MEMREP)
174 : #undef MEMREP
175 : };
176 : };
177 :
178 : // A collection of ValueType-related static methods.
179 : class V8_EXPORT_PRIVATE ValueTypes {
180 : public:
181 7644570 : static inline bool IsSubType(ValueType expected, ValueType actual) {
182 81754 : return (expected == actual) ||
183 163338 : (expected == kWasmAnyRef && actual == kWasmNullRef) ||
184 163150 : (expected == kWasmAnyRef && actual == kWasmAnyFunc) ||
185 163129 : (expected == kWasmAnyRef && actual == kWasmExceptRef) ||
186 7807592 : (expected == kWasmAnyFunc && actual == kWasmNullRef) ||
187 : // TODO(mstarzinger): For now we treat "null_ref" as a sub-type of
188 : // "except_ref", which is correct but might change. See here:
189 : // https://github.com/WebAssembly/exception-handling/issues/55
190 7726029 : (expected == kWasmExceptRef && actual == kWasmNullRef);
191 : }
192 :
193 : static inline bool IsReferenceType(ValueType type) {
194 : // This function assumes at the moment that it is never called with
195 : // {kWasmNullRef}. If this assumption is wrong, it should be added to the
196 : // result calculation below.
197 : DCHECK_NE(type, kWasmNullRef);
198 949585 : return type == kWasmAnyRef || type == kWasmAnyFunc ||
199 949585 : type == kWasmExceptRef;
200 : }
201 :
202 : static byte MemSize(MachineType type) {
203 1043032 : return 1 << i::ElementSizeLog2Of(type.representation());
204 : }
205 :
206 911984 : static int ElementSizeInBytes(ValueType type) {
207 911984 : switch (type) {
208 : case kWasmI32:
209 : case kWasmF32:
210 : return 4;
211 : case kWasmI64:
212 : case kWasmF64:
213 117472 : return 8;
214 : case kWasmS128:
215 0 : return 16;
216 : default:
217 0 : UNREACHABLE();
218 : }
219 : }
220 :
221 107821 : static int ElementSizeLog2Of(ValueType type) {
222 107821 : switch (type) {
223 : case kWasmI32:
224 : case kWasmF32:
225 : return 2;
226 : case kWasmI64:
227 : case kWasmF64:
228 8 : return 3;
229 : case kWasmS128:
230 0 : return 4;
231 : default:
232 0 : UNREACHABLE();
233 : }
234 : }
235 :
236 107806 : static byte MemSize(ValueType type) { return 1 << ElementSizeLog2Of(type); }
237 :
238 59778 : static ValueTypeCode ValueTypeCodeFor(ValueType type) {
239 59778 : switch (type) {
240 : case kWasmI32:
241 : return kLocalI32;
242 : case kWasmI64:
243 17011 : return kLocalI64;
244 : case kWasmF32:
245 1322 : return kLocalF32;
246 : case kWasmF64:
247 3794 : return kLocalF64;
248 : case kWasmS128:
249 3124 : return kLocalS128;
250 : case kWasmAnyRef:
251 29 : return kLocalAnyRef;
252 : case kWasmExceptRef:
253 1 : return kLocalExceptRef;
254 : case kWasmStmt:
255 12 : return kLocalVoid;
256 : default:
257 0 : UNREACHABLE();
258 : }
259 : }
260 :
261 1377686 : static MachineType MachineTypeFor(ValueType type) {
262 1377686 : switch (type) {
263 : case kWasmI32:
264 : return MachineType::Int32();
265 : case kWasmI64:
266 : return MachineType::Int64();
267 : case kWasmF32:
268 : return MachineType::Float32();
269 : case kWasmF64:
270 : return MachineType::Float64();
271 : case kWasmAnyFunc:
272 : case kWasmAnyRef:
273 : return MachineType::TaggedPointer();
274 : case kWasmS128:
275 : return MachineType::Simd128();
276 : case kWasmStmt:
277 : return MachineType::None();
278 : default:
279 0 : UNREACHABLE();
280 : }
281 : }
282 :
283 4671540 : static MachineRepresentation MachineRepresentationFor(ValueType type) {
284 4671540 : switch (type) {
285 : case kWasmI32:
286 : return MachineRepresentation::kWord32;
287 : case kWasmI64:
288 134093 : return MachineRepresentation::kWord64;
289 : case kWasmF32:
290 379050 : return MachineRepresentation::kFloat32;
291 : case kWasmF64:
292 595194 : return MachineRepresentation::kFloat64;
293 : case kWasmAnyRef:
294 : case kWasmAnyFunc:
295 : case kWasmExceptRef:
296 15481 : return MachineRepresentation::kTaggedPointer;
297 : case kWasmS128:
298 32 : return MachineRepresentation::kSimd128;
299 : case kWasmStmt:
300 0 : return MachineRepresentation::kNone;
301 : default:
302 0 : UNREACHABLE();
303 : }
304 : }
305 :
306 1155968 : static ValueType ValueTypeFor(MachineType type) {
307 1155968 : switch (type.representation()) {
308 : case MachineRepresentation::kWord8:
309 : case MachineRepresentation::kWord16:
310 : case MachineRepresentation::kWord32:
311 : return kWasmI32;
312 : case MachineRepresentation::kWord64:
313 : return kWasmI64;
314 : case MachineRepresentation::kFloat32:
315 : return kWasmF32;
316 : case MachineRepresentation::kFloat64:
317 : return kWasmF64;
318 : case MachineRepresentation::kTaggedPointer:
319 : return kWasmAnyRef;
320 : case MachineRepresentation::kSimd128:
321 : return kWasmS128;
322 : default:
323 0 : UNREACHABLE();
324 : }
325 : }
326 :
327 : static char ShortNameOf(ValueType type) {
328 : switch (type) {
329 : case kWasmI32:
330 : return 'i';
331 : case kWasmI64:
332 : return 'l';
333 : case kWasmF32:
334 : return 'f';
335 : case kWasmF64:
336 : return 'd';
337 : case kWasmAnyRef:
338 : return 'r';
339 : case kWasmAnyFunc:
340 : return 'a';
341 : case kWasmS128:
342 : return 's';
343 : case kWasmStmt:
344 : return 'v';
345 : case kWasmVar:
346 : return '*';
347 : default:
348 : return '?';
349 : }
350 : }
351 :
352 83880 : static const char* TypeName(ValueType type) {
353 83880 : switch (type) {
354 : case kWasmI32:
355 : return "i32";
356 : case kWasmI64:
357 18566 : return "i64";
358 : case kWasmF32:
359 17807 : return "f32";
360 : case kWasmF64:
361 14661 : return "f64";
362 : case kWasmAnyRef:
363 7319 : return "anyref";
364 : case kWasmAnyFunc:
365 190 : return "anyfunc";
366 : case kWasmNullRef:
367 0 : return "nullref";
368 : case kWasmExceptRef:
369 96 : return "exn";
370 : case kWasmS128:
371 16 : return "s128";
372 : case kWasmStmt:
373 532 : return "<stmt>";
374 : case kWasmVar:
375 0 : return "<var>";
376 : default:
377 0 : return "<unknown>";
378 : }
379 : }
380 :
381 : private:
382 : DISALLOW_IMPLICIT_CONSTRUCTORS(ValueTypes);
383 : };
384 :
385 : } // namespace wasm
386 : } // namespace internal
387 : } // namespace v8
388 :
389 : #endif // V8_WASM_VALUE_TYPE_H_
|