mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
d5ec932c3a
llvm-svn: 120298
214 lines
7.1 KiB
C++
214 lines
7.1 KiB
C++
//===- 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
|