File indexing completed on 2026-05-10 08:43:02
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef LLVM_ADT_APSINT_H
0016 #define LLVM_ADT_APSINT_H
0017
0018 #include "llvm/ADT/APInt.h"
0019
0020 namespace llvm {
0021
0022
0023 class [[nodiscard]] APSInt : public APInt {
0024 bool IsUnsigned = false;
0025
0026 public:
0027
0028 explicit APSInt() = default;
0029
0030
0031 explicit APSInt(uint32_t BitWidth, bool isUnsigned = true)
0032 : APInt(BitWidth, 0), IsUnsigned(isUnsigned) {}
0033
0034 explicit APSInt(APInt I, bool isUnsigned = true)
0035 : APInt(std::move(I)), IsUnsigned(isUnsigned) {}
0036
0037
0038
0039
0040
0041
0042
0043
0044 explicit APSInt(StringRef Str);
0045
0046
0047
0048
0049 bool isNegative() const { return isSigned() && APInt::isNegative(); }
0050
0051
0052
0053
0054 bool isNonNegative() const { return !isNegative(); }
0055
0056
0057
0058
0059
0060
0061
0062 bool isStrictlyPositive() const { return isNonNegative() && !isZero(); }
0063
0064 APSInt &operator=(APInt RHS) {
0065
0066 APInt::operator=(std::move(RHS));
0067 return *this;
0068 }
0069
0070 APSInt &operator=(uint64_t RHS) {
0071
0072 APInt::operator=(RHS);
0073 return *this;
0074 }
0075
0076
0077 bool isSigned() const { return !IsUnsigned; }
0078 bool isUnsigned() const { return IsUnsigned; }
0079 void setIsUnsigned(bool Val) { IsUnsigned = Val; }
0080 void setIsSigned(bool Val) { IsUnsigned = !Val; }
0081
0082
0083 void toString(SmallVectorImpl<char> &Str, unsigned Radix = 10) const {
0084 APInt::toString(Str, Radix, isSigned());
0085 }
0086 using APInt::toString;
0087
0088
0089 bool isRepresentableByInt64() const {
0090
0091
0092
0093
0094 return isSigned() ? isSignedIntN(64) : isIntN(63);
0095 }
0096
0097
0098 int64_t getExtValue() const {
0099 assert(isRepresentableByInt64() && "Too many bits for int64_t");
0100 return isSigned() ? getSExtValue() : getZExtValue();
0101 }
0102
0103 std::optional<int64_t> tryExtValue() const {
0104 return isRepresentableByInt64() ? std::optional<int64_t>(getExtValue())
0105 : std::nullopt;
0106 }
0107
0108 APSInt trunc(uint32_t width) const {
0109 return APSInt(APInt::trunc(width), IsUnsigned);
0110 }
0111
0112 APSInt extend(uint32_t width) const {
0113 if (IsUnsigned)
0114 return APSInt(zext(width), IsUnsigned);
0115 else
0116 return APSInt(sext(width), IsUnsigned);
0117 }
0118
0119 APSInt extOrTrunc(uint32_t width) const {
0120 if (IsUnsigned)
0121 return APSInt(zextOrTrunc(width), IsUnsigned);
0122 else
0123 return APSInt(sextOrTrunc(width), IsUnsigned);
0124 }
0125
0126 const APSInt &operator%=(const APSInt &RHS) {
0127 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
0128 if (IsUnsigned)
0129 *this = urem(RHS);
0130 else
0131 *this = srem(RHS);
0132 return *this;
0133 }
0134 const APSInt &operator/=(const APSInt &RHS) {
0135 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
0136 if (IsUnsigned)
0137 *this = udiv(RHS);
0138 else
0139 *this = sdiv(RHS);
0140 return *this;
0141 }
0142 APSInt operator%(const APSInt &RHS) const {
0143 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
0144 return IsUnsigned ? APSInt(urem(RHS), true) : APSInt(srem(RHS), false);
0145 }
0146 APSInt operator/(const APSInt &RHS) const {
0147 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
0148 return IsUnsigned ? APSInt(udiv(RHS), true) : APSInt(sdiv(RHS), false);
0149 }
0150
0151 APSInt operator>>(unsigned Amt) const {
0152 return IsUnsigned ? APSInt(lshr(Amt), true) : APSInt(ashr(Amt), false);
0153 }
0154 APSInt &operator>>=(unsigned Amt) {
0155 if (IsUnsigned)
0156 lshrInPlace(Amt);
0157 else
0158 ashrInPlace(Amt);
0159 return *this;
0160 }
0161 APSInt relativeShr(unsigned Amt) const {
0162 return IsUnsigned ? APSInt(relativeLShr(Amt), true)
0163 : APSInt(relativeAShr(Amt), false);
0164 }
0165
0166 inline bool operator<(const APSInt &RHS) const {
0167 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
0168 return IsUnsigned ? ult(RHS) : slt(RHS);
0169 }
0170 inline bool operator>(const APSInt &RHS) const {
0171 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
0172 return IsUnsigned ? ugt(RHS) : sgt(RHS);
0173 }
0174 inline bool operator<=(const APSInt &RHS) const {
0175 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
0176 return IsUnsigned ? ule(RHS) : sle(RHS);
0177 }
0178 inline bool operator>=(const APSInt &RHS) const {
0179 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
0180 return IsUnsigned ? uge(RHS) : sge(RHS);
0181 }
0182 inline bool operator==(const APSInt &RHS) const {
0183 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
0184 return eq(RHS);
0185 }
0186 inline bool operator!=(const APSInt &RHS) const { return !((*this) == RHS); }
0187
0188 bool operator==(int64_t RHS) const {
0189 return compareValues(*this, get(RHS)) == 0;
0190 }
0191 bool operator!=(int64_t RHS) const {
0192 return compareValues(*this, get(RHS)) != 0;
0193 }
0194 bool operator<=(int64_t RHS) const {
0195 return compareValues(*this, get(RHS)) <= 0;
0196 }
0197 bool operator>=(int64_t RHS) const {
0198 return compareValues(*this, get(RHS)) >= 0;
0199 }
0200 bool operator<(int64_t RHS) const {
0201 return compareValues(*this, get(RHS)) < 0;
0202 }
0203 bool operator>(int64_t RHS) const {
0204 return compareValues(*this, get(RHS)) > 0;
0205 }
0206
0207
0208
0209
0210 APSInt operator<<(unsigned Bits) const {
0211 return APSInt(static_cast<const APInt &>(*this) << Bits, IsUnsigned);
0212 }
0213 APSInt &operator<<=(unsigned Amt) {
0214 static_cast<APInt &>(*this) <<= Amt;
0215 return *this;
0216 }
0217 APSInt relativeShl(unsigned Amt) const {
0218 return IsUnsigned ? APSInt(relativeLShl(Amt), true)
0219 : APSInt(relativeAShl(Amt), false);
0220 }
0221
0222 APSInt &operator++() {
0223 ++(static_cast<APInt &>(*this));
0224 return *this;
0225 }
0226 APSInt &operator--() {
0227 --(static_cast<APInt &>(*this));
0228 return *this;
0229 }
0230 APSInt operator++(int) {
0231 return APSInt(++static_cast<APInt &>(*this), IsUnsigned);
0232 }
0233 APSInt operator--(int) {
0234 return APSInt(--static_cast<APInt &>(*this), IsUnsigned);
0235 }
0236 APSInt operator-() const {
0237 return APSInt(-static_cast<const APInt &>(*this), IsUnsigned);
0238 }
0239 APSInt &operator+=(const APSInt &RHS) {
0240 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
0241 static_cast<APInt &>(*this) += RHS;
0242 return *this;
0243 }
0244 APSInt &operator-=(const APSInt &RHS) {
0245 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
0246 static_cast<APInt &>(*this) -= RHS;
0247 return *this;
0248 }
0249 APSInt &operator*=(const APSInt &RHS) {
0250 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
0251 static_cast<APInt &>(*this) *= RHS;
0252 return *this;
0253 }
0254 APSInt &operator&=(const APSInt &RHS) {
0255 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
0256 static_cast<APInt &>(*this) &= RHS;
0257 return *this;
0258 }
0259 APSInt &operator|=(const APSInt &RHS) {
0260 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
0261 static_cast<APInt &>(*this) |= RHS;
0262 return *this;
0263 }
0264 APSInt &operator^=(const APSInt &RHS) {
0265 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
0266 static_cast<APInt &>(*this) ^= RHS;
0267 return *this;
0268 }
0269
0270 APSInt operator&(const APSInt &RHS) const {
0271 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
0272 return APSInt(static_cast<const APInt &>(*this) & RHS, IsUnsigned);
0273 }
0274
0275 APSInt operator|(const APSInt &RHS) const {
0276 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
0277 return APSInt(static_cast<const APInt &>(*this) | RHS, IsUnsigned);
0278 }
0279
0280 APSInt operator^(const APSInt &RHS) const {
0281 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
0282 return APSInt(static_cast<const APInt &>(*this) ^ RHS, IsUnsigned);
0283 }
0284
0285 APSInt operator*(const APSInt &RHS) const {
0286 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
0287 return APSInt(static_cast<const APInt &>(*this) * RHS, IsUnsigned);
0288 }
0289 APSInt operator+(const APSInt &RHS) const {
0290 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
0291 return APSInt(static_cast<const APInt &>(*this) + RHS, IsUnsigned);
0292 }
0293 APSInt operator-(const APSInt &RHS) const {
0294 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
0295 return APSInt(static_cast<const APInt &>(*this) - RHS, IsUnsigned);
0296 }
0297 APSInt operator~() const {
0298 return APSInt(~static_cast<const APInt &>(*this), IsUnsigned);
0299 }
0300
0301
0302
0303 static APSInt getMaxValue(uint32_t numBits, bool Unsigned) {
0304 return APSInt(Unsigned ? APInt::getMaxValue(numBits)
0305 : APInt::getSignedMaxValue(numBits),
0306 Unsigned);
0307 }
0308
0309
0310
0311 static APSInt getMinValue(uint32_t numBits, bool Unsigned) {
0312 return APSInt(Unsigned ? APInt::getMinValue(numBits)
0313 : APInt::getSignedMinValue(numBits),
0314 Unsigned);
0315 }
0316
0317
0318
0319 static bool isSameValue(const APSInt &I1, const APSInt &I2) {
0320 return !compareValues(I1, I2);
0321 }
0322
0323
0324 static int compareValues(const APSInt &I1, const APSInt &I2) {
0325 if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned())
0326 return I1.IsUnsigned ? I1.compare(I2) : I1.compareSigned(I2);
0327
0328
0329 if (I1.getBitWidth() > I2.getBitWidth())
0330 return compareValues(I1, I2.extend(I1.getBitWidth()));
0331 if (I2.getBitWidth() > I1.getBitWidth())
0332 return compareValues(I1.extend(I2.getBitWidth()), I2);
0333
0334
0335
0336 if (I1.isSigned()) {
0337 assert(!I2.isSigned() && "Expected signed mismatch");
0338 if (I1.isNegative())
0339 return -1;
0340 } else {
0341 assert(I2.isSigned() && "Expected signed mismatch");
0342 if (I2.isNegative())
0343 return 1;
0344 }
0345
0346 return I1.compare(I2);
0347 }
0348
0349 static APSInt get(int64_t X) { return APSInt(APInt(64, X), false); }
0350 static APSInt getUnsigned(uint64_t X) { return APSInt(APInt(64, X), true); }
0351
0352
0353
0354 void Profile(FoldingSetNodeID &ID) const;
0355 };
0356
0357 inline bool operator==(int64_t V1, const APSInt &V2) { return V2 == V1; }
0358 inline bool operator!=(int64_t V1, const APSInt &V2) { return V2 != V1; }
0359 inline bool operator<=(int64_t V1, const APSInt &V2) { return V2 >= V1; }
0360 inline bool operator>=(int64_t V1, const APSInt &V2) { return V2 <= V1; }
0361 inline bool operator<(int64_t V1, const APSInt &V2) { return V2 > V1; }
0362 inline bool operator>(int64_t V1, const APSInt &V2) { return V2 < V1; }
0363
0364 inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) {
0365 I.print(OS, I.isSigned());
0366 return OS;
0367 }
0368
0369
0370 template <> struct DenseMapInfo<APSInt, void> {
0371 static inline APSInt getEmptyKey() {
0372 return APSInt(DenseMapInfo<APInt, void>::getEmptyKey());
0373 }
0374
0375 static inline APSInt getTombstoneKey() {
0376 return APSInt(DenseMapInfo<APInt, void>::getTombstoneKey());
0377 }
0378
0379 static unsigned getHashValue(const APSInt &Key) {
0380 return DenseMapInfo<APInt, void>::getHashValue(Key);
0381 }
0382
0383 static bool isEqual(const APSInt &LHS, const APSInt &RHS) {
0384 return LHS.getBitWidth() == RHS.getBitWidth() &&
0385 LHS.isUnsigned() == RHS.isUnsigned() && LHS == RHS;
0386 }
0387 };
0388
0389 }
0390
0391 #endif