llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)

<details>
<summary>Changes</summary>

Unfortunately, a few circumstances make the implementation here less than 
ideal, but we need to handle overlapping regions anyway.

---
Full diff: https://github.com/llvm/llvm-project/pull/132523.diff


2 Files Affected:

- (modified) clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp (+29-12) 
- (modified) clang/test/AST/ByteCode/builtin-functions.cpp (+1-2) 


``````````diff
diff --git a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp 
b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
index 6b8860c09167c..239b3104e89f1 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
@@ -19,6 +19,8 @@
 #include "clang/AST/RecordLayout.h"
 #include "clang/Basic/TargetInfo.h"
 
+#include <variant>
+
 using namespace clang;
 using namespace clang::interp;
 
@@ -450,33 +452,48 @@ bool clang::interp::DoBitCastPtr(InterpState &S, CodePtr 
OpPC,
   return Success;
 }
 
+using PrimTypeVariant =
+    std::variant<Pointer, FunctionPointer, MemberPointer, FixedPoint,
+                 Integral<8, false>, Integral<8, true>, Integral<16, false>,
+                 Integral<16, true>, Integral<32, false>, Integral<32, true>,
+                 Integral<64, false>, Integral<64, true>, IntegralAP<true>,
+                 IntegralAP<false>, Boolean, Floating>;
+
+// NB: This implementation isn't exactly ideal, but:
+//   1) We can't just do a bitcast here since we need to be able to
+//      copy pointers.
+//   2) This also needs to handle overlapping regions.
+//   3) We currently have no way of iterating over the fields of a pointer
+//      backwards.
 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();
-
+  llvm::SmallVector<PrimTypeVariant> Values;
   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, { Values.push_back(P.deref<T>()); });
+                           return true;
+                         });
 
+  unsigned ValueIndex = 0;
+  enumeratePointerFields(DestPtr, S.getContext(), Size,
+                         [&](const Pointer &P, PrimType T, Bits BitOffset,
+                             Bits FullBitWidth, bool PackedBools) -> bool {
                            TYPE_SWITCH(T, {
-                             DestP.deref<T>() = P.deref<T>();
-                             DestP.initialize();
+                             P.deref<T>() = std::get<T>(Values[ValueIndex]);
+                             P.initialize();
                            });
 
+                           ++ValueIndex;
                            return true;
                          });
 
+  // We should've read all the values into DestPtr.
+  assert(ValueIndex == Values.size());
+
   return true;
 }
diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp 
b/clang/test/AST/ByteCode/builtin-functions.cpp
index 3dd348031fec1..13a34f71a6354 100644
--- a/clang/test/AST/ByteCode/builtin-functions.cpp
+++ b/clang/test/AST/ByteCode/builtin-functions.cpp
@@ -1276,7 +1276,6 @@ namespace BuiltinMemcpy {
   static_assert(test_incomplete_array_type() == 1234); // both-error 
{{constant}} both-note {{in call}}
 
 
-  /// FIXME: memmove needs to support overlapping memory regions.
   constexpr bool memmoveOverlapping() {
     char s1[] {1, 2, 3};
     __builtin_memmove(s1, s1 + 1, 2 * sizeof(char));
@@ -1289,7 +1288,7 @@ namespace BuiltinMemcpy {
 
     return Result1 && Result2;
   }
-  static_assert(memmoveOverlapping()); // expected-error {{failed}}
+  static_assert(memmoveOverlapping());
 }
 
 namespace Memcmp {

``````````

</details>


https://github.com/llvm/llvm-project/pull/132523
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to