forked from OSchip/llvm-project
Revert "[libc] Some clean work with memmove."
This reverts commit b659b789c0
.
This commit is contained in:
parent
d5c049a3f6
commit
cc84ce9129
|
@ -18,6 +18,17 @@ add_entrypoint_object(
|
|||
.string_utils
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
memmove
|
||||
SRCS
|
||||
memmove.cpp
|
||||
HDRS
|
||||
memmove.h
|
||||
DEPENDS
|
||||
libc.src.__support.integer_operations
|
||||
libc.src.string.memcpy
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
memrchr
|
||||
SRCS
|
||||
|
@ -324,27 +335,6 @@ else()
|
|||
add_memcpy(memcpy)
|
||||
endif()
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# memmove
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
function(add_memmove memmove_name)
|
||||
add_implementation(memmove ${memmove_name}
|
||||
SRCS ${MEMMOVE_SRC}
|
||||
HDRS ${LIBC_SOURCE_DIR}/src/string/memmove.h
|
||||
DEPENDS
|
||||
.memory_utils.memory_utils
|
||||
libc.src.__support.integer_operations
|
||||
libc.src.string.memcpy
|
||||
COMPILE_OPTIONS
|
||||
-fno-builtin-memmove
|
||||
${ARGN}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
set(MEMMOVE_SRC ${LIBC_SOURCE_DIR}/src/string/memmove.cpp)
|
||||
add_memmove(memmove)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# memset
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -15,50 +15,52 @@
|
|||
|
||||
namespace __llvm_libc {
|
||||
|
||||
static inline void move_byte_backward(char *dst, const char *src,
|
||||
size_t count) {
|
||||
for (size_t offset = count - 1; count; --count, --offset)
|
||||
dst[offset] = src[offset];
|
||||
static inline void move_byte_forward(char *dest_m, const char *src_m,
|
||||
size_t count) {
|
||||
for (size_t offset = 0; count; --count, ++offset)
|
||||
dest_m[offset] = src_m[offset];
|
||||
}
|
||||
|
||||
static void memmove_impl(char *dst, const char *src, size_t count) {
|
||||
|
||||
// If the distance between `src` and `dst` is equal to or greater
|
||||
// than count (integerAbs(src - dst) >= count), they would not overlap.
|
||||
// e.g. greater equal overlapping
|
||||
// [12345678] [12345678] [12345678]
|
||||
// src: [_ab_____] [_ab_____] [_ab_____]
|
||||
// dst: [_____yz_] [___yz___] [__yz____]
|
||||
|
||||
// Call `memcpy` when `src` and `dst` do not overlap.
|
||||
if (__llvm_libc::integerAbs(src - dst) >= static_cast<ptrdiff_t>(count))
|
||||
__llvm_libc::memcpy(dst, src, count);
|
||||
|
||||
// Overlap cases.
|
||||
// If `dst` starts before `src` (dst < src), copy forward from beginning to
|
||||
// end. If `dst` starts after `src` (dst > src), copy backward from end to
|
||||
// beginning. If `dst` and `src` start at the same address (dst == src), do
|
||||
// nothing.
|
||||
// e.g. forward backward
|
||||
// *-> <-*
|
||||
// src: [___abcde_] [_abcde___]
|
||||
// dst: [_abc--___] [___--cde_]
|
||||
|
||||
// In `memcpy` implementation, it copies bytes forward from beginning to
|
||||
// end. Otherwise, `memmove` unit tests will break.
|
||||
if (dst < src)
|
||||
__llvm_libc::memcpy(dst, src, count);
|
||||
|
||||
// TODO: Optimize `move_byte_xxx(...)` functions.
|
||||
if (dst > src)
|
||||
move_byte_backward(dst, src, count);
|
||||
static inline void move_byte_backward(char *dest_m, const char *src_m,
|
||||
size_t count) {
|
||||
for (size_t offset = count - 1; count; --count, --offset)
|
||||
dest_m[offset] = src_m[offset];
|
||||
}
|
||||
|
||||
LLVM_LIBC_FUNCTION(void *, memmove,
|
||||
(void *dst, const void *src, size_t count)) {
|
||||
memmove_impl(reinterpret_cast<char *>(dst),
|
||||
reinterpret_cast<const char *>(src), count);
|
||||
return dst;
|
||||
(void *dest, const void *src, size_t count)) {
|
||||
char *dest_c = reinterpret_cast<char *>(dest);
|
||||
const char *src_c = reinterpret_cast<const char *>(src);
|
||||
|
||||
// If the distance between src_c and dest_c is equal to or greater
|
||||
// than count (integerAbs(src_c - dest_c) >= count), they would not overlap.
|
||||
// e.g. greater equal overlapping
|
||||
// [12345678] [12345678] [12345678]
|
||||
// src_c: [_ab_____] [_ab_____] [_ab_____]
|
||||
// dest_c:[_____yz_] [___yz___] [__yz____]
|
||||
|
||||
// Use memcpy if src_c and dest_c do not overlap.
|
||||
if (__llvm_libc::integerAbs(src_c - dest_c) >= static_cast<ptrdiff_t>(count))
|
||||
return __llvm_libc::memcpy(dest_c, src_c, count);
|
||||
|
||||
// Overlap cases.
|
||||
// If dest_c starts before src_c (dest_c < src_c), copy forward(pointer add 1)
|
||||
// from beginning to end.
|
||||
// If dest_c starts after src_c (dest_c > src_c), copy backward(pointer add
|
||||
// -1) from end to beginning.
|
||||
// If dest_c and src_c start at the same address (dest_c == src_c),
|
||||
// just return dest.
|
||||
// e.g. forward backward
|
||||
// *--> <--*
|
||||
// src_c : [___abcde_] [_abcde___]
|
||||
// dest_c: [_abc--___] [___--cde_]
|
||||
|
||||
// TODO: Optimize `move_byte_xxx(...)` functions.
|
||||
if (dest_c < src_c)
|
||||
move_byte_forward(dest_c, src_c, count);
|
||||
if (dest_c > src_c)
|
||||
move_byte_backward(dest_c, src_c, count);
|
||||
return dest;
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
|
|
@ -6,65 +6,64 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/string/memcmp.h"
|
||||
#include "src/string/memmove.h"
|
||||
#include "utils/CPP/ArrayRef.h"
|
||||
#include "utils/UnitTest/Test.h"
|
||||
|
||||
class LlvmLibcMemmoveTest : public __llvm_libc::testing::Test {
|
||||
public:
|
||||
void check_memmove(void *dst, const void *src, size_t count,
|
||||
const unsigned char *str,
|
||||
void check_memmove(void *dest, const void *src, size_t count, const void *str,
|
||||
const __llvm_libc::cpp::ArrayRef<unsigned char> expected) {
|
||||
void *result = __llvm_libc::memmove(dst, src, count);
|
||||
// Making sure the pointer returned is same with `dst`.
|
||||
EXPECT_EQ(result, dst);
|
||||
// `expected` is designed according to `str`.
|
||||
// `dst` and `src` might be part of `str`.
|
||||
// Making sure `str` is same with `expected`.
|
||||
for (size_t i = 0; i < expected.size(); ++i)
|
||||
EXPECT_EQ(str[i], expected[i]);
|
||||
void *result = __llvm_libc::memmove(dest, src, count);
|
||||
// Making sure the pointer returned is same with dest.
|
||||
EXPECT_EQ(result, dest);
|
||||
// expected is designed according to str.
|
||||
// dest and src might be part of str.
|
||||
// Making sure the str is same with expected.
|
||||
EXPECT_EQ(__llvm_libc::memcmp(str, expected.data(), expected.size()), 0);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(LlvmLibcMemmoveTest, MoveZeroByte) {
|
||||
unsigned char dst[] = {'a', 'b'};
|
||||
unsigned char dest[] = {'a', 'b'};
|
||||
const unsigned char src[] = {'y', 'z'};
|
||||
const unsigned char expected[] = {'a', 'b'};
|
||||
check_memmove(dst, src, 0, dst, expected);
|
||||
check_memmove(dest, src, 0, dest, expected);
|
||||
}
|
||||
|
||||
TEST_F(LlvmLibcMemmoveTest, OverlapThatDstAndSrcPointToSameAddress) {
|
||||
TEST_F(LlvmLibcMemmoveTest, OverlapThatDestAndSrcPointToSameAddress) {
|
||||
unsigned char str[] = {'a', 'b'};
|
||||
const unsigned char expected[] = {'a', 'b'};
|
||||
check_memmove(str, str, 1, str, expected);
|
||||
}
|
||||
|
||||
TEST_F(LlvmLibcMemmoveTest, OverlapThatDstStartsBeforeSrc) {
|
||||
TEST_F(LlvmLibcMemmoveTest, OverlapThatDestStartsBeforeSrc) {
|
||||
// Set boundary at beginning and end for not overstepping when
|
||||
// copy forward or backward.
|
||||
unsigned char str[] = {'z', 'a', 'b', 'c', 'z'};
|
||||
const unsigned char expected[] = {'z', 'b', 'c', 'c', 'z'};
|
||||
// `dst` is `&str[1]`.
|
||||
// dest is &str[1].
|
||||
check_memmove(&str[1], &str[2], 2, str, expected);
|
||||
}
|
||||
|
||||
TEST_F(LlvmLibcMemmoveTest, OverlapThatDstStartsAfterSrc) {
|
||||
TEST_F(LlvmLibcMemmoveTest, OverlapThatDestStartsAfterSrc) {
|
||||
unsigned char str[] = {'z', 'a', 'b', 'c', 'z'};
|
||||
const unsigned char expected[] = {'z', 'a', 'a', 'b', 'z'};
|
||||
check_memmove(&str[2], &str[1], 2, str, expected);
|
||||
}
|
||||
|
||||
// e.g. `dst` follow `src`.
|
||||
// e.g. dest follow src.
|
||||
// str: [abcdefghij]
|
||||
// [__src_____]
|
||||
// [_____dst__]
|
||||
TEST_F(LlvmLibcMemmoveTest, SrcFollowDst) {
|
||||
// [_____dest_]
|
||||
TEST_F(LlvmLibcMemmoveTest, SrcFollowDest) {
|
||||
unsigned char str[] = {'z', 'a', 'b', 'z'};
|
||||
const unsigned char expected[] = {'z', 'b', 'b', 'z'};
|
||||
check_memmove(&str[1], &str[2], 1, str, expected);
|
||||
}
|
||||
|
||||
TEST_F(LlvmLibcMemmoveTest, DstFollowSrc) {
|
||||
TEST_F(LlvmLibcMemmoveTest, DestFollowSrc) {
|
||||
unsigned char str[] = {'z', 'a', 'b', 'z'};
|
||||
const unsigned char expected[] = {'z', 'a', 'a', 'z'};
|
||||
check_memmove(&str[2], &str[1], 1, str, expected);
|
||||
|
|
Loading…
Reference in New Issue