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