1 //===- Endian.h - Utilities for IO with endian specific data ----*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file declares generic functions to read and write endian specific data. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_SUPPORT_ENDIAN_H 15 #define LLVM_SUPPORT_ENDIAN_H 16 17 #include "llvm/Support/Host.h" 18 #include "llvm/Support/SwapByteOrder.h" 19 #include "llvm/Support/type_traits.h" 20 21 namespace llvm { 22 namespace support { 23 24 enum endianness {big, little}; 25 enum alignment {unaligned, aligned}; 26 27 namespace detail { 28 29 template<typename value_type, alignment align> 30 struct alignment_access_helper; 31 32 template<typename value_type> 33 struct alignment_access_helper<value_type, aligned> 34 { 35 value_type val; 36 }; 37 38 // Provides unaligned loads and stores. 39 #pragma pack(push) 40 #pragma pack(1) 41 template<typename value_type> 42 struct alignment_access_helper<value_type, unaligned> 43 { 44 value_type val; 45 }; 46 #pragma pack(pop) 47 48 } // end namespace detail 49 50 namespace endian { 51 template<typename value_type, alignment align> 52 static value_type read_le(const void *memory) { 53 value_type t = 54 reinterpret_cast<const detail::alignment_access_helper 55 <value_type, align> *>(memory)->val; 56 if (sys::isBigEndianHost()) 57 return sys::SwapByteOrder(t); 58 return t; 59 } 60 61 template<typename value_type, alignment align> 62 static void write_le(void *memory, value_type value) { 63 if (sys::isBigEndianHost()) 64 value = sys::SwapByteOrder(value); 65 reinterpret_cast<detail::alignment_access_helper<value_type, align> *> 66 (memory)->val = value; 67 } 68 69 template<typename value_type, alignment align> 70 static value_type read_be(const void *memory) { 71 value_type t = 72 reinterpret_cast<const detail::alignment_access_helper 73 <value_type, align> *>(memory)->val; 74 if (sys::isLittleEndianHost()) 75 return sys::SwapByteOrder(t); 76 return t; 77 } 78 79 template<typename value_type, alignment align> 80 static void write_be(void *memory, value_type value) { 81 if (sys::isLittleEndianHost()) 82 value = sys::SwapByteOrder(value); 83 reinterpret_cast<detail::alignment_access_helper<value_type, align> *> 84 (memory)->val = value; 85 } 86 } 87 88 namespace detail { 89 90 template<typename value_type, 91 endianness endian, 92 alignment align> 93 class packed_endian_specific_integral; 94 95 template<typename value_type> 96 class packed_endian_specific_integral<value_type, little, unaligned> { 97 public: 98 operator value_type() const { 99 return endian::read_le<value_type, unaligned>(Value); 100 } 101 private: 102 uint8_t Value[sizeof(value_type)]; 103 }; 104 105 template<typename value_type> 106 class packed_endian_specific_integral<value_type, big, unaligned> { 107 public: 108 operator value_type() const { 109 return endian::read_be<value_type, unaligned>(Value); 110 } 111 private: 112 uint8_t Value[sizeof(value_type)]; 113 }; 114 115 template<typename value_type> 116 class packed_endian_specific_integral<value_type, little, aligned> { 117 public: 118 operator value_type() const { 119 return endian::read_le<value_type, aligned>(&Value); 120 } 121 private: 122 value_type Value; 123 }; 124 125 template<typename value_type> 126 class packed_endian_specific_integral<value_type, big, aligned> { 127 public: 128 operator value_type() const { 129 return endian::read_be<value_type, aligned>(&Value); 130 } 131 private: 132 value_type Value; 133 }; 134 135 } // end namespace detail 136 137 typedef detail::packed_endian_specific_integral 138 <uint8_t, little, unaligned> ulittle8_t; 139 typedef detail::packed_endian_specific_integral 140 <uint16_t, little, unaligned> ulittle16_t; 141 typedef detail::packed_endian_specific_integral 142 <uint32_t, little, unaligned> ulittle32_t; 143 typedef detail::packed_endian_specific_integral 144 <uint64_t, little, unaligned> ulittle64_t; 145 146 typedef detail::packed_endian_specific_integral 147 <int8_t, little, unaligned> little8_t; 148 typedef detail::packed_endian_specific_integral 149 <int16_t, little, unaligned> little16_t; 150 typedef detail::packed_endian_specific_integral 151 <int32_t, little, unaligned> little32_t; 152 typedef detail::packed_endian_specific_integral 153 <int64_t, little, unaligned> little64_t; 154 155 typedef detail::packed_endian_specific_integral 156 <uint8_t, little, aligned> aligned_ulittle8_t; 157 typedef detail::packed_endian_specific_integral 158 <uint16_t, little, aligned> aligned_ulittle16_t; 159 typedef detail::packed_endian_specific_integral 160 <uint32_t, little, aligned> aligned_ulittle32_t; 161 typedef detail::packed_endian_specific_integral 162 <uint64_t, little, aligned> aligned_ulittle64_t; 163 164 typedef detail::packed_endian_specific_integral 165 <int8_t, little, aligned> aligned_little8_t; 166 typedef detail::packed_endian_specific_integral 167 <int16_t, little, aligned> aligned_little16_t; 168 typedef detail::packed_endian_specific_integral 169 <int32_t, little, aligned> aligned_little32_t; 170 typedef detail::packed_endian_specific_integral 171 <int64_t, little, aligned> aligned_little64_t; 172 173 typedef detail::packed_endian_specific_integral 174 <uint8_t, big, unaligned> ubig8_t; 175 typedef detail::packed_endian_specific_integral 176 <uint16_t, big, unaligned> ubig16_t; 177 typedef detail::packed_endian_specific_integral 178 <uint32_t, big, unaligned> ubig32_t; 179 typedef detail::packed_endian_specific_integral 180 <uint64_t, big, unaligned> ubig64_t; 181 182 typedef detail::packed_endian_specific_integral 183 <int8_t, big, unaligned> big8_t; 184 typedef detail::packed_endian_specific_integral 185 <int16_t, big, unaligned> big16_t; 186 typedef detail::packed_endian_specific_integral 187 <int32_t, big, unaligned> big32_t; 188 typedef detail::packed_endian_specific_integral 189 <int64_t, big, unaligned> big64_t; 190 191 typedef detail::packed_endian_specific_integral 192 <uint8_t, big, aligned> aligned_ubig8_t; 193 typedef detail::packed_endian_specific_integral 194 <uint16_t, big, aligned> aligned_ubig16_t; 195 typedef detail::packed_endian_specific_integral 196 <uint32_t, big, aligned> aligned_ubig32_t; 197 typedef detail::packed_endian_specific_integral 198 <uint64_t, big, aligned> aligned_ubig64_t; 199 200 typedef detail::packed_endian_specific_integral 201 <int8_t, big, aligned> aligned_big8_t; 202 typedef detail::packed_endian_specific_integral 203 <int16_t, big, aligned> aligned_big16_t; 204 typedef detail::packed_endian_specific_integral 205 <int32_t, big, aligned> aligned_big32_t; 206 typedef detail::packed_endian_specific_integral 207 <int64_t, big, aligned> aligned_big64_t; 208 209 } // end namespace llvm 210 } // end namespace support 211 212 #endif 213