Skip to content

Commit b184672

Browse files
authored
[libc] Implemented wmemmove (#142245)
Implemented wmemmove and added tests
1 parent 3bf1e1f commit b184672

File tree

7 files changed

+191
-0
lines changed

7 files changed

+191
-0
lines changed

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ set(TARGET_LIBC_ENTRYPOINTS
367367
libc.src.wchar.btowc
368368
libc.src.wchar.wcslen
369369
libc.src.wchar.wctob
370+
libc.src.wchar.wmemmove
370371
libc.src.wchar.wmemset
371372
libc.src.wchar.wcschr
372373
libc.src.wchar.wcsncmp

libc/include/wchar.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,14 @@ functions:
112112
- type: __restrict wchar_t *
113113
- type: const __restrict wchar_t *
114114
- type: size_t
115+
- name: wmemmove
116+
standards:
117+
- stdc
118+
return_type: wchar_t *
119+
arguments:
120+
- type: wchar_t *
121+
- type: const wchar_t *
122+
- type: size_t
115123
- name: wcsncpy
116124
standards:
117125
- stdc

libc/src/wchar/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,18 @@ add_entrypoint_object(
131131
libc.hdr.wchar_macros
132132
)
133133

134+
add_entrypoint_object(
135+
wmemmove
136+
SRCS
137+
wmemmove.cpp
138+
HDRS
139+
wmemmove.h
140+
DEPENDS
141+
libc.hdr.types.size_t
142+
libc.hdr.wchar_macros
143+
libc.src.__support.macros.null_check
144+
)
145+
134146
add_entrypoint_object(
135147
wcsncpy
136148
SRCS

libc/src/wchar/wmemmove.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//===-- Implementation of wmemmove ----------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/wchar/wmemmove.h"
10+
11+
#include "hdr/types/size_t.h"
12+
#include "hdr/types/wchar_t.h"
13+
#include "src/__support/common.h"
14+
#include "src/__support/macros/null_check.h"
15+
16+
namespace LIBC_NAMESPACE_DECL {
17+
18+
LLVM_LIBC_FUNCTION(wchar_t *, wmemmove,
19+
(wchar_t * dest, const wchar_t *src, size_t n)) {
20+
LIBC_CRASH_ON_NULLPTR(dest);
21+
LIBC_CRASH_ON_NULLPTR(src);
22+
23+
__builtin_memmove(dest, src, n * sizeof(wchar_t));
24+
return dest;
25+
}
26+
27+
} // namespace LIBC_NAMESPACE_DECL

libc/src/wchar/wmemmove.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//===-- Implementation header for wmemmove --------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_WCHAR_WMEMMOVE_H
10+
#define LLVM_LIBC_SRC_WCHAR_WMEMMOVE_H
11+
12+
#include "hdr/types/size_t.h"
13+
#include "hdr/types/wchar_t.h"
14+
#include "src/__support/macros/config.h"
15+
16+
namespace LIBC_NAMESPACE_DECL {
17+
18+
wchar_t *wmemmove(wchar_t *dest, const wchar_t *src, size_t n);
19+
20+
} // namespace LIBC_NAMESPACE_DECL
21+
22+
#endif // LLVM_LIBC_SRC_WCHAR_WMEMMOVE_H

libc/test/src/wchar/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,16 @@ add_libc_test(
145145
libc.src.wchar.wmemcpy
146146
)
147147

148+
add_libc_test(
149+
wmemmove_test
150+
SUITE
151+
libc_wchar_unittests
152+
SRCS
153+
wmemmove_test.cpp
154+
DEPENDS
155+
libc.src.wchar.wmemmove
156+
)
157+
148158
add_libc_test(
149159
wcsncpy_test
150160
SUITE

libc/test/src/wchar/wmemmove_test.cpp

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
//===-- Unittests for wmemmove --------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "hdr/types/size_t.h"
10+
#include "hdr/types/wchar_t.h"
11+
#include "src/wchar/wmemmove.h"
12+
#include "test/UnitTest/Test.h"
13+
14+
TEST(LlvmLibcWMemmoveTest, MoveZeroByte) {
15+
wchar_t buffer[] = {L'a', L'b', L'y', L'z'};
16+
17+
wchar_t *ret = LIBC_NAMESPACE::wmemmove(buffer, buffer + 2, 0);
18+
EXPECT_EQ(ret, buffer);
19+
20+
const wchar_t expected[] = {L'a', L'b', L'y', L'z'};
21+
EXPECT_TRUE(buffer[0] == expected[0]);
22+
EXPECT_TRUE(buffer[1] == expected[1]);
23+
EXPECT_TRUE(buffer[2] == expected[2]);
24+
EXPECT_TRUE(buffer[3] == expected[3]);
25+
}
26+
27+
TEST(LlvmLibcWMemmoveTest, DstAndSrcPointToSameAddress) {
28+
wchar_t buffer[] = {L'a', L'b'};
29+
30+
wchar_t *ret = LIBC_NAMESPACE::wmemmove(buffer, buffer, 1);
31+
EXPECT_EQ(ret, buffer);
32+
33+
const wchar_t expected[] = {L'a', L'b'};
34+
EXPECT_TRUE(buffer[0] == expected[0]);
35+
EXPECT_TRUE(buffer[1] == expected[1]);
36+
}
37+
38+
TEST(LlvmLibcWMemmoveTest, DstStartsBeforeSrc) {
39+
// Set boundary at beginning and end for not overstepping when
40+
// copy forward or backward.
41+
wchar_t buffer[] = {L'z', L'a', L'b', L'c', L'z'};
42+
43+
wchar_t *dst = buffer + 1;
44+
wchar_t *ret = LIBC_NAMESPACE::wmemmove(dst, buffer + 2, 2);
45+
EXPECT_EQ(ret, dst);
46+
47+
const wchar_t expected[] = {L'z', L'b', L'c', L'c', L'z'};
48+
EXPECT_TRUE(buffer[0] == expected[0]);
49+
EXPECT_TRUE(buffer[1] == expected[1]);
50+
EXPECT_TRUE(buffer[2] == expected[2]);
51+
EXPECT_TRUE(buffer[3] == expected[3]);
52+
EXPECT_TRUE(buffer[4] == expected[4]);
53+
}
54+
55+
TEST(LlvmLibcWMemmoveTest, DstStartsAfterSrc) {
56+
wchar_t buffer[] = {L'z', L'a', L'b', L'c', L'z'};
57+
58+
wchar_t *dst = buffer + 2;
59+
wchar_t *ret = LIBC_NAMESPACE::wmemmove(dst, buffer + 1, 2);
60+
EXPECT_EQ(ret, dst);
61+
62+
const wchar_t expected[] = {L'z', L'a', L'a', L'b', L'z'};
63+
EXPECT_TRUE(buffer[0] == expected[0]);
64+
EXPECT_TRUE(buffer[1] == expected[1]);
65+
EXPECT_TRUE(buffer[2] == expected[2]);
66+
EXPECT_TRUE(buffer[3] == expected[3]);
67+
EXPECT_TRUE(buffer[4] == expected[4]);
68+
}
69+
70+
// e.g. `Dst` follow `src`.
71+
// str: [abcdefghij]
72+
// [__src_____]
73+
// [_____Dst__]
74+
TEST(LlvmLibcWMemmoveTest, SrcFollowDst) {
75+
wchar_t buffer[] = {L'z', L'a', L'b', L'z'};
76+
77+
wchar_t *dst = buffer + 1;
78+
wchar_t *ret = LIBC_NAMESPACE::wmemmove(dst, buffer + 2, 1);
79+
EXPECT_EQ(ret, dst);
80+
81+
const char expected[] = {L'z', L'b', L'b', L'z'};
82+
EXPECT_TRUE(buffer[0] == expected[0]);
83+
EXPECT_TRUE(buffer[1] == expected[1]);
84+
EXPECT_TRUE(buffer[2] == expected[2]);
85+
EXPECT_TRUE(buffer[3] == expected[3]);
86+
}
87+
88+
TEST(LlvmLibcWMemmoveTest, DstFollowSrc) {
89+
wchar_t buffer[] = {L'z', L'a', L'b', L'z'};
90+
91+
wchar_t *dst = buffer + 2;
92+
wchar_t *ret = LIBC_NAMESPACE::wmemmove(dst, buffer + 1, 1);
93+
EXPECT_EQ(ret, dst);
94+
95+
const char expected[] = {L'z', L'a', L'a', L'z'};
96+
EXPECT_TRUE(buffer[0] == expected[0]);
97+
EXPECT_TRUE(buffer[1] == expected[1]);
98+
EXPECT_TRUE(buffer[2] == expected[2]);
99+
EXPECT_TRUE(buffer[3] == expected[3]);
100+
}
101+
102+
#if defined(LIBC_ADD_NULL_CHECKS) && !defined(LIBC_HAS_SANITIZER)
103+
TEST(LlvmLibcWMemmoveTest, NullptrCrash) {
104+
wchar_t buffer[] = {L'a', L'b'};
105+
// Passing in a nullptr should crash the program.
106+
EXPECT_DEATH([&buffer] { LIBC_NAMESPACE::wmemmove(buffer, nullptr, 2); },
107+
WITH_SIGNAL(-1));
108+
EXPECT_DEATH([&buffer] { LIBC_NAMESPACE::wmemmove(nullptr, buffer, 2); },
109+
WITH_SIGNAL(-1));
110+
}
111+
#endif // LIBC_HAS_ADDRESS_SANITIZER

0 commit comments

Comments
 (0)