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