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 namespace sys {
50 
51 #if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
52 constexpr bool IsBigEndianHost = true;
53 #else
54 constexpr bool IsBigEndianHost = false;
55 #endif
56 
57 static const bool IsLittleEndianHost = !IsBigEndianHost;
58 
59 inline unsigned char      getSwappedBytes(unsigned char      C) { return llvm::byteswap(C); }
60 inline   signed char      getSwappedBytes( signed  char      C) { return llvm::byteswap(C); }
61 inline          char      getSwappedBytes(         char      C) { return llvm::byteswap(C); }
62 
63 inline unsigned short     getSwappedBytes(unsigned short     C) { return llvm::byteswap(C); }
64 inline   signed short     getSwappedBytes(  signed short     C) { return llvm::byteswap(C); }
65 
66 inline unsigned int       getSwappedBytes(unsigned int       C) { return llvm::byteswap(C); }
67 inline   signed int       getSwappedBytes(  signed int       C) { return llvm::byteswap(C); }
68 
69 inline unsigned long      getSwappedBytes(unsigned long      C) { return llvm::byteswap(C); }
70 inline   signed long      getSwappedBytes(  signed long      C) { return llvm::byteswap(C); }
71 
72 inline unsigned long long getSwappedBytes(unsigned long long C) { return llvm::byteswap(C); }
73 inline   signed long long getSwappedBytes(  signed long long C) { return llvm::byteswap(C); }
74 
75 inline float getSwappedBytes(float C) {
76   union {
77     uint32_t i;
78     float f;
79   } in, out;
80   in.f = C;
81   out.i = llvm::byteswap(in.i);
82   return out.f;
83 }
84 
85 inline double getSwappedBytes(double C) {
86   union {
87     uint64_t i;
88     double d;
89   } in, out;
90   in.d = C;
91   out.i = llvm::byteswap(in.i);
92   return out.d;
93 }
94 
95 template <typename T>
96 inline std::enable_if_t<std::is_enum_v<T>, T> getSwappedBytes(T C) {
97   return static_cast<T>(
98       llvm::byteswap(static_cast<std::underlying_type_t<T>>(C)));
99 }
100 
101 template<typename T>
102 inline void swapByteOrder(T &Value) {
103   Value = getSwappedBytes(Value);
104 }
105 
106 } // end namespace sys
107 } // end namespace llvm
108 
109 #endif
110