41 changes: 21 additions & 20 deletions libc/src/string/memory_utils/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,7 @@ LIBC_INLINE uintptr_t distance_to_next_aligned(const void *ptr) {
}

// Returns the same pointer but notifies the compiler that it is aligned.
template <size_t alignment, typename T>
LIBC_INLINE T *assume_aligned(T *ptr) {
template <size_t alignment, typename T> LIBC_INLINE T *assume_aligned(T *ptr) {
return reinterpret_cast<T *>(__builtin_assume_aligned(ptr, alignment));
}

Expand Down Expand Up @@ -117,10 +116,10 @@ LIBC_INLINE void memcpy_inline(void *__restrict dst,
#ifdef LLVM_LIBC_HAS_BUILTIN_MEMCPY_INLINE
__builtin_memcpy_inline(dst, src, Size);
#else
// In memory functions `memcpy_inline` is instantiated several times with
// different value of the Size parameter. This doesn't play well with GCC's
// Value Range Analysis that wrongly detects out of bounds accesses. We disable
// the 'array-bounds' warning for the purpose of this function.
// In memory functions `memcpy_inline` is instantiated several times with
// different value of the Size parameter. This doesn't play well with GCC's
// Value Range Analysis that wrongly detects out of bounds accesses. We
// disable the 'array-bounds' warning for the purpose of this function.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds"
for (size_t i = 0; i < Size; ++i)
Expand All @@ -139,20 +138,21 @@ template <typename T> struct StrictIntegralType {

// Can only be constructed from a T.
template <typename U, cpp::enable_if_t<cpp::is_same_v<U, T>, bool> = 0>
StrictIntegralType(U value) : value(value) {}
LIBC_INLINE StrictIntegralType(U value) : value(value) {}

// Allows using the type in an if statement.
explicit operator bool() const { return value; }
LIBC_INLINE explicit operator bool() const { return value; }

// If type is unsigned (bcmp) we allow bitwise OR operations.
StrictIntegralType operator|(const StrictIntegralType &Rhs) const {
LIBC_INLINE StrictIntegralType
operator|(const StrictIntegralType &Rhs) const {
static_assert(!cpp::is_signed_v<T>);
return value | Rhs.value;
}

// For interation with the C API we allow explicit conversion back to the
// `int` type.
explicit operator int() const {
LIBC_INLINE explicit operator int() const {
// bit_cast makes sure that T and int have the same size.
return cpp::bit_cast<int>(value);
}
Expand Down Expand Up @@ -252,7 +252,7 @@ template <typename T> LIBC_INLINE void store(Ptr ptr, T value) {
// be aligned.
// e.g. load_aligned<uint32_t, uint16_t, uint16_t>(ptr);
template <typename ValueType, typename T, typename... TS>
ValueType load_aligned(CPtr src) {
LIBC_INLINE ValueType load_aligned(CPtr src) {
static_assert(sizeof(ValueType) >= (sizeof(T) + ... + sizeof(TS)));
const ValueType value = load<T>(assume_aligned<sizeof(T)>(src));
if constexpr (sizeof...(TS) > 0) {
Expand All @@ -271,14 +271,14 @@ ValueType load_aligned(CPtr src) {

// Alias for loading a 'uint32_t'.
template <typename T, typename... TS>
auto load32_aligned(CPtr src, size_t offset) {
LIBC_INLINE auto load32_aligned(CPtr src, size_t offset) {
static_assert((sizeof(T) + ... + sizeof(TS)) == sizeof(uint32_t));
return load_aligned<uint32_t, T, TS...>(src + offset);
}

// Alias for loading a 'uint64_t'.
template <typename T, typename... TS>
auto load64_aligned(CPtr src, size_t offset) {
LIBC_INLINE auto load64_aligned(CPtr src, size_t offset) {
static_assert((sizeof(T) + ... + sizeof(TS)) == sizeof(uint64_t));
return load_aligned<uint64_t, T, TS...>(src + offset);
}
Expand All @@ -287,7 +287,7 @@ auto load64_aligned(CPtr src, size_t offset) {
// to be aligned.
// e.g. store_aligned<uint32_t, uint16_t, uint16_t>(value, ptr);
template <typename ValueType, typename T, typename... TS>
void store_aligned(ValueType value, Ptr dst) {
LIBC_INLINE void store_aligned(ValueType value, Ptr dst) {
static_assert(sizeof(ValueType) >= (sizeof(T) + ... + sizeof(TS)));
constexpr size_t shift = sizeof(T) * 8;
if constexpr (Endian::IS_LITTLE) {
Expand All @@ -306,14 +306,14 @@ void store_aligned(ValueType value, Ptr dst) {

// Alias for storing a 'uint32_t'.
template <typename T, typename... TS>
void store32_aligned(uint32_t value, Ptr dst, size_t offset) {
LIBC_INLINE void store32_aligned(uint32_t value, Ptr dst, size_t offset) {
static_assert((sizeof(T) + ... + sizeof(TS)) == sizeof(uint32_t));
store_aligned<uint32_t, T, TS...>(value, dst + offset);
}

// Alias for storing a 'uint64_t'.
template <typename T, typename... TS>
void store64_aligned(uint64_t value, Ptr dst, size_t offset) {
LIBC_INLINE void store64_aligned(uint64_t value, Ptr dst, size_t offset) {
static_assert((sizeof(T) + ... + sizeof(TS)) == sizeof(uint64_t));
store_aligned<uint64_t, T, TS...>(value, dst + offset);
}
Expand All @@ -340,7 +340,7 @@ void align_p1_to_next_boundary(T1 *__restrict &p1, T2 *__restrict &p2,

// Same as align_p1_to_next_boundary above but with a single pointer instead.
template <size_t SIZE, typename T1>
void align_to_next_boundary(T1 *&p1, size_t &count) {
LIBC_INLINE void align_to_next_boundary(T1 *&p1, size_t &count) {
CPtr dummy;
align_p1_to_next_boundary<SIZE>(p1, dummy, count);
}
Expand All @@ -351,8 +351,8 @@ enum class Arg { P1, P2, Dst = P1, Src = P2 };
// Same as align_p1_to_next_boundary but allows for aligning p2 instead of p1.
// Precondition: &p1 != &p2
template <size_t SIZE, Arg AlignOn, typename T1, typename T2>
void align_to_next_boundary(T1 *__restrict &p1, T2 *__restrict &p2,
size_t &count) {
LIBC_INLINE void align_to_next_boundary(T1 *__restrict &p1, T2 *__restrict &p2,
size_t &count) {
if constexpr (AlignOn == Arg::P1)
align_p1_to_next_boundary<SIZE>(p1, p2, count);
else if constexpr (AlignOn == Arg::P2)
Expand All @@ -362,7 +362,8 @@ void align_to_next_boundary(T1 *__restrict &p1, T2 *__restrict &p2,
}

template <size_t SIZE> struct AlignHelper {
AlignHelper(CPtr ptr) : offset_(distance_to_next_aligned<SIZE>(ptr)) {}
LIBC_INLINE AlignHelper(CPtr ptr)
: offset_(distance_to_next_aligned<SIZE>(ptr)) {}

LIBC_INLINE bool not_aligned() const { return offset_ != SIZE; }
LIBC_INLINE uintptr_t offset() const { return offset_; }
Expand Down
4 changes: 2 additions & 2 deletions libc/src/string/string_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
namespace __llvm_libc {
namespace internal {

template <typename Word> constexpr Word repeat_byte(Word byte) {
template <typename Word> LIBC_INLINE constexpr Word repeat_byte(Word byte) {
constexpr size_t BITS_IN_BYTE = 8;
constexpr size_t BYTE_MASK = 0xff;
Word result = 0;
Expand All @@ -49,7 +49,7 @@ template <typename Word> constexpr Word repeat_byte(Word byte) {
// with the inverse of the original byte. This means that any byte that had the
// high bit set will no longer have it set, narrowing the list of bytes which
// result in non-zero values to just the zero byte.
template <typename Word> constexpr bool has_zeroes(Word block) {
template <typename Word> LIBC_INLINE constexpr bool has_zeroes(Word block) {
constexpr Word LOW_BITS = repeat_byte<Word>(0x01);
constexpr Word HIGH_BITS = repeat_byte<Word>(0x80);
Word subtracted = block - LOW_BITS;
Expand Down