Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:02

0001 //===-- llvm/ADT/APSInt.h - Arbitrary Precision Signed Int -----*- C++ -*--===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 ///
0009 /// \file
0010 /// This file implements the APSInt class, which is a simple class that
0011 /// represents an arbitrary sized integer that knows its signedness.
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 /// An arbitrary precision integer that knows its signedness.
0023 class [[nodiscard]] APSInt : public APInt {
0024   bool IsUnsigned = false;
0025 
0026 public:
0027   /// Default constructor that creates an uninitialized APInt.
0028   explicit APSInt() = default;
0029 
0030   /// Create an APSInt with the specified width, default to unsigned.
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   /// Construct an APSInt from a string representation.
0038   ///
0039   /// This constructor interprets the string \p Str using the radix of 10.
0040   /// The interpretation stops at the end of the string. The bit width of the
0041   /// constructed APSInt is determined automatically.
0042   ///
0043   /// \param Str the string to be interpreted.
0044   explicit APSInt(StringRef Str);
0045 
0046   /// Determine sign of this APSInt.
0047   ///
0048   /// \returns true if this APSInt is negative, false otherwise
0049   bool isNegative() const { return isSigned() && APInt::isNegative(); }
0050 
0051   /// Determine if this APSInt Value is non-negative (>= 0)
0052   ///
0053   /// \returns true if this APSInt is non-negative, false otherwise
0054   bool isNonNegative() const { return !isNegative(); }
0055 
0056   /// Determine if this APSInt Value is positive.
0057   ///
0058   /// This tests if the value of this APSInt is positive (> 0). Note
0059   /// that 0 is not a positive value.
0060   ///
0061   /// \returns true if this APSInt is positive.
0062   bool isStrictlyPositive() const { return isNonNegative() && !isZero(); }
0063 
0064   APSInt &operator=(APInt RHS) {
0065     // Retain our current sign.
0066     APInt::operator=(std::move(RHS));
0067     return *this;
0068   }
0069 
0070   APSInt &operator=(uint64_t RHS) {
0071     // Retain our current sign.
0072     APInt::operator=(RHS);
0073     return *this;
0074   }
0075 
0076   // Query sign information.
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   /// Append this APSInt to the specified SmallString.
0083   void toString(SmallVectorImpl<char> &Str, unsigned Radix = 10) const {
0084     APInt::toString(Str, Radix, isSigned());
0085   }
0086   using APInt::toString;
0087 
0088   /// If this int is representable using an int64_t.
0089   bool isRepresentableByInt64() const {
0090     // For unsigned values with 64 active bits, they technically fit into a
0091     // int64_t, but the user may get negative numbers and has to manually cast
0092     // them to unsigned. Let's not bet the user has the sanity to do that and
0093     // not give them a vague value at the first place.
0094     return isSigned() ? isSignedIntN(64) : isIntN(63);
0095   }
0096 
0097   /// Get the correctly-extended \c int64_t value.
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   // The remaining operators just wrap the logic of APInt, but retain the
0208   // signedness information.
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   /// Return the APSInt representing the maximum integer value with the given
0302   /// bit width and signedness.
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   /// Return the APSInt representing the minimum integer value with the given
0310   /// bit width and signedness.
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   /// Determine if two APSInts have the same value, zero- or
0318   /// sign-extending as needed.
0319   static bool isSameValue(const APSInt &I1, const APSInt &I2) {
0320     return !compareValues(I1, I2);
0321   }
0322 
0323   /// Compare underlying values of two numbers.
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     // Check for a bit-width mismatch.
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     // We have a signedness mismatch. Check for negative values and do an
0335     // unsigned compare if both are positive.
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   /// Used to insert APSInt objects, or objects that contain APSInt objects,
0353   /// into FoldingSets.
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 /// Provide DenseMapInfo for APSInt, using the DenseMapInfo for APInt.
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 } // end namespace llvm
0390 
0391 #endif