[libc-commits] [PATCH] D104226: [libc] Add a set of elementary operations

Guillaume Chatelet via Phabricator via libc-commits libc-commits at lists.llvm.org
Mon Jun 14 06:58:23 PDT 2021


gchatelet created this revision.
gchatelet added a reviewer: courbet.
Herald added subscribers: libc-commits, ecnelises, tschuett, mgorny.
Herald added a project: libc-project.
gchatelet requested review of this revision.

Resubmission of D100646 <https://reviews.llvm.org/D100646> now making sure that we handle cases were `__builtin_memcpy_inline` is not available.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D104226

Files:
  libc/src/string/memory_utils/elements.h
  libc/test/src/string/memory_utils/CMakeLists.txt


Index: libc/test/src/string/memory_utils/CMakeLists.txt
===================================================================
--- libc/test/src/string/memory_utils/CMakeLists.txt
+++ libc/test/src/string/memory_utils/CMakeLists.txt
@@ -12,9 +12,3 @@
   COMPILE_OPTIONS
     ${LIBC_COMPILE_OPTIONS_NATIVE}
 )
-
-target_compile_definitions(
-  libc.test.src.string.memory_utils.utils_test
-  PRIVATE
-  LLVM_LIBC_MEMCPY_MONITOR=memcpy_monitor
-)
Index: libc/src/string/memory_utils/elements.h
===================================================================
--- libc/src/string/memory_utils/elements.h
+++ libc/src/string/memory_utils/elements.h
@@ -348,11 +348,30 @@
 // `_inline` versions of all the builtins. Theoretically, Clang can still turn
 // them into calls to the C library leading to reentrancy problems.
 namespace builtin {
+
+// __builtin_memcpy_inline guarantees to never call external functions.
+// Unfortunately it is not widely available.
+#ifdef __clang__
+#if __has_builtin(__builtin_memcpy_inline)
+#define USE_BUILTIN_MEMCPY_INLINE
+#endif
+#elif defined(__GNUC__)
+#define USE_BUILTIN_MEMCPY
+#endif
+
 template <size_t Size> struct Builtin {
   static constexpr size_t kSize = Size;
 
   static void Copy(char *__restrict dst, const char *__restrict src) {
+#if LLVM_LIBC_HAVE_MEMORY_SANITIZER || LLVM_LIBC_HAVE_ADDRESS_SANITIZER
+    ForLoopCopy<kBlockSize>(dst, src);
+#elif defined(USE_BUILTIN_MEMCPY_INLINE)
     __builtin_memcpy_inline(dst, src, kSize);
+#elif defined(USE_BUILTIN_MEMCPY)
+    __builtin_memcpy(dst, src, kSize);
+#else
+    ForLoopCopy<kBlockSize>(dst, src);
+#endif
   }
 
   static bool Equals(const char *lhs, const char *rhs) {
@@ -366,8 +385,21 @@
   static void SplatSet(char *dst, const unsigned char value) {
     __builtin_memset(dst, value, kSize);
   }
+
+private:
+  // Copies `kBlockSize` bytes from `src` to `dst` using a for loop.
+  // This code requires the use of `-fno-buitin-memcpy` to prevent the compiler
+  // from turning the for-loop back into `__builtin_memcpy`.
+  template <size_t kBlockSize>
+  static void ForLoopCopy(char *__restrict dst, const char *__restrict src) {
+    for (size_t i = 0; i < kBlockSize; ++i)
+      dst[i] = src[i];
+  }
 };
 
+#undef USE_BUILTIN_MEMCPY_INLINE
+#undef USE_BUILTIN_MEMCPY
+
 using _1 = Builtin<1>;
 using _2 = Builtin<2>;
 using _3 = Builtin<3>;
@@ -407,11 +439,11 @@
 private:
   static T Load(const char *ptr) {
     T value;
-    __builtin_memcpy_inline(&value, ptr, kSize);
+    builtin::Builtin<kSize>::Copy(reinterpret_cast<char *>(&value), ptr);
     return value;
   }
   static void Store(char *ptr, T value) {
-    __builtin_memcpy_inline(ptr, &value, kSize);
+    builtin::Builtin<kSize>::Copy(ptr, reinterpret_cast<const char *>(&value));
   }
   static T GetSplattedValue(const unsigned char value) {
     return T(~0) / T(0xFF) * T(value);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D104226.351858.patch
Type: text/x-patch
Size: 2870 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libc-commits/attachments/20210614/3c2216f8/attachment.bin>


More information about the libc-commits mailing list