1 //===-- Implementation of memmove -----------------------------------------===// 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/string/memmove.h" 10 11 #include "src/__support/common.h" 12 #include "src/__support/integer_operations.h" 13 #include "src/string/memory_utils/memcpy_implementations.h" 14 #include <stddef.h> // size_t, ptrdiff_t 15 16 namespace __llvm_libc { 17 18 static inline void move_byte_forward(char *dest_m, const char *src_m, 19 size_t count) { 20 for (size_t offset = 0; count; --count, ++offset) 21 dest_m[offset] = src_m[offset]; 22 } 23 24 static inline void move_byte_backward(char *dest_m, const char *src_m, 25 size_t count) { 26 for (size_t offset = count - 1; count; --count, --offset) 27 dest_m[offset] = src_m[offset]; 28 } 29 30 LLVM_LIBC_FUNCTION(void *, memmove, 31 (void *dst, const void *src, size_t count)) { 32 char *dest_c = reinterpret_cast<char *>(dst); 33 const char *src_c = reinterpret_cast<const char *>(src); 34 35 // If the distance between `src_c` and `dest_c` is equal to or greater 36 // than `count` (integerAbs(src_c - dest_c) >= count), they would not overlap. 37 // e.g. greater equal overlapping 38 // [12345678] [12345678] [12345678] 39 // src_c: [_ab_____] [_ab_____] [_ab_____] 40 // dest_c:[_____yz_] [___yz___] [__yz____] 41 42 // Call `memcpy` if `src_c` and `dest_c` do not overlap. 43 if (__llvm_libc::integer_abs(src_c - dest_c) >= 44 static_cast<ptrdiff_t>(count)) { 45 inline_memcpy(dest_c, src_c, count); 46 return dest_c; 47 } 48 49 // Overlapping cases. 50 // If `dest_c` starts before `src_c` (dest_c < src_c), copy 51 // forward(pointer add 1) from beginning to end. 52 // If `dest_c` starts after `src_c` (dest_c > src_c), copy 53 // backward(pointer add -1) from end to beginning. 54 // If `dest_c` and `src_c` start at the same address (dest_c == src_c), 55 // just return dest. 56 // e.g. forward backward 57 // *-> <-* 58 // src_c : [___abcde_] [_abcde___] 59 // dest_c: [_abc--___] [___--cde_] 60 61 // TODO: Optimize `move_byte_xxx(...)` functions. 62 if (dest_c < src_c) 63 move_byte_forward(dest_c, src_c, count); 64 if (dest_c > src_c) 65 move_byte_backward(dest_c, src_c, count); 66 return dst; 67 } 68 69 } // namespace __llvm_libc 70