APSInt.h revision 341825
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 15249423Sdim#ifndef LLVM_ADT_APSINT_H 16249423Sdim#define LLVM_ADT_APSINT_H 17193323Sed 18193323Sed#include "llvm/ADT/APInt.h" 19193323Sed 20193323Sednamespace llvm { 21193323Sed 22314564Sdimclass LLVM_NODISCARD APSInt : public APInt { 23193323Sed bool IsUnsigned; 24296417Sdim 25193323Sedpublic: 26193323Sed /// Default constructor that creates an uninitialized APInt. 27249423Sdim explicit APSInt() : IsUnsigned(false) {} 28193323Sed 29193323Sed /// APSInt ctor - Create an APSInt with the specified width, default to 30193323Sed /// unsigned. 31193323Sed explicit APSInt(uint32_t BitWidth, bool isUnsigned = true) 32193323Sed : APInt(BitWidth, 0), IsUnsigned(isUnsigned) {} 33193323Sed 34276479Sdim explicit APSInt(APInt I, bool isUnsigned = true) 35276479Sdim : APInt(std::move(I)), IsUnsigned(isUnsigned) {} 36193323Sed 37288943Sdim /// Construct an APSInt from a string representation. 38288943Sdim /// 39288943Sdim /// This constructor interprets the string \p Str using the radix of 10. 40288943Sdim /// The interpretation stops at the end of the string. The bit width of the 41288943Sdim /// constructed APSInt is determined automatically. 42288943Sdim /// 43288943Sdim /// \param Str the string to be interpreted. 44288943Sdim explicit APSInt(StringRef Str); 45288943Sdim 46276479Sdim APSInt &operator=(APInt RHS) { 47193323Sed // Retain our current sign. 48276479Sdim APInt::operator=(std::move(RHS)); 49193323Sed return *this; 50193323Sed } 51193323Sed 52193323Sed APSInt &operator=(uint64_t RHS) { 53193323Sed // Retain our current sign. 54193323Sed APInt::operator=(RHS); 55193323Sed return *this; 56193323Sed } 57193323Sed 58193323Sed // Query sign information. 59193323Sed bool isSigned() const { return !IsUnsigned; } 60193323Sed bool isUnsigned() const { return IsUnsigned; } 61193323Sed void setIsUnsigned(bool Val) { IsUnsigned = Val; } 62193323Sed void setIsSigned(bool Val) { IsUnsigned = !Val; } 63193323Sed 64193323Sed /// toString - Append this APSInt to the specified SmallString. 65193323Sed void toString(SmallVectorImpl<char> &Str, unsigned Radix = 10) const { 66193323Sed APInt::toString(Str, Radix, isSigned()); 67193323Sed } 68193323Sed /// toString - Converts an APInt to a std::string. This is an inefficient 69276479Sdim /// method; you should prefer passing in a SmallString instead. 70193323Sed std::string toString(unsigned Radix) const { 71193323Sed return APInt::toString(Radix, isSigned()); 72193323Sed } 73193323Sed using APInt::toString; 74193323Sed 75341825Sdim /// Get the correctly-extended \c int64_t value. 76288943Sdim int64_t getExtValue() const { 77288943Sdim assert(getMinSignedBits() <= 64 && "Too many bits for int64_t"); 78288943Sdim return isSigned() ? getSExtValue() : getZExtValue(); 79288943Sdim } 80288943Sdim 81314564Sdim APSInt trunc(uint32_t width) const { 82218893Sdim return APSInt(APInt::trunc(width), IsUnsigned); 83218893Sdim } 84218893Sdim 85314564Sdim APSInt extend(uint32_t width) const { 86193323Sed if (IsUnsigned) 87218893Sdim return APSInt(zext(width), IsUnsigned); 88193323Sed else 89218893Sdim return APSInt(sext(width), IsUnsigned); 90193323Sed } 91193323Sed 92314564Sdim APSInt extOrTrunc(uint32_t width) const { 93314564Sdim if (IsUnsigned) 94314564Sdim return APSInt(zextOrTrunc(width), IsUnsigned); 95314564Sdim else 96314564Sdim return APSInt(sextOrTrunc(width), IsUnsigned); 97193323Sed } 98193323Sed 99193323Sed const APSInt &operator%=(const APSInt &RHS) { 100193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 101193323Sed if (IsUnsigned) 102193323Sed *this = urem(RHS); 103193323Sed else 104193323Sed *this = srem(RHS); 105193323Sed return *this; 106193323Sed } 107193323Sed const APSInt &operator/=(const APSInt &RHS) { 108193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 109193323Sed if (IsUnsigned) 110193323Sed *this = udiv(RHS); 111193323Sed else 112193323Sed *this = sdiv(RHS); 113193323Sed return *this; 114193323Sed } 115193323Sed APSInt operator%(const APSInt &RHS) const { 116193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 117193323Sed return IsUnsigned ? APSInt(urem(RHS), true) : APSInt(srem(RHS), false); 118193323Sed } 119193323Sed APSInt operator/(const APSInt &RHS) const { 120193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 121193323Sed return IsUnsigned ? APSInt(udiv(RHS), true) : APSInt(sdiv(RHS), false); 122193323Sed } 123193323Sed 124193323Sed APSInt operator>>(unsigned Amt) const { 125193323Sed return IsUnsigned ? APSInt(lshr(Amt), true) : APSInt(ashr(Amt), false); 126193323Sed } 127193323Sed APSInt& operator>>=(unsigned Amt) { 128321369Sdim if (IsUnsigned) 129321369Sdim lshrInPlace(Amt); 130321369Sdim else 131321369Sdim ashrInPlace(Amt); 132193323Sed return *this; 133193323Sed } 134193323Sed 135193323Sed inline bool operator<(const APSInt& RHS) const { 136193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 137193323Sed return IsUnsigned ? ult(RHS) : slt(RHS); 138193323Sed } 139193323Sed inline bool operator>(const APSInt& RHS) const { 140193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 141193323Sed return IsUnsigned ? ugt(RHS) : sgt(RHS); 142193323Sed } 143193323Sed inline bool operator<=(const APSInt& RHS) const { 144193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 145193323Sed return IsUnsigned ? ule(RHS) : sle(RHS); 146193323Sed } 147193323Sed inline bool operator>=(const APSInt& RHS) const { 148193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 149193323Sed return IsUnsigned ? uge(RHS) : sge(RHS); 150193323Sed } 151239462Sdim inline bool operator==(const APSInt& RHS) const { 152239462Sdim assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 153239462Sdim return eq(RHS); 154239462Sdim } 155239462Sdim inline bool operator!=(const APSInt& RHS) const { 156239462Sdim return !((*this) == RHS); 157239462Sdim } 158288943Sdim 159288943Sdim bool operator==(int64_t RHS) const { 160288943Sdim return compareValues(*this, get(RHS)) == 0; 161239462Sdim } 162288943Sdim bool operator!=(int64_t RHS) const { 163288943Sdim return compareValues(*this, get(RHS)) != 0; 164288943Sdim } 165288943Sdim bool operator<=(int64_t RHS) const { 166288943Sdim return compareValues(*this, get(RHS)) <= 0; 167288943Sdim } 168288943Sdim bool operator>=(int64_t RHS) const { 169288943Sdim return compareValues(*this, get(RHS)) >= 0; 170288943Sdim } 171288943Sdim bool operator<(int64_t RHS) const { 172288943Sdim return compareValues(*this, get(RHS)) < 0; 173288943Sdim } 174288943Sdim bool operator>(int64_t RHS) const { 175288943Sdim return compareValues(*this, get(RHS)) > 0; 176288943Sdim } 177193323Sed 178193323Sed // The remaining operators just wrap the logic of APInt, but retain the 179193323Sed // signedness information. 180193323Sed 181193323Sed APSInt operator<<(unsigned Bits) const { 182193323Sed return APSInt(static_cast<const APInt&>(*this) << Bits, IsUnsigned); 183193323Sed } 184193323Sed APSInt& operator<<=(unsigned Amt) { 185321369Sdim static_cast<APInt&>(*this) <<= Amt; 186193323Sed return *this; 187193323Sed } 188193323Sed 189193323Sed APSInt& operator++() { 190249423Sdim ++(static_cast<APInt&>(*this)); 191193323Sed return *this; 192193323Sed } 193193323Sed APSInt& operator--() { 194249423Sdim --(static_cast<APInt&>(*this)); 195193323Sed return *this; 196193323Sed } 197193323Sed APSInt operator++(int) { 198193323Sed return APSInt(++static_cast<APInt&>(*this), IsUnsigned); 199193323Sed } 200193323Sed APSInt operator--(int) { 201193323Sed return APSInt(--static_cast<APInt&>(*this), IsUnsigned); 202193323Sed } 203193323Sed APSInt operator-() const { 204193323Sed return APSInt(-static_cast<const APInt&>(*this), IsUnsigned); 205193323Sed } 206193323Sed APSInt& operator+=(const APSInt& RHS) { 207193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 208193323Sed static_cast<APInt&>(*this) += RHS; 209193323Sed return *this; 210193323Sed } 211193323Sed APSInt& operator-=(const APSInt& RHS) { 212193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 213193323Sed static_cast<APInt&>(*this) -= RHS; 214193323Sed return *this; 215193323Sed } 216193323Sed APSInt& operator*=(const APSInt& RHS) { 217193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 218193323Sed static_cast<APInt&>(*this) *= RHS; 219193323Sed return *this; 220193323Sed } 221193323Sed APSInt& operator&=(const APSInt& RHS) { 222193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 223193323Sed static_cast<APInt&>(*this) &= RHS; 224193323Sed return *this; 225193323Sed } 226193323Sed APSInt& operator|=(const APSInt& RHS) { 227193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 228193323Sed static_cast<APInt&>(*this) |= RHS; 229193323Sed return *this; 230193323Sed } 231193323Sed APSInt& operator^=(const APSInt& RHS) { 232193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 233193323Sed static_cast<APInt&>(*this) ^= RHS; 234193323Sed return *this; 235193323Sed } 236193323Sed 237193323Sed APSInt operator&(const APSInt& RHS) const { 238193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 239193323Sed return APSInt(static_cast<const APInt&>(*this) & RHS, IsUnsigned); 240193323Sed } 241193323Sed 242193323Sed APSInt operator|(const APSInt& RHS) const { 243193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 244193323Sed return APSInt(static_cast<const APInt&>(*this) | RHS, IsUnsigned); 245193323Sed } 246193323Sed 247296417Sdim APSInt operator^(const APSInt &RHS) const { 248193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 249193323Sed return APSInt(static_cast<const APInt&>(*this) ^ RHS, IsUnsigned); 250193323Sed } 251193323Sed 252193323Sed APSInt operator*(const APSInt& RHS) const { 253193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 254193323Sed return APSInt(static_cast<const APInt&>(*this) * RHS, IsUnsigned); 255193323Sed } 256193323Sed APSInt operator+(const APSInt& RHS) const { 257193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 258193323Sed return APSInt(static_cast<const APInt&>(*this) + RHS, IsUnsigned); 259193323Sed } 260193323Sed APSInt operator-(const APSInt& RHS) const { 261193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 262193323Sed return APSInt(static_cast<const APInt&>(*this) - RHS, IsUnsigned); 263193323Sed } 264193323Sed APSInt operator~() const { 265193323Sed return APSInt(~static_cast<const APInt&>(*this), IsUnsigned); 266193323Sed } 267193323Sed 268193323Sed /// getMaxValue - Return the APSInt representing the maximum integer value 269193323Sed /// with the given bit width and signedness. 270193323Sed static APSInt getMaxValue(uint32_t numBits, bool Unsigned) { 271193323Sed return APSInt(Unsigned ? APInt::getMaxValue(numBits) 272193323Sed : APInt::getSignedMaxValue(numBits), Unsigned); 273193323Sed } 274193323Sed 275193323Sed /// getMinValue - Return the APSInt representing the minimum integer value 276193323Sed /// with the given bit width and signedness. 277193323Sed static APSInt getMinValue(uint32_t numBits, bool Unsigned) { 278193323Sed return APSInt(Unsigned ? APInt::getMinValue(numBits) 279193323Sed : APInt::getSignedMinValue(numBits), Unsigned); 280193323Sed } 281193323Sed 282341825Sdim /// Determine if two APSInts have the same value, zero- or 283296417Sdim /// sign-extending as needed. 284239462Sdim static bool isSameValue(const APSInt &I1, const APSInt &I2) { 285288943Sdim return !compareValues(I1, I2); 286288943Sdim } 287288943Sdim 288341825Sdim /// Compare underlying values of two numbers. 289288943Sdim static int compareValues(const APSInt &I1, const APSInt &I2) { 290239462Sdim if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned()) 291321369Sdim return I1.IsUnsigned ? I1.compare(I2) : I1.compareSigned(I2); 292239462Sdim 293239462Sdim // Check for a bit-width mismatch. 294239462Sdim if (I1.getBitWidth() > I2.getBitWidth()) 295288943Sdim return compareValues(I1, I2.extend(I1.getBitWidth())); 296321369Sdim if (I2.getBitWidth() > I1.getBitWidth()) 297288943Sdim return compareValues(I1.extend(I2.getBitWidth()), I2); 298239462Sdim 299280031Sdim // We have a signedness mismatch. Check for negative values and do an 300288943Sdim // unsigned compare if both are positive. 301288943Sdim if (I1.isSigned()) { 302288943Sdim assert(!I2.isSigned() && "Expected signed mismatch"); 303288943Sdim if (I1.isNegative()) 304288943Sdim return -1; 305288943Sdim } else { 306288943Sdim assert(I2.isSigned() && "Expected signed mismatch"); 307288943Sdim if (I2.isNegative()) 308288943Sdim return 1; 309288943Sdim } 310239462Sdim 311321369Sdim return I1.compare(I2); 312239462Sdim } 313239462Sdim 314288943Sdim static APSInt get(int64_t X) { return APSInt(APInt(64, X), false); } 315288943Sdim static APSInt getUnsigned(uint64_t X) { return APSInt(APInt(64, X), true); } 316288943Sdim 317193323Sed /// Profile - Used to insert APSInt objects, or objects that contain APSInt 318193323Sed /// objects, into FoldingSets. 319193323Sed void Profile(FoldingSetNodeID& ID) const; 320193323Sed}; 321193323Sed 322288943Sdiminline bool operator==(int64_t V1, const APSInt &V2) { return V2 == V1; } 323288943Sdiminline bool operator!=(int64_t V1, const APSInt &V2) { return V2 != V1; } 324288943Sdiminline bool operator<=(int64_t V1, const APSInt &V2) { return V2 >= V1; } 325288943Sdiminline bool operator>=(int64_t V1, const APSInt &V2) { return V2 <= V1; } 326288943Sdiminline bool operator<(int64_t V1, const APSInt &V2) { return V2 > V1; } 327288943Sdiminline bool operator>(int64_t V1, const APSInt &V2) { return V2 < V1; } 328239462Sdim 329193323Sedinline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) { 330193323Sed I.print(OS, I.isSigned()); 331193323Sed return OS; 332193323Sed} 333193323Sed 334193323Sed} // end namespace llvm 335193323Sed 336193323Sed#endif 337