1193323Sed//===-- llvm/ADT/APSInt.h - Arbitrary Precision Signed Int -----*- C++ -*--===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// This file implements the APSInt class, which is a simple class that 11193323Sed// represents an arbitrary sized integer that knows its signedness. 12193323Sed// 13193323Sed//===----------------------------------------------------------------------===// 14193323Sed 15252723Sdim#ifndef LLVM_ADT_APSINT_H 16252723Sdim#define LLVM_ADT_APSINT_H 17193323Sed 18193323Sed#include "llvm/ADT/APInt.h" 19193323Sed 20193323Sednamespace llvm { 21193323Sed 22193323Sedclass APSInt : public APInt { 23193323Sed bool IsUnsigned; 24193323Sedpublic: 25193323Sed /// Default constructor that creates an uninitialized APInt. 26252723Sdim explicit APSInt() : IsUnsigned(false) {} 27193323Sed 28193323Sed /// APSInt ctor - Create an APSInt with the specified width, default to 29193323Sed /// unsigned. 30193323Sed explicit APSInt(uint32_t BitWidth, bool isUnsigned = true) 31193323Sed : APInt(BitWidth, 0), IsUnsigned(isUnsigned) {} 32193323Sed 33193323Sed explicit APSInt(const APInt &I, bool isUnsigned = true) 34193323Sed : APInt(I), IsUnsigned(isUnsigned) {} 35193323Sed 36193323Sed APSInt &operator=(const APSInt &RHS) { 37193323Sed APInt::operator=(RHS); 38193323Sed IsUnsigned = RHS.IsUnsigned; 39193323Sed return *this; 40193323Sed } 41193323Sed 42193323Sed APSInt &operator=(const APInt &RHS) { 43193323Sed // Retain our current sign. 44193323Sed APInt::operator=(RHS); 45193323Sed return *this; 46193323Sed } 47193323Sed 48193323Sed APSInt &operator=(uint64_t RHS) { 49193323Sed // Retain our current sign. 50193323Sed APInt::operator=(RHS); 51193323Sed return *this; 52193323Sed } 53193323Sed 54193323Sed // Query sign information. 55193323Sed bool isSigned() const { return !IsUnsigned; } 56193323Sed bool isUnsigned() const { return IsUnsigned; } 57193323Sed void setIsUnsigned(bool Val) { IsUnsigned = Val; } 58193323Sed void setIsSigned(bool Val) { IsUnsigned = !Val; } 59193323Sed 60193323Sed /// toString - Append this APSInt to the specified SmallString. 61193323Sed void toString(SmallVectorImpl<char> &Str, unsigned Radix = 10) const { 62193323Sed APInt::toString(Str, Radix, isSigned()); 63193323Sed } 64193323Sed /// toString - Converts an APInt to a std::string. This is an inefficient 65193323Sed /// method, your should prefer passing in a SmallString instead. 66193323Sed std::string toString(unsigned Radix) const { 67193323Sed return APInt::toString(Radix, isSigned()); 68193323Sed } 69193323Sed using APInt::toString; 70193323Sed 71263509Sdim APSInt LLVM_ATTRIBUTE_UNUSED_RESULT trunc(uint32_t width) const { 72218893Sdim return APSInt(APInt::trunc(width), IsUnsigned); 73218893Sdim } 74218893Sdim 75263509Sdim APSInt LLVM_ATTRIBUTE_UNUSED_RESULT extend(uint32_t width) const { 76193323Sed if (IsUnsigned) 77218893Sdim return APSInt(zext(width), IsUnsigned); 78193323Sed else 79218893Sdim return APSInt(sext(width), IsUnsigned); 80193323Sed } 81193323Sed 82263509Sdim APSInt LLVM_ATTRIBUTE_UNUSED_RESULT extOrTrunc(uint32_t width) const { 83193323Sed if (IsUnsigned) 84218893Sdim return APSInt(zextOrTrunc(width), IsUnsigned); 85193323Sed else 86218893Sdim return APSInt(sextOrTrunc(width), IsUnsigned); 87193323Sed } 88193323Sed 89193323Sed const APSInt &operator%=(const APSInt &RHS) { 90193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 91193323Sed if (IsUnsigned) 92193323Sed *this = urem(RHS); 93193323Sed else 94193323Sed *this = srem(RHS); 95193323Sed return *this; 96193323Sed } 97193323Sed const APSInt &operator/=(const APSInt &RHS) { 98193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 99193323Sed if (IsUnsigned) 100193323Sed *this = udiv(RHS); 101193323Sed else 102193323Sed *this = sdiv(RHS); 103193323Sed return *this; 104193323Sed } 105193323Sed APSInt operator%(const APSInt &RHS) const { 106193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 107193323Sed return IsUnsigned ? APSInt(urem(RHS), true) : APSInt(srem(RHS), false); 108193323Sed } 109193323Sed APSInt operator/(const APSInt &RHS) const { 110193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 111193323Sed return IsUnsigned ? APSInt(udiv(RHS), true) : APSInt(sdiv(RHS), false); 112193323Sed } 113193323Sed 114193323Sed APSInt operator>>(unsigned Amt) const { 115193323Sed return IsUnsigned ? APSInt(lshr(Amt), true) : APSInt(ashr(Amt), false); 116193323Sed } 117193323Sed APSInt& operator>>=(unsigned Amt) { 118193323Sed *this = *this >> Amt; 119193323Sed return *this; 120193323Sed } 121193323Sed 122193323Sed inline bool operator<(const APSInt& RHS) const { 123193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 124193323Sed return IsUnsigned ? ult(RHS) : slt(RHS); 125193323Sed } 126193323Sed inline bool operator>(const APSInt& RHS) const { 127193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 128193323Sed return IsUnsigned ? ugt(RHS) : sgt(RHS); 129193323Sed } 130193323Sed inline bool operator<=(const APSInt& RHS) const { 131193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 132193323Sed return IsUnsigned ? ule(RHS) : sle(RHS); 133193323Sed } 134193323Sed inline bool operator>=(const APSInt& RHS) const { 135193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 136193323Sed return IsUnsigned ? uge(RHS) : sge(RHS); 137193323Sed } 138245431Sdim inline bool operator==(const APSInt& RHS) const { 139245431Sdim assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 140245431Sdim return eq(RHS); 141245431Sdim } 142245431Sdim inline bool operator==(int64_t RHS) const { 143245431Sdim return isSameValue(*this, APSInt(APInt(64, RHS), true)); 144245431Sdim } 145245431Sdim inline bool operator!=(const APSInt& RHS) const { 146245431Sdim return !((*this) == RHS); 147245431Sdim } 148245431Sdim inline bool operator!=(int64_t RHS) const { 149245431Sdim return !((*this) == RHS); 150245431Sdim } 151193323Sed 152193323Sed // The remaining operators just wrap the logic of APInt, but retain the 153193323Sed // signedness information. 154193323Sed 155193323Sed APSInt operator<<(unsigned Bits) const { 156193323Sed return APSInt(static_cast<const APInt&>(*this) << Bits, IsUnsigned); 157193323Sed } 158193323Sed APSInt& operator<<=(unsigned Amt) { 159193323Sed *this = *this << Amt; 160193323Sed return *this; 161193323Sed } 162193323Sed 163193323Sed APSInt& operator++() { 164252723Sdim ++(static_cast<APInt&>(*this)); 165193323Sed return *this; 166193323Sed } 167193323Sed APSInt& operator--() { 168252723Sdim --(static_cast<APInt&>(*this)); 169193323Sed return *this; 170193323Sed } 171193323Sed APSInt operator++(int) { 172193323Sed return APSInt(++static_cast<APInt&>(*this), IsUnsigned); 173193323Sed } 174193323Sed APSInt operator--(int) { 175193323Sed return APSInt(--static_cast<APInt&>(*this), IsUnsigned); 176193323Sed } 177193323Sed APSInt operator-() const { 178193323Sed return APSInt(-static_cast<const APInt&>(*this), IsUnsigned); 179193323Sed } 180193323Sed APSInt& operator+=(const APSInt& RHS) { 181193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 182193323Sed static_cast<APInt&>(*this) += RHS; 183193323Sed return *this; 184193323Sed } 185193323Sed APSInt& operator-=(const APSInt& RHS) { 186193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 187193323Sed static_cast<APInt&>(*this) -= RHS; 188193323Sed return *this; 189193323Sed } 190193323Sed APSInt& operator*=(const APSInt& RHS) { 191193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 192193323Sed static_cast<APInt&>(*this) *= RHS; 193193323Sed return *this; 194193323Sed } 195193323Sed APSInt& operator&=(const APSInt& RHS) { 196193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 197193323Sed static_cast<APInt&>(*this) &= RHS; 198193323Sed return *this; 199193323Sed } 200193323Sed APSInt& operator|=(const APSInt& RHS) { 201193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 202193323Sed static_cast<APInt&>(*this) |= RHS; 203193323Sed return *this; 204193323Sed } 205193323Sed APSInt& operator^=(const APSInt& RHS) { 206193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 207193323Sed static_cast<APInt&>(*this) ^= RHS; 208193323Sed return *this; 209193323Sed } 210193323Sed 211193323Sed APSInt operator&(const APSInt& RHS) const { 212193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 213193323Sed return APSInt(static_cast<const APInt&>(*this) & RHS, IsUnsigned); 214193323Sed } 215263509Sdim APSInt LLVM_ATTRIBUTE_UNUSED_RESULT And(const APSInt& RHS) const { 216193323Sed return this->operator&(RHS); 217193323Sed } 218193323Sed 219193323Sed APSInt operator|(const APSInt& RHS) const { 220193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 221193323Sed return APSInt(static_cast<const APInt&>(*this) | RHS, IsUnsigned); 222193323Sed } 223263509Sdim APSInt LLVM_ATTRIBUTE_UNUSED_RESULT Or(const APSInt& RHS) const { 224193323Sed return this->operator|(RHS); 225193323Sed } 226193323Sed 227193323Sed 228193323Sed APSInt operator^(const APSInt& RHS) const { 229193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 230193323Sed return APSInt(static_cast<const APInt&>(*this) ^ RHS, IsUnsigned); 231193323Sed } 232263509Sdim APSInt LLVM_ATTRIBUTE_UNUSED_RESULT Xor(const APSInt& RHS) const { 233193323Sed return this->operator^(RHS); 234193323Sed } 235193323Sed 236193323Sed APSInt operator*(const APSInt& RHS) const { 237193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 238193323Sed return APSInt(static_cast<const APInt&>(*this) * RHS, IsUnsigned); 239193323Sed } 240193323Sed APSInt operator+(const APSInt& RHS) const { 241193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 242193323Sed return APSInt(static_cast<const APInt&>(*this) + RHS, IsUnsigned); 243193323Sed } 244193323Sed APSInt operator-(const APSInt& RHS) const { 245193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 246193323Sed return APSInt(static_cast<const APInt&>(*this) - RHS, IsUnsigned); 247193323Sed } 248193323Sed APSInt operator~() const { 249193323Sed return APSInt(~static_cast<const APInt&>(*this), IsUnsigned); 250193323Sed } 251193323Sed 252193323Sed /// getMaxValue - Return the APSInt representing the maximum integer value 253193323Sed /// with the given bit width and signedness. 254193323Sed static APSInt getMaxValue(uint32_t numBits, bool Unsigned) { 255193323Sed return APSInt(Unsigned ? APInt::getMaxValue(numBits) 256193323Sed : APInt::getSignedMaxValue(numBits), Unsigned); 257193323Sed } 258193323Sed 259193323Sed /// getMinValue - Return the APSInt representing the minimum integer value 260193323Sed /// with the given bit width and signedness. 261193323Sed static APSInt getMinValue(uint32_t numBits, bool Unsigned) { 262193323Sed return APSInt(Unsigned ? APInt::getMinValue(numBits) 263193323Sed : APInt::getSignedMinValue(numBits), Unsigned); 264193323Sed } 265193323Sed 266245431Sdim /// \brief Determine if two APSInts have the same value, zero- or 267245431Sdim /// sign-extending as needed. 268245431Sdim static bool isSameValue(const APSInt &I1, const APSInt &I2) { 269245431Sdim if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned()) 270245431Sdim return I1 == I2; 271245431Sdim 272245431Sdim // Check for a bit-width mismatch. 273245431Sdim if (I1.getBitWidth() > I2.getBitWidth()) 274245431Sdim return isSameValue(I1, I2.extend(I1.getBitWidth())); 275245431Sdim else if (I2.getBitWidth() > I1.getBitWidth()) 276245431Sdim return isSameValue(I1.extend(I2.getBitWidth()), I2); 277245431Sdim 278245431Sdim // We have a signedness mismatch. Turn the signed value into an unsigned 279245431Sdim // value. 280245431Sdim if (I1.isSigned()) { 281245431Sdim if (I1.isNegative()) 282245431Sdim return false; 283245431Sdim 284245431Sdim return APSInt(I1, true) == I2; 285245431Sdim } 286245431Sdim 287245431Sdim if (I2.isNegative()) 288245431Sdim return false; 289245431Sdim 290245431Sdim return I1 == APSInt(I2, true); 291245431Sdim } 292245431Sdim 293193323Sed /// Profile - Used to insert APSInt objects, or objects that contain APSInt 294193323Sed /// objects, into FoldingSets. 295193323Sed void Profile(FoldingSetNodeID& ID) const; 296193323Sed}; 297193323Sed 298245431Sdiminline bool operator==(int64_t V1, const APSInt& V2) { 299245431Sdim return V2 == V1; 300245431Sdim} 301245431Sdiminline bool operator!=(int64_t V1, const APSInt& V2) { 302245431Sdim return V2 != V1; 303245431Sdim} 304245431Sdim 305193323Sedinline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) { 306193323Sed I.print(OS, I.isSigned()); 307193323Sed return OS; 308193323Sed} 309193323Sed 310193323Sed} // end namespace llvm 311193323Sed 312193323Sed#endif 313