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