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 20namespace llvm { 21 22class LLVM_NODISCARD APSInt : public APInt { 23 bool IsUnsigned; 24 25public: 26 /// Default constructor that creates an uninitialized APInt. 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) 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. 59 bool isSigned() const { return !IsUnsigned; } 60 bool isUnsigned() const { return IsUnsigned; } 61 void setIsUnsigned(bool Val) { IsUnsigned = 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. 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. 76 int64_t getExtValue() const { 77 assert(getMinSignedBits() <= 64 && "Too many bits for int64_t"); 78 return isSigned() ? getSExtValue() : getZExtValue(); 79 } 80 81 APSInt trunc(uint32_t width) const { 82 return APSInt(APInt::trunc(width), IsUnsigned); 83 } 84 85 APSInt extend(uint32_t width) const { 86 if (IsUnsigned) 87 return APSInt(zext(width), IsUnsigned); 88 else 89 return APSInt(sext(width), IsUnsigned); 90 } 91 92 APSInt 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 if (IsUnsigned) 129 lshrInPlace(Amt); 130 else 131 ashrInPlace(Amt); 132 return *this; 133 } 134 135 inline bool operator<(const APSInt& RHS) const { 136 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 137 return IsUnsigned ? ult(RHS) : slt(RHS); 138 } 139 inline bool operator>(const APSInt& RHS) const { 140 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 141 return IsUnsigned ? ugt(RHS) : sgt(RHS); 142 } 143 inline bool operator<=(const APSInt& RHS) const { 144 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 145 return IsUnsigned ? ule(RHS) : sle(RHS); 146 } 147 inline bool operator>=(const APSInt& RHS) const { 148 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 149 return IsUnsigned ? uge(RHS) : sge(RHS); 150 } 151 inline bool operator==(const APSInt& RHS) const { 152 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 153 return eq(RHS); 154 } 155 inline bool operator!=(const APSInt& RHS) const { 156 return !((*this) == RHS); 157 } 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 bool operator>(int64_t RHS) const { 175 return compareValues(*this, get(RHS)) > 0; 176 } 177 178 // The remaining operators just wrap the logic of APInt, but retain the 179 // signedness information. 180 181 APSInt operator<<(unsigned Bits) const { 182 return APSInt(static_cast<const APInt&>(*this) << Bits, IsUnsigned); 183 } 184 APSInt& operator<<=(unsigned Amt) { 185 static_cast<APInt&>(*this) <<= Amt; 186 return *this; 187 } 188 189 APSInt& operator++() { 190 ++(static_cast<APInt&>(*this)); 191 return *this; 192 } 193 APSInt& operator--() { 194 --(static_cast<APInt&>(*this)); 195 return *this; 196 } 197 APSInt operator++(int) { 198 return APSInt(++static_cast<APInt&>(*this), IsUnsigned); 199 } 200 APSInt operator--(int) { 201 return APSInt(--static_cast<APInt&>(*this), IsUnsigned); 202 } 203 APSInt operator-() const { 204 return APSInt(-static_cast<const APInt&>(*this), IsUnsigned); 205 } 206 APSInt& operator+=(const APSInt& RHS) { 207 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 208 static_cast<APInt&>(*this) += RHS; 209 return *this; 210 } 211 APSInt& operator-=(const APSInt& RHS) { 212 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 213 static_cast<APInt&>(*this) -= RHS; 214 return *this; 215 } 216 APSInt& operator*=(const APSInt& RHS) { 217 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 218 static_cast<APInt&>(*this) *= RHS; 219 return *this; 220 } 221 APSInt& operator&=(const APSInt& RHS) { 222 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 223 static_cast<APInt&>(*this) &= RHS; 224 return *this; 225 } 226 APSInt& operator|=(const APSInt& RHS) { 227 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 228 static_cast<APInt&>(*this) |= RHS; 229 return *this; 230 } 231 APSInt& operator^=(const APSInt& RHS) { 232 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 233 static_cast<APInt&>(*this) ^= RHS; 234 return *this; 235 } 236 237 APSInt operator&(const APSInt& RHS) const { 238 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 239 return APSInt(static_cast<const APInt&>(*this) & RHS, IsUnsigned); 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 } 246 247 APSInt operator^(const APSInt &RHS) const { 248 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 249 return APSInt(static_cast<const APInt&>(*this) ^ RHS, IsUnsigned); 250 } 251 252 APSInt operator*(const APSInt& RHS) const { 253 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 254 return APSInt(static_cast<const APInt&>(*this) * RHS, IsUnsigned); 255 } 256 APSInt operator+(const APSInt& RHS) const { 257 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 258 return APSInt(static_cast<const APInt&>(*this) + RHS, IsUnsigned); 259 } 260 APSInt operator-(const APSInt& RHS) const { 261 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 262 return APSInt(static_cast<const APInt&>(*this) - RHS, IsUnsigned); 263 } 264 APSInt operator~() const { 265 return APSInt(~static_cast<const APInt&>(*this), IsUnsigned); 266 } 267 268 /// getMaxValue - Return the APSInt representing the maximum integer value 269 /// with the given bit width and signedness. 270 static APSInt getMaxValue(uint32_t numBits, bool Unsigned) { 271 return APSInt(Unsigned ? APInt::getMaxValue(numBits) 272 : APInt::getSignedMaxValue(numBits), Unsigned); 273 } 274 275 /// getMinValue - Return the APSInt representing the minimum integer value 276 /// with the given bit width and signedness. 277 static APSInt getMinValue(uint32_t numBits, bool Unsigned) { 278 return APSInt(Unsigned ? APInt::getMinValue(numBits) 279 : APInt::getSignedMinValue(numBits), Unsigned); 280 } 281 282 /// \brief Determine if two APSInts have the same value, zero- or 283 /// sign-extending as needed. 284 static bool isSameValue(const APSInt &I1, const APSInt &I2) { 285 return !compareValues(I1, I2); 286 } 287 288 /// \brief Compare underlying values of two numbers. 289 static int compareValues(const APSInt &I1, const APSInt &I2) { 290 if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned()) 291 return I1.IsUnsigned ? I1.compare(I2) : I1.compareSigned(I2); 292 293 // Check for a bit-width mismatch. 294 if (I1.getBitWidth() > I2.getBitWidth()) 295 return compareValues(I1, I2.extend(I1.getBitWidth())); 296 if (I2.getBitWidth() > I1.getBitWidth()) 297 return compareValues(I1.extend(I2.getBitWidth()), I2); 298 299 // We have a signedness mismatch. Check for negative values and do an 300 // unsigned compare if both are positive. 301 if (I1.isSigned()) { 302 assert(!I2.isSigned() && "Expected signed mismatch"); 303 if (I1.isNegative()) 304 return -1; 305 } else { 306 assert(I2.isSigned() && "Expected signed mismatch"); 307 if (I2.isNegative()) 308 return 1; 309 } 310 311 return I1.compare(I2); 312 } 313 314 static APSInt get(int64_t X) { return APSInt(APInt(64, X), false); } 315 static APSInt getUnsigned(uint64_t X) { return APSInt(APInt(64, X), true); } 316 317 /// Profile - Used to insert APSInt objects, or objects that contain APSInt 318 /// objects, into FoldingSets. 319 void Profile(FoldingSetNodeID& ID) const; 320}; 321 322inline bool operator==(int64_t V1, const APSInt &V2) { return V2 == V1; } 323inline bool operator!=(int64_t V1, const APSInt &V2) { return V2 != V1; } 324inline bool operator<=(int64_t V1, const APSInt &V2) { return V2 >= V1; } 325inline bool operator>=(int64_t V1, const APSInt &V2) { return V2 <= V1; } 326inline bool operator<(int64_t V1, const APSInt &V2) { return V2 > V1; } 327inline bool operator>(int64_t V1, const APSInt &V2) { return V2 < V1; } 328 329inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) { 330 I.print(OS, I.isSigned()); 331 return OS; 332} 333 334} // end namespace llvm 335 336#endif 337