1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
// 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_
|