From 5e0b2bf657dd8b6b3bb58439e6cb293f3116687f Mon Sep 17 00:00:00 2001 From: "Michael J. Spencer" Date: Thu, 21 Oct 2010 20:28:21 +0000 Subject: Support: Add Endian.h git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@117057 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/Endian.h | 228 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 include/llvm/Support/Endian.h (limited to 'include/llvm/Support/Endian.h') 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 +static typename enable_if_c::type +SwapByteOrderIfDifferent(value_type value) { + // Target endianess is the same as the host. Just pass the value through. + return value; +} + +template +static typename enable_if_c::type +SwapByteOrderIfDifferent(value_type value) { + return sys::SwapByteOrder(value); +} + +namespace detail { + +template +struct alignment_access_helper; + +template +struct alignment_access_helper +{ + value_type val; +}; + +// Provides unaligned loads and stores. +#pragma pack(push) +#pragma pack(1) +template +struct alignment_access_helper +{ + 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 + static value_type read_le(const void *memory) { + return SwapByteOrderIfDifferent( + reinterpret_cast *>(memory)->val); + } + + template + static void write_le(void *memory, value_type value) { + reinterpret_cast *> + (memory)->val = + SwapByteOrderIfDifferent< value_type + , host_endianness + , little>(value); + } + + template + static value_type read_be(const void *memory) { + return SwapByteOrderIfDifferent( + reinterpret_cast *>(memory)->val); + } + + template + static void write_be(void *memory, value_type value) { + reinterpret_cast *>(memory)->val = + SwapByteOrderIfDifferent< value_type + , host_endianness + , big>(value); + } +}; + +namespace detail { + +template +class packed_endian_specific_integral; + +template +class packed_endian_specific_integral { +public: + operator value_type() const { + return endian::read_le(Value); + } +private: + uint8_t Value[sizeof(value_type)]; +}; + +template +class packed_endian_specific_integral { +public: + operator value_type() const { + return endian::read_be(Value); + } +private: + uint8_t Value[sizeof(value_type)]; +}; + +template +class packed_endian_specific_integral { +public: + operator value_type() const { + return endian::read_le(&Value); + } +private: + value_type Value; +}; + +template +class packed_endian_specific_integral { +public: + operator value_type() const { + return endian::read_be(&Value); + } +private: + value_type Value; +}; + +} // end namespace detail + +typedef detail::packed_endian_specific_integral + ulittle8_t; +typedef detail::packed_endian_specific_integral + ulittle16_t; +typedef detail::packed_endian_specific_integral + ulittle32_t; +typedef detail::packed_endian_specific_integral + ulittle64_t; + +typedef detail::packed_endian_specific_integral + little8_t; +typedef detail::packed_endian_specific_integral + little16_t; +typedef detail::packed_endian_specific_integral + little32_t; +typedef detail::packed_endian_specific_integral + little64_t; + +typedef detail::packed_endian_specific_integral + aligned_ulittle8_t; +typedef detail::packed_endian_specific_integral + aligned_ulittle16_t; +typedef detail::packed_endian_specific_integral + aligned_ulittle32_t; +typedef detail::packed_endian_specific_integral + aligned_ulittle64_t; + +typedef detail::packed_endian_specific_integral + aligned_little8_t; +typedef detail::packed_endian_specific_integral + aligned_little16_t; +typedef detail::packed_endian_specific_integral + aligned_little32_t; +typedef detail::packed_endian_specific_integral + aligned_little64_t; + +typedef detail::packed_endian_specific_integral + ubig8_t; +typedef detail::packed_endian_specific_integral + ubig16_t; +typedef detail::packed_endian_specific_integral + ubig32_t; +typedef detail::packed_endian_specific_integral + ubig64_t; + +typedef detail::packed_endian_specific_integral + big8_t; +typedef detail::packed_endian_specific_integral + big16_t; +typedef detail::packed_endian_specific_integral + big32_t; +typedef detail::packed_endian_specific_integral + big64_t; + +typedef detail::packed_endian_specific_integral + aligned_ubig8_t; +typedef detail::packed_endian_specific_integral + aligned_ubig16_t; +typedef detail::packed_endian_specific_integral + aligned_ubig32_t; +typedef detail::packed_endian_specific_integral + aligned_ubig64_t; + +typedef detail::packed_endian_specific_integral + aligned_big8_t; +typedef detail::packed_endian_specific_integral + aligned_big16_t; +typedef detail::packed_endian_specific_integral + aligned_big32_t; +typedef detail::packed_endian_specific_integral + aligned_big64_t; + +} // end namespace llvm +} // end namespace support + +#endif -- cgit v1.2.3