1193323Sed//===-- llvm/ADT/APSInt.h - Arbitrary Precision Signed Int -----*- C++ -*--===//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed//===----------------------------------------------------------------------===//
9193323Sed//
10193323Sed// This file implements the APSInt class, which is a simple class that
11193323Sed// represents an arbitrary sized integer that knows its signedness.
12193323Sed//
13193323Sed//===----------------------------------------------------------------------===//
14193323Sed
15252723Sdim#ifndef LLVM_ADT_APSINT_H
16252723Sdim#define LLVM_ADT_APSINT_H
17193323Sed
18193323Sed#include "llvm/ADT/APInt.h"
19193323Sed
20193323Sednamespace llvm {
21193323Sed
22193323Sedclass APSInt : public APInt {
23193323Sed  bool IsUnsigned;
24193323Sedpublic:
25193323Sed  /// Default constructor that creates an uninitialized APInt.
26252723Sdim  explicit APSInt() : IsUnsigned(false) {}
27193323Sed
28193323Sed  /// APSInt ctor - Create an APSInt with the specified width, default to
29193323Sed  /// unsigned.
30193323Sed  explicit APSInt(uint32_t BitWidth, bool isUnsigned = true)
31193323Sed   : APInt(BitWidth, 0), IsUnsigned(isUnsigned) {}
32193323Sed
33193323Sed  explicit APSInt(const APInt &I, bool isUnsigned = true)
34193323Sed   : APInt(I), IsUnsigned(isUnsigned) {}
35193323Sed
36193323Sed  APSInt &operator=(const APSInt &RHS) {
37193323Sed    APInt::operator=(RHS);
38193323Sed    IsUnsigned = RHS.IsUnsigned;
39193323Sed    return *this;
40193323Sed  }
41193323Sed
42193323Sed  APSInt &operator=(const APInt &RHS) {
43193323Sed    // Retain our current sign.
44193323Sed    APInt::operator=(RHS);
45193323Sed    return *this;
46193323Sed  }
47193323Sed
48193323Sed  APSInt &operator=(uint64_t RHS) {
49193323Sed    // Retain our current sign.
50193323Sed    APInt::operator=(RHS);
51193323Sed    return *this;
52193323Sed  }
53193323Sed
54193323Sed  // Query sign information.
55193323Sed  bool isSigned() const { return !IsUnsigned; }
56193323Sed  bool isUnsigned() const { return IsUnsigned; }
57193323Sed  void setIsUnsigned(bool Val) { IsUnsigned = Val; }
58193323Sed  void setIsSigned(bool Val) { IsUnsigned = !Val; }
59193323Sed
60193323Sed  /// toString - Append this APSInt to the specified SmallString.
61193323Sed  void toString(SmallVectorImpl<char> &Str, unsigned Radix = 10) const {
62193323Sed    APInt::toString(Str, Radix, isSigned());
63193323Sed  }
64193323Sed  /// toString - Converts an APInt to a std::string.  This is an inefficient
65193323Sed  /// method, your should prefer passing in a SmallString instead.
66193323Sed  std::string toString(unsigned Radix) const {
67193323Sed    return APInt::toString(Radix, isSigned());
68193323Sed  }
69193323Sed  using APInt::toString;
70193323Sed
71263509Sdim  APSInt LLVM_ATTRIBUTE_UNUSED_RESULT trunc(uint32_t width) const {
72218893Sdim    return APSInt(APInt::trunc(width), IsUnsigned);
73218893Sdim  }
74218893Sdim
75263509Sdim  APSInt LLVM_ATTRIBUTE_UNUSED_RESULT extend(uint32_t width) const {
76193323Sed    if (IsUnsigned)
77218893Sdim      return APSInt(zext(width), IsUnsigned);
78193323Sed    else
79218893Sdim      return APSInt(sext(width), IsUnsigned);
80193323Sed  }
81193323Sed
82263509Sdim  APSInt LLVM_ATTRIBUTE_UNUSED_RESULT extOrTrunc(uint32_t width) const {
83193323Sed      if (IsUnsigned)
84218893Sdim        return APSInt(zextOrTrunc(width), IsUnsigned);
85193323Sed      else
86218893Sdim        return APSInt(sextOrTrunc(width), IsUnsigned);
87193323Sed  }
88193323Sed
89193323Sed  const APSInt &operator%=(const APSInt &RHS) {
90193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
91193323Sed    if (IsUnsigned)
92193323Sed      *this = urem(RHS);
93193323Sed    else
94193323Sed      *this = srem(RHS);
95193323Sed    return *this;
96193323Sed  }
97193323Sed  const APSInt &operator/=(const APSInt &RHS) {
98193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
99193323Sed    if (IsUnsigned)
100193323Sed      *this = udiv(RHS);
101193323Sed    else
102193323Sed      *this = sdiv(RHS);
103193323Sed    return *this;
104193323Sed  }
105193323Sed  APSInt operator%(const APSInt &RHS) const {
106193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
107193323Sed    return IsUnsigned ? APSInt(urem(RHS), true) : APSInt(srem(RHS), false);
108193323Sed  }
109193323Sed  APSInt operator/(const APSInt &RHS) const {
110193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
111193323Sed    return IsUnsigned ? APSInt(udiv(RHS), true) : APSInt(sdiv(RHS), false);
112193323Sed  }
113193323Sed
114193323Sed  APSInt operator>>(unsigned Amt) const {
115193323Sed    return IsUnsigned ? APSInt(lshr(Amt), true) : APSInt(ashr(Amt), false);
116193323Sed  }
117193323Sed  APSInt& operator>>=(unsigned Amt) {
118193323Sed    *this = *this >> Amt;
119193323Sed    return *this;
120193323Sed  }
121193323Sed
122193323Sed  inline bool operator<(const APSInt& RHS) const {
123193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
124193323Sed    return IsUnsigned ? ult(RHS) : slt(RHS);
125193323Sed  }
126193323Sed  inline bool operator>(const APSInt& RHS) const {
127193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
128193323Sed    return IsUnsigned ? ugt(RHS) : sgt(RHS);
129193323Sed  }
130193323Sed  inline bool operator<=(const APSInt& RHS) const {
131193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
132193323Sed    return IsUnsigned ? ule(RHS) : sle(RHS);
133193323Sed  }
134193323Sed  inline bool operator>=(const APSInt& RHS) const {
135193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
136193323Sed    return IsUnsigned ? uge(RHS) : sge(RHS);
137193323Sed  }
138245431Sdim  inline bool operator==(const APSInt& RHS) const {
139245431Sdim    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
140245431Sdim    return eq(RHS);
141245431Sdim  }
142245431Sdim  inline bool operator==(int64_t RHS) const {
143245431Sdim    return isSameValue(*this, APSInt(APInt(64, RHS), true));
144245431Sdim  }
145245431Sdim  inline bool operator!=(const APSInt& RHS) const {
146245431Sdim    return !((*this) == RHS);
147245431Sdim  }
148245431Sdim  inline bool operator!=(int64_t RHS) const {
149245431Sdim    return !((*this) == RHS);
150245431Sdim  }
151193323Sed
152193323Sed  // The remaining operators just wrap the logic of APInt, but retain the
153193323Sed  // signedness information.
154193323Sed
155193323Sed  APSInt operator<<(unsigned Bits) const {
156193323Sed    return APSInt(static_cast<const APInt&>(*this) << Bits, IsUnsigned);
157193323Sed  }
158193323Sed  APSInt& operator<<=(unsigned Amt) {
159193323Sed    *this = *this << Amt;
160193323Sed    return *this;
161193323Sed  }
162193323Sed
163193323Sed  APSInt& operator++() {
164252723Sdim    ++(static_cast<APInt&>(*this));
165193323Sed    return *this;
166193323Sed  }
167193323Sed  APSInt& operator--() {
168252723Sdim    --(static_cast<APInt&>(*this));
169193323Sed    return *this;
170193323Sed  }
171193323Sed  APSInt operator++(int) {
172193323Sed    return APSInt(++static_cast<APInt&>(*this), IsUnsigned);
173193323Sed  }
174193323Sed  APSInt operator--(int) {
175193323Sed    return APSInt(--static_cast<APInt&>(*this), IsUnsigned);
176193323Sed  }
177193323Sed  APSInt operator-() const {
178193323Sed    return APSInt(-static_cast<const APInt&>(*this), IsUnsigned);
179193323Sed  }
180193323Sed  APSInt& operator+=(const APSInt& RHS) {
181193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
182193323Sed    static_cast<APInt&>(*this) += RHS;
183193323Sed    return *this;
184193323Sed  }
185193323Sed  APSInt& operator-=(const APSInt& RHS) {
186193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
187193323Sed    static_cast<APInt&>(*this) -= RHS;
188193323Sed    return *this;
189193323Sed  }
190193323Sed  APSInt& operator*=(const APSInt& RHS) {
191193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
192193323Sed    static_cast<APInt&>(*this) *= RHS;
193193323Sed    return *this;
194193323Sed  }
195193323Sed  APSInt& operator&=(const APSInt& RHS) {
196193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
197193323Sed    static_cast<APInt&>(*this) &= RHS;
198193323Sed    return *this;
199193323Sed  }
200193323Sed  APSInt& operator|=(const APSInt& RHS) {
201193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
202193323Sed    static_cast<APInt&>(*this) |= RHS;
203193323Sed    return *this;
204193323Sed  }
205193323Sed  APSInt& operator^=(const APSInt& RHS) {
206193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
207193323Sed    static_cast<APInt&>(*this) ^= RHS;
208193323Sed    return *this;
209193323Sed  }
210193323Sed
211193323Sed  APSInt operator&(const APSInt& RHS) const {
212193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
213193323Sed    return APSInt(static_cast<const APInt&>(*this) & RHS, IsUnsigned);
214193323Sed  }
215263509Sdim  APSInt LLVM_ATTRIBUTE_UNUSED_RESULT And(const APSInt& RHS) const {
216193323Sed    return this->operator&(RHS);
217193323Sed  }
218193323Sed
219193323Sed  APSInt operator|(const APSInt& RHS) const {
220193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
221193323Sed    return APSInt(static_cast<const APInt&>(*this) | RHS, IsUnsigned);
222193323Sed  }
223263509Sdim  APSInt LLVM_ATTRIBUTE_UNUSED_RESULT Or(const APSInt& RHS) const {
224193323Sed    return this->operator|(RHS);
225193323Sed  }
226193323Sed
227193323Sed
228193323Sed  APSInt operator^(const APSInt& RHS) const {
229193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
230193323Sed    return APSInt(static_cast<const APInt&>(*this) ^ RHS, IsUnsigned);
231193323Sed  }
232263509Sdim  APSInt LLVM_ATTRIBUTE_UNUSED_RESULT Xor(const APSInt& RHS) const {
233193323Sed    return this->operator^(RHS);
234193323Sed  }
235193323Sed
236193323Sed  APSInt operator*(const APSInt& RHS) const {
237193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
238193323Sed    return APSInt(static_cast<const APInt&>(*this) * RHS, IsUnsigned);
239193323Sed  }
240193323Sed  APSInt operator+(const APSInt& RHS) const {
241193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
242193323Sed    return APSInt(static_cast<const APInt&>(*this) + RHS, IsUnsigned);
243193323Sed  }
244193323Sed  APSInt operator-(const APSInt& RHS) const {
245193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
246193323Sed    return APSInt(static_cast<const APInt&>(*this) - RHS, IsUnsigned);
247193323Sed  }
248193323Sed  APSInt operator~() const {
249193323Sed    return APSInt(~static_cast<const APInt&>(*this), IsUnsigned);
250193323Sed  }
251193323Sed
252193323Sed  /// getMaxValue - Return the APSInt representing the maximum integer value
253193323Sed  ///  with the given bit width and signedness.
254193323Sed  static APSInt getMaxValue(uint32_t numBits, bool Unsigned) {
255193323Sed    return APSInt(Unsigned ? APInt::getMaxValue(numBits)
256193323Sed                           : APInt::getSignedMaxValue(numBits), Unsigned);
257193323Sed  }
258193323Sed
259193323Sed  /// getMinValue - Return the APSInt representing the minimum integer value
260193323Sed  ///  with the given bit width and signedness.
261193323Sed  static APSInt getMinValue(uint32_t numBits, bool Unsigned) {
262193323Sed    return APSInt(Unsigned ? APInt::getMinValue(numBits)
263193323Sed                           : APInt::getSignedMinValue(numBits), Unsigned);
264193323Sed  }
265193323Sed
266245431Sdim  /// \brief Determine if two APSInts have the same value, zero- or
267245431Sdim  /// sign-extending as needed.
268245431Sdim  static bool isSameValue(const APSInt &I1, const APSInt &I2) {
269245431Sdim    if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned())
270245431Sdim      return I1 == I2;
271245431Sdim
272245431Sdim    // Check for a bit-width mismatch.
273245431Sdim    if (I1.getBitWidth() > I2.getBitWidth())
274245431Sdim      return isSameValue(I1, I2.extend(I1.getBitWidth()));
275245431Sdim    else if (I2.getBitWidth() > I1.getBitWidth())
276245431Sdim      return isSameValue(I1.extend(I2.getBitWidth()), I2);
277245431Sdim
278245431Sdim    // We have a signedness mismatch. Turn the signed value into an unsigned
279245431Sdim    // value.
280245431Sdim    if (I1.isSigned()) {
281245431Sdim      if (I1.isNegative())
282245431Sdim        return false;
283245431Sdim
284245431Sdim      return APSInt(I1, true) == I2;
285245431Sdim    }
286245431Sdim
287245431Sdim    if (I2.isNegative())
288245431Sdim      return false;
289245431Sdim
290245431Sdim    return I1 == APSInt(I2, true);
291245431Sdim  }
292245431Sdim
293193323Sed  /// Profile - Used to insert APSInt objects, or objects that contain APSInt
294193323Sed  ///  objects, into FoldingSets.
295193323Sed  void Profile(FoldingSetNodeID& ID) const;
296193323Sed};
297193323Sed
298245431Sdiminline bool operator==(int64_t V1, const APSInt& V2) {
299245431Sdim  return V2 == V1;
300245431Sdim}
301245431Sdiminline bool operator!=(int64_t V1, const APSInt& V2) {
302245431Sdim  return V2 != V1;
303245431Sdim}
304245431Sdim
305193323Sedinline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) {
306193323Sed  I.print(OS, I.isSigned());
307193323Sed  return OS;
308193323Sed}
309193323Sed
310193323Sed} // end namespace llvm
311193323Sed
312193323Sed#endif
313