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