[clang] 57828fe - Revert "[clang][bytecode] Allocate IntegralAP and Floating types using an allocator (#144246)"
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 17 12:08:56 PDT 2025
Author: Timm Bäder
Date: 2025-06-17T21:08:23+02:00
New Revision: 57828fec760f086b334ce0cb1c465fc559dcaea4
URL: https://github.com/llvm/llvm-project/commit/57828fec760f086b334ce0cb1c465fc559dcaea4
DIFF: https://github.com/llvm/llvm-project/commit/57828fec760f086b334ce0cb1c465fc559dcaea4.diff
LOG: Revert "[clang][bytecode] Allocate IntegralAP and Floating types using an allocator (#144246)"
This reverts commit c66be289901b3f035187d391e80e3610d7d6232e.
This breaks the armv8-quick builder:
https://lab.llvm.org/buildbot/#/builders/154/builds/17549
Added:
Modified:
clang/lib/AST/ByteCode/Compiler.cpp
clang/lib/AST/ByteCode/Compiler.h
clang/lib/AST/ByteCode/Descriptor.cpp
clang/lib/AST/ByteCode/Disasm.cpp
clang/lib/AST/ByteCode/Floating.h
clang/lib/AST/ByteCode/Integral.h
clang/lib/AST/ByteCode/IntegralAP.h
clang/lib/AST/ByteCode/Interp.cpp
clang/lib/AST/ByteCode/Interp.h
clang/lib/AST/ByteCode/InterpBuiltin.cpp
clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
clang/lib/AST/ByteCode/InterpState.h
clang/lib/AST/ByteCode/Opcodes.td
clang/lib/AST/ByteCode/PrimType.h
clang/lib/AST/ByteCode/Program.h
clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp
clang/test/AST/ByteCode/builtin-functions.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 3f884ed8d094a..9fe4803ce98ec 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -748,8 +748,7 @@ bool Compiler<Emitter>::VisitFloatingLiteral(const FloatingLiteral *E) {
if (DiscardResult)
return true;
- APFloat F = E->getValue();
- return this->emitFloat(F, E);
+ return this->emitConstFloat(E->getValue(), E);
}
template <class Emitter>
@@ -4186,10 +4185,8 @@ bool Compiler<Emitter>::visitZeroInitializer(PrimType T, QualType QT,
nullptr, E);
case PT_MemberPtr:
return this->emitNullMemberPtr(0, nullptr, E);
- case PT_Float: {
- APFloat F = APFloat::getZero(Ctx.getFloatSemantics(QT));
- return this->emitFloat(F, E);
- }
+ case PT_Float:
+ return this->emitConstFloat(APFloat::getZero(Ctx.getFloatSemantics(QT)), E);
case PT_FixedPoint: {
auto Sem = Ctx.getASTContext().getFixedPointSemantics(E->getType());
return this->emitConstFixedPoint(FixedPoint::zero(Sem), E);
@@ -4677,7 +4674,10 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD,
if (!visitInitializer(Init))
return false;
- return this->emitFinishInitGlobal(Init);
+ if (!this->emitFinishInit(Init))
+ return false;
+
+ return this->emitPopPtr(Init);
};
DeclScope<Emitter> LocalScope(this, VD);
@@ -4698,45 +4698,51 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD,
return false;
return !Init || (checkDecl() && initGlobal(*GlobalIndex));
- }
- // Local variables.
- InitLinkScope<Emitter> ILS(this, InitLink::Decl(VD));
+ } else {
+ InitLinkScope<Emitter> ILS(this, InitLink::Decl(VD));
- if (VarT) {
- unsigned Offset = this->allocateLocalPrimitive(
- VD, *VarT, VD->getType().isConstQualified(), nullptr, ScopeKind::Block,
- IsConstexprUnknown);
- if (Init) {
- // If this is a toplevel declaration, create a scope for the
- // initializer.
- if (Toplevel) {
- LocalScope<Emitter> Scope(this);
- if (!this->visit(Init))
- return false;
- return this->emitSetLocal(*VarT, Offset, VD) && Scope.destroyLocals();
- } else {
- if (!this->visit(Init))
- return false;
- return this->emitSetLocal(*VarT, Offset, VD);
+ if (VarT) {
+ unsigned Offset = this->allocateLocalPrimitive(
+ VD, *VarT, VD->getType().isConstQualified(), nullptr,
+ ScopeKind::Block, IsConstexprUnknown);
+ if (Init) {
+ // If this is a toplevel declaration, create a scope for the
+ // initializer.
+ if (Toplevel) {
+ LocalScope<Emitter> Scope(this);
+ if (!this->visit(Init))
+ return false;
+ return this->emitSetLocal(*VarT, Offset, VD) && Scope.destroyLocals();
+ } else {
+ if (!this->visit(Init))
+ return false;
+ return this->emitSetLocal(*VarT, Offset, VD);
+ }
}
- }
- } else {
- if (std::optional<unsigned> Offset = this->allocateLocal(
- VD, VD->getType(), nullptr, ScopeKind::Block, IsConstexprUnknown)) {
- if (!Init)
- return true;
+ } else {
+ if (std::optional<unsigned> Offset =
+ this->allocateLocal(VD, VD->getType(), nullptr, ScopeKind::Block,
+ IsConstexprUnknown)) {
+ if (!Init)
+ return true;
- if (!this->emitGetPtrLocal(*Offset, Init))
- return false;
+ if (!this->emitGetPtrLocal(*Offset, Init))
+ return false;
- if (!visitInitializer(Init))
- return false;
+ if (!visitInitializer(Init))
+ return false;
+
+ if (!this->emitFinishInit(Init))
+ return false;
- return this->emitFinishInitPop(Init);
+ return this->emitPopPtr(Init);
+ }
+ return false;
}
- return false;
+ return true;
}
- return true;
+
+ return false;
}
template <class Emitter>
@@ -4745,10 +4751,8 @@ bool Compiler<Emitter>::visitAPValue(const APValue &Val, PrimType ValType,
assert(!DiscardResult);
if (Val.isInt())
return this->emitConst(Val.getInt(), ValType, E);
- else if (Val.isFloat()) {
- APFloat F = Val.getFloat();
- return this->emitFloat(F, E);
- }
+ else if (Val.isFloat())
+ return this->emitConstFloat(Val.getFloat(), E);
if (Val.isLValue()) {
if (Val.isNullPointer())
@@ -6129,10 +6133,8 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
const auto &TargetSemantics = Ctx.getFloatSemantics(E->getType());
if (!this->emitLoadFloat(E))
return false;
- APFloat F(TargetSemantics, 1);
- if (!this->emitFloat(F, E))
+ if (!this->emitConstFloat(llvm::APFloat(TargetSemantics, 1), E))
return false;
-
if (!this->emitAddf(getFPOptions(E), E))
return false;
if (!this->emitStoreFloat(E))
@@ -6174,10 +6176,8 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
const auto &TargetSemantics = Ctx.getFloatSemantics(E->getType());
if (!this->emitLoadFloat(E))
return false;
- APFloat F(TargetSemantics, 1);
- if (!this->emitFloat(F, E))
+ if (!this->emitConstFloat(llvm::APFloat(TargetSemantics, 1), E))
return false;
-
if (!this->emitSubf(getFPOptions(E), E))
return false;
if (!this->emitStoreFloat(E))
@@ -6953,20 +6953,6 @@ bool Compiler<Emitter>::emitDummyPtr(const DeclTy &D, const Expr *E) {
return true;
}
-template <class Emitter>
-bool Compiler<Emitter>::emitFloat(const APFloat &F, const Expr *E) {
- assert(!DiscardResult && "Should've been checked before");
-
- if (Floating::singleWord(F.getSemantics()))
- return this->emitConstFloat(Floating(F), E);
-
- APInt I = F.bitcastToAPInt();
- return this->emitConstFloat(
- Floating(const_cast<uint64_t *>(I.getRawData()),
- llvm::APFloatBase::SemanticsToEnum(F.getSemantics())),
- E);
-}
-
// This function is constexpr if and only if To, From, and the types of
// all subobjects of To and From are types T such that...
// (3.1) - is_union_v<T> is false;
diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h
index a1d068cc7e0ae..ac3ad84766dc6 100644
--- a/clang/lib/AST/ByteCode/Compiler.h
+++ b/clang/lib/AST/ByteCode/Compiler.h
@@ -391,7 +391,6 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
bool emitRecordDestruction(const Record *R, SourceInfo Loc);
bool emitDestruction(const Descriptor *Desc, SourceInfo Loc);
bool emitDummyPtr(const DeclTy &D, const Expr *E);
- bool emitFloat(const APFloat &F, const Expr *E);
unsigned collectBaseOffset(const QualType BaseType,
const QualType DerivedType);
bool emitLambdaStaticInvokerBody(const CXXMethodDecl *MD);
diff --git a/clang/lib/AST/ByteCode/Descriptor.cpp b/clang/lib/AST/ByteCode/Descriptor.cpp
index 46e4d0d940b3e..5531295dfa2f8 100644
--- a/clang/lib/AST/ByteCode/Descriptor.cpp
+++ b/clang/lib/AST/ByteCode/Descriptor.cpp
@@ -368,7 +368,7 @@ Descriptor::Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD,
bool IsTemporary, bool IsConst, UnknownSize)
: Source(D), ElemSize(primSize(Type)), Size(UnknownSizeMark),
MDSize(MD.value_or(0)),
- AllocSize(MDSize + sizeof(InitMapPtr) + alignof(void *)), PrimT(Type),
+ AllocSize(MDSize + sizeof(InitMapPtr) + alignof(void *)),
IsConst(IsConst), IsMutable(false), IsTemporary(IsTemporary),
IsArray(true), CtorFn(getCtorArrayPrim(Type)),
DtorFn(getDtorArrayPrim(Type)), MoveFn(getMoveArrayPrim(Type)) {
diff --git a/clang/lib/AST/ByteCode/Disasm.cpp b/clang/lib/AST/ByteCode/Disasm.cpp
index 7c6b78386b14f..846dc2fe92a70 100644
--- a/clang/lib/AST/ByteCode/Disasm.cpp
+++ b/clang/lib/AST/ByteCode/Disasm.cpp
@@ -50,56 +50,34 @@ inline static std::string printArg(Program &P, CodePtr &OpPC) {
}
template <> inline std::string printArg<Floating>(Program &P, CodePtr &OpPC) {
- auto Sem = Floating::deserializeSemantics(*OpPC);
-
- unsigned BitWidth = llvm::APFloatBase::semanticsSizeInBits(
- llvm::APFloatBase::EnumToSemantics(Sem));
- auto Memory =
- std::make_unique<uint64_t[]>(llvm::APInt::getNumWords(BitWidth));
- Floating Result(Memory.get(), Sem);
- Floating::deserialize(*OpPC, &Result);
-
- OpPC += align(Result.bytesToSerialize());
+ auto F = Floating::deserialize(*OpPC);
+ OpPC += align(F.bytesToSerialize());
- std::string S;
- llvm::raw_string_ostream SS(S);
- SS << Result;
- return S;
+ std::string Result;
+ llvm::raw_string_ostream SS(Result);
+ SS << F;
+ return Result;
}
template <>
inline std::string printArg<IntegralAP<false>>(Program &P, CodePtr &OpPC) {
- using T = IntegralAP<false>;
- unsigned BitWidth = T::deserializeSize(*OpPC);
- auto Memory =
- std::make_unique<uint64_t[]>(llvm::APInt::getNumWords(BitWidth));
-
- T Result(Memory.get(), BitWidth);
- T::deserialize(*OpPC, &Result);
-
- OpPC += Result.bytesToSerialize();
- std::string Str;
- llvm::raw_string_ostream SS(Str);
- SS << Result;
- return Str;
-}
+ auto F = IntegralAP<false>::deserialize(*OpPC);
+ OpPC += align(F.bytesToSerialize());
+ std::string Result;
+ llvm::raw_string_ostream SS(Result);
+ SS << F;
+ return Result;
+}
template <>
inline std::string printArg<IntegralAP<true>>(Program &P, CodePtr &OpPC) {
- using T = IntegralAP<true>;
- unsigned BitWidth = T::deserializeSize(*OpPC);
- auto Memory =
- std::make_unique<uint64_t[]>(llvm::APInt::getNumWords(BitWidth));
-
- T Result(Memory.get(), BitWidth);
- T::deserialize(*OpPC, &Result);
-
- std::string Str;
- llvm::raw_string_ostream SS(Str);
- SS << Result;
+ auto F = IntegralAP<true>::deserialize(*OpPC);
+ OpPC += align(F.bytesToSerialize());
- OpPC += Result.bytesToSerialize();
- return Str;
+ std::string Result;
+ llvm::raw_string_ostream SS(Result);
+ SS << F;
+ return Result;
}
template <> inline std::string printArg<FixedPoint>(Program &P, CodePtr &OpPC) {
diff --git a/clang/lib/AST/ByteCode/Floating.h b/clang/lib/AST/ByteCode/Floating.h
index 659892e720abf..3750568fc23c7 100644
--- a/clang/lib/AST/ByteCode/Floating.h
+++ b/clang/lib/AST/ByteCode/Floating.h
@@ -17,79 +17,63 @@
#include "clang/AST/APValue.h"
#include "llvm/ADT/APFloat.h"
-// XXX This is just a debugging help. Setting this to 1 will heap-allocate ALL
-// floating values.
-#define ALLOCATE_ALL 0
-
namespace clang {
namespace interp {
using APFloat = llvm::APFloat;
using APSInt = llvm::APSInt;
-using APInt = llvm::APInt;
-/// If a Floating 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.
class Floating final {
private:
- union {
- uint64_t Val = 0;
- uint64_t *Memory;
- };
- llvm::APFloatBase::Semantics Semantics;
-
- APFloat getValue() const {
- unsigned BitWidth = bitWidth();
- if (singleWord())
- return APFloat(getSemantics(), APInt(BitWidth, Val));
- unsigned NumWords = numWords();
- return APFloat(getSemantics(), APInt(BitWidth, NumWords, Memory));
- }
+ // The underlying value storage.
+ APFloat F;
public:
- Floating() = default;
- Floating(llvm::APFloatBase::Semantics Semantics)
- : Val(0), Semantics(Semantics) {}
- Floating(const APFloat &F) {
+ /// Zero-initializes a Floating.
+ Floating() : F(0.0f) {}
+ Floating(const APFloat &F) : F(F) {}
- Semantics = llvm::APFloatBase::SemanticsToEnum(F.getSemantics());
- this->copy(F);
+ // Static constructors for special floating point values.
+ static Floating getInf(const llvm::fltSemantics &Sem) {
+ return Floating(APFloat::getInf(Sem));
}
- Floating(uint64_t *Memory, llvm::APFloatBase::Semantics Semantics)
- : Memory(Memory), Semantics(Semantics) {}
-
- APFloat getAPFloat() const { return getValue(); }
+ const APFloat &getAPFloat() const { return F; }
- bool operator<(Floating RHS) const { return getValue() < RHS.getValue(); }
- bool operator>(Floating RHS) const { return getValue() > RHS.getValue(); }
- bool operator<=(Floating RHS) const { return getValue() <= RHS.getValue(); }
- bool operator>=(Floating RHS) const { return getValue() >= RHS.getValue(); }
+ bool operator<(Floating RHS) const { return F < RHS.F; }
+ bool operator>(Floating RHS) const { return F > RHS.F; }
+ bool operator<=(Floating RHS) const { return F <= RHS.F; }
+ bool operator>=(Floating RHS) const { return F >= RHS.F; }
+ bool operator==(Floating RHS) const { return F == RHS.F; }
+ bool operator!=(Floating RHS) const { return F != RHS.F; }
+ Floating operator-() const { return Floating(-F); }
APFloat::opStatus convertToInteger(APSInt &Result) const {
bool IsExact;
- return getValue().convertToInteger(Result, llvm::APFloat::rmTowardZero,
- &IsExact);
+ return F.convertToInteger(Result, llvm::APFloat::rmTowardZero, &IsExact);
}
- void toSemantics(const llvm::fltSemantics *Sem, llvm::RoundingMode RM,
- Floating *Result) const {
- APFloat Copy = getValue();
+ Floating toSemantics(const llvm::fltSemantics *Sem,
+ llvm::RoundingMode RM) const {
+ APFloat Copy = F;
bool LosesInfo;
Copy.convert(*Sem, RM, &LosesInfo);
(void)LosesInfo;
- Result->copy(Copy);
+ return Floating(Copy);
+ }
+
+ /// Convert this Floating to one with the same semantics as \Other.
+ Floating toSemantics(const Floating &Other, llvm::RoundingMode RM) const {
+ return toSemantics(&Other.F.getSemantics(), RM);
}
APSInt toAPSInt(unsigned NumBits = 0) const {
- return APSInt(getValue().bitcastToAPInt());
+ return APSInt(F.bitcastToAPInt());
}
- APValue toAPValue(const ASTContext &) const { return APValue(getValue()); }
+ APValue toAPValue(const ASTContext &) const { return APValue(F); }
void print(llvm::raw_ostream &OS) const {
// Can't use APFloat::print() since it appends a newline.
SmallVector<char, 16> Buffer;
- getValue().toString(Buffer);
+ F.toString(Buffer);
OS << Buffer;
}
std::string toDiagnosticString(const ASTContext &Ctx) const {
@@ -99,62 +83,25 @@ class Floating final {
return NameStr;
}
- unsigned bitWidth() const {
- return llvm::APFloatBase::semanticsSizeInBits(getSemantics());
- }
- unsigned numWords() const { return llvm::APInt::getNumWords(bitWidth()); }
- bool singleWord() const {
-#if ALLOCATE_ALL
- return false;
-#endif
- return numWords() == 1;
- }
- static bool singleWord(const llvm::fltSemantics &Sem) {
-#if ALLOCATE_ALL
- return false;
-#endif
- return APInt::getNumWords(llvm::APFloatBase::getSizeInBits(Sem)) == 1;
- }
- const llvm::fltSemantics &getSemantics() const {
- return llvm::APFloatBase::EnumToSemantics(Semantics);
- }
-
- void copy(const APFloat &F) {
- if (singleWord()) {
- Val = F.bitcastToAPInt().getZExtValue();
- } else {
- assert(Memory);
- std::memcpy(Memory, F.bitcastToAPInt().getRawData(),
- numWords() * sizeof(uint64_t));
- }
- }
-
- void take(uint64_t *NewMemory) {
- if (singleWord())
- return;
-
- if (Memory)
- std::memcpy(NewMemory, Memory, numWords() * sizeof(uint64_t));
- Memory = NewMemory;
- }
+ unsigned bitWidth() const { return F.semanticsSizeInBits(F.getSemantics()); }
bool isSigned() const { return true; }
- bool isNegative() const { return getValue().isNegative(); }
- bool isZero() const { return getValue().isZero(); }
- bool isNonZero() const { return getValue().isNonZero(); }
- bool isMin() const { return getValue().isSmallest(); }
- bool isMinusOne() const { return getValue().isExactlyValue(-1.0); }
- bool isNan() const { return getValue().isNaN(); }
- bool isSignaling() const { return getValue().isSignaling(); }
- bool isInf() const { return getValue().isInfinity(); }
- bool isFinite() const { return getValue().isFinite(); }
- bool isNormal() const { return getValue().isNormal(); }
- bool isDenormal() const { return getValue().isDenormal(); }
- llvm::FPClassTest classify() const { return getValue().classify(); }
- APFloat::fltCategory getCategory() const { return getValue().getCategory(); }
+ bool isNegative() const { return F.isNegative(); }
+ bool isZero() const { return F.isZero(); }
+ bool isNonZero() const { return F.isNonZero(); }
+ bool isMin() const { return F.isSmallest(); }
+ bool isMinusOne() const { return F.isExactlyValue(-1.0); }
+ bool isNan() const { return F.isNaN(); }
+ bool isSignaling() const { return F.isSignaling(); }
+ bool isInf() const { return F.isInfinity(); }
+ bool isFinite() const { return F.isFinite(); }
+ bool isNormal() const { return F.isNormal(); }
+ bool isDenormal() const { return F.isDenormal(); }
+ llvm::FPClassTest classify() const { return F.classify(); }
+ APFloat::fltCategory getCategory() const { return F.getCategory(); }
ComparisonCategoryResult compare(const Floating &RHS) const {
- llvm::APFloatBase::cmpResult CmpRes = getValue().compare(RHS.getValue());
+ llvm::APFloatBase::cmpResult CmpRes = F.compare(RHS.F);
switch (CmpRes) {
case llvm::APFloatBase::cmpLessThan:
return ComparisonCategoryResult::Less;
@@ -171,130 +118,97 @@ class Floating final {
static APFloat::opStatus fromIntegral(APSInt Val,
const llvm::fltSemantics &Sem,
llvm::RoundingMode RM,
- Floating *Result) {
+ Floating &Result) {
APFloat F = APFloat(Sem);
APFloat::opStatus Status = F.convertFromAPInt(Val, Val.isSigned(), RM);
- Result->copy(F);
+ Result = Floating(F);
return Status;
}
- static void bitcastFromMemory(const std::byte *Buff,
- const llvm::fltSemantics &Sem,
- Floating *Result) {
+ static Floating bitcastFromMemory(const std::byte *Buff,
+ const llvm::fltSemantics &Sem) {
size_t Size = APFloat::semanticsSizeInBits(Sem);
llvm::APInt API(Size, true);
llvm::LoadIntFromMemory(API, (const uint8_t *)Buff, Size / 8);
- Result->copy(APFloat(Sem, API));
+
+ return Floating(APFloat(Sem, API));
}
void bitcastToMemory(std::byte *Buff) const {
- llvm::APInt API = getValue().bitcastToAPInt();
+ llvm::APInt API = F.bitcastToAPInt();
llvm::StoreIntToMemory(API, (uint8_t *)Buff, bitWidth() / 8);
}
// === Serialization support ===
size_t bytesToSerialize() const {
- return sizeof(Semantics) + (numWords() * sizeof(uint64_t));
+ return sizeof(llvm::fltSemantics *) +
+ (APFloat::semanticsSizeInBits(F.getSemantics()) / 8);
}
void serialize(std::byte *Buff) const {
- std::memcpy(Buff, &Semantics, sizeof(Semantics));
- if (singleWord()) {
- std::memcpy(Buff + sizeof(Semantics), &Val, sizeof(uint64_t));
- } else {
- std::memcpy(Buff + sizeof(Semantics), Memory,
- numWords() * sizeof(uint64_t));
- }
+ // Semantics followed by an APInt.
+ *reinterpret_cast<const llvm::fltSemantics **>(Buff) = &F.getSemantics();
+
+ llvm::APInt API = F.bitcastToAPInt();
+ llvm::StoreIntToMemory(API, (uint8_t *)(Buff + sizeof(void *)),
+ bitWidth() / 8);
}
- static llvm::APFloatBase::Semantics
- deserializeSemantics(const std::byte *Buff) {
- return *reinterpret_cast<const llvm::APFloatBase::Semantics *>(Buff);
+ static Floating deserialize(const std::byte *Buff) {
+ const llvm::fltSemantics *Sem;
+ std::memcpy((void *)&Sem, Buff, sizeof(void *));
+ return bitcastFromMemory(Buff + sizeof(void *), *Sem);
}
- static void deserialize(const std::byte *Buff, Floating *Result) {
- llvm::APFloatBase::Semantics Semantics;
- std::memcpy(&Semantics, Buff, sizeof(Semantics));
-
- unsigned BitWidth = llvm::APFloat::semanticsSizeInBits(
- llvm::APFloatBase::EnumToSemantics(Semantics));
- unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
-
- Result->Semantics = Semantics;
- if (NumWords == 1 && !ALLOCATE_ALL) {
- std::memcpy(&Result->Val, Buff + sizeof(Semantics), sizeof(uint64_t));
- } else {
- assert(Result->Memory);
- std::memcpy(Result->Memory, Buff + sizeof(Semantics),
- NumWords * sizeof(uint64_t));
- }
+ static Floating abs(const Floating &F) {
+ APFloat V = F.F;
+ if (V.isNegative())
+ V.changeSign();
+ return Floating(V);
}
// -------
static APFloat::opStatus add(const Floating &A, const Floating &B,
llvm::RoundingMode RM, Floating *R) {
- APFloat LHS = A.getValue();
- APFloat RHS = B.getValue();
-
- auto Status = LHS.add(RHS, RM);
- R->copy(LHS);
- return Status;
+ *R = Floating(A.F);
+ return R->F.add(B.F, RM);
}
static APFloat::opStatus increment(const Floating &A, llvm::RoundingMode RM,
Floating *R) {
- APFloat One(A.getSemantics(), 1);
- APFloat LHS = A.getValue();
-
- auto Status = LHS.add(One, RM);
- R->copy(LHS);
- return Status;
+ APFloat One(A.F.getSemantics(), 1);
+ *R = Floating(A.F);
+ return R->F.add(One, RM);
}
static APFloat::opStatus sub(const Floating &A, const Floating &B,
llvm::RoundingMode RM, Floating *R) {
- APFloat LHS = A.getValue();
- APFloat RHS = B.getValue();
-
- auto Status = LHS.subtract(RHS, RM);
- R->copy(LHS);
- return Status;
+ *R = Floating(A.F);
+ return R->F.subtract(B.F, RM);
}
static APFloat::opStatus decrement(const Floating &A, llvm::RoundingMode RM,
Floating *R) {
- APFloat One(A.getSemantics(), 1);
- APFloat LHS = A.getValue();
-
- auto Status = LHS.subtract(One, RM);
- R->copy(LHS);
- return Status;
+ APFloat One(A.F.getSemantics(), 1);
+ *R = Floating(A.F);
+ return R->F.subtract(One, RM);
}
static APFloat::opStatus mul(const Floating &A, const Floating &B,
llvm::RoundingMode RM, Floating *R) {
-
- APFloat LHS = A.getValue();
- APFloat RHS = B.getValue();
-
- auto Status = LHS.multiply(RHS, RM);
- R->copy(LHS);
- return Status;
+ *R = Floating(A.F);
+ return R->F.multiply(B.F, RM);
}
static APFloat::opStatus div(const Floating &A, const Floating &B,
llvm::RoundingMode RM, Floating *R) {
- APFloat LHS = A.getValue();
- APFloat RHS = B.getValue();
-
- auto Status = LHS.divide(RHS, RM);
- R->copy(LHS);
- return Status;
+ *R = Floating(A.F);
+ return R->F.divide(B.F, RM);
}
static bool neg(const Floating &A, Floating *R) {
- R->copy(-A.getValue());
+ *R = -A;
return false;
}
};
diff --git a/clang/lib/AST/ByteCode/Integral.h b/clang/lib/AST/ByteCode/Integral.h
index af5cd2d13ecca..13fdb5369f2b7 100644
--- a/clang/lib/AST/ByteCode/Integral.h
+++ b/clang/lib/AST/ByteCode/Integral.h
@@ -99,9 +99,6 @@ template <unsigned Bits, bool Signed> class Integral final {
bool operator>=(Integral RHS) const { return V >= RHS.V; }
bool operator==(Integral RHS) const { return V == RHS.V; }
bool operator!=(Integral RHS) const { return V != RHS.V; }
- bool operator>=(unsigned RHS) const {
- return static_cast<unsigned>(V) >= RHS;
- }
bool operator>(unsigned RHS) const {
return V >= 0 && static_cast<unsigned>(V) > RHS;
diff --git a/clang/lib/AST/ByteCode/IntegralAP.h b/clang/lib/AST/ByteCode/IntegralAP.h
index 259262bdc5243..8ee08dfb5cfe7 100644
--- a/clang/lib/AST/ByteCode/IntegralAP.h
+++ b/clang/lib/AST/ByteCode/IntegralAP.h
@@ -28,19 +28,12 @@ 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 {
-public:
- union {
- uint64_t *Memory = nullptr;
- uint64_t Val;
- };
- unsigned BitWidth = 0;
+private:
friend IntegralAP<!Signed>;
+ APInt V;
template <typename T, bool InputSigned>
static T truncateCast(const APInt &V) {
@@ -59,82 +52,52 @@ template <bool Signed> class IntegralAP final {
: 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>;
- void take(uint64_t *NewMemory) {
- assert(!singleWord());
- std::memcpy(NewMemory, Memory, numWords() * sizeof(uint64_t));
- Memory = NewMemory;
- }
-
- void copy(const APInt &V) {
- assert(BitWidth == V.getBitWidth());
- assert(numWords() == V.getNumWords());
-
- 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));
- }
+ template <typename T>
+ IntegralAP(T Value, unsigned BitWidth)
+ : V(APInt(BitWidth, static_cast<uint64_t>(Value), Signed)) {}
- // Constructors.
- IntegralAP() = default;
- IntegralAP(unsigned BitWidth) : BitWidth(BitWidth) {}
- IntegralAP(uint64_t *Memory, unsigned BitWidth)
- : Memory(Memory), BitWidth(BitWidth) {}
- IntegralAP(const APInt &V)
- : IntegralAP(const_cast<uint64_t *>((const uint64_t *)V.getRawData()),
- V.getBitWidth()) {}
+ IntegralAP(APInt V) : V(V) {}
+ /// Arbitrary value for uninitialized variables.
+ IntegralAP() : IntegralAP(Signed ? -1 : 7, 3) {}
- IntegralAP operator-() const { return IntegralAP(-getValue()); }
+ IntegralAP operator-() const { return IntegralAP(-V); }
IntegralAP operator-(const IntegralAP &Other) const {
- return IntegralAP(getValue() - Other.getValue());
+ return IntegralAP(V - Other.V);
}
bool operator>(const IntegralAP &RHS) const {
if constexpr (Signed)
- return getValue().sgt(RHS.getValue());
- return getValue().ugt(RHS.getValue());
+ return V.ugt(RHS.V);
+ return V.sgt(RHS.V);
}
- bool operator>=(unsigned RHS) const {
+ bool operator>=(IntegralAP RHS) const {
if constexpr (Signed)
- return getValue().sge(RHS);
- return getValue().uge(RHS);
+ return V.uge(RHS.V);
+ return V.sge(RHS.V);
}
bool operator<(IntegralAP RHS) const {
if constexpr (Signed)
- return getValue().slt(RHS.getValue());
- return getValue().ult(RHS.getValue());
+ 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);
}
template <typename Ty, typename = std::enable_if_t<std::is_integral_v<Ty>>>
explicit operator Ty() const {
- return truncateCast<Ty, Signed>(getValue());
+ return truncateCast<Ty, Signed>(V);
}
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);
- }
- static IntegralAP from(const APInt &Value) {
- return IntegralAP<Signed>(Value);
+ return IntegralAP<Signed>(Copy);
}
template <bool InputSigned>
@@ -143,45 +106,52 @@ template <bool Signed> class IntegralAP final {
NumBits = V.bitWidth();
if constexpr (InputSigned)
- return IntegralAP<Signed>(V.getValue().sextOrTrunc(NumBits));
- return IntegralAP<Signed>(V.getValue().zextOrTrunc(NumBits));
+ 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 BitWidth; }
- constexpr unsigned numWords() const { return APInt::getNumWords(BitWidth); }
- constexpr bool singleWord() const { return numWords() == 1; }
+ constexpr unsigned bitWidth() const { return V.getBitWidth(); }
APSInt toAPSInt(unsigned Bits = 0) const {
if (Bits == 0)
Bits = bitWidth();
- APInt V = getValue();
if constexpr (Signed)
- return APSInt(getValue().sext(Bits), !Signed);
+ return APSInt(V.sext(Bits), !Signed);
else
- return APSInt(getValue().zext(Bits), !Signed);
+ return APSInt(V.zext(Bits), !Signed);
}
APValue toAPValue(const ASTContext &) const { return APValue(toAPSInt()); }
- bool isZero() const { return getValue().isZero(); }
+ bool isZero() const { return V.isZero(); }
bool isPositive() const {
if constexpr (Signed)
- return getValue().isNonNegative();
+ return V.isNonNegative();
return true;
}
bool isNegative() const {
if constexpr (Signed)
- return !getValue().isNonNegative();
+ return !V.isNonNegative();
return false;
}
- bool isMin() const { return getValue().isMinValue(); }
- bool isMax() const { return getValue().isMaxValue(); }
+ bool isMin() const { return V.isMinValue(); }
+ bool isMax() const { return V.isMaxValue(); }
static constexpr bool isSigned() { return Signed; }
- bool isMinusOne() const { return Signed && getValue().isAllOnes(); }
+ bool isMinusOne() const { return Signed && V == -1; }
- unsigned countLeadingZeros() const { return getValue().countl_zero(); }
+ unsigned countLeadingZeros() const { return V.countl_zero(); }
- void print(llvm::raw_ostream &OS) const { getValue().print(OS, Signed); }
+ void print(llvm::raw_ostream &OS) const { V.print(OS, Signed);}
std::string toDiagnosticString(const ASTContext &Ctx) const {
std::string NameStr;
llvm::raw_string_ostream OS(NameStr);
@@ -191,64 +161,53 @@ template <bool Signed> class IntegralAP final {
IntegralAP truncate(unsigned BitWidth) const {
if constexpr (Signed)
- return IntegralAP(
- getValue().trunc(BitWidth).sextOrTrunc(this->bitWidth()));
+ return IntegralAP(V.trunc(BitWidth).sextOrTrunc(this->bitWidth()));
else
- return IntegralAP(
- getValue().trunc(BitWidth).zextOrTrunc(this->bitWidth()));
+ return IntegralAP(V.trunc(BitWidth).zextOrTrunc(this->bitWidth()));
}
IntegralAP<false> toUnsigned() const {
- return IntegralAP<false>(Memory, BitWidth);
+ APInt Copy = V;
+ return IntegralAP<false>(Copy);
}
void bitcastToMemory(std::byte *Dest) const {
- llvm::StoreIntToMemory(getValue(), (uint8_t *)Dest, bitWidth() / 8);
+ llvm::StoreIntToMemory(V, (uint8_t *)Dest, bitWidth() / 8);
}
static IntegralAP bitcastFromMemory(const std::byte *Src, unsigned BitWidth) {
- // FIXME: Remove this.
APInt V(BitWidth, static_cast<uint64_t>(0), Signed);
llvm::LoadIntFromMemory(V, (const uint8_t *)Src, BitWidth / 8);
return IntegralAP(V);
}
- 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);
- 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 (V1.slt(V2))
+ if (V.slt(RHS.V))
return ComparisonCategoryResult::Less;
- if (V1.sgt(V2))
+ if (V.sgt(RHS.V))
return ComparisonCategoryResult::Greater;
return ComparisonCategoryResult::Equal;
}
assert(!Signed);
- if (V1.ult(V2))
+ if (V.ult(RHS.V))
return ComparisonCategoryResult::Less;
- if (V1.ugt(V2))
+ if (V.ugt(RHS.V))
return ComparisonCategoryResult::Greater;
return ComparisonCategoryResult::Equal;
}
static bool increment(IntegralAP A, IntegralAP *R) {
- APSInt One(APInt(A.bitWidth(), 1ull, Signed), !Signed);
- return add(A, IntegralAP<Signed>(One), A.bitWidth() + 1, R);
+ IntegralAP<Signed> One(1, A.bitWidth());
+ return add(A, One, A.bitWidth() + 1, R);
}
static bool decrement(IntegralAP A, IntegralAP *R) {
- APSInt One(APInt(A.bitWidth(), 1ull, Signed), !Signed);
- return sub(A, IntegralAP<Signed>(One), A.bitWidth() + 1, R);
+ IntegralAP<Signed> One(1, A.bitWidth());
+ return sub(A, One, A.bitWidth() + 1, R);
}
static bool add(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) {
@@ -265,95 +224,87 @@ template <bool Signed> class IntegralAP final {
static bool rem(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) {
if constexpr (Signed)
- R->copy(A.getValue().srem(B.getValue()));
+ *R = IntegralAP(A.V.srem(B.V));
else
- R->copy(A.getValue().urem(B.getValue()));
+ *R = IntegralAP(A.V.urem(B.V));
return false;
}
static bool div(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) {
if constexpr (Signed)
- R->copy(A.getValue().sdiv(B.getValue()));
+ *R = IntegralAP(A.V.sdiv(B.V));
else
- R->copy(A.getValue().udiv(B.getValue()));
+ *R = IntegralAP(A.V.udiv(B.V));
return false;
}
static bool bitAnd(IntegralAP A, IntegralAP B, unsigned OpBits,
IntegralAP *R) {
- R->copy(A.getValue() & B.getValue());
+ *R = IntegralAP(A.V & B.V);
return false;
}
static bool bitOr(IntegralAP A, IntegralAP B, unsigned OpBits,
IntegralAP *R) {
- R->copy(A.getValue() | B.getValue());
+ *R = IntegralAP(A.V | B.V);
return false;
}
static bool bitXor(IntegralAP A, IntegralAP B, unsigned OpBits,
IntegralAP *R) {
- R->copy(A.getValue() ^ B.getValue());
+ *R = IntegralAP(A.V ^ B.V);
return false;
}
static bool neg(const IntegralAP &A, IntegralAP *R) {
- APInt AI = A.getValue();
+ APInt AI = A.V;
AI.negate();
- R->copy(AI);
+ *R = IntegralAP(AI);
return false;
}
static bool comp(IntegralAP A, IntegralAP *R) {
- R->copy(~A.getValue());
+ *R = IntegralAP(~A.V);
return false;
}
static void shiftLeft(const IntegralAP A, const IntegralAP B, unsigned OpBits,
IntegralAP *R) {
- *R = IntegralAP(A.getValue().shl(B.getValue().getZExtValue()));
+ *R = IntegralAP(A.V.shl(B.V.getZExtValue()));
}
static void shiftRight(const IntegralAP A, const IntegralAP B,
unsigned OpBits, IntegralAP *R) {
- unsigned ShiftAmount = B.getValue().getZExtValue();
+ unsigned ShiftAmount = B.V.getZExtValue();
if constexpr (Signed)
- R->copy(A.getValue().ashr(ShiftAmount));
+ *R = IntegralAP(A.V.ashr(ShiftAmount));
else
- R->copy(A.getValue().lshr(ShiftAmount));
+ *R = IntegralAP(A.V.lshr(ShiftAmount));
}
// === Serialization support ===
size_t bytesToSerialize() const {
- assert(BitWidth != 0);
- uint32_t NumWords = llvm::APInt::getNumWords(bitWidth());
- return sizeof(uint64_t) + (NumWords * sizeof(uint64_t));
+ // 4 bytes for the BitWidth followed by N bytes for the actual APInt.
+ return sizeof(uint32_t) + (V.getBitWidth() / CHAR_BIT);
}
void serialize(std::byte *Buff) const {
- uint64_t NumWords = llvm::APInt::getNumWords(bitWidth());
- std::memcpy(Buff, &BitWidth, sizeof(uint64_t));
- if (singleWord())
- std::memcpy(Buff + sizeof(uint64_t), &Val, NumWords * sizeof(uint64_t));
- else
- std::memcpy(Buff + sizeof(uint64_t), Memory, NumWords * sizeof(uint64_t));
- }
+ assert(V.getBitWidth() < std::numeric_limits<uint8_t>::max());
+ uint32_t BitWidth = V.getBitWidth();
- static uint32_t deserializeSize(const std::byte *Buff) {
- return *reinterpret_cast<const uint64_t *>(Buff);
+ std::memcpy(Buff, &BitWidth, sizeof(uint32_t));
+ llvm::StoreIntToMemory(V, (uint8_t *)(Buff + sizeof(uint32_t)),
+ BitWidth / CHAR_BIT);
}
- static void deserialize(const std::byte *Buff, IntegralAP<Signed> *Result) {
- uint32_t BitWidth = Result->BitWidth;
- uint32_t NumWords = llvm::APInt::getNumWords(BitWidth);
- assert(BitWidth == Result->BitWidth);
- assert(Result->Memory);
+ 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));
- if (NumWords == 1)
- std::memcpy(&Result->Val, Buff + sizeof(uint64_t), sizeof(uint64_t));
- else
- std::memcpy(Result->Memory, Buff + sizeof(uint64_t),
- NumWords * sizeof(uint64_t));
+ llvm::LoadIntFromMemory(Val.V, (const uint8_t *)Buff + sizeof(uint32_t),
+ BitWidth / CHAR_BIT);
+ return Val;
}
private:
@@ -361,7 +312,7 @@ template <bool Signed> class IntegralAP final {
static bool CheckAddSubMulUB(const IntegralAP &A, const IntegralAP &B,
unsigned BitWidth, IntegralAP *R) {
if constexpr (!Signed) {
- R->copy(Op<APInt>{}(A.getValue(), B.getValue()));
+ R->V = Op<APInt>{}(A.V, B.V);
return false;
}
@@ -369,7 +320,7 @@ template <bool Signed> class IntegralAP final {
const APSInt &RHS = B.toAPSInt();
APSInt Value = Op<APSInt>{}(LHS.extend(BitWidth), RHS.extend(BitWidth));
APSInt Result = Value.trunc(LHS.getBitWidth());
- R->copy(Result);
+ R->V = Result;
return Result.extend(BitWidth) != Value;
}
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 1e2032feabb64..5c8abffb3a99d 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -1935,10 +1935,8 @@ bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
if (!CheckPointerToIntegralCast(S, OpPC, Ptr, BitWidth))
return false;
- auto Result = S.allocAP<IntegralAP<false>>(BitWidth);
- Result.copy(APInt(BitWidth, Ptr.getIntegerRepresentation()));
-
- S.Stk.push<IntegralAP<false>>(Result);
+ S.Stk.push<IntegralAP<false>>(
+ IntegralAP<false>::from(Ptr.getIntegerRepresentation(), BitWidth));
return true;
}
@@ -1948,10 +1946,8 @@ bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
if (!CheckPointerToIntegralCast(S, OpPC, Ptr, BitWidth))
return false;
- auto Result = S.allocAP<IntegralAP<true>>(BitWidth);
- Result.copy(APInt(BitWidth, Ptr.getIntegerRepresentation()));
-
- S.Stk.push<IntegralAP<true>>(Result);
+ S.Stk.push<IntegralAP<true>>(
+ IntegralAP<true>::from(Ptr.getIntegerRepresentation(), BitWidth));
return true;
}
@@ -2057,100 +2053,6 @@ bool arePotentiallyOverlappingStringLiterals(const Pointer &LHS,
return Shorter == Longer.take_front(Shorter.size());
}
-static void copyPrimitiveMemory(InterpState &S, const Pointer &Ptr,
- PrimType T) {
-
- if (T == PT_IntAPS) {
- auto &Val = Ptr.deref<IntegralAP<true>>();
- if (!Val.singleWord()) {
- uint64_t *NewMemory = new (S.P) uint64_t[Val.numWords()];
- Val.take(NewMemory);
- }
- } else if (T == PT_IntAP) {
- auto &Val = Ptr.deref<IntegralAP<false>>();
- if (!Val.singleWord()) {
- uint64_t *NewMemory = new (S.P) uint64_t[Val.numWords()];
- Val.take(NewMemory);
- }
- } else if (T == PT_Float) {
- auto &Val = Ptr.deref<Floating>();
- if (!Val.singleWord()) {
- uint64_t *NewMemory = new (S.P) uint64_t[Val.numWords()];
- Val.take(NewMemory);
- }
- }
-}
-
-template <typename T>
-static void copyPrimitiveMemory(InterpState &S, const Pointer &Ptr) {
- assert(needsAlloc<T>());
- auto &Val = Ptr.deref<T>();
- if (!Val.singleWord()) {
- uint64_t *NewMemory = new (S.P) uint64_t[Val.numWords()];
- Val.take(NewMemory);
- }
-}
-
-static void finishGlobalRecurse(InterpState &S, const Pointer &Ptr) {
- if (const Record *R = Ptr.getRecord()) {
- for (const Record::Field &Fi : R->fields()) {
- if (Fi.Desc->isPrimitive()) {
- TYPE_SWITCH_ALLOC(Fi.Desc->getPrimType(), {
- copyPrimitiveMemory<T>(S, Ptr.atField(Fi.Offset));
- });
- copyPrimitiveMemory(S, Ptr.atField(Fi.Offset), Fi.Desc->getPrimType());
- } else
- finishGlobalRecurse(S, Ptr.atField(Fi.Offset));
- }
- return;
- }
-
- if (const Descriptor *D = Ptr.getFieldDesc(); D && D->isArray()) {
- unsigned NumElems = D->getNumElems();
- if (NumElems == 0)
- return;
-
- if (D->isPrimitiveArray()) {
- PrimType PT = D->getPrimType();
- if (!needsAlloc(PT))
- return;
- assert(NumElems >= 1);
- const Pointer EP = Ptr.atIndex(0);
- bool AllSingleWord = true;
- TYPE_SWITCH_ALLOC(PT, {
- if (!EP.deref<T>().singleWord()) {
- copyPrimitiveMemory<T>(S, EP);
- AllSingleWord = false;
- }
- });
- if (AllSingleWord)
- return;
- for (unsigned I = 1; I != D->getNumElems(); ++I) {
- const Pointer EP = Ptr.atIndex(I);
- copyPrimitiveMemory(S, EP, PT);
- }
- } else {
- assert(D->isCompositeArray());
- for (unsigned I = 0; I != D->getNumElems(); ++I) {
- const Pointer EP = Ptr.atIndex(I).narrow();
- finishGlobalRecurse(S, EP);
- }
- }
- }
-}
-
-bool FinishInitGlobal(InterpState &S, CodePtr OpPC) {
- const Pointer &Ptr = S.Stk.pop<Pointer>();
-
- finishGlobalRecurse(S, Ptr);
- if (Ptr.canBeInitialized()) {
- Ptr.initialize();
- Ptr.activate();
- }
-
- return true;
-}
-
// https://github.com/llvm/llvm-project/issues/102513
#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
#pragma optimize("", off)
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 66d3e6d79e8b2..ae3d4a441a799 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -189,7 +189,7 @@ bool CheckShift(InterpState &S, CodePtr OpPC, const LT &LHS, const RT &RHS,
// C++11 [expr.shift]p1: Shift width must be less than the bit width of
// the shifted type.
- if (Bits > 1 && RHS >= Bits) {
+ if (Bits > 1 && RHS >= RT::from(Bits, RHS.bitWidth())) {
const Expr *E = S.Current->getExpr(OpPC);
const APSInt Val = RHS.toAPSInt();
QualType Ty = E->getType();
@@ -370,9 +370,6 @@ bool AddSubMulHelper(InterpState &S, CodePtr OpPC, unsigned Bits, const T &LHS,
const T &RHS) {
// Fast path - add the numbers with fixed width.
T Result;
- if constexpr (needsAlloc<T>())
- Result = S.allocAP<T>(LHS.bitWidth());
-
if (!OpFW(LHS, RHS, Bits, &Result)) {
S.Stk.push<T>(Result);
return true;
@@ -411,7 +408,6 @@ bool Add(InterpState &S, CodePtr OpPC) {
const T &RHS = S.Stk.pop<T>();
const T &LHS = S.Stk.pop<T>();
const unsigned Bits = RHS.bitWidth() + 1;
-
return AddSubMulHelper<T, T::add, std::plus>(S, OpPC, Bits, LHS, RHS);
}
@@ -427,7 +423,7 @@ inline bool Addf(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
const Floating &LHS = S.Stk.pop<Floating>();
FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
- Floating Result = S.allocFloat(LHS.getSemantics());
+ Floating Result;
auto Status = Floating::add(LHS, RHS, getRoundingMode(FPO), &Result);
S.Stk.push<Floating>(Result);
return CheckFloatResult(S, OpPC, Result, Status, FPO);
@@ -438,7 +434,6 @@ bool Sub(InterpState &S, CodePtr OpPC) {
const T &RHS = S.Stk.pop<T>();
const T &LHS = S.Stk.pop<T>();
const unsigned Bits = RHS.bitWidth() + 1;
-
return AddSubMulHelper<T, T::sub, std::minus>(S, OpPC, Bits, LHS, RHS);
}
@@ -447,7 +442,7 @@ inline bool Subf(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
const Floating &LHS = S.Stk.pop<Floating>();
FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
- Floating Result = S.allocFloat(LHS.getSemantics());
+ Floating Result;
auto Status = Floating::sub(LHS, RHS, getRoundingMode(FPO), &Result);
S.Stk.push<Floating>(Result);
return CheckFloatResult(S, OpPC, Result, Status, FPO);
@@ -458,7 +453,6 @@ bool Mul(InterpState &S, CodePtr OpPC) {
const T &RHS = S.Stk.pop<T>();
const T &LHS = S.Stk.pop<T>();
const unsigned Bits = RHS.bitWidth() * 2;
-
return AddSubMulHelper<T, T::mul, std::multiplies>(S, OpPC, Bits, LHS, RHS);
}
@@ -467,10 +461,8 @@ inline bool Mulf(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
const Floating &LHS = S.Stk.pop<Floating>();
FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
- Floating Result = S.allocFloat(LHS.getSemantics());
-
+ Floating Result;
auto Status = Floating::mul(LHS, RHS, getRoundingMode(FPO), &Result);
-
S.Stk.push<Floating>(Result);
return CheckFloatResult(S, OpPC, Result, Status, FPO);
}
@@ -492,14 +484,9 @@ inline bool Mulc(InterpState &S, CodePtr OpPC) {
HandleComplexComplexMul(A, B, C, D, ResR, ResI);
// Copy into the result.
- Floating RA = S.allocFloat(A.getSemantics());
- RA.copy(ResR);
- Result.atIndex(0).deref<Floating>() = RA; // Floating(ResR);
+ Result.atIndex(0).deref<Floating>() = Floating(ResR);
Result.atIndex(0).initialize();
-
- Floating RI = S.allocFloat(A.getSemantics());
- RI.copy(ResI);
- Result.atIndex(1).deref<Floating>() = RI; // Floating(ResI);
+ Result.atIndex(1).deref<Floating>() = Floating(ResI);
Result.atIndex(1).initialize();
Result.initialize();
} else {
@@ -552,20 +539,10 @@ inline bool Divc(InterpState &S, CodePtr OpPC) {
HandleComplexComplexDiv(A, B, C, D, ResR, ResI);
// Copy into the result.
- // Result.atIndex(0).deref<Floating>() = Floating(ResR);
- // Result.atIndex(0).initialize();
- // Result.atIndex(1).deref<Floating>() = Floating(ResI);
- // Result.atIndex(1).initialize();
-
- Floating RA = S.allocFloat(A.getSemantics());
- RA.copy(ResR);
- Result.atIndex(0).deref<Floating>() = RA; // Floating(ResR);
+ Result.atIndex(0).deref<Floating>() = Floating(ResR);
Result.atIndex(0).initialize();
-
- Floating RI = S.allocFloat(A.getSemantics());
- RI.copy(ResI);
- Result.atIndex(1).deref<Floating>() = RI; // Floating(ResI);
-
+ Result.atIndex(1).deref<Floating>() = Floating(ResI);
+ Result.atIndex(1).initialize();
Result.initialize();
} else {
// Integer element type.
@@ -631,12 +608,9 @@ template <PrimType Name, class T = typename PrimConv<Name>::T>
bool BitAnd(InterpState &S, CodePtr OpPC) {
const T &RHS = S.Stk.pop<T>();
const T &LHS = S.Stk.pop<T>();
- unsigned Bits = RHS.bitWidth();
+ unsigned Bits = RHS.bitWidth();
T Result;
- if constexpr (needsAlloc<T>())
- Result = S.allocAP<T>(Bits);
-
if (!T::bitAnd(LHS, RHS, Bits, &Result)) {
S.Stk.push<T>(Result);
return true;
@@ -651,12 +625,9 @@ template <PrimType Name, class T = typename PrimConv<Name>::T>
bool BitOr(InterpState &S, CodePtr OpPC) {
const T &RHS = S.Stk.pop<T>();
const T &LHS = S.Stk.pop<T>();
- unsigned Bits = RHS.bitWidth();
+ unsigned Bits = RHS.bitWidth();
T Result;
- if constexpr (needsAlloc<T>())
- Result = S.allocAP<T>(Bits);
-
if (!T::bitOr(LHS, RHS, Bits, &Result)) {
S.Stk.push<T>(Result);
return true;
@@ -673,11 +644,7 @@ bool BitXor(InterpState &S, CodePtr OpPC) {
const T &LHS = S.Stk.pop<T>();
unsigned Bits = RHS.bitWidth();
-
T Result;
- if constexpr (needsAlloc<T>())
- Result = S.allocAP<T>(Bits);
-
if (!T::bitXor(LHS, RHS, Bits, &Result)) {
S.Stk.push<T>(Result);
return true;
@@ -692,15 +659,12 @@ template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Rem(InterpState &S, CodePtr OpPC) {
const T &RHS = S.Stk.pop<T>();
const T &LHS = S.Stk.pop<T>();
- const unsigned Bits = RHS.bitWidth() * 2;
if (!CheckDivRem(S, OpPC, LHS, RHS))
return false;
+ const unsigned Bits = RHS.bitWidth() * 2;
T Result;
- if constexpr (needsAlloc<T>())
- Result = S.allocAP<T>(LHS.bitWidth());
-
if (!T::rem(LHS, RHS, Bits, &Result)) {
S.Stk.push<T>(Result);
return true;
@@ -715,15 +679,12 @@ template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Div(InterpState &S, CodePtr OpPC) {
const T &RHS = S.Stk.pop<T>();
const T &LHS = S.Stk.pop<T>();
- const unsigned Bits = RHS.bitWidth() * 2;
if (!CheckDivRem(S, OpPC, LHS, RHS))
return false;
+ const unsigned Bits = RHS.bitWidth() * 2;
T Result;
- if constexpr (needsAlloc<T>())
- Result = S.allocAP<T>(LHS.bitWidth());
-
if (!T::div(LHS, RHS, Bits, &Result)) {
S.Stk.push<T>(Result);
return true;
@@ -746,10 +707,8 @@ inline bool Divf(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
return false;
FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
-
- Floating Result = S.allocFloat(LHS.getSemantics());
+ Floating Result;
auto Status = Floating::div(LHS, RHS, getRoundingMode(FPO), &Result);
-
S.Stk.push<Floating>(Result);
return CheckFloatResult(S, OpPC, Result, Status, FPO);
}
@@ -771,44 +730,31 @@ inline bool Inv(InterpState &S, CodePtr OpPC) {
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Neg(InterpState &S, CodePtr OpPC) {
const T &Value = S.Stk.pop<T>();
+ T Result;
- if constexpr (std::is_same_v<T, Floating>) {
- T Result = S.allocFloat(Value.getSemantics());
-
- if (!T::neg(Value, &Result)) {
- S.Stk.push<T>(Result);
- return true;
- }
- return false;
- } else {
- T Result;
- if constexpr (needsAlloc<T>())
- Result = S.allocAP<T>(Value.bitWidth());
-
- if (!T::neg(Value, &Result)) {
- S.Stk.push<T>(Result);
- return true;
- }
-
- assert(isIntegralType(Name) &&
- "don't expect other types to fail at constexpr negation");
+ if (!T::neg(Value, &Result)) {
S.Stk.push<T>(Result);
+ return true;
+ }
- APSInt NegatedValue = -Value.toAPSInt(Value.bitWidth() + 1);
- if (S.checkingForUndefinedBehavior()) {
- const Expr *E = S.Current->getExpr(OpPC);
- QualType Type = E->getType();
- SmallString<32> Trunc;
- NegatedValue.trunc(Result.bitWidth())
- .toString(Trunc, 10, Result.isSigned(), /*formatAsCLiteral=*/false,
- /*UpperCase=*/true, /*InsertSeparators=*/true);
- S.report(E->getExprLoc(), diag::warn_integer_constant_overflow)
- << Trunc << Type << E->getSourceRange();
- return true;
- }
+ assert(isIntegralType(Name) &&
+ "don't expect other types to fail at constexpr negation");
+ S.Stk.push<T>(Result);
- return handleOverflow(S, OpPC, NegatedValue);
+ APSInt NegatedValue = -Value.toAPSInt(Value.bitWidth() + 1);
+ if (S.checkingForUndefinedBehavior()) {
+ const Expr *E = S.Current->getExpr(OpPC);
+ QualType Type = E->getType();
+ SmallString<32> Trunc;
+ NegatedValue.trunc(Result.bitWidth())
+ .toString(Trunc, 10, Result.isSigned(), /*formatAsCLiteral=*/false,
+ /*UpperCase=*/true, /*InsertSeparators=*/true);
+ S.report(E->getExprLoc(), diag::warn_integer_constant_overflow)
+ << Trunc << Type << E->getSourceRange();
+ return true;
}
+
+ return handleOverflow(S, OpPC, NegatedValue);
}
enum class PushVal : bool {
@@ -837,8 +783,6 @@ bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
const T &Value = Ptr.deref<T>();
T Result;
- if constexpr (needsAlloc<T>())
- Result = S.allocAP<T>(Value.bitWidth());
if constexpr (DoPush == PushVal::Yes)
S.Stk.push<T>(Value);
@@ -946,6 +890,7 @@ bool PreDec(InterpState &S, CodePtr OpPC, bool CanOverflow) {
const Pointer &Ptr = S.Stk.peek<Pointer>();
if (!CheckLoad(S, OpPC, Ptr, AK_Decrement))
return false;
+
return IncDecHelper<T, IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr, CanOverflow);
}
@@ -953,7 +898,7 @@ template <IncDecOp Op, PushVal DoPush>
bool IncDecFloatHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
uint32_t FPOI) {
Floating Value = Ptr.deref<Floating>();
- Floating Result = S.allocFloat(Value.getSemantics());
+ Floating Result;
if constexpr (DoPush == PushVal::Yes)
S.Stk.push<Floating>(Value);
@@ -1007,15 +952,12 @@ inline bool DecfPop(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Comp(InterpState &S, CodePtr OpPC) {
const T &Val = S.Stk.pop<T>();
-
T Result;
- if constexpr (needsAlloc<T>())
- Result = S.allocAP<T>(Val.bitWidth());
-
if (!T::comp(Val, &Result)) {
S.Stk.push<T>(Result);
return true;
}
+
return false;
}
@@ -1383,23 +1325,10 @@ bool Flip(InterpState &S, CodePtr OpPC) {
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Const(InterpState &S, CodePtr OpPC, const T &Arg) {
- if constexpr (needsAlloc<T>()) {
- T Result = S.allocAP<T>(Arg.bitWidth());
- Result.copy(Arg.toAPSInt());
- S.Stk.push<T>(Result);
- return true;
- }
S.Stk.push<T>(Arg);
return true;
}
-inline bool ConstFloat(InterpState &S, CodePtr OpPC, const Floating &F) {
- Floating Result = S.allocFloat(F.getSemantics());
- Result.copy(F.getAPFloat());
- S.Stk.push<Floating>(Result);
- return true;
-}
-
//===----------------------------------------------------------------------===//
// Get/Set Local/Param/Global/This
//===----------------------------------------------------------------------===//
@@ -1554,24 +1483,7 @@ bool SetGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool InitGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
const Pointer &P = S.P.getGlobal(I);
-
P.deref<T>() = S.Stk.pop<T>();
-
- if constexpr (std::is_same_v<T, Floating>) {
- auto &Val = P.deref<Floating>();
- if (!Val.singleWord()) {
- uint64_t *NewMemory = new (S.P) uint64_t[Val.numWords()];
- Val.take(NewMemory);
- }
-
- } else if constexpr (needsAlloc<T>()) {
- auto &Val = P.deref<T>();
- if (!Val.singleWord()) {
- uint64_t *NewMemory = new (S.P) uint64_t[Val.numWords()];
- Val.take(NewMemory);
- }
- }
-
P.initialize();
return true;
}
@@ -1673,22 +1585,7 @@ bool InitBitField(InterpState &S, CodePtr OpPC, const Record::Field *F) {
assert(F->isBitField());
const T &Value = S.Stk.pop<T>();
const Pointer &Field = S.Stk.peek<Pointer>().atField(F->Offset);
-
- if constexpr (needsAlloc<T>()) {
- T Result = S.allocAP<T>(Value.bitWidth());
- if (T::isSigned())
- Result.copy(Value.toAPSInt()
- .trunc(F->Decl->getBitWidthValue())
- .sextOrTrunc(Value.bitWidth()));
- else
- Result.copy(Value.toAPSInt()
- .trunc(F->Decl->getBitWidthValue())
- .zextOrTrunc(Value.bitWidth()));
-
- Field.deref<T>() = Result;
- } else {
- Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue());
- }
+ Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue());
Field.activate();
Field.initialize();
return true;
@@ -1868,8 +1765,6 @@ inline bool FinishInit(InterpState &S, CodePtr OpPC) {
return true;
}
-bool FinishInitGlobal(InterpState &S, CodePtr OpPC);
-
inline bool Dump(InterpState &S, CodePtr OpPC) {
S.Stk.dump();
return true;
@@ -2376,8 +2271,7 @@ template <PrimType TIn, PrimType TOut> bool Cast(InterpState &S, CodePtr OpPC) {
inline bool CastFP(InterpState &S, CodePtr OpPC, const llvm::fltSemantics *Sem,
llvm::RoundingMode RM) {
Floating F = S.Stk.pop<Floating>();
- Floating Result = S.allocFloat(*Sem);
- F.toSemantics(Sem, RM, &Result);
+ Floating Result = F.toSemantics(Sem, RM);
S.Stk.push<Floating>(Result);
return true;
}
@@ -2401,25 +2295,15 @@ inline bool CastFixedPoint(InterpState &S, CodePtr OpPC, uint32_t FPS) {
/// to know what bitwidth the result should be.
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool CastAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
- auto Result = S.allocAP<IntegralAP<false>>(BitWidth);
- // Copy data.
- {
- APInt Source = S.Stk.pop<T>().toAPSInt().extOrTrunc(BitWidth);
- Result.copy(Source);
- }
- S.Stk.push<IntegralAP<false>>(Result);
+ S.Stk.push<IntegralAP<false>>(
+ IntegralAP<false>::from(S.Stk.pop<T>(), BitWidth));
return true;
}
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool CastAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
- auto Result = S.allocAP<IntegralAP<true>>(BitWidth);
- // Copy data.
- {
- APInt Source = S.Stk.pop<T>().toAPSInt().extOrTrunc(BitWidth);
- Result.copy(Source);
- }
- S.Stk.push<IntegralAP<true>>(Result);
+ S.Stk.push<IntegralAP<true>>(
+ IntegralAP<true>::from(S.Stk.pop<T>(), BitWidth));
return true;
}
@@ -2428,11 +2312,11 @@ bool CastIntegralFloating(InterpState &S, CodePtr OpPC,
const llvm::fltSemantics *Sem, uint32_t FPOI) {
const T &From = S.Stk.pop<T>();
APSInt FromAP = From.toAPSInt();
+ Floating Result;
FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
- Floating Result = S.allocFloat(*Sem);
auto Status =
- Floating::fromIntegral(FromAP, *Sem, getRoundingMode(FPO), &Result);
+ Floating::fromIntegral(FromAP, *Sem, getRoundingMode(FPO), Result);
S.Stk.push<Floating>(Result);
return CheckFloatResult(S, OpPC, Result, Status, FPO);
@@ -2481,12 +2365,7 @@ static inline bool CastFloatingIntegralAP(InterpState &S, CodePtr OpPC,
return handleOverflow(S, OpPC, F.getAPFloat());
FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
-
- auto ResultAP = S.allocAP<IntegralAP<false>>(BitWidth);
- ResultAP.copy(Result);
-
- S.Stk.push<IntegralAP<false>>(ResultAP);
-
+ S.Stk.push<IntegralAP<true>>(IntegralAP<true>(Result));
return CheckFloatResult(S, OpPC, F, Status, FPO);
}
@@ -2502,12 +2381,7 @@ static inline bool CastFloatingIntegralAPS(InterpState &S, CodePtr OpPC,
return handleOverflow(S, OpPC, F.getAPFloat());
FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
-
- auto ResultAP = S.allocAP<IntegralAP<true>>(BitWidth);
- ResultAP.copy(Result);
-
- S.Stk.push<IntegralAP<true>>(ResultAP);
-
+ S.Stk.push<IntegralAP<true>>(IntegralAP<true>(Result));
return CheckFloatResult(S, OpPC, F, Status, FPO);
}
@@ -2567,9 +2441,8 @@ static inline bool CastFloatingFixedPoint(InterpState &S, CodePtr OpPC,
static inline bool CastFixedPointFloating(InterpState &S, CodePtr OpPC,
const llvm::fltSemantics *Sem) {
const auto &Fixed = S.Stk.pop<FixedPoint>();
- Floating Result = S.allocFloat(*Sem);
- Result.copy(Fixed.toFloat(Sem));
- S.Stk.push<Floating>(Result);
+
+ S.Stk.push<Floating>(Fixed.toFloat(Sem));
return true;
}
@@ -2633,18 +2506,12 @@ bool Zero(InterpState &S, CodePtr OpPC) {
}
static inline bool ZeroIntAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
- auto Result = S.allocAP<IntegralAP<false>>(BitWidth);
- if (!Result.singleWord())
- std::memset(Result.Memory, 0, Result.numWords() * sizeof(uint64_t));
- S.Stk.push<IntegralAP<false>>(Result);
+ S.Stk.push<IntegralAP<false>>(IntegralAP<false>::zero(BitWidth));
return true;
}
static inline bool ZeroIntAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
- auto Result = S.allocAP<IntegralAP<true>>(BitWidth);
- if (!Result.singleWord())
- std::memset(Result.Memory, 0, Result.numWords() * sizeof(uint64_t));
- S.Stk.push<IntegralAP<true>>(Result);
+ S.Stk.push<IntegralAP<true>>(IntegralAP<true>::zero(BitWidth));
return true;
}
@@ -2711,9 +2578,7 @@ inline bool RVOPtr(InterpState &S, CodePtr OpPC) {
//===----------------------------------------------------------------------===//
template <class LT, class RT, ShiftDir Dir>
-inline bool DoShift(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS,
- LT *Result) {
-
+inline bool DoShift(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS) {
const unsigned Bits = LHS.bitWidth();
// OpenCL 6.3j: shift values are effectively % word size of LHS.
@@ -2731,7 +2596,7 @@ inline bool DoShift(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS,
RHS = -RHS;
return DoShift<LT, RT,
Dir == ShiftDir::Left ? ShiftDir::Right : ShiftDir::Left>(
- S, OpPC, LHS, RHS, Result);
+ S, OpPC, LHS, RHS);
}
if (!CheckShift<Dir>(S, OpPC, LHS, RHS, Bits))
@@ -2779,7 +2644,6 @@ inline bool DoShift(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS,
// Do the shift on potentially signed LT, then convert to unsigned type.
LT A;
LT::shiftRight(LHS, LT::from(RHS, Bits), Bits, &A);
- // LT::shiftRight(LHS, LT(RHSTemp), Bits, &A);
R = LT::AsUnsigned::from(A);
}
}
@@ -2788,48 +2652,6 @@ inline bool DoShift(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS,
return true;
}
-/// A version of DoShift that works on IntegralAP.
-template <class LT, class RT, ShiftDir Dir>
-inline bool DoShiftAP(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS,
- LT *Result) {
- const unsigned Bits = LHS.bitWidth();
- const APSInt &LHSAP = LHS.toAPSInt();
- APSInt RHSAP = RHS.toAPSInt();
-
- // OpenCL 6.3j: shift values are effectively % word size of LHS.
- if (S.getLangOpts().OpenCL)
- RHSAP &= APSInt(llvm::APInt(RHSAP.getBitWidth(),
- static_cast<uint64_t>(LHSAP.getBitWidth() - 1)),
- RHSAP.isUnsigned());
-
- if (RHS.isNegative()) {
- // During constant-folding, a negative shift is an opposite shift. Such a
- // shift is not a constant expression.
- const SourceInfo &Loc = S.Current->getSource(OpPC);
- S.CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS.toAPSInt();
- if (!S.noteUndefinedBehavior())
- return false;
- RHS = -RHS;
- return DoShiftAP<LT, RT,
- Dir == ShiftDir::Left ? ShiftDir::Right : ShiftDir::Left>(
- S, OpPC, LHS, RHS, Result);
- }
-
- if (!CheckShift<Dir>(S, OpPC, LHS, RHS, Bits))
- return false;
-
- if constexpr (Dir == ShiftDir::Left) {
- unsigned SA = (unsigned)RHSAP.getLimitedValue(LHS.bitWidth() - 1);
- Result->copy(LHSAP << SA);
- } else {
- unsigned SA = (unsigned)RHSAP.getLimitedValue(LHS.bitWidth() - 1);
- Result->copy(LHSAP >> SA);
- }
-
- S.Stk.push<LT>(*Result);
- return true;
-}
-
template <PrimType NameL, PrimType NameR>
inline bool Shr(InterpState &S, CodePtr OpPC) {
using LT = typename PrimConv<NameL>::T;
@@ -2837,13 +2659,7 @@ inline bool Shr(InterpState &S, CodePtr OpPC) {
auto RHS = S.Stk.pop<RT>();
auto LHS = S.Stk.pop<LT>();
- if constexpr (needsAlloc<LT>()) {
- LT Result = S.allocAP<LT>(LHS.bitWidth());
- return DoShiftAP<LT, RT, ShiftDir::Right>(S, OpPC, LHS, RHS, &Result);
- } else {
- LT Result;
- return DoShift<LT, RT, ShiftDir::Right>(S, OpPC, LHS, RHS, &Result);
- }
+ return DoShift<LT, RT, ShiftDir::Right>(S, OpPC, LHS, RHS);
}
template <PrimType NameL, PrimType NameR>
@@ -2852,13 +2668,8 @@ inline bool Shl(InterpState &S, CodePtr OpPC) {
using RT = typename PrimConv<NameR>::T;
auto RHS = S.Stk.pop<RT>();
auto LHS = S.Stk.pop<LT>();
- if constexpr (needsAlloc<LT>()) {
- LT Result = S.allocAP<LT>(LHS.bitWidth());
- return DoShiftAP<LT, RT, ShiftDir::Left>(S, OpPC, LHS, RHS, &Result);
- } else {
- LT Result;
- return DoShift<LT, RT, ShiftDir::Left>(S, OpPC, LHS, RHS, &Result);
- }
+
+ return DoShift<LT, RT, ShiftDir::Left>(S, OpPC, LHS, RHS);
}
static inline bool ShiftFixedPoint(InterpState &S, CodePtr OpPC, bool Left) {
@@ -3441,15 +3252,7 @@ inline bool BitCastPrim(InterpState &S, CodePtr OpPC, bool TargetIsUCharOrByte,
if constexpr (std::is_same_v<T, Floating>) {
assert(Sem);
- Floating Result = S.allocFloat(*Sem);
- Floating::bitcastFromMemory(Buff.data(), *Sem, &Result);
- S.Stk.push<Floating>(Result);
-
- // S.Stk.push<Floating>(T::bitcastFromMemory(Buff.data(), *Sem));
- } else if constexpr (needsAlloc<T>()) {
- T Result = S.allocAP<T>(ResultBitWidth);
- T::bitcastFromMemory(Buff.data(), ResultBitWidth, &Result);
- S.Stk.push<T>(Result);
+ S.Stk.push<Floating>(T::bitcastFromMemory(Buff.data(), *Sem));
} else {
assert(!Sem);
S.Stk.push<T>(T::bitcastFromMemory(Buff.data(), ResultBitWidth));
@@ -3507,11 +3310,7 @@ template <typename T> inline T ReadArg(InterpState &S, CodePtr &OpPC) {
}
template <> inline Floating ReadArg<Floating>(InterpState &S, CodePtr &OpPC) {
- auto &Semantics =
- llvm::APFloatBase::EnumToSemantics(Floating::deserializeSemantics(*OpPC));
-
- auto F = S.allocFloat(Semantics);
- Floating::deserialize(*OpPC, &F);
+ Floating F = Floating::deserialize(*OpPC);
OpPC += align(F.bytesToSerialize());
return F;
}
@@ -3519,25 +3318,17 @@ template <> inline Floating ReadArg<Floating>(InterpState &S, CodePtr &OpPC) {
template <>
inline IntegralAP<false> ReadArg<IntegralAP<false>>(InterpState &S,
CodePtr &OpPC) {
- uint32_t BitWidth = IntegralAP<false>::deserializeSize(*OpPC);
- auto Result = S.allocAP<IntegralAP<false>>(BitWidth);
- assert(Result.bitWidth() == BitWidth);
-
- IntegralAP<false>::deserialize(*OpPC, &Result);
- OpPC += align(Result.bytesToSerialize());
- return Result;
+ IntegralAP<false> I = IntegralAP<false>::deserialize(*OpPC);
+ OpPC += align(I.bytesToSerialize());
+ return I;
}
template <>
inline IntegralAP<true> ReadArg<IntegralAP<true>>(InterpState &S,
CodePtr &OpPC) {
- uint32_t BitWidth = IntegralAP<true>::deserializeSize(*OpPC);
- auto Result = S.allocAP<IntegralAP<true>>(BitWidth);
- assert(Result.bitWidth() == BitWidth);
-
- IntegralAP<true>::deserialize(*OpPC, &Result);
- OpPC += align(Result.bytesToSerialize());
- return Result;
+ IntegralAP<true> I = IntegralAP<true>::deserialize(*OpPC);
+ OpPC += align(I.bytesToSerialize());
+ return I;
}
template <>
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 5304bd77f2c06..d01e3d042a8bf 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -57,21 +57,6 @@ static void pushInteger(InterpState &S, const APSInt &Val, QualType QT) {
assert(T);
unsigned BitWidth = S.getASTContext().getTypeSize(QT);
-
- if (T == PT_IntAPS) {
- auto Result = S.allocAP<IntegralAP<true>>(BitWidth);
- Result.copy(Val);
- S.Stk.push<IntegralAP<true>>(Result);
- return;
- }
-
- if (T == PT_IntAP) {
- auto Result = S.allocAP<IntegralAP<false>>(BitWidth);
- Result.copy(Val);
- S.Stk.push<IntegralAP<false>>(Result);
- return;
- }
-
if (QT->isSignedIntegerOrEnumerationType()) {
int64_t V = Val.getSExtValue();
INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V, BitWidth)); });
@@ -342,13 +327,13 @@ static bool interp__builtin_nan(InterpState &S, CodePtr OpPC,
S.getASTContext().getFloatTypeSemantics(
Call->getDirectCallee()->getReturnType());
- Floating Result = S.allocFloat(TargetSemantics);
+ Floating Result;
if (S.getASTContext().getTargetInfo().isNan2008()) {
if (Signaling)
- Result.copy(
+ Result = Floating(
llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill));
else
- Result.copy(
+ Result = Floating(
llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill));
} else {
// Prior to IEEE 754-2008, architectures were allowed to choose whether
@@ -357,10 +342,10 @@ static bool interp__builtin_nan(InterpState &S, CodePtr OpPC,
// 2008 revisions, MIPS interpreted sNaN-2008 as qNan and qNaN-2008 as
// sNaN. This is now known as "legacy NaN" encoding.
if (Signaling)
- Result.copy(
+ Result = Floating(
llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill));
else
- Result.copy(
+ Result = Floating(
llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill));
}
@@ -375,9 +360,7 @@ static bool interp__builtin_inf(InterpState &S, CodePtr OpPC,
S.getASTContext().getFloatTypeSemantics(
Call->getDirectCallee()->getReturnType());
- Floating Result = S.allocFloat(TargetSemantics);
- Result.copy(APFloat::getInf(TargetSemantics));
- S.Stk.push<Floating>(Result);
+ S.Stk.push<Floating>(Floating::getInf(TargetSemantics));
return true;
}
@@ -385,12 +368,10 @@ static bool interp__builtin_copysign(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame) {
const Floating &Arg2 = S.Stk.pop<Floating>();
const Floating &Arg1 = S.Stk.pop<Floating>();
- Floating Result = S.allocFloat(Arg1.getSemantics());
APFloat Copy = Arg1.getAPFloat();
Copy.copySign(Arg2.getAPFloat());
- Result.copy(Copy);
- S.Stk.push<Floating>(Result);
+ S.Stk.push<Floating>(Floating(Copy));
return true;
}
@@ -399,13 +380,11 @@ static bool interp__builtin_fmin(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame, bool IsNumBuiltin) {
const Floating &RHS = S.Stk.pop<Floating>();
const Floating &LHS = S.Stk.pop<Floating>();
- Floating Result = S.allocFloat(LHS.getSemantics());
if (IsNumBuiltin)
- Result.copy(llvm::minimumnum(LHS.getAPFloat(), RHS.getAPFloat()));
+ S.Stk.push<Floating>(llvm::minimumnum(LHS.getAPFloat(), RHS.getAPFloat()));
else
- Result.copy(minnum(LHS.getAPFloat(), RHS.getAPFloat()));
- S.Stk.push<Floating>(Result);
+ S.Stk.push<Floating>(minnum(LHS.getAPFloat(), RHS.getAPFloat()));
return true;
}
@@ -413,13 +392,11 @@ static bool interp__builtin_fmax(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame, bool IsNumBuiltin) {
const Floating &RHS = S.Stk.pop<Floating>();
const Floating &LHS = S.Stk.pop<Floating>();
- Floating Result = S.allocFloat(LHS.getSemantics());
if (IsNumBuiltin)
- Result.copy(llvm::maximumnum(LHS.getAPFloat(), RHS.getAPFloat()));
+ S.Stk.push<Floating>(llvm::maximumnum(LHS.getAPFloat(), RHS.getAPFloat()));
else
- Result.copy(maxnum(LHS.getAPFloat(), RHS.getAPFloat()));
- S.Stk.push<Floating>(Result);
+ S.Stk.push<Floating>(maxnum(LHS.getAPFloat(), RHS.getAPFloat()));
return true;
}
@@ -594,16 +571,8 @@ static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC,
static bool interp__builtin_fabs(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame) {
const Floating &Val = S.Stk.pop<Floating>();
- APFloat F = Val.getAPFloat();
- if (!F.isNegative()) {
- S.Stk.push<Floating>(Val);
- return true;
- }
- Floating Result = S.allocFloat(Val.getSemantics());
- F.changeSign();
- Result.copy(F);
- S.Stk.push<Floating>(Result);
+ S.Stk.push<Floating>(Floating::abs(Val));
return true;
}
diff --git a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
index 2569cac018b31..239b3104e89f1 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
@@ -402,9 +402,7 @@ bool clang::interp::DoBitCastPtr(InterpState &S, CodePtr OpPC,
if (llvm::sys::IsBigEndianHost)
swapBytes(M.get(), NumBits.roundToBytes());
- Floating R = S.allocFloat(Semantics);
- Floating::bitcastFromMemory(M.get(), Semantics, &R);
- P.deref<Floating>() = R;
+ P.deref<Floating>() = Floating::bitcastFromMemory(M.get(), Semantics);
P.initialize();
return true;
}
diff --git a/clang/lib/AST/ByteCode/InterpState.h b/clang/lib/AST/ByteCode/InterpState.h
index 08765561985e2..e8dc6f0483d60 100644
--- a/clang/lib/AST/ByteCode/InterpState.h
+++ b/clang/lib/AST/ByteCode/InterpState.h
@@ -15,7 +15,6 @@
#include "Context.h"
#include "DynamicAllocator.h"
-#include "Floating.h"
#include "Function.h"
#include "InterpFrame.h"
#include "InterpStack.h"
@@ -127,33 +126,6 @@ class InterpState final : public State, public SourceMapper {
StdAllocatorCaller getStdAllocatorCaller(StringRef Name) const;
- void *allocate(size_t Size, unsigned Align = 8) const {
- return Allocator.Allocate(Size, Align);
- }
- template <typename T> T *allocate(size_t Num = 1) const {
- return static_cast<T *>(allocate(Num * sizeof(T), alignof(T)));
- }
-
- template <typename T> T allocAP(unsigned BitWidth) {
- unsigned NumWords = APInt::getNumWords(BitWidth);
- if (NumWords == 1)
- return T(BitWidth);
- uint64_t *Mem = (uint64_t *)this->allocate(NumWords * sizeof(uint64_t));
- // std::memset(Mem, 0, NumWords * sizeof(uint64_t)); // Debug
- return T(Mem, BitWidth);
- }
-
- Floating allocFloat(const llvm::fltSemantics &Sem) {
- if (Floating::singleWord(Sem))
- return Floating(llvm::APFloatBase::SemanticsToEnum(Sem));
-
- unsigned NumWords =
- APInt::getNumWords(llvm::APFloatBase::getSizeInBits(Sem));
- uint64_t *Mem = (uint64_t *)this->allocate(NumWords * sizeof(uint64_t));
- // std::memset(Mem, 0, NumWords * sizeof(uint64_t)); // Debug
- return Floating(Mem, llvm::APFloatBase::SemanticsToEnum(Sem));
- }
-
private:
friend class EvaluationResult;
friend class InterpStateCCOverride;
@@ -189,8 +161,6 @@ class InterpState final : public State, public SourceMapper {
llvm::SmallVector<
std::pair<const Expr *, const LifetimeExtendedTemporaryDecl *>>
SeenGlobalTemporaries;
-
- mutable llvm::BumpPtrAllocator Allocator;
};
class InterpStateCCOverride final {
diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td
index 57e01f7bd9da0..c76ac5f8ae868 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -48,7 +48,6 @@ def ArgUint64 : ArgType { let Name = "uint64_t"; }
def ArgIntAP : ArgType { let Name = "IntegralAP<false>"; let AsRef = true; }
def ArgIntAPS : ArgType { let Name = "IntegralAP<true>"; let AsRef = true; }
def ArgFloat : ArgType { let Name = "Floating"; let AsRef = true; }
-
def ArgBool : ArgType { let Name = "bool"; }
def ArgFixedPoint : ArgType { let Name = "FixedPoint"; let AsRef = true; }
@@ -89,9 +88,6 @@ def IntegerAndFixedTypeClass : TypeClass {
Uint32, Sint64, Uint64, IntAP, IntAPS, FixedPoint];
}
-def IntegralTypeClass : TypeClass {
- let Types = !listconcat(IntegerTypeClass.Types, [Bool]);
-}
def FixedSizeIntegralTypeClass : TypeClass {
let Types = [Sint8, Uint8, Sint16, Uint16, Sint32,
Uint32, Sint64, Uint64, Bool];
@@ -269,13 +265,12 @@ def ConstSint32 : ConstOpcode<Sint32, ArgSint32>;
def ConstUint32 : ConstOpcode<Uint32, ArgUint32>;
def ConstSint64 : ConstOpcode<Sint64, ArgSint64>;
def ConstUint64 : ConstOpcode<Uint64, ArgUint64>;
-def ConstIntAP : ConstOpcode<IntAP, ArgIntAP>;
-def ConstIntAPS : ConstOpcode<IntAPS, ArgIntAPS>;
+def ConstFloat : ConstOpcode<Float, ArgFloat>;
+def constIntAP : ConstOpcode<IntAP, ArgIntAP>;
+def constIntAPS : ConstOpcode<IntAPS, ArgIntAPS>;
def ConstBool : ConstOpcode<Bool, ArgBool>;
def ConstFixedPoint : ConstOpcode<FixedPoint, ArgFixedPoint>;
-def ConstFloat : Opcode { let Args = [ArgFloat]; }
-
// [] -> [Integer]
def Zero : Opcode {
let Types = [FixedSizeIntegralTypeClass];
@@ -333,7 +328,6 @@ def GetMemberPtrBasePop : Opcode {
def FinishInitPop : Opcode;
def FinishInit : Opcode;
-def FinishInitGlobal : Opcode;
def GetPtrDerivedPop : Opcode { let Args = [ArgUint32, ArgBool, ArgTypePtr]; }
@@ -395,7 +389,7 @@ class AccessOpcode : Opcode {
}
class BitFieldOpcode : Opcode {
- let Types = [IntegralTypeClass];
+ let Types = [AluTypeClass];
let Args = [ArgRecordField];
let HasGroup = 1;
}
diff --git a/clang/lib/AST/ByteCode/PrimType.h b/clang/lib/AST/ByteCode/PrimType.h
index a156cccbb3c1b..6152fbfbe3a74 100644
--- a/clang/lib/AST/ByteCode/PrimType.h
+++ b/clang/lib/AST/ByteCode/PrimType.h
@@ -76,13 +76,6 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
}
constexpr bool isIntegralType(PrimType T) { return T <= PT_FixedPoint; }
-template <typename T> constexpr bool needsAlloc() {
- return std::is_same_v<T, IntegralAP<false>> ||
- std::is_same_v<T, IntegralAP<true>> || std::is_same_v<T, Floating>;
-}
-constexpr bool needsAlloc(PrimType T) {
- return T == PT_IntAP || T == PT_IntAPS || T == PT_Float;
-}
/// Mapping from primitive types to their representation.
template <PrimType T> struct PrimConv;
@@ -216,16 +209,6 @@ static inline bool aligned(const void *P) {
} \
} while (0)
-#define TYPE_SWITCH_ALLOC(Expr, B) \
- do { \
- switch (Expr) { \
- TYPE_SWITCH_CASE(PT_Float, B) \
- TYPE_SWITCH_CASE(PT_IntAP, B) \
- TYPE_SWITCH_CASE(PT_IntAPS, B) \
- default:; \
- } \
- } while (0)
-
#define COMPOSITE_TYPE_SWITCH(Expr, B, D) \
do { \
switch (Expr) { \
diff --git a/clang/lib/AST/ByteCode/Program.h b/clang/lib/AST/ByteCode/Program.h
index 5d9c422447493..23ba1bbd193b1 100644
--- a/clang/lib/AST/ByteCode/Program.h
+++ b/clang/lib/AST/ByteCode/Program.h
@@ -132,14 +132,6 @@ class Program final {
bool IsMutable = false, bool IsVolatile = false,
const Expr *Init = nullptr);
- void *Allocate(size_t Size, unsigned Align = 8) const {
- return Allocator.Allocate(Size, Align);
- }
- template <typename T> T *Allocate(size_t Num = 1) const {
- return static_cast<T *>(Allocate(Num * sizeof(T), alignof(T)));
- }
- void Deallocate(void *Ptr) const {}
-
/// Context to manage declaration lifetimes.
class DeclScope {
public:
@@ -212,7 +204,7 @@ class Program final {
};
/// Allocator for globals.
- mutable PoolAllocTy Allocator;
+ PoolAllocTy Allocator;
/// Global objects.
std::vector<Global *> Globals;
@@ -246,18 +238,4 @@ class Program final {
} // namespace interp
} // namespace clang
-inline void *operator new(size_t Bytes, const clang::interp::Program &C,
- size_t Alignment = 8) {
- return C.Allocate(Bytes, Alignment);
-}
-
-inline void operator delete(void *Ptr, const clang::interp::Program &C,
- size_t) {
- C.Deallocate(Ptr);
-}
-inline void *operator new[](size_t Bytes, const clang::interp::Program &C,
- size_t Alignment = 8) {
- return C.Allocate(Bytes, Alignment);
-}
-
#endif
diff --git a/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp b/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp
index 1013a771d13b4..710612bef8fd0 100644
--- a/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp
+++ b/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp
@@ -21,9 +21,6 @@ template <class To, class From>
constexpr To bit_cast(const From &from) {
static_assert(sizeof(To) == sizeof(From));
return __builtin_bit_cast(To, from);
-#if __x86_64
- // both-note at -2 {{indeterminate value can only initialize an object of type}}
-#endif
}
template <class Intermediate, class Init>
@@ -41,8 +38,11 @@ constexpr Init round_trip(const Init &init) {
namespace test_long_double {
#if __x86_64
-constexpr __int128_t test_cast_to_int128 = bit_cast<__int128_t>((long double)0); // both-error{{must be initialized by a constant expression}}\
- // both-note{{in call}}
+/// FIXME: We could enable this, but since it aborts, it causes the usual mempory leak.
+#if 0
+constexpr __int128_t test_cast_to_int128 = bit_cast<__int128_t>((long double)0); // expected-error{{must be initialized by a constant expression}}\
+ // expected-note{{in call}}
+#endif
constexpr long double ld = 3.1425926539;
struct bytes {
diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp
index 174c1ffa79a43..21dca15a45775 100644
--- a/clang/test/AST/ByteCode/builtin-functions.cpp
+++ b/clang/test/AST/ByteCode/builtin-functions.cpp
@@ -208,7 +208,7 @@ namespace nan {
constexpr double NaN3 = __builtin_nan("foo"); // both-error {{must be initialized by a constant expression}}
constexpr float NaN4 = __builtin_nanf("");
- constexpr long double NaN5 = __builtin_nanf128("");
+ //constexpr long double NaN5 = __builtin_nanf128("");
/// FIXME: This should be accepted by the current interpreter as well.
constexpr char f[] = {'0', 'x', 'A', 'E', '\0'};
@@ -655,6 +655,8 @@ void test_noexcept(int *i) {
} // end namespace test_launder
+/// FIXME: The commented out tests here use a IntAP value and fail.
+/// This currently means we will leak the IntAP value since nothing cleans it up.
namespace clz {
char clz1[__builtin_clz(1) == BITSIZE(int) - 1 ? 1 : -1];
char clz2[__builtin_clz(7) == BITSIZE(int) - 3 ? 1 : -1];
@@ -707,7 +709,7 @@ namespace clz {
char clz48[__builtin_clzg(1ULL << (BITSIZE(long long) - 1)) == 0 ? 1 : -1];
char clz49[__builtin_clzg(1ULL << (BITSIZE(long long) - 1), 42) == 0 ? 1 : -1];
#ifdef __SIZEOF_INT128__
- int clz50 = __builtin_clzg((unsigned __int128)0);
+ // int clz50 = __builtin_clzg((unsigned __int128)0);
char clz51[__builtin_clzg((unsigned __int128)0, 42) == 42 ? 1 : -1];
char clz52[__builtin_clzg((unsigned __int128)0x1) == BITSIZE(__int128) - 1 ? 1 : -1];
char clz53[__builtin_clzg((unsigned __int128)0x1, 42) == BITSIZE(__int128) - 1 ? 1 : -1];
@@ -715,7 +717,7 @@ namespace clz {
char clz55[__builtin_clzg((unsigned __int128)0xf, 42) == BITSIZE(__int128) - 4 ? 1 : -1];
#endif
#ifndef __AVR__
- int clz58 = __builtin_clzg((unsigned _BitInt(128))0);
+ // int clz58 = __builtin_clzg((unsigned _BitInt(128))0);
char clz59[__builtin_clzg((unsigned _BitInt(128))0, 42) == 42 ? 1 : -1];
char clz60[__builtin_clzg((unsigned _BitInt(128))0x1) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1];
char clz61[__builtin_clzg((unsigned _BitInt(128))0x1, 42) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1];
@@ -773,7 +775,7 @@ namespace ctz {
char ctz46[__builtin_ctzg(1ULL << (BITSIZE(long long) - 1)) == BITSIZE(long long) - 1 ? 1 : -1];
char ctz47[__builtin_ctzg(1ULL << (BITSIZE(long long) - 1), 42) == BITSIZE(long long) - 1 ? 1 : -1];
#ifdef __SIZEOF_INT128__
- int ctz48 = __builtin_ctzg((unsigned __int128)0);
+ // int ctz48 = __builtin_ctzg((unsigned __int128)0);
char ctz49[__builtin_ctzg((unsigned __int128)0, 42) == 42 ? 1 : -1];
char ctz50[__builtin_ctzg((unsigned __int128)0x1) == 0 ? 1 : -1];
char ctz51[__builtin_ctzg((unsigned __int128)0x1, 42) == 0 ? 1 : -1];
@@ -783,7 +785,7 @@ namespace ctz {
char ctz55[__builtin_ctzg((unsigned __int128)1 << (BITSIZE(__int128) - 1), 42) == BITSIZE(__int128) - 1 ? 1 : -1];
#endif
#ifndef __AVR__
- int ctz56 = __builtin_ctzg((unsigned _BitInt(128))0);
+ // int ctz56 = __builtin_ctzg((unsigned _BitInt(128))0);
char ctz57[__builtin_ctzg((unsigned _BitInt(128))0, 42) == 42 ? 1 : -1];
char ctz58[__builtin_ctzg((unsigned _BitInt(128))0x1) == 0 ? 1 : -1];
char ctz59[__builtin_ctzg((unsigned _BitInt(128))0x1, 42) == 0 ? 1 : -1];
More information about the cfe-commits
mailing list