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 namespace wasm {
14 
15 enum ValueType : uint8_t {
16   kWasmStmt,
17   kWasmI32,
18   kWasmI64,
19   kWasmF32,
20   kWasmF64,
21   kWasmS128,
22   kWasmAnyRef,
23   kWasmVar,
24 };
25 
26 // TODO(clemensh): Compute memtype and size from ValueType once we have c++14
27 // constexpr support.
28 #define FOREACH_LOAD_TYPE(V) \
29   V(I32, , Int32, 2)         \
30   V(I32, 8S, Int8, 0)        \
31   V(I32, 8U, Uint8, 0)       \
32   V(I32, 16S, Int16, 1)      \
33   V(I32, 16U, Uint16, 1)     \
34   V(I64, , Int64, 3)         \
35   V(I64, 8S, Int8, 0)        \
36   V(I64, 8U, Uint8, 0)       \
37   V(I64, 16S, Int16, 1)      \
38   V(I64, 16U, Uint16, 1)     \
39   V(I64, 32S, Int32, 2)      \
40   V(I64, 32U, Uint32, 2)     \
41   V(F32, , Float32, 2)       \
42   V(F64, , Float64, 3)       \
43   V(S128, , Simd128, 4)
44 
45 class LoadType {
46  public:
47   enum LoadTypeValue : uint8_t {
48 #define DEF_ENUM(type, suffix, ...) k##type##Load##suffix,
49     FOREACH_LOAD_TYPE(DEF_ENUM)
50 #undef DEF_ENUM
51   };
52 
53   // Allow implicit convertion of the enum value to this wrapper.
LoadType(LoadTypeValue val)54   constexpr LoadType(LoadTypeValue val)  // NOLINT(runtime/explicit)
55       : val_(val) {}
56 
value()57   constexpr LoadTypeValue value() const { return val_; }
size_log_2()58   constexpr unsigned size_log_2() const { return kLoadSizeLog2[val_]; }
size()59   constexpr unsigned size() const { return 1 << size_log_2(); }
value_type()60   constexpr ValueType value_type() const { return kValueType[val_]; }
mem_type()61   constexpr MachineType mem_type() const { return kMemType[val_]; }
62 
ForValueType(ValueType type)63   static LoadType ForValueType(ValueType type) {
64     switch (type) {
65       case kWasmI32:
66         return kI32Load;
67       case kWasmI64:
68         return kI64Load;
69       case kWasmF32:
70         return kF32Load;
71       case kWasmF64:
72         return kF64Load;
73       default:
74         UNREACHABLE();
75     }
76   }
77 
78  private:
79   const LoadTypeValue val_;
80 
81   static constexpr uint8_t kLoadSizeLog2[] = {
82 #define LOAD_SIZE(_, __, ___, size) size,
83       FOREACH_LOAD_TYPE(LOAD_SIZE)
84 #undef LOAD_SIZE
85   };
86 
87   static constexpr ValueType kValueType[] = {
88 #define VALUE_TYPE(type, ...) kWasm##type,
89       FOREACH_LOAD_TYPE(VALUE_TYPE)
90 #undef VALUE_TYPE
91   };
92 
93   static constexpr MachineType kMemType[] = {
94 #define MEMTYPE(_, __, memtype, ___) MachineType::memtype(),
95       FOREACH_LOAD_TYPE(MEMTYPE)
96 #undef MEMTYPE
97   };
98 };
99 
100 #define FOREACH_STORE_TYPE(V) \
101   V(I32, , Word32, 2)         \
102   V(I32, 8, Word8, 0)         \
103   V(I32, 16, Word16, 1)       \
104   V(I64, , Word64, 3)         \
105   V(I64, 8, Word8, 0)         \
106   V(I64, 16, Word16, 1)       \
107   V(I64, 32, Word32, 2)       \
108   V(F32, , Float32, 2)        \
109   V(F64, , Float64, 3)        \
110   V(S128, , Simd128, 4)
111 
112 class StoreType {
113  public:
114   enum StoreTypeValue : uint8_t {
115 #define DEF_ENUM(type, suffix, ...) k##type##Store##suffix,
116     FOREACH_STORE_TYPE(DEF_ENUM)
117 #undef DEF_ENUM
118   };
119 
120   // Allow implicit convertion of the enum value to this wrapper.
StoreType(StoreTypeValue val)121   constexpr StoreType(StoreTypeValue val)  // NOLINT(runtime/explicit)
122       : val_(val) {}
123 
value()124   constexpr StoreTypeValue value() const { return val_; }
size_log_2()125   constexpr unsigned size_log_2() const { return kStoreSizeLog2[val_]; }
size()126   constexpr unsigned size() const { return 1 << size_log_2(); }
value_type()127   constexpr ValueType value_type() const { return kValueType[val_]; }
mem_rep()128   constexpr MachineRepresentation mem_rep() const { return kMemRep[val_]; }
129 
ForValueType(ValueType type)130   static StoreType ForValueType(ValueType type) {
131     switch (type) {
132       case kWasmI32:
133         return kI32Store;
134       case kWasmI64:
135         return kI64Store;
136       case kWasmF32:
137         return kF32Store;
138       case kWasmF64:
139         return kF64Store;
140       default:
141         UNREACHABLE();
142     }
143   }
144 
145  private:
146   const StoreTypeValue val_;
147 
148   static constexpr uint8_t kStoreSizeLog2[] = {
149 #define STORE_SIZE(_, __, ___, size) size,
150       FOREACH_STORE_TYPE(STORE_SIZE)
151 #undef STORE_SIZE
152   };
153 
154   static constexpr ValueType kValueType[] = {
155 #define VALUE_TYPE(type, ...) kWasm##type,
156       FOREACH_STORE_TYPE(VALUE_TYPE)
157 #undef VALUE_TYPE
158   };
159 
160   static constexpr MachineRepresentation kMemRep[] = {
161 #define MEMREP(_, __, memrep, ___) MachineRepresentation::k##memrep,
162       FOREACH_STORE_TYPE(MEMREP)
163 #undef MEMREP
164   };
165 };
166 
167 // A collection of ValueType-related static methods.
168 class V8_EXPORT_PRIVATE ValueTypes {
169  public:
MemSize(MachineType type)170   static byte MemSize(MachineType type) {
171     return 1 << i::ElementSizeLog2Of(type.representation());
172   }
173 
ElementSizeInBytes(ValueType type)174   static int ElementSizeInBytes(ValueType type) {
175     switch (type) {
176       case kWasmI32:
177       case kWasmF32:
178         return 4;
179       case kWasmI64:
180       case kWasmF64:
181         return 8;
182       case kWasmS128:
183         return 16;
184       default:
185         UNREACHABLE();
186     }
187   }
188 
ElementSizeLog2Of(ValueType type)189   static int ElementSizeLog2Of(ValueType type) {
190     switch (type) {
191       case kWasmI32:
192       case kWasmF32:
193         return 2;
194       case kWasmI64:
195       case kWasmF64:
196         return 3;
197       case kWasmS128:
198         return 4;
199       default:
200         UNREACHABLE();
201     }
202   }
203 
MemSize(ValueType type)204   static byte MemSize(ValueType type) { return 1 << ElementSizeLog2Of(type); }
205 
ValueTypeCodeFor(ValueType type)206   static ValueTypeCode ValueTypeCodeFor(ValueType type) {
207     switch (type) {
208       case kWasmI32:
209         return kLocalI32;
210       case kWasmI64:
211         return kLocalI64;
212       case kWasmF32:
213         return kLocalF32;
214       case kWasmF64:
215         return kLocalF64;
216       case kWasmS128:
217         return kLocalS128;
218       case kWasmAnyRef:
219         return kLocalAnyRef;
220       case kWasmStmt:
221         return kLocalVoid;
222       default:
223         UNREACHABLE();
224     }
225   }
226 
MachineTypeFor(ValueType type)227   static MachineType MachineTypeFor(ValueType type) {
228     switch (type) {
229       case kWasmI32:
230         return MachineType::Int32();
231       case kWasmI64:
232         return MachineType::Int64();
233       case kWasmF32:
234         return MachineType::Float32();
235       case kWasmF64:
236         return MachineType::Float64();
237       case kWasmAnyRef:
238         return MachineType::TaggedPointer();
239       case kWasmS128:
240         return MachineType::Simd128();
241       case kWasmStmt:
242         return MachineType::None();
243       default:
244         UNREACHABLE();
245     }
246   }
247 
MachineRepresentationFor(ValueType type)248   static MachineRepresentation MachineRepresentationFor(ValueType type) {
249     switch (type) {
250       case kWasmI32:
251         return MachineRepresentation::kWord32;
252       case kWasmI64:
253         return MachineRepresentation::kWord64;
254       case kWasmF32:
255         return MachineRepresentation::kFloat32;
256       case kWasmF64:
257         return MachineRepresentation::kFloat64;
258       case kWasmAnyRef:
259         return MachineRepresentation::kTaggedPointer;
260       case kWasmS128:
261         return MachineRepresentation::kSimd128;
262       case kWasmStmt:
263         return MachineRepresentation::kNone;
264       default:
265         UNREACHABLE();
266     }
267   }
268 
ValueTypeFor(MachineType type)269   static ValueType ValueTypeFor(MachineType type) {
270     switch (type.representation()) {
271       case MachineRepresentation::kWord8:
272       case MachineRepresentation::kWord16:
273       case MachineRepresentation::kWord32:
274         return kWasmI32;
275       case MachineRepresentation::kWord64:
276         return kWasmI64;
277       case MachineRepresentation::kFloat32:
278         return kWasmF32;
279       case MachineRepresentation::kFloat64:
280         return kWasmF64;
281       case MachineRepresentation::kTaggedPointer:
282         return kWasmAnyRef;
283       case MachineRepresentation::kSimd128:
284         return kWasmS128;
285       default:
286         UNREACHABLE();
287     }
288   }
289 
ShortNameOf(ValueType type)290   static char ShortNameOf(ValueType type) {
291     switch (type) {
292       case kWasmI32:
293         return 'i';
294       case kWasmI64:
295         return 'l';
296       case kWasmF32:
297         return 'f';
298       case kWasmF64:
299         return 'd';
300       case kWasmAnyRef:
301         return 'r';
302       case kWasmS128:
303         return 's';
304       case kWasmStmt:
305         return 'v';
306       case kWasmVar:
307         return '*';
308       default:
309         return '?';
310     }
311   }
312 
TypeName(ValueType type)313   static const char* TypeName(ValueType type) {
314     switch (type) {
315       case kWasmI32:
316         return "i32";
317       case kWasmI64:
318         return "i64";
319       case kWasmF32:
320         return "f32";
321       case kWasmF64:
322         return "f64";
323       case kWasmAnyRef:
324         return "ref";
325       case kWasmS128:
326         return "s128";
327       case kWasmStmt:
328         return "<stmt>";
329       case kWasmVar:
330         return "<var>";
331       default:
332         return "<unknown>";
333     }
334   }
335 
336  private:
337   DISALLOW_IMPLICIT_CONSTRUCTORS(ValueTypes);
338 };
339 
340 }  // namespace wasm
341 }  // namespace internal
342 }  // namespace v8
343 
344 #endif  // V8_WASM_VALUE_TYPE_H_
345