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