1193323Sed//===-- llvm/ADT/APSInt.h - Arbitrary Precision Signed Int -----*- C++ -*--===// 2193323Sed// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6193323Sed// 7193323Sed//===----------------------------------------------------------------------===// 8193323Sed// 9193323Sed// This file implements the APSInt class, which is a simple class that 10193323Sed// represents an arbitrary sized integer that knows its signedness. 11193323Sed// 12193323Sed//===----------------------------------------------------------------------===// 13193323Sed 14249423Sdim#ifndef LLVM_ADT_APSINT_H 15249423Sdim#define LLVM_ADT_APSINT_H 16193323Sed 17193323Sed#include "llvm/ADT/APInt.h" 18193323Sed 19193323Sednamespace llvm { 20193323Sed 21314564Sdimclass LLVM_NODISCARD APSInt : public APInt { 22193323Sed bool IsUnsigned; 23296417Sdim 24193323Sedpublic: 25193323Sed /// Default constructor that creates an uninitialized APInt. 26249423Sdim 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 33276479Sdim explicit APSInt(APInt I, bool isUnsigned = true) 34276479Sdim : APInt(std::move(I)), IsUnsigned(isUnsigned) {} 35193323Sed 36288943Sdim /// Construct an APSInt from a string representation. 37288943Sdim /// 38288943Sdim /// This constructor interprets the string \p Str using the radix of 10. 39288943Sdim /// The interpretation stops at the end of the string. The bit width of the 40288943Sdim /// constructed APSInt is determined automatically. 41288943Sdim /// 42288943Sdim /// \param Str the string to be interpreted. 43288943Sdim explicit APSInt(StringRef Str); 44288943Sdim 45353358Sdim /// Determine sign of this APSInt. 46353358Sdim /// 47353358Sdim /// \returns true if this APSInt is negative, false otherwise 48353358Sdim bool isNegative() const { return isSigned() && APInt::isNegative(); } 49353358Sdim 50353358Sdim /// Determine if this APSInt Value is non-negative (>= 0) 51353358Sdim /// 52353358Sdim /// \returns true if this APSInt is non-negative, false otherwise 53353358Sdim bool isNonNegative() const { return !isNegative(); } 54353358Sdim 55353358Sdim /// Determine if this APSInt Value is positive. 56353358Sdim /// 57353358Sdim /// This tests if the value of this APSInt is positive (> 0). Note 58353358Sdim /// that 0 is not a positive value. 59353358Sdim /// 60353358Sdim /// \returns true if this APSInt is positive. 61353358Sdim bool isStrictlyPositive() const { return isNonNegative() && !isNullValue(); } 62353358Sdim 63276479Sdim APSInt &operator=(APInt RHS) { 64193323Sed // Retain our current sign. 65276479Sdim APInt::operator=(std::move(RHS)); 66193323Sed return *this; 67193323Sed } 68193323Sed 69193323Sed APSInt &operator=(uint64_t RHS) { 70193323Sed // Retain our current sign. 71193323Sed APInt::operator=(RHS); 72193323Sed return *this; 73193323Sed } 74193323Sed 75193323Sed // Query sign information. 76193323Sed bool isSigned() const { return !IsUnsigned; } 77193323Sed bool isUnsigned() const { return IsUnsigned; } 78193323Sed void setIsUnsigned(bool Val) { IsUnsigned = Val; } 79193323Sed void setIsSigned(bool Val) { IsUnsigned = !Val; } 80193323Sed 81193323Sed /// toString - Append this APSInt to the specified SmallString. 82193323Sed void toString(SmallVectorImpl<char> &Str, unsigned Radix = 10) const { 83193323Sed APInt::toString(Str, Radix, isSigned()); 84193323Sed } 85193323Sed /// toString - Converts an APInt to a std::string. This is an inefficient 86276479Sdim /// method; you should prefer passing in a SmallString instead. 87193323Sed std::string toString(unsigned Radix) const { 88193323Sed return APInt::toString(Radix, isSigned()); 89193323Sed } 90193323Sed using APInt::toString; 91193323Sed 92341825Sdim /// Get the correctly-extended \c int64_t value. 93288943Sdim int64_t getExtValue() const { 94288943Sdim assert(getMinSignedBits() <= 64 && "Too many bits for int64_t"); 95288943Sdim return isSigned() ? getSExtValue() : getZExtValue(); 96288943Sdim } 97288943Sdim 98314564Sdim APSInt trunc(uint32_t width) const { 99218893Sdim return APSInt(APInt::trunc(width), IsUnsigned); 100218893Sdim } 101218893Sdim 102314564Sdim APSInt extend(uint32_t width) const { 103193323Sed if (IsUnsigned) 104218893Sdim return APSInt(zext(width), IsUnsigned); 105193323Sed else 106218893Sdim return APSInt(sext(width), IsUnsigned); 107193323Sed } 108193323Sed 109314564Sdim APSInt extOrTrunc(uint32_t width) const { 110314564Sdim if (IsUnsigned) 111314564Sdim return APSInt(zextOrTrunc(width), IsUnsigned); 112314564Sdim else 113314564Sdim return APSInt(sextOrTrunc(width), IsUnsigned); 114193323Sed } 115193323Sed 116193323Sed const APSInt &operator%=(const APSInt &RHS) { 117193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 118193323Sed if (IsUnsigned) 119193323Sed *this = urem(RHS); 120193323Sed else 121193323Sed *this = srem(RHS); 122193323Sed return *this; 123193323Sed } 124193323Sed const APSInt &operator/=(const APSInt &RHS) { 125193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 126193323Sed if (IsUnsigned) 127193323Sed *this = udiv(RHS); 128193323Sed else 129193323Sed *this = sdiv(RHS); 130193323Sed return *this; 131193323Sed } 132193323Sed APSInt operator%(const APSInt &RHS) const { 133193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 134193323Sed return IsUnsigned ? APSInt(urem(RHS), true) : APSInt(srem(RHS), false); 135193323Sed } 136193323Sed APSInt operator/(const APSInt &RHS) const { 137193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 138193323Sed return IsUnsigned ? APSInt(udiv(RHS), true) : APSInt(sdiv(RHS), false); 139193323Sed } 140193323Sed 141193323Sed APSInt operator>>(unsigned Amt) const { 142193323Sed return IsUnsigned ? APSInt(lshr(Amt), true) : APSInt(ashr(Amt), false); 143193323Sed } 144193323Sed APSInt& operator>>=(unsigned Amt) { 145321369Sdim if (IsUnsigned) 146321369Sdim lshrInPlace(Amt); 147321369Sdim else 148321369Sdim ashrInPlace(Amt); 149193323Sed return *this; 150193323Sed } 151193323Sed 152193323Sed inline bool operator<(const APSInt& RHS) const { 153193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 154193323Sed return IsUnsigned ? ult(RHS) : slt(RHS); 155193323Sed } 156193323Sed inline bool operator>(const APSInt& RHS) const { 157193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 158193323Sed return IsUnsigned ? ugt(RHS) : sgt(RHS); 159193323Sed } 160193323Sed inline bool operator<=(const APSInt& RHS) const { 161193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 162193323Sed return IsUnsigned ? ule(RHS) : sle(RHS); 163193323Sed } 164193323Sed inline bool operator>=(const APSInt& RHS) const { 165193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 166193323Sed return IsUnsigned ? uge(RHS) : sge(RHS); 167193323Sed } 168239462Sdim inline bool operator==(const APSInt& RHS) const { 169239462Sdim assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 170239462Sdim return eq(RHS); 171239462Sdim } 172239462Sdim inline bool operator!=(const APSInt& RHS) const { 173239462Sdim return !((*this) == RHS); 174239462Sdim } 175288943Sdim 176288943Sdim bool operator==(int64_t RHS) const { 177288943Sdim return compareValues(*this, get(RHS)) == 0; 178239462Sdim } 179288943Sdim bool operator!=(int64_t RHS) const { 180288943Sdim return compareValues(*this, get(RHS)) != 0; 181288943Sdim } 182288943Sdim bool operator<=(int64_t RHS) const { 183288943Sdim return compareValues(*this, get(RHS)) <= 0; 184288943Sdim } 185288943Sdim bool operator>=(int64_t RHS) const { 186288943Sdim return compareValues(*this, get(RHS)) >= 0; 187288943Sdim } 188288943Sdim bool operator<(int64_t RHS) const { 189288943Sdim return compareValues(*this, get(RHS)) < 0; 190288943Sdim } 191288943Sdim bool operator>(int64_t RHS) const { 192288943Sdim return compareValues(*this, get(RHS)) > 0; 193288943Sdim } 194193323Sed 195193323Sed // The remaining operators just wrap the logic of APInt, but retain the 196193323Sed // signedness information. 197193323Sed 198193323Sed APSInt operator<<(unsigned Bits) const { 199193323Sed return APSInt(static_cast<const APInt&>(*this) << Bits, IsUnsigned); 200193323Sed } 201193323Sed APSInt& operator<<=(unsigned Amt) { 202321369Sdim static_cast<APInt&>(*this) <<= Amt; 203193323Sed return *this; 204193323Sed } 205193323Sed 206193323Sed APSInt& operator++() { 207249423Sdim ++(static_cast<APInt&>(*this)); 208193323Sed return *this; 209193323Sed } 210193323Sed APSInt& operator--() { 211249423Sdim --(static_cast<APInt&>(*this)); 212193323Sed return *this; 213193323Sed } 214193323Sed APSInt operator++(int) { 215193323Sed return APSInt(++static_cast<APInt&>(*this), IsUnsigned); 216193323Sed } 217193323Sed APSInt operator--(int) { 218193323Sed return APSInt(--static_cast<APInt&>(*this), IsUnsigned); 219193323Sed } 220193323Sed APSInt operator-() const { 221193323Sed return APSInt(-static_cast<const APInt&>(*this), IsUnsigned); 222193323Sed } 223193323Sed APSInt& operator+=(const APSInt& RHS) { 224193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 225193323Sed static_cast<APInt&>(*this) += RHS; 226193323Sed return *this; 227193323Sed } 228193323Sed APSInt& operator-=(const APSInt& RHS) { 229193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 230193323Sed static_cast<APInt&>(*this) -= RHS; 231193323Sed return *this; 232193323Sed } 233193323Sed APSInt& operator*=(const APSInt& RHS) { 234193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 235193323Sed static_cast<APInt&>(*this) *= RHS; 236193323Sed return *this; 237193323Sed } 238193323Sed APSInt& operator&=(const APSInt& RHS) { 239193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 240193323Sed static_cast<APInt&>(*this) &= RHS; 241193323Sed return *this; 242193323Sed } 243193323Sed APSInt& operator|=(const APSInt& RHS) { 244193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 245193323Sed static_cast<APInt&>(*this) |= RHS; 246193323Sed return *this; 247193323Sed } 248193323Sed APSInt& operator^=(const APSInt& RHS) { 249193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 250193323Sed static_cast<APInt&>(*this) ^= RHS; 251193323Sed return *this; 252193323Sed } 253193323Sed 254193323Sed APSInt operator&(const APSInt& RHS) const { 255193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 256193323Sed return APSInt(static_cast<const APInt&>(*this) & RHS, IsUnsigned); 257193323Sed } 258193323Sed 259193323Sed APSInt operator|(const APSInt& RHS) const { 260193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 261193323Sed return APSInt(static_cast<const APInt&>(*this) | RHS, IsUnsigned); 262193323Sed } 263193323Sed 264296417Sdim APSInt operator^(const APSInt &RHS) const { 265193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 266193323Sed return APSInt(static_cast<const APInt&>(*this) ^ RHS, IsUnsigned); 267193323Sed } 268193323Sed 269193323Sed APSInt operator*(const APSInt& RHS) const { 270193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 271193323Sed return APSInt(static_cast<const APInt&>(*this) * RHS, IsUnsigned); 272193323Sed } 273193323Sed APSInt operator+(const APSInt& RHS) const { 274193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 275193323Sed return APSInt(static_cast<const APInt&>(*this) + RHS, IsUnsigned); 276193323Sed } 277193323Sed APSInt operator-(const APSInt& RHS) const { 278193323Sed assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); 279193323Sed return APSInt(static_cast<const APInt&>(*this) - RHS, IsUnsigned); 280193323Sed } 281193323Sed APSInt operator~() const { 282193323Sed return APSInt(~static_cast<const APInt&>(*this), IsUnsigned); 283193323Sed } 284193323Sed 285193323Sed /// getMaxValue - Return the APSInt representing the maximum integer value 286193323Sed /// with the given bit width and signedness. 287193323Sed static APSInt getMaxValue(uint32_t numBits, bool Unsigned) { 288193323Sed return APSInt(Unsigned ? APInt::getMaxValue(numBits) 289193323Sed : APInt::getSignedMaxValue(numBits), Unsigned); 290193323Sed } 291193323Sed 292193323Sed /// getMinValue - Return the APSInt representing the minimum integer value 293193323Sed /// with the given bit width and signedness. 294193323Sed static APSInt getMinValue(uint32_t numBits, bool Unsigned) { 295193323Sed return APSInt(Unsigned ? APInt::getMinValue(numBits) 296193323Sed : APInt::getSignedMinValue(numBits), Unsigned); 297193323Sed } 298193323Sed 299341825Sdim /// Determine if two APSInts have the same value, zero- or 300296417Sdim /// sign-extending as needed. 301239462Sdim static bool isSameValue(const APSInt &I1, const APSInt &I2) { 302288943Sdim return !compareValues(I1, I2); 303288943Sdim } 304288943Sdim 305341825Sdim /// Compare underlying values of two numbers. 306288943Sdim static int compareValues(const APSInt &I1, const APSInt &I2) { 307239462Sdim if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned()) 308321369Sdim return I1.IsUnsigned ? I1.compare(I2) : I1.compareSigned(I2); 309239462Sdim 310239462Sdim // Check for a bit-width mismatch. 311239462Sdim if (I1.getBitWidth() > I2.getBitWidth()) 312288943Sdim return compareValues(I1, I2.extend(I1.getBitWidth())); 313321369Sdim if (I2.getBitWidth() > I1.getBitWidth()) 314288943Sdim return compareValues(I1.extend(I2.getBitWidth()), I2); 315239462Sdim 316280031Sdim // We have a signedness mismatch. Check for negative values and do an 317288943Sdim // unsigned compare if both are positive. 318288943Sdim if (I1.isSigned()) { 319288943Sdim assert(!I2.isSigned() && "Expected signed mismatch"); 320288943Sdim if (I1.isNegative()) 321288943Sdim return -1; 322288943Sdim } else { 323288943Sdim assert(I2.isSigned() && "Expected signed mismatch"); 324288943Sdim if (I2.isNegative()) 325288943Sdim return 1; 326288943Sdim } 327239462Sdim 328321369Sdim return I1.compare(I2); 329239462Sdim } 330239462Sdim 331288943Sdim static APSInt get(int64_t X) { return APSInt(APInt(64, X), false); } 332288943Sdim static APSInt getUnsigned(uint64_t X) { return APSInt(APInt(64, X), true); } 333288943Sdim 334193323Sed /// Profile - Used to insert APSInt objects, or objects that contain APSInt 335193323Sed /// objects, into FoldingSets. 336193323Sed void Profile(FoldingSetNodeID& ID) const; 337193323Sed}; 338193323Sed 339288943Sdiminline bool operator==(int64_t V1, const APSInt &V2) { return V2 == V1; } 340288943Sdiminline bool operator!=(int64_t V1, const APSInt &V2) { return V2 != V1; } 341288943Sdiminline bool operator<=(int64_t V1, const APSInt &V2) { return V2 >= V1; } 342288943Sdiminline bool operator>=(int64_t V1, const APSInt &V2) { return V2 <= V1; } 343288943Sdiminline bool operator<(int64_t V1, const APSInt &V2) { return V2 > V1; } 344288943Sdiminline bool operator>(int64_t V1, const APSInt &V2) { return V2 < V1; } 345239462Sdim 346193323Sedinline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) { 347193323Sed I.print(OS, I.isSigned()); 348193323Sed return OS; 349193323Sed} 350193323Sed 351193323Sed} // end namespace llvm 352193323Sed 353193323Sed#endif 354