[clang] [clang][bytecode] Add simple __builtin_memcpy implementation (PR #118278)

Timm Baeder via cfe-commits cfe-commits at lists.llvm.org
Mon Dec 2 03:13:23 PST 2024


https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/118278

>From bcb316bd8f2b6a143cb303f1e67c6bbc04c8c986 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Mon, 2 Dec 2024 10:45:52 +0100
Subject: [PATCH] [clang][bytecode] Add simple __builtin_memcpy implementation

Not handling all the special- and error cases yet. Just making sure the
bitcast code can be used for this as well.
---
 clang/lib/AST/ByteCode/InterpBuiltin.cpp      | 31 +++++++++++++++++++
 clang/test/AST/ByteCode/builtin-functions.cpp | 11 ++++++-
 2 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 080fa891e641e3..8ede6717db0463 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -1723,6 +1723,32 @@ static bool interp__builtin_vector_reduce(InterpState &S, CodePtr OpPC,
   llvm_unreachable("Unsupported vector reduce builtin");
 }
 
+static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
+                                   const InterpFrame *Frame,
+                                   const Function *Func, const CallExpr *Call) {
+  assert(Call->getNumArgs() == 3);
+  Pointer DestPtr = getParam<Pointer>(Frame, 0);
+  const Pointer &SrcPtr = getParam<Pointer>(Frame, 1);
+  const APSInt &Size =
+      peekToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(2)));
+  assert(!Size.isSigned() && "memcpy and friends take an unsigned size");
+
+  if (DestPtr.isDummy() || SrcPtr.isDummy())
+    return false;
+
+  // If the size is zero, we treat this as always being a valid no-op.
+  if (Size.isZero()) {
+    S.Stk.push<Pointer>(DestPtr);
+    return true;
+  }
+
+  if (!DoBitCastPtr(S, OpPC, SrcPtr, DestPtr))
+    return false;
+
+  S.Stk.push<Pointer>(DestPtr);
+  return true;
+}
+
 bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
                       const CallExpr *Call, uint32_t BuiltinID) {
   const InterpFrame *Frame = S.Current;
@@ -2173,6 +2199,11 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
       return false;
     break;
 
+  case Builtin::BI__builtin_memcpy:
+    if (!interp__builtin_memcpy(S, OpPC, Frame, F, Call))
+      return false;
+    break;
+
   default:
     S.FFDiag(S.Current->getLocation(OpPC),
              diag::note_invalid_subexpr_in_const_expr)
diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp
index 972d39ca509615..78b692b819a0ab 100644
--- a/clang/test/AST/ByteCode/builtin-functions.cpp
+++ b/clang/test/AST/ByteCode/builtin-functions.cpp
@@ -991,7 +991,6 @@ namespace BuiltinInImplicitCtor {
   static_assert(Foo.a == 0, "");
 }
 
-
 typedef double vector4double __attribute__((__vector_size__(32)));
 typedef float vector4float __attribute__((__vector_size__(16)));
 typedef long long vector4long __attribute__((__vector_size__(32)));
@@ -1035,3 +1034,13 @@ namespace RecuceAdd {
   static_assert(reduceAddInt3 == 0);
 #endif
 }
+
+namespace BuiltinMemcpy {
+  constexpr int simple() {
+    int a = 12;
+    int b = 0;
+    __builtin_memcpy(&b, &a, sizeof(a));
+    return b;
+  }
+  static_assert(simple() == 12);
+}



More information about the cfe-commits mailing list