• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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