aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ByteCode/Interp.cpp
diff options
context:
space:
mode:
authorTimm Baeder <tbaeder@redhat.com>2025-06-20 18:06:01 +0200
committerGitHub <noreply@github.com>2025-06-20 18:06:01 +0200
commit32fc625a3fa27fa325c75b0fc841db4ce8e06805 (patch)
treeb71a99d6cf02373ce3c92dcda344ef1d6f0fef12 /clang/lib/AST/ByteCode/Interp.cpp
parent151ee0faad427651304b51b8af77704be26bb485 (diff)
downloadllvm-32fc625a3fa27fa325c75b0fc841db4ce8e06805.zip
llvm-32fc625a3fa27fa325c75b0fc841db4ce8e06805.tar.gz
llvm-32fc625a3fa27fa325c75b0fc841db4ce8e06805.tar.bz2
Reapply "Reapply "[clang][bytecode] Allocate IntegralAP and Floating … (#145014)
…types usi… (#144676)" This reverts commit 68471d29eed2c49f9b439e505b3f24d387d54f97. IntegralAP contains a union: union { uint64_t *Memory = nullptr; uint64_t Val; }; On 64bit systems, both Memory and Val have the same size. However, on 32 bit system, Val is 64bit and Memory only 32bit. Which means the default initializer for Memory will only zero half of Val. We fixed this by zero-initializing Val explicitly in the IntegralAP(unsigned BitWidth) constructor. See also the discussion in https://github.com/llvm/llvm-project/pull/144246
Diffstat (limited to 'clang/lib/AST/ByteCode/Interp.cpp')
-rw-r--r--clang/lib/AST/ByteCode/Interp.cpp106
1 files changed, 102 insertions, 4 deletions
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 5c8abff..1e2032f 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -1935,8 +1935,10 @@ bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
if (!CheckPointerToIntegralCast(S, OpPC, Ptr, BitWidth))
return false;
- S.Stk.push<IntegralAP<false>>(
- IntegralAP<false>::from(Ptr.getIntegerRepresentation(), BitWidth));
+ auto Result = S.allocAP<IntegralAP<false>>(BitWidth);
+ Result.copy(APInt(BitWidth, Ptr.getIntegerRepresentation()));
+
+ S.Stk.push<IntegralAP<false>>(Result);
return true;
}
@@ -1946,8 +1948,10 @@ bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
if (!CheckPointerToIntegralCast(S, OpPC, Ptr, BitWidth))
return false;
- S.Stk.push<IntegralAP<true>>(
- IntegralAP<true>::from(Ptr.getIntegerRepresentation(), BitWidth));
+ auto Result = S.allocAP<IntegralAP<true>>(BitWidth);
+ Result.copy(APInt(BitWidth, Ptr.getIntegerRepresentation()));
+
+ S.Stk.push<IntegralAP<true>>(Result);
return true;
}
@@ -2053,6 +2057,100 @@ 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)