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 void operator=(value_type newValue) { 102 endian::write_le<value_type, unaligned>((void *)&Value, newValue); 103 } 104 private: 105 uint8_t Value[sizeof(value_type)]; 106 }; 107 108 template<typename value_type> 109 class packed_endian_specific_integral<value_type, big, unaligned> { 110 public: 111 operator value_type() const { 112 return endian::read_be<value_type, unaligned>(Value); 113 } 114 void operator=(value_type newValue) { 115 endian::write_be<value_type, unaligned>((void *)&Value, newValue); 116 } 117 private: 118 uint8_t Value[sizeof(value_type)]; 119 }; 120 121 template<typename value_type> 122 class packed_endian_specific_integral<value_type, little, aligned> { 123 public: 124 operator value_type() const { 125 return endian::read_le<value_type, aligned>(&Value); 126 } 127 void operator=(value_type newValue) { 128 endian::write_le<value_type, aligned>((void *)&Value, newValue); 129 } 130 private: 131 value_type Value; 132 }; 133 134 template<typename value_type> 135 class packed_endian_specific_integral<value_type, big, aligned> { 136 public: 137 operator value_type() const { 138 return endian::read_be<value_type, aligned>(&Value); 139 } 140 void operator=(value_type newValue) { 141 endian::write_be<value_type, aligned>((void *)&Value, newValue); 142 } 143 private: 144 value_type Value; 145 }; 146 147 } // end namespace detail 148 149 typedef detail::packed_endian_specific_integral 150 <uint8_t, little, unaligned> ulittle8_t; 151 typedef detail::packed_endian_specific_integral 152 <uint16_t, little, unaligned> ulittle16_t; 153 typedef detail::packed_endian_specific_integral 154 <uint32_t, little, unaligned> ulittle32_t; 155 typedef detail::packed_endian_specific_integral 156 <uint64_t, little, unaligned> ulittle64_t; 157 158 typedef detail::packed_endian_specific_integral 159 <int8_t, little, unaligned> little8_t; 160 typedef detail::packed_endian_specific_integral 161 <int16_t, little, unaligned> little16_t; 162 typedef detail::packed_endian_specific_integral 163 <int32_t, little, unaligned> little32_t; 164 typedef detail::packed_endian_specific_integral 165 <int64_t, little, unaligned> little64_t; 166 167 typedef detail::packed_endian_specific_integral 168 <uint8_t, little, aligned> aligned_ulittle8_t; 169 typedef detail::packed_endian_specific_integral 170 <uint16_t, little, aligned> aligned_ulittle16_t; 171 typedef detail::packed_endian_specific_integral 172 <uint32_t, little, aligned> aligned_ulittle32_t; 173 typedef detail::packed_endian_specific_integral 174 <uint64_t, little, aligned> aligned_ulittle64_t; 175 176 typedef detail::packed_endian_specific_integral 177 <int8_t, little, aligned> aligned_little8_t; 178 typedef detail::packed_endian_specific_integral 179 <int16_t, little, aligned> aligned_little16_t; 180 typedef detail::packed_endian_specific_integral 181 <int32_t, little, aligned> aligned_little32_t; 182 typedef detail::packed_endian_specific_integral 183 <int64_t, little, aligned> aligned_little64_t; 184 185 typedef detail::packed_endian_specific_integral 186 <uint8_t, big, unaligned> ubig8_t; 187 typedef detail::packed_endian_specific_integral 188 <uint16_t, big, unaligned> ubig16_t; 189 typedef detail::packed_endian_specific_integral 190 <uint32_t, big, unaligned> ubig32_t; 191 typedef detail::packed_endian_specific_integral 192 <uint64_t, big, unaligned> ubig64_t; 193 194 typedef detail::packed_endian_specific_integral 195 <int8_t, big, unaligned> big8_t; 196 typedef detail::packed_endian_specific_integral 197 <int16_t, big, unaligned> big16_t; 198 typedef detail::packed_endian_specific_integral 199 <int32_t, big, unaligned> big32_t; 200 typedef detail::packed_endian_specific_integral 201 <int64_t, big, unaligned> big64_t; 202 203 typedef detail::packed_endian_specific_integral 204 <uint8_t, big, aligned> aligned_ubig8_t; 205 typedef detail::packed_endian_specific_integral 206 <uint16_t, big, aligned> aligned_ubig16_t; 207 typedef detail::packed_endian_specific_integral 208 <uint32_t, big, aligned> aligned_ubig32_t; 209 typedef detail::packed_endian_specific_integral 210 <uint64_t, big, aligned> aligned_ubig64_t; 211 212 typedef detail::packed_endian_specific_integral 213 <int8_t, big, aligned> aligned_big8_t; 214 typedef detail::packed_endian_specific_integral 215 <int16_t, big, aligned> aligned_big16_t; 216 typedef detail::packed_endian_specific_integral 217 <int32_t, big, aligned> aligned_big32_t; 218 typedef detail::packed_endian_specific_integral 219 <int64_t, big, aligned> aligned_big64_t; 220 221 } // end namespace llvm 222 } // end namespace support 223 224 #endif 225