#ifndef LLVM_LIBC_SRC_STRING_MEMORY_UTILS_OP_BUILTIN_H
#define LLVM_LIBC_SRC_STRING_MEMORY_UTILS_OP_BUILTIN_H
#include "src/__support/CPP/type_traits.h"
#include "src/__support/macros/config.h"
#include "src/string/memory_utils/utils.h"
namespace LIBC_NAMESPACE_DECL {
namespace builtin {
template <size_t Size> struct Memcpy {
static constexpr size_t SIZE = Size;
LIBC_INLINE static void block_offset(Ptr __restrict dst, CPtr __restrict src,
size_t offset) {
memcpy_inline<Size>(dst + offset, src + offset);
}
LIBC_INLINE static void block(Ptr __restrict dst, CPtr __restrict src) {
block_offset(dst, src, 0);
}
LIBC_INLINE static void tail(Ptr __restrict dst, CPtr __restrict src,
size_t count) {
block_offset(dst, src, count - SIZE);
}
LIBC_INLINE static void head_tail(Ptr __restrict dst, CPtr __restrict src,
size_t count) {
block(dst, src);
tail(dst, src, count);
}
LIBC_INLINE static void loop_and_tail_offset(Ptr __restrict dst,
CPtr __restrict src,
size_t count, size_t offset) {
static_assert(Size > 1, "a loop of size 1 does not need tail");
do {
block_offset(dst, src, offset);
offset += SIZE;
} while (offset < count - SIZE);
tail(dst, src, count);
}
LIBC_INLINE static void loop_and_tail(Ptr __restrict dst, CPtr __restrict src,
size_t count) {
return loop_and_tail_offset(dst, src, count, 0);
}
};
template <size_t Size> struct Memset {
using ME = Memset;
static constexpr size_t SIZE = Size;
LIBC_INLINE static void block(Ptr dst, uint8_t value) {
#ifdef LLVM_LIBC_HAS_BUILTIN_MEMSET_INLINE
__builtin_memset_inline(dst, value, Size);
#else
static_assert(cpp::always_false<decltype(Size)>,
"Missing __builtin_memset_inline");
(void)dst;
(void)value;
#endif
}
LIBC_INLINE static void tail(Ptr dst, uint8_t value, size_t count) {
block(dst + count - SIZE, value);
}
LIBC_INLINE static void head_tail(Ptr dst, uint8_t value, size_t count) {
block(dst, value);
tail(dst, value, count);
}
LIBC_INLINE static void loop_and_tail(Ptr dst, uint8_t value, size_t count) {
static_assert(Size > 1, "a loop of size 1 does not need tail");
size_t offset = 0;
do {
block(dst + offset, value);
offset += SIZE;
} while (offset < count - SIZE);
tail(dst, value, count);
}
};
template <size_t Size> struct Bcmp {
using ME = Bcmp;
static constexpr size_t SIZE = Size;
LIBC_INLINE static BcmpReturnType block(CPtr, CPtr) {
static_assert(cpp::always_false<decltype(Size)>,
"Missing __builtin_memcmp_inline");
return BcmpReturnType::zero();
}
LIBC_INLINE static BcmpReturnType tail(CPtr, CPtr, size_t) {
static_assert(cpp::always_false<decltype(Size)>, "Not implemented");
return BcmpReturnType::zero();
}
LIBC_INLINE static BcmpReturnType head_tail(CPtr, CPtr, size_t) {
static_assert(cpp::always_false<decltype(Size)>, "Not implemented");
return BcmpReturnType::zero();
}
LIBC_INLINE static BcmpReturnType loop_and_tail(CPtr, CPtr, size_t) {
static_assert(cpp::always_false<decltype(Size)>, "Not implemented");
return BcmpReturnType::zero();
}
};
template <size_t Size> struct Memcmp {
using ME = Memcmp;
static constexpr size_t SIZE = Size;
LIBC_INLINE static MemcmpReturnType block(CPtr, CPtr) {
static_assert(cpp::always_false<decltype(Size)>,
"Missing __builtin_memcmp_inline");
return MemcmpReturnType::zero();
}
LIBC_INLINE static MemcmpReturnType tail(CPtr, CPtr, size_t) {
static_assert(cpp::always_false<decltype(Size)>, "Not implemented");
return MemcmpReturnType::zero();
}
LIBC_INLINE static MemcmpReturnType head_tail(CPtr, CPtr, size_t) {
static_assert(cpp::always_false<decltype(Size)>, "Not implemented");
return MemcmpReturnType::zero();
}
LIBC_INLINE static MemcmpReturnType loop_and_tail(CPtr, CPtr, size_t) {
static_assert(cpp::always_false<decltype(Size)>, "Not implemented");
return MemcmpReturnType::zero();
}
};
}
}
#endif