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 trunc(uint32_t width)65 APSInt LLVM_ATTRIBUTE_UNUSED_RESULT trunc(uint32_t width) const { 66 return APSInt(APInt::trunc(width), IsUnsigned); 67 } 68 extend(uint32_t width)69 APSInt LLVM_ATTRIBUTE_UNUSED_RESULT extend(uint32_t width) const { 70 if (IsUnsigned) 71 return APSInt(zext(width), IsUnsigned); 72 else 73 return APSInt(sext(width), IsUnsigned); 74 } 75 extOrTrunc(uint32_t width)76 APSInt LLVM_ATTRIBUTE_UNUSED_RESULT extOrTrunc(uint32_t width) const { 77 if (IsUnsigned) 78 return APSInt(zextOrTrunc(width), IsUnsigned); 79 else 80 return APSInt(sextOrTrunc(width), IsUnsigned); 81 } 82 83 const APSInt &operator%=(const APSInt &RHS) { 84 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 85 if (IsUnsigned) 86 *this = urem(RHS); 87 else 88 *this = srem(RHS); 89 return *this; 90 } 91 const APSInt &operator/=(const APSInt &RHS) { 92 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 93 if (IsUnsigned) 94 *this = udiv(RHS); 95 else 96 *this = sdiv(RHS); 97 return *this; 98 } 99 APSInt operator%(const APSInt &RHS) const { 100 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 101 return IsUnsigned ? APSInt(urem(RHS), true) : APSInt(srem(RHS), false); 102 } 103 APSInt operator/(const APSInt &RHS) const { 104 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 105 return IsUnsigned ? APSInt(udiv(RHS), true) : APSInt(sdiv(RHS), false); 106 } 107 108 APSInt operator>>(unsigned Amt) const { 109 return IsUnsigned ? APSInt(lshr(Amt), true) : APSInt(ashr(Amt), false); 110 } 111 APSInt& operator>>=(unsigned Amt) { 112 *this = *this >> Amt; 113 return *this; 114 } 115 116 inline bool operator<(const APSInt& RHS) const { 117 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 118 return IsUnsigned ? ult(RHS) : slt(RHS); 119 } 120 inline bool operator>(const APSInt& RHS) const { 121 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 122 return IsUnsigned ? ugt(RHS) : sgt(RHS); 123 } 124 inline bool operator<=(const APSInt& RHS) const { 125 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 126 return IsUnsigned ? ule(RHS) : sle(RHS); 127 } 128 inline bool operator>=(const APSInt& RHS) const { 129 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 130 return IsUnsigned ? uge(RHS) : sge(RHS); 131 } 132 inline bool operator==(const APSInt& RHS) const { 133 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 134 return eq(RHS); 135 } 136 inline bool operator==(int64_t RHS) const { 137 return isSameValue(*this, APSInt(APInt(64, RHS), true)); 138 } 139 inline bool operator!=(const APSInt& RHS) const { 140 return !((*this) == RHS); 141 } 142 inline bool operator!=(int64_t RHS) const { 143 return !((*this) == RHS); 144 } 145 146 // The remaining operators just wrap the logic of APInt, but retain the 147 // signedness information. 148 149 APSInt operator<<(unsigned Bits) const { 150 return APSInt(static_cast<const APInt&>(*this) << Bits, IsUnsigned); 151 } 152 APSInt& operator<<=(unsigned Amt) { 153 *this = *this << Amt; 154 return *this; 155 } 156 157 APSInt& operator++() { 158 ++(static_cast<APInt&>(*this)); 159 return *this; 160 } 161 APSInt& operator--() { 162 --(static_cast<APInt&>(*this)); 163 return *this; 164 } 165 APSInt operator++(int) { 166 return APSInt(++static_cast<APInt&>(*this), IsUnsigned); 167 } 168 APSInt operator--(int) { 169 return APSInt(--static_cast<APInt&>(*this), IsUnsigned); 170 } 171 APSInt operator-() const { 172 return APSInt(-static_cast<const APInt&>(*this), IsUnsigned); 173 } 174 APSInt& operator+=(const APSInt& RHS) { 175 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 176 static_cast<APInt&>(*this) += RHS; 177 return *this; 178 } 179 APSInt& operator-=(const APSInt& RHS) { 180 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 181 static_cast<APInt&>(*this) -= RHS; 182 return *this; 183 } 184 APSInt& operator*=(const APSInt& RHS) { 185 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 186 static_cast<APInt&>(*this) *= RHS; 187 return *this; 188 } 189 APSInt& operator&=(const APSInt& RHS) { 190 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 191 static_cast<APInt&>(*this) &= RHS; 192 return *this; 193 } 194 APSInt& operator|=(const APSInt& RHS) { 195 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 196 static_cast<APInt&>(*this) |= RHS; 197 return *this; 198 } 199 APSInt& operator^=(const APSInt& RHS) { 200 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 201 static_cast<APInt&>(*this) ^= RHS; 202 return *this; 203 } 204 205 APSInt operator&(const APSInt& RHS) const { 206 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 207 return APSInt(static_cast<const APInt&>(*this) & RHS, IsUnsigned); 208 } And(const APSInt & RHS)209 APSInt LLVM_ATTRIBUTE_UNUSED_RESULT And(const APSInt& RHS) const { 210 return this->operator&(RHS); 211 } 212 213 APSInt operator|(const APSInt& RHS) const { 214 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 215 return APSInt(static_cast<const APInt&>(*this) | RHS, IsUnsigned); 216 } Or(const APSInt & RHS)217 APSInt LLVM_ATTRIBUTE_UNUSED_RESULT Or(const APSInt& RHS) const { 218 return this->operator|(RHS); 219 } 220 221 222 APSInt operator^(const APSInt& RHS) const { 223 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 224 return APSInt(static_cast<const APInt&>(*this) ^ RHS, IsUnsigned); 225 } Xor(const APSInt & RHS)226 APSInt LLVM_ATTRIBUTE_UNUSED_RESULT Xor(const APSInt& RHS) const { 227 return this->operator^(RHS); 228 } 229 230 APSInt operator*(const APSInt& RHS) const { 231 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 232 return APSInt(static_cast<const APInt&>(*this) * RHS, IsUnsigned); 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 operator-(const APSInt& RHS) const { 239 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 240 return APSInt(static_cast<const APInt&>(*this) - RHS, IsUnsigned); 241 } 242 APSInt operator~() const { 243 return APSInt(~static_cast<const APInt&>(*this), IsUnsigned); 244 } 245 246 /// getMaxValue - Return the APSInt representing the maximum integer value 247 /// with the given bit width and signedness. getMaxValue(uint32_t numBits,bool Unsigned)248 static APSInt getMaxValue(uint32_t numBits, bool Unsigned) { 249 return APSInt(Unsigned ? APInt::getMaxValue(numBits) 250 : APInt::getSignedMaxValue(numBits), Unsigned); 251 } 252 253 /// getMinValue - Return the APSInt representing the minimum integer value 254 /// with the given bit width and signedness. getMinValue(uint32_t numBits,bool Unsigned)255 static APSInt getMinValue(uint32_t numBits, bool Unsigned) { 256 return APSInt(Unsigned ? APInt::getMinValue(numBits) 257 : APInt::getSignedMinValue(numBits), Unsigned); 258 } 259 260 /// \brief Determine if two APSInts have the same value, zero- or 261 /// sign-extending as needed. isSameValue(const APSInt & I1,const APSInt & I2)262 static bool isSameValue(const APSInt &I1, const APSInt &I2) { 263 if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned()) 264 return I1 == I2; 265 266 // Check for a bit-width mismatch. 267 if (I1.getBitWidth() > I2.getBitWidth()) 268 return isSameValue(I1, I2.extend(I1.getBitWidth())); 269 else if (I2.getBitWidth() > I1.getBitWidth()) 270 return isSameValue(I1.extend(I2.getBitWidth()), I2); 271 272 // We have a signedness mismatch. Turn the signed value into an unsigned 273 // value. 274 if (I1.isSigned()) { 275 if (I1.isNegative()) 276 return false; 277 278 return APSInt(I1, true) == I2; 279 } 280 281 if (I2.isNegative()) 282 return false; 283 284 return I1 == APSInt(I2, true); 285 } 286 287 /// Profile - Used to insert APSInt objects, or objects that contain APSInt 288 /// objects, into FoldingSets. 289 void Profile(FoldingSetNodeID& ID) const; 290 }; 291 292 inline bool operator==(int64_t V1, const APSInt& V2) { 293 return V2 == V1; 294 } 295 inline bool operator!=(int64_t V1, const APSInt& V2) { 296 return V2 != V1; 297 } 298 299 inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) { 300 I.print(OS, I.isSigned()); 301 return OS; 302 } 303 304 } // end namespace llvm 305 306 #endif 307