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 public: 25 /// Default constructor that creates an uninitialized APInt. APSInt()26 explicit APSInt() : IsUnsigned(false) {} 27 28 /// APSInt ctor - Create an APSInt with the specified width, default to 29 /// unsigned. 30 explicit APSInt(uint32_t BitWidth, bool isUnsigned = true) 31 : APInt(BitWidth, 0), IsUnsigned(isUnsigned) {} 32 33 explicit APSInt(APInt I, bool isUnsigned = true) APInt(std::move (I))34 : APInt(std::move(I)), IsUnsigned(isUnsigned) {} 35 36 /// Construct an APSInt from a string representation. 37 /// 38 /// This constructor interprets the string \p Str using the radix of 10. 39 /// The interpretation stops at the end of the string. The bit width of the 40 /// constructed APSInt is determined automatically. 41 /// 42 /// \param Str the string to be interpreted. 43 explicit APSInt(StringRef Str); 44 45 APSInt &operator=(APInt RHS) { 46 // Retain our current sign. 47 APInt::operator=(std::move(RHS)); 48 return *this; 49 } 50 51 APSInt &operator=(uint64_t RHS) { 52 // Retain our current sign. 53 APInt::operator=(RHS); 54 return *this; 55 } 56 57 // Query sign information. isSigned()58 bool isSigned() const { return !IsUnsigned; } isUnsigned()59 bool isUnsigned() const { return IsUnsigned; } setIsUnsigned(bool Val)60 void setIsUnsigned(bool Val) { IsUnsigned = Val; } setIsSigned(bool Val)61 void setIsSigned(bool Val) { IsUnsigned = !Val; } 62 63 /// toString - Append this APSInt to the specified SmallString. 64 void toString(SmallVectorImpl<char> &Str, unsigned Radix = 10) const { 65 APInt::toString(Str, Radix, isSigned()); 66 } 67 /// toString - Converts an APInt to a std::string. This is an inefficient 68 /// method; you should prefer passing in a SmallString instead. toString(unsigned Radix)69 std::string toString(unsigned Radix) const { 70 return APInt::toString(Radix, isSigned()); 71 } 72 using APInt::toString; 73 74 /// \brief Get the correctly-extended \c int64_t value. getExtValue()75 int64_t getExtValue() const { 76 assert(getMinSignedBits() <= 64 && "Too many bits for int64_t"); 77 return isSigned() ? getSExtValue() : getZExtValue(); 78 } 79 trunc(uint32_t width)80 APSInt LLVM_ATTRIBUTE_UNUSED_RESULT trunc(uint32_t width) const { 81 return APSInt(APInt::trunc(width), IsUnsigned); 82 } 83 extend(uint32_t width)84 APSInt LLVM_ATTRIBUTE_UNUSED_RESULT extend(uint32_t width) const { 85 if (IsUnsigned) 86 return APSInt(zext(width), IsUnsigned); 87 else 88 return APSInt(sext(width), IsUnsigned); 89 } 90 extOrTrunc(uint32_t width)91 APSInt LLVM_ATTRIBUTE_UNUSED_RESULT extOrTrunc(uint32_t width) const { 92 if (IsUnsigned) 93 return APSInt(zextOrTrunc(width), IsUnsigned); 94 else 95 return APSInt(sextOrTrunc(width), IsUnsigned); 96 } 97 98 const APSInt &operator%=(const APSInt &RHS) { 99 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 100 if (IsUnsigned) 101 *this = urem(RHS); 102 else 103 *this = srem(RHS); 104 return *this; 105 } 106 const APSInt &operator/=(const APSInt &RHS) { 107 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 108 if (IsUnsigned) 109 *this = udiv(RHS); 110 else 111 *this = sdiv(RHS); 112 return *this; 113 } 114 APSInt operator%(const APSInt &RHS) const { 115 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 116 return IsUnsigned ? APSInt(urem(RHS), true) : APSInt(srem(RHS), false); 117 } 118 APSInt operator/(const APSInt &RHS) const { 119 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 120 return IsUnsigned ? APSInt(udiv(RHS), true) : APSInt(sdiv(RHS), false); 121 } 122 123 APSInt operator>>(unsigned Amt) const { 124 return IsUnsigned ? APSInt(lshr(Amt), true) : APSInt(ashr(Amt), false); 125 } 126 APSInt& operator>>=(unsigned Amt) { 127 *this = *this >> Amt; 128 return *this; 129 } 130 131 inline bool operator<(const APSInt& RHS) const { 132 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 133 return IsUnsigned ? ult(RHS) : slt(RHS); 134 } 135 inline bool operator>(const APSInt& RHS) const { 136 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 137 return IsUnsigned ? ugt(RHS) : sgt(RHS); 138 } 139 inline bool operator<=(const APSInt& RHS) const { 140 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 141 return IsUnsigned ? ule(RHS) : sle(RHS); 142 } 143 inline bool operator>=(const APSInt& RHS) const { 144 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 145 return IsUnsigned ? uge(RHS) : sge(RHS); 146 } 147 inline bool operator==(const APSInt& RHS) const { 148 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 149 return eq(RHS); 150 } 151 inline bool operator!=(const APSInt& RHS) const { 152 return !((*this) == RHS); 153 } 154 155 bool operator==(int64_t RHS) const { 156 return compareValues(*this, get(RHS)) == 0; 157 } 158 bool operator!=(int64_t RHS) const { 159 return compareValues(*this, get(RHS)) != 0; 160 } 161 bool operator<=(int64_t RHS) const { 162 return compareValues(*this, get(RHS)) <= 0; 163 } 164 bool operator>=(int64_t RHS) const { 165 return compareValues(*this, get(RHS)) >= 0; 166 } 167 bool operator<(int64_t RHS) const { 168 return compareValues(*this, get(RHS)) < 0; 169 } 170 bool operator>(int64_t RHS) const { 171 return compareValues(*this, get(RHS)) > 0; 172 } 173 174 // The remaining operators just wrap the logic of APInt, but retain the 175 // signedness information. 176 177 APSInt operator<<(unsigned Bits) const { 178 return APSInt(static_cast<const APInt&>(*this) << Bits, IsUnsigned); 179 } 180 APSInt& operator<<=(unsigned Amt) { 181 *this = *this << Amt; 182 return *this; 183 } 184 185 APSInt& operator++() { 186 ++(static_cast<APInt&>(*this)); 187 return *this; 188 } 189 APSInt& operator--() { 190 --(static_cast<APInt&>(*this)); 191 return *this; 192 } 193 APSInt operator++(int) { 194 return APSInt(++static_cast<APInt&>(*this), IsUnsigned); 195 } 196 APSInt operator--(int) { 197 return APSInt(--static_cast<APInt&>(*this), IsUnsigned); 198 } 199 APSInt operator-() const { 200 return APSInt(-static_cast<const APInt&>(*this), IsUnsigned); 201 } 202 APSInt& operator+=(const APSInt& RHS) { 203 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 204 static_cast<APInt&>(*this) += RHS; 205 return *this; 206 } 207 APSInt& operator-=(const APSInt& RHS) { 208 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 209 static_cast<APInt&>(*this) -= RHS; 210 return *this; 211 } 212 APSInt& operator*=(const APSInt& RHS) { 213 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 214 static_cast<APInt&>(*this) *= RHS; 215 return *this; 216 } 217 APSInt& operator&=(const APSInt& RHS) { 218 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 219 static_cast<APInt&>(*this) &= RHS; 220 return *this; 221 } 222 APSInt& operator|=(const APSInt& RHS) { 223 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 224 static_cast<APInt&>(*this) |= RHS; 225 return *this; 226 } 227 APSInt& operator^=(const APSInt& RHS) { 228 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 229 static_cast<APInt&>(*this) ^= RHS; 230 return *this; 231 } 232 233 APSInt operator&(const APSInt& RHS) const { 234 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 235 return APSInt(static_cast<const APInt&>(*this) & RHS, IsUnsigned); 236 } And(const APSInt & RHS)237 APSInt LLVM_ATTRIBUTE_UNUSED_RESULT And(const APSInt& RHS) const { 238 return this->operator&(RHS); 239 } 240 241 APSInt operator|(const APSInt& RHS) const { 242 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 243 return APSInt(static_cast<const APInt&>(*this) | RHS, IsUnsigned); 244 } Or(const APSInt & RHS)245 APSInt LLVM_ATTRIBUTE_UNUSED_RESULT Or(const APSInt& RHS) const { 246 return this->operator|(RHS); 247 } 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