Home | History | Annotate | Download | only in ADT
      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_ADT_APSINT_H
     16 #define LLVM_ADT_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() : IsUnsigned(false) {}
     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(APInt I, bool isUnsigned = true)
     34    : APInt(std::move(I)), IsUnsigned(isUnsigned) {}
     35 
     36   APSInt &operator=(APInt RHS) {
     37     // Retain our current sign.
     38     APInt::operator=(std::move(RHS));
     39     return *this;
     40   }
     41 
     42   APSInt &operator=(uint64_t RHS) {
     43     // Retain our current sign.
     44     APInt::operator=(RHS);
     45     return *this;
     46   }
     47 
     48   // Query sign information.
     49   bool isSigned() const { return !IsUnsigned; }
     50   bool isUnsigned() const { return IsUnsigned; }
     51   void setIsUnsigned(bool Val) { IsUnsigned = Val; }
     52   void setIsSigned(bool Val) { IsUnsigned = !Val; }
     53 
     54   /// toString - Append this APSInt to the specified SmallString.
     55   void toString(SmallVectorImpl<char> &Str, unsigned Radix = 10) const {
     56     APInt::toString(Str, Radix, isSigned());
     57   }
     58   /// toString - Converts an APInt to a std::string.  This is an inefficient
     59   /// method; you should prefer passing in a SmallString instead.
     60   std::string toString(unsigned Radix) const {
     61     return APInt::toString(Radix, isSigned());
     62   }
     63   using APInt::toString;
     64 
     65   APSInt LLVM_ATTRIBUTE_UNUSED_RESULT trunc(uint32_t width) const {
     66     return APSInt(APInt::trunc(width), IsUnsigned);
     67   }
     68 
     69   APSInt LLVM_ATTRIBUTE_UNUSED_RESULT extend(uint32_t width) const {
     70     if (IsUnsigned)
     71       return APSInt(zext(width), IsUnsigned);
     72     else
     73       return APSInt(sext(width), IsUnsigned);
     74   }
     75 
     76   APSInt LLVM_ATTRIBUTE_UNUSED_RESULT extOrTrunc(uint32_t width) const {
     77       if (IsUnsigned)
     78         return APSInt(zextOrTrunc(width), IsUnsigned);
     79       else
     80         return APSInt(sextOrTrunc(width), IsUnsigned);
     81   }
     82 
     83   const APSInt &operator%=(const APSInt &RHS) {
     84     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
     85     if (IsUnsigned)
     86       *this = urem(RHS);
     87     else
     88       *this = srem(RHS);
     89     return *this;
     90   }
     91   const APSInt &operator/=(const APSInt &RHS) {
     92     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
     93     if (IsUnsigned)
     94       *this = udiv(RHS);
     95     else
     96       *this = sdiv(RHS);
     97     return *this;
     98   }
     99   APSInt operator%(const APSInt &RHS) const {
    100     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    101     return IsUnsigned ? APSInt(urem(RHS), true) : APSInt(srem(RHS), false);
    102   }
    103   APSInt operator/(const APSInt &RHS) const {
    104     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    105     return IsUnsigned ? APSInt(udiv(RHS), true) : APSInt(sdiv(RHS), false);
    106   }
    107 
    108   APSInt operator>>(unsigned Amt) const {
    109     return IsUnsigned ? APSInt(lshr(Amt), true) : APSInt(ashr(Amt), false);
    110   }
    111   APSInt& operator>>=(unsigned Amt) {
    112     *this = *this >> Amt;
    113     return *this;
    114   }
    115 
    116   inline bool operator<(const APSInt& RHS) const {
    117     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    118     return IsUnsigned ? ult(RHS) : slt(RHS);
    119   }
    120   inline bool operator>(const APSInt& RHS) const {
    121     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    122     return IsUnsigned ? ugt(RHS) : sgt(RHS);
    123   }
    124   inline bool operator<=(const APSInt& RHS) const {
    125     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    126     return IsUnsigned ? ule(RHS) : sle(RHS);
    127   }
    128   inline bool operator>=(const APSInt& RHS) const {
    129     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    130     return IsUnsigned ? uge(RHS) : sge(RHS);
    131   }
    132   inline bool operator==(const APSInt& RHS) const {
    133     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    134     return eq(RHS);
    135   }
    136   inline bool operator==(int64_t RHS) const {
    137     return isSameValue(*this, APSInt(APInt(64, RHS), true));
    138   }
    139   inline bool operator!=(const APSInt& RHS) const {
    140     return !((*this) == RHS);
    141   }
    142   inline bool operator!=(int64_t RHS) const {
    143     return !((*this) == RHS);
    144   }
    145 
    146   // The remaining operators just wrap the logic of APInt, but retain the
    147   // signedness information.
    148 
    149   APSInt operator<<(unsigned Bits) const {
    150     return APSInt(static_cast<const APInt&>(*this) << Bits, IsUnsigned);
    151   }
    152   APSInt& operator<<=(unsigned Amt) {
    153     *this = *this << Amt;
    154     return *this;
    155   }
    156 
    157   APSInt& operator++() {
    158     ++(static_cast<APInt&>(*this));
    159     return *this;
    160   }
    161   APSInt& operator--() {
    162     --(static_cast<APInt&>(*this));
    163     return *this;
    164   }
    165   APSInt operator++(int) {
    166     return APSInt(++static_cast<APInt&>(*this), IsUnsigned);
    167   }
    168   APSInt operator--(int) {
    169     return APSInt(--static_cast<APInt&>(*this), IsUnsigned);
    170   }
    171   APSInt operator-() const {
    172     return APSInt(-static_cast<const APInt&>(*this), IsUnsigned);
    173   }
    174   APSInt& operator+=(const APSInt& RHS) {
    175     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    176     static_cast<APInt&>(*this) += RHS;
    177     return *this;
    178   }
    179   APSInt& operator-=(const APSInt& RHS) {
    180     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    181     static_cast<APInt&>(*this) -= RHS;
    182     return *this;
    183   }
    184   APSInt& operator*=(const APSInt& RHS) {
    185     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    186     static_cast<APInt&>(*this) *= RHS;
    187     return *this;
    188   }
    189   APSInt& operator&=(const APSInt& RHS) {
    190     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    191     static_cast<APInt&>(*this) &= RHS;
    192     return *this;
    193   }
    194   APSInt& operator|=(const APSInt& RHS) {
    195     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    196     static_cast<APInt&>(*this) |= RHS;
    197     return *this;
    198   }
    199   APSInt& operator^=(const APSInt& RHS) {
    200     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    201     static_cast<APInt&>(*this) ^= RHS;
    202     return *this;
    203   }
    204 
    205   APSInt operator&(const APSInt& RHS) const {
    206     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    207     return APSInt(static_cast<const APInt&>(*this) & RHS, IsUnsigned);
    208   }
    209   APSInt LLVM_ATTRIBUTE_UNUSED_RESULT And(const APSInt& RHS) const {
    210     return this->operator&(RHS);
    211   }
    212 
    213   APSInt operator|(const APSInt& RHS) const {
    214     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    215     return APSInt(static_cast<const APInt&>(*this) | RHS, IsUnsigned);
    216   }
    217   APSInt LLVM_ATTRIBUTE_UNUSED_RESULT Or(const APSInt& RHS) const {
    218     return this->operator|(RHS);
    219   }
    220 
    221 
    222   APSInt operator^(const APSInt& RHS) const {
    223     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    224     return APSInt(static_cast<const APInt&>(*this) ^ RHS, IsUnsigned);
    225   }
    226   APSInt LLVM_ATTRIBUTE_UNUSED_RESULT Xor(const APSInt& RHS) const {
    227     return this->operator^(RHS);
    228   }
    229 
    230   APSInt operator*(const APSInt& RHS) const {
    231     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    232     return APSInt(static_cast<const APInt&>(*this) * RHS, IsUnsigned);
    233   }
    234   APSInt operator+(const APSInt& RHS) const {
    235     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    236     return APSInt(static_cast<const APInt&>(*this) + RHS, IsUnsigned);
    237   }
    238   APSInt operator-(const APSInt& RHS) const {
    239     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    240     return APSInt(static_cast<const APInt&>(*this) - RHS, IsUnsigned);
    241   }
    242   APSInt operator~() const {
    243     return APSInt(~static_cast<const APInt&>(*this), IsUnsigned);
    244   }
    245 
    246   /// getMaxValue - Return the APSInt representing the maximum integer value
    247   ///  with the given bit width and signedness.
    248   static APSInt getMaxValue(uint32_t numBits, bool Unsigned) {
    249     return APSInt(Unsigned ? APInt::getMaxValue(numBits)
    250                            : APInt::getSignedMaxValue(numBits), Unsigned);
    251   }
    252 
    253   /// getMinValue - Return the APSInt representing the minimum integer value
    254   ///  with the given bit width and signedness.
    255   static APSInt getMinValue(uint32_t numBits, bool Unsigned) {
    256     return APSInt(Unsigned ? APInt::getMinValue(numBits)
    257                            : APInt::getSignedMinValue(numBits), Unsigned);
    258   }
    259 
    260   /// \brief Determine if two APSInts have the same value, zero- or
    261   /// sign-extending as needed.
    262   static bool isSameValue(const APSInt &I1, const APSInt &I2) {
    263     if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned())
    264       return I1 == I2;
    265 
    266     // Check for a bit-width mismatch.
    267     if (I1.getBitWidth() > I2.getBitWidth())
    268       return isSameValue(I1, I2.extend(I1.getBitWidth()));
    269     else if (I2.getBitWidth() > I1.getBitWidth())
    270       return isSameValue(I1.extend(I2.getBitWidth()), I2);
    271 
    272     // We have a signedness mismatch. Turn the signed value into an unsigned
    273     // value.
    274     if (I1.isSigned()) {
    275       if (I1.isNegative())
    276         return false;
    277 
    278       return APSInt(I1, true) == I2;
    279     }
    280 
    281     if (I2.isNegative())
    282       return false;
    283 
    284     return I1 == APSInt(I2, true);
    285   }
    286 
    287   /// Profile - Used to insert APSInt objects, or objects that contain APSInt
    288   ///  objects, into FoldingSets.
    289   void Profile(FoldingSetNodeID& ID) const;
    290 };
    291 
    292 inline bool operator==(int64_t V1, const APSInt& V2) {
    293   return V2 == V1;
    294 }
    295 inline bool operator!=(int64_t V1, const APSInt& V2) {
    296   return V2 != V1;
    297 }
    298 
    299 inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) {
    300   I.print(OS, I.isSigned());
    301   return OS;
    302 }
    303 
    304 } // end namespace llvm
    305 
    306 #endif
    307