1 // Copyright 2022 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_NUMBERS_INTEGER_LITERAL_H_ 6 #define V8_NUMBERS_INTEGER_LITERAL_H_ 7 8 #include "src/base/optional.h" 9 #include "src/common/globals.h" 10 11 namespace v8 { 12 namespace internal { 13 14 class IntegerLiteral { 15 public: IntegerLiteral(bool negative,uint64_t absolute_value)16 IntegerLiteral(bool negative, uint64_t absolute_value) 17 : negative_(negative), absolute_value_(absolute_value) { 18 if (absolute_value == 0) negative_ = false; 19 } 20 21 template <typename T> IntegerLiteral(T value)22 explicit IntegerLiteral(T value) : IntegerLiteral(value, true) {} 23 is_negative()24 bool is_negative() const { return negative_; } absolute_value()25 uint64_t absolute_value() const { return absolute_value_; } 26 27 template <typename T> IsRepresentableAs()28 bool IsRepresentableAs() const { 29 static_assert(std::is_integral<T>::value, "Integral type required"); 30 static_assert(sizeof(T) <= sizeof(uint64_t), 31 "Types with more than 64 bits are not supported"); 32 return Compare(IntegerLiteral(std::numeric_limits<T>::min(), false)) >= 0 && 33 Compare(IntegerLiteral(std::numeric_limits<T>::max(), false)) <= 0; 34 } 35 36 template <typename T> To()37 T To() const { 38 static_assert(std::is_integral<T>::value, "Integral type required"); 39 DCHECK(IsRepresentableAs<T>()); 40 uint64_t v = absolute_value_; 41 if (negative_) v = ~v + 1; 42 return static_cast<T>(v); 43 } 44 45 template <typename T> TryTo()46 base::Optional<T> TryTo() const { 47 static_assert(std::is_integral<T>::value, "Integral type required"); 48 if (!IsRepresentableAs<T>()) return base::nullopt; 49 return To<T>(); 50 } 51 Compare(const IntegerLiteral & other)52 int Compare(const IntegerLiteral& other) const { 53 if (absolute_value_ == other.absolute_value_) { 54 if (absolute_value_ == 0 || negative_ == other.negative_) return 0; 55 return negative_ ? -1 : 1; 56 } else if (absolute_value_ < other.absolute_value_) { 57 return other.negative_ ? 1 : -1; 58 } else { 59 return negative_ ? -1 : 1; 60 } 61 } 62 63 std::string ToString() const; 64 65 private: 66 template <typename T> IntegerLiteral(T value,bool perform_dcheck)67 explicit IntegerLiteral(T value, bool perform_dcheck) : negative_(false) { 68 static_assert(std::is_integral<T>::value, "Integral type required"); 69 absolute_value_ = static_cast<uint64_t>(value); 70 if (value < T(0)) { 71 negative_ = true; 72 absolute_value_ = ~absolute_value_ + 1; 73 } 74 if (perform_dcheck) DCHECK_EQ(To<T>(), value); 75 } 76 77 bool negative_; 78 uint64_t absolute_value_; 79 }; 80 81 inline bool operator==(const IntegerLiteral& x, const IntegerLiteral& y) { 82 return x.Compare(y) == 0; 83 } 84 85 inline bool operator!=(const IntegerLiteral& x, const IntegerLiteral& y) { 86 return x.Compare(y) != 0; 87 } 88 89 inline std::ostream& operator<<(std::ostream& stream, 90 const IntegerLiteral& literal) { 91 return stream << literal.ToString(); 92 } 93 94 inline IntegerLiteral operator|(const IntegerLiteral& x, 95 const IntegerLiteral& y) { 96 DCHECK(!x.is_negative()); 97 DCHECK(!y.is_negative()); 98 return IntegerLiteral(false, x.absolute_value() | y.absolute_value()); 99 } 100 101 IntegerLiteral operator<<(const IntegerLiteral& x, const IntegerLiteral& y); 102 IntegerLiteral operator+(const IntegerLiteral& x, const IntegerLiteral& y); 103 104 } // namespace internal 105 } // namespace v8 106 #endif // V8_NUMBERS_INTEGER_LITERAL_H_ 107