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/memcpy.h" 14 #include <stddef.h> // size_t, ptrdiff_t 15 16 namespace __llvm_libc { 17 18 static inline void move_byte_backward(char *dst, const char *src, 19 size_t count) { 20 for (size_t offset = count - 1; count; --count, --offset) 21 dst[offset] = src[offset]; 22 } 23 24 static void memmove_impl(char *dst, const char *src, size_t count) { 25 26 // If the distance between `src` and `dst` is equal to or greater 27 // than count (integerAbs(src - dst) >= count), they would not overlap. 28 // e.g. greater equal overlapping 29 // [12345678] [12345678] [12345678] 30 // src: [_ab_____] [_ab_____] [_ab_____] 31 // dst: [_____yz_] [___yz___] [__yz____] 32 33 // Call `memcpy` when `src` and `dst` do not overlap. 34 if (__llvm_libc::integerAbs(src - dst) >= static_cast<ptrdiff_t>(count)) 35 __llvm_libc::memcpy(dst, src, count); 36 37 // Overlap cases. 38 // If `dst` starts before `src` (dst < src), copy forward from beginning to 39 // end. If `dst` starts after `src` (dst > src), copy backward from end to 40 // beginning. If `dst` and `src` start at the same address (dst == src), do 41 // nothing. 42 // e.g. forward backward 43 // *-> <-* 44 // src: [___abcde_] [_abcde___] 45 // dst: [_abc--___] [___--cde_] 46 47 // In `memcpy` implementation, it copies bytes forward from beginning to 48 // end. Otherwise, `memmove` unit tests will break. 49 if (dst < src) 50 __llvm_libc::memcpy(dst, src, count); 51 52 // TODO: Optimize `move_byte_xxx(...)` functions. 53 if (dst > src) 54 move_byte_backward(dst, src, count); 55 } 56 57 LLVM_LIBC_FUNCTION(void *, memmove, 58 (void *dst, const void *src, size_t count)) { 59 memmove_impl(reinterpret_cast<char *>(dst), 60 reinterpret_cast<const char *>(src), count); 61 return dst; 62 } 63 64 } // namespace __llvm_libc 65