1 //===-- llvm/ADT/APSInt.h - Arbitrary Precision Signed Int -----*- C++ -*--===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 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 20 namespace llvm { 21 22 class LLVM_NODISCARD APSInt : public APInt { 23 bool IsUnsigned; 24 25 public: 26 /// Default constructor that creates an uninitialized APInt. 27 explicit APSInt() : IsUnsigned(false) {} 28 29 /// APSInt ctor - Create an APSInt with the specified width, default to 30 /// 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 APSInt &operator=(APInt RHS) { 47 // Retain our current sign. 48 APInt::operator=(std::move(RHS)); 49 return *this; 50 } 51 52 APSInt &operator=(uint64_t RHS) { 53 // Retain our current sign. 54 APInt::operator=(RHS); 55 return *this; 56 } 57 58 // Query sign information. 59 bool isSigned() const { return !IsUnsigned; } 60 bool isUnsigned() const { return IsUnsigned; } 61 void setIsUnsigned(bool Val) { IsUnsigned = Val; } 62 void setIsSigned(bool Val) { IsUnsigned = !Val; } 63 64 /// toString - Append this APSInt to the specified SmallString. 65 void toString(SmallVectorImpl<char> &Str, unsigned Radix = 10) const { 66 APInt::toString(Str, Radix, isSigned()); 67 } 68 /// toString - Converts an APInt to a std::string. This is an inefficient 69 /// method; you should prefer passing in a SmallString instead. 70 std::string toString(unsigned Radix) const { 71 return APInt::toString(Radix, isSigned()); 72 } 73 using APInt::toString; 74 75 /// \brief Get the correctly-extended \c int64_t value. 76 int64_t getExtValue() const { 77 assert(getMinSignedBits() <= 64 && "Too many bits for int64_t"); 78 return isSigned() ? getSExtValue() : getZExtValue(); 79 } 80 81 APSInt trunc(uint32_t width) const { 82 return APSInt(APInt::trunc(width), IsUnsigned); 83 } 84 85 APSInt extend(uint32_t width) const { 86 if (IsUnsigned) 87 return APSInt(zext(width), IsUnsigned); 88 else 89 return APSInt(sext(width), IsUnsigned); 90 } 91 92 APSInt extOrTrunc(uint32_t width) const { 93 if (IsUnsigned) 94 return APSInt(zextOrTrunc(width), IsUnsigned); 95 else 96 return APSInt(sextOrTrunc(width), IsUnsigned); 97 } 98 99 const APSInt &operator%=(const APSInt &RHS) { 100 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 101 if (IsUnsigned) 102 *this = urem(RHS); 103 else 104 *this = srem(RHS); 105 return *this; 106 } 107 const APSInt &operator/=(const APSInt &RHS) { 108 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 109 if (IsUnsigned) 110 *this = udiv(RHS); 111 else 112 *this = sdiv(RHS); 113 return *this; 114 } 115 APSInt operator%(const APSInt &RHS) const { 116 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 117 return IsUnsigned ? APSInt(urem(RHS), true) : APSInt(srem(RHS), false); 118 } 119 APSInt operator/(const APSInt &RHS) const { 120 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 121 return IsUnsigned ? APSInt(udiv(RHS), true) : APSInt(sdiv(RHS), false); 122 } 123 124 APSInt operator>>(unsigned Amt) const { 125 return IsUnsigned ? APSInt(lshr(Amt), true) : APSInt(ashr(Amt), false); 126 } 127 APSInt& operator>>=(unsigned Amt) { 128 *this = *this >> Amt; 129 return *this; 130 } 131 132 inline bool operator<(const APSInt& RHS) const { 133 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 134 return IsUnsigned ? ult(RHS) : slt(RHS); 135 } 136 inline bool operator>(const APSInt& RHS) const { 137 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 138 return IsUnsigned ? ugt(RHS) : sgt(RHS); 139 } 140 inline bool operator<=(const APSInt& RHS) const { 141 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 142 return IsUnsigned ? ule(RHS) : sle(RHS); 143 } 144 inline bool operator>=(const APSInt& RHS) const { 145 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 146 return IsUnsigned ? uge(RHS) : sge(RHS); 147 } 148 inline bool operator==(const APSInt& RHS) const { 149 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 150 return eq(RHS); 151 } 152 inline bool operator!=(const APSInt& RHS) const { 153 return !((*this) == RHS); 154 } 155 156 bool operator==(int64_t RHS) const { 157 return compareValues(*this, get(RHS)) == 0; 158 } 159 bool operator!=(int64_t RHS) const { 160 return compareValues(*this, get(RHS)) != 0; 161 } 162 bool operator<=(int64_t RHS) const { 163 return compareValues(*this, get(RHS)) <= 0; 164 } 165 bool operator>=(int64_t RHS) const { 166 return compareValues(*this, get(RHS)) >= 0; 167 } 168 bool operator<(int64_t RHS) const { 169 return compareValues(*this, get(RHS)) < 0; 170 } 171 bool operator>(int64_t RHS) const { 172 return compareValues(*this, get(RHS)) > 0; 173 } 174 175 // The remaining operators just wrap the logic of APInt, but retain the 176 // signedness information. 177 178 APSInt operator<<(unsigned Bits) const { 179 return APSInt(static_cast<const APInt&>(*this) << Bits, IsUnsigned); 180 } 181 APSInt& operator<<=(unsigned Amt) { 182 *this = *this << Amt; 183 return *this; 184 } 185 186 APSInt& operator++() { 187 ++(static_cast<APInt&>(*this)); 188 return *this; 189 } 190 APSInt& operator--() { 191 --(static_cast<APInt&>(*this)); 192 return *this; 193 } 194 APSInt operator++(int) { 195 return APSInt(++static_cast<APInt&>(*this), IsUnsigned); 196 } 197 APSInt operator--(int) { 198 return APSInt(--static_cast<APInt&>(*this), IsUnsigned); 199 } 200 APSInt operator-() const { 201 return APSInt(-static_cast<const APInt&>(*this), IsUnsigned); 202 } 203 APSInt& operator+=(const APSInt& RHS) { 204 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 205 static_cast<APInt&>(*this) += RHS; 206 return *this; 207 } 208 APSInt& operator-=(const APSInt& RHS) { 209 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 210 static_cast<APInt&>(*this) -= RHS; 211 return *this; 212 } 213 APSInt& operator*=(const APSInt& RHS) { 214 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 215 static_cast<APInt&>(*this) *= RHS; 216 return *this; 217 } 218 APSInt& operator&=(const APSInt& RHS) { 219 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 220 static_cast<APInt&>(*this) &= RHS; 221 return *this; 222 } 223 APSInt& operator|=(const APSInt& RHS) { 224 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 225 static_cast<APInt&>(*this) |= RHS; 226 return *this; 227 } 228 APSInt& operator^=(const APSInt& RHS) { 229 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 230 static_cast<APInt&>(*this) ^= RHS; 231 return *this; 232 } 233 234 APSInt operator&(const APSInt& RHS) const { 235 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 236 return APSInt(static_cast<const APInt&>(*this) & RHS, IsUnsigned); 237 } 238 APSInt And(const APSInt &RHS) const { return this->operator&(RHS); } 239 240 APSInt operator|(const APSInt& RHS) const { 241 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 242 return APSInt(static_cast<const APInt&>(*this) | RHS, IsUnsigned); 243 } 244 APSInt Or(const APSInt &RHS) const { return this->operator|(RHS); } 245 246 APSInt operator^(const APSInt &RHS) const { 247 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 248 return APSInt(static_cast<const APInt&>(*this) ^ RHS, IsUnsigned); 249 } 250 APSInt Xor(const APSInt &RHS) const { return this->operator^(RHS); } 251 252 APSInt operator*(const APSInt& RHS) const { 253 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 254 return APSInt(static_cast<const APInt&>(*this) * RHS, IsUnsigned); 255 } 256 APSInt operator+(const APSInt& RHS) const { 257 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 258 return APSInt(static_cast<const APInt&>(*this) + RHS, IsUnsigned); 259 } 260 APSInt operator-(const APSInt& RHS) const { 261 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 262 return APSInt(static_cast<const APInt&>(*this) - RHS, IsUnsigned); 263 } 264 APSInt operator~() const { 265 return APSInt(~static_cast<const APInt&>(*this), IsUnsigned); 266 } 267 268 /// getMaxValue - Return the APSInt representing the maximum integer value 269 /// with the given bit width and signedness. 270 static APSInt getMaxValue(uint32_t numBits, bool Unsigned) { 271 return APSInt(Unsigned ? APInt::getMaxValue(numBits) 272 : APInt::getSignedMaxValue(numBits), Unsigned); 273 } 274 275 /// getMinValue - Return the APSInt representing the minimum integer value 276 /// with the given bit width and signedness. 277 static APSInt getMinValue(uint32_t numBits, bool Unsigned) { 278 return APSInt(Unsigned ? APInt::getMinValue(numBits) 279 : APInt::getSignedMinValue(numBits), Unsigned); 280 } 281 282 /// \brief Determine if two APSInts have the same value, zero- or 283 /// sign-extending as needed. 284 static bool isSameValue(const APSInt &I1, const APSInt &I2) { 285 return !compareValues(I1, I2); 286 } 287 288 /// \brief Compare underlying values of two numbers. 289 static int compareValues(const APSInt &I1, const APSInt &I2) { 290 if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned()) 291 return I1 == I2 ? 0 : I1 > I2 ? 1 : -1; 292 293 // Check for a bit-width mismatch. 294 if (I1.getBitWidth() > I2.getBitWidth()) 295 return compareValues(I1, I2.extend(I1.getBitWidth())); 296 else if (I2.getBitWidth() > I1.getBitWidth()) 297 return compareValues(I1.extend(I2.getBitWidth()), I2); 298 299 // We have a signedness mismatch. Check for negative values and do an 300 // unsigned compare if both are positive. 301 if (I1.isSigned()) { 302 assert(!I2.isSigned() && "Expected signed mismatch"); 303 if (I1.isNegative()) 304 return -1; 305 } else { 306 assert(I2.isSigned() && "Expected signed mismatch"); 307 if (I2.isNegative()) 308 return 1; 309 } 310 311 return I1.eq(I2) ? 0 : I1.ugt(I2) ? 1 : -1; 312 } 313 314 static APSInt get(int64_t X) { return APSInt(APInt(64, X), false); } 315 static APSInt getUnsigned(uint64_t X) { return APSInt(APInt(64, X), true); } 316 317 /// Profile - Used to insert APSInt objects, or objects that contain APSInt 318 /// objects, into FoldingSets. 319 void Profile(FoldingSetNodeID& ID) const; 320 }; 321 322 inline bool operator==(int64_t V1, const APSInt &V2) { return V2 == V1; } 323 inline bool operator!=(int64_t V1, const APSInt &V2) { return V2 != V1; } 324 inline bool operator<=(int64_t V1, const APSInt &V2) { return V2 >= V1; } 325 inline bool operator>=(int64_t V1, const APSInt &V2) { return V2 <= V1; } 326 inline bool operator<(int64_t V1, const APSInt &V2) { return V2 > V1; } 327 inline bool operator>(int64_t V1, const APSInt &V2) { return V2 < V1; } 328 329 inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) { 330 I.print(OS, I.isSigned()); 331 return OS; 332 } 333 334 } // end namespace llvm 335 336 #endif 337