summaryrefslogtreecommitdiff
path: root/include/llvm/Support/Endian.h
diff options
context:
space:
mode:
authorMichael J. Spencer <bigcheesegs@gmail.com>2010-10-21 20:28:21 +0000
committerMichael J. Spencer <bigcheesegs@gmail.com>2010-10-21 20:28:21 +0000
commit5e0b2bf657dd8b6b3bb58439e6cb293f3116687f (patch)
tree8d692616f4fb03bd88385566947ffbd9da0ef6c6 /include/llvm/Support/Endian.h
parentd451f888b85d01caa586b0d45bacb41836fd2c31 (diff)
downloadllvm-5e0b2bf657dd8b6b3bb58439e6cb293f3116687f.tar.gz
llvm-5e0b2bf657dd8b6b3bb58439e6cb293f3116687f.tar.bz2
llvm-5e0b2bf657dd8b6b3bb58439e6cb293f3116687f.tar.xz
Support: Add Endian.h
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@117057 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/llvm/Support/Endian.h')
-rw-r--r--include/llvm/Support/Endian.h228
1 files changed, 228 insertions, 0 deletions
diff --git a/include/llvm/Support/Endian.h b/include/llvm/Support/Endian.h
new file mode 100644
index 0000000000..985c5870dd
--- /dev/null
+++ b/include/llvm/Support/Endian.h
@@ -0,0 +1,228 @@
+//===- Endian.h - Utilities for IO with endian specific data ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares generic functions to read and write endian specific data.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ENDIAN_H
+#define LLVM_SUPPORT_ENDIAN_H
+
+#include "llvm/Config/config.h"
+#include "llvm/System/SwapByteOrder.h"
+#include "llvm/Support/type_traits.h"
+
+namespace llvm {
+namespace support {
+
+enum endianness {big, little};
+enum alignment {unaligned, aligned};
+
+template<typename value_type, int host, int target>
+static typename enable_if_c<host == target, value_type>::type
+SwapByteOrderIfDifferent(value_type value) {
+ // Target endianess is the same as the host. Just pass the value through.
+ return value;
+}
+
+template<typename value_type, int host, int target>
+static typename enable_if_c<host != target, value_type>::type
+SwapByteOrderIfDifferent(value_type value) {
+ return sys::SwapByteOrder<value_type>(value);
+}
+
+namespace detail {
+
+template<typename value_type, alignment align>
+struct alignment_access_helper;
+
+template<typename value_type>
+struct alignment_access_helper<value_type, aligned>
+{
+ value_type val;
+};
+
+// Provides unaligned loads and stores.
+#pragma pack(push)
+#pragma pack(1)
+template<typename value_type>
+struct alignment_access_helper<value_type, unaligned>
+{
+ value_type val;
+};
+#pragma pack(pop)
+
+} // end namespace detail
+
+#if defined(LLVM_IS_TARGET_BIG_ENDIAN) \
+ || defined(_BIG_ENDIAN) || defined(__BIG_ENDIAN__)
+static const endianness host_endianness = big;
+#else
+static const endianness host_endianness = little;
+#endif
+
+struct endian {
+ template<typename value_type, alignment align>
+ static value_type read_le(const void *memory) {
+ return SwapByteOrderIfDifferent<value_type, host_endianness, little>(
+ reinterpret_cast<const detail::alignment_access_helper
+ <value_type, align> *>(memory)->val);
+ }
+
+ template<typename value_type, alignment align>
+ static void write_le(void *memory, value_type value) {
+ reinterpret_cast<detail::alignment_access_helper<value_type, align> *>
+ (memory)->val =
+ SwapByteOrderIfDifferent< value_type
+ , host_endianness
+ , little>(value);
+ }
+
+ template<typename value_type, alignment align>
+ static value_type read_be(const void *memory) {
+ return SwapByteOrderIfDifferent<value_type, host_endianness, big>(
+ reinterpret_cast<const detail::alignment_access_helper
+ <value_type, align> *>(memory)->val);
+ }
+
+ template<typename value_type, alignment align>
+ static void write_be(void *memory, value_type value) {
+ reinterpret_cast<detail::alignment_access_helper
+ <value_type, align> *>(memory)->val =
+ SwapByteOrderIfDifferent< value_type
+ , host_endianness
+ , big>(value);
+ }
+};
+
+namespace detail {
+
+template<typename value_type,
+ endianness target_endianness,
+ alignment target_alignment>
+class packed_endian_specific_integral;
+
+template<typename value_type>
+class packed_endian_specific_integral<value_type, little, unaligned> {
+public:
+ operator value_type() const {
+ return endian::read_le<value_type, unaligned>(Value);
+ }
+private:
+ uint8_t Value[sizeof(value_type)];
+};
+
+template<typename value_type>
+class packed_endian_specific_integral<value_type, big, unaligned> {
+public:
+ operator value_type() const {
+ return endian::read_be<value_type, unaligned>(Value);
+ }
+private:
+ uint8_t Value[sizeof(value_type)];
+};
+
+template<typename value_type>
+class packed_endian_specific_integral<value_type, little, aligned> {
+public:
+ operator value_type() const {
+ return endian::read_le<value_type, aligned>(&Value);
+ }
+private:
+ value_type Value;
+};
+
+template<typename value_type>
+class packed_endian_specific_integral<value_type, big, aligned> {
+public:
+ operator value_type() const {
+ return endian::read_be<value_type, aligned>(&Value);
+ }
+private:
+ value_type Value;
+};
+
+} // end namespace detail
+
+typedef detail::packed_endian_specific_integral
+ <uint8_t, little, unaligned> ulittle8_t;
+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;
+
+typedef detail::packed_endian_specific_integral
+ <int8_t, little, unaligned> little8_t;
+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;
+
+typedef detail::packed_endian_specific_integral
+ <uint8_t, little, aligned> aligned_ulittle8_t;
+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;
+
+typedef detail::packed_endian_specific_integral
+ <int8_t, little, aligned> aligned_little8_t;
+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;
+
+typedef detail::packed_endian_specific_integral
+ <uint8_t, big, unaligned> ubig8_t;
+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;
+
+typedef detail::packed_endian_specific_integral
+ <int8_t, big, unaligned> big8_t;
+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;
+
+typedef detail::packed_endian_specific_integral
+ <uint8_t, big, aligned> aligned_ubig8_t;
+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;
+
+typedef detail::packed_endian_specific_integral
+ <int8_t, big, aligned> aligned_big8_t;
+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;
+
+} // end namespace llvm
+} // end namespace support
+
+#endif