1 //===- SwapByteOrder.h - Generic and optimized byte swaps -------*- 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 // This file declares generic and optimized functions to swap the byte order of
10 // an integral type.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_SUPPORT_SWAPBYTEORDER_H
15 #define LLVM_SUPPORT_SWAPBYTEORDER_H
16 
17 #include "llvm/ADT/bit.h"
18 #include <cstddef>
19 #include <cstdint>
20 #include <type_traits>
21 
22 #if defined(__linux__) || defined(__GNU__) || defined(__HAIKU__) ||            \
23     defined(__Fuchsia__) || defined(__EMSCRIPTEN__)
24 #include <endian.h>
25 #elif defined(_AIX)
26 #include <sys/machine.h>
27 #elif defined(__sun)
28 /* Solaris provides _BIG_ENDIAN/_LITTLE_ENDIAN selector in sys/types.h */
29 #include <sys/types.h>
30 #define BIG_ENDIAN 4321
31 #define LITTLE_ENDIAN 1234
32 #if defined(_BIG_ENDIAN)
33 #define BYTE_ORDER BIG_ENDIAN
34 #else
35 #define BYTE_ORDER LITTLE_ENDIAN
36 #endif
37 #elif defined(__MVS__)
38 #define BIG_ENDIAN 4321
39 #define LITTLE_ENDIAN 1234
40 #define BYTE_ORDER BIG_ENDIAN
41 #else
42 #if !defined(BYTE_ORDER) && !defined(_WIN32)
43 #include <machine/endian.h>
44 #endif
45 #endif
46 
47 namespace llvm {
48 
49 /// ByteSwap_16 - This function returns a byte-swapped representation of
50 /// the 16-bit argument.
51 inline uint16_t ByteSwap_16(uint16_t value) { return llvm::byteswap(value); }
52 
53 /// This function returns a byte-swapped representation of the 32-bit argument.
54 inline uint32_t ByteSwap_32(uint32_t value) { return llvm::byteswap(value); }
55 
56 /// This function returns a byte-swapped representation of the 64-bit argument.
57 inline uint64_t ByteSwap_64(uint64_t value) { return llvm::byteswap(value); }
58 
59 namespace sys {
60 
61 #if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
62 constexpr bool IsBigEndianHost = true;
63 #else
64 constexpr bool IsBigEndianHost = false;
65 #endif
66 
67 static const bool IsLittleEndianHost = !IsBigEndianHost;
68 
69 inline unsigned char      getSwappedBytes(unsigned char      C) { return llvm::byteswap(C); }
70 inline   signed char      getSwappedBytes( signed  char      C) { return llvm::byteswap(C); }
71 inline          char      getSwappedBytes(         char      C) { return llvm::byteswap(C); }
72 
73 inline unsigned short     getSwappedBytes(unsigned short     C) { return llvm::byteswap(C); }
74 inline   signed short     getSwappedBytes(  signed short     C) { return llvm::byteswap(C); }
75 
76 inline unsigned int       getSwappedBytes(unsigned int       C) { return llvm::byteswap(C); }
77 inline   signed int       getSwappedBytes(  signed int       C) { return llvm::byteswap(C); }
78 
79 inline unsigned long      getSwappedBytes(unsigned long      C) { return llvm::byteswap(C); }
80 inline   signed long      getSwappedBytes(  signed long      C) { return llvm::byteswap(C); }
81 
82 inline unsigned long long getSwappedBytes(unsigned long long C) { return llvm::byteswap(C); }
83 inline   signed long long getSwappedBytes(  signed long long C) { return llvm::byteswap(C); }
84 
85 inline float getSwappedBytes(float C) {
86   union {
87     uint32_t i;
88     float f;
89   } in, out;
90   in.f = C;
91   out.i = llvm::byteswap(in.i);
92   return out.f;
93 }
94 
95 inline double getSwappedBytes(double C) {
96   union {
97     uint64_t i;
98     double d;
99   } in, out;
100   in.d = C;
101   out.i = llvm::byteswap(in.i);
102   return out.d;
103 }
104 
105 template <typename T>
106 inline std::enable_if_t<std::is_enum<T>::value, T> getSwappedBytes(T C) {
107   return static_cast<T>(
108       llvm::byteswap(static_cast<std::underlying_type_t<T>>(C)));
109 }
110 
111 template<typename T>
112 inline void swapByteOrder(T &Value) {
113   Value = getSwappedBytes(Value);
114 }
115 
116 } // end namespace sys
117 } // end namespace llvm
118 
119 #endif
120