diff options
Diffstat (limited to 'include/llvm/Support/Endian.h')
-rw-r--r-- | include/llvm/Support/Endian.h | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/include/llvm/Support/Endian.h b/include/llvm/Support/Endian.h new file mode 100644 index 0000000..f62eab0 --- /dev/null +++ b/include/llvm/Support/Endian.h @@ -0,0 +1,213 @@ +//===- 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/Support/Host.h" +#include "llvm/Support/SwapByteOrder.h" +#include "llvm/Support/type_traits.h" + +namespace llvm { +namespace support { + +enum endianness {big, little}; +enum alignment {unaligned, aligned}; + +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 + +namespace endian { + template<typename value_type, alignment align> + static value_type read_le(const void *memory) { + value_type t = + reinterpret_cast<const detail::alignment_access_helper + <value_type, align> *>(memory)->val; + if (sys::isBigEndianHost()) + return sys::SwapByteOrder(t); + return t; + } + + template<typename value_type, alignment align> + static void write_le(void *memory, value_type value) { + if (sys::isBigEndianHost()) + value = sys::SwapByteOrder(value); + reinterpret_cast<detail::alignment_access_helper<value_type, align> *> + (memory)->val = value; + } + + template<typename value_type, alignment align> + static value_type read_be(const void *memory) { + value_type t = + reinterpret_cast<const detail::alignment_access_helper + <value_type, align> *>(memory)->val; + if (sys::isLittleEndianHost()) + return sys::SwapByteOrder(t); + return t; + } + + template<typename value_type, alignment align> + static void write_be(void *memory, value_type value) { + if (sys::isLittleEndianHost()) + value = sys::SwapByteOrder(value); + reinterpret_cast<detail::alignment_access_helper<value_type, align> *> + (memory)->val = value; + } +} + +namespace detail { + +template<typename value_type, + endianness endian, + alignment align> +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 |