mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
As Chris and Reid suggested, remove "isSigned" field from APInt, instead,
add some signed/unsigned arithmetic operation functions into APInt.h to handle the signed/unsigned issue. These functions will be defined inside a namespace "APIntOps" which is inside llvm namespace. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@34053 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
a3cf7e7a95
commit
0b706b18bd
@ -21,6 +21,21 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// Forward declaration.
|
||||
class APInt;
|
||||
namespace APIntOps {
|
||||
bool isIntN(unsigned N, const APInt& APIVal);
|
||||
APInt ByteSwap(const APInt& APIVal);
|
||||
APInt LogBase2(const APInt& APIVal);
|
||||
APInt ashr(const APInt& LHS, unsigned shiftAmt);
|
||||
APInt lshr(const APInt& LHS, unsigned shiftAmt);
|
||||
APInt shl(const APInt& LHS, unsigned shiftAmt);
|
||||
APInt sdiv(const APInt& LHS, const APInt& RHS);
|
||||
APInt udiv(const APInt& LHS, const APInt& RHS);
|
||||
APInt srem(const APInt& LHS, const APInt& RHS);
|
||||
APInt urem(const APInt& LHS, const APInt& RHS);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// APInt Class
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -40,14 +55,18 @@ namespace llvm {
|
||||
class APInt {
|
||||
/// Friend Functions of APInt declared here. For detailed comments,
|
||||
/// see bottom of this file.
|
||||
friend bool isIntN(unsigned N, const APInt& APIVal);
|
||||
friend APInt ByteSwap(const APInt& APIVal);
|
||||
friend APInt LogBase2(const APInt& APIVal);
|
||||
friend double APIntToDouble(const APInt& APIVal);
|
||||
friend float APIntToFloat(const APInt& APIVal);
|
||||
friend bool APIntOps::isIntN(unsigned N, const APInt& APIVal);
|
||||
friend APInt APIntOps::ByteSwap(const APInt& APIVal);
|
||||
friend APInt APIntOps::LogBase2(const APInt& APIVal);
|
||||
friend APInt APIntOps::ashr(const APInt& LHS, unsigned shiftAmt);
|
||||
friend APInt APIntOps::lshr(const APInt& LHS, unsigned shiftAmt);
|
||||
friend APInt APIntOps::shl(const APInt& LHS, unsigned shiftAmt);
|
||||
friend APInt APIntOps::sdiv(const APInt& LHS, const APInt& RHS);
|
||||
friend APInt APIntOps::udiv(const APInt& LHS, const APInt& RHS);
|
||||
friend APInt APIntOps::srem(const APInt& LHS, const APInt& RHS);
|
||||
friend APInt APIntOps::urem(const APInt& LHS, const APInt& RHS);
|
||||
|
||||
unsigned BitsNum; ///< The number of bits.
|
||||
bool isSigned; ///< The sign flag for this APInt.
|
||||
|
||||
/// This union is used to store the integer value. When the
|
||||
/// integer bit-width <= 64, it uses VAL;
|
||||
@ -114,20 +133,19 @@ class APInt {
|
||||
|
||||
public:
|
||||
/// @brief Create a new APInt of numBits bit-width, and initialized as val.
|
||||
APInt(uint64_t val = 0, unsigned numBits = APINT_BITS_PER_WORD,
|
||||
bool sign = false);
|
||||
APInt(uint64_t val = 0, unsigned numBits = APINT_BITS_PER_WORD);
|
||||
|
||||
/// @brief Create a new APInt of numBits bit-width, and initialized as
|
||||
/// bigVal[].
|
||||
APInt(unsigned numBits, uint64_t bigVal[], bool sign = false);
|
||||
APInt(unsigned numBits, uint64_t bigVal[]);
|
||||
|
||||
/// @brief Create a new APInt by translating the string represented
|
||||
/// integer value.
|
||||
APInt(const std::string& Val, uint8_t radix = 10, bool sign = false);
|
||||
APInt(const std::string& Val, uint8_t radix = 10);
|
||||
|
||||
/// @brief Create a new APInt by translating the char array represented
|
||||
/// integer value.
|
||||
APInt(const char StrStart[], unsigned slen, uint8_t radix, bool sign = false);
|
||||
APInt(const char StrStart[], unsigned slen, uint8_t radix);
|
||||
|
||||
/// @brief Copy Constructor.
|
||||
APInt(const APInt& API);
|
||||
@ -179,14 +197,6 @@ public:
|
||||
/// @brief Bitwise XOR assignment operator.
|
||||
APInt& operator^=(const APInt& RHS);
|
||||
|
||||
/// Left-shift the APInt by shiftAmt and assigns the result to this APInt.
|
||||
/// @brief Left-shift assignment operator.
|
||||
APInt& operator<<=(unsigned shiftAmt);
|
||||
|
||||
/// Right-shift the APInt by shiftAmt and assigns the result to this APInt.
|
||||
/// @brief Right-shift assignment operator.
|
||||
APInt& operator>>=(unsigned shiftAmt);
|
||||
|
||||
/// Performs a bitwise complement operation on this APInt.
|
||||
/// @brief Bitwise complement operator.
|
||||
APInt operator~() const;
|
||||
@ -196,11 +206,6 @@ public:
|
||||
/// @brief Multiplication assignment operator.
|
||||
APInt& operator*=(const APInt& RHS);
|
||||
|
||||
/// Divides this APInt by the given APInt &RHS and
|
||||
/// assigns the result to this APInt.
|
||||
/// @brief Division assignment operator.
|
||||
APInt& operator/=(const APInt& RHS);
|
||||
|
||||
/// Adds this APInt by the given APInt& RHS and
|
||||
/// assigns the result to this APInt.
|
||||
/// @brief Addition assignment operator.
|
||||
@ -211,11 +216,6 @@ public:
|
||||
/// @brief Subtraction assignment operator.
|
||||
APInt& operator-=(const APInt& RHS);
|
||||
|
||||
/// Yields the remainder from the division of this APInt by
|
||||
/// the given APInt& RHS and assigns the remainder to this APInt.
|
||||
/// @brief Remainder assignment operator.
|
||||
APInt& operator%=(const APInt& RHS);
|
||||
|
||||
/// Performs bitwise AND operation on this APInt and
|
||||
/// the given APInt& RHS.
|
||||
/// @brief Bitwise AND operator.
|
||||
@ -245,15 +245,6 @@ public:
|
||||
/// @brief Multiplication operator.
|
||||
APInt operator*(const APInt& RHS) const;
|
||||
|
||||
/// Divides this APInt by the given APInt& RHS.
|
||||
/// @brief Division operator.
|
||||
APInt operator/(const APInt& RHS) const;
|
||||
|
||||
/// Yields the remainder from the division of
|
||||
/// this APInt and the given APInt& RHS.
|
||||
/// @brief Remainder operator.
|
||||
APInt operator%(const APInt& RHS) const;
|
||||
|
||||
/// Adds this APInt by the given APInt& RHS.
|
||||
/// @brief Addition operator.
|
||||
APInt operator+(const APInt& RHS) const;
|
||||
@ -262,13 +253,10 @@ public:
|
||||
/// @brief Subtraction operator.
|
||||
APInt operator-(const APInt& RHS) const;
|
||||
|
||||
/// Left-shift the APInt by shiftAmt.
|
||||
/// @brief Left-shift operator.
|
||||
APInt operator<<(unsigned shiftAmt) const;
|
||||
|
||||
/// Right-shift the APInt by shiftAmt.
|
||||
/// @brief Right-shift operator.
|
||||
APInt operator>>(unsigned shiftAmt) const;
|
||||
///
|
||||
inline APInt operator-() const {
|
||||
return APInt(0, BitsNum) - (*this);
|
||||
}
|
||||
|
||||
/// @brief Array-indexing support.
|
||||
bool operator[](unsigned bitPosition) const;
|
||||
@ -321,9 +309,7 @@ public:
|
||||
/// word, just returns VAL, otherwise pVal[0].
|
||||
inline uint64_t getValue() {
|
||||
if (isSingleWord())
|
||||
return isSigned ? ((int64_t(VAL) << (APINT_BITS_PER_WORD - BitsNum)) >>
|
||||
(APINT_BITS_PER_WORD - BitsNum)) :
|
||||
VAL;
|
||||
return VAL;
|
||||
assert(0 && "This APInt's bitwidth > 64");
|
||||
}
|
||||
|
||||
@ -403,6 +389,8 @@ public:
|
||||
|
||||
};
|
||||
|
||||
namespace APIntOps {
|
||||
|
||||
/// @brief Check if the specified APInt has a N-bits integer value.
|
||||
inline bool isIntN(unsigned N, const APInt& APIVal) {
|
||||
if (APIVal.isSingleWord()) {
|
||||
@ -439,6 +427,62 @@ inline APInt LogBase2(const APInt& APIVal) {
|
||||
/// using Euclid's algorithm.
|
||||
APInt GreatestCommonDivisor(const APInt& API1, const APInt& API2);
|
||||
|
||||
/// Arithmetic right-shift the APInt by shiftAmt.
|
||||
/// @brief Arithmetic right-shift function.
|
||||
APInt ashr(const APInt& LHS, unsigned shiftAmt);
|
||||
|
||||
/// Logical right-shift the APInt by shiftAmt.
|
||||
/// @brief Logical right-shift function.
|
||||
APInt lshr(const APInt& LHS, unsigned shiftAmt);
|
||||
|
||||
/// Left-shift the APInt by shiftAmt.
|
||||
/// @brief Left-shift function.
|
||||
APInt shl(const APInt& LHS, unsigned shiftAmt);
|
||||
|
||||
/// Signed divide APInt LHS by APInt RHS.
|
||||
/// @brief Signed division function for APInt.
|
||||
inline APInt sdiv(const APInt& LHS, const APInt& RHS) {
|
||||
bool isSignedLHS = LHS[LHS.BitsNum - 1], isSignedRHS = RHS[RHS.BitsNum - 1];
|
||||
APInt API = udiv(isSignedLHS ? -LHS : LHS, isSignedRHS ? -RHS : RHS);
|
||||
return isSignedLHS != isSignedRHS ? -API : API;;
|
||||
}
|
||||
|
||||
/// Unsigned divide APInt LHS by APInt RHS.
|
||||
/// @brief Unsigned division function for APInt.
|
||||
APInt udiv(const APInt& LHS, const APInt& RHS);
|
||||
|
||||
/// Signed remainder operation on APInt.
|
||||
/// @brief Function for signed remainder operation.
|
||||
inline APInt srem(const APInt& LHS, const APInt& RHS) {
|
||||
bool isSignedLHS = LHS[LHS.BitsNum - 1], isSignedRHS = RHS[RHS.BitsNum - 1];
|
||||
APInt API = urem(isSignedLHS ? -LHS : LHS, isSignedRHS ? -RHS : RHS);
|
||||
return isSignedLHS ? -API : API;
|
||||
}
|
||||
|
||||
/// Unsigned remainder operation on APInt.
|
||||
/// @brief Function for unsigned remainder operation.
|
||||
APInt urem(const APInt& LHS, const APInt& RHS);
|
||||
|
||||
/// Performs multiplication on APInt values.
|
||||
/// @brief Function for multiplication operation.
|
||||
inline APInt mul(const APInt& LHS, const APInt& RHS) {
|
||||
return LHS * RHS;
|
||||
}
|
||||
|
||||
/// Performs addition on APInt values.
|
||||
/// @brief Function for addition operation.
|
||||
inline APInt add(const APInt& LHS, const APInt& RHS) {
|
||||
return LHS + RHS;
|
||||
}
|
||||
|
||||
/// Performs subtraction on APInt values.
|
||||
/// @brief Function for subtraction operation.
|
||||
inline APInt sub(const APInt& LHS, const APInt& RHS) {
|
||||
return LHS - RHS;
|
||||
}
|
||||
|
||||
} // End of APIntOps namespace
|
||||
|
||||
} // End of llvm namespace
|
||||
|
||||
#endif
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
#include "llvm/ADT/APInt.h"
|
||||
|
||||
#if 0
|
||||
#if 1
|
||||
#include "llvm/DerivedTypes.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include <cstring>
|
||||
@ -262,8 +262,8 @@ static uint64_t lshift(uint64_t dest[], unsigned d_offset,
|
||||
return retVal;
|
||||
}
|
||||
|
||||
APInt::APInt(uint64_t val, unsigned numBits, bool sign)
|
||||
: BitsNum(numBits), isSigned(sign) {
|
||||
APInt::APInt(uint64_t val, unsigned numBits)
|
||||
: BitsNum(numBits) {
|
||||
assert(BitsNum >= IntegerType::MIN_INT_BITS && "bitwidth too small");
|
||||
assert(BitsNum <= IntegerType::MAX_INT_BITS && "bitwidth too large");
|
||||
if (isSingleWord())
|
||||
@ -277,8 +277,8 @@ APInt::APInt(uint64_t val, unsigned numBits, bool sign)
|
||||
}
|
||||
}
|
||||
|
||||
APInt::APInt(unsigned numBits, uint64_t bigVal[], bool sign)
|
||||
: BitsNum(numBits), isSigned(sign) {
|
||||
APInt::APInt(unsigned numBits, uint64_t bigVal[])
|
||||
: BitsNum(numBits) {
|
||||
assert(BitsNum >= IntegerType::MIN_INT_BITS && "bitwidth too small");
|
||||
assert(BitsNum <= IntegerType::MAX_INT_BITS && "bitwidth too large");
|
||||
assert(bigVal && "Null pointer detected!");
|
||||
@ -301,15 +301,13 @@ APInt::APInt(unsigned numBits, uint64_t bigVal[], bool sign)
|
||||
|
||||
/// @brief Create a new APInt by translating the char array represented
|
||||
/// integer value.
|
||||
APInt::APInt(const char StrStart[], unsigned slen, uint8_t radix, bool sign)
|
||||
: isSigned(sign) {
|
||||
APInt::APInt(const char StrStart[], unsigned slen, uint8_t radix) {
|
||||
StrToAPInt(StrStart, slen, radix);
|
||||
}
|
||||
|
||||
/// @brief Create a new APInt by translating the string represented
|
||||
/// integer value.
|
||||
APInt::APInt(const std::string& Val, uint8_t radix, bool sign)
|
||||
: isSigned(sign) {
|
||||
APInt::APInt(const std::string& Val, uint8_t radix) {
|
||||
assert(!Val.empty() && "String empty?");
|
||||
StrToAPInt(Val.c_str(), Val.size(), radix);
|
||||
}
|
||||
@ -386,7 +384,7 @@ void APInt::StrToAPInt(const char *StrStart, unsigned slen, uint8_t radix) {
|
||||
}
|
||||
|
||||
APInt::APInt(const APInt& APIVal)
|
||||
: BitsNum(APIVal.BitsNum), isSigned(APIVal.isSigned) {
|
||||
: BitsNum(APIVal.BitsNum) {
|
||||
if (isSingleWord()) VAL = APIVal.VAL;
|
||||
else {
|
||||
// Memory allocation and check if successful.
|
||||
@ -421,6 +419,7 @@ APInt& APInt::operator=(uint64_t RHS) {
|
||||
pVal[0] = RHS;
|
||||
memset(pVal, 0, (getNumWords() - 1) * 8);
|
||||
}
|
||||
TruncToBits();
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -514,101 +513,6 @@ APInt& APInt::operator*=(const APInt& RHS) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// @brief Division assignment operator. Divides this APInt by the given APInt
|
||||
/// &RHS and assigns the result to this APInt.
|
||||
APInt& APInt::operator/=(const APInt& RHS) {
|
||||
unsigned first = RHS.getNumWords() * APINT_BITS_PER_WORD -
|
||||
RHS.CountLeadingZeros();
|
||||
unsigned ylen = !first ? 0 : whichWord(first - 1) + 1;
|
||||
assert(ylen && "Divided by zero???");
|
||||
if (isSingleWord()) {
|
||||
if (isSigned && RHS.isSigned)
|
||||
VAL = RHS.isSingleWord() ? (int64_t(VAL) / int64_t(RHS.VAL)) :
|
||||
(ylen > 1 ? 0 : int64_t(VAL) / int64_t(RHS.pVal[0]));
|
||||
else
|
||||
VAL = RHS.isSingleWord() ? (VAL / RHS.VAL) :
|
||||
(ylen > 1 ? 0 : VAL / RHS.pVal[0]);
|
||||
} else {
|
||||
unsigned first2 = getNumWords() * APINT_BITS_PER_WORD - CountLeadingZeros();
|
||||
unsigned xlen = !first2 ? 0 : whichWord(first2 - 1) + 1;
|
||||
if (!xlen)
|
||||
return *this;
|
||||
else if ((*this) < RHS)
|
||||
memset(pVal, 0, getNumWords() * 8);
|
||||
else if ((*this) == RHS) {
|
||||
memset(pVal, 0, getNumWords() * 8);
|
||||
pVal[0] = 1;
|
||||
} else if (xlen == 1)
|
||||
pVal[0] /= RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0];
|
||||
else {
|
||||
uint64_t *xwords = new uint64_t[xlen+1], *ywords = new uint64_t[ylen];
|
||||
assert(xwords && ywords && "Memory Allocation Failed!");
|
||||
memcpy(xwords, pVal, xlen * 8);
|
||||
xwords[xlen] = 0;
|
||||
memcpy(ywords, RHS.isSingleWord() ? &RHS.VAL : RHS.pVal, ylen * 8);
|
||||
if (unsigned nshift = 63 - (first - 1) % 64) {
|
||||
lshift(ywords, 0, ywords, ylen, nshift);
|
||||
unsigned xlentmp = xlen;
|
||||
xwords[xlen++] = lshift(xwords, 0, xwords, xlentmp, nshift);
|
||||
}
|
||||
div((unsigned*)xwords, xlen*2-1, (unsigned*)ywords, ylen*2);
|
||||
memset(pVal, 0, getNumWords() * 8);
|
||||
memcpy(pVal, xwords + ylen, (xlen - ylen) * 8);
|
||||
delete[] xwords;
|
||||
delete[] ywords;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// @brief Remainder assignment operator. Yields the remainder from the
|
||||
/// division of this APInt by the given APInt& RHS and assigns the remainder
|
||||
/// to this APInt.
|
||||
APInt& APInt::operator%=(const APInt& RHS) {
|
||||
unsigned first = RHS.getNumWords() * APINT_BITS_PER_WORD -
|
||||
RHS.CountLeadingZeros();
|
||||
unsigned ylen = !first ? 0 : whichWord(first - 1) + 1;
|
||||
assert(ylen && "Performing remainder operation by zero ???");
|
||||
if (isSingleWord()) {
|
||||
if (isSigned && RHS.isSigned)
|
||||
VAL = RHS.isSingleWord() ? (int64_t(VAL) % int64_t(RHS.VAL)) :
|
||||
(ylen > 1 ? VAL : int64_t(VAL) % int64_t(RHS.pVal[0]));
|
||||
else
|
||||
VAL = RHS.isSingleWord() ? (VAL % RHS.VAL) :
|
||||
(ylen > 1 ? VAL : VAL % RHS.pVal[0]);
|
||||
} else {
|
||||
unsigned first2 = getNumWords() * APINT_BITS_PER_WORD - CountLeadingZeros();
|
||||
unsigned xlen = !first2 ? 0 : whichWord(first2 - 1) + 1;
|
||||
if (!xlen || (*this) < RHS)
|
||||
return *this;
|
||||
else if ((*this) == RHS)
|
||||
memset(pVal, 0, getNumWords() * 8);
|
||||
else if (xlen == 1)
|
||||
pVal[0] %= RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0];
|
||||
else {
|
||||
uint64_t *xwords = new uint64_t[xlen+1], *ywords = new uint64_t[ylen];
|
||||
assert(xwords && ywords && "Memory Allocation Failed!");
|
||||
memcpy(xwords, pVal, xlen * 8);
|
||||
xwords[xlen] = 0;
|
||||
memcpy(ywords, RHS.isSingleWord() ? &RHS.VAL : RHS.pVal, ylen * 8);
|
||||
unsigned nshift = 63 - (first - 1) % 64;
|
||||
if (nshift) {
|
||||
lshift(ywords, 0, ywords, ylen, nshift);
|
||||
unsigned xlentmp = xlen;
|
||||
xwords[xlen++] = lshift(xwords, 0, xwords, xlentmp, nshift);
|
||||
}
|
||||
div((unsigned*)xwords, xlen*2-1, (unsigned*)ywords, ylen*2);
|
||||
memset(pVal, 0, getNumWords() * 8);
|
||||
for (unsigned i = 0; i < ylen-1; ++i)
|
||||
pVal[i] = (xwords[i] >> nshift) | (xwords[i+1] << (64 - nshift));
|
||||
pVal[ylen-1] = xwords[ylen-1] >> nshift;
|
||||
delete[] xwords;
|
||||
delete[] ywords;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// @brief Bitwise AND assignment operator. Performs bitwise AND operation on
|
||||
/// this APInt and the given APInt& RHS, assigns the result to this APInt.
|
||||
APInt& APInt::operator&=(const APInt& RHS) {
|
||||
@ -753,19 +657,6 @@ APInt APInt::operator*(const APInt& RHS) const {
|
||||
return API;
|
||||
}
|
||||
|
||||
/// @brief Division operator. Divides this APInt by the given APInt& RHS.
|
||||
APInt APInt::operator/(const APInt& RHS) const {
|
||||
APInt API(*this);
|
||||
return API /= RHS;
|
||||
}
|
||||
|
||||
/// @brief Remainder operator. Yields the remainder from the division of this
|
||||
/// APInt and the given APInt& RHS.
|
||||
APInt APInt::operator%(const APInt& RHS) const {
|
||||
APInt API(*this);
|
||||
return API %= RHS;
|
||||
}
|
||||
|
||||
/// @brief Addition operator. Adds this APInt by the given APInt& RHS.
|
||||
APInt APInt::operator+(const APInt& RHS) const {
|
||||
APInt API(*this);
|
||||
@ -778,7 +669,6 @@ APInt APInt::operator+(const APInt& RHS) const {
|
||||
APInt APInt::operator-(const APInt& RHS) const {
|
||||
APInt API(*this);
|
||||
API -= RHS;
|
||||
API.TruncToBits();
|
||||
return API;
|
||||
}
|
||||
|
||||
@ -822,12 +712,6 @@ bool APInt::operator==(uint64_t Val) const {
|
||||
/// @brief Less-than operator. Compare this APInt with the given APInt& RHS
|
||||
/// for the validity of the less-than relationship.
|
||||
bool APInt::operator <(const APInt& RHS) const {
|
||||
if (isSigned && RHS.isSigned) {
|
||||
if ((*this)[BitsNum-1] > RHS[RHS.BitsNum-1])
|
||||
return false;
|
||||
else if ((*this)[BitsNum-1] < RHS[RHS.BitsNum-1])
|
||||
return true;
|
||||
}
|
||||
unsigned n1 = getNumWords() * 64 - CountLeadingZeros(),
|
||||
n2 = RHS.getNumWords() * 64 - RHS.CountLeadingZeros();
|
||||
if (n1 < n2) return true;
|
||||
@ -896,54 +780,6 @@ APInt& APInt::clear() {
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// @brief Left-shift assignment operator. Left-shift the APInt by shiftAmt
|
||||
/// and assigns the result to this APInt.
|
||||
APInt& APInt::operator<<=(unsigned shiftAmt) {
|
||||
if (shiftAmt >= BitsNum) {
|
||||
if (isSingleWord()) VAL = 0;
|
||||
else
|
||||
memset(pVal, 0, getNumWords() * 8);
|
||||
} else {
|
||||
for (unsigned i = 0; i < shiftAmt; ++i) clear(i);
|
||||
for (unsigned i = shiftAmt; i < BitsNum; ++i) {
|
||||
if ((*this)[i-shiftAmt]) set(i);
|
||||
else clear(i);
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// @brief Left-shift operator. Left-shift the APInt by shiftAmt.
|
||||
APInt APInt::operator<<(unsigned shiftAmt) const {
|
||||
APInt API(*this);
|
||||
API <<= shiftAmt;
|
||||
return API;
|
||||
}
|
||||
|
||||
/// @brief Right-shift assignment operator. Right-shift the APInt by shiftAmt
|
||||
/// and assigns the result to this APInt.
|
||||
APInt& APInt::operator>>=(unsigned shiftAmt) {
|
||||
bool isAShr = isSigned && (*this)[BitsNum-1];
|
||||
if (isSingleWord())
|
||||
VAL = isAShr ? (int64_t(VAL) >> shiftAmt) : (VAL >> shiftAmt);
|
||||
else {
|
||||
unsigned i = 0;
|
||||
for (i = 0; i < BitsNum - shiftAmt; ++i)
|
||||
if ((*this)[i+shiftAmt]) set(i);
|
||||
else clear(i);
|
||||
for (; i < BitsNum; ++i)
|
||||
isAShr ? set(i) : clear(i);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// @brief Right-shift operator. Right-shift the APInt by shiftAmt.
|
||||
APInt APInt::operator>>(unsigned shiftAmt) const {
|
||||
APInt API(*this);
|
||||
API >>= shiftAmt;
|
||||
return API;
|
||||
}
|
||||
|
||||
/// @brief Bitwise NOT operator. Performs a bitwise logical NOT operation on
|
||||
/// this APInt.
|
||||
APInt APInt::operator~() const {
|
||||
@ -1042,12 +878,13 @@ APInt APInt::getNullValue(unsigned numBits) {
|
||||
|
||||
/// HiBits - This function returns the high "numBits" bits of this APInt.
|
||||
APInt APInt::HiBits(unsigned numBits) const {
|
||||
return (*this) >> (BitsNum - numBits);
|
||||
return APIntOps::lshr(*this, BitsNum - numBits);
|
||||
}
|
||||
|
||||
/// LoBits - This function returns the low "numBits" bits of this APInt.
|
||||
APInt APInt::LoBits(unsigned numBits) const {
|
||||
return ((*this) << (BitsNum - numBits)) >> (BitsNum - numBits);
|
||||
return APIntOps::lshr(APIntOps::shl(*this, BitsNum - numBits),
|
||||
BitsNum - numBits);
|
||||
}
|
||||
|
||||
/// CountLeadingZeros - This function is a APInt version corresponding to
|
||||
@ -1096,7 +933,7 @@ unsigned APInt::CountPopulation() const {
|
||||
|
||||
/// ByteSwap - This function returns a byte-swapped representation of the
|
||||
/// APInt argument, APIVal.
|
||||
APInt llvm::ByteSwap(const APInt& APIVal) {
|
||||
APInt llvm::APIntOps::ByteSwap(const APInt& APIVal) {
|
||||
if (APIVal.BitsNum <= 32)
|
||||
return APInt(APIVal.BitsNum, ByteSwap_32(unsigned(APIVal.VAL)));
|
||||
else if (APIVal.BitsNum <= 64)
|
||||
@ -1107,15 +944,170 @@ APInt llvm::ByteSwap(const APInt& APIVal) {
|
||||
|
||||
/// GreatestCommonDivisor - This function returns the greatest common
|
||||
/// divisor of the two APInt values using Enclid's algorithm.
|
||||
APInt llvm::GreatestCommonDivisor(const APInt& API1, const APInt& API2) {
|
||||
APInt llvm::APIntOps::GreatestCommonDivisor(const APInt& API1,
|
||||
const APInt& API2) {
|
||||
APInt A = API1, B = API2;
|
||||
while (!!B) {
|
||||
APInt T = B;
|
||||
B = A % B;
|
||||
B = APIntOps::urem(A, B);
|
||||
A = T;
|
||||
}
|
||||
return A;
|
||||
}
|
||||
|
||||
/// Arithmetic right-shift the APInt by shiftAmt.
|
||||
/// @brief Arithmetic right-shift function.
|
||||
APInt llvm::APIntOps::ashr(const APInt& LHS, unsigned shiftAmt) {
|
||||
APInt API(LHS);
|
||||
if (API.isSingleWord())
|
||||
API.VAL = (((int64_t(API.VAL) << (64 - API.BitsNum)) >> (64 - API.BitsNum))
|
||||
>> shiftAmt) & (~uint64_t(0UL) >> (64 - API.BitsNum));
|
||||
else {
|
||||
if (shiftAmt >= API.BitsNum) {
|
||||
memset(API.pVal, API[API.BitsNum-1] ? 1 : 0, (API.getNumWords()-1) * 8);
|
||||
API.pVal[API.getNumWords() - 1] = ~uint64_t(0UL) >>
|
||||
(64 - API.BitsNum % 64);
|
||||
} else {
|
||||
unsigned i = 0;
|
||||
for (; i < API.BitsNum - shiftAmt; ++i)
|
||||
if (API[i+shiftAmt])
|
||||
API.set(i);
|
||||
else
|
||||
API.clear(i);
|
||||
for (; i < API.BitsNum; ++i)
|
||||
API[API.BitsNum-1] ? API.set(i) : API.clear(i);
|
||||
}
|
||||
}
|
||||
return API;
|
||||
}
|
||||
|
||||
/// Logical right-shift the APInt by shiftAmt.
|
||||
/// @brief Logical right-shift function.
|
||||
APInt llvm::APIntOps::lshr(const APInt& RHS, unsigned shiftAmt) {
|
||||
APInt API(RHS);
|
||||
if (API.isSingleWord())
|
||||
API.VAL >>= shiftAmt;
|
||||
else {
|
||||
if (shiftAmt >= API.BitsNum)
|
||||
memset(API.pVal, 0, API.getNumWords() * 8);
|
||||
unsigned i = 0;
|
||||
for (i = 0; i < API.BitsNum - shiftAmt; ++i)
|
||||
if (API[i+shiftAmt]) API.set(i);
|
||||
else API.clear(i);
|
||||
for (; i < API.BitsNum; ++i)
|
||||
API.clear(i);
|
||||
}
|
||||
return API;
|
||||
}
|
||||
|
||||
/// Left-shift the APInt by shiftAmt.
|
||||
/// @brief Left-shift function.
|
||||
APInt llvm::APIntOps::shl(const APInt& RHS, unsigned shiftAmt) {
|
||||
APInt API(RHS);
|
||||
if (shiftAmt >= API.BitsNum) {
|
||||
if (API.isSingleWord())
|
||||
API.VAL = 0;
|
||||
else
|
||||
memset(API.pVal, 0, API.getNumWords() * 8);
|
||||
} else {
|
||||
for (unsigned i = 0; i < shiftAmt; ++i) API.clear(i);
|
||||
for (unsigned i = shiftAmt; i < API.BitsNum; ++i) {
|
||||
if (API[i-shiftAmt]) API.set(i);
|
||||
else API.clear(i);
|
||||
}
|
||||
}
|
||||
return API;
|
||||
}
|
||||
|
||||
/// Unsigned divide APInt LHS by APInt RHS.
|
||||
/// @brief Unsigned division function for APInt.
|
||||
APInt llvm::APIntOps::udiv(const APInt& LHS, const APInt& RHS) {
|
||||
APInt API(LHS);
|
||||
unsigned first = RHS.getNumWords() * APInt::APINT_BITS_PER_WORD -
|
||||
RHS.CountLeadingZeros();
|
||||
unsigned ylen = !first ? 0 : APInt::whichWord(first - 1) + 1;
|
||||
assert(ylen && "Divided by zero???");
|
||||
if (API.isSingleWord()) {
|
||||
API.VAL = RHS.isSingleWord() ? (API.VAL / RHS.VAL) :
|
||||
(ylen > 1 ? 0 : API.VAL / RHS.pVal[0]);
|
||||
} else {
|
||||
unsigned first2 = API.getNumWords() * APInt::APINT_BITS_PER_WORD -
|
||||
API.CountLeadingZeros();
|
||||
unsigned xlen = !first2 ? 0 : APInt::whichWord(first2 - 1) + 1;
|
||||
if (!xlen)
|
||||
return API;
|
||||
else if (API < RHS)
|
||||
memset(API.pVal, 0, API.getNumWords() * 8);
|
||||
else if (API == RHS) {
|
||||
memset(API.pVal, 0, API.getNumWords() * 8);
|
||||
API.pVal[0] = 1;
|
||||
} else if (xlen == 1)
|
||||
API.pVal[0] /= RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0];
|
||||
else {
|
||||
uint64_t *xwords = new uint64_t[xlen+1], *ywords = new uint64_t[ylen];
|
||||
assert(xwords && ywords && "Memory Allocation Failed!");
|
||||
memcpy(xwords, API.pVal, xlen * 8);
|
||||
xwords[xlen] = 0;
|
||||
memcpy(ywords, RHS.isSingleWord() ? &RHS.VAL : RHS.pVal, ylen * 8);
|
||||
if (unsigned nshift = 63 - (first - 1) % 64) {
|
||||
lshift(ywords, 0, ywords, ylen, nshift);
|
||||
unsigned xlentmp = xlen;
|
||||
xwords[xlen++] = lshift(xwords, 0, xwords, xlentmp, nshift);
|
||||
}
|
||||
div((unsigned*)xwords, xlen*2-1, (unsigned*)ywords, ylen*2);
|
||||
memset(API.pVal, 0, API.getNumWords() * 8);
|
||||
memcpy(API.pVal, xwords + ylen, (xlen - ylen) * 8);
|
||||
delete[] xwords;
|
||||
delete[] ywords;
|
||||
}
|
||||
}
|
||||
return API;
|
||||
}
|
||||
|
||||
/// Unsigned remainder operation on APInt.
|
||||
/// @brief Function for unsigned remainder operation.
|
||||
APInt llvm::APIntOps::urem(const APInt& LHS, const APInt& RHS) {
|
||||
APInt API(LHS);
|
||||
unsigned first = RHS.getNumWords() * APInt::APINT_BITS_PER_WORD -
|
||||
RHS.CountLeadingZeros();
|
||||
unsigned ylen = !first ? 0 : APInt::whichWord(first - 1) + 1;
|
||||
assert(ylen && "Performing remainder operation by zero ???");
|
||||
if (API.isSingleWord()) {
|
||||
API.VAL = RHS.isSingleWord() ? (API.VAL % RHS.VAL) :
|
||||
(ylen > 1 ? API.VAL : API.VAL % RHS.pVal[0]);
|
||||
} else {
|
||||
unsigned first2 = API.getNumWords() * APInt::APINT_BITS_PER_WORD -
|
||||
API.CountLeadingZeros();
|
||||
unsigned xlen = !first2 ? 0 : API.whichWord(first2 - 1) + 1;
|
||||
if (!xlen || API < RHS)
|
||||
return API;
|
||||
else if (API == RHS)
|
||||
memset(API.pVal, 0, API.getNumWords() * 8);
|
||||
else if (xlen == 1)
|
||||
API.pVal[0] %= RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0];
|
||||
else {
|
||||
uint64_t *xwords = new uint64_t[xlen+1], *ywords = new uint64_t[ylen];
|
||||
assert(xwords && ywords && "Memory Allocation Failed!");
|
||||
memcpy(xwords, API.pVal, xlen * 8);
|
||||
xwords[xlen] = 0;
|
||||
memcpy(ywords, RHS.isSingleWord() ? &RHS.VAL : RHS.pVal, ylen * 8);
|
||||
unsigned nshift = 63 - (first - 1) % 64;
|
||||
if (nshift) {
|
||||
lshift(ywords, 0, ywords, ylen, nshift);
|
||||
unsigned xlentmp = xlen;
|
||||
xwords[xlen++] = lshift(xwords, 0, xwords, xlentmp, nshift);
|
||||
}
|
||||
div((unsigned*)xwords, xlen*2-1, (unsigned*)ywords, ylen*2);
|
||||
memset(API.pVal, 0, API.getNumWords() * 8);
|
||||
for (unsigned i = 0; i < ylen-1; ++i)
|
||||
API.pVal[i] = (xwords[i] >> nshift) | (xwords[i+1] << (64 - nshift));
|
||||
API.pVal[ylen-1] = xwords[ylen-1] >> nshift;
|
||||
delete[] xwords;
|
||||
delete[] ywords;
|
||||
}
|
||||
}
|
||||
return API;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user