1 // Copyright 2017 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_WASM_VALUE_H_
6 #define V8_WASM_WASM_VALUE_H_
7
8 #include "src/boxed-float.h"
9 #include "src/v8memory.h"
10 #include "src/wasm/wasm-opcodes.h"
11 #include "src/zone/zone-containers.h"
12
13 namespace v8 {
14 namespace internal {
15 namespace wasm {
16
17 #define FOREACH_SIMD_TYPE(V) \
18 V(float, float4, f32x4, 4) \
19 V(int32_t, int4, i32x4, 4) \
20 V(int16_t, int8, i16x8, 8) \
21 V(int8_t, int16, i8x16, 16)
22
23 #define DEFINE_SIMD_TYPE(cType, sType, name, kSize) \
24 struct sType { \
25 cType val[kSize]; \
26 };
FOREACH_SIMD_TYPE(DEFINE_SIMD_TYPE)27 FOREACH_SIMD_TYPE(DEFINE_SIMD_TYPE)
28 #undef DEFINE_SIMD_TYPE
29
30 class Simd128 {
31 public:
32 Simd128() : val_() {
33 for (size_t i = 0; i < 16; i++) {
34 val_[i] = 0;
35 }
36 }
37 #define DEFINE_SIMD_TYPE_SPECIFIC_METHODS(cType, sType, name, size) \
38 explicit Simd128(sType val) { \
39 WriteUnalignedValue<sType>(reinterpret_cast<Address>(val_), val); \
40 } \
41 sType to_##name() { \
42 return ReadUnalignedValue<sType>(reinterpret_cast<Address>(val_)); \
43 }
44 FOREACH_SIMD_TYPE(DEFINE_SIMD_TYPE_SPECIFIC_METHODS)
45 #undef DEFINE_SIMD_TYPE_SPECIFIC_METHODS
46
47 private:
48 uint8_t val_[16];
49 };
50
51 // Macro for defining WasmValue methods for different types.
52 // Elements:
53 // - name (for to_<name>() method)
54 // - wasm type
55 // - c type
56 #define FOREACH_WASMVAL_TYPE(V) \
57 V(i32, kWasmI32, int32_t) \
58 V(u32, kWasmI32, uint32_t) \
59 V(i64, kWasmI64, int64_t) \
60 V(u64, kWasmI64, uint64_t) \
61 V(f32, kWasmF32, float) \
62 V(f32_boxed, kWasmF32, Float32) \
63 V(f64, kWasmF64, double) \
64 V(f64_boxed, kWasmF64, Float64) \
65 V(s128, kWasmS128, Simd128)
66
67 // A wasm value with type information.
68 class WasmValue {
69 public:
WasmValue()70 WasmValue() : type_(kWasmStmt), bit_pattern_{} {}
71
72 #define DEFINE_TYPE_SPECIFIC_METHODS(name, localtype, ctype) \
73 explicit WasmValue(ctype v) : type_(localtype), bit_pattern_{} { \
74 static_assert(sizeof(ctype) <= sizeof(bit_pattern_), \
75 "size too big for WasmValue"); \
76 WriteUnalignedValue<ctype>(reinterpret_cast<Address>(bit_pattern_), v); \
77 } \
78 ctype to_##name() const { \
79 DCHECK_EQ(localtype, type_); \
80 return to_##name##_unchecked(); \
81 } \
82 ctype to_##name##_unchecked() const { \
83 return ReadUnalignedValue<ctype>(reinterpret_cast<Address>(bit_pattern_)); \
84 }
FOREACH_WASMVAL_TYPE(DEFINE_TYPE_SPECIFIC_METHODS)85 FOREACH_WASMVAL_TYPE(DEFINE_TYPE_SPECIFIC_METHODS)
86 #undef DEFINE_TYPE_SPECIFIC_METHODS
87
88 ValueType type() const { return type_; }
89
90 // Checks equality of type and bit pattern (also for float and double values).
91 bool operator==(const WasmValue& other) const {
92 return type_ == other.type_ &&
93 !memcmp(bit_pattern_, other.bit_pattern_, 16);
94 }
95
96 template <typename T>
97 inline T to() const;
98
99 template <typename T>
100 inline T to_unchecked() const;
101
102 private:
103 ValueType type_;
104 uint8_t bit_pattern_[16];
105 };
106
107 #define DECLARE_CAST(name, localtype, ctype, ...) \
108 template <> \
109 inline ctype WasmValue::to_unchecked() const { \
110 return to_##name##_unchecked(); \
111 } \
112 template <> \
113 inline ctype WasmValue::to() const { \
114 return to_##name(); \
115 }
116 FOREACH_WASMVAL_TYPE(DECLARE_CAST)
117 #undef DECLARE_CAST
118
119 } // namespace wasm
120 } // namespace internal
121 } // namespace v8
122
123 #endif // V8_WASM_WASM_VALUE_H_
124