llvm.org GIT mirror llvm / 058101e
[Support] Add support for runtime endian values. Endian functions only support reading and writing when the endianness is known at compile time. This patch adds overloads where the endianness is a runtime value, and then delegates the compile-time versions to the runtime versions. Differential Revision: https://reviews.llvm.org/D29467 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@294209 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 3 years ago
2 changed file(s) with 71 addition(s) and 20 deletion(s). Raw diff Collapse all Expand all
3232 } // end namespace detail
3333
3434 namespace endian {
35 constexpr endianness system_endianness() {
36 return sys::IsBigEndianHost ? big : little;
37 }
38
39 template
40 inline value_type byte_swap(value_type value, endianness endian) {
41 if ((endian != native) && (endian != system_endianness()))
42 sys::swapByteOrder(value);
43 return value;
44 }
45
3546 /// Swap the bytes of value to match the given endianness.
3647 template
3748 inline value_type byte_swap(value_type value) {
38 if (endian != native && sys::IsBigEndianHost != (endian == big))
39 sys::swapByteOrder(value);
40 return value;
49 return byte_swap(value, endian);
4150 }
4251
4352 /// Read a value of a particular endianness from memory.
53 template
54 inline value_type read(const void *memory, endianness endian) {
55 value_type ret;
56
57 memcpy(&ret,
58 LLVM_ASSUME_ALIGNED(
59 memory, (detail::PickAlignment::value)),
60 sizeof(value_type));
61 return byte_swap(ret, endian);
62 }
63
4464 template
4565 endianness endian,
4666 std::size_t alignment>
4767 inline value_type read(const void *memory) {
48 value_type ret;
49
50 memcpy(&ret,
51 LLVM_ASSUME_ALIGNED(memory,
52 (detail::PickAlignment::value)),
53 sizeof(value_type));
54 return byte_swap(ret);
68 return read(memory, endian);
5569 }
5670
5771 /// Read a value of a particular endianness from a buffer, and increment the
5872 /// buffer past that value.
73 template
74 inline value_type readNext(const CharT *&memory, endianness endian) {
75 value_type ret = read(memory, endian);
76 memory += sizeof(value_type);
77 return ret;
78 }
79
5980 template
6081 typename CharT>
6182 inline value_type readNext(const CharT *&memory) {
62 value_type ret = read(memory);
63 memory += sizeof(value_type);
64 return ret;
83 return readNext(memory, endian);
6584 }
6685
6786 /// Write a value to memory with a particular endianness.
87 template
88 inline void write(void *memory, value_type value, endianness endian) {
89 value = byte_swap(value, endian);
90 memcpy(LLVM_ASSUME_ALIGNED(
91 memory, (detail::PickAlignment::value)),
92 &value, sizeof(value_type));
93 }
94
6895 template
6996 endianness endian,
7097 std::size_t alignment>
7198 inline void write(void *memory, value_type value) {
72 value = byte_swap(value);
73 memcpy(LLVM_ASSUME_ALIGNED(memory,
74 (detail::PickAlignment::value)),
75 &value,
76 sizeof(value_type));
99 write(memory, value, endian);
77100 }
78101
79102 template
299322 unaligned_int64_t;
300323
301324 namespace endian {
325 template inline T read(const void *P, endianness E) {
326 return read(P, E);
327 }
328
302329 template inline T read(const void *P) {
303330 return *(const detail::packed_endian_specific_integral *)P;
331 }
332
333 inline uint16_t read16(const void *P, endianness E) {
334 return read(P, E);
335 }
336 inline uint32_t read32(const void *P, endianness E) {
337 return read(P, E);
338 }
339 inline uint64_t read64(const void *P, endianness E) {
340 return read(P, E);
304341 }
305342
306343 template inline uint16_t read16(const void *P) {
320357 inline uint32_t read32be(const void *P) { return read32(P); }
321358 inline uint64_t read64be(const void *P) { return read64(P); }
322359
360 template inline void write(void *P, T V, endianness E) {
361 write(P, V, E);
362 }
363
323364 template inline void write(void *P, T V) {
324365 *(detail::packed_endian_specific_integral *)P = V;
366 }
367
368 inline void write16(void *P, uint16_t V, endianness E) {
369 write(P, V, E);
370 }
371 inline void write32(void *P, uint32_t V, endianness E) {
372 write(P, V, E);
373 }
374 inline void write64(void *P, uint64_t V, endianness E) {
375 write(P, V, E);
325376 }
326377
327378 template inline void write16(void *P, uint16_t V) {
3131 namespace sys {
3232
3333 #if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
34 static const bool IsBigEndianHost = true;
34 constexpr bool IsBigEndianHost = true;
3535 #else
36 static const bool IsBigEndianHost = false;
36 constexpr bool IsBigEndianHost = false;
3737 #endif
3838
3939 static const bool IsLittleEndianHost = !IsBigEndianHost;