1 //===-- Endianness support ------------------------------------------------===// 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 <stdint.h> 13 14 namespace __llvm_libc { 15 16 // We rely on compiler preprocessor defines to allow for cross compilation. 17 #if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || \ 18 !defined(__ORDER_BIG_ENDIAN__) 19 #error "Missing preprocessor definitions for endianness detection." 20 #endif 21 22 namespace internal { 23 24 // Converts uint8_t, uint16_t, uint32_t, uint64_t to its big or little endian 25 // counterpart. 26 // We use explicit template specialization: 27 // - to prevent accidental integer promotion. 28 // - to prevent fallback in (unlikely) case of middle-endianness. 29 30 template <unsigned ORDER> struct Endian { 31 static constexpr const bool isLittle = ORDER == __ORDER_LITTLE_ENDIAN__; 32 static constexpr const bool isBig = ORDER == __ORDER_BIG_ENDIAN__; 33 template <typename T> static T ToBigEndian(T value); 34 template <typename T> static T ToLittleEndian(T value); 35 }; 36 37 // Little Endian specializations 38 template <> 39 template <> 40 inline uint8_t 41 Endian<__ORDER_LITTLE_ENDIAN__>::ToBigEndian<uint8_t>(uint8_t v) { 42 return v; 43 } 44 template <> 45 template <> 46 inline uint8_t 47 Endian<__ORDER_LITTLE_ENDIAN__>::ToLittleEndian<uint8_t>(uint8_t v) { 48 return v; 49 } 50 template <> 51 template <> 52 inline uint16_t 53 Endian<__ORDER_LITTLE_ENDIAN__>::ToBigEndian<uint16_t>(uint16_t v) { 54 return __builtin_bswap16(v); 55 } 56 template <> 57 template <> 58 inline uint16_t 59 Endian<__ORDER_LITTLE_ENDIAN__>::ToLittleEndian<uint16_t>(uint16_t v) { 60 return v; 61 } 62 template <> 63 template <> 64 inline uint32_t 65 Endian<__ORDER_LITTLE_ENDIAN__>::ToBigEndian<uint32_t>(uint32_t v) { 66 return __builtin_bswap32(v); 67 } 68 template <> 69 template <> 70 inline uint32_t 71 Endian<__ORDER_LITTLE_ENDIAN__>::ToLittleEndian<uint32_t>(uint32_t v) { 72 return v; 73 } 74 template <> 75 template <> 76 inline uint64_t 77 Endian<__ORDER_LITTLE_ENDIAN__>::ToBigEndian<uint64_t>(uint64_t v) { 78 return __builtin_bswap64(v); 79 } 80 template <> 81 template <> 82 inline uint64_t 83 Endian<__ORDER_LITTLE_ENDIAN__>::ToLittleEndian<uint64_t>(uint64_t v) { 84 return v; 85 } 86 87 // Big Endian specializations 88 template <> 89 template <> 90 inline uint8_t Endian<__ORDER_BIG_ENDIAN__>::ToBigEndian<uint8_t>(uint8_t v) { 91 return v; 92 } 93 template <> 94 template <> 95 inline uint8_t 96 Endian<__ORDER_BIG_ENDIAN__>::ToLittleEndian<uint8_t>(uint8_t v) { 97 return v; 98 } 99 template <> 100 template <> 101 inline uint16_t 102 Endian<__ORDER_BIG_ENDIAN__>::ToBigEndian<uint16_t>(uint16_t v) { 103 return v; 104 } 105 template <> 106 template <> 107 inline uint16_t 108 Endian<__ORDER_BIG_ENDIAN__>::ToLittleEndian<uint16_t>(uint16_t v) { 109 return __builtin_bswap16(v); 110 } 111 template <> 112 template <> 113 inline uint32_t 114 Endian<__ORDER_BIG_ENDIAN__>::ToBigEndian<uint32_t>(uint32_t v) { 115 return v; 116 } 117 template <> 118 template <> 119 inline uint32_t 120 Endian<__ORDER_BIG_ENDIAN__>::ToLittleEndian<uint32_t>(uint32_t v) { 121 return __builtin_bswap32(v); 122 } 123 template <> 124 template <> 125 inline uint64_t 126 Endian<__ORDER_BIG_ENDIAN__>::ToBigEndian<uint64_t>(uint64_t v) { 127 return v; 128 } 129 template <> 130 template <> 131 inline uint64_t 132 Endian<__ORDER_BIG_ENDIAN__>::ToLittleEndian<uint64_t>(uint64_t v) { 133 return __builtin_bswap64(v); 134 } 135 136 } // namespace internal 137 138 using Endian = internal::Endian<__BYTE_ORDER__>; 139 140 } // namespace __llvm_libc 141 142 #endif // LLVM_LIBC_SRC_SUPPORT_ENDIAN_H 143