1193323Sed//===-- llvm/ADT/APSInt.h - Arbitrary Precision Signed Int -----*- C++ -*--===//
2193323Sed//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6193323Sed//
7193323Sed//===----------------------------------------------------------------------===//
8193323Sed//
9193323Sed// This file implements the APSInt class, which is a simple class that
10193323Sed// represents an arbitrary sized integer that knows its signedness.
11193323Sed//
12193323Sed//===----------------------------------------------------------------------===//
13193323Sed
14249423Sdim#ifndef LLVM_ADT_APSINT_H
15249423Sdim#define LLVM_ADT_APSINT_H
16193323Sed
17193323Sed#include "llvm/ADT/APInt.h"
18193323Sed
19193323Sednamespace llvm {
20193323Sed
21314564Sdimclass LLVM_NODISCARD APSInt : public APInt {
22193323Sed  bool IsUnsigned;
23296417Sdim
24193323Sedpublic:
25193323Sed  /// Default constructor that creates an uninitialized APInt.
26249423Sdim  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
33276479Sdim  explicit APSInt(APInt I, bool isUnsigned = true)
34276479Sdim   : APInt(std::move(I)), IsUnsigned(isUnsigned) {}
35193323Sed
36288943Sdim  /// Construct an APSInt from a string representation.
37288943Sdim  ///
38288943Sdim  /// This constructor interprets the string \p Str using the radix of 10.
39288943Sdim  /// The interpretation stops at the end of the string. The bit width of the
40288943Sdim  /// constructed APSInt is determined automatically.
41288943Sdim  ///
42288943Sdim  /// \param Str the string to be interpreted.
43288943Sdim  explicit APSInt(StringRef Str);
44288943Sdim
45353358Sdim  /// Determine sign of this APSInt.
46353358Sdim  ///
47353358Sdim  /// \returns true if this APSInt is negative, false otherwise
48353358Sdim  bool isNegative() const { return isSigned() && APInt::isNegative(); }
49353358Sdim
50353358Sdim  /// Determine if this APSInt Value is non-negative (>= 0)
51353358Sdim  ///
52353358Sdim  /// \returns true if this APSInt is non-negative, false otherwise
53353358Sdim  bool isNonNegative() const { return !isNegative(); }
54353358Sdim
55353358Sdim  /// Determine if this APSInt Value is positive.
56353358Sdim  ///
57353358Sdim  /// This tests if the value of this APSInt is positive (> 0). Note
58353358Sdim  /// that 0 is not a positive value.
59353358Sdim  ///
60353358Sdim  /// \returns true if this APSInt is positive.
61353358Sdim  bool isStrictlyPositive() const { return isNonNegative() && !isNullValue(); }
62353358Sdim
63276479Sdim  APSInt &operator=(APInt RHS) {
64193323Sed    // Retain our current sign.
65276479Sdim    APInt::operator=(std::move(RHS));
66193323Sed    return *this;
67193323Sed  }
68193323Sed
69193323Sed  APSInt &operator=(uint64_t RHS) {
70193323Sed    // Retain our current sign.
71193323Sed    APInt::operator=(RHS);
72193323Sed    return *this;
73193323Sed  }
74193323Sed
75193323Sed  // Query sign information.
76193323Sed  bool isSigned() const { return !IsUnsigned; }
77193323Sed  bool isUnsigned() const { return IsUnsigned; }
78193323Sed  void setIsUnsigned(bool Val) { IsUnsigned = Val; }
79193323Sed  void setIsSigned(bool Val) { IsUnsigned = !Val; }
80193323Sed
81193323Sed  /// toString - Append this APSInt to the specified SmallString.
82193323Sed  void toString(SmallVectorImpl<char> &Str, unsigned Radix = 10) const {
83193323Sed    APInt::toString(Str, Radix, isSigned());
84193323Sed  }
85193323Sed  /// toString - Converts an APInt to a std::string.  This is an inefficient
86276479Sdim  /// method; you should prefer passing in a SmallString instead.
87193323Sed  std::string toString(unsigned Radix) const {
88193323Sed    return APInt::toString(Radix, isSigned());
89193323Sed  }
90193323Sed  using APInt::toString;
91193323Sed
92341825Sdim  /// Get the correctly-extended \c int64_t value.
93288943Sdim  int64_t getExtValue() const {
94288943Sdim    assert(getMinSignedBits() <= 64 && "Too many bits for int64_t");
95288943Sdim    return isSigned() ? getSExtValue() : getZExtValue();
96288943Sdim  }
97288943Sdim
98314564Sdim  APSInt trunc(uint32_t width) const {
99218893Sdim    return APSInt(APInt::trunc(width), IsUnsigned);
100218893Sdim  }
101218893Sdim
102314564Sdim  APSInt extend(uint32_t width) const {
103193323Sed    if (IsUnsigned)
104218893Sdim      return APSInt(zext(width), IsUnsigned);
105193323Sed    else
106218893Sdim      return APSInt(sext(width), IsUnsigned);
107193323Sed  }
108193323Sed
109314564Sdim  APSInt extOrTrunc(uint32_t width) const {
110314564Sdim    if (IsUnsigned)
111314564Sdim      return APSInt(zextOrTrunc(width), IsUnsigned);
112314564Sdim    else
113314564Sdim      return APSInt(sextOrTrunc(width), IsUnsigned);
114193323Sed  }
115193323Sed
116193323Sed  const APSInt &operator%=(const APSInt &RHS) {
117193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
118193323Sed    if (IsUnsigned)
119193323Sed      *this = urem(RHS);
120193323Sed    else
121193323Sed      *this = srem(RHS);
122193323Sed    return *this;
123193323Sed  }
124193323Sed  const APSInt &operator/=(const APSInt &RHS) {
125193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
126193323Sed    if (IsUnsigned)
127193323Sed      *this = udiv(RHS);
128193323Sed    else
129193323Sed      *this = sdiv(RHS);
130193323Sed    return *this;
131193323Sed  }
132193323Sed  APSInt operator%(const APSInt &RHS) const {
133193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
134193323Sed    return IsUnsigned ? APSInt(urem(RHS), true) : APSInt(srem(RHS), false);
135193323Sed  }
136193323Sed  APSInt operator/(const APSInt &RHS) const {
137193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
138193323Sed    return IsUnsigned ? APSInt(udiv(RHS), true) : APSInt(sdiv(RHS), false);
139193323Sed  }
140193323Sed
141193323Sed  APSInt operator>>(unsigned Amt) const {
142193323Sed    return IsUnsigned ? APSInt(lshr(Amt), true) : APSInt(ashr(Amt), false);
143193323Sed  }
144193323Sed  APSInt& operator>>=(unsigned Amt) {
145321369Sdim    if (IsUnsigned)
146321369Sdim      lshrInPlace(Amt);
147321369Sdim    else
148321369Sdim      ashrInPlace(Amt);
149193323Sed    return *this;
150193323Sed  }
151193323Sed
152193323Sed  inline bool operator<(const APSInt& RHS) const {
153193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
154193323Sed    return IsUnsigned ? ult(RHS) : slt(RHS);
155193323Sed  }
156193323Sed  inline bool operator>(const APSInt& RHS) const {
157193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
158193323Sed    return IsUnsigned ? ugt(RHS) : sgt(RHS);
159193323Sed  }
160193323Sed  inline bool operator<=(const APSInt& RHS) const {
161193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
162193323Sed    return IsUnsigned ? ule(RHS) : sle(RHS);
163193323Sed  }
164193323Sed  inline bool operator>=(const APSInt& RHS) const {
165193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
166193323Sed    return IsUnsigned ? uge(RHS) : sge(RHS);
167193323Sed  }
168239462Sdim  inline bool operator==(const APSInt& RHS) const {
169239462Sdim    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
170239462Sdim    return eq(RHS);
171239462Sdim  }
172239462Sdim  inline bool operator!=(const APSInt& RHS) const {
173239462Sdim    return !((*this) == RHS);
174239462Sdim  }
175288943Sdim
176288943Sdim  bool operator==(int64_t RHS) const {
177288943Sdim    return compareValues(*this, get(RHS)) == 0;
178239462Sdim  }
179288943Sdim  bool operator!=(int64_t RHS) const {
180288943Sdim    return compareValues(*this, get(RHS)) != 0;
181288943Sdim  }
182288943Sdim  bool operator<=(int64_t RHS) const {
183288943Sdim    return compareValues(*this, get(RHS)) <= 0;
184288943Sdim  }
185288943Sdim  bool operator>=(int64_t RHS) const {
186288943Sdim    return compareValues(*this, get(RHS)) >= 0;
187288943Sdim  }
188288943Sdim  bool operator<(int64_t RHS) const {
189288943Sdim    return compareValues(*this, get(RHS)) < 0;
190288943Sdim  }
191288943Sdim  bool operator>(int64_t RHS) const {
192288943Sdim    return compareValues(*this, get(RHS)) > 0;
193288943Sdim  }
194193323Sed
195193323Sed  // The remaining operators just wrap the logic of APInt, but retain the
196193323Sed  // signedness information.
197193323Sed
198193323Sed  APSInt operator<<(unsigned Bits) const {
199193323Sed    return APSInt(static_cast<const APInt&>(*this) << Bits, IsUnsigned);
200193323Sed  }
201193323Sed  APSInt& operator<<=(unsigned Amt) {
202321369Sdim    static_cast<APInt&>(*this) <<= Amt;
203193323Sed    return *this;
204193323Sed  }
205193323Sed
206193323Sed  APSInt& operator++() {
207249423Sdim    ++(static_cast<APInt&>(*this));
208193323Sed    return *this;
209193323Sed  }
210193323Sed  APSInt& operator--() {
211249423Sdim    --(static_cast<APInt&>(*this));
212193323Sed    return *this;
213193323Sed  }
214193323Sed  APSInt operator++(int) {
215193323Sed    return APSInt(++static_cast<APInt&>(*this), IsUnsigned);
216193323Sed  }
217193323Sed  APSInt operator--(int) {
218193323Sed    return APSInt(--static_cast<APInt&>(*this), IsUnsigned);
219193323Sed  }
220193323Sed  APSInt operator-() const {
221193323Sed    return APSInt(-static_cast<const APInt&>(*this), IsUnsigned);
222193323Sed  }
223193323Sed  APSInt& operator+=(const APSInt& RHS) {
224193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
225193323Sed    static_cast<APInt&>(*this) += RHS;
226193323Sed    return *this;
227193323Sed  }
228193323Sed  APSInt& operator-=(const APSInt& RHS) {
229193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
230193323Sed    static_cast<APInt&>(*this) -= RHS;
231193323Sed    return *this;
232193323Sed  }
233193323Sed  APSInt& operator*=(const APSInt& RHS) {
234193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
235193323Sed    static_cast<APInt&>(*this) *= RHS;
236193323Sed    return *this;
237193323Sed  }
238193323Sed  APSInt& operator&=(const APSInt& RHS) {
239193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
240193323Sed    static_cast<APInt&>(*this) &= RHS;
241193323Sed    return *this;
242193323Sed  }
243193323Sed  APSInt& operator|=(const APSInt& RHS) {
244193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
245193323Sed    static_cast<APInt&>(*this) |= RHS;
246193323Sed    return *this;
247193323Sed  }
248193323Sed  APSInt& operator^=(const APSInt& RHS) {
249193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
250193323Sed    static_cast<APInt&>(*this) ^= RHS;
251193323Sed    return *this;
252193323Sed  }
253193323Sed
254193323Sed  APSInt operator&(const APSInt& RHS) const {
255193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
256193323Sed    return APSInt(static_cast<const APInt&>(*this) & RHS, IsUnsigned);
257193323Sed  }
258193323Sed
259193323Sed  APSInt operator|(const APSInt& RHS) const {
260193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
261193323Sed    return APSInt(static_cast<const APInt&>(*this) | RHS, IsUnsigned);
262193323Sed  }
263193323Sed
264296417Sdim  APSInt operator^(const APSInt &RHS) const {
265193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
266193323Sed    return APSInt(static_cast<const APInt&>(*this) ^ RHS, IsUnsigned);
267193323Sed  }
268193323Sed
269193323Sed  APSInt operator*(const APSInt& RHS) const {
270193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
271193323Sed    return APSInt(static_cast<const APInt&>(*this) * RHS, IsUnsigned);
272193323Sed  }
273193323Sed  APSInt operator+(const APSInt& RHS) const {
274193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
275193323Sed    return APSInt(static_cast<const APInt&>(*this) + RHS, IsUnsigned);
276193323Sed  }
277193323Sed  APSInt operator-(const APSInt& RHS) const {
278193323Sed    assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
279193323Sed    return APSInt(static_cast<const APInt&>(*this) - RHS, IsUnsigned);
280193323Sed  }
281193323Sed  APSInt operator~() const {
282193323Sed    return APSInt(~static_cast<const APInt&>(*this), IsUnsigned);
283193323Sed  }
284193323Sed
285193323Sed  /// getMaxValue - Return the APSInt representing the maximum integer value
286193323Sed  ///  with the given bit width and signedness.
287193323Sed  static APSInt getMaxValue(uint32_t numBits, bool Unsigned) {
288193323Sed    return APSInt(Unsigned ? APInt::getMaxValue(numBits)
289193323Sed                           : APInt::getSignedMaxValue(numBits), Unsigned);
290193323Sed  }
291193323Sed
292193323Sed  /// getMinValue - Return the APSInt representing the minimum integer value
293193323Sed  ///  with the given bit width and signedness.
294193323Sed  static APSInt getMinValue(uint32_t numBits, bool Unsigned) {
295193323Sed    return APSInt(Unsigned ? APInt::getMinValue(numBits)
296193323Sed                           : APInt::getSignedMinValue(numBits), Unsigned);
297193323Sed  }
298193323Sed
299341825Sdim  /// Determine if two APSInts have the same value, zero- or
300296417Sdim  /// sign-extending as needed.
301239462Sdim  static bool isSameValue(const APSInt &I1, const APSInt &I2) {
302288943Sdim    return !compareValues(I1, I2);
303288943Sdim  }
304288943Sdim
305341825Sdim  /// Compare underlying values of two numbers.
306288943Sdim  static int compareValues(const APSInt &I1, const APSInt &I2) {
307239462Sdim    if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned())
308321369Sdim      return I1.IsUnsigned ? I1.compare(I2) : I1.compareSigned(I2);
309239462Sdim
310239462Sdim    // Check for a bit-width mismatch.
311239462Sdim    if (I1.getBitWidth() > I2.getBitWidth())
312288943Sdim      return compareValues(I1, I2.extend(I1.getBitWidth()));
313321369Sdim    if (I2.getBitWidth() > I1.getBitWidth())
314288943Sdim      return compareValues(I1.extend(I2.getBitWidth()), I2);
315239462Sdim
316280031Sdim    // We have a signedness mismatch. Check for negative values and do an
317288943Sdim    // unsigned compare if both are positive.
318288943Sdim    if (I1.isSigned()) {
319288943Sdim      assert(!I2.isSigned() && "Expected signed mismatch");
320288943Sdim      if (I1.isNegative())
321288943Sdim        return -1;
322288943Sdim    } else {
323288943Sdim      assert(I2.isSigned() && "Expected signed mismatch");
324288943Sdim      if (I2.isNegative())
325288943Sdim        return 1;
326288943Sdim    }
327239462Sdim
328321369Sdim    return I1.compare(I2);
329239462Sdim  }
330239462Sdim
331288943Sdim  static APSInt get(int64_t X) { return APSInt(APInt(64, X), false); }
332288943Sdim  static APSInt getUnsigned(uint64_t X) { return APSInt(APInt(64, X), true); }
333288943Sdim
334193323Sed  /// Profile - Used to insert APSInt objects, or objects that contain APSInt
335193323Sed  ///  objects, into FoldingSets.
336193323Sed  void Profile(FoldingSetNodeID& ID) const;
337193323Sed};
338193323Sed
339288943Sdiminline bool operator==(int64_t V1, const APSInt &V2) { return V2 == V1; }
340288943Sdiminline bool operator!=(int64_t V1, const APSInt &V2) { return V2 != V1; }
341288943Sdiminline bool operator<=(int64_t V1, const APSInt &V2) { return V2 >= V1; }
342288943Sdiminline bool operator>=(int64_t V1, const APSInt &V2) { return V2 <= V1; }
343288943Sdiminline bool operator<(int64_t V1, const APSInt &V2) { return V2 > V1; }
344288943Sdiminline bool operator>(int64_t V1, const APSInt &V2) { return V2 < V1; }
345239462Sdim
346193323Sedinline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) {
347193323Sed  I.print(OS, I.isSigned());
348193323Sed  return OS;
349193323Sed}
350193323Sed
351193323Sed} // end namespace llvm
352193323Sed
353193323Sed#endif
354