LLVM 19.0.0git
APSInt.h
Go to the documentation of this file.
1//===-- llvm/ADT/APSInt.h - Arbitrary Precision Signed Int -----*- C++ -*--===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file implements the APSInt class, which is a simple class that
11/// represents an arbitrary sized integer that knows its signedness.
12///
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_ADT_APSINT_H
16#define LLVM_ADT_APSINT_H
17
18#include "llvm/ADT/APInt.h"
19
20namespace llvm {
21
22/// An arbitrary precision integer that knows its signedness.
23class [[nodiscard]] APSInt : public APInt {
24 bool IsUnsigned = false;
25
26public:
27 /// Default constructor that creates an uninitialized APInt.
28 explicit APSInt() = default;
29
30 /// Create an APSInt with the specified width, default to unsigned.
31 explicit APSInt(uint32_t BitWidth, bool isUnsigned = true)
32 : APInt(BitWidth, 0), IsUnsigned(isUnsigned) {}
33
34 explicit APSInt(APInt I, bool isUnsigned = true)
35 : APInt(std::move(I)), IsUnsigned(isUnsigned) {}
36
37 /// Construct an APSInt from a string representation.
38 ///
39 /// This constructor interprets the string \p Str using the radix of 10.
40 /// The interpretation stops at the end of the string. The bit width of the
41 /// constructed APSInt is determined automatically.
42 ///
43 /// \param Str the string to be interpreted.
44 explicit APSInt(StringRef Str);
45
46 /// Determine sign of this APSInt.
47 ///
48 /// \returns true if this APSInt is negative, false otherwise
49 bool isNegative() const { return isSigned() && APInt::isNegative(); }
50
51 /// Determine if this APSInt Value is non-negative (>= 0)
52 ///
53 /// \returns true if this APSInt is non-negative, false otherwise
54 bool isNonNegative() const { return !isNegative(); }
55
56 /// Determine if this APSInt Value is positive.
57 ///
58 /// This tests if the value of this APSInt is positive (> 0). Note
59 /// that 0 is not a positive value.
60 ///
61 /// \returns true if this APSInt is positive.
62 bool isStrictlyPositive() const { return isNonNegative() && !isZero(); }
63
65 // Retain our current sign.
66 APInt::operator=(std::move(RHS));
67 return *this;
68 }
69
71 // Retain our current sign.
72 APInt::operator=(RHS);
73 return *this;
74 }
75
76 // Query sign information.
77 bool isSigned() const { return !IsUnsigned; }
78 bool isUnsigned() const { return IsUnsigned; }
79 void setIsUnsigned(bool Val) { IsUnsigned = Val; }
80 void setIsSigned(bool Val) { IsUnsigned = !Val; }
81
82 /// Append this APSInt to the specified SmallString.
83 void toString(SmallVectorImpl<char> &Str, unsigned Radix = 10) const {
84 APInt::toString(Str, Radix, isSigned());
85 }
86 using APInt::toString;
87
88 /// If this int is representable using an int64_t.
90 // For unsigned values with 64 active bits, they technically fit into a
91 // int64_t, but the user may get negative numbers and has to manually cast
92 // them to unsigned. Let's not bet the user has the sanity to do that and
93 // not give them a vague value at the first place.
94 return isSigned() ? isSignedIntN(64) : isIntN(63);
95 }
96
97 /// Get the correctly-extended \c int64_t value.
98 int64_t getExtValue() const {
99 assert(isRepresentableByInt64() && "Too many bits for int64_t");
100 return isSigned() ? getSExtValue() : getZExtValue();
101 }
102
103 std::optional<int64_t> tryExtValue() const {
104 return isRepresentableByInt64() ? std::optional<int64_t>(getExtValue())
105 : std::nullopt;
106 }
107
108 APSInt trunc(uint32_t width) const {
109 return APSInt(APInt::trunc(width), IsUnsigned);
110 }
111
112 APSInt extend(uint32_t width) const {
113 if (IsUnsigned)
114 return APSInt(zext(width), IsUnsigned);
115 else
116 return APSInt(sext(width), IsUnsigned);
117 }
118
120 if (IsUnsigned)
121 return APSInt(zextOrTrunc(width), IsUnsigned);
122 else
123 return APSInt(sextOrTrunc(width), IsUnsigned);
124 }
125
126 const APSInt &operator%=(const APSInt &RHS) {
127 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
128 if (IsUnsigned)
129 *this = urem(RHS);
130 else
131 *this = srem(RHS);
132 return *this;
133 }
134 const APSInt &operator/=(const APSInt &RHS) {
135 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
136 if (IsUnsigned)
137 *this = udiv(RHS);
138 else
139 *this = sdiv(RHS);
140 return *this;
141 }
142 APSInt operator%(const APSInt &RHS) const {
143 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
144 return IsUnsigned ? APSInt(urem(RHS), true) : APSInt(srem(RHS), false);
145 }
146 APSInt operator/(const APSInt &RHS) const {
147 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
148 return IsUnsigned ? APSInt(udiv(RHS), true) : APSInt(sdiv(RHS), false);
149 }
150
151 APSInt operator>>(unsigned Amt) const {
152 return IsUnsigned ? APSInt(lshr(Amt), true) : APSInt(ashr(Amt), false);
153 }
154 APSInt &operator>>=(unsigned Amt) {
155 if (IsUnsigned)
156 lshrInPlace(Amt);
157 else
158 ashrInPlace(Amt);
159 return *this;
160 }
161 APSInt relativeShr(unsigned Amt) const {
162 return IsUnsigned ? APSInt(relativeLShr(Amt), true)
163 : APSInt(relativeAShr(Amt), false);
164 }
165
166 inline bool operator<(const APSInt &RHS) const {
167 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
168 return IsUnsigned ? ult(RHS) : slt(RHS);
169 }
170 inline bool operator>(const APSInt &RHS) const {
171 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
172 return IsUnsigned ? ugt(RHS) : sgt(RHS);
173 }
174 inline bool operator<=(const APSInt &RHS) const {
175 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
176 return IsUnsigned ? ule(RHS) : sle(RHS);
177 }
178 inline bool operator>=(const APSInt &RHS) const {
179 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
180 return IsUnsigned ? uge(RHS) : sge(RHS);
181 }
182 inline bool operator==(const APSInt &RHS) const {
183 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
184 return eq(RHS);
185 }
186 inline bool operator!=(const APSInt &RHS) const { return !((*this) == RHS); }
187
188 bool operator==(int64_t RHS) const {
189 return compareValues(*this, get(RHS)) == 0;
190 }
191 bool operator!=(int64_t RHS) const {
192 return compareValues(*this, get(RHS)) != 0;
193 }
194 bool operator<=(int64_t RHS) const {
195 return compareValues(*this, get(RHS)) <= 0;
196 }
197 bool operator>=(int64_t RHS) const {
198 return compareValues(*this, get(RHS)) >= 0;
199 }
200 bool operator<(int64_t RHS) const {
201 return compareValues(*this, get(RHS)) < 0;
202 }
203 bool operator>(int64_t RHS) const {
204 return compareValues(*this, get(RHS)) > 0;
205 }
206
207 // The remaining operators just wrap the logic of APInt, but retain the
208 // signedness information.
209
210 APSInt operator<<(unsigned Bits) const {
211 return APSInt(static_cast<const APInt &>(*this) << Bits, IsUnsigned);
212 }
213 APSInt &operator<<=(unsigned Amt) {
214 static_cast<APInt &>(*this) <<= Amt;
215 return *this;
216 }
217 APSInt relativeShl(unsigned Amt) const {
218 return IsUnsigned ? APSInt(relativeLShl(Amt), true)
219 : APSInt(relativeAShl(Amt), false);
220 }
221
223 ++(static_cast<APInt &>(*this));
224 return *this;
225 }
227 --(static_cast<APInt &>(*this));
228 return *this;
229 }
231 return APSInt(++static_cast<APInt &>(*this), IsUnsigned);
232 }
234 return APSInt(--static_cast<APInt &>(*this), IsUnsigned);
235 }
237 return APSInt(-static_cast<const APInt &>(*this), IsUnsigned);
238 }
240 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
241 static_cast<APInt &>(*this) += RHS;
242 return *this;
243 }
245 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
246 static_cast<APInt &>(*this) -= RHS;
247 return *this;
248 }
250 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
251 static_cast<APInt &>(*this) *= RHS;
252 return *this;
253 }
255 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
256 static_cast<APInt &>(*this) &= RHS;
257 return *this;
258 }
260 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
261 static_cast<APInt &>(*this) |= RHS;
262 return *this;
263 }
265 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
266 static_cast<APInt &>(*this) ^= RHS;
267 return *this;
268 }
269
270 APSInt operator&(const APSInt &RHS) const {
271 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
272 return APSInt(static_cast<const APInt &>(*this) & RHS, IsUnsigned);
273 }
274
275 APSInt operator|(const APSInt &RHS) const {
276 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
277 return APSInt(static_cast<const APInt &>(*this) | RHS, IsUnsigned);
278 }
279
280 APSInt operator^(const APSInt &RHS) const {
281 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
282 return APSInt(static_cast<const APInt &>(*this) ^ RHS, IsUnsigned);
283 }
284
285 APSInt operator*(const APSInt &RHS) const {
286 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
287 return APSInt(static_cast<const APInt &>(*this) * RHS, IsUnsigned);
288 }
289 APSInt operator+(const APSInt &RHS) const {
290 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
291 return APSInt(static_cast<const APInt &>(*this) + RHS, IsUnsigned);
292 }
293 APSInt operator-(const APSInt &RHS) const {
294 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
295 return APSInt(static_cast<const APInt &>(*this) - RHS, IsUnsigned);
296 }
298 return APSInt(~static_cast<const APInt &>(*this), IsUnsigned);
299 }
300
301 /// Return the APSInt representing the maximum integer value with the given
302 /// bit width and signedness.
303 static APSInt getMaxValue(uint32_t numBits, bool Unsigned) {
304 return APSInt(Unsigned ? APInt::getMaxValue(numBits)
305 : APInt::getSignedMaxValue(numBits),
306 Unsigned);
307 }
308
309 /// Return the APSInt representing the minimum integer value with the given
310 /// bit width and signedness.
311 static APSInt getMinValue(uint32_t numBits, bool Unsigned) {
312 return APSInt(Unsigned ? APInt::getMinValue(numBits)
313 : APInt::getSignedMinValue(numBits),
314 Unsigned);
315 }
316
317 /// Determine if two APSInts have the same value, zero- or
318 /// sign-extending as needed.
319 static bool isSameValue(const APSInt &I1, const APSInt &I2) {
320 return !compareValues(I1, I2);
321 }
322
323 /// Compare underlying values of two numbers.
324 static int compareValues(const APSInt &I1, const APSInt &I2) {
325 if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned())
326 return I1.IsUnsigned ? I1.compare(I2) : I1.compareSigned(I2);
327
328 // Check for a bit-width mismatch.
329 if (I1.getBitWidth() > I2.getBitWidth())
330 return compareValues(I1, I2.extend(I1.getBitWidth()));
331 if (I2.getBitWidth() > I1.getBitWidth())
332 return compareValues(I1.extend(I2.getBitWidth()), I2);
333
334 // We have a signedness mismatch. Check for negative values and do an
335 // unsigned compare if both are positive.
336 if (I1.isSigned()) {
337 assert(!I2.isSigned() && "Expected signed mismatch");
338 if (I1.isNegative())
339 return -1;
340 } else {
341 assert(I2.isSigned() && "Expected signed mismatch");
342 if (I2.isNegative())
343 return 1;
344 }
345
346 return I1.compare(I2);
347 }
348
349 static APSInt get(int64_t X) { return APSInt(APInt(64, X), false); }
350 static APSInt getUnsigned(uint64_t X) { return APSInt(APInt(64, X), true); }
351
352 /// Used to insert APSInt objects, or objects that contain APSInt objects,
353 /// into FoldingSets.
354 void Profile(FoldingSetNodeID &ID) const;
355};
356
357inline bool operator==(int64_t V1, const APSInt &V2) { return V2 == V1; }
358inline bool operator!=(int64_t V1, const APSInt &V2) { return V2 != V1; }
359inline bool operator<=(int64_t V1, const APSInt &V2) { return V2 >= V1; }
360inline bool operator>=(int64_t V1, const APSInt &V2) { return V2 <= V1; }
361inline bool operator<(int64_t V1, const APSInt &V2) { return V2 > V1; }
362inline bool operator>(int64_t V1, const APSInt &V2) { return V2 < V1; }
363
365 I.print(OS, I.isSigned());
366 return OS;
367}
368
369/// Provide DenseMapInfo for APSInt, using the DenseMapInfo for APInt.
370template <> struct DenseMapInfo<APSInt, void> {
371 static inline APSInt getEmptyKey() {
373 }
374
375 static inline APSInt getTombstoneKey() {
377 }
378
379 static unsigned getHashValue(const APSInt &Key) {
381 }
382
383 static bool isEqual(const APSInt &LHS, const APSInt &RHS) {
384 return LHS.getBitWidth() == RHS.getBitWidth() &&
385 LHS.isUnsigned() == RHS.isUnsigned() && LHS == RHS;
386 }
387};
388
389} // end namespace llvm
390
391#endif
This file implements a class to represent arbitrary precision integral constant values and operations...
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
static bool isSigned(unsigned int Opcode)
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
Definition: Lint.cpp:531
#define I(x, y, z)
Definition: MD5.cpp:58
Load MIR Sample Profile
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
Value * RHS
Value * LHS
Class for arbitrary precision integers.
Definition: APInt.h:76
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition: APInt.h:1439
An arbitrary precision integer that knows its signedness.
Definition: APSInt.h:23
APSInt extOrTrunc(uint32_t width) const
Definition: APSInt.h:119
APSInt & operator+=(const APSInt &RHS)
Definition: APSInt.h:239
APSInt operator-(const APSInt &RHS) const
Definition: APSInt.h:293
APSInt & operator=(APInt RHS)
Definition: APSInt.h:64
static APSInt getMinValue(uint32_t numBits, bool Unsigned)
Return the APSInt representing the minimum integer value with the given bit width and signedness.
Definition: APSInt.h:311
bool operator==(int64_t RHS) const
Definition: APSInt.h:188
static APSInt get(int64_t X)
Definition: APSInt.h:349
bool operator==(const APSInt &RHS) const
Definition: APSInt.h:182
bool isNegative() const
Determine sign of this APSInt.
Definition: APSInt.h:49
APSInt operator>>(unsigned Amt) const
Definition: APSInt.h:151
APSInt operator^(const APSInt &RHS) const
Definition: APSInt.h:280
bool operator!=(int64_t RHS) const
Definition: APSInt.h:191
APSInt operator*(const APSInt &RHS) const
Definition: APSInt.h:285
APSInt & operator*=(const APSInt &RHS)
Definition: APSInt.h:249
APSInt & operator++()
Definition: APSInt.h:222
bool operator>(const APSInt &RHS) const
Definition: APSInt.h:170
bool operator>(int64_t RHS) const
Definition: APSInt.h:203
APSInt(uint32_t BitWidth, bool isUnsigned=true)
Create an APSInt with the specified width, default to unsigned.
Definition: APSInt.h:31
APSInt relativeShr(unsigned Amt) const
Definition: APSInt.h:161
bool operator<(const APSInt &RHS) const
Definition: APSInt.h:166
static int compareValues(const APSInt &I1, const APSInt &I2)
Compare underlying values of two numbers.
Definition: APSInt.h:324
int64_t getExtValue() const
Get the correctly-extended int64_t value.
Definition: APSInt.h:98
APSInt operator+(const APSInt &RHS) const
Definition: APSInt.h:289
const APSInt & operator/=(const APSInt &RHS)
Definition: APSInt.h:134
APSInt operator++(int)
Definition: APSInt.h:230
bool isRepresentableByInt64() const
If this int is representable using an int64_t.
Definition: APSInt.h:89
static APSInt getMaxValue(uint32_t numBits, bool Unsigned)
Return the APSInt representing the maximum integer value with the given bit width and signedness.
Definition: APSInt.h:303
bool isNonNegative() const
Determine if this APSInt Value is non-negative (>= 0)
Definition: APSInt.h:54
static APSInt getUnsigned(uint64_t X)
Definition: APSInt.h:350
APSInt operator-() const
Definition: APSInt.h:236
bool operator<=(int64_t RHS) const
Definition: APSInt.h:194
APSInt operator<<(unsigned Bits) const
Definition: APSInt.h:210
APSInt operator&(const APSInt &RHS) const
Definition: APSInt.h:270
APSInt operator--(int)
Definition: APSInt.h:233
bool isStrictlyPositive() const
Determine if this APSInt Value is positive.
Definition: APSInt.h:62
APSInt & operator&=(const APSInt &RHS)
Definition: APSInt.h:254
void setIsSigned(bool Val)
Definition: APSInt.h:80
bool operator>=(const APSInt &RHS) const
Definition: APSInt.h:178
APSInt(APInt I, bool isUnsigned=true)
Definition: APSInt.h:34
APSInt operator~() const
Definition: APSInt.h:297
APSInt operator%(const APSInt &RHS) const
Definition: APSInt.h:142
const APSInt & operator%=(const APSInt &RHS)
Definition: APSInt.h:126
APSInt & operator|=(const APSInt &RHS)
Definition: APSInt.h:259
APSInt relativeShl(unsigned Amt) const
Definition: APSInt.h:217
void toString(SmallVectorImpl< char > &Str, unsigned Radix=10) const
Append this APSInt to the specified SmallString.
Definition: APSInt.h:83
bool operator!=(const APSInt &RHS) const
Definition: APSInt.h:186
std::optional< int64_t > tryExtValue() const
Definition: APSInt.h:103
bool operator<(int64_t RHS) const
Definition: APSInt.h:200
bool isUnsigned() const
Definition: APSInt.h:78
APSInt()=default
Default constructor that creates an uninitialized APInt.
APSInt & operator>>=(unsigned Amt)
Definition: APSInt.h:154
void setIsUnsigned(bool Val)
Definition: APSInt.h:79
static bool isSameValue(const APSInt &I1, const APSInt &I2)
Determine if two APSInts have the same value, zero- or sign-extending as needed.
Definition: APSInt.h:319
APSInt extend(uint32_t width) const
Definition: APSInt.h:112
APSInt & operator-=(const APSInt &RHS)
Definition: APSInt.h:244
APSInt operator|(const APSInt &RHS) const
Definition: APSInt.h:275
bool operator<=(const APSInt &RHS) const
Definition: APSInt.h:174
APSInt operator/(const APSInt &RHS) const
Definition: APSInt.h:146
APSInt & operator=(uint64_t RHS)
Definition: APSInt.h:70
bool operator>=(int64_t RHS) const
Definition: APSInt.h:197
APSInt trunc(uint32_t width) const
Definition: APSInt.h:108
APSInt & operator--()
Definition: APSInt.h:226
bool isSigned() const
Definition: APSInt.h:77
APSInt & operator^=(const APSInt &RHS)
Definition: APSInt.h:264
APSInt & operator<<=(unsigned Amt)
Definition: APSInt.h:213
FoldingSetNodeID - This class is used to gather all the unique data bits of a node.
Definition: FoldingSet.h:320
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
bool operator<(int64_t V1, const APSInt &V2)
Definition: APSInt.h:361
bool operator!=(uint64_t V1, const APInt &V2)
Definition: APInt.h:2043
bool operator>=(int64_t V1, const APSInt &V2)
Definition: APSInt.h:360
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
bool operator>(int64_t V1, const APSInt &V2)
Definition: APSInt.h:362
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:233
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
Definition: APFixedPoint.h:293
constexpr unsigned BitWidth
Definition: BitmaskEnum.h:191
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1858
bool operator<=(int64_t V1, const APSInt &V2)
Definition: APSInt.h:359
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
static bool isEqual(const APSInt &LHS, const APSInt &RHS)
Definition: APSInt.h:383
static APSInt getTombstoneKey()
Definition: APSInt.h:375
static unsigned getHashValue(const APSInt &Key)
Definition: APSInt.h:379
An information struct used to provide DenseMap with the various necessary components for a given valu...
Definition: DenseMapInfo.h:50