[reland][libc] Add bcopy
authorGuillaume Chatelet <gchatelet@google.com>
Thu, 1 Dec 2022 10:06:36 +0000 (10:06 +0000)
committerGuillaume Chatelet <gchatelet@google.com>
Thu, 1 Dec 2022 10:07:04 +0000 (10:07 +0000)
Differential Revision: https://reviews.llvm.org/D138994

14 files changed:
libc/config/darwin/arm/entrypoints.txt
libc/config/linux/aarch64/entrypoints.txt
libc/config/linux/arm/entrypoints.txt
libc/config/linux/x86_64/entrypoints.txt
libc/config/windows/entrypoints.txt
libc/docs/strings.rst
libc/spec/llvm_libc_ext.td
libc/src/string/CMakeLists.txt
libc/src/string/bcopy.cpp [new file with mode: 0644]
libc/src/string/bcopy.h [new file with mode: 0644]
libc/test/src/string/CMakeLists.txt
libc/test/src/string/bcopy_test.cpp [new file with mode: 0644]
utils/bazel/llvm-project-overlay/libc/BUILD.bazel
utils/bazel/llvm-project-overlay/libc/test/src/string/BUILD.bazel

index cd50073..d16bf08 100644 (file)
@@ -19,6 +19,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     
     # string.h entrypoints
     libc.src.string.bcmp
+    libc.src.string.bcopy
     libc.src.string.bzero
     libc.src.string.memccpy
     libc.src.string.memchr
index 8db3b79..a67165e 100644 (file)
@@ -28,6 +28,7 @@ set(TARGET_LIBC_ENTRYPOINTS
 
     # string.h entrypoints
     libc.src.string.bcmp
+    libc.src.string.bcopy
     libc.src.string.bzero
     libc.src.string.memccpy
     libc.src.string.memchr
index c88cbb1..7253652 100644 (file)
@@ -19,6 +19,7 @@ set(TARGET_LIBC_ENTRYPOINTS
 
     # string.h entrypoints
     libc.src.string.bcmp
+    libc.src.string.bcopy
     libc.src.string.bzero
     libc.src.string.memccpy
     libc.src.string.memchr
index e9e173a..14043b0 100644 (file)
@@ -28,6 +28,7 @@ set(TARGET_LIBC_ENTRYPOINTS
 
     # string.h entrypoints
     libc.src.string.bcmp
+    libc.src.string.bcopy
     libc.src.string.bzero
     libc.src.string.memccpy
     libc.src.string.memchr
index 69a0aca..bf52c8c 100644 (file)
@@ -19,6 +19,7 @@ set(TARGET_LIBC_ENTRYPOINTS
 
     # string.h entrypoints
     libc.src.string.bcmp
+    libc.src.string.bcopy
     libc.src.string.bzero
     libc.src.string.memccpy
     libc.src.string.memchr
index c475134..50b479b 100644 (file)
@@ -36,6 +36,7 @@ Function Name  Available
 =============  =========
 bzero          |check|
 bcmp           |check|
+bcopy          |check|       
 memcpy         |check|
 memset         |check|
 memcmp         |check|
index 76f0622..731671f 100644 (file)
@@ -6,6 +6,11 @@ def LLVMLibcExt : StandardSpec<"llvm_libc_ext"> {
       [], // Enumerations
       [
           FunctionSpec<
+              "bcopy",
+              RetValSpec<VoidType>,
+              [ArgSpec<ConstVoidPtr>, ArgSpec<VoidPtr>, ArgSpec<SizeTType>]
+          >,
+          FunctionSpec<
               "bzero",
               RetValSpec<VoidType>,
               [ArgSpec<VoidPtr>, ArgSpec<SizeTType>]
index 7719178..422d24c 100644 (file)
@@ -21,6 +21,14 @@ add_header_library(
 )
 
 add_entrypoint_object(
+  bcopy
+  SRCS
+    bcopy.cpp
+  HDRS
+    bcopy.h
+)
+
+add_entrypoint_object(
   memccpy
   SRCS
     memccpy.cpp
@@ -28,7 +36,6 @@ add_entrypoint_object(
     memccpy.h
 )
 
-
 add_entrypoint_object(
   mempcpy
   SRCS
diff --git a/libc/src/string/bcopy.cpp b/libc/src/string/bcopy.cpp
new file mode 100644 (file)
index 0000000..9653c73
--- /dev/null
@@ -0,0 +1,19 @@
+//===-- Implementation of bcopy -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/string/bcopy.h"
+#include "src/__support/common.h"
+#include "src/string/memory_utils/memmove_implementations.h"
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(void, bcopy, (const void *src, void *dst, size_t count)) {
+  return inline_memmove(dst, src, count);
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/string/bcopy.h b/libc/src/string/bcopy.h
new file mode 100644 (file)
index 0000000..12de749
--- /dev/null
@@ -0,0 +1,20 @@
+//===-- Implementation header for bcopy -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_STRING_BCOPY_H
+#define LLVM_LIBC_SRC_STRING_BCOPY_H
+
+#include <stddef.h> // size_t
+
+namespace __llvm_libc {
+
+void bcopy(const void *src, void *dest, size_t count);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_STRING_BCOPY_H
index b0b3529..8b427cc 100644 (file)
@@ -3,6 +3,18 @@ add_libc_testsuite(libc_string_unittests)
 add_subdirectory(memory_utils)
 
 add_libc_unittest(
+  bcopy_test
+  SUITE
+    libc_string_unittests
+  SRCS
+    bcopy_test.cpp
+  DEPENDS
+    libc.src.string.bcopy
+  LINK_LIBRARIES
+    LibcMemoryHelpers
+)
+
+add_libc_unittest(
   memccpy_test
   SUITE
     libc_string_unittests
diff --git a/libc/test/src/string/bcopy_test.cpp b/libc/test/src/string/bcopy_test.cpp
new file mode 100644 (file)
index 0000000..fa57d25
--- /dev/null
@@ -0,0 +1,104 @@
+//===-- Unittests for bcopy -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/CPP/span.h"
+#include "src/string/bcopy.h"
+#include "utils/UnitTest/MemoryMatcher.h"
+#include "utils/UnitTest/Test.h"
+
+using __llvm_libc::cpp::array;
+using __llvm_libc::cpp::span;
+
+TEST(LlvmLibcBcopyTest, MoveZeroByte) {
+  char Buffer[] = {'a', 'b', 'y', 'z'};
+  const char Expected[] = {'a', 'b', 'y', 'z'};
+  void *const Dst = Buffer;
+  __llvm_libc::bcopy(Buffer + 2, Dst, 0);
+  ASSERT_MEM_EQ(Buffer, Expected);
+}
+
+TEST(LlvmLibcBcopyTest, DstAndSrcPointToSameAddress) {
+  char Buffer[] = {'a', 'b'};
+  const char Expected[] = {'a', 'b'};
+  void *const Dst = Buffer;
+  __llvm_libc::bcopy(Buffer, Dst, 1);
+  ASSERT_MEM_EQ(Buffer, Expected);
+}
+
+TEST(LlvmLibcBcopyTest, DstStartsBeforeSrc) {
+  // Set boundary at beginning and end for not overstepping when
+  // copy forward or backward.
+  char Buffer[] = {'z', 'a', 'b', 'c', 'z'};
+  const char Expected[] = {'z', 'b', 'c', 'c', 'z'};
+  void *const Dst = Buffer + 1;
+  __llvm_libc::bcopy(Buffer + 2, Dst, 2);
+  ASSERT_MEM_EQ(Buffer, Expected);
+}
+
+TEST(LlvmLibcBcopyTest, DstStartsAfterSrc) {
+  char Buffer[] = {'z', 'a', 'b', 'c', 'z'};
+  const char Expected[] = {'z', 'a', 'a', 'b', 'z'};
+  void *const Dst = Buffer + 2;
+  __llvm_libc::bcopy(Buffer + 1, Dst, 2);
+  ASSERT_MEM_EQ(Buffer, Expected);
+}
+
+// e.g. `Dst` follow `src`.
+// str: [abcdefghij]
+//      [__src_____]
+//      [_____Dst__]
+TEST(LlvmLibcBcopyTest, SrcFollowDst) {
+  char Buffer[] = {'z', 'a', 'b', 'z'};
+  const char Expected[] = {'z', 'b', 'b', 'z'};
+  void *const Dst = Buffer + 1;
+  __llvm_libc::bcopy(Buffer + 2, Dst, 1);
+  ASSERT_MEM_EQ(Buffer, Expected);
+}
+
+TEST(LlvmLibcBcopyTest, DstFollowSrc) {
+  char Buffer[] = {'z', 'a', 'b', 'z'};
+  const char Expected[] = {'z', 'a', 'a', 'z'};
+  void *const Dst = Buffer + 2;
+  __llvm_libc::bcopy(Buffer + 1, Dst, 1);
+  ASSERT_MEM_EQ(Buffer, Expected);
+}
+
+static constexpr int kMaxSize = 512;
+
+char GetRandomChar() {
+  static constexpr const uint64_t A = 1103515245;
+  static constexpr const uint64_t C = 12345;
+  static constexpr const uint64_t M = 1ULL << 31;
+  static uint64_t Seed = 123456789;
+  Seed = (A * Seed + C) % M;
+  return Seed;
+}
+
+void Randomize(span<char> Buffer) {
+  for (auto &current : Buffer)
+    current = GetRandomChar();
+}
+
+TEST(LlvmLibcBcopyTest, SizeSweep) {
+  using LargeBuffer = array<char, 3 * kMaxSize>;
+  LargeBuffer GroundTruth;
+  Randomize(GroundTruth);
+  for (int Size = 0; Size < kMaxSize; ++Size) {
+    for (int Offset = -Size; Offset < Size; ++Offset) {
+      LargeBuffer Buffer = GroundTruth;
+      LargeBuffer Expected = GroundTruth;
+      size_t DstOffset = kMaxSize;
+      size_t SrcOffset = kMaxSize + Offset;
+      for (int I = 0; I < Size; ++I)
+        Expected[DstOffset + I] = GroundTruth[SrcOffset + I];
+      void *const Dst = Buffer.data() + DstOffset;
+      __llvm_libc::bcopy(Buffer.data() + SrcOffset, Dst, Size);
+      ASSERT_MEM_EQ(Buffer, Expected);
+    }
+  }
+}
index 1aafa2a..48c84fc 100644 (file)
@@ -1125,6 +1125,17 @@ libc_function(
 )
 
 libc_function(
+    name = "bcopy",
+    srcs = ["src/string/bcopy.cpp"],
+    hdrs = ["src/string/bcopy.h"],
+    features = no_sanitize_features,
+    deps = [
+        ":__support_common",
+        ":string_memory_utils",
+    ],
+)
+
+libc_function(
     name = "memcmp",
     srcs = ["src/string/memcmp.cpp"],
     hdrs = ["src/string/memcmp.h"],
index 8ccc627..cfda301 100644 (file)
@@ -147,6 +147,18 @@ libc_test(
 )
 
 libc_test(
+    name = "bcopy_test",
+    srcs = ["bcopy_test.cpp"],
+    libc_function_deps = [
+        "//libc:bcopy",
+    ],
+    deps = [
+        "//libc:__support_cpp_span",
+        "//libc/utils/UnitTest:memory_matcher",
+    ],
+)
+
+libc_test(
     name = "memcmp_test",
     srcs = ["memcmp_test.cpp"],
     libc_function_deps = [