diff 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
line wrap: on
line diff
--- a/include/llvm/Support/Endian.h	Fri Nov 25 19:14:25 2016 +0900
+++ b/include/llvm/Support/Endian.h	Fri Oct 27 17:07:41 2017 +0900
@@ -14,67 +14,101 @@
 #ifndef LLVM_SUPPORT_ENDIAN_H
 #define LLVM_SUPPORT_ENDIAN_H
 
+#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/Compiler.h"
 #include "llvm/Support/Host.h"
 #include "llvm/Support/SwapByteOrder.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <type_traits>
 
 namespace llvm {
 namespace support {
+
 enum endianness {big, little, native};
 
 // These are named values for common alignments.
 enum {aligned = 0, unaligned = 1};
 
 namespace detail {
-  /// \brief ::value is either alignment, or alignof(T) if alignment is 0.
-  template<class T, int alignment>
-  struct PickAlignment {
-    enum { value = alignment == 0 ? alignof(T) : alignment };
-  };
+
+/// \brief ::value is either alignment, or alignof(T) if alignment is 0.
+template<class T, int alignment>
+struct PickAlignment {
+ enum { value = alignment == 0 ? alignof(T) : alignment };
+};
+
 } // end namespace detail
 
 namespace endian {
-/// Swap the bytes of value to match the given endianness.
-template<typename value_type, endianness endian>
-inline value_type byte_swap(value_type value) {
-  if (endian != native && sys::IsBigEndianHost != (endian == big))
+
+constexpr endianness system_endianness() {
+  return sys::IsBigEndianHost ? big : little;
+}
+
+template <typename value_type>
+inline value_type byte_swap(value_type value, endianness endian) {
+  if ((endian != native) && (endian != system_endianness()))
     sys::swapByteOrder(value);
   return value;
 }
 
+/// Swap the bytes of value to match the given endianness.
+template<typename value_type, endianness endian>
+inline value_type byte_swap(value_type value) {
+  return byte_swap(value, endian);
+}
+
 /// Read a value of a particular endianness from memory.
+template <typename value_type, std::size_t alignment>
+inline value_type read(const void *memory, endianness endian) {
+  value_type ret;
+
+  memcpy(&ret,
+         LLVM_ASSUME_ALIGNED(
+             memory, (detail::PickAlignment<value_type, alignment>::value)),
+         sizeof(value_type));
+  return byte_swap<value_type>(ret, endian);
+}
+
 template<typename value_type,
          endianness endian,
          std::size_t alignment>
 inline value_type read(const void *memory) {
-  value_type ret;
-
-  memcpy(&ret,
-         LLVM_ASSUME_ALIGNED(memory,
-           (detail::PickAlignment<value_type, alignment>::value)),
-         sizeof(value_type));
-  return byte_swap<value_type, endian>(ret);
+  return read<value_type, alignment>(memory, endian);
 }
 
 /// Read a value of a particular endianness from a buffer, and increment the
 /// buffer past that value.
-template<typename value_type, endianness endian, std::size_t alignment,
-         typename CharT>
-inline value_type readNext(const CharT *&memory) {
-  value_type ret = read<value_type, endian, alignment>(memory);
+template <typename value_type, std::size_t alignment, typename CharT>
+inline value_type readNext(const CharT *&memory, endianness endian) {
+  value_type ret = read<value_type, alignment>(memory, endian);
   memory += sizeof(value_type);
   return ret;
 }
 
+template<typename value_type, endianness endian, std::size_t alignment,
+         typename CharT>
+inline value_type readNext(const CharT *&memory) {
+  return readNext<value_type, alignment, CharT>(memory, endian);
+}
+
 /// Write a value to memory with a particular endianness.
+template <typename value_type, std::size_t alignment>
+inline void write(void *memory, value_type value, endianness endian) {
+  value = byte_swap<value_type>(value, endian);
+  memcpy(LLVM_ASSUME_ALIGNED(
+             memory, (detail::PickAlignment<value_type, alignment>::value)),
+         &value, sizeof(value_type));
+}
+
 template<typename value_type,
          endianness endian,
          std::size_t alignment>
 inline void write(void *memory, value_type value) {
-  value = byte_swap<value_type, endian>(value);
-  memcpy(LLVM_ASSUME_ALIGNED(memory,
-           (detail::PickAlignment<value_type, alignment>::value)),
-         &value,
-         sizeof(value_type));
+  write<value_type, alignment>(memory, value, endian);
 }
 
 template <typename value_type>
@@ -165,9 +199,11 @@
            &val[0], sizeof(value_type) * 2);
   }
 }
+
 } // end namespace endian
 
 namespace detail {
+
 template<typename value_type,
          endianness endian,
          std::size_t alignment>
@@ -229,81 +265,96 @@
 
 } // end namespace detail
 
-typedef detail::packed_endian_specific_integral
-                  <uint16_t, little, unaligned> ulittle16_t;
-typedef detail::packed_endian_specific_integral
-                  <uint32_t, little, unaligned> ulittle32_t;
-typedef detail::packed_endian_specific_integral
-                  <uint64_t, little, unaligned> ulittle64_t;
+using ulittle16_t =
+    detail::packed_endian_specific_integral<uint16_t, little, unaligned>;
+using ulittle32_t =
+    detail::packed_endian_specific_integral<uint32_t, little, unaligned>;
+using ulittle64_t =
+    detail::packed_endian_specific_integral<uint64_t, little, unaligned>;
 
-typedef detail::packed_endian_specific_integral
-                   <int16_t, little, unaligned> little16_t;
-typedef detail::packed_endian_specific_integral
-                   <int32_t, little, unaligned> little32_t;
-typedef detail::packed_endian_specific_integral
-                   <int64_t, little, unaligned> little64_t;
+using little16_t =
+    detail::packed_endian_specific_integral<int16_t, little, unaligned>;
+using little32_t =
+    detail::packed_endian_specific_integral<int32_t, little, unaligned>;
+using little64_t =
+    detail::packed_endian_specific_integral<int64_t, little, unaligned>;
 
-typedef detail::packed_endian_specific_integral
-                    <uint16_t, little, aligned> aligned_ulittle16_t;
-typedef detail::packed_endian_specific_integral
-                    <uint32_t, little, aligned> aligned_ulittle32_t;
-typedef detail::packed_endian_specific_integral
-                    <uint64_t, little, aligned> aligned_ulittle64_t;
+using aligned_ulittle16_t =
+    detail::packed_endian_specific_integral<uint16_t, little, aligned>;
+using aligned_ulittle32_t =
+    detail::packed_endian_specific_integral<uint32_t, little, aligned>;
+using aligned_ulittle64_t =
+    detail::packed_endian_specific_integral<uint64_t, little, aligned>;
 
-typedef detail::packed_endian_specific_integral
-                     <int16_t, little, aligned> aligned_little16_t;
-typedef detail::packed_endian_specific_integral
-                     <int32_t, little, aligned> aligned_little32_t;
-typedef detail::packed_endian_specific_integral
-                     <int64_t, little, aligned> aligned_little64_t;
+using aligned_little16_t =
+    detail::packed_endian_specific_integral<int16_t, little, aligned>;
+using aligned_little32_t =
+    detail::packed_endian_specific_integral<int32_t, little, aligned>;
+using aligned_little64_t =
+    detail::packed_endian_specific_integral<int64_t, little, aligned>;
 
-typedef detail::packed_endian_specific_integral
-                  <uint16_t, big, unaligned>    ubig16_t;
-typedef detail::packed_endian_specific_integral
-                  <uint32_t, big, unaligned>    ubig32_t;
-typedef detail::packed_endian_specific_integral
-                  <uint64_t, big, unaligned>    ubig64_t;
+using ubig16_t =
+    detail::packed_endian_specific_integral<uint16_t, big, unaligned>;
+using ubig32_t =
+    detail::packed_endian_specific_integral<uint32_t, big, unaligned>;
+using ubig64_t =
+    detail::packed_endian_specific_integral<uint64_t, big, unaligned>;
 
-typedef detail::packed_endian_specific_integral
-                   <int16_t, big, unaligned>    big16_t;
-typedef detail::packed_endian_specific_integral
-                   <int32_t, big, unaligned>    big32_t;
-typedef detail::packed_endian_specific_integral
-                   <int64_t, big, unaligned>    big64_t;
+using big16_t =
+    detail::packed_endian_specific_integral<int16_t, big, unaligned>;
+using big32_t =
+    detail::packed_endian_specific_integral<int32_t, big, unaligned>;
+using big64_t =
+    detail::packed_endian_specific_integral<int64_t, big, unaligned>;
 
-typedef detail::packed_endian_specific_integral
-                    <uint16_t, big, aligned>    aligned_ubig16_t;
-typedef detail::packed_endian_specific_integral
-                    <uint32_t, big, aligned>    aligned_ubig32_t;
-typedef detail::packed_endian_specific_integral
-                    <uint64_t, big, aligned>    aligned_ubig64_t;
+using aligned_ubig16_t =
+    detail::packed_endian_specific_integral<uint16_t, big, aligned>;
+using aligned_ubig32_t =
+    detail::packed_endian_specific_integral<uint32_t, big, aligned>;
+using aligned_ubig64_t =
+    detail::packed_endian_specific_integral<uint64_t, big, aligned>;
 
-typedef detail::packed_endian_specific_integral
-                     <int16_t, big, aligned>    aligned_big16_t;
-typedef detail::packed_endian_specific_integral
-                     <int32_t, big, aligned>    aligned_big32_t;
-typedef detail::packed_endian_specific_integral
-                     <int64_t, big, aligned>    aligned_big64_t;
+using aligned_big16_t =
+    detail::packed_endian_specific_integral<int16_t, big, aligned>;
+using aligned_big32_t =
+    detail::packed_endian_specific_integral<int32_t, big, aligned>;
+using aligned_big64_t =
+    detail::packed_endian_specific_integral<int64_t, big, aligned>;
 
-typedef detail::packed_endian_specific_integral
-                  <uint16_t, native, unaligned> unaligned_uint16_t;
-typedef detail::packed_endian_specific_integral
-                  <uint32_t, native, unaligned> unaligned_uint32_t;
-typedef detail::packed_endian_specific_integral
-                  <uint64_t, native, unaligned> unaligned_uint64_t;
+using unaligned_uint16_t =
+    detail::packed_endian_specific_integral<uint16_t, native, unaligned>;
+using unaligned_uint32_t =
+    detail::packed_endian_specific_integral<uint32_t, native, unaligned>;
+using unaligned_uint64_t =
+    detail::packed_endian_specific_integral<uint64_t, native, unaligned>;
 
-typedef detail::packed_endian_specific_integral
-                   <int16_t, native, unaligned> unaligned_int16_t;
-typedef detail::packed_endian_specific_integral
-                   <int32_t, native, unaligned> unaligned_int32_t;
-typedef detail::packed_endian_specific_integral
-                   <int64_t, native, unaligned> unaligned_int64_t;
+using unaligned_int16_t =
+    detail::packed_endian_specific_integral<int16_t, native, unaligned>;
+using unaligned_int32_t =
+    detail::packed_endian_specific_integral<int32_t, native, unaligned>;
+using unaligned_int64_t =
+    detail::packed_endian_specific_integral<int64_t, native, unaligned>;
 
 namespace endian {
+
+template <typename T> inline T read(const void *P, endianness E) {
+  return read<T, unaligned>(P, E);
+}
+
 template <typename T, endianness E> inline T read(const void *P) {
   return *(const detail::packed_endian_specific_integral<T, E, unaligned> *)P;
 }
 
+inline uint16_t read16(const void *P, endianness E) {
+  return read<uint16_t>(P, E);
+}
+inline uint32_t read32(const void *P, endianness E) {
+  return read<uint32_t>(P, E);
+}
+inline uint64_t read64(const void *P, endianness E) {
+  return read<uint64_t>(P, E);
+}
+
 template <endianness E> inline uint16_t read16(const void *P) {
   return read<uint16_t, E>(P);
 }
@@ -321,10 +372,24 @@
 inline uint32_t read32be(const void *P) { return read32<big>(P); }
 inline uint64_t read64be(const void *P) { return read64<big>(P); }
 
+template <typename T> inline void write(void *P, T V, endianness E) {
+  write<T, unaligned>(P, V, E);
+}
+
 template <typename T, endianness E> inline void write(void *P, T V) {
   *(detail::packed_endian_specific_integral<T, E, unaligned> *)P = V;
 }
 
+inline void write16(void *P, uint16_t V, endianness E) {
+  write<uint16_t>(P, V, E);
+}
+inline void write32(void *P, uint32_t V, endianness E) {
+  write<uint32_t>(P, V, E);
+}
+inline void write64(void *P, uint64_t V, endianness E) {
+  write<uint64_t>(P, V, E);
+}
+
 template <endianness E> inline void write16(void *P, uint16_t V) {
   write<uint16_t, E>(P, V);
 }
@@ -341,8 +406,10 @@
 inline void write16be(void *P, uint16_t V) { write16<big>(P, V); }
 inline void write32be(void *P, uint32_t V) { write32<big>(P, V); }
 inline void write64be(void *P, uint64_t V) { write64<big>(P, V); }
+
 } // end namespace endian
+
 } // end namespace support
 } // end namespace llvm
 
-#endif
+#endif // LLVM_SUPPORT_ENDIAN_H