APSInt.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  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. #ifndef LLVM_ADT_APSINT_H
  15. #define LLVM_ADT_APSINT_H
  16. #include "llvm/ADT/APInt.h"
  17. namespace llvm {
  18. class APSInt : public APInt {
  19. bool IsUnsigned;
  20. public:
  21. /// Default constructor that creates an uninitialized APInt.
  22. explicit APSInt() : IsUnsigned(false) {}
  23. /// APSInt ctor - Create an APSInt with the specified width, default to
  24. /// unsigned.
  25. explicit APSInt(uint32_t BitWidth, bool isUnsigned = true)
  26. : APInt(BitWidth, 0), IsUnsigned(isUnsigned) {}
  27. explicit APSInt(APInt I, bool isUnsigned = true)
  28. : APInt(std::move(I)), IsUnsigned(isUnsigned) {}
  29. /// Construct an APSInt from a string representation.
  30. ///
  31. /// This constructor interprets the string \p Str using the radix of 10.
  32. /// The interpretation stops at the end of the string. The bit width of the
  33. /// constructed APSInt is determined automatically.
  34. ///
  35. /// \param Str the string to be interpreted.
  36. explicit APSInt(StringRef Str);
  37. APSInt &operator=(APInt RHS) {
  38. // Retain our current sign.
  39. APInt::operator=(std::move(RHS));
  40. return *this;
  41. }
  42. APSInt &operator=(uint64_t RHS) {
  43. // Retain our current sign.
  44. APInt::operator=(RHS);
  45. return *this;
  46. }
  47. // Query sign information.
  48. bool isSigned() const { return !IsUnsigned; }
  49. bool isUnsigned() const { return IsUnsigned; }
  50. void setIsUnsigned(bool Val) { IsUnsigned = Val; }
  51. void setIsSigned(bool Val) { IsUnsigned = !Val; }
  52. /// toString - Append this APSInt to the specified SmallString.
  53. void toString(SmallVectorImpl<char> &Str, unsigned Radix = 10) const {
  54. APInt::toString(Str, Radix, isSigned());
  55. }
  56. /// toString - Converts an APInt to a std::string. This is an inefficient
  57. /// method; you should prefer passing in a SmallString instead.
  58. std::string toString(unsigned Radix) const {
  59. return APInt::toString(Radix, isSigned());
  60. }
  61. using APInt::toString;
  62. /// \brief Get the correctly-extended \c int64_t value.
  63. int64_t getExtValue() const {
  64. assert(getMinSignedBits() <= 64 && "Too many bits for int64_t");
  65. return isSigned() ? getSExtValue() : getZExtValue();
  66. }
  67. APSInt LLVM_ATTRIBUTE_UNUSED_RESULT trunc(uint32_t width) const {
  68. return APSInt(APInt::trunc(width), IsUnsigned);
  69. }
  70. APSInt LLVM_ATTRIBUTE_UNUSED_RESULT extend(uint32_t width) const {
  71. if (IsUnsigned)
  72. return APSInt(zext(width), IsUnsigned);
  73. else
  74. return APSInt(sext(width), IsUnsigned);
  75. }
  76. APSInt LLVM_ATTRIBUTE_UNUSED_RESULT extOrTrunc(uint32_t width) const {
  77. if (IsUnsigned)
  78. return APSInt(zextOrTrunc(width), IsUnsigned);
  79. else
  80. return APSInt(sextOrTrunc(width), IsUnsigned);
  81. }
  82. const APSInt &operator%=(const APSInt &RHS) {
  83. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  84. if (IsUnsigned)
  85. *this = urem(RHS);
  86. else
  87. *this = srem(RHS);
  88. return *this;
  89. }
  90. const APSInt &operator/=(const APSInt &RHS) {
  91. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  92. if (IsUnsigned)
  93. *this = udiv(RHS);
  94. else
  95. *this = sdiv(RHS);
  96. return *this;
  97. }
  98. APSInt operator%(const APSInt &RHS) const {
  99. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  100. return IsUnsigned ? APSInt(urem(RHS), true) : APSInt(srem(RHS), false);
  101. }
  102. APSInt operator/(const APSInt &RHS) const {
  103. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  104. return IsUnsigned ? APSInt(udiv(RHS), true) : APSInt(sdiv(RHS), false);
  105. }
  106. APSInt operator>>(unsigned Amt) const {
  107. return IsUnsigned ? APSInt(lshr(Amt), true) : APSInt(ashr(Amt), false);
  108. }
  109. APSInt& operator>>=(unsigned Amt) {
  110. *this = *this >> Amt;
  111. return *this;
  112. }
  113. inline bool operator<(const APSInt& RHS) const {
  114. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  115. return IsUnsigned ? ult(RHS) : slt(RHS);
  116. }
  117. inline bool operator>(const APSInt& RHS) const {
  118. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  119. return IsUnsigned ? ugt(RHS) : sgt(RHS);
  120. }
  121. inline bool operator<=(const APSInt& RHS) const {
  122. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  123. return IsUnsigned ? ule(RHS) : sle(RHS);
  124. }
  125. inline bool operator>=(const APSInt& RHS) const {
  126. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  127. return IsUnsigned ? uge(RHS) : sge(RHS);
  128. }
  129. inline bool operator==(const APSInt& RHS) const {
  130. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  131. return eq(RHS);
  132. }
  133. inline bool operator!=(const APSInt& RHS) const {
  134. return !((*this) == RHS);
  135. }
  136. bool operator==(int64_t RHS) const {
  137. return compareValues(*this, get(RHS)) == 0;
  138. }
  139. bool operator!=(int64_t RHS) const {
  140. return compareValues(*this, get(RHS)) != 0;
  141. }
  142. bool operator<=(int64_t RHS) const {
  143. return compareValues(*this, get(RHS)) <= 0;
  144. }
  145. bool operator>=(int64_t RHS) const {
  146. return compareValues(*this, get(RHS)) >= 0;
  147. }
  148. bool operator<(int64_t RHS) const {
  149. return compareValues(*this, get(RHS)) < 0;
  150. }
  151. bool operator>(int64_t RHS) const {
  152. return compareValues(*this, get(RHS)) > 0;
  153. }
  154. // The remaining operators just wrap the logic of APInt, but retain the
  155. // signedness information.
  156. APSInt operator<<(unsigned Bits) const {
  157. return APSInt(static_cast<const APInt&>(*this) << Bits, IsUnsigned);
  158. }
  159. APSInt& operator<<=(unsigned Amt) {
  160. *this = *this << Amt;
  161. return *this;
  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. APSInt operator&(const APSInt& RHS) const {
  211. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  212. return APSInt(static_cast<const APInt&>(*this) & RHS, IsUnsigned);
  213. }
  214. APSInt LLVM_ATTRIBUTE_UNUSED_RESULT And(const APSInt& RHS) const {
  215. return this->operator&(RHS);
  216. }
  217. APSInt operator|(const APSInt& RHS) const {
  218. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  219. return APSInt(static_cast<const APInt&>(*this) | RHS, IsUnsigned);
  220. }
  221. APSInt LLVM_ATTRIBUTE_UNUSED_RESULT Or(const APSInt& RHS) const {
  222. return this->operator|(RHS);
  223. }
  224. APSInt operator^(const APSInt& RHS) const {
  225. assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  226. return APSInt(static_cast<const APInt&>(*this) ^ RHS, IsUnsigned);
  227. }
  228. APSInt LLVM_ATTRIBUTE_UNUSED_RESULT Xor(const APSInt& RHS) const {
  229. return this->operator^(RHS);
  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 {
  244. return APSInt(~static_cast<const APInt&>(*this), IsUnsigned);
  245. }
  246. /// getMaxValue - Return the APSInt representing the maximum integer value
  247. /// with the given bit width and signedness.
  248. static APSInt getMaxValue(uint32_t numBits, bool Unsigned) {
  249. return APSInt(Unsigned ? APInt::getMaxValue(numBits)
  250. : APInt::getSignedMaxValue(numBits), Unsigned);
  251. }
  252. /// getMinValue - Return the APSInt representing the minimum integer value
  253. /// with the given bit width and signedness.
  254. static APSInt getMinValue(uint32_t numBits, bool Unsigned) {
  255. return APSInt(Unsigned ? APInt::getMinValue(numBits)
  256. : APInt::getSignedMinValue(numBits), Unsigned);
  257. }
  258. /// \brief Determine if two APSInts have the same value, zero- or
  259. /// sign-extending as needed.
  260. static bool isSameValue(const APSInt &I1, const APSInt &I2) {
  261. return !compareValues(I1, I2);
  262. }
  263. /// \brief Compare underlying values of two numbers.
  264. static int compareValues(const APSInt &I1, const APSInt &I2) {
  265. if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned())
  266. return I1 == I2 ? 0 : I1 > I2 ? 1 : -1;
  267. // Check for a bit-width mismatch.
  268. if (I1.getBitWidth() > I2.getBitWidth())
  269. return compareValues(I1, I2.extend(I1.getBitWidth()));
  270. else if (I2.getBitWidth() > I1.getBitWidth())
  271. return compareValues(I1.extend(I2.getBitWidth()), I2);
  272. // We have a signedness mismatch. Check for negative values and do an
  273. // unsigned compare if both are positive.
  274. if (I1.isSigned()) {
  275. assert(!I2.isSigned() && "Expected signed mismatch");
  276. if (I1.isNegative())
  277. return -1;
  278. } else {
  279. assert(I2.isSigned() && "Expected signed mismatch");
  280. if (I2.isNegative())
  281. return 1;
  282. }
  283. return I1.eq(I2) ? 0 : I1.ugt(I2) ? 1 : -1;
  284. }
  285. static APSInt get(int64_t X) { return APSInt(APInt(64, X), false); }
  286. static APSInt getUnsigned(uint64_t X) { return APSInt(APInt(64, X), true); }
  287. /// Profile - Used to insert APSInt objects, or objects that contain APSInt
  288. /// objects, into FoldingSets.
  289. void Profile(FoldingSetNodeID& ID) const;
  290. };
  291. inline bool operator==(int64_t V1, const APSInt &V2) { return V2 == V1; }
  292. inline bool operator!=(int64_t V1, const APSInt &V2) { return V2 != V1; }
  293. inline bool operator<=(int64_t V1, const APSInt &V2) { return V2 >= V1; }
  294. inline bool operator>=(int64_t V1, const APSInt &V2) { return V2 <= V1; }
  295. inline bool operator<(int64_t V1, const APSInt &V2) { return V2 > V1; }
  296. inline bool operator>(int64_t V1, const APSInt &V2) { return V2 < V1; }
  297. inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) {
  298. I.print(OS, I.isSigned());
  299. return OS;
  300. }
  301. } // end namespace llvm
  302. #endif