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_APSINT_H 16 #define LLVM_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. 26 explicit APSInt() {} 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) 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. 55 bool isSigned() const { return !IsUnsigned; } 56 bool isUnsigned() const { return IsUnsigned; } 57 void setIsUnsigned(bool Val) { IsUnsigned = 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. 66 std::string toString(unsigned Radix) const { 67 return APInt::toString(Radix, isSigned()); 68 } 69 using APInt::toString; 70 71 APSInt trunc(uint32_t width) const { 72 return APSInt(APInt::trunc(width), IsUnsigned); 73 } 74 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 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 139 // The remaining operators just wrap the logic of APInt, but retain the 140 // signedness information. 141 142 APSInt operator<<(unsigned Bits) const { 143 return APSInt(static_cast<const APInt&>(*this) << Bits, IsUnsigned); 144 } 145 APSInt& operator<<=(unsigned Amt) { 146 *this = *this << Amt; 147 return *this; 148 } 149 150 APSInt& operator++() { 151 static_cast<APInt&>(*this)++; 152 return *this; 153 } 154 APSInt& operator--() { 155 static_cast<APInt&>(*this)--; 156 return *this; 157 } 158 APSInt operator++(int) { 159 return APSInt(++static_cast<APInt&>(*this), IsUnsigned); 160 } 161 APSInt operator--(int) { 162 return APSInt(--static_cast<APInt&>(*this), IsUnsigned); 163 } 164 APSInt operator-() const { 165 return APSInt(-static_cast<const APInt&>(*this), IsUnsigned); 166 } 167 APSInt& operator+=(const APSInt& RHS) { 168 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 169 static_cast<APInt&>(*this) += RHS; 170 return *this; 171 } 172 APSInt& operator-=(const APSInt& RHS) { 173 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 174 static_cast<APInt&>(*this) -= RHS; 175 return *this; 176 } 177 APSInt& operator*=(const APSInt& RHS) { 178 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 179 static_cast<APInt&>(*this) *= RHS; 180 return *this; 181 } 182 APSInt& operator&=(const APSInt& RHS) { 183 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 184 static_cast<APInt&>(*this) &= RHS; 185 return *this; 186 } 187 APSInt& operator|=(const APSInt& RHS) { 188 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 189 static_cast<APInt&>(*this) |= RHS; 190 return *this; 191 } 192 APSInt& operator^=(const APSInt& RHS) { 193 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 194 static_cast<APInt&>(*this) ^= RHS; 195 return *this; 196 } 197 198 APSInt operator&(const APSInt& RHS) const { 199 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 200 return APSInt(static_cast<const APInt&>(*this) & RHS, IsUnsigned); 201 } 202 APSInt And(const APSInt& RHS) const { 203 return this->operator&(RHS); 204 } 205 206 APSInt operator|(const APSInt& RHS) const { 207 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 208 return APSInt(static_cast<const APInt&>(*this) | RHS, IsUnsigned); 209 } 210 APSInt Or(const APSInt& RHS) const { 211 return this->operator|(RHS); 212 } 213 214 215 APSInt operator^(const APSInt& RHS) const { 216 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 217 return APSInt(static_cast<const APInt&>(*this) ^ RHS, IsUnsigned); 218 } 219 APSInt Xor(const APSInt& RHS) const { 220 return this->operator^(RHS); 221 } 222 223 APSInt operator*(const APSInt& RHS) const { 224 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 225 return APSInt(static_cast<const APInt&>(*this) * RHS, IsUnsigned); 226 } 227 APSInt operator+(const APSInt& RHS) const { 228 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 229 return APSInt(static_cast<const APInt&>(*this) + RHS, IsUnsigned); 230 } 231 APSInt operator-(const APSInt& RHS) const { 232 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 233 return APSInt(static_cast<const APInt&>(*this) - RHS, IsUnsigned); 234 } 235 APSInt operator~() const { 236 return APSInt(~static_cast<const APInt&>(*this), IsUnsigned); 237 } 238 239 /// getMaxValue - Return the APSInt representing the maximum integer value 240 /// with the given bit width and signedness. 241 static APSInt getMaxValue(uint32_t numBits, bool Unsigned) { 242 return APSInt(Unsigned ? APInt::getMaxValue(numBits) 243 : APInt::getSignedMaxValue(numBits), Unsigned); 244 } 245 246 /// getMinValue - Return the APSInt representing the minimum integer value 247 /// with the given bit width and signedness. 248 static APSInt getMinValue(uint32_t numBits, bool Unsigned) { 249 return APSInt(Unsigned ? APInt::getMinValue(numBits) 250 : APInt::getSignedMinValue(numBits), Unsigned); 251 } 252 253 /// Profile - Used to insert APSInt objects, or objects that contain APSInt 254 /// objects, into FoldingSets. 255 void Profile(FoldingSetNodeID& ID) const; 256 }; 257 258 inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) { 259 I.print(OS, I.isSigned()); 260 return OS; 261 } 262 263 264 } // end namespace llvm 265 266 #endif 267