Mercurial > hg > CbC > CbC_llvm
comparison include/llvm/Support/Endian.h @ 121:803732b1fca8
LLVM 5.0
author | kono |
---|---|
date | Fri, 27 Oct 2017 17:07:41 +0900 |
parents | 1172e4bd9c6f |
children | c2174574ed3a |
comparison
equal
deleted
inserted
replaced
120:1172e4bd9c6f | 121:803732b1fca8 |
---|---|
12 //===----------------------------------------------------------------------===// | 12 //===----------------------------------------------------------------------===// |
13 | 13 |
14 #ifndef LLVM_SUPPORT_ENDIAN_H | 14 #ifndef LLVM_SUPPORT_ENDIAN_H |
15 #define LLVM_SUPPORT_ENDIAN_H | 15 #define LLVM_SUPPORT_ENDIAN_H |
16 | 16 |
17 #include "llvm/Support/AlignOf.h" | |
18 #include "llvm/Support/Compiler.h" | |
17 #include "llvm/Support/Host.h" | 19 #include "llvm/Support/Host.h" |
18 #include "llvm/Support/SwapByteOrder.h" | 20 #include "llvm/Support/SwapByteOrder.h" |
21 #include <cassert> | |
22 #include <cstddef> | |
23 #include <cstdint> | |
24 #include <cstring> | |
25 #include <type_traits> | |
19 | 26 |
20 namespace llvm { | 27 namespace llvm { |
21 namespace support { | 28 namespace support { |
29 | |
22 enum endianness {big, little, native}; | 30 enum endianness {big, little, native}; |
23 | 31 |
24 // These are named values for common alignments. | 32 // These are named values for common alignments. |
25 enum {aligned = 0, unaligned = 1}; | 33 enum {aligned = 0, unaligned = 1}; |
26 | 34 |
27 namespace detail { | 35 namespace detail { |
28 /// \brief ::value is either alignment, or alignof(T) if alignment is 0. | 36 |
29 template<class T, int alignment> | 37 /// \brief ::value is either alignment, or alignof(T) if alignment is 0. |
30 struct PickAlignment { | 38 template<class T, int alignment> |
31 enum { value = alignment == 0 ? alignof(T) : alignment }; | 39 struct PickAlignment { |
32 }; | 40 enum { value = alignment == 0 ? alignof(T) : alignment }; |
41 }; | |
42 | |
33 } // end namespace detail | 43 } // end namespace detail |
34 | 44 |
35 namespace endian { | 45 namespace endian { |
46 | |
47 constexpr endianness system_endianness() { | |
48 return sys::IsBigEndianHost ? big : little; | |
49 } | |
50 | |
51 template <typename value_type> | |
52 inline value_type byte_swap(value_type value, endianness endian) { | |
53 if ((endian != native) && (endian != system_endianness())) | |
54 sys::swapByteOrder(value); | |
55 return value; | |
56 } | |
57 | |
36 /// Swap the bytes of value to match the given endianness. | 58 /// Swap the bytes of value to match the given endianness. |
37 template<typename value_type, endianness endian> | 59 template<typename value_type, endianness endian> |
38 inline value_type byte_swap(value_type value) { | 60 inline value_type byte_swap(value_type value) { |
39 if (endian != native && sys::IsBigEndianHost != (endian == big)) | 61 return byte_swap(value, endian); |
40 sys::swapByteOrder(value); | |
41 return value; | |
42 } | 62 } |
43 | 63 |
44 /// Read a value of a particular endianness from memory. | 64 /// Read a value of a particular endianness from memory. |
65 template <typename value_type, std::size_t alignment> | |
66 inline value_type read(const void *memory, endianness endian) { | |
67 value_type ret; | |
68 | |
69 memcpy(&ret, | |
70 LLVM_ASSUME_ALIGNED( | |
71 memory, (detail::PickAlignment<value_type, alignment>::value)), | |
72 sizeof(value_type)); | |
73 return byte_swap<value_type>(ret, endian); | |
74 } | |
75 | |
45 template<typename value_type, | 76 template<typename value_type, |
46 endianness endian, | 77 endianness endian, |
47 std::size_t alignment> | 78 std::size_t alignment> |
48 inline value_type read(const void *memory) { | 79 inline value_type read(const void *memory) { |
49 value_type ret; | 80 return read<value_type, alignment>(memory, endian); |
50 | |
51 memcpy(&ret, | |
52 LLVM_ASSUME_ALIGNED(memory, | |
53 (detail::PickAlignment<value_type, alignment>::value)), | |
54 sizeof(value_type)); | |
55 return byte_swap<value_type, endian>(ret); | |
56 } | 81 } |
57 | 82 |
58 /// Read a value of a particular endianness from a buffer, and increment the | 83 /// Read a value of a particular endianness from a buffer, and increment the |
59 /// buffer past that value. | 84 /// buffer past that value. |
85 template <typename value_type, std::size_t alignment, typename CharT> | |
86 inline value_type readNext(const CharT *&memory, endianness endian) { | |
87 value_type ret = read<value_type, alignment>(memory, endian); | |
88 memory += sizeof(value_type); | |
89 return ret; | |
90 } | |
91 | |
60 template<typename value_type, endianness endian, std::size_t alignment, | 92 template<typename value_type, endianness endian, std::size_t alignment, |
61 typename CharT> | 93 typename CharT> |
62 inline value_type readNext(const CharT *&memory) { | 94 inline value_type readNext(const CharT *&memory) { |
63 value_type ret = read<value_type, endian, alignment>(memory); | 95 return readNext<value_type, alignment, CharT>(memory, endian); |
64 memory += sizeof(value_type); | |
65 return ret; | |
66 } | 96 } |
67 | 97 |
68 /// Write a value to memory with a particular endianness. | 98 /// Write a value to memory with a particular endianness. |
99 template <typename value_type, std::size_t alignment> | |
100 inline void write(void *memory, value_type value, endianness endian) { | |
101 value = byte_swap<value_type>(value, endian); | |
102 memcpy(LLVM_ASSUME_ALIGNED( | |
103 memory, (detail::PickAlignment<value_type, alignment>::value)), | |
104 &value, sizeof(value_type)); | |
105 } | |
106 | |
69 template<typename value_type, | 107 template<typename value_type, |
70 endianness endian, | 108 endianness endian, |
71 std::size_t alignment> | 109 std::size_t alignment> |
72 inline void write(void *memory, value_type value) { | 110 inline void write(void *memory, value_type value) { |
73 value = byte_swap<value_type, endian>(value); | 111 write<value_type, alignment>(memory, value, endian); |
74 memcpy(LLVM_ASSUME_ALIGNED(memory, | |
75 (detail::PickAlignment<value_type, alignment>::value)), | |
76 &value, | |
77 sizeof(value_type)); | |
78 } | 112 } |
79 | 113 |
80 template <typename value_type> | 114 template <typename value_type> |
81 using make_unsigned_t = typename std::make_unsigned<value_type>::type; | 115 using make_unsigned_t = typename std::make_unsigned<value_type>::type; |
82 | 116 |
163 memcpy(LLVM_ASSUME_ALIGNED( | 197 memcpy(LLVM_ASSUME_ALIGNED( |
164 memory, (detail::PickAlignment<value_type, alignment>::value)), | 198 memory, (detail::PickAlignment<value_type, alignment>::value)), |
165 &val[0], sizeof(value_type) * 2); | 199 &val[0], sizeof(value_type) * 2); |
166 } | 200 } |
167 } | 201 } |
202 | |
168 } // end namespace endian | 203 } // end namespace endian |
169 | 204 |
170 namespace detail { | 205 namespace detail { |
206 | |
171 template<typename value_type, | 207 template<typename value_type, |
172 endianness endian, | 208 endianness endian, |
173 std::size_t alignment> | 209 std::size_t alignment> |
174 struct packed_endian_specific_integral { | 210 struct packed_endian_specific_integral { |
175 packed_endian_specific_integral() = default; | 211 packed_endian_specific_integral() = default; |
227 }; | 263 }; |
228 }; | 264 }; |
229 | 265 |
230 } // end namespace detail | 266 } // end namespace detail |
231 | 267 |
232 typedef detail::packed_endian_specific_integral | 268 using ulittle16_t = |
233 <uint16_t, little, unaligned> ulittle16_t; | 269 detail::packed_endian_specific_integral<uint16_t, little, unaligned>; |
234 typedef detail::packed_endian_specific_integral | 270 using ulittle32_t = |
235 <uint32_t, little, unaligned> ulittle32_t; | 271 detail::packed_endian_specific_integral<uint32_t, little, unaligned>; |
236 typedef detail::packed_endian_specific_integral | 272 using ulittle64_t = |
237 <uint64_t, little, unaligned> ulittle64_t; | 273 detail::packed_endian_specific_integral<uint64_t, little, unaligned>; |
238 | 274 |
239 typedef detail::packed_endian_specific_integral | 275 using little16_t = |
240 <int16_t, little, unaligned> little16_t; | 276 detail::packed_endian_specific_integral<int16_t, little, unaligned>; |
241 typedef detail::packed_endian_specific_integral | 277 using little32_t = |
242 <int32_t, little, unaligned> little32_t; | 278 detail::packed_endian_specific_integral<int32_t, little, unaligned>; |
243 typedef detail::packed_endian_specific_integral | 279 using little64_t = |
244 <int64_t, little, unaligned> little64_t; | 280 detail::packed_endian_specific_integral<int64_t, little, unaligned>; |
245 | 281 |
246 typedef detail::packed_endian_specific_integral | 282 using aligned_ulittle16_t = |
247 <uint16_t, little, aligned> aligned_ulittle16_t; | 283 detail::packed_endian_specific_integral<uint16_t, little, aligned>; |
248 typedef detail::packed_endian_specific_integral | 284 using aligned_ulittle32_t = |
249 <uint32_t, little, aligned> aligned_ulittle32_t; | 285 detail::packed_endian_specific_integral<uint32_t, little, aligned>; |
250 typedef detail::packed_endian_specific_integral | 286 using aligned_ulittle64_t = |
251 <uint64_t, little, aligned> aligned_ulittle64_t; | 287 detail::packed_endian_specific_integral<uint64_t, little, aligned>; |
252 | 288 |
253 typedef detail::packed_endian_specific_integral | 289 using aligned_little16_t = |
254 <int16_t, little, aligned> aligned_little16_t; | 290 detail::packed_endian_specific_integral<int16_t, little, aligned>; |
255 typedef detail::packed_endian_specific_integral | 291 using aligned_little32_t = |
256 <int32_t, little, aligned> aligned_little32_t; | 292 detail::packed_endian_specific_integral<int32_t, little, aligned>; |
257 typedef detail::packed_endian_specific_integral | 293 using aligned_little64_t = |
258 <int64_t, little, aligned> aligned_little64_t; | 294 detail::packed_endian_specific_integral<int64_t, little, aligned>; |
259 | 295 |
260 typedef detail::packed_endian_specific_integral | 296 using ubig16_t = |
261 <uint16_t, big, unaligned> ubig16_t; | 297 detail::packed_endian_specific_integral<uint16_t, big, unaligned>; |
262 typedef detail::packed_endian_specific_integral | 298 using ubig32_t = |
263 <uint32_t, big, unaligned> ubig32_t; | 299 detail::packed_endian_specific_integral<uint32_t, big, unaligned>; |
264 typedef detail::packed_endian_specific_integral | 300 using ubig64_t = |
265 <uint64_t, big, unaligned> ubig64_t; | 301 detail::packed_endian_specific_integral<uint64_t, big, unaligned>; |
266 | 302 |
267 typedef detail::packed_endian_specific_integral | 303 using big16_t = |
268 <int16_t, big, unaligned> big16_t; | 304 detail::packed_endian_specific_integral<int16_t, big, unaligned>; |
269 typedef detail::packed_endian_specific_integral | 305 using big32_t = |
270 <int32_t, big, unaligned> big32_t; | 306 detail::packed_endian_specific_integral<int32_t, big, unaligned>; |
271 typedef detail::packed_endian_specific_integral | 307 using big64_t = |
272 <int64_t, big, unaligned> big64_t; | 308 detail::packed_endian_specific_integral<int64_t, big, unaligned>; |
273 | 309 |
274 typedef detail::packed_endian_specific_integral | 310 using aligned_ubig16_t = |
275 <uint16_t, big, aligned> aligned_ubig16_t; | 311 detail::packed_endian_specific_integral<uint16_t, big, aligned>; |
276 typedef detail::packed_endian_specific_integral | 312 using aligned_ubig32_t = |
277 <uint32_t, big, aligned> aligned_ubig32_t; | 313 detail::packed_endian_specific_integral<uint32_t, big, aligned>; |
278 typedef detail::packed_endian_specific_integral | 314 using aligned_ubig64_t = |
279 <uint64_t, big, aligned> aligned_ubig64_t; | 315 detail::packed_endian_specific_integral<uint64_t, big, aligned>; |
280 | 316 |
281 typedef detail::packed_endian_specific_integral | 317 using aligned_big16_t = |
282 <int16_t, big, aligned> aligned_big16_t; | 318 detail::packed_endian_specific_integral<int16_t, big, aligned>; |
283 typedef detail::packed_endian_specific_integral | 319 using aligned_big32_t = |
284 <int32_t, big, aligned> aligned_big32_t; | 320 detail::packed_endian_specific_integral<int32_t, big, aligned>; |
285 typedef detail::packed_endian_specific_integral | 321 using aligned_big64_t = |
286 <int64_t, big, aligned> aligned_big64_t; | 322 detail::packed_endian_specific_integral<int64_t, big, aligned>; |
287 | 323 |
288 typedef detail::packed_endian_specific_integral | 324 using unaligned_uint16_t = |
289 <uint16_t, native, unaligned> unaligned_uint16_t; | 325 detail::packed_endian_specific_integral<uint16_t, native, unaligned>; |
290 typedef detail::packed_endian_specific_integral | 326 using unaligned_uint32_t = |
291 <uint32_t, native, unaligned> unaligned_uint32_t; | 327 detail::packed_endian_specific_integral<uint32_t, native, unaligned>; |
292 typedef detail::packed_endian_specific_integral | 328 using unaligned_uint64_t = |
293 <uint64_t, native, unaligned> unaligned_uint64_t; | 329 detail::packed_endian_specific_integral<uint64_t, native, unaligned>; |
294 | 330 |
295 typedef detail::packed_endian_specific_integral | 331 using unaligned_int16_t = |
296 <int16_t, native, unaligned> unaligned_int16_t; | 332 detail::packed_endian_specific_integral<int16_t, native, unaligned>; |
297 typedef detail::packed_endian_specific_integral | 333 using unaligned_int32_t = |
298 <int32_t, native, unaligned> unaligned_int32_t; | 334 detail::packed_endian_specific_integral<int32_t, native, unaligned>; |
299 typedef detail::packed_endian_specific_integral | 335 using unaligned_int64_t = |
300 <int64_t, native, unaligned> unaligned_int64_t; | 336 detail::packed_endian_specific_integral<int64_t, native, unaligned>; |
301 | 337 |
302 namespace endian { | 338 namespace endian { |
339 | |
340 template <typename T> inline T read(const void *P, endianness E) { | |
341 return read<T, unaligned>(P, E); | |
342 } | |
343 | |
303 template <typename T, endianness E> inline T read(const void *P) { | 344 template <typename T, endianness E> inline T read(const void *P) { |
304 return *(const detail::packed_endian_specific_integral<T, E, unaligned> *)P; | 345 return *(const detail::packed_endian_specific_integral<T, E, unaligned> *)P; |
346 } | |
347 | |
348 inline uint16_t read16(const void *P, endianness E) { | |
349 return read<uint16_t>(P, E); | |
350 } | |
351 inline uint32_t read32(const void *P, endianness E) { | |
352 return read<uint32_t>(P, E); | |
353 } | |
354 inline uint64_t read64(const void *P, endianness E) { | |
355 return read<uint64_t>(P, E); | |
305 } | 356 } |
306 | 357 |
307 template <endianness E> inline uint16_t read16(const void *P) { | 358 template <endianness E> inline uint16_t read16(const void *P) { |
308 return read<uint16_t, E>(P); | 359 return read<uint16_t, E>(P); |
309 } | 360 } |
319 inline uint64_t read64le(const void *P) { return read64<little>(P); } | 370 inline uint64_t read64le(const void *P) { return read64<little>(P); } |
320 inline uint16_t read16be(const void *P) { return read16<big>(P); } | 371 inline uint16_t read16be(const void *P) { return read16<big>(P); } |
321 inline uint32_t read32be(const void *P) { return read32<big>(P); } | 372 inline uint32_t read32be(const void *P) { return read32<big>(P); } |
322 inline uint64_t read64be(const void *P) { return read64<big>(P); } | 373 inline uint64_t read64be(const void *P) { return read64<big>(P); } |
323 | 374 |
375 template <typename T> inline void write(void *P, T V, endianness E) { | |
376 write<T, unaligned>(P, V, E); | |
377 } | |
378 | |
324 template <typename T, endianness E> inline void write(void *P, T V) { | 379 template <typename T, endianness E> inline void write(void *P, T V) { |
325 *(detail::packed_endian_specific_integral<T, E, unaligned> *)P = V; | 380 *(detail::packed_endian_specific_integral<T, E, unaligned> *)P = V; |
381 } | |
382 | |
383 inline void write16(void *P, uint16_t V, endianness E) { | |
384 write<uint16_t>(P, V, E); | |
385 } | |
386 inline void write32(void *P, uint32_t V, endianness E) { | |
387 write<uint32_t>(P, V, E); | |
388 } | |
389 inline void write64(void *P, uint64_t V, endianness E) { | |
390 write<uint64_t>(P, V, E); | |
326 } | 391 } |
327 | 392 |
328 template <endianness E> inline void write16(void *P, uint16_t V) { | 393 template <endianness E> inline void write16(void *P, uint16_t V) { |
329 write<uint16_t, E>(P, V); | 394 write<uint16_t, E>(P, V); |
330 } | 395 } |
339 inline void write32le(void *P, uint32_t V) { write32<little>(P, V); } | 404 inline void write32le(void *P, uint32_t V) { write32<little>(P, V); } |
340 inline void write64le(void *P, uint64_t V) { write64<little>(P, V); } | 405 inline void write64le(void *P, uint64_t V) { write64<little>(P, V); } |
341 inline void write16be(void *P, uint16_t V) { write16<big>(P, V); } | 406 inline void write16be(void *P, uint16_t V) { write16<big>(P, V); } |
342 inline void write32be(void *P, uint32_t V) { write32<big>(P, V); } | 407 inline void write32be(void *P, uint32_t V) { write32<big>(P, V); } |
343 inline void write64be(void *P, uint64_t V) { write64<big>(P, V); } | 408 inline void write64be(void *P, uint64_t V) { write64<big>(P, V); } |
409 | |
344 } // end namespace endian | 410 } // end namespace endian |
411 | |
345 } // end namespace support | 412 } // end namespace support |
346 } // end namespace llvm | 413 } // end namespace llvm |
347 | 414 |
348 #endif | 415 #endif // LLVM_SUPPORT_ENDIAN_H |