diff options
author | Timm Baeder <tbaeder@redhat.com> | 2025-06-20 18:06:01 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-06-20 18:06:01 +0200 |
commit | 32fc625a3fa27fa325c75b0fc841db4ce8e06805 (patch) | |
tree | b71a99d6cf02373ce3c92dcda344ef1d6f0fef12 /clang/lib/AST/ByteCode/Interp.cpp | |
parent | 151ee0faad427651304b51b8af77704be26bb485 (diff) | |
download | llvm-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.cpp | 106 |
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) |