[libc-commits] [libc] 436c8f4 - [reland][libc] Add bcopy

Guillaume Chatelet via libc-commits libc-commits at lists.llvm.org
Thu Dec 1 02:07:14 PST 2022


Author: Guillaume Chatelet
Date: 2022-12-01T10:07:04Z
New Revision: 436c8f4420a62e7d3601693f4097bc6e6a5ee9f4

URL: https://github.com/llvm/llvm-project/commit/436c8f4420a62e7d3601693f4097bc6e6a5ee9f4
DIFF: https://github.com/llvm/llvm-project/commit/436c8f4420a62e7d3601693f4097bc6e6a5ee9f4.diff

LOG: [reland][libc] Add bcopy

Differential Revision: https://reviews.llvm.org/D138994

Added: 
    libc/src/string/bcopy.cpp
    libc/src/string/bcopy.h
    libc/test/src/string/bcopy_test.cpp

Modified: 
    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/test/src/string/CMakeLists.txt
    utils/bazel/llvm-project-overlay/libc/BUILD.bazel
    utils/bazel/llvm-project-overlay/libc/test/src/string/BUILD.bazel

Removed: 
    


################################################################################
diff  --git a/libc/config/darwin/arm/entrypoints.txt b/libc/config/darwin/arm/entrypoints.txt
index cd500736ac175..d16bf0816e54e 100644
--- a/libc/config/darwin/arm/entrypoints.txt
+++ b/libc/config/darwin/arm/entrypoints.txt
@@ -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

diff  --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 8db3b795a83b6..a67165e96f669 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -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

diff  --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index c88cbb1c3b5ef..725365231af5c 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -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

diff  --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index e9e173a831013..14043b039041c 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -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

diff  --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt
index 69a0acab6ad5f..bf52c8caccdfc 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -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

diff  --git a/libc/docs/strings.rst b/libc/docs/strings.rst
index c475134937861..50b479bf2117e 100644
--- a/libc/docs/strings.rst
+++ b/libc/docs/strings.rst
@@ -36,6 +36,7 @@ Function Name  Available
 =============  =========
 bzero          |check|
 bcmp           |check|
+bcopy          |check|       
 memcpy         |check|
 memset         |check|
 memcmp         |check|

diff  --git a/libc/spec/llvm_libc_ext.td b/libc/spec/llvm_libc_ext.td
index 76f06223756da..731671f7306bc 100644
--- a/libc/spec/llvm_libc_ext.td
+++ b/libc/spec/llvm_libc_ext.td
@@ -5,6 +5,11 @@ def LLVMLibcExt : StandardSpec<"llvm_libc_ext"> {
       [], // Types
       [], // Enumerations
       [
+          FunctionSpec<
+              "bcopy",
+              RetValSpec<VoidType>,
+              [ArgSpec<ConstVoidPtr>, ArgSpec<VoidPtr>, ArgSpec<SizeTType>]
+          >,
           FunctionSpec<
               "bzero",
               RetValSpec<VoidType>,

diff  --git a/libc/src/string/CMakeLists.txt b/libc/src/string/CMakeLists.txt
index 7719178da457b..422d24c131312 100644
--- a/libc/src/string/CMakeLists.txt
+++ b/libc/src/string/CMakeLists.txt
@@ -20,6 +20,14 @@ add_header_library(
     .memory_utils.memcpy_implementation
 )
 
+add_entrypoint_object(
+  bcopy
+  SRCS
+    bcopy.cpp
+  HDRS
+    bcopy.h
+)
+
 add_entrypoint_object(
   memccpy
   SRCS
@@ -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
index 0000000000000..9653c73f1305d
--- /dev/null
+++ b/libc/src/string/bcopy.cpp
@@ -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
index 0000000000000..12de749d4640d
--- /dev/null
+++ b/libc/src/string/bcopy.h
@@ -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

diff  --git a/libc/test/src/string/CMakeLists.txt b/libc/test/src/string/CMakeLists.txt
index b0b352913cc94..8b427cc2d116e 100644
--- a/libc/test/src/string/CMakeLists.txt
+++ b/libc/test/src/string/CMakeLists.txt
@@ -2,6 +2,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

diff  --git a/libc/test/src/string/bcopy_test.cpp b/libc/test/src/string/bcopy_test.cpp
new file mode 100644
index 0000000000000..fa57d2502c2de
--- /dev/null
+++ b/libc/test/src/string/bcopy_test.cpp
@@ -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);
+    }
+  }
+}

diff  --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 1aafa2a8473b1..48c84fc96e69f 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -1124,6 +1124,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"],

diff  --git a/utils/bazel/llvm-project-overlay/libc/test/src/string/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/src/string/BUILD.bazel
index 8ccc62767696d..cfda301ff2d7a 100644
--- a/utils/bazel/llvm-project-overlay/libc/test/src/string/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/test/src/string/BUILD.bazel
@@ -146,6 +146,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"],


        


More information about the libc-commits mailing list