SwapByteOrder.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- SwapByteOrder.h - Generic and optimized byte swaps -------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This file declares generic and optimized functions to swap the byte order of
  15. // an integral type.
  16. //
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_SUPPORT_SWAPBYTEORDER_H
  19. #define LLVM_SUPPORT_SWAPBYTEORDER_H
  20. #include <cstddef>
  21. #include <cstdint>
  22. #include <type_traits>
  23. #if defined(_MSC_VER) && !defined(_DEBUG)
  24. #include <stdlib.h>
  25. #endif
  26. #if defined(__linux__) || defined(__GNU__) || defined(__HAIKU__) || \
  27. defined(__Fuchsia__) || defined(__EMSCRIPTEN__)
  28. #include <endian.h>
  29. #elif defined(_AIX)
  30. #include <sys/machine.h>
  31. #elif defined(__sun)
  32. /* Solaris provides _BIG_ENDIAN/_LITTLE_ENDIAN selector in sys/types.h */
  33. #include <sys/types.h>
  34. #define BIG_ENDIAN 4321
  35. #define LITTLE_ENDIAN 1234
  36. #if defined(_BIG_ENDIAN)
  37. #define BYTE_ORDER BIG_ENDIAN
  38. #else
  39. #define BYTE_ORDER LITTLE_ENDIAN
  40. #endif
  41. #elif defined(__MVS__)
  42. #define BIG_ENDIAN 4321
  43. #define LITTLE_ENDIAN 1234
  44. #define BYTE_ORDER BIG_ENDIAN
  45. #else
  46. #if !defined(BYTE_ORDER) && !defined(_WIN32)
  47. #include <machine/endian.h>
  48. #endif
  49. #endif
  50. namespace llvm {
  51. /// ByteSwap_16 - This function returns a byte-swapped representation of
  52. /// the 16-bit argument.
  53. inline uint16_t ByteSwap_16(uint16_t value) {
  54. #if defined(_MSC_VER) && !defined(_DEBUG)
  55. // The DLL version of the runtime lacks these functions (bug!?), but in a
  56. // release build they're replaced with BSWAP instructions anyway.
  57. return _byteswap_ushort(value);
  58. #else
  59. uint16_t Hi = value << 8;
  60. uint16_t Lo = value >> 8;
  61. return Hi | Lo;
  62. #endif
  63. }
  64. /// This function returns a byte-swapped representation of the 32-bit argument.
  65. inline uint32_t ByteSwap_32(uint32_t value) {
  66. #if defined(__llvm__) || (defined(__GNUC__) && !defined(__ICC))
  67. return __builtin_bswap32(value);
  68. #elif defined(_MSC_VER) && !defined(_DEBUG)
  69. return _byteswap_ulong(value);
  70. #else
  71. uint32_t Byte0 = value & 0x000000FF;
  72. uint32_t Byte1 = value & 0x0000FF00;
  73. uint32_t Byte2 = value & 0x00FF0000;
  74. uint32_t Byte3 = value & 0xFF000000;
  75. return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24);
  76. #endif
  77. }
  78. /// This function returns a byte-swapped representation of the 64-bit argument.
  79. inline uint64_t ByteSwap_64(uint64_t value) {
  80. #if defined(__llvm__) || (defined(__GNUC__) && !defined(__ICC))
  81. return __builtin_bswap64(value);
  82. #elif defined(_MSC_VER) && !defined(_DEBUG)
  83. return _byteswap_uint64(value);
  84. #else
  85. uint64_t Hi = ByteSwap_32(uint32_t(value));
  86. uint32_t Lo = ByteSwap_32(uint32_t(value >> 32));
  87. return (Hi << 32) | Lo;
  88. #endif
  89. }
  90. namespace sys {
  91. #if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
  92. constexpr bool IsBigEndianHost = true;
  93. #else
  94. constexpr bool IsBigEndianHost = false;
  95. #endif
  96. static const bool IsLittleEndianHost = !IsBigEndianHost;
  97. inline unsigned char getSwappedBytes(unsigned char C) { return C; }
  98. inline signed char getSwappedBytes(signed char C) { return C; }
  99. inline char getSwappedBytes(char C) { return C; }
  100. inline unsigned short getSwappedBytes(unsigned short C) { return ByteSwap_16(C); }
  101. inline signed short getSwappedBytes( signed short C) { return ByteSwap_16(C); }
  102. inline unsigned int getSwappedBytes(unsigned int C) { return ByteSwap_32(C); }
  103. inline signed int getSwappedBytes( signed int C) { return ByteSwap_32(C); }
  104. inline unsigned long getSwappedBytes(unsigned long C) {
  105. // Handle LLP64 and LP64 platforms.
  106. return sizeof(long) == sizeof(int) ? ByteSwap_32((uint32_t)C)
  107. : ByteSwap_64((uint64_t)C);
  108. }
  109. inline signed long getSwappedBytes(signed long C) {
  110. // Handle LLP64 and LP64 platforms.
  111. return sizeof(long) == sizeof(int) ? ByteSwap_32((uint32_t)C)
  112. : ByteSwap_64((uint64_t)C);
  113. }
  114. inline unsigned long long getSwappedBytes(unsigned long long C) {
  115. return ByteSwap_64(C);
  116. }
  117. inline signed long long getSwappedBytes(signed long long C) {
  118. return ByteSwap_64(C);
  119. }
  120. inline float getSwappedBytes(float C) {
  121. union {
  122. uint32_t i;
  123. float f;
  124. } in, out;
  125. in.f = C;
  126. out.i = ByteSwap_32(in.i);
  127. return out.f;
  128. }
  129. inline double getSwappedBytes(double C) {
  130. union {
  131. uint64_t i;
  132. double d;
  133. } in, out;
  134. in.d = C;
  135. out.i = ByteSwap_64(in.i);
  136. return out.d;
  137. }
  138. template <typename T>
  139. inline std::enable_if_t<std::is_enum<T>::value, T> getSwappedBytes(T C) {
  140. return static_cast<T>(
  141. getSwappedBytes(static_cast<std::underlying_type_t<T>>(C)));
  142. }
  143. template<typename T>
  144. inline void swapByteOrder(T &Value) {
  145. Value = getSwappedBytes(Value);
  146. }
  147. } // end namespace sys
  148. } // end namespace llvm
  149. #endif
  150. #ifdef __GNUC__
  151. #pragma GCC diagnostic pop
  152. #endif