Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  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. /// \file
  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.  
  15. #ifndef LLVM_ADT_APSINT_H
  16. #define LLVM_ADT_APSINT_H
  17.  
  18. #include "llvm/ADT/APInt.h"
  19.  
  20. namespace llvm {
  21.  
  22. /// An arbitrary precision integer that knows its signedness.
  23. class [[nodiscard]] APSInt : public APInt {
  24.   bool IsUnsigned = false;
  25.  
  26. public:
  27.   /// Default constructor that creates an uninitialized APInt.
  28.   explicit APSInt() = default;
  29.  
  30.   /// Create an APSInt with the specified width, default to unsigned.
  31.   explicit APSInt(uint32_t BitWidth, bool isUnsigned = true)
  32.       : APInt(BitWidth, 0), IsUnsigned(isUnsigned) {}
  33.  
  34.   explicit APSInt(APInt I, bool isUnsigned = true)
  35.       : APInt(std::move(I)), IsUnsigned(isUnsigned) {}
  36.  
  37.   /// Construct an APSInt from a string representation.
  38.   ///
  39.   /// This constructor interprets the string \p Str using the radix of 10.
  40.   /// The interpretation stops at the end of the string. The bit width of the
  41.   /// constructed APSInt is determined automatically.
  42.   ///
  43.   /// \param Str the string to be interpreted.
  44.   explicit APSInt(StringRef Str);
  45.  
  46.   /// Determine sign of this APSInt.
  47.   ///
  48.   /// \returns true if this APSInt is negative, false otherwise
  49.   bool isNegative() const { return isSigned() && APInt::isNegative(); }
  50.  
  51.   /// Determine if this APSInt Value is non-negative (>= 0)
  52.   ///
  53.   /// \returns true if this APSInt is non-negative, false otherwise
  54.   bool isNonNegative() const { return !isNegative(); }
  55.  
  56.   /// Determine if this APSInt Value is positive.
  57.   ///
  58.   /// This tests if the value of this APSInt is positive (> 0). Note
  59.   /// that 0 is not a positive value.
  60.   ///
  61.   /// \returns true if this APSInt is positive.
  62.   bool isStrictlyPositive() const { return isNonNegative() && !isZero(); }
  63.  
  64.   APSInt &operator=(APInt RHS) {
  65.     // Retain our current sign.
  66.     APInt::operator=(std::move(RHS));
  67.     return *this;
  68.   }
  69.  
  70.   APSInt &operator=(uint64_t RHS) {
  71.     // Retain our current sign.
  72.     APInt::operator=(RHS);
  73.     return *this;
  74.   }
  75.  
  76.   // Query sign information.
  77.   bool isSigned() const { return !IsUnsigned; }
  78.   bool isUnsigned() const { return IsUnsigned; }
  79.   void setIsUnsigned(bool Val) { IsUnsigned = Val; }
  80.   void setIsSigned(bool Val) { IsUnsigned = !Val; }
  81.  
  82.   /// Append this APSInt to the specified SmallString.
  83.   void toString(SmallVectorImpl<char> &Str, unsigned Radix = 10) const {
  84.     APInt::toString(Str, Radix, isSigned());
  85.   }
  86.   using APInt::toString;
  87.  
  88.   /// If this int is representable using an int64_t.
  89.   bool isRepresentableByInt64() const {
  90.     // For unsigned values with 64 active bits, they technically fit into a
  91.     // int64_t, but the user may get negative numbers and has to manually cast
  92.     // them to unsigned. Let's not bet the user has the sanity to do that and
  93.     // not give them a vague value at the first place.
  94.     return isSigned() ? isSignedIntN(64) : isIntN(63);
  95.   }
  96.  
  97.   /// Get the correctly-extended \c int64_t value.
  98.   int64_t getExtValue() const {
  99.     assert(isRepresentableByInt64() && "Too many bits for int64_t");
  100.     return isSigned() ? getSExtValue() : getZExtValue();
  101.   }
  102.  
  103.   std::optional<int64_t> tryExtValue() const {
  104.     return isRepresentableByInt64() ? std::optional<int64_t>(getExtValue())
  105.                                     : std::nullopt;
  106.   }
  107.  
  108.   APSInt trunc(uint32_t width) const {
  109.     return APSInt(APInt::trunc(width), IsUnsigned);
  110.   }
  111.  
  112.   APSInt extend(uint32_t width) const {
  113.     if (IsUnsigned)
  114.       return APSInt(zext(width), IsUnsigned);
  115.     else
  116.       return APSInt(sext(width), IsUnsigned);
  117.   }
  118.  
  119.   APSInt extOrTrunc(uint32_t width) const {
  120.     if (IsUnsigned)
  121.       return APSInt(zextOrTrunc(width), IsUnsigned);
  122.     else
  123.       return APSInt(sextOrTrunc(width), IsUnsigned);
  124.   }
  125.  
  126.   const APSInt &operator%=(const APSInt &RHS) {
  127.     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  128.     if (IsUnsigned)
  129.       *this = urem(RHS);
  130.     else
  131.       *this = srem(RHS);
  132.     return *this;
  133.   }
  134.   const APSInt &operator/=(const APSInt &RHS) {
  135.     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  136.     if (IsUnsigned)
  137.       *this = udiv(RHS);
  138.     else
  139.       *this = sdiv(RHS);
  140.     return *this;
  141.   }
  142.   APSInt operator%(const APSInt &RHS) const {
  143.     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  144.     return IsUnsigned ? APSInt(urem(RHS), true) : APSInt(srem(RHS), false);
  145.   }
  146.   APSInt operator/(const APSInt &RHS) const {
  147.     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  148.     return IsUnsigned ? APSInt(udiv(RHS), true) : APSInt(sdiv(RHS), false);
  149.   }
  150.  
  151.   APSInt operator>>(unsigned Amt) const {
  152.     return IsUnsigned ? APSInt(lshr(Amt), true) : APSInt(ashr(Amt), false);
  153.   }
  154.   APSInt &operator>>=(unsigned Amt) {
  155.     if (IsUnsigned)
  156.       lshrInPlace(Amt);
  157.     else
  158.       ashrInPlace(Amt);
  159.     return *this;
  160.   }
  161.   APSInt relativeShr(unsigned Amt) const {
  162.     return IsUnsigned ? APSInt(relativeLShr(Amt), true)
  163.                       : APSInt(relativeAShr(Amt), false);
  164.   }
  165.  
  166.   inline bool operator<(const APSInt &RHS) const {
  167.     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  168.     return IsUnsigned ? ult(RHS) : slt(RHS);
  169.   }
  170.   inline bool operator>(const APSInt &RHS) const {
  171.     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  172.     return IsUnsigned ? ugt(RHS) : sgt(RHS);
  173.   }
  174.   inline bool operator<=(const APSInt &RHS) const {
  175.     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  176.     return IsUnsigned ? ule(RHS) : sle(RHS);
  177.   }
  178.   inline bool operator>=(const APSInt &RHS) const {
  179.     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  180.     return IsUnsigned ? uge(RHS) : sge(RHS);
  181.   }
  182.   inline bool operator==(const APSInt &RHS) const {
  183.     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  184.     return eq(RHS);
  185.   }
  186.   inline bool operator!=(const APSInt &RHS) const { return !((*this) == RHS); }
  187.  
  188.   bool operator==(int64_t RHS) const {
  189.     return compareValues(*this, get(RHS)) == 0;
  190.   }
  191.   bool operator!=(int64_t RHS) const {
  192.     return compareValues(*this, get(RHS)) != 0;
  193.   }
  194.   bool operator<=(int64_t RHS) const {
  195.     return compareValues(*this, get(RHS)) <= 0;
  196.   }
  197.   bool operator>=(int64_t RHS) const {
  198.     return compareValues(*this, get(RHS)) >= 0;
  199.   }
  200.   bool operator<(int64_t RHS) const {
  201.     return compareValues(*this, get(RHS)) < 0;
  202.   }
  203.   bool operator>(int64_t RHS) const {
  204.     return compareValues(*this, get(RHS)) > 0;
  205.   }
  206.  
  207.   // The remaining operators just wrap the logic of APInt, but retain the
  208.   // signedness information.
  209.  
  210.   APSInt operator<<(unsigned Bits) const {
  211.     return APSInt(static_cast<const APInt &>(*this) << Bits, IsUnsigned);
  212.   }
  213.   APSInt &operator<<=(unsigned Amt) {
  214.     static_cast<APInt &>(*this) <<= Amt;
  215.     return *this;
  216.   }
  217.   APSInt relativeShl(unsigned Amt) const {
  218.     return IsUnsigned ? APSInt(relativeLShl(Amt), true)
  219.                       : APSInt(relativeAShl(Amt), false);
  220.   }
  221.  
  222.   APSInt &operator++() {
  223.     ++(static_cast<APInt &>(*this));
  224.     return *this;
  225.   }
  226.   APSInt &operator--() {
  227.     --(static_cast<APInt &>(*this));
  228.     return *this;
  229.   }
  230.   APSInt operator++(int) {
  231.     return APSInt(++static_cast<APInt &>(*this), IsUnsigned);
  232.   }
  233.   APSInt operator--(int) {
  234.     return APSInt(--static_cast<APInt &>(*this), IsUnsigned);
  235.   }
  236.   APSInt operator-() const {
  237.     return APSInt(-static_cast<const APInt &>(*this), IsUnsigned);
  238.   }
  239.   APSInt &operator+=(const APSInt &RHS) {
  240.     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  241.     static_cast<APInt &>(*this) += RHS;
  242.     return *this;
  243.   }
  244.   APSInt &operator-=(const APSInt &RHS) {
  245.     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  246.     static_cast<APInt &>(*this) -= RHS;
  247.     return *this;
  248.   }
  249.   APSInt &operator*=(const APSInt &RHS) {
  250.     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  251.     static_cast<APInt &>(*this) *= RHS;
  252.     return *this;
  253.   }
  254.   APSInt &operator&=(const APSInt &RHS) {
  255.     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  256.     static_cast<APInt &>(*this) &= RHS;
  257.     return *this;
  258.   }
  259.   APSInt &operator|=(const APSInt &RHS) {
  260.     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  261.     static_cast<APInt &>(*this) |= RHS;
  262.     return *this;
  263.   }
  264.   APSInt &operator^=(const APSInt &RHS) {
  265.     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  266.     static_cast<APInt &>(*this) ^= RHS;
  267.     return *this;
  268.   }
  269.  
  270.   APSInt operator&(const APSInt &RHS) const {
  271.     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  272.     return APSInt(static_cast<const APInt &>(*this) & RHS, IsUnsigned);
  273.   }
  274.  
  275.   APSInt operator|(const APSInt &RHS) const {
  276.     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  277.     return APSInt(static_cast<const APInt &>(*this) | RHS, IsUnsigned);
  278.   }
  279.  
  280.   APSInt operator^(const APSInt &RHS) const {
  281.     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  282.     return APSInt(static_cast<const APInt &>(*this) ^ RHS, IsUnsigned);
  283.   }
  284.  
  285.   APSInt operator*(const APSInt &RHS) const {
  286.     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  287.     return APSInt(static_cast<const APInt &>(*this) * RHS, IsUnsigned);
  288.   }
  289.   APSInt operator+(const APSInt &RHS) const {
  290.     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  291.     return APSInt(static_cast<const APInt &>(*this) + RHS, IsUnsigned);
  292.   }
  293.   APSInt operator-(const APSInt &RHS) const {
  294.     assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
  295.     return APSInt(static_cast<const APInt &>(*this) - RHS, IsUnsigned);
  296.   }
  297.   APSInt operator~() const {
  298.     return APSInt(~static_cast<const APInt &>(*this), IsUnsigned);
  299.   }
  300.  
  301.   /// Return the APSInt representing the maximum integer value with the given
  302.   /// bit width and signedness.
  303.   static APSInt getMaxValue(uint32_t numBits, bool Unsigned) {
  304.     return APSInt(Unsigned ? APInt::getMaxValue(numBits)
  305.                            : APInt::getSignedMaxValue(numBits),
  306.                   Unsigned);
  307.   }
  308.  
  309.   /// Return the APSInt representing the minimum integer value with the given
  310.   /// bit width and signedness.
  311.   static APSInt getMinValue(uint32_t numBits, bool Unsigned) {
  312.     return APSInt(Unsigned ? APInt::getMinValue(numBits)
  313.                            : APInt::getSignedMinValue(numBits),
  314.                   Unsigned);
  315.   }
  316.  
  317.   /// Determine if two APSInts have the same value, zero- or
  318.   /// sign-extending as needed.
  319.   static bool isSameValue(const APSInt &I1, const APSInt &I2) {
  320.     return !compareValues(I1, I2);
  321.   }
  322.  
  323.   /// Compare underlying values of two numbers.
  324.   static int compareValues(const APSInt &I1, const APSInt &I2) {
  325.     if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned())
  326.       return I1.IsUnsigned ? I1.compare(I2) : I1.compareSigned(I2);
  327.  
  328.     // Check for a bit-width mismatch.
  329.     if (I1.getBitWidth() > I2.getBitWidth())
  330.       return compareValues(I1, I2.extend(I1.getBitWidth()));
  331.     if (I2.getBitWidth() > I1.getBitWidth())
  332.       return compareValues(I1.extend(I2.getBitWidth()), I2);
  333.  
  334.     // We have a signedness mismatch. Check for negative values and do an
  335.     // unsigned compare if both are positive.
  336.     if (I1.isSigned()) {
  337.       assert(!I2.isSigned() && "Expected signed mismatch");
  338.       if (I1.isNegative())
  339.         return -1;
  340.     } else {
  341.       assert(I2.isSigned() && "Expected signed mismatch");
  342.       if (I2.isNegative())
  343.         return 1;
  344.     }
  345.  
  346.     return I1.compare(I2);
  347.   }
  348.  
  349.   static APSInt get(int64_t X) { return APSInt(APInt(64, X), false); }
  350.   static APSInt getUnsigned(uint64_t X) { return APSInt(APInt(64, X), true); }
  351.  
  352.   /// Used to insert APSInt objects, or objects that contain APSInt objects,
  353.   /// into FoldingSets.
  354.   void Profile(FoldingSetNodeID &ID) const;
  355. };
  356.  
  357. inline bool operator==(int64_t V1, const APSInt &V2) { return V2 == V1; }
  358. inline bool operator!=(int64_t V1, const APSInt &V2) { return V2 != V1; }
  359. inline bool operator<=(int64_t V1, const APSInt &V2) { return V2 >= V1; }
  360. inline bool operator>=(int64_t V1, const APSInt &V2) { return V2 <= V1; }
  361. inline bool operator<(int64_t V1, const APSInt &V2) { return V2 > V1; }
  362. inline bool operator>(int64_t V1, const APSInt &V2) { return V2 < V1; }
  363.  
  364. inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) {
  365.   I.print(OS, I.isSigned());
  366.   return OS;
  367. }
  368.  
  369. /// Provide DenseMapInfo for APSInt, using the DenseMapInfo for APInt.
  370. template <> struct DenseMapInfo<APSInt, void> {
  371.   static inline APSInt getEmptyKey() {
  372.     return APSInt(DenseMapInfo<APInt, void>::getEmptyKey());
  373.   }
  374.  
  375.   static inline APSInt getTombstoneKey() {
  376.     return APSInt(DenseMapInfo<APInt, void>::getTombstoneKey());
  377.   }
  378.  
  379.   static unsigned getHashValue(const APSInt &Key) {
  380.     return DenseMapInfo<APInt, void>::getHashValue(Key);
  381.   }
  382.  
  383.   static bool isEqual(const APSInt &LHS, const APSInt &RHS) {
  384.     return LHS.getBitWidth() == RHS.getBitWidth() &&
  385.            LHS.isUnsigned() == RHS.isUnsigned() && LHS == RHS;
  386.   }
  387. };
  388.  
  389. } // end namespace llvm
  390.  
  391. #endif
  392.