[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