1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00

[Support/Endian] Add support for endian-specific enums

Summary:
Binary formats often include various enumerations or bitsets, but using
endian-specific types for accessing them is tricky because they
currently only support integral types. This is particularly true for
scoped enums (enum class), as these are not implicitly convertible to
integral types, and so one has to perform two casts just to read the
enum value.

This fixes that support by adding first-class support for enumeration
types to endian-specific types. The support for them was already almost
working -- all I needed to do was overload getSwappedBytes for
enumeration types (which casts the enum to its underlying type and performs the
conversion there). I also add some convenience template aliases to simplify
declaring endian-specific enums.

Reviewers: Bigcheese, zturner

Subscribers: kristina, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D59141

llvm-svn: 355812
This commit is contained in:
Pavel Labath 2019-03-11 09:06:18 +00:00
parent c4befaef73
commit aa70828a6f
3 changed files with 27 additions and 0 deletions

View File

@ -338,6 +338,17 @@ using unaligned_int32_t =
using unaligned_int64_t =
detail::packed_endian_specific_integral<int64_t, native, unaligned>;
template <typename T>
using little_t = detail::packed_endian_specific_integral<T, little, unaligned>;
template <typename T>
using big_t = detail::packed_endian_specific_integral<T, big, unaligned>;
template <typename T>
using aligned_little_t =
detail::packed_endian_specific_integral<T, little, aligned>;
template <typename T>
using aligned_big_t = detail::packed_endian_specific_integral<T, big, aligned>;
namespace endian {
template <typename T> inline T read(const void *P, endianness E) {

View File

@ -115,6 +115,13 @@ inline double getSwappedBytes(double C) {
return out.d;
}
template <typename T>
inline typename std::enable_if<std::is_enum<T>::value, T>::type
getSwappedBytes(T C) {
return static_cast<T>(
getSwappedBytes(static_cast<typename std::underlying_type<T>::type>(C)));
}
template<typename T>
inline void swapByteOrder(T &Value) {
Value = getSwappedBytes(Value);

View File

@ -200,4 +200,13 @@ TEST(Endian, PackedEndianSpecificIntegral) {
EXPECT_EQ(*big_val, *little_val);
}
TEST(Endian, PacketEndianSpecificIntegralAsEnum) {
enum class Test : uint16_t { ONETWO = 0x0102, TWOONE = 0x0201 };
unsigned char bytes[] = {0x01, 0x02};
using LittleTest = little_t<Test>;
using BigTest = big_t<Test>;
EXPECT_EQ(Test::TWOONE, *reinterpret_cast<LittleTest *>(bytes));
EXPECT_EQ(Test::ONETWO, *reinterpret_cast<BigTest *>(bytes));
}
} // end anon namespace