[clang] 1f2d934 - [clang][bytecode] Support pointers in __builtin_mem{move,cpy} (#120560)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Dec 19 07:39:02 PST 2024
Author: Timm Baeder
Date: 2024-12-19T16:38:58+01:00
New Revision: 1f2d934525833c4aae5f0436fd99551c776fd246
URL: https://github.com/llvm/llvm-project/commit/1f2d934525833c4aae5f0436fd99551c776fd246
DIFF: https://github.com/llvm/llvm-project/commit/1f2d934525833c4aae5f0436fd99551c776fd246.diff
LOG: [clang][bytecode] Support pointers in __builtin_mem{move,cpy} (#120560)
Unfortunately, that means we can't use the __builtin_bit_cast
implementation for this.
Added:
Modified:
clang/lib/AST/ByteCode/InterpBuiltin.cpp
clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
clang/lib/AST/ByteCode/InterpBuiltinBitCast.h
clang/lib/AST/ByteCode/Pointer.h
clang/test/AST/ByteCode/builtin-functions.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index d6b33c8aeeaac3..2ae91feb2d9e8e 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -1862,10 +1862,10 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
}
QualType ElemType;
- if (SrcPtr.getFieldDesc()->isArray())
- ElemType = SrcPtr.getFieldDesc()->getElemQualType();
+ if (DestPtr.getFieldDesc()->isArray())
+ ElemType = DestPtr.getFieldDesc()->getElemQualType();
else
- ElemType = SrcPtr.getType();
+ ElemType = DestPtr.getType();
unsigned ElemSize =
S.getASTContext().getTypeSizeInChars(ElemType).getQuantity();
@@ -1876,6 +1876,18 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
return false;
}
+ QualType SrcElemType;
+ if (SrcPtr.getFieldDesc()->isArray())
+ SrcElemType = SrcPtr.getFieldDesc()->getElemQualType();
+ else
+ SrcElemType = SrcPtr.getType();
+
+ if (!S.getASTContext().hasSameUnqualifiedType(ElemType, SrcElemType)) {
+ S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_type_pun)
+ << Move << SrcElemType << ElemType;
+ return false;
+ }
+
// Check for overlapping memory regions.
if (!Move && Pointer::pointToSameBlock(SrcPtr, DestPtr)) {
unsigned SrcIndex = SrcPtr.getIndex() * SrcPtr.elemSize();
@@ -1893,8 +1905,8 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
// As a last resort, reject dummy pointers.
if (DestPtr.isDummy() || SrcPtr.isDummy())
return false;
-
- if (!DoBitCastPtr(S, OpPC, SrcPtr, DestPtr, Size.getZExtValue()))
+ assert(Size.getZExtValue() % ElemSize == 0);
+ if (!DoMemcpy(S, OpPC, SrcPtr, DestPtr, Bytes(Size.getZExtValue()).toBits()))
return false;
S.Stk.push<Pointer>(DestPtr);
diff --git a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
index 07f76943708216..0fc94e1694822a 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
@@ -448,3 +448,34 @@ bool clang::interp::DoBitCastPtr(InterpState &S, CodePtr OpPC,
return Success;
}
+
+bool clang::interp::DoMemcpy(InterpState &S, CodePtr OpPC,
+ const Pointer &SrcPtr, const Pointer &DestPtr,
+ Bits Size) {
+ assert(SrcPtr.isBlockPointer());
+ assert(DestPtr.isBlockPointer());
+
+ unsigned SrcStartOffset = SrcPtr.getByteOffset();
+ unsigned DestStartOffset = DestPtr.getByteOffset();
+
+ enumeratePointerFields(SrcPtr, S.getContext(), Size,
+ [&](const Pointer &P, PrimType T, Bits BitOffset,
+ Bits FullBitWidth, bool PackedBools) -> bool {
+ unsigned SrcOffsetDiff =
+ P.getByteOffset() - SrcStartOffset;
+
+ Pointer DestP =
+ Pointer(DestPtr.asBlockPointer().Pointee,
+ DestPtr.asBlockPointer().Base,
+ DestStartOffset + SrcOffsetDiff);
+
+ TYPE_SWITCH(T, {
+ DestP.deref<T>() = P.deref<T>();
+ DestP.initialize();
+ });
+
+ return true;
+ });
+
+ return true;
+}
diff --git a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.h b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.h
index b45613b2f21e20..a0191bab693c45 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.h
+++ b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.h
@@ -33,6 +33,10 @@ bool DoBitCastPtr(InterpState &S, CodePtr OpPC, const Pointer &FromPtr,
Pointer &ToPtr, size_t Size);
bool readPointerToBuffer(const Context &Ctx, const Pointer &FromPtr,
BitcastBuffer &Buffer, bool ReturnOnUninit);
+
+bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &SrcPtr,
+ const Pointer &DestPtr, Bits Size);
+
} // namespace interp
} // namespace clang
diff --git a/clang/lib/AST/ByteCode/Pointer.h b/clang/lib/AST/ByteCode/Pointer.h
index 457fe93b278175..0d467c2abf0838 100644
--- a/clang/lib/AST/ByteCode/Pointer.h
+++ b/clang/lib/AST/ByteCode/Pointer.h
@@ -107,6 +107,7 @@ class Pointer {
: Offset(Offset), StorageKind(Storage::Fn) {
PointeeStorage.Fn = FunctionPointer(F);
}
+ Pointer(Block *Pointee, unsigned Base, uint64_t Offset);
~Pointer();
void operator=(const Pointer &P);
@@ -706,8 +707,6 @@ class Pointer {
friend struct InitMap;
friend class DynamicAllocator;
- Pointer(Block *Pointee, unsigned Base, uint64_t Offset);
-
/// Returns the embedded descriptor preceding a field.
InlineDescriptor *getInlineDesc() const {
assert(isBlockPointer());
diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp
index 5906cb970f06c4..c1fd1bc1381503 100644
--- a/clang/test/AST/ByteCode/builtin-functions.cpp
+++ b/clang/test/AST/ByteCode/builtin-functions.cpp
@@ -1222,6 +1222,28 @@ namespace BuiltinMemcpy {
static_assert(test_memcpy(1, 2, sizeof(int)) == 1334);
static_assert(test_memcpy(0, 1, sizeof(int) * 2) == 2334); // both-error {{not an integral constant expression}} \
// both-note {{in call}}
+
+ /// Both memcpy and memmove must support pointers.
+ constexpr bool moveptr() {
+ int a = 0;
+ void *x = &a;
+ void *z = nullptr;
+
+ __builtin_memmove(&z, &x, sizeof(void*));
+ return z == x;
+ }
+ static_assert(moveptr());
+
+ constexpr bool cpyptr() {
+ int a = 0;
+ void *x = &a;
+ void *z = nullptr;
+
+ __builtin_memcpy(&z, &x, sizeof(void*));
+ return z == x;
+ }
+ static_assert(cpyptr());
+
}
namespace Memcmp {
More information about the cfe-commits
mailing list