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_H
10 #define LLVM_LIBC_SRC_SUPPORT_ENDIAN_H
16 namespace __llvm_libc
{
18 // We rely on compiler preprocessor defines to allow for cross compilation.
19 #if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || \
20 !defined(__ORDER_BIG_ENDIAN__)
21 #error "Missing preprocessor definitions for endianness detection."
26 // Converts uint8_t, uint16_t, uint32_t, uint64_t to its big or little endian
28 // We use explicit template specialization:
29 // - to prevent accidental integer promotion.
30 // - to prevent fallback in (unlikely) case of middle-endianness.
32 template <unsigned ORDER
> struct Endian
{
33 static constexpr const bool IS_LITTLE
= ORDER
== __ORDER_LITTLE_ENDIAN__
;
34 static constexpr const bool IS_BIG
= ORDER
== __ORDER_BIG_ENDIAN__
;
35 template <typename T
> LIBC_INLINE
static T
to_big_endian(T value
);
36 template <typename T
> LIBC_INLINE
static T
to_little_endian(T value
);
39 // Little Endian specializations
43 Endian
<__ORDER_LITTLE_ENDIAN__
>::to_big_endian
<uint8_t>(uint8_t v
) {
49 Endian
<__ORDER_LITTLE_ENDIAN__
>::to_little_endian
<uint8_t>(uint8_t v
) {
55 Endian
<__ORDER_LITTLE_ENDIAN__
>::to_big_endian
<uint16_t>(uint16_t v
) {
56 return __builtin_bswap16(v
);
61 Endian
<__ORDER_LITTLE_ENDIAN__
>::to_little_endian
<uint16_t>(uint16_t v
) {
67 Endian
<__ORDER_LITTLE_ENDIAN__
>::to_big_endian
<uint32_t>(uint32_t v
) {
68 return __builtin_bswap32(v
);
73 Endian
<__ORDER_LITTLE_ENDIAN__
>::to_little_endian
<uint32_t>(uint32_t v
) {
79 Endian
<__ORDER_LITTLE_ENDIAN__
>::to_big_endian
<uint64_t>(uint64_t v
) {
80 return __builtin_bswap64(v
);
85 Endian
<__ORDER_LITTLE_ENDIAN__
>::to_little_endian
<uint64_t>(uint64_t v
) {
89 // Big Endian specializations
93 Endian
<__ORDER_BIG_ENDIAN__
>::to_big_endian
<uint8_t>(uint8_t v
) {
99 Endian
<__ORDER_BIG_ENDIAN__
>::to_little_endian
<uint8_t>(uint8_t v
) {
105 Endian
<__ORDER_BIG_ENDIAN__
>::to_big_endian
<uint16_t>(uint16_t v
) {
111 Endian
<__ORDER_BIG_ENDIAN__
>::to_little_endian
<uint16_t>(uint16_t v
) {
112 return __builtin_bswap16(v
);
117 Endian
<__ORDER_BIG_ENDIAN__
>::to_big_endian
<uint32_t>(uint32_t v
) {
123 Endian
<__ORDER_BIG_ENDIAN__
>::to_little_endian
<uint32_t>(uint32_t v
) {
124 return __builtin_bswap32(v
);
129 Endian
<__ORDER_BIG_ENDIAN__
>::to_big_endian
<uint64_t>(uint64_t v
) {
135 Endian
<__ORDER_BIG_ENDIAN__
>::to_little_endian
<uint64_t>(uint64_t v
) {
136 return __builtin_bswap64(v
);
139 } // namespace internal
141 using Endian
= internal::Endian
<__BYTE_ORDER__
>;
143 } // namespace __llvm_libc
145 #endif // LLVM_LIBC_SRC_SUPPORT_ENDIAN_H