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