summaryrefslogtreecommitdiff
path: root/clang/lib/AST/ByteCode/IntegralAP.h
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/ByteCode/IntegralAP.h')
-rw-r--r--clang/lib/AST/ByteCode/IntegralAP.h236
1 files changed, 134 insertions, 102 deletions
diff --git a/clang/lib/AST/ByteCode/IntegralAP.h b/clang/lib/AST/ByteCode/IntegralAP.h
index 8ee08dfb5cfe..316c003e0e50 100644
--- a/clang/lib/AST/ByteCode/IntegralAP.h
+++ b/clang/lib/AST/ByteCode/IntegralAP.h
@@ -28,12 +28,19 @@ namespace interp {
using APInt = llvm::APInt;
using APSInt = llvm::APSInt;
-template <unsigned Bits, bool Signed> class Integral;
+/// If an IntegralAP is constructed from Memory, it DOES NOT OWN THAT MEMORY.
+/// It will NOT copy the memory (unless, of course, copy() is called) and it
+/// won't alllocate anything. The allocation should happen via InterpState or
+/// Program.
template <bool Signed> class IntegralAP final {
-private:
+public:
+ union {
+ uint64_t *Memory = nullptr;
+ uint64_t Val;
+ };
+ uint32_t BitWidth = 0;
friend IntegralAP<!Signed>;
- APInt V;
template <typename T, bool InputSigned>
static T truncateCast(const APInt &V) {
@@ -52,106 +59,118 @@ private:
: V.trunc(BitSize).getZExtValue();
}
+ APInt getValue() const {
+ if (singleWord())
+ return APInt(BitWidth, Val, Signed);
+ unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
+ return llvm::APInt(BitWidth, NumWords, Memory);
+ }
+
public:
using AsUnsigned = IntegralAP<false>;
- template <typename T>
- IntegralAP(T Value, unsigned BitWidth)
- : V(APInt(BitWidth, static_cast<uint64_t>(Value), Signed)) {}
+ void take(uint64_t *NewMemory) {
+ assert(!singleWord());
+ std::memcpy(NewMemory, Memory, numWords() * sizeof(uint64_t));
+ Memory = NewMemory;
+ }
- IntegralAP(APInt V) : V(V) {}
- /// Arbitrary value for uninitialized variables.
- IntegralAP() : IntegralAP(Signed ? -1 : 7, 3) {}
+ void copy(const APInt &V) {
+ assert(BitWidth == V.getBitWidth());
+ assert(numWords() == V.getNumWords());
- IntegralAP operator-() const { return IntegralAP(-V); }
- IntegralAP operator-(const IntegralAP &Other) const {
- return IntegralAP(V - Other.V);
+ if (V.isSingleWord()) {
+ if constexpr (Signed)
+ Val = V.getSExtValue();
+ else
+ Val = V.getZExtValue();
+ return;
+ }
+ assert(Memory);
+ std::memcpy(Memory, V.getRawData(), V.getNumWords() * sizeof(uint64_t));
+ }
+
+ IntegralAP() = default;
+ /// Zeroed, single-word IntegralAP of the given bitwidth.
+ IntegralAP(unsigned BitWidth) : Val(0), BitWidth(BitWidth) {
+ assert(singleWord());
+ }
+ IntegralAP(uint64_t *Memory, unsigned BitWidth)
+ : Memory(Memory), BitWidth(BitWidth) {}
+ IntegralAP(const APInt &V) : BitWidth(V.getBitWidth()) {
+ if (V.isSingleWord()) {
+ Val = Signed ? V.getSExtValue() : V.getZExtValue();
+ } else {
+ Memory = const_cast<uint64_t *>(V.getRawData());
+ }
}
+
+ IntegralAP operator-() const { return IntegralAP(-getValue()); }
bool operator>(const IntegralAP &RHS) const {
if constexpr (Signed)
- return V.ugt(RHS.V);
- return V.sgt(RHS.V);
+ return getValue().sgt(RHS.getValue());
+ return getValue().ugt(RHS.getValue());
}
- bool operator>=(IntegralAP RHS) const {
+ bool operator>=(unsigned RHS) const {
if constexpr (Signed)
- return V.uge(RHS.V);
- return V.sge(RHS.V);
+ return getValue().sge(RHS);
+ return getValue().uge(RHS);
}
bool operator<(IntegralAP RHS) const {
if constexpr (Signed)
- return V.slt(RHS.V);
- return V.slt(RHS.V);
- }
- bool operator<=(IntegralAP RHS) const {
- if constexpr (Signed)
- return V.ult(RHS.V);
- return V.ult(RHS.V);
+ return getValue().slt(RHS.getValue());
+ return getValue().ult(RHS.getValue());
}
template <typename Ty, typename = std::enable_if_t<std::is_integral_v<Ty>>>
explicit operator Ty() const {
- return truncateCast<Ty, Signed>(V);
+ return truncateCast<Ty, Signed>(getValue());
}
template <typename T> static IntegralAP from(T Value, unsigned NumBits = 0) {
+ if (NumBits == 0)
+ NumBits = sizeof(T) * 8;
assert(NumBits > 0);
APInt Copy = APInt(NumBits, static_cast<uint64_t>(Value), Signed);
-
+ assert(false);
return IntegralAP<Signed>(Copy);
}
- template <bool InputSigned>
- static IntegralAP from(IntegralAP<InputSigned> V, unsigned NumBits = 0) {
- if (NumBits == 0)
- NumBits = V.bitWidth();
-
- if constexpr (InputSigned)
- return IntegralAP<Signed>(V.V.sextOrTrunc(NumBits));
- return IntegralAP<Signed>(V.V.zextOrTrunc(NumBits));
- }
-
- template <unsigned Bits, bool InputSigned>
- static IntegralAP from(Integral<Bits, InputSigned> I, unsigned BitWidth) {
- return IntegralAP<Signed>(I.toAPInt(BitWidth));
- }
-
- static IntegralAP zero(int32_t BitWidth) {
- APInt V = APInt(BitWidth, 0LL, Signed);
- return IntegralAP(V);
- }
-
- constexpr unsigned bitWidth() const { return V.getBitWidth(); }
+ constexpr uint32_t bitWidth() const { return BitWidth; }
+ constexpr unsigned numWords() const { return APInt::getNumWords(BitWidth); }
+ constexpr bool singleWord() const { return numWords() == 1; }
APSInt toAPSInt(unsigned Bits = 0) const {
if (Bits == 0)
Bits = bitWidth();
+ APInt V = getValue();
if constexpr (Signed)
- return APSInt(V.sext(Bits), !Signed);
+ return APSInt(getValue().sext(Bits), !Signed);
else
- return APSInt(V.zext(Bits), !Signed);
+ return APSInt(getValue().zext(Bits), !Signed);
}
APValue toAPValue(const ASTContext &) const { return APValue(toAPSInt()); }
- bool isZero() const { return V.isZero(); }
+ bool isZero() const { return getValue().isZero(); }
bool isPositive() const {
if constexpr (Signed)
- return V.isNonNegative();
+ return getValue().isNonNegative();
return true;
}
bool isNegative() const {
if constexpr (Signed)
- return !V.isNonNegative();
+ return !getValue().isNonNegative();
return false;
}
- bool isMin() const { return V.isMinValue(); }
- bool isMax() const { return V.isMaxValue(); }
+ bool isMin() const { return getValue().isMinValue(); }
+ bool isMax() const { return getValue().isMaxValue(); }
static constexpr bool isSigned() { return Signed; }
- bool isMinusOne() const { return Signed && V == -1; }
+ bool isMinusOne() const { return Signed && getValue().isAllOnes(); }
- unsigned countLeadingZeros() const { return V.countl_zero(); }
+ unsigned countLeadingZeros() const { return getValue().countl_zero(); }
- void print(llvm::raw_ostream &OS) const { V.print(OS, Signed);}
+ void print(llvm::raw_ostream &OS) const { getValue().print(OS, Signed); }
std::string toDiagnosticString(const ASTContext &Ctx) const {
std::string NameStr;
llvm::raw_string_ostream OS(NameStr);
@@ -161,53 +180,57 @@ public:
IntegralAP truncate(unsigned BitWidth) const {
if constexpr (Signed)
- return IntegralAP(V.trunc(BitWidth).sextOrTrunc(this->bitWidth()));
+ return IntegralAP(
+ getValue().trunc(BitWidth).sextOrTrunc(this->bitWidth()));
else
- return IntegralAP(V.trunc(BitWidth).zextOrTrunc(this->bitWidth()));
+ return IntegralAP(
+ getValue().trunc(BitWidth).zextOrTrunc(this->bitWidth()));
}
IntegralAP<false> toUnsigned() const {
- APInt Copy = V;
- return IntegralAP<false>(Copy);
+ return IntegralAP<false>(Memory, BitWidth);
}
void bitcastToMemory(std::byte *Dest) const {
- llvm::StoreIntToMemory(V, (uint8_t *)Dest, bitWidth() / 8);
+ llvm::StoreIntToMemory(getValue(), (uint8_t *)Dest, bitWidth() / 8);
}
- static IntegralAP bitcastFromMemory(const std::byte *Src, unsigned BitWidth) {
+ static void bitcastFromMemory(const std::byte *Src, unsigned BitWidth,
+ IntegralAP *Result) {
APInt V(BitWidth, static_cast<uint64_t>(0), Signed);
llvm::LoadIntFromMemory(V, (const uint8_t *)Src, BitWidth / 8);
- return IntegralAP(V);
+ Result->copy(V);
}
ComparisonCategoryResult compare(const IntegralAP &RHS) const {
assert(Signed == RHS.isSigned());
assert(bitWidth() == RHS.bitWidth());
+ APInt V1 = getValue();
+ APInt V2 = RHS.getValue();
if constexpr (Signed) {
- if (V.slt(RHS.V))
+ if (V1.slt(V2))
return ComparisonCategoryResult::Less;
- if (V.sgt(RHS.V))
+ if (V1.sgt(V2))
return ComparisonCategoryResult::Greater;
return ComparisonCategoryResult::Equal;
}
assert(!Signed);
- if (V.ult(RHS.V))
+ if (V1.ult(V2))
return ComparisonCategoryResult::Less;
- if (V.ugt(RHS.V))
+ if (V1.ugt(V2))
return ComparisonCategoryResult::Greater;
return ComparisonCategoryResult::Equal;
}
static bool increment(IntegralAP A, IntegralAP *R) {
- IntegralAP<Signed> One(1, A.bitWidth());
- return add(A, One, A.bitWidth() + 1, R);
+ APSInt One(APInt(A.bitWidth(), 1ull, Signed), !Signed);
+ return add(A, IntegralAP<Signed>(One), A.bitWidth() + 1, R);
}
static bool decrement(IntegralAP A, IntegralAP *R) {
- IntegralAP<Signed> One(1, A.bitWidth());
- return sub(A, One, A.bitWidth() + 1, R);
+ APSInt One(APInt(A.bitWidth(), 1ull, Signed), !Signed);
+ return sub(A, IntegralAP<Signed>(One), A.bitWidth() + 1, R);
}
static bool add(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) {
@@ -224,87 +247,96 @@ public:
static bool rem(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) {
if constexpr (Signed)
- *R = IntegralAP(A.V.srem(B.V));
+ R->copy(A.getValue().srem(B.getValue()));
else
- *R = IntegralAP(A.V.urem(B.V));
+ R->copy(A.getValue().urem(B.getValue()));
return false;
}
static bool div(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) {
if constexpr (Signed)
- *R = IntegralAP(A.V.sdiv(B.V));
+ R->copy(A.getValue().sdiv(B.getValue()));
else
- *R = IntegralAP(A.V.udiv(B.V));
+ R->copy(A.getValue().udiv(B.getValue()));
return false;
}
static bool bitAnd(IntegralAP A, IntegralAP B, unsigned OpBits,
IntegralAP *R) {
- *R = IntegralAP(A.V & B.V);
+ R->copy(A.getValue() & B.getValue());
return false;
}
static bool bitOr(IntegralAP A, IntegralAP B, unsigned OpBits,
IntegralAP *R) {
- *R = IntegralAP(A.V | B.V);
+ R->copy(A.getValue() | B.getValue());
return false;
}
static bool bitXor(IntegralAP A, IntegralAP B, unsigned OpBits,
IntegralAP *R) {
- *R = IntegralAP(A.V ^ B.V);
+ R->copy(A.getValue() ^ B.getValue());
return false;
}
static bool neg(const IntegralAP &A, IntegralAP *R) {
- APInt AI = A.V;
+ APInt AI = A.getValue();
AI.negate();
- *R = IntegralAP(AI);
+ R->copy(AI);
return false;
}
static bool comp(IntegralAP A, IntegralAP *R) {
- *R = IntegralAP(~A.V);
+ R->copy(~A.getValue());
return false;
}
static void shiftLeft(const IntegralAP A, const IntegralAP B, unsigned OpBits,
IntegralAP *R) {
- *R = IntegralAP(A.V.shl(B.V.getZExtValue()));
+ *R = IntegralAP(A.getValue().shl(B.getValue().getZExtValue()));
}
static void shiftRight(const IntegralAP A, const IntegralAP B,
unsigned OpBits, IntegralAP *R) {
- unsigned ShiftAmount = B.V.getZExtValue();
+ unsigned ShiftAmount = B.getValue().getZExtValue();
if constexpr (Signed)
- *R = IntegralAP(A.V.ashr(ShiftAmount));
+ R->copy(A.getValue().ashr(ShiftAmount));
else
- *R = IntegralAP(A.V.lshr(ShiftAmount));
+ R->copy(A.getValue().lshr(ShiftAmount));
}
// === Serialization support ===
size_t bytesToSerialize() const {
- // 4 bytes for the BitWidth followed by N bytes for the actual APInt.
- return sizeof(uint32_t) + (V.getBitWidth() / CHAR_BIT);
+ assert(BitWidth != 0);
+ return sizeof(uint32_t) + (numWords() * sizeof(uint64_t));
}
void serialize(std::byte *Buff) const {
- assert(V.getBitWidth() < std::numeric_limits<uint8_t>::max());
- uint32_t BitWidth = V.getBitWidth();
-
std::memcpy(Buff, &BitWidth, sizeof(uint32_t));
- llvm::StoreIntToMemory(V, (uint8_t *)(Buff + sizeof(uint32_t)),
- BitWidth / CHAR_BIT);
+ if (singleWord())
+ std::memcpy(Buff + sizeof(uint32_t), &Val, sizeof(uint64_t));
+ else {
+ std::memcpy(Buff + sizeof(uint32_t), Memory,
+ numWords() * sizeof(uint64_t));
+ }
}
- static IntegralAP<Signed> deserialize(const std::byte *Buff) {
- uint32_t BitWidth;
- std::memcpy(&BitWidth, Buff, sizeof(uint32_t));
- IntegralAP<Signed> Val(APInt(BitWidth, 0ull, !Signed));
+ static uint32_t deserializeSize(const std::byte *Buff) {
+ return *reinterpret_cast<const uint32_t *>(Buff);
+ }
+
+ static void deserialize(const std::byte *Buff, IntegralAP<Signed> *Result) {
+ uint32_t BitWidth = Result->BitWidth;
+ assert(BitWidth != 0);
+ unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
- llvm::LoadIntFromMemory(Val.V, (const uint8_t *)Buff + sizeof(uint32_t),
- BitWidth / CHAR_BIT);
- return Val;
+ if (NumWords == 1)
+ std::memcpy(&Result->Val, Buff + sizeof(uint32_t), sizeof(uint64_t));
+ else {
+ assert(Result->Memory);
+ std::memcpy(Result->Memory, Buff + sizeof(uint32_t),
+ NumWords * sizeof(uint64_t));
+ }
}
private:
@@ -312,7 +344,7 @@ private:
static bool CheckAddSubMulUB(const IntegralAP &A, const IntegralAP &B,
unsigned BitWidth, IntegralAP *R) {
if constexpr (!Signed) {
- R->V = Op<APInt>{}(A.V, B.V);
+ R->copy(Op<APInt>{}(A.getValue(), B.getValue()));
return false;
}
@@ -320,7 +352,7 @@ private:
const APSInt &RHS = B.toAPSInt();
APSInt Value = Op<APSInt>{}(LHS.extend(BitWidth), RHS.extend(BitWidth));
APSInt Result = Value.trunc(LHS.getBitWidth());
- R->V = Result;
+ R->copy(Result);
return Result.extend(BitWidth) != Value;
}