[clang] [clang][bytecode] Support pointers in __builtin_mem{move, cpy} (PR #120560)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Thu Dec 19 03:48:31 PST 2024
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/120560
Unfortunately, that means we can't use the __builtin_bit_cast implementation for this.
>From 1fe4940ad01bae6ab75cdf8bd1ea9812929e716d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Thu, 19 Dec 2024 12:46:43 +0100
Subject: [PATCH] [clang][bytecode] Support pointers in __builtin_mem{move,cpy}
Unfortunately, that means we can't use the __builtin_bit_cast
implementation for this.
---
clang/lib/AST/ByteCode/InterpBuiltin.cpp | 22 ++++++++++---
.../lib/AST/ByteCode/InterpBuiltinBitCast.cpp | 31 +++++++++++++++++++
clang/lib/AST/ByteCode/InterpBuiltinBitCast.h | 4 +++
clang/lib/AST/ByteCode/Pointer.h | 3 +-
clang/test/AST/ByteCode/builtin-functions.cpp | 22 +++++++++++++
5 files changed, 75 insertions(+), 7 deletions(-)
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