-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[libc] Implemented wmemmove #142245
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[libc] Implemented wmemmove #142245
Conversation
@llvm/pr-subscribers-libc Author: Uzair Nawaz (uzairnawaz) ChangesImplemented wmemmove and added tests Full diff: https://github.com/llvm/llvm-project/pull/142245.diff 7 Files Affected:
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 7ddeb4d31b466..ffedf8e088fe5 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -364,6 +364,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.wchar.btowc
libc.src.wchar.wcslen
libc.src.wchar.wctob
+ libc.src.wchar.wmemmove
libc.src.wchar.wmemset
libc.src.wchar.wcschr
libc.src.wchar.wcspbrk
diff --git a/libc/include/wchar.yaml b/libc/include/wchar.yaml
index bd9105f69222c..5117e795d35ea 100644
--- a/libc/include/wchar.yaml
+++ b/libc/include/wchar.yaml
@@ -72,3 +72,11 @@ functions:
- type: __restricted wchar_t *
- type: const __ restricted wchar_t *
- type: size_t
+ - name: wmemmove
+ standards:
+ - stdc
+ return_type: wchar_t *
+ arguments:
+ - type: wchar_t *
+ - type: const wchar_t *
+ - type: size_t
diff --git a/libc/src/wchar/CMakeLists.txt b/libc/src/wchar/CMakeLists.txt
index 9db121762348b..6d839317fb8d8 100644
--- a/libc/src/wchar/CMakeLists.txt
+++ b/libc/src/wchar/CMakeLists.txt
@@ -104,3 +104,16 @@ add_entrypoint_object(
libc.hdr.wchar_macros
libc.src.__support.wctype_utils
)
+
+add_entrypoint_object(
+ wmemmove
+ SRCS
+ wmemmove.cpp
+ HDRS
+ wmemmove.h
+ DEPENDS
+ libc.hdr.types.size_t
+ libc.hdr.wchar_macros
+ libc.src.__support.wctype_utils
+ libc.src.__support.macros.null_check
+)
diff --git a/libc/src/wchar/wmemmove.cpp b/libc/src/wchar/wmemmove.cpp
new file mode 100644
index 0000000000000..2b7cf21f52667
--- /dev/null
+++ b/libc/src/wchar/wmemmove.cpp
@@ -0,0 +1,28 @@
+//===-- Implementation of wmemmove ----------------------------------------===//
+//
+// 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/wchar/wmemmove.h"
+
+#include "hdr/types/size_t.h"
+#include "hdr/types/wchar_t.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/null_check.h"
+#include "src/string/memory_utils/inline_memmove.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(wchar_t *, wmemmove,
+ (wchar_t *dest, const wchar_t *src, size_t n)) {
+ LIBC_CRASH_ON_NULLPTR(dest);
+ LIBC_CRASH_ON_NULLPTR(src);
+
+ inline_memmove(dest, src, n * sizeof(wchar_t));
+ return dest;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/wchar/wmemmove.h b/libc/src/wchar/wmemmove.h
new file mode 100644
index 0000000000000..b4c31ac7b397c
--- /dev/null
+++ b/libc/src/wchar/wmemmove.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for wmemmove --------------------------------===//
+//
+// 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_WCHAR_WMEMMOVE_H
+#define LLVM_LIBC_SRC_WCHAR_WMEMMOVE_H
+
+#include "hdr/types/size_t.h"
+#include "hdr/types/wchar_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+wchar_t *wmemmove(wchar_t *dest, const wchar_t *src, size_t n);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_WCHAR_WMEMMOVE_H
diff --git a/libc/test/src/wchar/CMakeLists.txt b/libc/test/src/wchar/CMakeLists.txt
index 9bc230e0bddf3..afe283475be69 100644
--- a/libc/test/src/wchar/CMakeLists.txt
+++ b/libc/test/src/wchar/CMakeLists.txt
@@ -94,3 +94,13 @@ add_libc_test(
DEPENDS
libc.src.wchar.wmemcpy
)
+
+add_libc_test(
+ wmemmove_test
+ SUITE
+ libc_wchar_unittests
+ SRCS
+ wmemmove_test.cpp
+ DEPENDS
+ libc.src.wchar.wmemmove
+)
diff --git a/libc/test/src/wchar/wmemmove_test.cpp b/libc/test/src/wchar/wmemmove_test.cpp
new file mode 100644
index 0000000000000..d23aa0f0b3af1
--- /dev/null
+++ b/libc/test/src/wchar/wmemmove_test.cpp
@@ -0,0 +1,111 @@
+//===-- Unittests for wmemmove --------------------------------------------===//
+//
+// 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 "hdr/types/size_t.h"
+#include "hdr/types/wchar_t.h"
+#include "src/wchar/wmemmove.h"
+#include "test/UnitTest/Test.h"
+
+TEST(LlvmLibcWMemmoveTest, MoveZeroByte) {
+ wchar_t buffer[] = {L'a', L'b', L'y', L'z'};
+
+ wchar_t *ret = LIBC_NAMESPACE::wmemmove(buffer, buffer + 2, 0);
+ EXPECT_EQ(ret, buffer);
+
+ const wchar_t expected[] = {L'a', L'b', L'y', L'z'};
+ EXPECT_TRUE(buffer[0] == expected[0]);
+ EXPECT_TRUE(buffer[1] == expected[1]);
+ EXPECT_TRUE(buffer[2] == expected[2]);
+ EXPECT_TRUE(buffer[3] == expected[3]);
+}
+
+TEST(LlvmLibcWMemmoveTest, DstAndSrcPointToSameAddress) {
+ wchar_t buffer[] = {L'a', L'b'};
+
+ wchar_t *ret = LIBC_NAMESPACE::wmemmove(buffer, buffer, 1);
+ EXPECT_EQ(ret, buffer);
+
+ const wchar_t expected[] = {L'a', L'b'};
+ EXPECT_TRUE(buffer[0] == expected[0]);
+ EXPECT_TRUE(buffer[1] == expected[1]);
+}
+
+TEST(LlvmLibcWMemmoveTest, DstStartsBeforeSrc) {
+ // Set boundary at beginning and end for not overstepping when
+ // copy forward or backward.
+ wchar_t buffer[] = {L'z', L'a', L'b', L'c', L'z'};
+
+ wchar_t *dst = buffer + 1;
+ wchar_t *ret = LIBC_NAMESPACE::wmemmove(dst, buffer + 2, 2);
+ EXPECT_EQ(ret, dst);
+
+ const wchar_t expected[] = {L'z', L'b', L'c', L'c', L'z'};
+ EXPECT_TRUE(buffer[0] == expected[0]);
+ EXPECT_TRUE(buffer[1] == expected[1]);
+ EXPECT_TRUE(buffer[2] == expected[2]);
+ EXPECT_TRUE(buffer[3] == expected[3]);
+ EXPECT_TRUE(buffer[4] == expected[4]);
+}
+
+TEST(LlvmLibcWMemmoveTest, DstStartsAfterSrc) {
+ wchar_t buffer[] = {L'z', L'a', L'b', L'c', L'z'};
+
+ wchar_t *dst = buffer + 2;
+ wchar_t *ret = LIBC_NAMESPACE::wmemmove(dst, buffer + 1, 2);
+ EXPECT_EQ(ret, dst);
+
+ const wchar_t expected[] = {L'z', L'a', L'a', L'b', L'z'};
+ EXPECT_TRUE(buffer[0] == expected[0]);
+ EXPECT_TRUE(buffer[1] == expected[1]);
+ EXPECT_TRUE(buffer[2] == expected[2]);
+ EXPECT_TRUE(buffer[3] == expected[3]);
+ EXPECT_TRUE(buffer[4] == expected[4]);
+}
+
+// e.g. `Dst` follow `src`.
+// str: [abcdefghij]
+// [__src_____]
+// [_____Dst__]
+TEST(LlvmLibcWMemmoveTest, SrcFollowDst) {
+ wchar_t buffer[] = {L'z', L'a', L'b', L'z'};
+
+ wchar_t *dst = buffer + 1;
+ wchar_t *ret = LIBC_NAMESPACE::wmemmove(dst, buffer + 2, 1);
+ EXPECT_EQ(ret, dst);
+
+ const char expected[] = {L'z', L'b', L'b', L'z'};
+ EXPECT_TRUE(buffer[0] == expected[0]);
+ EXPECT_TRUE(buffer[1] == expected[1]);
+ EXPECT_TRUE(buffer[2] == expected[2]);
+ EXPECT_TRUE(buffer[3] == expected[3]);
+}
+
+TEST(LlvmLibcWMemmoveTest, DstFollowSrc) {
+ wchar_t buffer[] = {L'z', L'a', L'b', L'z'};
+
+ wchar_t *dst = buffer + 2;
+ wchar_t *ret = LIBC_NAMESPACE::wmemmove(dst, buffer + 1, 1);
+ EXPECT_EQ(ret, dst);
+
+ const char expected[] = {L'z', L'a', L'a', L'z'};
+ EXPECT_TRUE(buffer[0] == expected[0]);
+ EXPECT_TRUE(buffer[1] == expected[1]);
+ EXPECT_TRUE(buffer[2] == expected[2]);
+ EXPECT_TRUE(buffer[3] == expected[3]);
+}
+
+#if defined(LIBC_ADD_NULL_CHECKS) && !defined(LIBC_HAS_SANITIZER)
+TEST(LlvmLibcWMemmoveTest, NullptrCrash) {
+ wchar_t buffer[] = {L'a', L'b'};
+ // Passing in a nullptr should crash the program.
+ EXPECT_DEATH([&buffer] { LIBC_NAMESPACE::wmemmove(buffer, nullptr, 2); },
+ WITH_SIGNAL(-1));
+ EXPECT_DEATH([&buffer] { LIBC_NAMESPACE::wmemmove(nullptr, buffer, 2); },
+ WITH_SIGNAL(-1));
+}
+#endif // LIBC_HAS_ADDRESS_SANITIZER
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
overall LGTM with a build fix
libc/src/wchar/CMakeLists.txt
Outdated
DEPENDS | ||
libc.hdr.types.size_t | ||
libc.hdr.wchar_macros | ||
libc.src.__support.wctype_utils |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this function uses inline_memmove
and not wctype_utils
, need to correct the dependency here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
libc/src/wchar/wmemmove.cpp
Outdated
LIBC_CRASH_ON_NULLPTR(dest); | ||
LIBC_CRASH_ON_NULLPTR(src); | ||
|
||
inline_memmove(dest, src, n * sizeof(wchar_t)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the memory functions we're moving away from calling the internal ones and towards using the builtins. For that reason this should be __builtin_memmove
Implemented wmemmove and added tests
Implemented wmemmove and added tests
Implemented wmemmove and added tests