1//===-- Endianness support --------------------------------------*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_LIBC_SRC___SUPPORT_ENDIAN_H
10#define LLVM_LIBC_SRC___SUPPORT_ENDIAN_H
11
12#include "common.h"
13
14#include <stdint.h>
15
16namespace LIBC_NAMESPACE {
17
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."
22#endif
23
24namespace internal {
25
26// Converts uint8_t, uint16_t, uint32_t, uint64_t to its big or little endian
27// counterpart.
28// We use explicit template specialization:
29// - to prevent accidental integer promotion.
30// - to prevent fallback in (unlikely) case of middle-endianness.
31
32template <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);
37};
38
39// Little Endian specializations
40template <>
41template <>
42LIBC_INLINE uint8_t
43Endian<__ORDER_LITTLE_ENDIAN__>::to_big_endian<uint8_t>(uint8_t v) {
44 return v;
45}
46template <>
47template <>
48LIBC_INLINE uint8_t
49Endian<__ORDER_LITTLE_ENDIAN__>::to_little_endian<uint8_t>(uint8_t v) {
50 return v;
51}
52template <>
53template <>
54LIBC_INLINE uint16_t
55Endian<__ORDER_LITTLE_ENDIAN__>::to_big_endian<uint16_t>(uint16_t v) {
56 return __builtin_bswap16(v);
57}
58template <>
59template <>
60LIBC_INLINE uint16_t
61Endian<__ORDER_LITTLE_ENDIAN__>::to_little_endian<uint16_t>(uint16_t v) {
62 return v;
63}
64template <>
65template <>
66LIBC_INLINE uint32_t
67Endian<__ORDER_LITTLE_ENDIAN__>::to_big_endian<uint32_t>(uint32_t v) {
68 return __builtin_bswap32(v);
69}
70template <>
71template <>
72LIBC_INLINE uint32_t
73Endian<__ORDER_LITTLE_ENDIAN__>::to_little_endian<uint32_t>(uint32_t v) {
74 return v;
75}
76template <>
77template <>
78LIBC_INLINE uint64_t
79Endian<__ORDER_LITTLE_ENDIAN__>::to_big_endian<uint64_t>(uint64_t v) {
80 return __builtin_bswap64(v);
81}
82template <>
83template <>
84LIBC_INLINE uint64_t
85Endian<__ORDER_LITTLE_ENDIAN__>::to_little_endian<uint64_t>(uint64_t v) {
86 return v;
87}
88
89// Big Endian specializations
90template <>
91template <>
92LIBC_INLINE uint8_t
93Endian<__ORDER_BIG_ENDIAN__>::to_big_endian<uint8_t>(uint8_t v) {
94 return v;
95}
96template <>
97template <>
98LIBC_INLINE uint8_t
99Endian<__ORDER_BIG_ENDIAN__>::to_little_endian<uint8_t>(uint8_t v) {
100 return v;
101}
102template <>
103template <>
104LIBC_INLINE uint16_t
105Endian<__ORDER_BIG_ENDIAN__>::to_big_endian<uint16_t>(uint16_t v) {
106 return v;
107}
108template <>
109template <>
110LIBC_INLINE uint16_t
111Endian<__ORDER_BIG_ENDIAN__>::to_little_endian<uint16_t>(uint16_t v) {
112 return __builtin_bswap16(v);
113}
114template <>
115template <>
116LIBC_INLINE uint32_t
117Endian<__ORDER_BIG_ENDIAN__>::to_big_endian<uint32_t>(uint32_t v) {
118 return v;
119}
120template <>
121template <>
122LIBC_INLINE uint32_t
123Endian<__ORDER_BIG_ENDIAN__>::to_little_endian<uint32_t>(uint32_t v) {
124 return __builtin_bswap32(v);
125}
126template <>
127template <>
128LIBC_INLINE uint64_t
129Endian<__ORDER_BIG_ENDIAN__>::to_big_endian<uint64_t>(uint64_t v) {
130 return v;
131}
132template <>
133template <>
134LIBC_INLINE uint64_t
135Endian<__ORDER_BIG_ENDIAN__>::to_little_endian<uint64_t>(uint64_t v) {
136 return __builtin_bswap64(v);
137}
138
139} // namespace internal
140
141using Endian = internal::Endian<__BYTE_ORDER__>;
142
143} // namespace LIBC_NAMESPACE
144
145#endif // LLVM_LIBC_SRC___SUPPORT_ENDIAN_H
146

source code of libc/src/__support/endian.h