• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
APSInt()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)
APInt(std::move (I))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.
isSigned()49   bool isSigned() const { return !IsUnsigned; }
isUnsigned()50   bool isUnsigned() const { return IsUnsigned; }
setIsUnsigned(bool Val)51   void setIsUnsigned(bool Val) { IsUnsigned = Val; }
setIsSigned(bool 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.
toString(unsigned Radix)60   std::string toString(unsigned Radix) const {
61     return APInt::toString(Radix, isSigned());
62   }
63   using APInt::toString;
64 
trunc(uint32_t width)65   APSInt LLVM_ATTRIBUTE_UNUSED_RESULT trunc(uint32_t width) const {
66     return APSInt(APInt::trunc(width), IsUnsigned);
67   }
68 
extend(uint32_t width)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 
extOrTrunc(uint32_t width)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   }
And(const APSInt & RHS)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   }
Or(const APSInt & RHS)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   }
Xor(const APSInt & RHS)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.
getMaxValue(uint32_t numBits,bool Unsigned)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.
getMinValue(uint32_t numBits,bool Unsigned)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.
isSameValue(const APSInt & I1,const APSInt & I2)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