1 //===-- Endianness support --------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_LIBC_SRC___SUPPORT_ENDIAN_INTERNAL_H
10 #define LLVM_LIBC_SRC___SUPPORT_ENDIAN_INTERNAL_H
13 #include "src/__support/macros/config.h"
17 namespace LIBC_NAMESPACE_DECL
{
19 // We rely on compiler preprocessor defines to allow for cross compilation.
20 #if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || \
21 !defined(__ORDER_BIG_ENDIAN__)
22 #error "Missing preprocessor definitions for endianness detection."
27 // Converts uint8_t, uint16_t, uint32_t, uint64_t to its big or little endian
29 // We use explicit template specialization:
30 // - to prevent accidental integer promotion.
31 // - to prevent fallback in (unlikely) case of middle-endianness.
33 template <unsigned ORDER
> struct Endian
{
34 static constexpr const bool IS_LITTLE
= ORDER
== __ORDER_LITTLE_ENDIAN__
;
35 static constexpr const bool IS_BIG
= ORDER
== __ORDER_BIG_ENDIAN__
;
36 template <typename T
> LIBC_INLINE
static T
to_big_endian(T value
);
37 template <typename T
> LIBC_INLINE
static T
to_little_endian(T value
);
40 // Little Endian specializations
44 Endian
<__ORDER_LITTLE_ENDIAN__
>::to_big_endian
<uint8_t>(uint8_t v
) {
50 Endian
<__ORDER_LITTLE_ENDIAN__
>::to_little_endian
<uint8_t>(uint8_t v
) {
56 Endian
<__ORDER_LITTLE_ENDIAN__
>::to_big_endian
<uint16_t>(uint16_t v
) {
57 return __builtin_bswap16(v
);
62 Endian
<__ORDER_LITTLE_ENDIAN__
>::to_little_endian
<uint16_t>(uint16_t v
) {
68 Endian
<__ORDER_LITTLE_ENDIAN__
>::to_big_endian
<uint32_t>(uint32_t v
) {
69 return __builtin_bswap32(v
);
74 Endian
<__ORDER_LITTLE_ENDIAN__
>::to_little_endian
<uint32_t>(uint32_t v
) {
80 Endian
<__ORDER_LITTLE_ENDIAN__
>::to_big_endian
<uint64_t>(uint64_t v
) {
81 return __builtin_bswap64(v
);
86 Endian
<__ORDER_LITTLE_ENDIAN__
>::to_little_endian
<uint64_t>(uint64_t v
) {
90 // Big Endian specializations
94 Endian
<__ORDER_BIG_ENDIAN__
>::to_big_endian
<uint8_t>(uint8_t v
) {
100 Endian
<__ORDER_BIG_ENDIAN__
>::to_little_endian
<uint8_t>(uint8_t v
) {
106 Endian
<__ORDER_BIG_ENDIAN__
>::to_big_endian
<uint16_t>(uint16_t v
) {
112 Endian
<__ORDER_BIG_ENDIAN__
>::to_little_endian
<uint16_t>(uint16_t v
) {
113 return __builtin_bswap16(v
);
118 Endian
<__ORDER_BIG_ENDIAN__
>::to_big_endian
<uint32_t>(uint32_t v
) {
124 Endian
<__ORDER_BIG_ENDIAN__
>::to_little_endian
<uint32_t>(uint32_t v
) {
125 return __builtin_bswap32(v
);
130 Endian
<__ORDER_BIG_ENDIAN__
>::to_big_endian
<uint64_t>(uint64_t v
) {
136 Endian
<__ORDER_BIG_ENDIAN__
>::to_little_endian
<uint64_t>(uint64_t v
) {
137 return __builtin_bswap64(v
);
140 } // namespace internal
142 using Endian
= internal::Endian
<__BYTE_ORDER__
>;
144 } // namespace LIBC_NAMESPACE_DECL
146 #endif // LLVM_LIBC_SRC___SUPPORT_ENDIAN_INTERNAL_H