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