// Copyright 2017 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_WASM_WASM_VALUE_H_ #define V8_WASM_WASM_VALUE_H_ #include "src/boxed-float.h" #include "src/handles.h" #include "src/v8memory.h" #include "src/wasm/wasm-opcodes.h" #include "src/zone/zone-containers.h" namespace v8 { namespace internal { namespace wasm { #define FOREACH_SIMD_TYPE(V) \ V(float, float4, f32x4, 4) \ V(int32_t, int4, i32x4, 4) \ V(int16_t, int8, i16x8, 8) \ V(int8_t, int16, i8x16, 16) #define DEFINE_SIMD_TYPE(cType, sType, name, kSize) \ struct sType { \ cType val[kSize]; \ }; FOREACH_SIMD_TYPE(DEFINE_SIMD_TYPE) #undef DEFINE_SIMD_TYPE class Simd128 { public: Simd128() : val_() { for (size_t i = 0; i < 16; i++) { val_[i] = 0; } } #define DEFINE_SIMD_TYPE_SPECIFIC_METHODS(cType, sType, name, size) \ explicit Simd128(sType val) { \ WriteUnalignedValue<sType>(reinterpret_cast<Address>(val_), val); \ } \ sType to_##name() { \ return ReadUnalignedValue<sType>(reinterpret_cast<Address>(val_)); \ } FOREACH_SIMD_TYPE(DEFINE_SIMD_TYPE_SPECIFIC_METHODS) #undef DEFINE_SIMD_TYPE_SPECIFIC_METHODS private: uint8_t val_[16]; }; // Macro for defining WasmValue methods for different types. // Elements: // - name (for to_<name>() method) // - wasm type // - c type #define FOREACH_WASMVAL_TYPE(V) \ V(i32, kWasmI32, int32_t) \ V(u32, kWasmI32, uint32_t) \ V(i64, kWasmI64, int64_t) \ V(u64, kWasmI64, uint64_t) \ V(f32, kWasmF32, float) \ V(f32_boxed, kWasmF32, Float32) \ V(f64, kWasmF64, double) \ V(f64_boxed, kWasmF64, Float64) \ V(s128, kWasmS128, Simd128) \ V(anyref, kWasmAnyRef, Handle<Object>) ASSERT_TRIVIALLY_COPYABLE(Handle<Object>); // A wasm value with type information. class WasmValue { public: WasmValue() : type_(kWasmStmt), bit_pattern_{} {} #define DEFINE_TYPE_SPECIFIC_METHODS(name, localtype, ctype) \ explicit WasmValue(ctype v) : type_(localtype), bit_pattern_{} { \ static_assert(sizeof(ctype) <= sizeof(bit_pattern_), \ "size too big for WasmValue"); \ WriteUnalignedValue<ctype>(reinterpret_cast<Address>(bit_pattern_), v); \ } \ ctype to_##name() const { \ DCHECK_EQ(localtype, type_); \ return to_##name##_unchecked(); \ } \ ctype to_##name##_unchecked() const { \ return ReadUnalignedValue<ctype>(reinterpret_cast<Address>(bit_pattern_)); \ } FOREACH_WASMVAL_TYPE(DEFINE_TYPE_SPECIFIC_METHODS) #undef DEFINE_TYPE_SPECIFIC_METHODS ValueType type() const { return type_; } // Checks equality of type and bit pattern (also for float and double values). bool operator==(const WasmValue& other) const { return type_ == other.type_ && !memcmp(bit_pattern_, other.bit_pattern_, 16); } template <typename T> inline T to() const; template <typename T> inline T to_unchecked() const; private: ValueType type_; uint8_t bit_pattern_[16]; }; #define DECLARE_CAST(name, localtype, ctype, ...) \ template <> \ inline ctype WasmValue::to_unchecked() const { \ return to_##name##_unchecked(); \ } \ template <> \ inline ctype WasmValue::to() const { \ return to_##name(); \ } FOREACH_WASMVAL_TYPE(DECLARE_CAST) #undef DECLARE_CAST } // namespace wasm } // namespace internal } // namespace v8 #endif // V8_WASM_WASM_VALUE_H_