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_APSINT_H
     16 #define LLVM_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() {}
     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 
    139   // The remaining operators just wrap the logic of APInt, but retain the
    140   // signedness information.
    141 
    142   APSInt operator<<(unsigned Bits) const {
    143     return APSInt(static_cast<const APInt&>(*this) << Bits, IsUnsigned);
    144   }
    145   APSInt& operator<<=(unsigned Amt) {
    146     *this = *this << Amt;
    147     return *this;
    148   }
    149 
    150   APSInt& operator++() {
    151     static_cast<APInt&>(*this)++;
    152     return *this;
    153   }
    154   APSInt& operator--() {
    155     static_cast<APInt&>(*this)--;
    156     return *this;
    157   }
    158   APSInt operator++(int) {
    159     return APSInt(++static_cast<APInt&>(*this), IsUnsigned);
    160   }
    161   APSInt operator--(int) {
    162     return APSInt(--static_cast<APInt&>(*this), IsUnsigned);
    163   }
    164   APSInt operator-() const {
    165     return APSInt(-static_cast<const APInt&>(*this), IsUnsigned);
    166   }
    167   APSInt& operator+=(const APSInt& RHS) {
    168     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    169     static_cast<APInt&>(*this) += RHS;
    170     return *this;
    171   }
    172   APSInt& operator-=(const APSInt& RHS) {
    173     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    174     static_cast<APInt&>(*this) -= RHS;
    175     return *this;
    176   }
    177   APSInt& operator*=(const APSInt& RHS) {
    178     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    179     static_cast<APInt&>(*this) *= RHS;
    180     return *this;
    181   }
    182   APSInt& operator&=(const APSInt& RHS) {
    183     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    184     static_cast<APInt&>(*this) &= RHS;
    185     return *this;
    186   }
    187   APSInt& operator|=(const APSInt& RHS) {
    188     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    189     static_cast<APInt&>(*this) |= RHS;
    190     return *this;
    191   }
    192   APSInt& operator^=(const APSInt& RHS) {
    193     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    194     static_cast<APInt&>(*this) ^= RHS;
    195     return *this;
    196   }
    197 
    198   APSInt operator&(const APSInt& RHS) const {
    199     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    200     return APSInt(static_cast<const APInt&>(*this) & RHS, IsUnsigned);
    201   }
    202   APSInt And(const APSInt& RHS) const {
    203     return this->operator&(RHS);
    204   }
    205 
    206   APSInt operator|(const APSInt& RHS) const {
    207     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    208     return APSInt(static_cast<const APInt&>(*this) | RHS, IsUnsigned);
    209   }
    210   APSInt Or(const APSInt& RHS) const {
    211     return this->operator|(RHS);
    212   }
    213 
    214 
    215   APSInt operator^(const APSInt& RHS) const {
    216     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    217     return APSInt(static_cast<const APInt&>(*this) ^ RHS, IsUnsigned);
    218   }
    219   APSInt Xor(const APSInt& RHS) const {
    220     return this->operator^(RHS);
    221   }
    222 
    223   APSInt operator*(const APSInt& RHS) const {
    224     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    225     return APSInt(static_cast<const APInt&>(*this) * RHS, IsUnsigned);
    226   }
    227   APSInt operator+(const APSInt& RHS) const {
    228     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    229     return APSInt(static_cast<const APInt&>(*this) + RHS, IsUnsigned);
    230   }
    231   APSInt operator-(const APSInt& RHS) const {
    232     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
    233     return APSInt(static_cast<const APInt&>(*this) - RHS, IsUnsigned);
    234   }
    235   APSInt operator~() const {
    236     return APSInt(~static_cast<const APInt&>(*this), IsUnsigned);
    237   }
    238 
    239   /// getMaxValue - Return the APSInt representing the maximum integer value
    240   ///  with the given bit width and signedness.
    241   static APSInt getMaxValue(uint32_t numBits, bool Unsigned) {
    242     return APSInt(Unsigned ? APInt::getMaxValue(numBits)
    243                            : APInt::getSignedMaxValue(numBits), Unsigned);
    244   }
    245 
    246   /// getMinValue - Return the APSInt representing the minimum integer value
    247   ///  with the given bit width and signedness.
    248   static APSInt getMinValue(uint32_t numBits, bool Unsigned) {
    249     return APSInt(Unsigned ? APInt::getMinValue(numBits)
    250                            : APInt::getSignedMinValue(numBits), Unsigned);
    251   }
    252 
    253   /// Profile - Used to insert APSInt objects, or objects that contain APSInt
    254   ///  objects, into FoldingSets.
    255   void Profile(FoldingSetNodeID& ID) const;
    256 };
    257 
    258 inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) {
    259   I.print(OS, I.isSigned());
    260   return OS;
    261 }
    262 
    263 
    264 } // end namespace llvm
    265 
    266 #endif
    267