5#ifndef V8_COMPILER_TURBOSHAFT_TYPES_H_
6#define V8_COMPILER_TURBOSHAFT_TYPES_H_
24#define TURBOSHAFT_TRACE_TYPING(...) \
26 if (V8_UNLIKELY(v8_flags.turboshaft_trace_typing)) { \
27 PrintF(__VA_ARGS__); \
31#define TURBOSHAFT_TRACE_TYPING_WITH_COLOR(colorcode, str, ...) \
32 TURBOSHAFT_TRACE_TYPING( \
33 (v8_flags.log_colour ? ("\033[" colorcode "m" str "\033[m") : str), \
35#define TURBOSHAFT_TRACE_TYPING_OK(str, ...) \
36 TURBOSHAFT_TRACE_TYPING_WITH_COLOR("32", str, __VA_ARGS__)
37#define TURBOSHAFT_TRACE_TYPING_FAIL(str, ...) \
38 TURBOSHAFT_TRACE_TYPING_WITH_COLOR("31", str, __VA_ARGS__)
40#define TURBOSHAFT_TRACE_TYPING(...) ((void)0)
41#define TURBOSHAFT_TRACE_TYPING_WITH_COLOR(colorcode, str, ...) ((void)0)
42#define TURBOSHAFT_TRACE_TYPING_OK(str, ...) ((void)0)
43#define TURBOSHAFT_TRACE_TYPING_FAIL(str, ...) ((void)0)
56 if (std::size(container) <= 1)
return true;
57 auto cur = std::begin(container);
59 for (++next; next != std::end(container); ++cur, ++next) {
60 if (!(*cur < *next))
return false;
82 std::numeric_limits<float_type>::quiet_NaN();
89 std::numeric_limits<float_type>::quiet_NaN();
124 requires std::is_floating_point<T>::value
127 DCHECK_LT(-std::numeric_limits<T>::infinity(), v);
128 return std::nextafter(v, -std::numeric_limits<T>::infinity());
133 requires std::is_floating_point<T>::value
136 DCHECK_LT(v, std::numeric_limits<T>::infinity());
137 return std::nextafter(v, std::numeric_limits<T>::infinity());
142 requires std::is_integral<T>::value
144 DCHECK_LT(std::numeric_limits<T>::min(), v);
150 requires std::is_integral<T>::value
152 DCHECK_LT(v, std::numeric_limits<T>::max());
156template <
size_t Bits>
158template <
size_t Bits>
160template <
size_t Bits>
163template <
size_t Bits>
165template <
size_t Bits>
219 static_assert(
B == 32 ||
B == 64);
220 if constexpr (
B == 32)
227 static_assert(
B == 32 ||
B == 64);
228 if constexpr (
B == 32)
242 static_assert(
B == 32 ||
B == 64);
243 if constexpr (
B == 32)
250 static_assert(
B == 32 ||
B == 64);
251 if constexpr (
B == 32)
258 bool Equals(
const Type& other)
const;
259 bool IsSubtypeOf(
const Type& other)
const;
262 void PrintTo(std::ostream& stream)
const;
265 std::stringstream stream;
272 static std::optional<Type> ParseFromString(
const std::string_view& str,
277 template <
typename Payload>
279 uint8_t reserved,
const Payload& payload)
284 bitfield_(bitfield) {
285 static_assert(
sizeof(Payload) <=
sizeof(payload_));
286 memcpy(&payload_[0], &payload,
sizeof(Payload));
287 if constexpr (
sizeof(Payload) <
sizeof(payload_)) {
288 memset(
reinterpret_cast<uint8_t*
>(&payload_[0]) +
sizeof(Payload), 0x00,
289 sizeof(payload_) -
sizeof(Payload));
293 template <
typename Payload>
295 static_assert(
sizeof(Payload) <=
sizeof(payload_));
296 return *
reinterpret_cast<const Payload*
>(&payload_[0]);
313 uint64_t payload_[2];
320static_assert(
sizeof(
Type) == 24);
322template <
size_t Bits>
324 static_assert(Bits == 32 || Bits == 64);
340 return Range(0, std::numeric_limits<word_t>::max(),
nullptr);
351 return Set(elements, zone);
355 if ((std::numeric_limits<word_t>::max() - from + to) <=
kMaxSetSize - 2) {
358 for (
word_t i = from; i < std::numeric_limits<word_t>::max(); ++
i) {
361 elements.
push_back(std::numeric_limits<word_t>::max());
365 return Set(elements, zone);
378 static WordType Set(
const std::initializer_list<word_t>& elements,
397#if defined(__GNUC__) && !defined(__clang__)
405 for (
size_t i = 0;
i < elements.
size(); ++
i) p.
array[
i] = elements[
i];
430 std::pair<word_t, word_t>
range()
const {
490 void PrintTo(std::ostream& stream)
const;
500 template <
typename Payload>
508template <
size_t Bits>
510 static_assert(Bits == 32 || Bits == 64);
512 static constexpr int kMaxInlineSetSize = 2;
521 static constexpr int kMaxSetSize = 8;
526 kNoSpecialValues = 0x0,
534 return FloatType{SubKind::kOnlySpecialValues, 0, special_values,
538 return FloatType{SubKind::kOnlySpecialValues, 0, Special::kNaN,
542 return FloatType{SubKind::kOnlySpecialValues, 0, Special::kMinusZero,
546 Special::kMinusZero) {
548 std::numeric_limits<float_t>::infinity(),
549 special_values,
nullptr);
552 return Range(min, max, Special::kNoSpecialValues, zone);
556 special_values |= IdentifyMinusZero(min);
557 special_values |= IdentifyMinusZero(max);
561 if (min == max)
return Set({min}, special_values, zone);
562 return FloatType{SubKind::kRange, 0, special_values,
568 return Set(elements, Special::kNoSpecialValues, zone);
572 uint32_t special_values,
Zone* zone) {
576 uint32_t special_values,
Zone* zone) {
580 return Set(elements, Special::kNoSpecialValues, zone);
583 uint32_t special_values,
Zone* zone) {
587 uint32_t special_values,
Zone* zone) {
595 if (elements.
size() <= kMaxInlineSetSize) {
600 special_values |= IdentifyMinusZero(p.
elements[0]);
601 if (elements.
size() > 1) {
603 special_values |= IdentifyMinusZero(p.
elements[1]);
605 return FloatType{SubKind::kSet,
static_cast<uint8_t
>(elements.
size()),
612 for (
size_t i = 0;
i < elements.
size(); ++
i) {
614 special_values |= IdentifyMinusZero(p.
array[
i]);
616 return FloatType{SubKind::kSet,
static_cast<uint8_t
>(elements.
size()),
621 return Set({constant}, 0,
nullptr);
626 return sub_kind() == SubKind::kOnlySpecialValues;
629 return is_only_special_values() && (special_values() == Special::kNaN);
632 return is_only_special_values() &&
633 (special_values() == Special::kMinusZero);
635 bool is_range()
const {
return sub_kind() == SubKind::kRange; }
636 bool is_set()
const {
return sub_kind() == SubKind::kSet; }
639 range_min() == -std::numeric_limits<float_t>::infinity() &&
640 range_max() == std::numeric_limits<float_t>::infinity();
644 return set_size_ == 1 && !has_special_values();
648 bool has_nan()
const {
return (special_values() & Special::kNaN) != 0; }
650 return (special_values() & Special::kMinusZero) != 0;
656 return get_payload<Payload_Range>().min;
660 return get_payload<Payload_Range>().max;
662 std::pair<float_t, float_t>
range()
const {
664 return {range_min(), range_max()};
668 return static_cast<int>(set_size_);
674 return set_elements()[
index];
678 if (set_size() <= kMaxInlineSetSize) {
680 get_payload<Payload_InlineSet>().elements, set_size());
683 get_payload<Payload_OutlineSet>().array, set_size());
687 switch (sub_kind()) {
688 case SubKind::kOnlySpecialValues:
689 if (has_minus_zero())
return float_t{-0.0};
692 case SubKind::kRange:
693 if (has_minus_zero())
return std::min(
float_t{-0.0}, range_min());
696 if (has_minus_zero())
return std::min(
float_t{-0.0}, set_element(0));
697 return set_element(0);
701 switch (sub_kind()) {
702 case SubKind::kOnlySpecialValues:
703 if (has_minus_zero())
return float_t{-0.0};
706 case SubKind::kRange:
707 if (has_minus_zero())
return std::max(
float_t{-0.0}, range_max());
710 if (has_minus_zero()) {
711 return std::max(
float_t{-0.0}, set_element(set_size() - 1));
713 return set_element(set_size() - 1);
716 std::pair<float_t, float_t>
minmax()
const {
return {min(), max()}; }
718 if (!is_constant())
return std::nullopt;
721 return set_element(0);
724 if (
V8_UNLIKELY(std::isnan(value)))
return is_only_nan();
726 if (
auto c = try_get_constant())
return *c ==
value;
732 switch (sub_kind()) {
733 case SubKind::kOnlySpecialValues:
735 case SubKind::kRange:
738 return set_element(0);
744 switch (sub_kind()) {
745 case SubKind::kOnlySpecialValues:
747 case SubKind::kRange:
750 return set_element(set_size() - 1);
754 return {range_or_set_min(), range_or_set_max()};
758 bool Contains(float_t value)
const;
759 bool Equals(
const FloatType& other)
const;
760 bool IsSubtypeOf(
const FloatType& other)
const;
764 void PrintTo(std::ostream& stream)
const;
774 return Special::kMinusZero;
776 return Special::kNoSpecialValues;
779 uint32_t special_values) {
780 if (special_values == 0 && t.is_only_special_values()) {
789 static constexpr Kind KIND = Bits == 32 ? Kind::kFloat32 : Kind::kFloat64;
796 template <
typename Payload>
798 const Payload& payload)
799 :
Type(
KIND, static_cast<uint8_t>(sub_kind), set_size, special_values, 0,
801 DCHECK_EQ(special_values & ~(Special::kNaN | Special::kMinusZero), 0);
810 static constexpr int kMaxTupleSize = std::numeric_limits<uint8_t>::max();
818 p.
array[0] = element0;
819 p.
array[1] = element1;
828 for (
size_t i = 0;
i < elements.
size(); ++
i) {
835 int size()
const {
return static_cast<int>(set_size_); }
839 return get_payload<Payload>().array[
index];
842 return {get_payload<Payload>().array,
static_cast<size_t>(
size())};
846 bool Equals(
const TupleType& other)
const;
847 bool IsSubtypeOf(
const TupleType& other)
const;
850 void PrintTo(std::ostream& stream)
const;
857 :
Type(
KIND, 0, tuple_size, 0, 0, payload) {}
882 return *
static_cast<const TupleType*
>(
this);
888 return stream <<
"Invalid";
890 return stream <<
"None";
892 return stream <<
"Word32";
894 return stream <<
"Word64";
896 return stream <<
"Float32";
898 return stream <<
"Float64";
900 return stream <<
"Tuple";
902 return stream <<
"Any";
907 type.PrintTo(stream);
constexpr size_t size() const
T * AllocateArray(size_t length)
bool has_special_values() const
float_type< Bits > float_t
FloatType(SubKind sub_kind, uint8_t set_size, uint32_t special_values, const Payload &payload)
static FloatType Any(uint32_t special_values=Special::kNaN|Special::kMinusZero)
static FloatType Set(base::Vector< const float_t > elements, uint32_t special_values, Zone *zone)
static FloatType Set(const std::vector< float_t > &elements, uint32_t special_values, Zone *zone)
float_t set_element(int index) const
float_t range_or_set_max() const
static FloatType Set(const std::initializer_list< float_t > &elements, uint32_t special_values, Zone *zone)
bool has_minus_zero() const
static FloatType Set(const base::SmallVector< float_t, N > &elements, uint32_t special_values, Zone *zone)
static uint32_t IdentifyMinusZero(float_t &value)
float_t range_max() const
static FloatType OnlySpecialValues(uint32_t special_values)
bool is_constant(float_t value) const
std::pair< float_t, float_t > range() const
static FloatType Range(float_t min, float_t max, Zone *zone)
base::Vector< const float_t > set_elements() const
std::pair< float_t, float_t > minmax() const
std::pair< float_t, float_t > range_or_set_minmax() const
static FloatType Range(float_t min, float_t max, uint32_t special_values, Zone *zone)
static FloatType Constant(float_t constant)
static Type ReplacedSpecialValues(const FloatType &t, uint32_t special_values)
static FloatType Set(const base::SmallVector< const float_t, N > &elements, Zone *zone)
bool is_only_special_values() const
static FloatType Set(const std::vector< float_t > &elements, Zone *zone)
bool is_only_minus_zero() const
float_t range_min() const
float_t range_or_set_min() const
uint32_t special_values() const
std::optional< float_t > try_get_constant() const
static FloatType MinusZero()
static TupleType Tuple(const Type &element0, const Type &element1, Zone *zone)
static TupleType Tuple(base::Vector< Type > elements, Zone *zone)
TupleType(uint8_t tuple_size, const Payload &payload)
base::Vector< Type > elements() const
const Type & element(int index) const
const auto & AsWord() const
bool Equals(const Type &other) const
const TupleType & AsTuple() const
const Word32Type & AsWord32() const
const Payload & get_payload() const
const Float32Type & AsFloat32() const
const auto & AsFloat() const
Type(Kind kind, uint8_t sub_kind, uint8_t set_size, uint32_t bitfield, uint8_t reserved, const Payload &payload)
std::string ToString() const
const Word64Type & AsWord64() const
const Float64Type & AsFloat64() const
static constexpr int kMaxInlineSetSize
Handle< TurboshaftType > AllocateOnHeap(Factory *factory) const
void PrintTo(std::ostream &stream) const
static WordType Set(const std::vector< word_t > &elements, Zone *zone)
bool Equals(const WordType &other) const
static WordType Set(base::Vector< const word_t > elements, Zone *zone)
WordType(SubKind sub_kind, uint8_t set_size, const Payload &payload)
static WordType LeastUpperBound(const WordType &lhs, const WordType &rhs, Zone *zone)
word_t unsigned_min() const
bool is_constant(word_t value) const
bool Contains(word_t value) const
bool IsSubtypeOf(const WordType &other) const
word_t set_element(int index) const
static WordType Set(const std::initializer_list< word_t > &elements, Zone *zone)
std::optional< word_t > try_get_constant() const
word_t range_from() const
static constexpr int kMaxSetSize
base::Vector< const word_t > set_elements() const
static Type Intersect(const WordType &lhs, const WordType &rhs, ResolutionMode resolution_mode, Zone *zone)
static WordType Constant(word_t constant)
std::pair< word_t, word_t > range() const
static constexpr Kind KIND
static WordType Range(word_t from, word_t to, Zone *zone)
static WordType Set(const base::SmallVector< word_t, N > &elements, Zone *zone)
word_t unsigned_max() const
#define EXPORT_TEMPLATE_DECLARE(export)
ZoneVector< RpoNumber > & result
bool none_of(const C &container, const P &predicate)
constexpr Vector< T > VectorOf(T *start, size_t size)
bool is_minus_zero(T value)
bool is_float_special_value(T value)
bool is_unique_and_sorted(const T &container)
std::ostream & operator<<(std::ostream &os, PaddingSpace padding)
bool operator==(const ControlState &lhs, const ControlState &rhs)
typename detail::TypeForBits< Bits >::uint_type uint_type
constexpr float_type< Bits > nan_v
Range(V< T >, V< T >, V< T >) -> Range< T >
typename detail::TypeForBits< Bits >::float_type float_type
bool operator!=(const ControlState &lhs, const ControlState &rhs)
std::make_unsigned_t< Tagged_t > word_t
static bool IsMinusZero(double value)
#define DCHECK_LE(v1, v2)
#define DCHECK_NOT_NULL(val)
#define DCHECK_IMPLIES(v1, v2)
#define DCHECK_NE(v1, v2)
#define DCHECK_GE(v1, v2)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define DCHECK_EQ(v1, v2)
#define DCHECK_GT(v1, v2)
#define V8_EXPORT_PRIVATE
size_t operator()(const Type &v) const
#define V8_UNLIKELY(condition)