APSInt.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. //===-- llvm/ADT/APSInt.h - Arbitrary Precision Signed Int -----*- C++ -*--===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file implements the APSInt class, which is a simple class that
  10. // represents an arbitrary sized integer that knows its signedness.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_ADT_APSINT_H
  14. #define LLVM_ADT_APSINT_H
  15. #include "llvm/ADT/APInt.h"
  16. namespace llvm {
  17. /// An arbitrary precision integer that knows its signedness.
  18. class LLVM_NODISCARD APSInt : public APInt {
  19. bool IsUnsigned;
  20. public:
  21. /// Default constructor that creates an uninitialized APInt.
  22. explicit APSInt() : IsUnsigned(false) {}
  23. /// Create an APSInt with the specified width, default to unsigned.
  24. explicit APSInt(uint32_t BitWidth, bool isUnsigned = true)
  25. : APInt(BitWidth, 0), IsUnsigned(isUnsigned) {}
  26. explicit APSInt(APInt I, bool isUnsigned = true)
  27. : APInt(std::move(I)), IsUnsigned(isUnsigned) {}
  28. /// Construct an APSInt from a string representation.
  29. ///
  30. /// This constructor interprets the string \p Str using the radix of 10.
  31. /// The interpretation stops at the end of the string. The bit width of the
  32. /// constructed APSInt is determined automatically.
  33. ///
  34. /// \param Str the string to be interpreted.
  35. explicit APSInt(StringRef Str);
  36. /// Determine sign of this APSInt.
  37. ///
  38. /// \returns true if this APSInt is negative, false otherwise
  39. bool isNegative() const { return isSigned() && APInt::isNegative(); }
  40. /// Determine if this APSInt Value is non-negative (>= 0)
  41. ///
  42. /// \returns true if this APSInt is non-negative, false otherwise
  43. bool isNonNegative() const { return !isNegative(); }
  44. /// Determine if this APSInt Value is positive.
  45. ///
  46. /// This tests if the value of this APSInt is positive (> 0). Note
  47. /// that 0 is not a positive value.
  48. ///
  49. /// \returns true if this APSInt is positive.
  50. bool isStrictlyPositive() const { return isNonNegative() && !isNullValue(); }
  51. APSInt &operator=(APInt RHS) {
  52. // Retain our current sign.
  53. APInt::operator=(std::move(RHS));
  54. return *this;
  55. }
  56. APSInt &operator=(uint64_t RHS) {
  57. // Retain our current sign.
  58. APInt::operator=(RHS);
  59. return *this;
  60. }
  61. // Query sign information.
  62. bool isSigned() const { return !IsUnsigned; }
  63. bool isUnsigned() const { return IsUnsigned; }
  64. void setIsUnsigned(bool Val) { IsUnsigned = Val; }
  65. void setIsSigned(bool Val) { IsUnsigned = !Val; }
  66. /// Append this APSInt to the specified SmallString.
  67. void toString(SmallVectorImpl<char> &Str, unsigned Radix = 10) const {
  68. APInt::toString(Str, Radix, isSigned());
  69. }
  70. /// Converts an APInt to a std::string. This is an inefficient
  71. /// method; you should prefer passing in a SmallString instead.
  72. std::string toString(unsigned Radix) const {
  73. return APInt::toString(Radix, isSigned());
  74. }
  75. using APInt::toString;
  76. /// Get the correctly-extended \c int64_t value.
  77. int64_t getExtValue() const {
  78. assert(getMinSignedBits() <= 64 && "Too many bits for int64_t");
  79. return isSigned() ? getSExtValue() : getZExtValue();
  80. }
  81. APSInt trunc(uint32_t width) const {
  82. return APSInt(APInt::trunc(width), IsUnsigned);
  83. }
  84. APSInt extend(uint32_t width) const {
  85. if (IsUnsigned)
  86. return APSInt(zext(width), IsUnsigned);
  87. else
  88. return APSInt(sext(width), IsUnsigned);
  89. }
  90. APSInt extOrTrunc(uint32_t width) const {
  91. if (IsUnsigned)
  92. return APSInt(zextOrTrunc(width), IsUnsigned);
  93. else
  94. return APSInt(sextOrTrunc(width), IsUnsigned);
  95. }
  96. const APSInt &operator%=(const APSInt &RHS) {
  97. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  98. if (IsUnsigned)
  99. *this = urem(RHS);
  100. else
  101. *this = srem(RHS);
  102. return *this;
  103. }
  104. const APSInt &operator/=(const APSInt &RHS) {
  105. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  106. if (IsUnsigned)
  107. *this = udiv(RHS);
  108. else
  109. *this = sdiv(RHS);
  110. return *this;
  111. }
  112. APSInt operator%(const APSInt &RHS) const {
  113. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  114. return IsUnsigned ? APSInt(urem(RHS), true) : APSInt(srem(RHS), false);
  115. }
  116. APSInt operator/(const APSInt &RHS) const {
  117. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  118. return IsUnsigned ? APSInt(udiv(RHS), true) : APSInt(sdiv(RHS), false);
  119. }
  120. APSInt operator>>(unsigned Amt) const {
  121. return IsUnsigned ? APSInt(lshr(Amt), true) : APSInt(ashr(Amt), false);
  122. }
  123. APSInt& operator>>=(unsigned Amt) {
  124. if (IsUnsigned)
  125. lshrInPlace(Amt);
  126. else
  127. ashrInPlace(Amt);
  128. return *this;
  129. }
  130. inline bool operator<(const APSInt& RHS) const {
  131. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  132. return IsUnsigned ? ult(RHS) : slt(RHS);
  133. }
  134. inline bool operator>(const APSInt& RHS) const {
  135. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  136. return IsUnsigned ? ugt(RHS) : sgt(RHS);
  137. }
  138. inline bool operator<=(const APSInt& RHS) const {
  139. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  140. return IsUnsigned ? ule(RHS) : sle(RHS);
  141. }
  142. inline bool operator>=(const APSInt& RHS) const {
  143. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  144. return IsUnsigned ? uge(RHS) : sge(RHS);
  145. }
  146. inline bool operator==(const APSInt& RHS) const {
  147. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  148. return eq(RHS);
  149. }
  150. inline bool operator!=(const APSInt& RHS) const {
  151. return !((*this) == RHS);
  152. }
  153. bool operator==(int64_t RHS) const {
  154. return compareValues(*this, get(RHS)) == 0;
  155. }
  156. bool operator!=(int64_t RHS) const {
  157. return compareValues(*this, get(RHS)) != 0;
  158. }
  159. bool operator<=(int64_t RHS) const {
  160. return compareValues(*this, get(RHS)) <= 0;
  161. }
  162. bool operator>=(int64_t RHS) const {
  163. return compareValues(*this, get(RHS)) >= 0;
  164. }
  165. bool operator<(int64_t RHS) const {
  166. return compareValues(*this, get(RHS)) < 0;
  167. }
  168. bool operator>(int64_t RHS) const {
  169. return compareValues(*this, get(RHS)) > 0;
  170. }
  171. // The remaining operators just wrap the logic of APInt, but retain the
  172. // signedness information.
  173. APSInt operator<<(unsigned Bits) const {
  174. return APSInt(static_cast<const APInt&>(*this) << Bits, IsUnsigned);
  175. }
  176. APSInt& operator<<=(unsigned Amt) {
  177. static_cast<APInt&>(*this) <<= Amt;
  178. return *this;
  179. }
  180. APSInt& operator++() {
  181. ++(static_cast<APInt&>(*this));
  182. return *this;
  183. }
  184. APSInt& operator--() {
  185. --(static_cast<APInt&>(*this));
  186. return *this;
  187. }
  188. APSInt operator++(int) {
  189. return APSInt(++static_cast<APInt&>(*this), IsUnsigned);
  190. }
  191. APSInt operator--(int) {
  192. return APSInt(--static_cast<APInt&>(*this), IsUnsigned);
  193. }
  194. APSInt operator-() const {
  195. return APSInt(-static_cast<const APInt&>(*this), IsUnsigned);
  196. }
  197. APSInt& operator+=(const APSInt& RHS) {
  198. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  199. static_cast<APInt&>(*this) += RHS;
  200. return *this;
  201. }
  202. APSInt& operator-=(const APSInt& RHS) {
  203. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  204. static_cast<APInt&>(*this) -= RHS;
  205. return *this;
  206. }
  207. APSInt& operator*=(const APSInt& RHS) {
  208. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  209. static_cast<APInt&>(*this) *= RHS;
  210. return *this;
  211. }
  212. APSInt& operator&=(const APSInt& RHS) {
  213. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  214. static_cast<APInt&>(*this) &= RHS;
  215. return *this;
  216. }
  217. APSInt& operator|=(const APSInt& RHS) {
  218. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  219. static_cast<APInt&>(*this) |= RHS;
  220. return *this;
  221. }
  222. APSInt& operator^=(const APSInt& RHS) {
  223. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  224. static_cast<APInt&>(*this) ^= RHS;
  225. return *this;
  226. }
  227. APSInt operator&(const APSInt& RHS) const {
  228. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  229. return APSInt(static_cast<const APInt&>(*this) & RHS, IsUnsigned);
  230. }
  231. APSInt operator|(const APSInt& RHS) const {
  232. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  233. return APSInt(static_cast<const APInt&>(*this) | RHS, IsUnsigned);
  234. }
  235. APSInt operator^(const APSInt &RHS) const {
  236. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  237. return APSInt(static_cast<const APInt&>(*this) ^ RHS, IsUnsigned);
  238. }
  239. APSInt operator*(const APSInt& RHS) const {
  240. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  241. return APSInt(static_cast<const APInt&>(*this) * RHS, IsUnsigned);
  242. }
  243. APSInt operator+(const APSInt& RHS) const {
  244. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  245. return APSInt(static_cast<const APInt&>(*this) + RHS, IsUnsigned);
  246. }
  247. APSInt operator-(const APSInt& RHS) const {
  248. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  249. return APSInt(static_cast<const APInt&>(*this) - RHS, IsUnsigned);
  250. }
  251. APSInt operator~() const {
  252. return APSInt(~static_cast<const APInt&>(*this), IsUnsigned);
  253. }
  254. /// Return the APSInt representing the maximum integer value with the given
  255. /// bit width and signedness.
  256. static APSInt getMaxValue(uint32_t numBits, bool Unsigned) {
  257. return APSInt(Unsigned ? APInt::getMaxValue(numBits)
  258. : APInt::getSignedMaxValue(numBits), Unsigned);
  259. }
  260. /// Return the APSInt representing the minimum integer value with the given
  261. /// bit width and signedness.
  262. static APSInt getMinValue(uint32_t numBits, bool Unsigned) {
  263. return APSInt(Unsigned ? APInt::getMinValue(numBits)
  264. : APInt::getSignedMinValue(numBits), Unsigned);
  265. }
  266. /// 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. return !compareValues(I1, I2);
  270. }
  271. /// Compare underlying values of two numbers.
  272. static int compareValues(const APSInt &I1, const APSInt &I2) {
  273. if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned())
  274. return I1.IsUnsigned ? I1.compare(I2) : I1.compareSigned(I2);
  275. // Check for a bit-width mismatch.
  276. if (I1.getBitWidth() > I2.getBitWidth())
  277. return compareValues(I1, I2.extend(I1.getBitWidth()));
  278. if (I2.getBitWidth() > I1.getBitWidth())
  279. return compareValues(I1.extend(I2.getBitWidth()), I2);
  280. // We have a signedness mismatch. Check for negative values and do an
  281. // unsigned compare if both are positive.
  282. if (I1.isSigned()) {
  283. assert(!I2.isSigned() && "Expected signed mismatch");
  284. if (I1.isNegative())
  285. return -1;
  286. } else {
  287. assert(I2.isSigned() && "Expected signed mismatch");
  288. if (I2.isNegative())
  289. return 1;
  290. }
  291. return I1.compare(I2);
  292. }
  293. static APSInt get(int64_t X) { return APSInt(APInt(64, X), false); }
  294. static APSInt getUnsigned(uint64_t X) { return APSInt(APInt(64, X), true); }
  295. /// Used to insert APSInt objects, or objects that contain APSInt objects,
  296. /// into FoldingSets.
  297. void Profile(FoldingSetNodeID& ID) const;
  298. };
  299. inline bool operator==(int64_t V1, const APSInt &V2) { return V2 == V1; }
  300. inline bool operator!=(int64_t V1, const APSInt &V2) { return V2 != V1; }
  301. inline bool operator<=(int64_t V1, const APSInt &V2) { return V2 >= V1; }
  302. inline bool operator>=(int64_t V1, const APSInt &V2) { return V2 <= V1; }
  303. inline bool operator<(int64_t V1, const APSInt &V2) { return V2 > V1; }
  304. inline bool operator>(int64_t V1, const APSInt &V2) { return V2 < V1; }
  305. inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) {
  306. I.print(OS, I.isSigned());
  307. return OS;
  308. }
  309. } // end namespace llvm
  310. #endif