APSInt.h revision 341825
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
15249423Sdim#ifndef LLVM_ADT_APSINT_H
16249423Sdim#define LLVM_ADT_APSINT_H
17193323Sed
18193323Sed#include "llvm/ADT/APInt.h"
19193323Sed
20193323Sednamespace llvm {
21193323Sed
22314564Sdimclass LLVM_NODISCARD APSInt : public APInt {
23193323Sed  bool IsUnsigned;
24296417Sdim
25193323Sedpublic:
26193323Sed  /// Default constructor that creates an uninitialized APInt.
27249423Sdim  explicit APSInt() : IsUnsigned(false) {}
28193323Sed
29193323Sed  /// APSInt ctor - Create an APSInt with the specified width, default to
30193323Sed  /// unsigned.
31193323Sed  explicit APSInt(uint32_t BitWidth, bool isUnsigned = true)
32193323Sed   : APInt(BitWidth, 0), IsUnsigned(isUnsigned) {}
33193323Sed
34276479Sdim  explicit APSInt(APInt I, bool isUnsigned = true)
35276479Sdim   : APInt(std::move(I)), IsUnsigned(isUnsigned) {}
36193323Sed
37288943Sdim  /// Construct an APSInt from a string representation.
38288943Sdim  ///
39288943Sdim  /// This constructor interprets the string \p Str using the radix of 10.
40288943Sdim  /// The interpretation stops at the end of the string. The bit width of the
41288943Sdim  /// constructed APSInt is determined automatically.
42288943Sdim  ///
43288943Sdim  /// \param Str the string to be interpreted.
44288943Sdim  explicit APSInt(StringRef Str);
45288943Sdim
46276479Sdim  APSInt &operator=(APInt RHS) {
47193323Sed    // Retain our current sign.
48276479Sdim    APInt::operator=(std::move(RHS));
49193323Sed    return *this;
50193323Sed  }
51193323Sed
52193323Sed  APSInt &operator=(uint64_t RHS) {
53193323Sed    // Retain our current sign.
54193323Sed    APInt::operator=(RHS);
55193323Sed    return *this;
56193323Sed  }
57193323Sed
58193323Sed  // Query sign information.
59193323Sed  bool isSigned() const { return !IsUnsigned; }
60193323Sed  bool isUnsigned() const { return IsUnsigned; }
61193323Sed  void setIsUnsigned(bool Val) { IsUnsigned = Val; }
62193323Sed  void setIsSigned(bool Val) { IsUnsigned = !Val; }
63193323Sed
64193323Sed  /// toString - Append this APSInt to the specified SmallString.
65193323Sed  void toString(SmallVectorImpl<char> &Str, unsigned Radix = 10) const {
66193323Sed    APInt::toString(Str, Radix, isSigned());
67193323Sed  }
68193323Sed  /// toString - Converts an APInt to a std::string.  This is an inefficient
69276479Sdim  /// method; you should prefer passing in a SmallString instead.
70193323Sed  std::string toString(unsigned Radix) const {
71193323Sed    return APInt::toString(Radix, isSigned());
72193323Sed  }
73193323Sed  using APInt::toString;
74193323Sed
75341825Sdim  /// Get the correctly-extended \c int64_t value.
76288943Sdim  int64_t getExtValue() const {
77288943Sdim    assert(getMinSignedBits() <= 64 && "Too many bits for int64_t");
78288943Sdim    return isSigned() ? getSExtValue() : getZExtValue();
79288943Sdim  }
80288943Sdim
81314564Sdim  APSInt trunc(uint32_t width) const {
82218893Sdim    return APSInt(APInt::trunc(width), IsUnsigned);
83218893Sdim  }
84218893Sdim
85314564Sdim  APSInt extend(uint32_t width) const {
86193323Sed    if (IsUnsigned)
87218893Sdim      return APSInt(zext(width), IsUnsigned);
88193323Sed    else
89218893Sdim      return APSInt(sext(width), IsUnsigned);
90193323Sed  }
91193323Sed
92314564Sdim  APSInt extOrTrunc(uint32_t width) const {
93314564Sdim    if (IsUnsigned)
94314564Sdim      return APSInt(zextOrTrunc(width), IsUnsigned);
95314564Sdim    else
96314564Sdim      return APSInt(sextOrTrunc(width), IsUnsigned);
97193323Sed  }
98193323Sed
99193323Sed  const APSInt &operator%=(const APSInt &RHS) {
100193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
101193323Sed    if (IsUnsigned)
102193323Sed      *this = urem(RHS);
103193323Sed    else
104193323Sed      *this = srem(RHS);
105193323Sed    return *this;
106193323Sed  }
107193323Sed  const APSInt &operator/=(const APSInt &RHS) {
108193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
109193323Sed    if (IsUnsigned)
110193323Sed      *this = udiv(RHS);
111193323Sed    else
112193323Sed      *this = sdiv(RHS);
113193323Sed    return *this;
114193323Sed  }
115193323Sed  APSInt operator%(const APSInt &RHS) const {
116193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
117193323Sed    return IsUnsigned ? APSInt(urem(RHS), true) : APSInt(srem(RHS), false);
118193323Sed  }
119193323Sed  APSInt operator/(const APSInt &RHS) const {
120193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
121193323Sed    return IsUnsigned ? APSInt(udiv(RHS), true) : APSInt(sdiv(RHS), false);
122193323Sed  }
123193323Sed
124193323Sed  APSInt operator>>(unsigned Amt) const {
125193323Sed    return IsUnsigned ? APSInt(lshr(Amt), true) : APSInt(ashr(Amt), false);
126193323Sed  }
127193323Sed  APSInt& operator>>=(unsigned Amt) {
128321369Sdim    if (IsUnsigned)
129321369Sdim      lshrInPlace(Amt);
130321369Sdim    else
131321369Sdim      ashrInPlace(Amt);
132193323Sed    return *this;
133193323Sed  }
134193323Sed
135193323Sed  inline bool operator<(const APSInt& RHS) const {
136193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
137193323Sed    return IsUnsigned ? ult(RHS) : slt(RHS);
138193323Sed  }
139193323Sed  inline bool operator>(const APSInt& RHS) const {
140193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
141193323Sed    return IsUnsigned ? ugt(RHS) : sgt(RHS);
142193323Sed  }
143193323Sed  inline bool operator<=(const APSInt& RHS) const {
144193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
145193323Sed    return IsUnsigned ? ule(RHS) : sle(RHS);
146193323Sed  }
147193323Sed  inline bool operator>=(const APSInt& RHS) const {
148193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
149193323Sed    return IsUnsigned ? uge(RHS) : sge(RHS);
150193323Sed  }
151239462Sdim  inline bool operator==(const APSInt& RHS) const {
152239462Sdim    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
153239462Sdim    return eq(RHS);
154239462Sdim  }
155239462Sdim  inline bool operator!=(const APSInt& RHS) const {
156239462Sdim    return !((*this) == RHS);
157239462Sdim  }
158288943Sdim
159288943Sdim  bool operator==(int64_t RHS) const {
160288943Sdim    return compareValues(*this, get(RHS)) == 0;
161239462Sdim  }
162288943Sdim  bool operator!=(int64_t RHS) const {
163288943Sdim    return compareValues(*this, get(RHS)) != 0;
164288943Sdim  }
165288943Sdim  bool operator<=(int64_t RHS) const {
166288943Sdim    return compareValues(*this, get(RHS)) <= 0;
167288943Sdim  }
168288943Sdim  bool operator>=(int64_t RHS) const {
169288943Sdim    return compareValues(*this, get(RHS)) >= 0;
170288943Sdim  }
171288943Sdim  bool operator<(int64_t RHS) const {
172288943Sdim    return compareValues(*this, get(RHS)) < 0;
173288943Sdim  }
174288943Sdim  bool operator>(int64_t RHS) const {
175288943Sdim    return compareValues(*this, get(RHS)) > 0;
176288943Sdim  }
177193323Sed
178193323Sed  // The remaining operators just wrap the logic of APInt, but retain the
179193323Sed  // signedness information.
180193323Sed
181193323Sed  APSInt operator<<(unsigned Bits) const {
182193323Sed    return APSInt(static_cast<const APInt&>(*this) << Bits, IsUnsigned);
183193323Sed  }
184193323Sed  APSInt& operator<<=(unsigned Amt) {
185321369Sdim    static_cast<APInt&>(*this) <<= Amt;
186193323Sed    return *this;
187193323Sed  }
188193323Sed
189193323Sed  APSInt& operator++() {
190249423Sdim    ++(static_cast<APInt&>(*this));
191193323Sed    return *this;
192193323Sed  }
193193323Sed  APSInt& operator--() {
194249423Sdim    --(static_cast<APInt&>(*this));
195193323Sed    return *this;
196193323Sed  }
197193323Sed  APSInt operator++(int) {
198193323Sed    return APSInt(++static_cast<APInt&>(*this), IsUnsigned);
199193323Sed  }
200193323Sed  APSInt operator--(int) {
201193323Sed    return APSInt(--static_cast<APInt&>(*this), IsUnsigned);
202193323Sed  }
203193323Sed  APSInt operator-() const {
204193323Sed    return APSInt(-static_cast<const APInt&>(*this), IsUnsigned);
205193323Sed  }
206193323Sed  APSInt& operator+=(const APSInt& RHS) {
207193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
208193323Sed    static_cast<APInt&>(*this) += RHS;
209193323Sed    return *this;
210193323Sed  }
211193323Sed  APSInt& operator-=(const APSInt& RHS) {
212193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
213193323Sed    static_cast<APInt&>(*this) -= RHS;
214193323Sed    return *this;
215193323Sed  }
216193323Sed  APSInt& operator*=(const APSInt& RHS) {
217193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
218193323Sed    static_cast<APInt&>(*this) *= RHS;
219193323Sed    return *this;
220193323Sed  }
221193323Sed  APSInt& operator&=(const APSInt& RHS) {
222193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
223193323Sed    static_cast<APInt&>(*this) &= RHS;
224193323Sed    return *this;
225193323Sed  }
226193323Sed  APSInt& operator|=(const APSInt& RHS) {
227193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
228193323Sed    static_cast<APInt&>(*this) |= RHS;
229193323Sed    return *this;
230193323Sed  }
231193323Sed  APSInt& operator^=(const APSInt& RHS) {
232193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
233193323Sed    static_cast<APInt&>(*this) ^= RHS;
234193323Sed    return *this;
235193323Sed  }
236193323Sed
237193323Sed  APSInt operator&(const APSInt& RHS) const {
238193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
239193323Sed    return APSInt(static_cast<const APInt&>(*this) & RHS, IsUnsigned);
240193323Sed  }
241193323Sed
242193323Sed  APSInt operator|(const APSInt& RHS) const {
243193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
244193323Sed    return APSInt(static_cast<const APInt&>(*this) | RHS, IsUnsigned);
245193323Sed  }
246193323Sed
247296417Sdim  APSInt operator^(const APSInt &RHS) const {
248193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
249193323Sed    return APSInt(static_cast<const APInt&>(*this) ^ RHS, IsUnsigned);
250193323Sed  }
251193323Sed
252193323Sed  APSInt operator*(const APSInt& RHS) const {
253193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
254193323Sed    return APSInt(static_cast<const APInt&>(*this) * RHS, IsUnsigned);
255193323Sed  }
256193323Sed  APSInt operator+(const APSInt& RHS) const {
257193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
258193323Sed    return APSInt(static_cast<const APInt&>(*this) + RHS, IsUnsigned);
259193323Sed  }
260193323Sed  APSInt operator-(const APSInt& RHS) const {
261193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
262193323Sed    return APSInt(static_cast<const APInt&>(*this) - RHS, IsUnsigned);
263193323Sed  }
264193323Sed  APSInt operator~() const {
265193323Sed    return APSInt(~static_cast<const APInt&>(*this), IsUnsigned);
266193323Sed  }
267193323Sed
268193323Sed  /// getMaxValue - Return the APSInt representing the maximum integer value
269193323Sed  ///  with the given bit width and signedness.
270193323Sed  static APSInt getMaxValue(uint32_t numBits, bool Unsigned) {
271193323Sed    return APSInt(Unsigned ? APInt::getMaxValue(numBits)
272193323Sed                           : APInt::getSignedMaxValue(numBits), Unsigned);
273193323Sed  }
274193323Sed
275193323Sed  /// getMinValue - Return the APSInt representing the minimum integer value
276193323Sed  ///  with the given bit width and signedness.
277193323Sed  static APSInt getMinValue(uint32_t numBits, bool Unsigned) {
278193323Sed    return APSInt(Unsigned ? APInt::getMinValue(numBits)
279193323Sed                           : APInt::getSignedMinValue(numBits), Unsigned);
280193323Sed  }
281193323Sed
282341825Sdim  /// Determine if two APSInts have the same value, zero- or
283296417Sdim  /// sign-extending as needed.
284239462Sdim  static bool isSameValue(const APSInt &I1, const APSInt &I2) {
285288943Sdim    return !compareValues(I1, I2);
286288943Sdim  }
287288943Sdim
288341825Sdim  /// Compare underlying values of two numbers.
289288943Sdim  static int compareValues(const APSInt &I1, const APSInt &I2) {
290239462Sdim    if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned())
291321369Sdim      return I1.IsUnsigned ? I1.compare(I2) : I1.compareSigned(I2);
292239462Sdim
293239462Sdim    // Check for a bit-width mismatch.
294239462Sdim    if (I1.getBitWidth() > I2.getBitWidth())
295288943Sdim      return compareValues(I1, I2.extend(I1.getBitWidth()));
296321369Sdim    if (I2.getBitWidth() > I1.getBitWidth())
297288943Sdim      return compareValues(I1.extend(I2.getBitWidth()), I2);
298239462Sdim
299280031Sdim    // We have a signedness mismatch. Check for negative values and do an
300288943Sdim    // unsigned compare if both are positive.
301288943Sdim    if (I1.isSigned()) {
302288943Sdim      assert(!I2.isSigned() && "Expected signed mismatch");
303288943Sdim      if (I1.isNegative())
304288943Sdim        return -1;
305288943Sdim    } else {
306288943Sdim      assert(I2.isSigned() && "Expected signed mismatch");
307288943Sdim      if (I2.isNegative())
308288943Sdim        return 1;
309288943Sdim    }
310239462Sdim
311321369Sdim    return I1.compare(I2);
312239462Sdim  }
313239462Sdim
314288943Sdim  static APSInt get(int64_t X) { return APSInt(APInt(64, X), false); }
315288943Sdim  static APSInt getUnsigned(uint64_t X) { return APSInt(APInt(64, X), true); }
316288943Sdim
317193323Sed  /// Profile - Used to insert APSInt objects, or objects that contain APSInt
318193323Sed  ///  objects, into FoldingSets.
319193323Sed  void Profile(FoldingSetNodeID& ID) const;
320193323Sed};
321193323Sed
322288943Sdiminline bool operator==(int64_t V1, const APSInt &V2) { return V2 == V1; }
323288943Sdiminline bool operator!=(int64_t V1, const APSInt &V2) { return V2 != V1; }
324288943Sdiminline bool operator<=(int64_t V1, const APSInt &V2) { return V2 >= V1; }
325288943Sdiminline bool operator>=(int64_t V1, const APSInt &V2) { return V2 <= V1; }
326288943Sdiminline bool operator<(int64_t V1, const APSInt &V2) { return V2 > V1; }
327288943Sdiminline bool operator>(int64_t V1, const APSInt &V2) { return V2 < V1; }
328239462Sdim
329193323Sedinline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) {
330193323Sed  I.print(OS, I.isSigned());
331193323Sed  return OS;
332193323Sed}
333193323Sed
334193323Sed} // end namespace llvm
335193323Sed
336193323Sed#endif
337