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