mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-27 14:34:58 +00:00
Review changes:
1. Function style changes. 2. 80-col violations. 3. Better names for things. 4. Arrange constructors so they all take bit width first. 5. Add named signed and unsigned comparison functions and remove the corresponding operators. 6. Remove operator&& and operator|| but provide a getBoolValue function which converts to bool as comparison against 0. This allows the normal && and || operators to be used as if (X.getBoolValue() && Y.getBoolValue()) Note: this still doesn't function 100% yet. I'm working on the bugs now. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@34353 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
ae6f1fa36b
commit
e81d2dad2c
@ -24,8 +24,8 @@ namespace llvm {
|
|||||||
/// Forward declaration.
|
/// Forward declaration.
|
||||||
class APInt;
|
class APInt;
|
||||||
namespace APIntOps {
|
namespace APIntOps {
|
||||||
APInt UDiv(const APInt& LHS, const APInt& RHS);
|
APInt udiv(const APInt& LHS, const APInt& RHS);
|
||||||
APInt URem(const APInt& LHS, const APInt& RHS);
|
APInt urem(const APInt& LHS, const APInt& RHS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -35,17 +35,31 @@ namespace APIntOps {
|
|||||||
/// APInt - This class represents arbitrary precision constant integral values.
|
/// APInt - This class represents arbitrary precision constant integral values.
|
||||||
/// It is a functional replacement for common case unsigned integer type like
|
/// It is a functional replacement for common case unsigned integer type like
|
||||||
/// "unsigned", "unsigned long" or "uint64_t", but also allows non-byte-width
|
/// "unsigned", "unsigned long" or "uint64_t", but also allows non-byte-width
|
||||||
/// integer type and large integer value types such as 3-bits, 15-bits, or more
|
/// integer sizes and large integer value types such as 3-bits, 15-bits, or more
|
||||||
/// than 64-bits of precision. APInt provides a variety of arithmetic operators
|
/// than 64-bits of precision. APInt provides a variety of arithmetic operators
|
||||||
/// and methods to manipulate integer values of any bit-width. It supports not
|
/// and methods to manipulate integer values of any bit-width. It supports both
|
||||||
/// only all the operations of uint64_t but also bitwise manipulation.
|
/// the typical integer arithmetic and comparison operations as well as bitwise
|
||||||
|
/// manipulation.
|
||||||
|
///
|
||||||
|
/// The class has several invariants worth noting:
|
||||||
|
/// * All bit, byte, and word positions are zero-based.
|
||||||
|
/// * Once the bit width is set, it doesn't change except by the Truncate,
|
||||||
|
/// SignExtend, or ZeroExtend operations.
|
||||||
|
/// * All binary operators must be on APInt instances of the same bit width.
|
||||||
|
/// Attempting to use these operators on instances with different bit
|
||||||
|
/// widths will yield an assertion.
|
||||||
|
/// * The value is stored canonically as an unsigned value. For operations
|
||||||
|
/// where it makes a difference, there are both signed and unsigned variants
|
||||||
|
/// of the operation. For example, sdiv and udiv. However, because the bit
|
||||||
|
/// widths must be the same, operations such as Mul and Add produce the same
|
||||||
|
/// results regardless of whether the values are interpreted as signed or
|
||||||
|
/// not.
|
||||||
|
/// * In general, the class tries to follow the style of computation that LLVM
|
||||||
|
/// uses in its IR. This simplifies its use for LLVM.
|
||||||
///
|
///
|
||||||
/// @brief Class for arbitrary precision integers.
|
/// @brief Class for arbitrary precision integers.
|
||||||
///
|
|
||||||
/// Note: In this class, all bit/byte/word positions are zero-based.
|
|
||||||
///
|
|
||||||
class APInt {
|
class APInt {
|
||||||
unsigned BitsNum; ///< The number of bits.
|
unsigned BitWidth; ///< The number of bits in this APInt.
|
||||||
|
|
||||||
/// This union is used to store the integer value. When the
|
/// This union is used to store the integer value. When the
|
||||||
/// integer bit-width <= 64, it uses VAL;
|
/// integer bit-width <= 64, it uses VAL;
|
||||||
@ -64,67 +78,79 @@ class APInt {
|
|||||||
/// @returns the number of words to hold the integer value of this APInt.
|
/// @returns the number of words to hold the integer value of this APInt.
|
||||||
/// @brief Get the number of words.
|
/// @brief Get the number of words.
|
||||||
inline unsigned getNumWords() const {
|
inline unsigned getNumWords() const {
|
||||||
return (BitsNum + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD;
|
return (BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @returns true if the number of bits <= 64, false otherwise.
|
/// @returns true if the number of bits <= 64, false otherwise.
|
||||||
/// @brief Determine if this APInt just has one word to store value.
|
/// @brief Determine if this APInt just has one word to store value.
|
||||||
inline bool isSingleWord() const
|
inline bool isSingleWord() const {
|
||||||
{ return BitsNum <= APINT_BITS_PER_WORD; }
|
return BitWidth <= APINT_BITS_PER_WORD;
|
||||||
|
}
|
||||||
|
|
||||||
/// @returns the word position for the specified bit position.
|
/// @returns the word position for the specified bit position.
|
||||||
static inline unsigned whichWord(unsigned bitPosition)
|
static inline unsigned whichWord(unsigned bitPosition) {
|
||||||
{ return bitPosition / APINT_BITS_PER_WORD; }
|
return bitPosition / APINT_BITS_PER_WORD;
|
||||||
|
}
|
||||||
|
|
||||||
/// @returns the byte position for the specified bit position.
|
/// @returns the byte position for the specified bit position.
|
||||||
static inline unsigned whichByte(unsigned bitPosition)
|
static inline unsigned whichByte(unsigned bitPosition) {
|
||||||
{ return (bitPosition % APINT_BITS_PER_WORD) / 8; }
|
return (bitPosition % APINT_BITS_PER_WORD) / 8;
|
||||||
|
}
|
||||||
|
|
||||||
/// @returns the bit position in a word for the specified bit position
|
/// @returns the bit position in a word for the specified bit position
|
||||||
/// in APInt.
|
/// in APInt.
|
||||||
static inline unsigned whichBit(unsigned bitPosition)
|
static inline unsigned whichBit(unsigned bitPosition) {
|
||||||
{ return bitPosition % APINT_BITS_PER_WORD; }
|
return bitPosition % APINT_BITS_PER_WORD;
|
||||||
|
}
|
||||||
|
|
||||||
/// @returns a uint64_t type integer with just bit position at
|
/// @returns a uint64_t type integer with just bit position at
|
||||||
/// "whichBit(bitPosition)" setting, others zero.
|
/// "whichBit(bitPosition)" setting, others zero.
|
||||||
static inline uint64_t maskBit(unsigned bitPosition)
|
static inline uint64_t maskBit(unsigned bitPosition) {
|
||||||
{ return (static_cast<uint64_t>(1)) << whichBit(bitPosition); }
|
return (static_cast<uint64_t>(1)) << whichBit(bitPosition);
|
||||||
|
}
|
||||||
|
|
||||||
inline void TruncToBits() {
|
/// This method is used internally to clear the to "N" bits that are not used
|
||||||
|
/// by the APInt. This is needed after a word is assigned a value to ensure
|
||||||
|
/// that those bits are zero'd out.
|
||||||
|
/// @brief Clear high order bits
|
||||||
|
inline void clearUnusedBits() {
|
||||||
if (isSingleWord())
|
if (isSingleWord())
|
||||||
VAL &= ~uint64_t(0ULL) >> (APINT_BITS_PER_WORD - BitsNum);
|
VAL &= ~uint64_t(0ULL) >> (APINT_BITS_PER_WORD - BitWidth);
|
||||||
else
|
else
|
||||||
pVal[getNumWords() - 1] &= ~uint64_t(0ULL) >>
|
pVal[getNumWords() - 1] &= ~uint64_t(0ULL) >>
|
||||||
(APINT_BITS_PER_WORD - (whichBit(BitsNum - 1) + 1));
|
(APINT_BITS_PER_WORD - (whichBit(BitWidth - 1) + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @returns the corresponding word for the specified bit position.
|
/// @returns the corresponding word for the specified bit position.
|
||||||
inline uint64_t& getWord(unsigned bitPosition)
|
inline uint64_t& getWord(unsigned bitPosition) {
|
||||||
{ return isSingleWord() ? VAL : pVal[whichWord(bitPosition)]; }
|
return isSingleWord() ? VAL : pVal[whichWord(bitPosition)];
|
||||||
|
}
|
||||||
|
|
||||||
/// @returns the corresponding word for the specified bit position.
|
/// @returns the corresponding word for the specified bit position.
|
||||||
/// This is a constant version.
|
/// This is a constant version.
|
||||||
inline uint64_t getWord(unsigned bitPosition) const
|
inline uint64_t getWord(unsigned bitPosition) const {
|
||||||
{ return isSingleWord() ? VAL : pVal[whichWord(bitPosition)]; }
|
return isSingleWord() ? VAL : pVal[whichWord(bitPosition)];
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Converts a char array into an integer.
|
/// @brief Converts a char array into an integer.
|
||||||
void StrToAPInt(const char *StrStart, unsigned slen, uint8_t radix);
|
void fromString(unsigned numBits, const char *StrStart, unsigned slen,
|
||||||
|
uint8_t radix);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// @brief Create a new APInt of numBits bit-width, and initialized as val.
|
/// @brief Create a new APInt of numBits bit-width, and initialized as val.
|
||||||
APInt(uint64_t val = 0, unsigned numBits = APINT_BITS_PER_WORD);
|
APInt(unsigned numBits, uint64_t val);
|
||||||
|
|
||||||
/// @brief Create a new APInt of numBits bit-width, and initialized as
|
/// @brief Create a new APInt of numBits bit-width, and initialized as
|
||||||
/// bigVal[].
|
/// bigVal[].
|
||||||
APInt(unsigned numBits, uint64_t bigVal[]);
|
APInt(unsigned numBits, unsigned numWords, uint64_t bigVal[]);
|
||||||
|
|
||||||
/// @brief Create a new APInt by translating the string represented
|
/// @brief Create a new APInt by translating the string represented
|
||||||
/// integer value.
|
/// integer value.
|
||||||
APInt(const std::string& Val, uint8_t radix = 10);
|
APInt(unsigned numBits, const std::string& Val, uint8_t radix);
|
||||||
|
|
||||||
/// @brief Create a new APInt by translating the char array represented
|
/// @brief Create a new APInt by translating the char array represented
|
||||||
/// integer value.
|
/// integer value.
|
||||||
APInt(const char StrStart[], unsigned slen, uint8_t radix);
|
APInt(unsigned numBits, const char StrStart[], unsigned slen, uint8_t radix);
|
||||||
|
|
||||||
/// @brief Copy Constructor.
|
/// @brief Copy Constructor.
|
||||||
APInt(const APInt& API);
|
APInt(const APInt& API);
|
||||||
@ -210,14 +236,6 @@ public:
|
|||||||
/// @brief Bitwise XOR operator.
|
/// @brief Bitwise XOR operator.
|
||||||
APInt operator^(const APInt& RHS) const;
|
APInt operator^(const APInt& RHS) const;
|
||||||
|
|
||||||
/// Performs logical AND operation on this APInt and the given APInt& RHS.
|
|
||||||
/// @brief Logical AND operator.
|
|
||||||
bool operator&&(const APInt& RHS) const;
|
|
||||||
|
|
||||||
/// Performs logical OR operation on this APInt and the given APInt& RHS.
|
|
||||||
/// @brief Logical OR operator.
|
|
||||||
bool operator||(const APInt& RHS) const;
|
|
||||||
|
|
||||||
/// Performs logical negation operation on this APInt.
|
/// Performs logical negation operation on this APInt.
|
||||||
/// @brief Logical negation operator.
|
/// @brief Logical negation operator.
|
||||||
bool operator !() const;
|
bool operator !() const;
|
||||||
@ -234,9 +252,9 @@ public:
|
|||||||
/// @brief Subtraction operator.
|
/// @brief Subtraction operator.
|
||||||
APInt operator-(const APInt& RHS) const;
|
APInt operator-(const APInt& RHS) const;
|
||||||
|
|
||||||
///
|
/// @brief Unary negation operator
|
||||||
inline APInt operator-() const {
|
inline APInt operator-() const {
|
||||||
return APInt(0, BitsNum) - (*this);
|
return APInt(0, BitWidth) - (*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Array-indexing support.
|
/// @brief Array-indexing support.
|
||||||
@ -266,32 +284,147 @@ public:
|
|||||||
return !((*this) == Val);
|
return !((*this) == Val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compare this APInt with the given APInt& RHS for
|
/// @brief Equality comparison
|
||||||
/// the validity of the less-than relationship.
|
bool eq(const APInt &RHS) const {
|
||||||
/// @brief Less-than operator.
|
return (*this) == RHS;
|
||||||
bool operator <(const APInt& RHS) const;
|
}
|
||||||
|
|
||||||
/// Compare this APInt with the given APInt& RHS for the validity
|
/// @brief Inequality comparison
|
||||||
/// of the less-than-or-equal relationship.
|
bool ne(const APInt &RHS) const {
|
||||||
/// @brief Less-than-or-equal operator.
|
return !((*this) == RHS);
|
||||||
bool operator<=(const APInt& RHS) const;
|
}
|
||||||
|
|
||||||
/// Compare this APInt with the given APInt& RHS for the validity
|
/// @brief Unsigned less than comparison
|
||||||
/// of the greater-than relationship.
|
bool ult(const APInt& RHS) const;
|
||||||
/// @brief Greater-than operator.
|
|
||||||
bool operator> (const APInt& RHS) const;
|
|
||||||
|
|
||||||
/// @brief Greater-than-or-equal operator.
|
/// @brief Signed less than comparison
|
||||||
/// Compare this APInt with the given APInt& RHS for the validity
|
bool slt(const APInt& RHS) const;
|
||||||
/// of the greater-than-or-equal relationship.
|
|
||||||
bool operator>=(const APInt& RHS) const;
|
/// @brief Unsigned less or equal comparison
|
||||||
|
bool ule(const APInt& RHS) const {
|
||||||
|
return ult(RHS) || eq(RHS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Signed less or equal comparison
|
||||||
|
bool sle(const APInt& RHS) const {
|
||||||
|
return slt(RHS) || eq(RHS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Unsigned greather than comparison
|
||||||
|
bool ugt(const APInt& RHS) const {
|
||||||
|
return !ult(RHS) && !eq(RHS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Signed greather than comparison
|
||||||
|
bool sgt(const APInt& RHS) const {
|
||||||
|
return !slt(RHS) && !eq(RHS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Unsigned greater or equal comparison
|
||||||
|
bool uge(const APInt& RHS) const {
|
||||||
|
return !ult(RHS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Signed greather or equal comparison
|
||||||
|
bool sge(const APInt& RHS) const {
|
||||||
|
return !slt(RHS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Arithmetic right-shift this APInt by shiftAmt.
|
||||||
|
/// @brief Arithmetic right-shift function.
|
||||||
|
APInt ashr(unsigned shiftAmt) const;
|
||||||
|
|
||||||
|
/// Logical right-shift this APInt by shiftAmt.
|
||||||
|
/// @brief Logical right-shift function.
|
||||||
|
APInt lshr(unsigned shiftAmt) const;
|
||||||
|
|
||||||
|
/// Left-shift this APInt by shiftAmt.
|
||||||
|
/// @brief Left-shift function.
|
||||||
|
APInt shl(unsigned shiftAmt) const;
|
||||||
|
|
||||||
|
/// Signed divide this APInt by APInt RHS.
|
||||||
|
/// @brief Signed division function for APInt.
|
||||||
|
inline APInt sdiv(const APInt& RHS) const {
|
||||||
|
bool isNegativeLHS = (*this)[BitWidth - 1];
|
||||||
|
bool isNegativeRHS = RHS[RHS.BitWidth - 1];
|
||||||
|
APInt API = APIntOps::udiv(
|
||||||
|
isNegativeLHS ? -(*this) : (*this), isNegativeRHS ? -RHS : RHS);
|
||||||
|
return isNegativeLHS != isNegativeRHS ? -API : API;;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Unsigned divide this APInt by APInt RHS.
|
||||||
|
/// @brief Unsigned division function for APInt.
|
||||||
|
APInt udiv(const APInt& RHS) const;
|
||||||
|
|
||||||
|
/// Signed remainder operation on APInt.
|
||||||
|
/// @brief Function for signed remainder operation.
|
||||||
|
inline APInt srem(const APInt& RHS) const {
|
||||||
|
bool isNegativeLHS = (*this)[BitWidth - 1];
|
||||||
|
bool isNegativeRHS = RHS[RHS.BitWidth - 1];
|
||||||
|
APInt API = APIntOps::urem(
|
||||||
|
isNegativeLHS ? -(*this) : (*this), isNegativeRHS ? -RHS : RHS);
|
||||||
|
return isNegativeLHS ? -API : API;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Unsigned remainder operation on APInt.
|
||||||
|
/// @brief Function for unsigned remainder operation.
|
||||||
|
APInt urem(const APInt& RHS) const;
|
||||||
|
|
||||||
|
/// Truncate the APInt to a specified width. It is an error to specify a width
|
||||||
|
/// that is greater than or equal to the current width.
|
||||||
|
/// @brief Truncate to new width.
|
||||||
|
void trunc(unsigned width);
|
||||||
|
|
||||||
|
/// This operation sign extends the APInt to a new width. If the high order
|
||||||
|
/// bit is set, the fill on the left will be done with 1 bits, otherwise zero.
|
||||||
|
/// It is an error to specify a width that is less than or equal to the
|
||||||
|
/// current width.
|
||||||
|
/// @brief Sign extend to a new width.
|
||||||
|
void sext(unsigned width);
|
||||||
|
|
||||||
|
/// This operation zero extends the APInt to a new width. Thie high order bits
|
||||||
|
/// are filled with 0 bits. It is an error to specify a width that is less
|
||||||
|
/// than or equal to the current width.
|
||||||
|
/// @brief Zero extend to a new width.
|
||||||
|
void zext(unsigned width);
|
||||||
|
|
||||||
|
/// @brief Set every bit to 1.
|
||||||
|
APInt& set();
|
||||||
|
|
||||||
|
/// Set the given bit to 1 whose position is given as "bitPosition".
|
||||||
|
/// @brief Set a given bit to 1.
|
||||||
|
APInt& set(unsigned bitPosition);
|
||||||
|
|
||||||
|
/// @brief Set every bit to 0.
|
||||||
|
APInt& clear();
|
||||||
|
|
||||||
|
/// Set the given bit to 0 whose position is given as "bitPosition".
|
||||||
|
/// @brief Set a given bit to 0.
|
||||||
|
APInt& clear(unsigned bitPosition);
|
||||||
|
|
||||||
|
/// @brief Toggle every bit to its opposite value.
|
||||||
|
APInt& flip();
|
||||||
|
|
||||||
|
/// Toggle a given bit to its opposite value whose position is given
|
||||||
|
/// as "bitPosition".
|
||||||
|
/// @brief Toggles a given bit to its opposite value.
|
||||||
|
APInt& flip(unsigned bitPosition);
|
||||||
|
|
||||||
|
/// This function returns the number of active bits which is defined as the
|
||||||
|
/// bit width minus the number of leading zeros. This is used in several
|
||||||
|
/// computations to see how "wide" the value is.
|
||||||
|
/// @brief Compute the number of active bits in the value
|
||||||
|
inline unsigned getActiveBits() const {
|
||||||
|
return getNumWords() * APINT_BITS_PER_WORD - countLeadingZeros();
|
||||||
|
}
|
||||||
|
|
||||||
/// @returns a uint64_t value from this APInt. If this APInt contains a single
|
/// @returns a uint64_t value from this APInt. If this APInt contains a single
|
||||||
/// word, just returns VAL, otherwise pVal[0].
|
/// word, just returns VAL, otherwise pVal[0].
|
||||||
inline uint64_t getValue(bool isSigned = false) const {
|
inline uint64_t getValue(bool isSigned = false) const {
|
||||||
if (isSingleWord())
|
if (isSingleWord())
|
||||||
return isSigned ? int64_t(VAL << (64 - BitsNum)) >> (64 - BitsNum) : VAL;
|
return isSigned ? int64_t(VAL << (64 - BitWidth)) >>
|
||||||
unsigned n = getNumWords() * 64 - CountLeadingZeros();
|
(64 - BitWidth) : VAL;
|
||||||
|
unsigned n = getActiveBits();
|
||||||
if (n <= 64)
|
if (n <= 64)
|
||||||
return pVal[0];
|
return pVal[0];
|
||||||
assert(0 && "This APInt's bitwidth > 64");
|
assert(0 && "This APInt's bitwidth > 64");
|
||||||
@ -316,119 +449,65 @@ public:
|
|||||||
/// @brief Get the '0' value.
|
/// @brief Get the '0' value.
|
||||||
static APInt getNullValue(unsigned numBits);
|
static APInt getNullValue(unsigned numBits);
|
||||||
|
|
||||||
/// @brief Set every bit to 1.
|
/// This converts the APInt to a boolean valy as a test against zero.
|
||||||
APInt& set();
|
/// @brief Boolean conversion function.
|
||||||
|
inline bool getBoolValue() const {
|
||||||
/// Set the given bit to 1 whose position is given as "bitPosition".
|
return countLeadingZeros() != BitWidth;
|
||||||
/// @brief Set a given bit to 1.
|
}
|
||||||
APInt& set(unsigned bitPosition);
|
|
||||||
|
|
||||||
/// @brief Set every bit to 0.
|
|
||||||
APInt& clear();
|
|
||||||
|
|
||||||
/// Set the given bit to 0 whose position is given as "bitPosition".
|
|
||||||
/// @brief Set a given bit to 0.
|
|
||||||
APInt& clear(unsigned bitPosition);
|
|
||||||
|
|
||||||
/// @brief Toggle every bit to its opposite value.
|
|
||||||
APInt& flip();
|
|
||||||
|
|
||||||
/// Toggle a given bit to its opposite value whose position is given
|
|
||||||
/// as "bitPosition".
|
|
||||||
/// @brief Toggles a given bit to its opposite value.
|
|
||||||
APInt& flip(unsigned bitPosition);
|
|
||||||
|
|
||||||
/// @returns a character interpretation of the APInt.
|
/// @returns a character interpretation of the APInt.
|
||||||
std::string to_string(uint8_t radix = 10) const;
|
std::string toString(uint8_t radix = 10) const;
|
||||||
|
|
||||||
/// Get an APInt with the same BitsNum as this APInt, just zero mask
|
/// Get an APInt with the same BitWidth as this APInt, just zero mask
|
||||||
/// the low bits and right shift to the least significant bit.
|
/// the low bits and right shift to the least significant bit.
|
||||||
/// @returns the high "numBits" bits of this APInt.
|
/// @returns the high "numBits" bits of this APInt.
|
||||||
APInt HiBits(unsigned numBits) const;
|
APInt getHiBits(unsigned numBits) const;
|
||||||
|
|
||||||
/// Get an APInt with the same BitsNum as this APInt, just zero mask
|
/// Get an APInt with the same BitWidth as this APInt, just zero mask
|
||||||
/// the high bits.
|
/// the high bits.
|
||||||
/// @returns the low "numBits" bits of this APInt.
|
/// @returns the low "numBits" bits of this APInt.
|
||||||
APInt LoBits(unsigned numBits) const;
|
APInt getLoBits(unsigned numBits) const;
|
||||||
|
|
||||||
/// @returns true if the argument APInt value is a power of two > 0.
|
/// @returns true if the argument APInt value is a power of two > 0.
|
||||||
inline const bool isPowerOf2() const {
|
inline bool isPowerOf2() const;
|
||||||
return (!!*this) && !(*this & (*this - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @returns the number of zeros from the most significant bit to the first
|
/// @returns the number of zeros from the most significant bit to the first
|
||||||
/// one bits.
|
/// one bits.
|
||||||
unsigned CountLeadingZeros() const;
|
unsigned countLeadingZeros() const;
|
||||||
|
|
||||||
/// @returns the number of zeros from the least significant bit to the first
|
/// @returns the number of zeros from the least significant bit to the first
|
||||||
/// one bit.
|
/// one bit.
|
||||||
unsigned CountTrailingZeros() const;
|
unsigned countTrailingZeros() const;
|
||||||
|
|
||||||
/// @returns the number of set bits.
|
/// @returns the number of set bits.
|
||||||
unsigned CountPopulation() const;
|
unsigned countPopulation() const;
|
||||||
|
|
||||||
/// @returns the total number of bits.
|
/// @returns the total number of bits.
|
||||||
inline unsigned getNumBits() const
|
inline unsigned getNumBits() const {
|
||||||
{ return BitsNum; }
|
return BitWidth;
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Check if this APInt has a N-bits integer value.
|
/// @brief Check if this APInt has a N-bits integer value.
|
||||||
inline bool IsIntN(unsigned N) const {
|
inline bool isIntN(unsigned N) const {
|
||||||
assert(N && "N == 0 ???");
|
assert(N && "N == 0 ???");
|
||||||
if (isSingleWord()) {
|
if (isSingleWord()) {
|
||||||
return VAL == (VAL & (~0ULL >> (64 - N)));
|
return VAL == (VAL & (~0ULL >> (64 - N)));
|
||||||
} else {
|
} else {
|
||||||
APInt Tmp(N, pVal);
|
APInt Tmp(N, getNumWords(), pVal);
|
||||||
return Tmp == (*this);
|
return Tmp == (*this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @returns a byte-swapped representation of this APInt Value.
|
/// @returns a byte-swapped representation of this APInt Value.
|
||||||
APInt ByteSwap() const;
|
APInt byteSwap() const;
|
||||||
|
|
||||||
/// @returns the floor log base 2 of this APInt.
|
/// @returns the floor log base 2 of this APInt.
|
||||||
inline unsigned LogBase2() const {
|
inline unsigned logBase2() const {
|
||||||
return getNumWords() * APINT_BITS_PER_WORD - 1 -
|
return getNumWords() * APINT_BITS_PER_WORD - 1 - countLeadingZeros();
|
||||||
CountLeadingZeros();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Converts this APInt to a double value.
|
/// @brief Converts this APInt to a double value.
|
||||||
double RoundToDouble(bool isSigned = false) const;
|
double roundToDouble(bool isSigned = false) const;
|
||||||
|
|
||||||
/// Arithmetic right-shift this APInt by shiftAmt.
|
|
||||||
/// @brief Arithmetic right-shift function.
|
|
||||||
APInt AShr(unsigned shiftAmt) const;
|
|
||||||
|
|
||||||
/// Logical right-shift this APInt by shiftAmt.
|
|
||||||
/// @brief Logical right-shift function.
|
|
||||||
APInt LShr(unsigned shiftAmt) const;
|
|
||||||
|
|
||||||
/// Left-shift this APInt by shiftAmt.
|
|
||||||
/// @brief Left-shift function.
|
|
||||||
APInt Shl(unsigned shiftAmt) const;
|
|
||||||
|
|
||||||
/// Signed divide this APInt by APInt RHS.
|
|
||||||
/// @brief Signed division function for APInt.
|
|
||||||
inline APInt SDiv(const APInt& RHS) const {
|
|
||||||
bool isSignedLHS = (*this)[BitsNum - 1], isSignedRHS = RHS[RHS.BitsNum - 1];
|
|
||||||
APInt API = APIntOps::UDiv(isSignedLHS ? -(*this) : (*this), isSignedRHS ? -RHS : RHS);
|
|
||||||
return isSignedLHS != isSignedRHS ? -API : API;;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Unsigned divide this APInt by APInt RHS.
|
|
||||||
/// @brief Unsigned division function for APInt.
|
|
||||||
APInt UDiv(const APInt& RHS) const;
|
|
||||||
|
|
||||||
/// Signed remainder operation on APInt.
|
|
||||||
/// @brief Function for signed remainder operation.
|
|
||||||
inline APInt SRem(const APInt& RHS) const {
|
|
||||||
bool isSignedLHS = (*this)[BitsNum - 1], isSignedRHS = RHS[RHS.BitsNum - 1];
|
|
||||||
APInt API = APIntOps::URem(isSignedLHS ? -(*this) : (*this), isSignedRHS ? -RHS : RHS);
|
|
||||||
return isSignedLHS ? -API : API;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Unsigned remainder operation on APInt.
|
|
||||||
/// @brief Function for unsigned remainder operation.
|
|
||||||
APInt URem(const APInt& RHS) const;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -436,29 +515,29 @@ namespace APIntOps {
|
|||||||
|
|
||||||
/// @brief Check if the specified APInt has a N-bits integer value.
|
/// @brief Check if the specified APInt has a N-bits integer value.
|
||||||
inline bool isIntN(unsigned N, const APInt& APIVal) {
|
inline bool isIntN(unsigned N, const APInt& APIVal) {
|
||||||
return APIVal.IsIntN(N);
|
return APIVal.isIntN(N);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @returns true if the argument APInt value is a sequence of ones
|
/// @returns true if the argument APInt value is a sequence of ones
|
||||||
/// starting at the least significant bit with the remainder zero.
|
/// starting at the least significant bit with the remainder zero.
|
||||||
inline const bool isMask(unsigned numBits, const APInt& APIVal) {
|
inline const bool isMask(unsigned numBits, const APInt& APIVal) {
|
||||||
return APIVal && ((APIVal + 1) & APIVal) == 0;
|
return APIVal.getBoolValue() && ((APIVal + APInt(numBits,1)) & APIVal) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @returns true if the argument APInt value contains a sequence of ones
|
/// @returns true if the argument APInt value contains a sequence of ones
|
||||||
/// with the remainder zero.
|
/// with the remainder zero.
|
||||||
inline const bool isShiftedMask(unsigned numBits, const APInt& APIVal) {
|
inline const bool isShiftedMask(unsigned numBits, const APInt& APIVal) {
|
||||||
return isMask(numBits, (APIVal - 1) | APIVal);
|
return isMask(numBits, (APIVal - APInt(numBits,1)) | APIVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @returns a byte-swapped representation of the specified APInt Value.
|
/// @returns a byte-swapped representation of the specified APInt Value.
|
||||||
inline APInt ByteSwap(const APInt& APIVal) {
|
inline APInt byteSwap(const APInt& APIVal) {
|
||||||
return APIVal.ByteSwap();
|
return APIVal.byteSwap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @returns the floor log base 2 of the specified APInt value.
|
/// @returns the floor log base 2 of the specified APInt value.
|
||||||
inline unsigned LogBase2(const APInt& APIVal) {
|
inline unsigned logBase2(const APInt& APIVal) {
|
||||||
return APIVal.LogBase2();
|
return APIVal.logBase2();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @returns the greatest common divisor of the two values
|
/// @returns the greatest common divisor of the two values
|
||||||
@ -466,80 +545,80 @@ inline unsigned LogBase2(const APInt& APIVal) {
|
|||||||
APInt GreatestCommonDivisor(const APInt& API1, const APInt& API2);
|
APInt GreatestCommonDivisor(const APInt& API1, const APInt& API2);
|
||||||
|
|
||||||
/// @brief Converts the given APInt to a double value.
|
/// @brief Converts the given APInt to a double value.
|
||||||
inline double APIntRoundToDouble(const APInt& APIVal, bool isSigned = false) {
|
inline double RoundAPIntToDouble(const APInt& APIVal, bool isSigned = false) {
|
||||||
return APIVal.RoundToDouble(isSigned);
|
return APIVal.roundToDouble(isSigned);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Converts the given APInt to a float vlalue.
|
/// @brief Converts the given APInt to a float vlalue.
|
||||||
inline float APIntRoundToFloat(const APInt& APIVal) {
|
inline float RoundAPIntToFloat(const APInt& APIVal) {
|
||||||
return float(APIntRoundToDouble(APIVal));
|
return float(RoundAPIntToDouble(APIVal));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Converts the given double value into a APInt.
|
/// @brief Converts the given double value into a APInt.
|
||||||
APInt DoubleRoundToAPInt(double Double);
|
APInt RoundDoubleToAPInt(double Double);
|
||||||
|
|
||||||
/// @brief Converts the given float value into a APInt.
|
/// @brief Converts the given float value into a APInt.
|
||||||
inline APInt FloatRoundToAPInt(float Float) {
|
inline APInt RoundFloatToAPInt(float Float) {
|
||||||
return DoubleRoundToAPInt(double(Float));
|
return RoundDoubleToAPInt(double(Float));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Arithmetic right-shift the APInt by shiftAmt.
|
/// Arithmetic right-shift the APInt by shiftAmt.
|
||||||
/// @brief Arithmetic right-shift function.
|
/// @brief Arithmetic right-shift function.
|
||||||
inline APInt AShr(const APInt& LHS, unsigned shiftAmt) {
|
inline APInt ashr(const APInt& LHS, unsigned shiftAmt) {
|
||||||
return LHS.AShr(shiftAmt);
|
return LHS.ashr(shiftAmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Logical right-shift the APInt by shiftAmt.
|
/// Logical right-shift the APInt by shiftAmt.
|
||||||
/// @brief Logical right-shift function.
|
/// @brief Logical right-shift function.
|
||||||
inline APInt LShr(const APInt& LHS, unsigned shiftAmt) {
|
inline APInt lshr(const APInt& LHS, unsigned shiftAmt) {
|
||||||
return LHS.LShr(shiftAmt);
|
return LHS.lshr(shiftAmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Left-shift the APInt by shiftAmt.
|
/// Left-shift the APInt by shiftAmt.
|
||||||
/// @brief Left-shift function.
|
/// @brief Left-shift function.
|
||||||
inline APInt Shl(const APInt& LHS, unsigned shiftAmt) {
|
inline APInt shl(const APInt& LHS, unsigned shiftAmt) {
|
||||||
return LHS.Shl(shiftAmt);
|
return LHS.shl(shiftAmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signed divide APInt LHS by APInt RHS.
|
/// Signed divide APInt LHS by APInt RHS.
|
||||||
/// @brief Signed division function for APInt.
|
/// @brief Signed division function for APInt.
|
||||||
inline APInt SDiv(const APInt& LHS, const APInt& RHS) {
|
inline APInt sdiv(const APInt& LHS, const APInt& RHS) {
|
||||||
return LHS.SDiv(RHS);
|
return LHS.sdiv(RHS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unsigned divide APInt LHS by APInt RHS.
|
/// Unsigned divide APInt LHS by APInt RHS.
|
||||||
/// @brief Unsigned division function for APInt.
|
/// @brief Unsigned division function for APInt.
|
||||||
inline APInt UDiv(const APInt& LHS, const APInt& RHS) {
|
inline APInt udiv(const APInt& LHS, const APInt& RHS) {
|
||||||
return LHS.UDiv(RHS);
|
return LHS.udiv(RHS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signed remainder operation on APInt.
|
/// Signed remainder operation on APInt.
|
||||||
/// @brief Function for signed remainder operation.
|
/// @brief Function for signed remainder operation.
|
||||||
inline APInt SRem(const APInt& LHS, const APInt& RHS) {
|
inline APInt srem(const APInt& LHS, const APInt& RHS) {
|
||||||
return LHS.SRem(RHS);
|
return LHS.srem(RHS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unsigned remainder operation on APInt.
|
/// Unsigned remainder operation on APInt.
|
||||||
/// @brief Function for unsigned remainder operation.
|
/// @brief Function for unsigned remainder operation.
|
||||||
inline APInt URem(const APInt& LHS, const APInt& RHS) {
|
inline APInt urem(const APInt& LHS, const APInt& RHS) {
|
||||||
return LHS.URem(RHS);
|
return LHS.urem(RHS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Performs multiplication on APInt values.
|
/// Performs multiplication on APInt values.
|
||||||
/// @brief Function for multiplication operation.
|
/// @brief Function for multiplication operation.
|
||||||
inline APInt Mul(const APInt& LHS, const APInt& RHS) {
|
inline APInt mul(const APInt& LHS, const APInt& RHS) {
|
||||||
return LHS * RHS;
|
return LHS * RHS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Performs addition on APInt values.
|
/// Performs addition on APInt values.
|
||||||
/// @brief Function for addition operation.
|
/// @brief Function for addition operation.
|
||||||
inline APInt Add(const APInt& LHS, const APInt& RHS) {
|
inline APInt add(const APInt& LHS, const APInt& RHS) {
|
||||||
return LHS + RHS;
|
return LHS + RHS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Performs subtraction on APInt values.
|
/// Performs subtraction on APInt values.
|
||||||
/// @brief Function for subtraction operation.
|
/// @brief Function for subtraction operation.
|
||||||
inline APInt Sub(const APInt& LHS, const APInt& RHS) {
|
inline APInt sub(const APInt& LHS, const APInt& RHS) {
|
||||||
return LHS - RHS;
|
return LHS - RHS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,6 +241,7 @@ static void div(unsigned zds[], unsigned nx, unsigned y[], unsigned ny) {
|
|||||||
} while (--j >= ny);
|
} while (--j >= ny);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
/// lshift - This function shift x[0:len-1] left by shiftAmt bits, and
|
/// lshift - This function shift x[0:len-1] left by shiftAmt bits, and
|
||||||
/// store the len least significant words of the result in
|
/// store the len least significant words of the result in
|
||||||
/// dest[d_offset:d_offset+len-1]. It returns the bits shifted out from
|
/// dest[d_offset:d_offset+len-1]. It returns the bits shifted out from
|
||||||
@ -259,13 +260,14 @@ static uint64_t lshift(uint64_t dest[], unsigned d_offset,
|
|||||||
dest[d_offset+i] = high_word << shiftAmt;
|
dest[d_offset+i] = high_word << shiftAmt;
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
APInt::APInt(uint64_t val, unsigned numBits)
|
APInt::APInt(unsigned numBits, uint64_t val)
|
||||||
: BitsNum(numBits) {
|
: BitWidth(numBits) {
|
||||||
assert(BitsNum >= IntegerType::MIN_INT_BITS && "bitwidth too small");
|
assert(BitWidth >= IntegerType::MIN_INT_BITS && "bitwidth too small");
|
||||||
assert(BitsNum <= IntegerType::MAX_INT_BITS && "bitwidth too large");
|
assert(BitWidth <= IntegerType::MAX_INT_BITS && "bitwidth too large");
|
||||||
if (isSingleWord())
|
if (isSingleWord())
|
||||||
VAL = val & (~uint64_t(0ULL) >> (APINT_BITS_PER_WORD - BitsNum));
|
VAL = val & (~uint64_t(0ULL) >> (APINT_BITS_PER_WORD - BitWidth));
|
||||||
else {
|
else {
|
||||||
// Memory allocation and check if successful.
|
// Memory allocation and check if successful.
|
||||||
assert((pVal = new uint64_t[getNumWords()]) &&
|
assert((pVal = new uint64_t[getNumWords()]) &&
|
||||||
@ -275,53 +277,54 @@ APInt::APInt(uint64_t val, unsigned numBits)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
APInt::APInt(unsigned numBits, uint64_t bigVal[])
|
APInt::APInt(unsigned numBits, unsigned numWords, uint64_t bigVal[])
|
||||||
: BitsNum(numBits) {
|
: BitWidth(numBits) {
|
||||||
assert(BitsNum >= IntegerType::MIN_INT_BITS && "bitwidth too small");
|
assert(BitWidth >= IntegerType::MIN_INT_BITS && "bitwidth too small");
|
||||||
assert(BitsNum <= IntegerType::MAX_INT_BITS && "bitwidth too large");
|
assert(BitWidth <= IntegerType::MAX_INT_BITS && "bitwidth too large");
|
||||||
assert(bigVal && "Null pointer detected!");
|
assert(bigVal && "Null pointer detected!");
|
||||||
if (isSingleWord())
|
if (isSingleWord())
|
||||||
VAL = bigVal[0] & (~uint64_t(0ULL) >> (APINT_BITS_PER_WORD - BitsNum));
|
VAL = bigVal[0] & (~uint64_t(0ULL) >> (APINT_BITS_PER_WORD - BitWidth));
|
||||||
else {
|
else {
|
||||||
// Memory allocation and check if successful.
|
// Memory allocation and check if successful.
|
||||||
assert((pVal = new uint64_t[getNumWords()]) &&
|
assert((pVal = new uint64_t[getNumWords()]) &&
|
||||||
"APInt memory allocation fails!");
|
"APInt memory allocation fails!");
|
||||||
// Calculate the actual length of bigVal[].
|
// Calculate the actual length of bigVal[].
|
||||||
unsigned n = sizeof(*bigVal) / sizeof(bigVal[0]);
|
unsigned maxN = std::max<unsigned>(numWords, getNumWords());
|
||||||
unsigned maxN = std::max<unsigned>(n, getNumWords());
|
unsigned minN = std::min<unsigned>(numWords, getNumWords());
|
||||||
unsigned minN = std::min<unsigned>(n, getNumWords());
|
|
||||||
memcpy(pVal, bigVal, (minN - 1) * 8);
|
memcpy(pVal, bigVal, (minN - 1) * 8);
|
||||||
pVal[minN-1] = bigVal[minN-1] & (~uint64_t(0ULL) >> (64 - BitsNum % 64));
|
pVal[minN-1] = bigVal[minN-1] & (~uint64_t(0ULL) >> (64 - BitWidth % 64));
|
||||||
if (maxN == getNumWords())
|
if (maxN == getNumWords())
|
||||||
memset(pVal+n, 0, (getNumWords() - n) * 8);
|
memset(pVal+numWords, 0, (getNumWords() - numWords) * 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Create a new APInt by translating the char array represented
|
/// @brief Create a new APInt by translating the char array represented
|
||||||
/// integer value.
|
/// integer value.
|
||||||
APInt::APInt(const char StrStart[], unsigned slen, uint8_t radix) {
|
APInt::APInt(unsigned numbits, const char StrStart[], unsigned slen,
|
||||||
StrToAPInt(StrStart, slen, radix);
|
uint8_t radix) {
|
||||||
|
fromString(numbits, StrStart, slen, radix);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Create a new APInt by translating the string represented
|
/// @brief Create a new APInt by translating the string represented
|
||||||
/// integer value.
|
/// integer value.
|
||||||
APInt::APInt(const std::string& Val, uint8_t radix) {
|
APInt::APInt(unsigned numbits, const std::string& Val, uint8_t radix) {
|
||||||
assert(!Val.empty() && "String empty?");
|
assert(!Val.empty() && "String empty?");
|
||||||
StrToAPInt(Val.c_str(), Val.size(), radix);
|
fromString(numbits, Val.c_str(), Val.size(), radix);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Converts a char array into an integer.
|
/// @brief Converts a char array into an integer.
|
||||||
void APInt::StrToAPInt(const char *StrStart, unsigned slen, uint8_t radix) {
|
void APInt::fromString(unsigned numbits, const char *StrStart, unsigned slen,
|
||||||
|
uint8_t radix) {
|
||||||
assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) &&
|
assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) &&
|
||||||
"Radix should be 2, 8, 10, or 16!");
|
"Radix should be 2, 8, 10, or 16!");
|
||||||
assert(StrStart && "String empty?");
|
assert(StrStart && "String is null?");
|
||||||
unsigned size = 0;
|
unsigned size = 0;
|
||||||
// If the radix is a power of 2, read the input
|
// If the radix is a power of 2, read the input
|
||||||
// from most significant to least significant.
|
// from most significant to least significant.
|
||||||
if ((radix & (radix - 1)) == 0) {
|
if ((radix & (radix - 1)) == 0) {
|
||||||
unsigned nextBitPos = 0, bits_per_digit = radix / 8 + 2;
|
unsigned nextBitPos = 0, bits_per_digit = radix / 8 + 2;
|
||||||
uint64_t resDigit = 0;
|
uint64_t resDigit = 0;
|
||||||
BitsNum = slen * bits_per_digit;
|
BitWidth = slen * bits_per_digit;
|
||||||
if (getNumWords() > 1)
|
if (getNumWords() > 1)
|
||||||
assert((pVal = new uint64_t[getNumWords()]) &&
|
assert((pVal = new uint64_t[getNumWords()]) &&
|
||||||
"APInt memory allocation fails!");
|
"APInt memory allocation fails!");
|
||||||
@ -348,10 +351,10 @@ void APInt::StrToAPInt(const char *StrStart, unsigned slen, uint8_t radix) {
|
|||||||
if (slen < chars_per_word ||
|
if (slen < chars_per_word ||
|
||||||
(slen == chars_per_word && // In case the value <= 2^64 - 1
|
(slen == chars_per_word && // In case the value <= 2^64 - 1
|
||||||
strcmp(StrStart, "18446744073709551615") <= 0)) {
|
strcmp(StrStart, "18446744073709551615") <= 0)) {
|
||||||
BitsNum = 64;
|
BitWidth = 64;
|
||||||
VAL = strtoull(StrStart, 0, 10);
|
VAL = strtoull(StrStart, 0, 10);
|
||||||
} else { // In case the value > 2^64 - 1
|
} else { // In case the value > 2^64 - 1
|
||||||
BitsNum = (slen / chars_per_word + 1) * 64;
|
BitWidth = (slen / chars_per_word + 1) * 64;
|
||||||
assert((pVal = new uint64_t[getNumWords()]) &&
|
assert((pVal = new uint64_t[getNumWords()]) &&
|
||||||
"APInt memory allocation fails!");
|
"APInt memory allocation fails!");
|
||||||
memset(pVal, 0, getNumWords() * 8);
|
memset(pVal, 0, getNumWords() * 8);
|
||||||
@ -382,7 +385,7 @@ void APInt::StrToAPInt(const char *StrStart, unsigned slen, uint8_t radix) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
APInt::APInt(const APInt& APIVal)
|
APInt::APInt(const APInt& APIVal)
|
||||||
: BitsNum(APIVal.BitsNum) {
|
: BitWidth(APIVal.BitWidth) {
|
||||||
if (isSingleWord()) VAL = APIVal.VAL;
|
if (isSingleWord()) VAL = APIVal.VAL;
|
||||||
else {
|
else {
|
||||||
// Memory allocation and check if successful.
|
// Memory allocation and check if successful.
|
||||||
@ -399,7 +402,9 @@ APInt::~APInt() {
|
|||||||
/// @brief Copy assignment operator. Create a new object from the given
|
/// @brief Copy assignment operator. Create a new object from the given
|
||||||
/// APInt one by initialization.
|
/// APInt one by initialization.
|
||||||
APInt& APInt::operator=(const APInt& RHS) {
|
APInt& APInt::operator=(const APInt& RHS) {
|
||||||
if (isSingleWord()) VAL = RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0];
|
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
|
||||||
|
if (isSingleWord())
|
||||||
|
VAL = RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0];
|
||||||
else {
|
else {
|
||||||
unsigned minN = std::min(getNumWords(), RHS.getNumWords());
|
unsigned minN = std::min(getNumWords(), RHS.getNumWords());
|
||||||
memcpy(pVal, RHS.isSingleWord() ? &RHS.VAL : RHS.pVal, minN * 8);
|
memcpy(pVal, RHS.isSingleWord() ? &RHS.VAL : RHS.pVal, minN * 8);
|
||||||
@ -412,21 +417,23 @@ APInt& APInt::operator=(const APInt& RHS) {
|
|||||||
/// @brief Assignment operator. Assigns a common case integer value to
|
/// @brief Assignment operator. Assigns a common case integer value to
|
||||||
/// the APInt.
|
/// the APInt.
|
||||||
APInt& APInt::operator=(uint64_t RHS) {
|
APInt& APInt::operator=(uint64_t RHS) {
|
||||||
if (isSingleWord()) VAL = RHS;
|
if (isSingleWord())
|
||||||
|
VAL = RHS;
|
||||||
else {
|
else {
|
||||||
pVal[0] = RHS;
|
pVal[0] = RHS;
|
||||||
memset(pVal, 0, (getNumWords() - 1) * 8);
|
memset(pVal, 0, (getNumWords() - 1) * 8);
|
||||||
}
|
}
|
||||||
TruncToBits();
|
clearUnusedBits();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Prefix increment operator. Increments the APInt by one.
|
/// @brief Prefix increment operator. Increments the APInt by one.
|
||||||
APInt& APInt::operator++() {
|
APInt& APInt::operator++() {
|
||||||
if (isSingleWord()) ++VAL;
|
if (isSingleWord())
|
||||||
|
++VAL;
|
||||||
else
|
else
|
||||||
add_1(pVal, pVal, getNumWords(), 1);
|
add_1(pVal, pVal, getNumWords(), 1);
|
||||||
TruncToBits();
|
clearUnusedBits();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,7 +442,7 @@ APInt& APInt::operator--() {
|
|||||||
if (isSingleWord()) --VAL;
|
if (isSingleWord()) --VAL;
|
||||||
else
|
else
|
||||||
sub_1(pVal, getNumWords(), 1);
|
sub_1(pVal, getNumWords(), 1);
|
||||||
TruncToBits();
|
clearUnusedBits();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -455,7 +462,7 @@ APInt& APInt::operator+=(const APInt& RHS) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TruncToBits();
|
clearUnusedBits();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -476,7 +483,7 @@ APInt& APInt::operator-=(const APInt& RHS) {
|
|||||||
sub(pVal, pVal, RHS.pVal, getNumWords());
|
sub(pVal, pVal, RHS.pVal, getNumWords());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TruncToBits();
|
clearUnusedBits();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,14 +493,14 @@ APInt& APInt::operator*=(const APInt& RHS) {
|
|||||||
if (isSingleWord()) VAL *= RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0];
|
if (isSingleWord()) VAL *= RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0];
|
||||||
else {
|
else {
|
||||||
// one-based first non-zero bit position.
|
// one-based first non-zero bit position.
|
||||||
unsigned first = getNumWords() * APINT_BITS_PER_WORD - CountLeadingZeros();
|
unsigned first = getActiveBits();
|
||||||
unsigned xlen = !first ? 0 : whichWord(first - 1) + 1;
|
unsigned xlen = !first ? 0 : whichWord(first - 1) + 1;
|
||||||
if (!xlen)
|
if (!xlen)
|
||||||
return *this;
|
return *this;
|
||||||
else if (RHS.isSingleWord())
|
else if (RHS.isSingleWord())
|
||||||
mul_1(pVal, pVal, xlen, RHS.VAL);
|
mul_1(pVal, pVal, xlen, RHS.VAL);
|
||||||
else {
|
else {
|
||||||
first = RHS.getNumWords() * APINT_BITS_PER_WORD - RHS.CountLeadingZeros();
|
first = RHS.getActiveBits();
|
||||||
unsigned ylen = !first ? 0 : whichWord(first - 1) + 1;
|
unsigned ylen = !first ? 0 : whichWord(first - 1) + 1;
|
||||||
if (!ylen) {
|
if (!ylen) {
|
||||||
memset(pVal, 0, getNumWords() * 8);
|
memset(pVal, 0, getNumWords() * 8);
|
||||||
@ -507,7 +514,7 @@ APInt& APInt::operator*=(const APInt& RHS) {
|
|||||||
delete[] dest;
|
delete[] dest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TruncToBits();
|
clearUnusedBits();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -549,7 +556,7 @@ APInt& APInt::operator|=(const APInt& RHS) {
|
|||||||
pVal[i] |= RHS.pVal[i];
|
pVal[i] |= RHS.pVal[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TruncToBits();
|
clearUnusedBits();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -573,7 +580,7 @@ APInt& APInt::operator^=(const APInt& RHS) {
|
|||||||
pVal[i] ^= 0;
|
pVal[i] ^= 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TruncToBits();
|
clearUnusedBits();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -589,7 +596,7 @@ APInt APInt::operator&(const APInt& RHS) const {
|
|||||||
APInt APInt::operator|(const APInt& RHS) const {
|
APInt APInt::operator|(const APInt& RHS) const {
|
||||||
APInt API(RHS);
|
APInt API(RHS);
|
||||||
API |= *this;
|
API |= *this;
|
||||||
API.TruncToBits();
|
API.clearUnusedBits();
|
||||||
return API;
|
return API;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -598,41 +605,10 @@ APInt APInt::operator|(const APInt& RHS) const {
|
|||||||
APInt APInt::operator^(const APInt& RHS) const {
|
APInt APInt::operator^(const APInt& RHS) const {
|
||||||
APInt API(RHS);
|
APInt API(RHS);
|
||||||
API ^= *this;
|
API ^= *this;
|
||||||
API.TruncToBits();
|
API.clearUnusedBits();
|
||||||
return API;
|
return API;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Logical AND operator. Performs logical AND operation on this APInt
|
|
||||||
/// and the given APInt& RHS.
|
|
||||||
bool APInt::operator&&(const APInt& RHS) const {
|
|
||||||
if (isSingleWord())
|
|
||||||
return RHS.isSingleWord() ? VAL && RHS.VAL : VAL && RHS.pVal[0];
|
|
||||||
else if (RHS.isSingleWord())
|
|
||||||
return RHS.VAL && pVal[0];
|
|
||||||
else {
|
|
||||||
unsigned minN = std::min(getNumWords(), RHS.getNumWords());
|
|
||||||
for (unsigned i = 0; i < minN; ++i)
|
|
||||||
if (pVal[i] && RHS.pVal[i])
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Logical OR operator. Performs logical OR operation on this APInt
|
|
||||||
/// and the given APInt& RHS.
|
|
||||||
bool APInt::operator||(const APInt& RHS) const {
|
|
||||||
if (isSingleWord())
|
|
||||||
return RHS.isSingleWord() ? VAL || RHS.VAL : VAL || RHS.pVal[0];
|
|
||||||
else if (RHS.isSingleWord())
|
|
||||||
return RHS.VAL || pVal[0];
|
|
||||||
else {
|
|
||||||
unsigned minN = std::min(getNumWords(), RHS.getNumWords());
|
|
||||||
for (unsigned i = 0; i < minN; ++i)
|
|
||||||
if (pVal[i] || RHS.pVal[i])
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Logical negation operator. Performs logical negation operation on
|
/// @brief Logical negation operator. Performs logical negation operation on
|
||||||
/// this APInt.
|
/// this APInt.
|
||||||
@ -651,7 +627,7 @@ bool APInt::operator !() const {
|
|||||||
APInt APInt::operator*(const APInt& RHS) const {
|
APInt APInt::operator*(const APInt& RHS) const {
|
||||||
APInt API(RHS);
|
APInt API(RHS);
|
||||||
API *= *this;
|
API *= *this;
|
||||||
API.TruncToBits();
|
API.clearUnusedBits();
|
||||||
return API;
|
return API;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -659,7 +635,7 @@ APInt APInt::operator*(const APInt& RHS) const {
|
|||||||
APInt APInt::operator+(const APInt& RHS) const {
|
APInt APInt::operator+(const APInt& RHS) const {
|
||||||
APInt API(*this);
|
APInt API(*this);
|
||||||
API += RHS;
|
API += RHS;
|
||||||
API.TruncToBits();
|
API.clearUnusedBits();
|
||||||
return API;
|
return API;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -679,8 +655,8 @@ bool APInt::operator[](unsigned bitPosition) const {
|
|||||||
/// @brief Equality operator. Compare this APInt with the given APInt& RHS
|
/// @brief Equality operator. Compare this APInt with the given APInt& RHS
|
||||||
/// for the validity of the equality relationship.
|
/// for the validity of the equality relationship.
|
||||||
bool APInt::operator==(const APInt& RHS) const {
|
bool APInt::operator==(const APInt& RHS) const {
|
||||||
unsigned n1 = getNumWords() * APINT_BITS_PER_WORD - CountLeadingZeros(),
|
unsigned n1 = getActiveBits();
|
||||||
n2 = RHS.getNumWords() * APINT_BITS_PER_WORD - RHS.CountLeadingZeros();
|
unsigned n2 = RHS.getActiveBits();
|
||||||
if (n1 != n2) return false;
|
if (n1 != n2) return false;
|
||||||
else if (isSingleWord())
|
else if (isSingleWord())
|
||||||
return VAL == (RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0]);
|
return VAL == (RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0]);
|
||||||
@ -699,7 +675,7 @@ bool APInt::operator==(uint64_t Val) const {
|
|||||||
if (isSingleWord())
|
if (isSingleWord())
|
||||||
return VAL == Val;
|
return VAL == Val;
|
||||||
else {
|
else {
|
||||||
unsigned n = getNumWords() * APINT_BITS_PER_WORD - CountLeadingZeros();
|
unsigned n = getActiveBits();
|
||||||
if (n <= 64)
|
if (n <= 64)
|
||||||
return pVal[0] == Val;
|
return pVal[0] == Val;
|
||||||
else
|
else
|
||||||
@ -707,18 +683,20 @@ bool APInt::operator==(uint64_t Val) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Less-than operator. Compare this APInt with the given APInt& RHS
|
/// @brief Unsigned less than comparison
|
||||||
/// for the validity of the less-than relationship.
|
bool APInt::ult(const APInt& RHS) const {
|
||||||
bool APInt::operator <(const APInt& RHS) const {
|
assert(BitWidth == RHS.BitWidth && "Bit widths must be same for comparison");
|
||||||
unsigned n1 = getNumWords() * 64 - CountLeadingZeros(),
|
if (isSingleWord())
|
||||||
n2 = RHS.getNumWords() * 64 - RHS.CountLeadingZeros();
|
return VAL < RHS.VAL;
|
||||||
if (n1 < n2) return true;
|
|
||||||
else if (n1 > n2) return false;
|
|
||||||
else if (isSingleWord())
|
|
||||||
return VAL < (RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0]);
|
|
||||||
else {
|
else {
|
||||||
if (n1 <= 64)
|
unsigned n1 = getActiveBits();
|
||||||
return pVal[0] < (RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0]);
|
unsigned n2 = RHS.getActiveBits();
|
||||||
|
if (n1 < n2)
|
||||||
|
return true;
|
||||||
|
else if (n2 < n1)
|
||||||
|
return false;
|
||||||
|
else if (n1 <= 64 && n2 <= 64)
|
||||||
|
return pVal[0] < RHS.pVal[0];
|
||||||
for (int i = whichWord(n1 - 1); i >= 0; --i) {
|
for (int i = whichWord(n1 - 1); i >= 0; --i) {
|
||||||
if (pVal[i] > RHS.pVal[i]) return false;
|
if (pVal[i] > RHS.pVal[i]) return false;
|
||||||
else if (pVal[i] < RHS.pVal[i]) return true;
|
else if (pVal[i] < RHS.pVal[i]) return true;
|
||||||
@ -727,24 +705,28 @@ bool APInt::operator <(const APInt& RHS) const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Less-than-or-equal operator. Compare this APInt with the given
|
/// @brief Signed less than comparison
|
||||||
/// APInt& RHS for the validity of the less-than-or-equal relationship.
|
bool APInt::slt(const APInt& RHS) const {
|
||||||
bool APInt::operator<=(const APInt& RHS) const {
|
assert(BitWidth == RHS.BitWidth && "Bit widths must be same for comparison");
|
||||||
return (*this) == RHS || (*this) < RHS;
|
if (isSingleWord())
|
||||||
|
return VAL < RHS.VAL;
|
||||||
|
else {
|
||||||
|
unsigned n1 = getActiveBits();
|
||||||
|
unsigned n2 = RHS.getActiveBits();
|
||||||
|
if (n1 < n2)
|
||||||
|
return true;
|
||||||
|
else if (n2 < n1)
|
||||||
|
return false;
|
||||||
|
else if (n1 <= 64 && n2 <= 64)
|
||||||
|
return pVal[0] < RHS.pVal[0];
|
||||||
|
for (int i = whichWord(n1 - 1); i >= 0; --i) {
|
||||||
|
if (pVal[i] > RHS.pVal[i]) return false;
|
||||||
|
else if (pVal[i] < RHS.pVal[i]) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Greater-than operator. Compare this APInt with the given APInt& RHS
|
|
||||||
/// for the validity of the greater-than relationship.
|
|
||||||
bool APInt::operator >(const APInt& RHS) const {
|
|
||||||
return !((*this) <= RHS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Greater-than-or-equal operator. Compare this APInt with the given
|
|
||||||
/// APInt& RHS for the validity of the greater-than-or-equal relationship.
|
|
||||||
bool APInt::operator>=(const APInt& RHS) const {
|
|
||||||
return !((*this) < RHS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the given bit to 1 whose poition is given as "bitPosition".
|
/// Set the given bit to 1 whose poition is given as "bitPosition".
|
||||||
/// @brief Set a given bit to 1.
|
/// @brief Set a given bit to 1.
|
||||||
APInt& APInt::set(unsigned bitPosition) {
|
APInt& APInt::set(unsigned bitPosition) {
|
||||||
@ -755,11 +737,11 @@ APInt& APInt::set(unsigned bitPosition) {
|
|||||||
|
|
||||||
/// @brief Set every bit to 1.
|
/// @brief Set every bit to 1.
|
||||||
APInt& APInt::set() {
|
APInt& APInt::set() {
|
||||||
if (isSingleWord()) VAL = ~0ULL >> (64 - BitsNum);
|
if (isSingleWord()) VAL = ~0ULL >> (64 - BitWidth);
|
||||||
else {
|
else {
|
||||||
for (unsigned i = 0; i < getNumWords() - 1; ++i)
|
for (unsigned i = 0; i < getNumWords() - 1; ++i)
|
||||||
pVal[i] = -1ULL;
|
pVal[i] = -1ULL;
|
||||||
pVal[getNumWords() - 1] = ~0ULL >> (64 - BitsNum % 64);
|
pVal[getNumWords() - 1] = ~0ULL >> (64 - BitWidth % 64);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -790,12 +772,12 @@ APInt APInt::operator~() const {
|
|||||||
|
|
||||||
/// @brief Toggle every bit to its opposite value.
|
/// @brief Toggle every bit to its opposite value.
|
||||||
APInt& APInt::flip() {
|
APInt& APInt::flip() {
|
||||||
if (isSingleWord()) VAL = (~(VAL << (64 - BitsNum))) >> (64 - BitsNum);
|
if (isSingleWord()) VAL = (~(VAL << (64 - BitWidth))) >> (64 - BitWidth);
|
||||||
else {
|
else {
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
for (; i < getNumWords() - 1; ++i)
|
for (; i < getNumWords() - 1; ++i)
|
||||||
pVal[i] = ~pVal[i];
|
pVal[i] = ~pVal[i];
|
||||||
unsigned offset = 64 - (BitsNum - 64 * (i - 1));
|
unsigned offset = 64 - (BitWidth - 64 * (i - 1));
|
||||||
pVal[i] = (~(pVal[i] << offset)) >> offset;
|
pVal[i] = (~(pVal[i] << offset)) >> offset;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
@ -805,21 +787,21 @@ APInt& APInt::flip() {
|
|||||||
/// as "bitPosition".
|
/// as "bitPosition".
|
||||||
/// @brief Toggles a given bit to its opposite value.
|
/// @brief Toggles a given bit to its opposite value.
|
||||||
APInt& APInt::flip(unsigned bitPosition) {
|
APInt& APInt::flip(unsigned bitPosition) {
|
||||||
assert(bitPosition < BitsNum && "Out of the bit-width range!");
|
assert(bitPosition < BitWidth && "Out of the bit-width range!");
|
||||||
if ((*this)[bitPosition]) clear(bitPosition);
|
if ((*this)[bitPosition]) clear(bitPosition);
|
||||||
else set(bitPosition);
|
else set(bitPosition);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// to_string - This function translates the APInt into a string.
|
/// to_string - This function translates the APInt into a string.
|
||||||
std::string APInt::to_string(uint8_t radix) const {
|
std::string APInt::toString(uint8_t radix) const {
|
||||||
assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) &&
|
assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) &&
|
||||||
"Radix should be 2, 8, 10, or 16!");
|
"Radix should be 2, 8, 10, or 16!");
|
||||||
static const char *digits[] = {
|
static const char *digits[] = {
|
||||||
"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"
|
"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"
|
||||||
};
|
};
|
||||||
std::string result;
|
std::string result;
|
||||||
unsigned bits_used = getNumWords() * 64 - CountLeadingZeros();
|
unsigned bits_used = getActiveBits();
|
||||||
if (isSingleWord()) {
|
if (isSingleWord()) {
|
||||||
char buf[65];
|
char buf[65];
|
||||||
const char *format = (radix == 10 ? "%llu" :
|
const char *format = (radix == 10 ? "%llu" :
|
||||||
@ -845,11 +827,11 @@ std::string APInt::to_string(uint8_t radix) const {
|
|||||||
if (tmp == 0)
|
if (tmp == 0)
|
||||||
result = "0";
|
result = "0";
|
||||||
else while (tmp != 0) {
|
else while (tmp != 0) {
|
||||||
APInt APdigit = APIntOps::URem(tmp,divisor);
|
APInt APdigit = APIntOps::urem(tmp,divisor);
|
||||||
unsigned digit = APdigit.getValue();
|
unsigned digit = APdigit.getValue();
|
||||||
assert(digit < radix && "URem failed");
|
assert(digit < radix && "urem failed");
|
||||||
result.insert(0,digits[digit]);
|
result.insert(0,digits[digit]);
|
||||||
tmp = APIntOps::UDiv(tmp, divisor);
|
tmp = APIntOps::udiv(tmp, divisor);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -887,22 +869,26 @@ APInt APInt::getNullValue(unsigned numBits) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// HiBits - This function returns the high "numBits" bits of this APInt.
|
/// HiBits - This function returns the high "numBits" bits of this APInt.
|
||||||
APInt APInt::HiBits(unsigned numBits) const {
|
APInt APInt::getHiBits(unsigned numBits) const {
|
||||||
return APIntOps::LShr(*this, BitsNum - numBits);
|
return APIntOps::lshr(*this, BitWidth - numBits);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// LoBits - This function returns the low "numBits" bits of this APInt.
|
/// LoBits - This function returns the low "numBits" bits of this APInt.
|
||||||
APInt APInt::LoBits(unsigned numBits) const {
|
APInt APInt::getLoBits(unsigned numBits) const {
|
||||||
return APIntOps::LShr(APIntOps::Shl(*this, BitsNum - numBits),
|
return APIntOps::lshr(APIntOps::shl(*this, BitWidth - numBits),
|
||||||
BitsNum - numBits);
|
BitWidth - numBits);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CountLeadingZeros - This function is a APInt version corresponding to
|
bool APInt::isPowerOf2() const {
|
||||||
|
return (!!*this) && !(*this & (*this - APInt(BitWidth,1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// countLeadingZeros - This function is a APInt version corresponding to
|
||||||
/// llvm/include/llvm/Support/MathExtras.h's function
|
/// llvm/include/llvm/Support/MathExtras.h's function
|
||||||
/// CountLeadingZeros_{32, 64}. It performs platform optimal form of counting
|
/// countLeadingZeros_{32, 64}. It performs platform optimal form of counting
|
||||||
/// the number of zeros from the most significant bit to the first one bit.
|
/// the number of zeros from the most significant bit to the first one bit.
|
||||||
/// @returns numWord() * 64 if the value is zero.
|
/// @returns numWord() * 64 if the value is zero.
|
||||||
unsigned APInt::CountLeadingZeros() const {
|
unsigned APInt::countLeadingZeros() const {
|
||||||
if (isSingleWord())
|
if (isSingleWord())
|
||||||
return CountLeadingZeros_64(VAL);
|
return CountLeadingZeros_64(VAL);
|
||||||
unsigned Count = 0;
|
unsigned Count = 0;
|
||||||
@ -915,23 +901,23 @@ unsigned APInt::CountLeadingZeros() const {
|
|||||||
return Count;
|
return Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CountTrailingZero - This function is a APInt version corresponding to
|
/// countTrailingZeros - This function is a APInt version corresponding to
|
||||||
/// llvm/include/llvm/Support/MathExtras.h's function
|
/// llvm/include/llvm/Support/MathExtras.h's function
|
||||||
/// CountTrailingZeros_{32, 64}. It performs platform optimal form of counting
|
/// countTrailingZeros_{32, 64}. It performs platform optimal form of counting
|
||||||
/// the number of zeros from the least significant bit to the first one bit.
|
/// the number of zeros from the least significant bit to the first one bit.
|
||||||
/// @returns numWord() * 64 if the value is zero.
|
/// @returns numWord() * 64 if the value is zero.
|
||||||
unsigned APInt::CountTrailingZeros() const {
|
unsigned APInt::countTrailingZeros() const {
|
||||||
if (isSingleWord())
|
if (isSingleWord())
|
||||||
return CountTrailingZeros_64(~VAL & (VAL - 1));
|
return CountTrailingZeros_64(~VAL & (VAL - 1));
|
||||||
APInt Tmp = ~(*this) & ((*this) - 1);
|
APInt Tmp = ~(*this) & ((*this) - APInt(BitWidth,1));
|
||||||
return getNumWords() * 64 - Tmp.CountLeadingZeros();
|
return getNumWords() * APINT_BITS_PER_WORD - Tmp.countLeadingZeros();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CountPopulation - This function is a APInt version corresponding to
|
/// countPopulation - This function is a APInt version corresponding to
|
||||||
/// llvm/include/llvm/Support/MathExtras.h's function
|
/// llvm/include/llvm/Support/MathExtras.h's function
|
||||||
/// CountPopulation_{32, 64}. It counts the number of set bits in a value.
|
/// countPopulation_{32, 64}. It counts the number of set bits in a value.
|
||||||
/// @returns 0 if the value is zero.
|
/// @returns 0 if the value is zero.
|
||||||
unsigned APInt::CountPopulation() const {
|
unsigned APInt::countPopulation() const {
|
||||||
if (isSingleWord())
|
if (isSingleWord())
|
||||||
return CountPopulation_64(VAL);
|
return CountPopulation_64(VAL);
|
||||||
unsigned Count = 0;
|
unsigned Count = 0;
|
||||||
@ -941,31 +927,31 @@ unsigned APInt::CountPopulation() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// ByteSwap - This function returns a byte-swapped representation of the
|
/// byteSwap - This function returns a byte-swapped representation of the
|
||||||
/// this APInt.
|
/// this APInt.
|
||||||
APInt APInt::ByteSwap() const {
|
APInt APInt::byteSwap() const {
|
||||||
assert(BitsNum >= 16 && BitsNum % 16 == 0 && "Cannot byteswap!");
|
assert(BitWidth >= 16 && BitWidth % 16 == 0 && "Cannot byteswap!");
|
||||||
if (BitsNum == 16)
|
if (BitWidth == 16)
|
||||||
return APInt(ByteSwap_16(VAL), BitsNum);
|
return APInt(ByteSwap_16(VAL), BitWidth);
|
||||||
else if (BitsNum == 32)
|
else if (BitWidth == 32)
|
||||||
return APInt(ByteSwap_32(VAL), BitsNum);
|
return APInt(ByteSwap_32(VAL), BitWidth);
|
||||||
else if (BitsNum == 48) {
|
else if (BitWidth == 48) {
|
||||||
uint64_t Tmp1 = ((VAL >> 32) << 16) | (VAL & 0xFFFF);
|
uint64_t Tmp1 = ((VAL >> 32) << 16) | (VAL & 0xFFFF);
|
||||||
Tmp1 = ByteSwap_32(Tmp1);
|
Tmp1 = ByteSwap_32(Tmp1);
|
||||||
uint64_t Tmp2 = (VAL >> 16) & 0xFFFF;
|
uint64_t Tmp2 = (VAL >> 16) & 0xFFFF;
|
||||||
Tmp2 = ByteSwap_16(Tmp2);
|
Tmp2 = ByteSwap_16(Tmp2);
|
||||||
return
|
return
|
||||||
APInt((Tmp1 & 0xff) | ((Tmp1<<16) & 0xffff00000000ULL) | (Tmp2 << 16),
|
APInt((Tmp1 & 0xff) | ((Tmp1<<16) & 0xffff00000000ULL) | (Tmp2 << 16),
|
||||||
BitsNum);
|
BitWidth);
|
||||||
} else if (BitsNum == 64)
|
} else if (BitWidth == 64)
|
||||||
return APInt(ByteSwap_64(VAL), BitsNum);
|
return APInt(ByteSwap_64(VAL), BitWidth);
|
||||||
else {
|
else {
|
||||||
APInt Result(0, BitsNum);
|
APInt Result(0, BitWidth);
|
||||||
char *pByte = (char*)Result.pVal;
|
char *pByte = (char*)Result.pVal;
|
||||||
for (unsigned i = 0; i < BitsNum / 8 / 2; ++i) {
|
for (unsigned i = 0; i < BitWidth / 8 / 2; ++i) {
|
||||||
char Tmp = pByte[i];
|
char Tmp = pByte[i];
|
||||||
pByte[i] = pByte[BitsNum / 8 - 1 - i];
|
pByte[i] = pByte[BitWidth / 8 - 1 - i];
|
||||||
pByte[BitsNum / 8 - i - 1] = Tmp;
|
pByte[BitWidth / 8 - i - 1] = Tmp;
|
||||||
}
|
}
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
@ -978,7 +964,7 @@ APInt llvm::APIntOps::GreatestCommonDivisor(const APInt& API1,
|
|||||||
APInt A = API1, B = API2;
|
APInt A = API1, B = API2;
|
||||||
while (!!B) {
|
while (!!B) {
|
||||||
APInt T = B;
|
APInt T = B;
|
||||||
B = APIntOps::URem(A, B);
|
B = APIntOps::urem(A, B);
|
||||||
A = T;
|
A = T;
|
||||||
}
|
}
|
||||||
return A;
|
return A;
|
||||||
@ -986,7 +972,7 @@ APInt llvm::APIntOps::GreatestCommonDivisor(const APInt& API1,
|
|||||||
|
|
||||||
/// DoubleRoundToAPInt - This function convert a double value to
|
/// DoubleRoundToAPInt - This function convert a double value to
|
||||||
/// a APInt value.
|
/// a APInt value.
|
||||||
APInt llvm::APIntOps::DoubleRoundToAPInt(double Double) {
|
APInt llvm::APIntOps::RoundDoubleToAPInt(double Double) {
|
||||||
union {
|
union {
|
||||||
double D;
|
double D;
|
||||||
uint64_t I;
|
uint64_t I;
|
||||||
@ -995,13 +981,13 @@ APInt llvm::APIntOps::DoubleRoundToAPInt(double Double) {
|
|||||||
bool isNeg = T.I >> 63;
|
bool isNeg = T.I >> 63;
|
||||||
int64_t exp = ((T.I >> 52) & 0x7ff) - 1023;
|
int64_t exp = ((T.I >> 52) & 0x7ff) - 1023;
|
||||||
if (exp < 0)
|
if (exp < 0)
|
||||||
return APInt(0);
|
return APInt(64ull, 0u);
|
||||||
uint64_t mantissa = ((T.I << 12) >> 12) | (1ULL << 52);
|
uint64_t mantissa = ((T.I << 12) >> 12) | (1ULL << 52);
|
||||||
if (exp < 52)
|
if (exp < 52)
|
||||||
return isNeg ? -APInt(mantissa >> (52 - exp)) :
|
return isNeg ? -APInt(64u, mantissa >> (52 - exp)) :
|
||||||
APInt(mantissa >> (52 - exp));
|
APInt(64u, mantissa >> (52 - exp));
|
||||||
APInt Tmp(mantissa, exp + 1);
|
APInt Tmp(exp + 1, mantissa);
|
||||||
Tmp = Tmp.Shl(exp - 52);
|
Tmp = Tmp.shl(exp - 52);
|
||||||
return isNeg ? -Tmp : Tmp;
|
return isNeg ? -Tmp : Tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1012,12 +998,12 @@ APInt llvm::APIntOps::DoubleRoundToAPInt(double Double) {
|
|||||||
/// |-------------------------------------- |
|
/// |-------------------------------------- |
|
||||||
/// | 1[63] 11[62-52] 52[51-00] 1023 |
|
/// | 1[63] 11[62-52] 52[51-00] 1023 |
|
||||||
/// --------------------------------------
|
/// --------------------------------------
|
||||||
double APInt::RoundToDouble(bool isSigned) const {
|
double APInt::roundToDouble(bool isSigned) const {
|
||||||
bool isNeg = isSigned ? (*this)[BitsNum-1] : false;
|
bool isNeg = isSigned ? (*this)[BitWidth-1] : false;
|
||||||
APInt Tmp(isNeg ? -(*this) : (*this));
|
APInt Tmp(isNeg ? -(*this) : (*this));
|
||||||
if (Tmp.isSingleWord())
|
if (Tmp.isSingleWord())
|
||||||
return isSigned ? double(int64_t(Tmp.VAL)) : double(Tmp.VAL);
|
return isSigned ? double(int64_t(Tmp.VAL)) : double(Tmp.VAL);
|
||||||
unsigned n = Tmp.getNumWords() * 64 - Tmp.CountLeadingZeros();
|
unsigned n = Tmp.getActiveBits();
|
||||||
if (n <= 64)
|
if (n <= 64)
|
||||||
return isSigned ? double(int64_t(Tmp.pVal[0])) : double(Tmp.pVal[0]);
|
return isSigned ? double(int64_t(Tmp.pVal[0])) : double(Tmp.pVal[0]);
|
||||||
// Exponent when normalized to have decimal point directly after
|
// Exponent when normalized to have decimal point directly after
|
||||||
@ -1047,27 +1033,42 @@ double APInt::RoundToDouble(bool isSigned) const {
|
|||||||
return T.D;
|
return T.D;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Truncate to new width.
|
||||||
|
void APInt::trunc(unsigned width) {
|
||||||
|
assert(width < BitWidth && "Invalid APInt Truncate request");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign extend to a new width.
|
||||||
|
void APInt::sext(unsigned width) {
|
||||||
|
assert(width > BitWidth && "Invalid APInt SignExtend request");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zero extend to a new width.
|
||||||
|
void APInt::zext(unsigned width) {
|
||||||
|
assert(width > BitWidth && "Invalid APInt ZeroExtend request");
|
||||||
|
}
|
||||||
|
|
||||||
/// Arithmetic right-shift this APInt by shiftAmt.
|
/// Arithmetic right-shift this APInt by shiftAmt.
|
||||||
/// @brief Arithmetic right-shift function.
|
/// @brief Arithmetic right-shift function.
|
||||||
APInt APInt::AShr(unsigned shiftAmt) const {
|
APInt APInt::ashr(unsigned shiftAmt) const {
|
||||||
APInt API(*this);
|
APInt API(*this);
|
||||||
if (API.isSingleWord())
|
if (API.isSingleWord())
|
||||||
API.VAL = (((int64_t(API.VAL) << (64 - API.BitsNum)) >> (64 - API.BitsNum))
|
API.VAL = (((int64_t(API.VAL) << (64 - API.BitWidth)) >> (64 - API.BitWidth))
|
||||||
>> shiftAmt) & (~uint64_t(0UL) >> (64 - API.BitsNum));
|
>> shiftAmt) & (~uint64_t(0UL) >> (64 - API.BitWidth));
|
||||||
else {
|
else {
|
||||||
if (shiftAmt >= API.BitsNum) {
|
if (shiftAmt >= API.BitWidth) {
|
||||||
memset(API.pVal, API[API.BitsNum-1] ? 1 : 0, (API.getNumWords()-1) * 8);
|
memset(API.pVal, API[API.BitWidth-1] ? 1 : 0, (API.getNumWords()-1) * 8);
|
||||||
API.pVal[API.getNumWords() - 1] = ~uint64_t(0UL) >>
|
API.pVal[API.getNumWords() - 1] = ~uint64_t(0UL) >>
|
||||||
(64 - API.BitsNum % 64);
|
(64 - API.BitWidth % 64);
|
||||||
} else {
|
} else {
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
for (; i < API.BitsNum - shiftAmt; ++i)
|
for (; i < API.BitWidth - shiftAmt; ++i)
|
||||||
if (API[i+shiftAmt])
|
if (API[i+shiftAmt])
|
||||||
API.set(i);
|
API.set(i);
|
||||||
else
|
else
|
||||||
API.clear(i);
|
API.clear(i);
|
||||||
for (; i < API.BitsNum; ++i)
|
for (; i < API.BitWidth; ++i)
|
||||||
if (API[API.BitsNum-1])
|
if (API[API.BitWidth-1])
|
||||||
API.set(i);
|
API.set(i);
|
||||||
else API.clear(i);
|
else API.clear(i);
|
||||||
}
|
}
|
||||||
@ -1077,18 +1078,18 @@ APInt APInt::AShr(unsigned shiftAmt) const {
|
|||||||
|
|
||||||
/// Logical right-shift this APInt by shiftAmt.
|
/// Logical right-shift this APInt by shiftAmt.
|
||||||
/// @brief Logical right-shift function.
|
/// @brief Logical right-shift function.
|
||||||
APInt APInt::LShr(unsigned shiftAmt) const {
|
APInt APInt::lshr(unsigned shiftAmt) const {
|
||||||
APInt API(*this);
|
APInt API(*this);
|
||||||
if (API.isSingleWord())
|
if (API.isSingleWord())
|
||||||
API.VAL >>= shiftAmt;
|
API.VAL >>= shiftAmt;
|
||||||
else {
|
else {
|
||||||
if (shiftAmt >= API.BitsNum)
|
if (shiftAmt >= API.BitWidth)
|
||||||
memset(API.pVal, 0, API.getNumWords() * 8);
|
memset(API.pVal, 0, API.getNumWords() * 8);
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
for (i = 0; i < API.BitsNum - shiftAmt; ++i)
|
for (i = 0; i < API.BitWidth - shiftAmt; ++i)
|
||||||
if (API[i+shiftAmt]) API.set(i);
|
if (API[i+shiftAmt]) API.set(i);
|
||||||
else API.clear(i);
|
else API.clear(i);
|
||||||
for (; i < API.BitsNum; ++i)
|
for (; i < API.BitWidth; ++i)
|
||||||
API.clear(i);
|
API.clear(i);
|
||||||
}
|
}
|
||||||
return API;
|
return API;
|
||||||
@ -1096,11 +1097,11 @@ APInt APInt::LShr(unsigned shiftAmt) const {
|
|||||||
|
|
||||||
/// Left-shift this APInt by shiftAmt.
|
/// Left-shift this APInt by shiftAmt.
|
||||||
/// @brief Left-shift function.
|
/// @brief Left-shift function.
|
||||||
APInt APInt::Shl(unsigned shiftAmt) const {
|
APInt APInt::shl(unsigned shiftAmt) const {
|
||||||
APInt API(*this);
|
APInt API(*this);
|
||||||
if (API.isSingleWord())
|
if (API.isSingleWord())
|
||||||
API.VAL <<= shiftAmt;
|
API.VAL <<= shiftAmt;
|
||||||
else if (shiftAmt >= API.BitsNum)
|
else if (shiftAmt >= API.BitWidth)
|
||||||
memset(API.pVal, 0, API.getNumWords() * 8);
|
memset(API.pVal, 0, API.getNumWords() * 8);
|
||||||
else {
|
else {
|
||||||
if (unsigned offset = shiftAmt / 64) {
|
if (unsigned offset = shiftAmt / 64) {
|
||||||
@ -1115,28 +1116,26 @@ APInt APInt::Shl(unsigned shiftAmt) const {
|
|||||||
(API.pVal[i-1] >> (64-shiftAmt));
|
(API.pVal[i-1] >> (64-shiftAmt));
|
||||||
API.pVal[i] <<= shiftAmt;
|
API.pVal[i] <<= shiftAmt;
|
||||||
}
|
}
|
||||||
API.TruncToBits();
|
API.clearUnusedBits();
|
||||||
return API;
|
return API;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unsigned divide this APInt by APInt RHS.
|
/// Unsigned divide this APInt by APInt RHS.
|
||||||
/// @brief Unsigned division function for APInt.
|
/// @brief Unsigned division function for APInt.
|
||||||
APInt APInt::UDiv(const APInt& RHS) const {
|
APInt APInt::udiv(const APInt& RHS) const {
|
||||||
APInt API(*this);
|
APInt API(*this);
|
||||||
unsigned first = RHS.getNumWords() * APInt::APINT_BITS_PER_WORD -
|
unsigned first = RHS.getActiveBits();
|
||||||
RHS.CountLeadingZeros();
|
|
||||||
unsigned ylen = !first ? 0 : APInt::whichWord(first - 1) + 1;
|
unsigned ylen = !first ? 0 : APInt::whichWord(first - 1) + 1;
|
||||||
assert(ylen && "Divided by zero???");
|
assert(ylen && "Divided by zero???");
|
||||||
if (API.isSingleWord()) {
|
if (API.isSingleWord()) {
|
||||||
API.VAL = RHS.isSingleWord() ? (API.VAL / RHS.VAL) :
|
API.VAL = RHS.isSingleWord() ? (API.VAL / RHS.VAL) :
|
||||||
(ylen > 1 ? 0 : API.VAL / RHS.pVal[0]);
|
(ylen > 1 ? 0 : API.VAL / RHS.pVal[0]);
|
||||||
} else {
|
} else {
|
||||||
unsigned first2 = API.getNumWords() * APInt::APINT_BITS_PER_WORD -
|
unsigned first2 = API.getActiveBits();
|
||||||
API.CountLeadingZeros();
|
|
||||||
unsigned xlen = !first2 ? 0 : APInt::whichWord(first2 - 1) + 1;
|
unsigned xlen = !first2 ? 0 : APInt::whichWord(first2 - 1) + 1;
|
||||||
if (!xlen)
|
if (!xlen)
|
||||||
return API;
|
return API;
|
||||||
else if (xlen < ylen || API < RHS)
|
else if (xlen < ylen || API.ult(RHS))
|
||||||
memset(API.pVal, 0, API.getNumWords() * 8);
|
memset(API.pVal, 0, API.getNumWords() * 8);
|
||||||
else if (API == RHS) {
|
else if (API == RHS) {
|
||||||
memset(API.pVal, 0, API.getNumWords() * 8);
|
memset(API.pVal, 0, API.getNumWords() * 8);
|
||||||
@ -1146,8 +1145,8 @@ APInt APInt::UDiv(const APInt& RHS) const {
|
|||||||
else {
|
else {
|
||||||
APInt X(0, (xlen+1)*64), Y(0, ylen*64);
|
APInt X(0, (xlen+1)*64), Y(0, ylen*64);
|
||||||
if (unsigned nshift = 63 - (first - 1) % 64) {
|
if (unsigned nshift = 63 - (first - 1) % 64) {
|
||||||
Y = APIntOps::Shl(RHS, nshift);
|
Y = APIntOps::shl(RHS, nshift);
|
||||||
X = APIntOps::Shl(API, nshift);
|
X = APIntOps::shl(API, nshift);
|
||||||
++xlen;
|
++xlen;
|
||||||
}
|
}
|
||||||
div((unsigned*)X.pVal, xlen*2-1,
|
div((unsigned*)X.pVal, xlen*2-1,
|
||||||
@ -1161,20 +1160,18 @@ APInt APInt::UDiv(const APInt& RHS) const {
|
|||||||
|
|
||||||
/// Unsigned remainder operation on APInt.
|
/// Unsigned remainder operation on APInt.
|
||||||
/// @brief Function for unsigned remainder operation.
|
/// @brief Function for unsigned remainder operation.
|
||||||
APInt APInt::URem(const APInt& RHS) const {
|
APInt APInt::urem(const APInt& RHS) const {
|
||||||
APInt API(*this);
|
APInt API(*this);
|
||||||
unsigned first = RHS.getNumWords() * APInt::APINT_BITS_PER_WORD -
|
unsigned first = RHS.getActiveBits();
|
||||||
RHS.CountLeadingZeros();
|
|
||||||
unsigned ylen = !first ? 0 : APInt::whichWord(first - 1) + 1;
|
unsigned ylen = !first ? 0 : APInt::whichWord(first - 1) + 1;
|
||||||
assert(ylen && "Performing remainder operation by zero ???");
|
assert(ylen && "Performing remainder operation by zero ???");
|
||||||
if (API.isSingleWord()) {
|
if (API.isSingleWord()) {
|
||||||
API.VAL = RHS.isSingleWord() ? (API.VAL % RHS.VAL) :
|
API.VAL = RHS.isSingleWord() ? (API.VAL % RHS.VAL) :
|
||||||
(ylen > 1 ? API.VAL : API.VAL % RHS.pVal[0]);
|
(ylen > 1 ? API.VAL : API.VAL % RHS.pVal[0]);
|
||||||
} else {
|
} else {
|
||||||
unsigned first2 = API.getNumWords() * APInt::APINT_BITS_PER_WORD -
|
unsigned first2 = API.getActiveBits();
|
||||||
API.CountLeadingZeros();
|
|
||||||
unsigned xlen = !first2 ? 0 : API.whichWord(first2 - 1) + 1;
|
unsigned xlen = !first2 ? 0 : API.whichWord(first2 - 1) + 1;
|
||||||
if (!xlen || xlen < ylen || API < RHS)
|
if (!xlen || xlen < ylen || API.ult(RHS))
|
||||||
return API;
|
return API;
|
||||||
else if (API == RHS)
|
else if (API == RHS)
|
||||||
memset(API.pVal, 0, API.getNumWords() * 8);
|
memset(API.pVal, 0, API.getNumWords() * 8);
|
||||||
@ -1184,8 +1181,8 @@ APInt APInt::URem(const APInt& RHS) const {
|
|||||||
APInt X(0, (xlen+1)*64), Y(0, ylen*64);
|
APInt X(0, (xlen+1)*64), Y(0, ylen*64);
|
||||||
unsigned nshift = 63 - (first - 1) % 64;
|
unsigned nshift = 63 - (first - 1) % 64;
|
||||||
if (nshift) {
|
if (nshift) {
|
||||||
APIntOps::Shl(Y, nshift);
|
APIntOps::shl(Y, nshift);
|
||||||
APIntOps::Shl(X, nshift);
|
APIntOps::shl(X, nshift);
|
||||||
}
|
}
|
||||||
div((unsigned*)X.pVal, xlen*2-1,
|
div((unsigned*)X.pVal, xlen*2-1,
|
||||||
(unsigned*)(Y.isSingleWord() ? &Y.VAL : Y.pVal), ylen*2);
|
(unsigned*)(Y.isSingleWord() ? &Y.VAL : Y.pVal), ylen*2);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user