LLVM API Documentation
00001 //===-- llvm/ADT/APSInt.h - Arbitrary Precision Signed Int -----*- C++ -*--===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the APSInt class, which is a simple class that 00011 // represents an arbitrary sized integer that knows its signedness. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #ifndef LLVM_ADT_APSINT_H 00016 #define LLVM_ADT_APSINT_H 00017 00018 #include "llvm/ADT/APInt.h" 00019 00020 namespace llvm { 00021 00022 class APSInt : public APInt { 00023 bool IsUnsigned; 00024 public: 00025 /// Default constructor that creates an uninitialized APInt. 00026 explicit APSInt() : IsUnsigned(false) {} 00027 00028 /// APSInt ctor - Create an APSInt with the specified width, default to 00029 /// unsigned. 00030 explicit APSInt(uint32_t BitWidth, bool isUnsigned = true) 00031 : APInt(BitWidth, 0), IsUnsigned(isUnsigned) {} 00032 00033 explicit APSInt(APInt I, bool isUnsigned = true) 00034 : APInt(std::move(I)), IsUnsigned(isUnsigned) {} 00035 00036 APSInt &operator=(APInt RHS) { 00037 // Retain our current sign. 00038 APInt::operator=(std::move(RHS)); 00039 return *this; 00040 } 00041 00042 APSInt &operator=(uint64_t RHS) { 00043 // Retain our current sign. 00044 APInt::operator=(RHS); 00045 return *this; 00046 } 00047 00048 // Query sign information. 00049 bool isSigned() const { return !IsUnsigned; } 00050 bool isUnsigned() const { return IsUnsigned; } 00051 void setIsUnsigned(bool Val) { IsUnsigned = Val; } 00052 void setIsSigned(bool Val) { IsUnsigned = !Val; } 00053 00054 /// toString - Append this APSInt to the specified SmallString. 00055 void toString(SmallVectorImpl<char> &Str, unsigned Radix = 10) const { 00056 APInt::toString(Str, Radix, isSigned()); 00057 } 00058 /// toString - Converts an APInt to a std::string. This is an inefficient 00059 /// method; you should prefer passing in a SmallString instead. 00060 std::string toString(unsigned Radix) const { 00061 return APInt::toString(Radix, isSigned()); 00062 } 00063 using APInt::toString; 00064 00065 APSInt LLVM_ATTRIBUTE_UNUSED_RESULT trunc(uint32_t width) const { 00066 return APSInt(APInt::trunc(width), IsUnsigned); 00067 } 00068 00069 APSInt LLVM_ATTRIBUTE_UNUSED_RESULT extend(uint32_t width) const { 00070 if (IsUnsigned) 00071 return APSInt(zext(width), IsUnsigned); 00072 else 00073 return APSInt(sext(width), IsUnsigned); 00074 } 00075 00076 APSInt LLVM_ATTRIBUTE_UNUSED_RESULT extOrTrunc(uint32_t width) const { 00077 if (IsUnsigned) 00078 return APSInt(zextOrTrunc(width), IsUnsigned); 00079 else 00080 return APSInt(sextOrTrunc(width), IsUnsigned); 00081 } 00082 00083 const APSInt &operator%=(const APSInt &RHS) { 00084 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 00085 if (IsUnsigned) 00086 *this = urem(RHS); 00087 else 00088 *this = srem(RHS); 00089 return *this; 00090 } 00091 const APSInt &operator/=(const APSInt &RHS) { 00092 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 00093 if (IsUnsigned) 00094 *this = udiv(RHS); 00095 else 00096 *this = sdiv(RHS); 00097 return *this; 00098 } 00099 APSInt operator%(const APSInt &RHS) const { 00100 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 00101 return IsUnsigned ? APSInt(urem(RHS), true) : APSInt(srem(RHS), false); 00102 } 00103 APSInt operator/(const APSInt &RHS) const { 00104 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 00105 return IsUnsigned ? APSInt(udiv(RHS), true) : APSInt(sdiv(RHS), false); 00106 } 00107 00108 APSInt operator>>(unsigned Amt) const { 00109 return IsUnsigned ? APSInt(lshr(Amt), true) : APSInt(ashr(Amt), false); 00110 } 00111 APSInt& operator>>=(unsigned Amt) { 00112 *this = *this >> Amt; 00113 return *this; 00114 } 00115 00116 inline bool operator<(const APSInt& RHS) const { 00117 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 00118 return IsUnsigned ? ult(RHS) : slt(RHS); 00119 } 00120 inline bool operator>(const APSInt& RHS) const { 00121 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 00122 return IsUnsigned ? ugt(RHS) : sgt(RHS); 00123 } 00124 inline bool operator<=(const APSInt& RHS) const { 00125 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 00126 return IsUnsigned ? ule(RHS) : sle(RHS); 00127 } 00128 inline bool operator>=(const APSInt& RHS) const { 00129 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 00130 return IsUnsigned ? uge(RHS) : sge(RHS); 00131 } 00132 inline bool operator==(const APSInt& RHS) const { 00133 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 00134 return eq(RHS); 00135 } 00136 inline bool operator==(int64_t RHS) const { 00137 return isSameValue(*this, APSInt(APInt(64, RHS), true)); 00138 } 00139 inline bool operator!=(const APSInt& RHS) const { 00140 return !((*this) == RHS); 00141 } 00142 inline bool operator!=(int64_t RHS) const { 00143 return !((*this) == RHS); 00144 } 00145 00146 // The remaining operators just wrap the logic of APInt, but retain the 00147 // signedness information. 00148 00149 APSInt operator<<(unsigned Bits) const { 00150 return APSInt(static_cast<const APInt&>(*this) << Bits, IsUnsigned); 00151 } 00152 APSInt& operator<<=(unsigned Amt) { 00153 *this = *this << Amt; 00154 return *this; 00155 } 00156 00157 APSInt& operator++() { 00158 ++(static_cast<APInt&>(*this)); 00159 return *this; 00160 } 00161 APSInt& operator--() { 00162 --(static_cast<APInt&>(*this)); 00163 return *this; 00164 } 00165 APSInt operator++(int) { 00166 return APSInt(++static_cast<APInt&>(*this), IsUnsigned); 00167 } 00168 APSInt operator--(int) { 00169 return APSInt(--static_cast<APInt&>(*this), IsUnsigned); 00170 } 00171 APSInt operator-() const { 00172 return APSInt(-static_cast<const APInt&>(*this), IsUnsigned); 00173 } 00174 APSInt& operator+=(const APSInt& RHS) { 00175 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 00176 static_cast<APInt&>(*this) += RHS; 00177 return *this; 00178 } 00179 APSInt& operator-=(const APSInt& RHS) { 00180 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 00181 static_cast<APInt&>(*this) -= RHS; 00182 return *this; 00183 } 00184 APSInt& operator*=(const APSInt& RHS) { 00185 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 00186 static_cast<APInt&>(*this) *= RHS; 00187 return *this; 00188 } 00189 APSInt& operator&=(const APSInt& RHS) { 00190 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 00191 static_cast<APInt&>(*this) &= RHS; 00192 return *this; 00193 } 00194 APSInt& operator|=(const APSInt& RHS) { 00195 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 00196 static_cast<APInt&>(*this) |= RHS; 00197 return *this; 00198 } 00199 APSInt& operator^=(const APSInt& RHS) { 00200 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 00201 static_cast<APInt&>(*this) ^= RHS; 00202 return *this; 00203 } 00204 00205 APSInt operator&(const APSInt& RHS) const { 00206 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 00207 return APSInt(static_cast<const APInt&>(*this) & RHS, IsUnsigned); 00208 } 00209 APSInt LLVM_ATTRIBUTE_UNUSED_RESULT And(const APSInt& RHS) const { 00210 return this->operator&(RHS); 00211 } 00212 00213 APSInt operator|(const APSInt& RHS) const { 00214 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 00215 return APSInt(static_cast<const APInt&>(*this) | RHS, IsUnsigned); 00216 } 00217 APSInt LLVM_ATTRIBUTE_UNUSED_RESULT Or(const APSInt& RHS) const { 00218 return this->operator|(RHS); 00219 } 00220 00221 00222 APSInt operator^(const APSInt& RHS) const { 00223 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 00224 return APSInt(static_cast<const APInt&>(*this) ^ RHS, IsUnsigned); 00225 } 00226 APSInt LLVM_ATTRIBUTE_UNUSED_RESULT Xor(const APSInt& RHS) const { 00227 return this->operator^(RHS); 00228 } 00229 00230 APSInt operator*(const APSInt& RHS) const { 00231 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 00232 return APSInt(static_cast<const APInt&>(*this) * RHS, IsUnsigned); 00233 } 00234 APSInt operator+(const APSInt& RHS) const { 00235 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 00236 return APSInt(static_cast<const APInt&>(*this) + RHS, IsUnsigned); 00237 } 00238 APSInt operator-(const APSInt& RHS) const { 00239 assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 00240 return APSInt(static_cast<const APInt&>(*this) - RHS, IsUnsigned); 00241 } 00242 APSInt operator~() const { 00243 return APSInt(~static_cast<const APInt&>(*this), IsUnsigned); 00244 } 00245 00246 /// getMaxValue - Return the APSInt representing the maximum integer value 00247 /// with the given bit width and signedness. 00248 static APSInt getMaxValue(uint32_t numBits, bool Unsigned) { 00249 return APSInt(Unsigned ? APInt::getMaxValue(numBits) 00250 : APInt::getSignedMaxValue(numBits), Unsigned); 00251 } 00252 00253 /// getMinValue - Return the APSInt representing the minimum integer value 00254 /// with the given bit width and signedness. 00255 static APSInt getMinValue(uint32_t numBits, bool Unsigned) { 00256 return APSInt(Unsigned ? APInt::getMinValue(numBits) 00257 : APInt::getSignedMinValue(numBits), Unsigned); 00258 } 00259 00260 /// \brief Determine if two APSInts have the same value, zero- or 00261 /// sign-extending as needed. 00262 static bool isSameValue(const APSInt &I1, const APSInt &I2) { 00263 if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned()) 00264 return I1 == I2; 00265 00266 // Check for a bit-width mismatch. 00267 if (I1.getBitWidth() > I2.getBitWidth()) 00268 return isSameValue(I1, I2.extend(I1.getBitWidth())); 00269 else if (I2.getBitWidth() > I1.getBitWidth()) 00270 return isSameValue(I1.extend(I2.getBitWidth()), I2); 00271 00272 // We have a signedness mismatch. Turn the signed value into an unsigned 00273 // value. 00274 if (I1.isSigned()) { 00275 if (I1.isNegative()) 00276 return false; 00277 00278 return APSInt(I1, true) == I2; 00279 } 00280 00281 if (I2.isNegative()) 00282 return false; 00283 00284 return I1 == APSInt(I2, true); 00285 } 00286 00287 /// Profile - Used to insert APSInt objects, or objects that contain APSInt 00288 /// objects, into FoldingSets. 00289 void Profile(FoldingSetNodeID& ID) const; 00290 }; 00291 00292 inline bool operator==(int64_t V1, const APSInt& V2) { 00293 return V2 == V1; 00294 } 00295 inline bool operator!=(int64_t V1, const APSInt& V2) { 00296 return V2 != V1; 00297 } 00298 00299 inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) { 00300 I.print(OS, I.isSigned()); 00301 return OS; 00302 } 00303 00304 } // end namespace llvm 00305 00306 #endif