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(const APInt &I, bool isUnsigned = true) APInt(I)34 : APInt(I), IsUnsigned(isUnsigned) {} 35 36 APSInt &operator=(const APSInt &RHS) { 37 APInt::operator=(RHS); 38 IsUnsigned = RHS.IsUnsigned; 39 return *this; 40 } 41 42 APSInt &operator=(const APInt &RHS) { 43 // Retain our current sign. 44 APInt::operator=(RHS); 45 return *this; 46 } 47 48 APSInt &operator=(uint64_t RHS) { 49 // Retain our current sign. 50 APInt::operator=(RHS); 51 return *this; 52 } 53 54 // Query sign information. isSigned()55 bool isSigned() const { return !IsUnsigned; } isUnsigned()56 bool isUnsigned() const { return IsUnsigned; } setIsUnsigned(bool Val)57 void setIsUnsigned(bool Val) { IsUnsigned = Val; } setIsSigned(bool Val)58 void setIsSigned(bool Val) { IsUnsigned = !Val; } 59 60 /// toString - Append this APSInt to the specified SmallString. 61 void toString(SmallVectorImpl<char> &Str, unsigned Radix = 10) const { 62 APInt::toString(Str, Radix, isSigned()); 63 } 64 /// toString - Converts an APInt to a std::string. This is an inefficient 65 /// method, your should prefer passing in a SmallString instead. toString(unsigned Radix)66 std::string toString(unsigned Radix) const { 67 return APInt::toString(Radix, isSigned()); 68 } 69 using APInt::toString; 70 trunc(uint32_t width)71 APSInt trunc(uint32_t width) const { 72 return APSInt(APInt::trunc(width), IsUnsigned); 73 } 74 extend(uint32_t width)75 APSInt 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 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==(int64_t RHS) const { 143 return isSameValue(*this, APSInt(APInt(64, RHS), true)); 144 } 145 inline bool operator!=(const APSInt& RHS) const { 146 return !((*this) == RHS); 147 } 148 inline bool operator!=(int64_t RHS) const { 149 return !((*this) == RHS); 150 } 151 152 // The remaining operators just wrap the logic of APInt, but retain the 153 // signedness information. 154 155 APSInt operator<<(unsigned Bits) const { 156 return APSInt(static_cast<const APInt&>(*this) << Bits, IsUnsigned); 157 } 158 APSInt& operator<<=(unsigned Amt) { 159 *this = *this << Amt; 160 return *this; 161 } 162 163 APSInt& operator++() { 164 static_cast<APInt&>(*this)++; 165 return *this; 166 } 167 APSInt& operator--() { 168 static_cast<APInt&>(*this)--; 169 return *this; 170 } 171 APSInt operator++(int) { 172 return APSInt(++static_cast<APInt&>(*this), IsUnsigned); 173 } 174 APSInt operator--(int) { 175 return APSInt(--static_cast<APInt&>(*this), IsUnsigned); 176 } 177 APSInt operator-() const { 178 return APSInt(-static_cast<const APInt&>(*this), IsUnsigned); 179 } 180 APSInt& operator+=(const APSInt& RHS) { 181 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 182 static_cast<APInt&>(*this) += RHS; 183 return *this; 184 } 185 APSInt& operator-=(const APSInt& RHS) { 186 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 187 static_cast<APInt&>(*this) -= RHS; 188 return *this; 189 } 190 APSInt& operator*=(const APSInt& RHS) { 191 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 192 static_cast<APInt&>(*this) *= RHS; 193 return *this; 194 } 195 APSInt& operator&=(const APSInt& RHS) { 196 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 197 static_cast<APInt&>(*this) &= RHS; 198 return *this; 199 } 200 APSInt& operator|=(const APSInt& RHS) { 201 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 202 static_cast<APInt&>(*this) |= RHS; 203 return *this; 204 } 205 APSInt& operator^=(const APSInt& RHS) { 206 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 207 static_cast<APInt&>(*this) ^= RHS; 208 return *this; 209 } 210 211 APSInt operator&(const APSInt& RHS) const { 212 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 213 return APSInt(static_cast<const APInt&>(*this) & RHS, IsUnsigned); 214 } And(const APSInt & RHS)215 APSInt And(const APSInt& RHS) const { 216 return this->operator&(RHS); 217 } 218 219 APSInt operator|(const APSInt& RHS) const { 220 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 221 return APSInt(static_cast<const APInt&>(*this) | RHS, IsUnsigned); 222 } Or(const APSInt & RHS)223 APSInt Or(const APSInt& RHS) const { 224 return this->operator|(RHS); 225 } 226 227 228 APSInt operator^(const APSInt& RHS) const { 229 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 230 return APSInt(static_cast<const APInt&>(*this) ^ RHS, IsUnsigned); 231 } Xor(const APSInt & RHS)232 APSInt Xor(const APSInt& RHS) const { 233 return this->operator^(RHS); 234 } 235 236 APSInt operator*(const APSInt& RHS) const { 237 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 238 return APSInt(static_cast<const APInt&>(*this) * RHS, IsUnsigned); 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 operator-(const APSInt& RHS) const { 245 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 246 return APSInt(static_cast<const APInt&>(*this) - RHS, IsUnsigned); 247 } 248 APSInt operator~() const { 249 return APSInt(~static_cast<const APInt&>(*this), IsUnsigned); 250 } 251 252 /// getMaxValue - Return the APSInt representing the maximum integer value 253 /// with the given bit width and signedness. getMaxValue(uint32_t numBits,bool Unsigned)254 static APSInt getMaxValue(uint32_t numBits, bool Unsigned) { 255 return APSInt(Unsigned ? APInt::getMaxValue(numBits) 256 : APInt::getSignedMaxValue(numBits), Unsigned); 257 } 258 259 /// getMinValue - Return the APSInt representing the minimum integer value 260 /// with the given bit width and signedness. getMinValue(uint32_t numBits,bool Unsigned)261 static APSInt getMinValue(uint32_t numBits, bool Unsigned) { 262 return APSInt(Unsigned ? APInt::getMinValue(numBits) 263 : APInt::getSignedMinValue(numBits), Unsigned); 264 } 265 266 /// \brief Determine if two APSInts have the same value, zero- or 267 /// sign-extending as needed. isSameValue(const APSInt & I1,const APSInt & I2)268 static bool isSameValue(const APSInt &I1, const APSInt &I2) { 269 if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned()) 270 return I1 == I2; 271 272 // Check for a bit-width mismatch. 273 if (I1.getBitWidth() > I2.getBitWidth()) 274 return isSameValue(I1, I2.extend(I1.getBitWidth())); 275 else if (I2.getBitWidth() > I1.getBitWidth()) 276 return isSameValue(I1.extend(I2.getBitWidth()), I2); 277 278 // We have a signedness mismatch. Turn the signed value into an unsigned 279 // value. 280 if (I1.isSigned()) { 281 if (I1.isNegative()) 282 return false; 283 284 return APSInt(I1, true) == I2; 285 } 286 287 if (I2.isNegative()) 288 return false; 289 290 return I1 == APSInt(I2, true); 291 } 292 293 /// Profile - Used to insert APSInt objects, or objects that contain APSInt 294 /// objects, into FoldingSets. 295 void Profile(FoldingSetNodeID& ID) const; 296 }; 297 298 inline bool operator==(int64_t V1, const APSInt& V2) { 299 return V2 == V1; 300 } 301 inline bool operator!=(int64_t V1, const APSInt& V2) { 302 return V2 != V1; 303 } 304 305 inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) { 306 I.print(OS, I.isSigned()); 307 return OS; 308 } 309 310 } // end namespace llvm 311 312 #endif 313