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
20namespace llvm {
21
22class APSInt : public APInt {
23  bool IsUnsigned;
24public:
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 LLVM_ATTRIBUTE_UNUSED_RESULT trunc(uint32_t width) const {
72    return APSInt(APInt::trunc(width), IsUnsigned);
73  }
74
75  APSInt LLVM_ATTRIBUTE_UNUSED_RESULT 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 LLVM_ATTRIBUTE_UNUSED_RESULT 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 LLVM_ATTRIBUTE_UNUSED_RESULT 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 LLVM_ATTRIBUTE_UNUSED_RESULT 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 LLVM_ATTRIBUTE_UNUSED_RESULT 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
298inline bool operator==(int64_t V1, const APSInt& V2) {
299  return V2 == V1;
300}
301inline bool operator!=(int64_t V1, const APSInt& V2) {
302  return V2 != V1;
303}
304
305inline 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