// Copyright 2022 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_NUMBERS_INTEGER_LITERAL_H_ #define V8_NUMBERS_INTEGER_LITERAL_H_ #include "src/base/optional.h" #include "src/common/globals.h" namespace v8 { namespace internal { class IntegerLiteral { public: IntegerLiteral(bool negative, uint64_t absolute_value) : negative_(negative), absolute_value_(absolute_value) { if (absolute_value == 0) negative_ = false; } template <typename T> explicit IntegerLiteral(T value) : IntegerLiteral(value, true) {} bool is_negative() const { return negative_; } uint64_t absolute_value() const { return absolute_value_; } template <typename T> bool IsRepresentableAs() const { static_assert(std::is_integral<T>::value, "Integral type required"); static_assert(sizeof(T) <= sizeof(uint64_t), "Types with more than 64 bits are not supported"); return Compare(IntegerLiteral(std::numeric_limits<T>::min(), false)) >= 0 && Compare(IntegerLiteral(std::numeric_limits<T>::max(), false)) <= 0; } template <typename T> T To() const { static_assert(std::is_integral<T>::value, "Integral type required"); DCHECK(IsRepresentableAs<T>()); uint64_t v = absolute_value_; if (negative_) v = ~v + 1; return static_cast<T>(v); } template <typename T> base::Optional<T> TryTo() const { static_assert(std::is_integral<T>::value, "Integral type required"); if (!IsRepresentableAs<T>()) return base::nullopt; return To<T>(); } int Compare(const IntegerLiteral& other) const { if (absolute_value_ == other.absolute_value_) { if (absolute_value_ == 0 || negative_ == other.negative_) return 0; return negative_ ? -1 : 1; } else if (absolute_value_ < other.absolute_value_) { return other.negative_ ? 1 : -1; } else { return negative_ ? -1 : 1; } } std::string ToString() const; private: template <typename T> explicit IntegerLiteral(T value, bool perform_dcheck) : negative_(false) { static_assert(std::is_integral<T>::value, "Integral type required"); absolute_value_ = static_cast<uint64_t>(value); if (value < T(0)) { negative_ = true; absolute_value_ = ~absolute_value_ + 1; } if (perform_dcheck) DCHECK_EQ(To<T>(), value); } bool negative_; uint64_t absolute_value_; }; inline bool operator==(const IntegerLiteral& x, const IntegerLiteral& y) { return x.Compare(y) == 0; } inline bool operator!=(const IntegerLiteral& x, const IntegerLiteral& y) { return x.Compare(y) != 0; } inline std::ostream& operator<<(std::ostream& stream, const IntegerLiteral& literal) { return stream << literal.ToString(); } inline IntegerLiteral operator|(const IntegerLiteral& x, const IntegerLiteral& y) { DCHECK(!x.is_negative()); DCHECK(!y.is_negative()); return IntegerLiteral(false, x.absolute_value() | y.absolute_value()); } IntegerLiteral operator<<(const IntegerLiteral& x, const IntegerLiteral& y); IntegerLiteral operator+(const IntegerLiteral& x, const IntegerLiteral& y); } // namespace internal } // namespace v8 #endif // V8_NUMBERS_INTEGER_LITERAL_H_