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 2231757 : 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 231129 : : val_(val) {}
67 :
68 120626 : constexpr LoadTypeValue value() const { return val_; }
69 260158 : constexpr unsigned size_log_2() const { return kLoadSizeLog2[val_]; }
70 74800 : constexpr unsigned size() const { return 1 << size_log_2(); }
71 357384 : constexpr ValueType value_type() const { return kValueType[val_]; }
72 97243 : constexpr MachineType mem_type() const { return kMemType[val_]; }
73 :
74 485 : static LoadType ForValueType(ValueType type) {
75 485 : switch (type) {
76 : case kWasmI32:
77 335 : return kI32Load;
78 : case kWasmI64:
79 22 : return kI64Load;
80 : case kWasmF32:
81 64 : return kF32Load;
82 : case kWasmF64:
83 64 : 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 260614 : : val_(val) {}
134 :
135 105360 : constexpr StoreTypeValue value() const { return val_; }
136 365665 : constexpr unsigned size_log_2() const { return kStoreSizeLog2[val_]; }
137 105150 : constexpr unsigned size() const { return 1 << size_log_2(); }
138 509042 : constexpr ValueType value_type() const { return kValueType[val_]; }
139 143239 : constexpr MachineRepresentation mem_rep() const { return kMemRep[val_]; }
140 :
141 176 : static StoreType ForValueType(ValueType type) {
142 176 : switch (type) {
143 : case kWasmI32:
144 108 : return kI32Store;
145 : case kWasmI64:
146 13 : return kI64Store;
147 : case kWasmF32:
148 26 : return kF32Store;
149 : case kWasmF64:
150 29 : 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 8003367 : static inline bool IsSubType(ValueType expected, ValueType actual) {
182 77204 : return (expected == actual) ||
183 154061 : (expected == kWasmAnyRef && actual == kWasmNullRef) ||
184 153673 : (expected == kWasmAnyRef && actual == kWasmAnyFunc) ||
185 153632 : (expected == kWasmAnyRef && actual == kWasmExceptRef) ||
186 8156782 : (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 8079966 : (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 950754 : return type == kWasmAnyRef || type == kWasmAnyFunc ||
199 950754 : type == kWasmExceptRef;
200 : }
201 :
202 : static byte MemSize(MachineType type) {
203 1046523 : return 1 << i::ElementSizeLog2Of(type.representation());
204 : }
205 :
206 1235449 : static int ElementSizeInBytes(ValueType type) {
207 1235449 : switch (type) {
208 : case kWasmI32:
209 : case kWasmF32:
210 : return 4;
211 : case kWasmI64:
212 : case kWasmF64:
213 77720 : return 8;
214 : case kWasmS128:
215 0 : return 16;
216 : case kWasmAnyRef:
217 : case kWasmAnyFunc:
218 : case kWasmExceptRef:
219 7842 : return kSystemPointerSize;
220 : default:
221 0 : UNREACHABLE();
222 : }
223 : }
224 :
225 107734 : static int ElementSizeLog2Of(ValueType type) {
226 107734 : switch (type) {
227 : case kWasmI32:
228 : case kWasmF32:
229 : return 2;
230 : case kWasmI64:
231 : case kWasmF64:
232 3 : return 3;
233 : case kWasmS128:
234 0 : return 4;
235 : default:
236 0 : UNREACHABLE();
237 : }
238 : }
239 :
240 107728 : static byte MemSize(ValueType type) { return 1 << ElementSizeLog2Of(type); }
241 :
242 59964 : static ValueTypeCode ValueTypeCodeFor(ValueType type) {
243 59964 : switch (type) {
244 : case kWasmI32:
245 : return kLocalI32;
246 : case kWasmI64:
247 17011 : return kLocalI64;
248 : case kWasmF32:
249 1326 : return kLocalF32;
250 : case kWasmF64:
251 3808 : return kLocalF64;
252 : case kWasmS128:
253 3256 : return kLocalS128;
254 : case kWasmAnyRef:
255 37 : return kLocalAnyRef;
256 : case kWasmAnyFunc:
257 0 : return kLocalAnyFunc;
258 : case kWasmExceptRef:
259 1 : return kLocalExceptRef;
260 : case kWasmStmt:
261 12 : return kLocalVoid;
262 : default:
263 0 : UNREACHABLE();
264 : }
265 : }
266 :
267 1378477 : static MachineType MachineTypeFor(ValueType type) {
268 1378477 : switch (type) {
269 : case kWasmI32:
270 : return MachineType::Int32();
271 : case kWasmI64:
272 : return MachineType::Int64();
273 : case kWasmF32:
274 : return MachineType::Float32();
275 : case kWasmF64:
276 : return MachineType::Float64();
277 : case kWasmAnyRef:
278 : case kWasmAnyFunc:
279 : case kWasmExceptRef:
280 : return MachineType::TaggedPointer();
281 : case kWasmS128:
282 : return MachineType::Simd128();
283 : case kWasmStmt:
284 : return MachineType::None();
285 : default:
286 0 : UNREACHABLE();
287 : }
288 : }
289 :
290 4815705 : static MachineRepresentation MachineRepresentationFor(ValueType type) {
291 4815705 : switch (type) {
292 : case kWasmI32:
293 : return MachineRepresentation::kWord32;
294 : case kWasmI64:
295 137913 : return MachineRepresentation::kWord64;
296 : case kWasmF32:
297 469055 : return MachineRepresentation::kFloat32;
298 : case kWasmF64:
299 685621 : return MachineRepresentation::kFloat64;
300 : case kWasmAnyRef:
301 : case kWasmAnyFunc:
302 : case kWasmExceptRef:
303 25711 : return MachineRepresentation::kTaggedPointer;
304 : case kWasmS128:
305 32 : return MachineRepresentation::kSimd128;
306 : case kWasmStmt:
307 0 : return MachineRepresentation::kNone;
308 : default:
309 0 : UNREACHABLE();
310 : }
311 : }
312 :
313 1156656 : static ValueType ValueTypeFor(MachineType type) {
314 1156656 : switch (type.representation()) {
315 : case MachineRepresentation::kWord8:
316 : case MachineRepresentation::kWord16:
317 : case MachineRepresentation::kWord32:
318 : return kWasmI32;
319 : case MachineRepresentation::kWord64:
320 : return kWasmI64;
321 : case MachineRepresentation::kFloat32:
322 : return kWasmF32;
323 : case MachineRepresentation::kFloat64:
324 : return kWasmF64;
325 : case MachineRepresentation::kTaggedPointer:
326 : return kWasmAnyRef;
327 : case MachineRepresentation::kSimd128:
328 : return kWasmS128;
329 : default:
330 0 : UNREACHABLE();
331 : }
332 : }
333 :
334 : static char ShortNameOf(ValueType type) {
335 : switch (type) {
336 : case kWasmI32:
337 : return 'i';
338 : case kWasmI64:
339 : return 'l';
340 : case kWasmF32:
341 : return 'f';
342 : case kWasmF64:
343 : return 'd';
344 : case kWasmAnyRef:
345 : return 'r';
346 : case kWasmAnyFunc:
347 : return 'a';
348 : case kWasmS128:
349 : return 's';
350 : case kWasmStmt:
351 : return 'v';
352 : case kWasmVar:
353 : return '*';
354 : default:
355 : return '?';
356 : }
357 : }
358 :
359 80651 : static const char* TypeName(ValueType type) {
360 80651 : switch (type) {
361 : case kWasmI32:
362 : return "i32";
363 : case kWasmI64:
364 17800 : return "i64";
365 : case kWasmF32:
366 17089 : return "f32";
367 : case kWasmF64:
368 14267 : return "f64";
369 : case kWasmAnyRef:
370 7059 : return "anyref";
371 : case kWasmAnyFunc:
372 75 : return "anyfunc";
373 : case kWasmNullRef:
374 0 : return "nullref";
375 : case kWasmExceptRef:
376 39 : return "exn";
377 : case kWasmS128:
378 6 : return "s128";
379 : case kWasmStmt:
380 532 : return "<stmt>";
381 : case kWasmVar:
382 0 : return "<var>";
383 : default:
384 0 : return "<unknown>";
385 : }
386 : }
387 :
388 : private:
389 : DISALLOW_IMPLICIT_CONSTRUCTORS(ValueTypes);
390 : };
391 :
392 : } // namespace wasm
393 : } // namespace internal
394 : } // namespace v8
395 :
396 : #endif // V8_WASM_VALUE_TYPE_H_
|