11cb0ef41Sopenharmony_ci// Copyright 2017 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#if !V8_ENABLE_WEBASSEMBLY 61cb0ef41Sopenharmony_ci#error This header should only be included if WebAssembly is enabled. 71cb0ef41Sopenharmony_ci#endif // !V8_ENABLE_WEBASSEMBLY 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ci#ifndef V8_WASM_WASM_VALUE_H_ 101cb0ef41Sopenharmony_ci#define V8_WASM_WASM_VALUE_H_ 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ci#include "src/base/memory.h" 131cb0ef41Sopenharmony_ci#include "src/handles/handles.h" 141cb0ef41Sopenharmony_ci#include "src/utils/boxed-float.h" 151cb0ef41Sopenharmony_ci#include "src/wasm/value-type.h" 161cb0ef41Sopenharmony_ci#include "src/zone/zone-containers.h" 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_cinamespace v8 { 191cb0ef41Sopenharmony_cinamespace internal { 201cb0ef41Sopenharmony_cinamespace wasm { 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci#define FOREACH_SIMD_TYPE(V) \ 231cb0ef41Sopenharmony_ci V(double, float2, f64x2, 2) \ 241cb0ef41Sopenharmony_ci V(float, float4, f32x4, 4) \ 251cb0ef41Sopenharmony_ci V(int64_t, int2, i64x2, 2) \ 261cb0ef41Sopenharmony_ci V(int32_t, int4, i32x4, 4) \ 271cb0ef41Sopenharmony_ci V(int16_t, int8, i16x8, 8) \ 281cb0ef41Sopenharmony_ci V(int8_t, int16, i8x16, 16) 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ci#define DEFINE_SIMD_TYPE(cType, sType, name, kSize) \ 311cb0ef41Sopenharmony_ci struct sType { \ 321cb0ef41Sopenharmony_ci cType val[kSize]; \ 331cb0ef41Sopenharmony_ci }; 341cb0ef41Sopenharmony_ciFOREACH_SIMD_TYPE(DEFINE_SIMD_TYPE) 351cb0ef41Sopenharmony_ci#undef DEFINE_SIMD_TYPE 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_ciclass Simd128 { 381cb0ef41Sopenharmony_ci public: 391cb0ef41Sopenharmony_ci Simd128() = default; 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ci#define DEFINE_SIMD_TYPE_SPECIFIC_METHODS(cType, sType, name, size) \ 421cb0ef41Sopenharmony_ci explicit Simd128(sType val) { \ 431cb0ef41Sopenharmony_ci base::WriteUnalignedValue<sType>(reinterpret_cast<Address>(val_), val); \ 441cb0ef41Sopenharmony_ci } \ 451cb0ef41Sopenharmony_ci sType to_##name() const { \ 461cb0ef41Sopenharmony_ci return base::ReadUnalignedValue<sType>(reinterpret_cast<Address>(val_)); \ 471cb0ef41Sopenharmony_ci } 481cb0ef41Sopenharmony_ci FOREACH_SIMD_TYPE(DEFINE_SIMD_TYPE_SPECIFIC_METHODS) 491cb0ef41Sopenharmony_ci#undef DEFINE_SIMD_TYPE_SPECIFIC_METHODS 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_ci explicit Simd128(byte* bytes) { 521cb0ef41Sopenharmony_ci memcpy(static_cast<void*>(val_), reinterpret_cast<void*>(bytes), 531cb0ef41Sopenharmony_ci kSimd128Size); 541cb0ef41Sopenharmony_ci } 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci const uint8_t* bytes() { return val_; } 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_ci template <typename T> 591cb0ef41Sopenharmony_ci inline T to() const; 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci private: 621cb0ef41Sopenharmony_ci uint8_t val_[16] = {0}; 631cb0ef41Sopenharmony_ci}; 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci#define DECLARE_CAST(cType, sType, name, size) \ 661cb0ef41Sopenharmony_ci template <> \ 671cb0ef41Sopenharmony_ci inline sType Simd128::to() const { \ 681cb0ef41Sopenharmony_ci return to_##name(); \ 691cb0ef41Sopenharmony_ci } 701cb0ef41Sopenharmony_ciFOREACH_SIMD_TYPE(DECLARE_CAST) 711cb0ef41Sopenharmony_ci#undef DECLARE_CAST 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci// Macro for defining WasmValue methods for different types. 741cb0ef41Sopenharmony_ci// Elements: 751cb0ef41Sopenharmony_ci// - name (for to_<name>() method) 761cb0ef41Sopenharmony_ci// - wasm type 771cb0ef41Sopenharmony_ci// - c type 781cb0ef41Sopenharmony_ci#define FOREACH_PRIMITIVE_WASMVAL_TYPE(V) \ 791cb0ef41Sopenharmony_ci V(i8, kWasmI8, int8_t) \ 801cb0ef41Sopenharmony_ci V(i16, kWasmI16, int16_t) \ 811cb0ef41Sopenharmony_ci V(i32, kWasmI32, int32_t) \ 821cb0ef41Sopenharmony_ci V(u32, kWasmI32, uint32_t) \ 831cb0ef41Sopenharmony_ci V(i64, kWasmI64, int64_t) \ 841cb0ef41Sopenharmony_ci V(u64, kWasmI64, uint64_t) \ 851cb0ef41Sopenharmony_ci V(f32, kWasmF32, float) \ 861cb0ef41Sopenharmony_ci V(f32_boxed, kWasmF32, Float32) \ 871cb0ef41Sopenharmony_ci V(f64, kWasmF64, double) \ 881cb0ef41Sopenharmony_ci V(f64_boxed, kWasmF64, Float64) \ 891cb0ef41Sopenharmony_ci V(s128, kWasmS128, Simd128) 901cb0ef41Sopenharmony_ci 911cb0ef41Sopenharmony_ciASSERT_TRIVIALLY_COPYABLE(Handle<Object>); 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci// A wasm value with type information. 941cb0ef41Sopenharmony_ciclass WasmValue { 951cb0ef41Sopenharmony_ci public: 961cb0ef41Sopenharmony_ci WasmValue() : type_(kWasmVoid), bit_pattern_{} {} 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci#define DEFINE_TYPE_SPECIFIC_METHODS(name, localtype, ctype) \ 991cb0ef41Sopenharmony_ci explicit WasmValue(ctype v) : type_(localtype), bit_pattern_{} { \ 1001cb0ef41Sopenharmony_ci static_assert(sizeof(ctype) <= sizeof(bit_pattern_), \ 1011cb0ef41Sopenharmony_ci "size too big for WasmValue"); \ 1021cb0ef41Sopenharmony_ci base::WriteUnalignedValue<ctype>(reinterpret_cast<Address>(bit_pattern_), \ 1031cb0ef41Sopenharmony_ci v); \ 1041cb0ef41Sopenharmony_ci } \ 1051cb0ef41Sopenharmony_ci ctype to_##name() const { \ 1061cb0ef41Sopenharmony_ci DCHECK_EQ(localtype, type_); \ 1071cb0ef41Sopenharmony_ci return to_##name##_unchecked(); \ 1081cb0ef41Sopenharmony_ci } \ 1091cb0ef41Sopenharmony_ci ctype to_##name##_unchecked() const { \ 1101cb0ef41Sopenharmony_ci return base::ReadUnalignedValue<ctype>( \ 1111cb0ef41Sopenharmony_ci reinterpret_cast<Address>(bit_pattern_)); \ 1121cb0ef41Sopenharmony_ci } 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_ci FOREACH_PRIMITIVE_WASMVAL_TYPE(DEFINE_TYPE_SPECIFIC_METHODS) 1151cb0ef41Sopenharmony_ci#undef DEFINE_TYPE_SPECIFIC_METHODS 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ci WasmValue(byte* raw_bytes, ValueType type) : type_(type), bit_pattern_{} { 1181cb0ef41Sopenharmony_ci DCHECK(type_.is_numeric()); 1191cb0ef41Sopenharmony_ci memcpy(bit_pattern_, raw_bytes, type.value_kind_size()); 1201cb0ef41Sopenharmony_ci } 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_ci WasmValue(Handle<Object> ref, ValueType type) : type_(type), bit_pattern_{} { 1231cb0ef41Sopenharmony_ci static_assert(sizeof(Handle<Object>) <= sizeof(bit_pattern_), 1241cb0ef41Sopenharmony_ci "bit_pattern_ must be large enough to fit a Handle"); 1251cb0ef41Sopenharmony_ci DCHECK(type.is_reference()); 1261cb0ef41Sopenharmony_ci base::WriteUnalignedValue<Handle<Object>>( 1271cb0ef41Sopenharmony_ci reinterpret_cast<Address>(bit_pattern_), ref); 1281cb0ef41Sopenharmony_ci } 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_ci Handle<Object> to_ref() const { 1311cb0ef41Sopenharmony_ci DCHECK(type_.is_reference()); 1321cb0ef41Sopenharmony_ci return base::ReadUnalignedValue<Handle<Object>>( 1331cb0ef41Sopenharmony_ci reinterpret_cast<Address>(bit_pattern_)); 1341cb0ef41Sopenharmony_ci } 1351cb0ef41Sopenharmony_ci 1361cb0ef41Sopenharmony_ci ValueType type() const { return type_; } 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ci // Checks equality of type and bit pattern (also for float and double values). 1391cb0ef41Sopenharmony_ci bool operator==(const WasmValue& other) const { 1401cb0ef41Sopenharmony_ci return type_ == other.type_ && 1411cb0ef41Sopenharmony_ci !memcmp(bit_pattern_, other.bit_pattern_, 1421cb0ef41Sopenharmony_ci type_.is_reference() ? sizeof(Handle<Object>) 1431cb0ef41Sopenharmony_ci : type_.value_kind_size()); 1441cb0ef41Sopenharmony_ci } 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ci void CopyTo(byte* to) const { 1471cb0ef41Sopenharmony_ci STATIC_ASSERT(sizeof(float) == sizeof(Float32)); 1481cb0ef41Sopenharmony_ci STATIC_ASSERT(sizeof(double) == sizeof(Float64)); 1491cb0ef41Sopenharmony_ci DCHECK(type_.is_numeric()); 1501cb0ef41Sopenharmony_ci memcpy(to, bit_pattern_, type_.value_kind_size()); 1511cb0ef41Sopenharmony_ci } 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_ci // If {packed_type.is_packed()}, create a new value of {packed_type()}. 1541cb0ef41Sopenharmony_ci // Otherwise, return this object. 1551cb0ef41Sopenharmony_ci WasmValue Packed(ValueType packed_type) const { 1561cb0ef41Sopenharmony_ci if (packed_type == kWasmI8) { 1571cb0ef41Sopenharmony_ci DCHECK_EQ(type_, kWasmI32); 1581cb0ef41Sopenharmony_ci return WasmValue(static_cast<int8_t>(to_i32())); 1591cb0ef41Sopenharmony_ci } 1601cb0ef41Sopenharmony_ci if (packed_type == kWasmI16) { 1611cb0ef41Sopenharmony_ci DCHECK_EQ(type_, kWasmI32); 1621cb0ef41Sopenharmony_ci return WasmValue(static_cast<int16_t>(to_i32())); 1631cb0ef41Sopenharmony_ci } 1641cb0ef41Sopenharmony_ci return *this; 1651cb0ef41Sopenharmony_ci } 1661cb0ef41Sopenharmony_ci 1671cb0ef41Sopenharmony_ci template <typename T> 1681cb0ef41Sopenharmony_ci inline T to() const; 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci template <typename T> 1711cb0ef41Sopenharmony_ci inline T to_unchecked() const; 1721cb0ef41Sopenharmony_ci 1731cb0ef41Sopenharmony_ci static WasmValue ForUintPtr(uintptr_t value) { 1741cb0ef41Sopenharmony_ci using type = 1751cb0ef41Sopenharmony_ci std::conditional<kSystemPointerSize == 8, uint64_t, uint32_t>::type; 1761cb0ef41Sopenharmony_ci return WasmValue{type{value}}; 1771cb0ef41Sopenharmony_ci } 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_ci inline std::string to_string() const { 1801cb0ef41Sopenharmony_ci switch (type_.kind()) { 1811cb0ef41Sopenharmony_ci case kI8: 1821cb0ef41Sopenharmony_ci return std::to_string(to_i8()); 1831cb0ef41Sopenharmony_ci case kI16: 1841cb0ef41Sopenharmony_ci return std::to_string(to_i16()); 1851cb0ef41Sopenharmony_ci case kI32: 1861cb0ef41Sopenharmony_ci return std::to_string(to_i32()); 1871cb0ef41Sopenharmony_ci case kI64: 1881cb0ef41Sopenharmony_ci return std::to_string(to_i64()); 1891cb0ef41Sopenharmony_ci case kF32: 1901cb0ef41Sopenharmony_ci return std::to_string(to_f32()); 1911cb0ef41Sopenharmony_ci case kF64: 1921cb0ef41Sopenharmony_ci return std::to_string(to_f64()); 1931cb0ef41Sopenharmony_ci case kS128: { 1941cb0ef41Sopenharmony_ci std::stringstream stream; 1951cb0ef41Sopenharmony_ci stream << "0x" << std::hex; 1961cb0ef41Sopenharmony_ci for (int8_t byte : bit_pattern_) { 1971cb0ef41Sopenharmony_ci if (!(byte & 0xf0)) stream << '0'; 1981cb0ef41Sopenharmony_ci stream << byte; 1991cb0ef41Sopenharmony_ci } 2001cb0ef41Sopenharmony_ci return stream.str(); 2011cb0ef41Sopenharmony_ci } 2021cb0ef41Sopenharmony_ci case kOptRef: 2031cb0ef41Sopenharmony_ci case kRef: 2041cb0ef41Sopenharmony_ci case kRtt: 2051cb0ef41Sopenharmony_ci return "Handle [" + std::to_string(to_ref().address()) + "]"; 2061cb0ef41Sopenharmony_ci case kVoid: 2071cb0ef41Sopenharmony_ci case kBottom: 2081cb0ef41Sopenharmony_ci UNREACHABLE(); 2091cb0ef41Sopenharmony_ci } 2101cb0ef41Sopenharmony_ci } 2111cb0ef41Sopenharmony_ci 2121cb0ef41Sopenharmony_ci private: 2131cb0ef41Sopenharmony_ci ValueType type_; 2141cb0ef41Sopenharmony_ci uint8_t bit_pattern_[16]; 2151cb0ef41Sopenharmony_ci}; 2161cb0ef41Sopenharmony_ci 2171cb0ef41Sopenharmony_ci#define DECLARE_CAST(name, localtype, ctype, ...) \ 2181cb0ef41Sopenharmony_ci template <> \ 2191cb0ef41Sopenharmony_ci inline ctype WasmValue::to_unchecked() const { \ 2201cb0ef41Sopenharmony_ci return to_##name##_unchecked(); \ 2211cb0ef41Sopenharmony_ci } \ 2221cb0ef41Sopenharmony_ci template <> \ 2231cb0ef41Sopenharmony_ci inline ctype WasmValue::to() const { \ 2241cb0ef41Sopenharmony_ci return to_##name(); \ 2251cb0ef41Sopenharmony_ci } 2261cb0ef41Sopenharmony_ciFOREACH_PRIMITIVE_WASMVAL_TYPE(DECLARE_CAST) 2271cb0ef41Sopenharmony_ci#undef DECLARE_CAST 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ci} // namespace wasm 2301cb0ef41Sopenharmony_ci} // namespace internal 2311cb0ef41Sopenharmony_ci} // namespace v8 2321cb0ef41Sopenharmony_ci 2331cb0ef41Sopenharmony_ci#endif // V8_WASM_WASM_VALUE_H_ 234