mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-28 14:10:41 +00:00
Support: Add Endian.h
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@117057 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d451f888b8
commit
5e0b2bf657
@ -3,6 +3,7 @@ include(CheckLibraryExists)
|
||||
include(CheckSymbolExists)
|
||||
include(CheckFunctionExists)
|
||||
include(CheckCXXSourceCompiles)
|
||||
include(TestBigEndian)
|
||||
|
||||
if( UNIX AND NOT BEOS )
|
||||
# Used by check_symbol_exists:
|
||||
@ -257,6 +258,8 @@ if( LLVM_ENABLE_THREADS )
|
||||
endif()
|
||||
endif()
|
||||
|
||||
test_big_endian(LLVM_IS_TARGET_BIG_ENDIAN)
|
||||
|
||||
if( ENABLE_THREADS )
|
||||
message(STATUS "Threads enabled.")
|
||||
else( ENABLE_THREADS )
|
||||
|
@ -506,6 +506,9 @@
|
||||
/* Define if this is Win32ish platform */
|
||||
#cmakedefine LLVM_ON_WIN32 ${LLVM_ON_WIN32}
|
||||
|
||||
/* Define if this is targeting a big endian system */
|
||||
#cmakedefine LLVM_IS_TARGET_BIG_ENDIAN ${LLVM_IS_TARGET_BIG_ENDIAN}
|
||||
|
||||
/* Added by Kevin -- Maximum path length */
|
||||
#cmakedefine MAXPATHLEN ${MAXPATHLEN}
|
||||
|
||||
|
228
include/llvm/Support/Endian.h
Normal file
228
include/llvm/Support/Endian.h
Normal file
@ -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
|
@ -92,12 +92,13 @@ add_llvm_unittest(Support
|
||||
Support/Casting.cpp
|
||||
Support/CommandLineTest.cpp
|
||||
Support/ConstantRangeTest.cpp
|
||||
Support/EndianTest.cpp
|
||||
Support/LeakDetectorTest.cpp
|
||||
Support/MathExtrasTest.cpp
|
||||
Support/raw_ostream_test.cpp
|
||||
Support/RegexTest.cpp
|
||||
Support/System.cpp
|
||||
Support/SwapByteOrderTest.cpp
|
||||
Support/System.cpp
|
||||
Support/TypeBuilderTest.cpp
|
||||
Support/ValueHandleTest.cpp
|
||||
)
|
||||
|
72
unittests/Support/EndianTest.cpp
Normal file
72
unittests/Support/EndianTest.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
//===- unittests/Support/EndianTest.cpp - Endian.h tests ------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/System/DataTypes.h"
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
using namespace llvm;
|
||||
using namespace support;
|
||||
|
||||
#undef max
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(Endian, Read) {
|
||||
// These are 5 bytes so we can be sure at least one of the reads is unaligned.
|
||||
unsigned char big[] = {0x00, 0x01, 0x02, 0x03, 0x04};
|
||||
unsigned char little[] = {0x00, 0x04, 0x03, 0x02, 0x01};
|
||||
int32_t BigAsHost = 0x00010203;
|
||||
EXPECT_EQ(BigAsHost, (endian::read_be<int32_t, unaligned>(big)));
|
||||
int32_t LittleAsHost = 0x02030400;
|
||||
EXPECT_EQ(LittleAsHost, (endian::read_le<int32_t, unaligned>(little)));
|
||||
|
||||
EXPECT_EQ((endian::read_be<int32_t, unaligned>(big + 1)),
|
||||
(endian::read_le<int32_t, unaligned>(little + 1)));
|
||||
}
|
||||
|
||||
TEST(Endian, Write) {
|
||||
unsigned char data[5];
|
||||
endian::write_be<int32_t, unaligned>(data, -1362446643);
|
||||
EXPECT_EQ(data[0], 0xAE);
|
||||
EXPECT_EQ(data[1], 0xCA);
|
||||
EXPECT_EQ(data[2], 0xB6);
|
||||
EXPECT_EQ(data[3], 0xCD);
|
||||
endian::write_be<int32_t, unaligned>(data + 1, -1362446643);
|
||||
EXPECT_EQ(data[1], 0xAE);
|
||||
EXPECT_EQ(data[2], 0xCA);
|
||||
EXPECT_EQ(data[3], 0xB6);
|
||||
EXPECT_EQ(data[4], 0xCD);
|
||||
|
||||
endian::write_le<int32_t, unaligned>(data, -1362446643);
|
||||
EXPECT_EQ(data[0], 0xCD);
|
||||
EXPECT_EQ(data[1], 0xB6);
|
||||
EXPECT_EQ(data[2], 0xCA);
|
||||
EXPECT_EQ(data[3], 0xAE);
|
||||
endian::write_le<int32_t, unaligned>(data + 1, -1362446643);
|
||||
EXPECT_EQ(data[1], 0xCD);
|
||||
EXPECT_EQ(data[2], 0xB6);
|
||||
EXPECT_EQ(data[3], 0xCA);
|
||||
EXPECT_EQ(data[4], 0xAE);
|
||||
}
|
||||
|
||||
TEST(Endian, PackedEndianSpecificIntegral) {
|
||||
// These are 5 bytes so we can be sure at least one of the reads is unaligned.
|
||||
unsigned char big[] = {0x00, 0x01, 0x02, 0x03, 0x04};
|
||||
unsigned char little[] = {0x00, 0x04, 0x03, 0x02, 0x01};
|
||||
big32_t *big_val =
|
||||
reinterpret_cast<big32_t *>(big + 1);
|
||||
little32_t *little_val =
|
||||
reinterpret_cast<little32_t *>(little + 1);
|
||||
|
||||
EXPECT_EQ(*big_val, *little_val);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user