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 APSInt : public APInt { 23 bool IsUnsigned; 24 25 public: 26 /// Default constructor that creates an uninitialized APInt. APSInt()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) APInt(std::move (I))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. isSigned()59 bool isSigned() const { return !IsUnsigned; } isUnsigned()60 bool isUnsigned() const { return IsUnsigned; } setIsUnsigned(bool Val)61 void setIsUnsigned(bool Val) { IsUnsigned = Val; } setIsSigned(bool 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. toString(unsigned Radix)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. getExtValue()76 int64_t getExtValue() const { 77 assert(getMinSignedBits() <= 64 && "Too many bits for int64_t"); 78 return isSigned() ? getSExtValue() : getZExtValue(); 79 } 80 trunc(uint32_t width)81 APSInt LLVM_ATTRIBUTE_UNUSED_RESULT trunc(uint32_t width) const { 82 return APSInt(APInt::trunc(width), IsUnsigned); 83 } 84 extend(uint32_t width)85 APSInt LLVM_ATTRIBUTE_UNUSED_RESULT extend(uint32_t width) const { 86 if (IsUnsigned) 87 return APSInt(zext(width), IsUnsigned); 88 else 89 return APSInt(sext(width), IsUnsigned); 90 } 91 extOrTrunc(uint32_t width)92 APSInt LLVM_ATTRIBUTE_UNUSED_RESULT 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 } And(const APSInt & RHS)238 APSInt LLVM_ATTRIBUTE_UNUSED_RESULT And(const APSInt& RHS) const { 239 return this->operator&(RHS); 240 } 241 242 APSInt operator|(const APSInt& RHS) const { 243 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 244 return APSInt(static_cast<const APInt&>(*this) | RHS, IsUnsigned); 245 } Or(const APSInt & RHS)246 APSInt LLVM_ATTRIBUTE_UNUSED_RESULT Or(const APSInt& RHS) const { 247 return this->operator|(RHS); 248 } 249 250 APSInt operator^(const APSInt &RHS) const { 251 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 252 return APSInt(static_cast<const APInt&>(*this) ^ RHS, IsUnsigned); 253 } Xor(const APSInt & RHS)254 APSInt LLVM_ATTRIBUTE_UNUSED_RESULT Xor(const APSInt& RHS) const { 255 return this->operator^(RHS); 256 } 257 258 APSInt operator*(const APSInt& RHS) const { 259 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 260 return APSInt(static_cast<const APInt&>(*this) * RHS, IsUnsigned); 261 } 262 APSInt operator+(const APSInt& RHS) const { 263 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 264 return APSInt(static_cast<const APInt&>(*this) + RHS, IsUnsigned); 265 } 266 APSInt operator-(const APSInt& RHS) const { 267 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 268 return APSInt(static_cast<const APInt&>(*this) - RHS, IsUnsigned); 269 } 270 APSInt operator~() const { 271 return APSInt(~static_cast<const APInt&>(*this), IsUnsigned); 272 } 273 274 /// getMaxValue - Return the APSInt representing the maximum integer value 275 /// with the given bit width and signedness. getMaxValue(uint32_t numBits,bool Unsigned)276 static APSInt getMaxValue(uint32_t numBits, bool Unsigned) { 277 return APSInt(Unsigned ? APInt::getMaxValue(numBits) 278 : APInt::getSignedMaxValue(numBits), Unsigned); 279 } 280 281 /// getMinValue - Return the APSInt representing the minimum integer value 282 /// with the given bit width and signedness. getMinValue(uint32_t numBits,bool Unsigned)283 static APSInt getMinValue(uint32_t numBits, bool Unsigned) { 284 return APSInt(Unsigned ? APInt::getMinValue(numBits) 285 : APInt::getSignedMinValue(numBits), Unsigned); 286 } 287 288 /// \brief Determine if two APSInts have the same value, zero- or 289 /// sign-extending as needed. isSameValue(const APSInt & I1,const APSInt & I2)290 static bool isSameValue(const APSInt &I1, const APSInt &I2) { 291 return !compareValues(I1, I2); 292 } 293 294 /// \brief Compare underlying values of two numbers. compareValues(const APSInt & I1,const APSInt & I2)295 static int compareValues(const APSInt &I1, const APSInt &I2) { 296 if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned()) 297 return I1 == I2 ? 0 : I1 > I2 ? 1 : -1; 298 299 // Check for a bit-width mismatch. 300 if (I1.getBitWidth() > I2.getBitWidth()) 301 return compareValues(I1, I2.extend(I1.getBitWidth())); 302 else if (I2.getBitWidth() > I1.getBitWidth()) 303 return compareValues(I1.extend(I2.getBitWidth()), I2); 304 305 // We have a signedness mismatch. Check for negative values and do an 306 // unsigned compare if both are positive. 307 if (I1.isSigned()) { 308 assert(!I2.isSigned() && "Expected signed mismatch"); 309 if (I1.isNegative()) 310 return -1; 311 } else { 312 assert(I2.isSigned() && "Expected signed mismatch"); 313 if (I2.isNegative()) 314 return 1; 315 } 316 317 return I1.eq(I2) ? 0 : I1.ugt(I2) ? 1 : -1; 318 } 319 get(int64_t X)320 static APSInt get(int64_t X) { return APSInt(APInt(64, X), false); } getUnsigned(uint64_t X)321 static APSInt getUnsigned(uint64_t X) { return APSInt(APInt(64, X), true); } 322 323 /// Profile - Used to insert APSInt objects, or objects that contain APSInt 324 /// objects, into FoldingSets. 325 void Profile(FoldingSetNodeID& ID) const; 326 }; 327 328 inline bool operator==(int64_t V1, const APSInt &V2) { return V2 == V1; } 329 inline bool operator!=(int64_t V1, const APSInt &V2) { return V2 != V1; } 330 inline bool operator<=(int64_t V1, const APSInt &V2) { return V2 >= V1; } 331 inline bool operator>=(int64_t V1, const APSInt &V2) { return V2 <= V1; } 332 inline bool operator<(int64_t V1, const APSInt &V2) { return V2 > V1; } 333 inline bool operator>(int64_t V1, const APSInt &V2) { return V2 < V1; } 334 335 inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) { 336 I.print(OS, I.isSigned()); 337 return OS; 338 } 339 340 } // end namespace llvm 341 342 #endif 343