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

Pavel Labath via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 8 10:03:34 PST 2019


labath created this revision.
labath added reviewers: Bigcheese, zturner.
Herald added a subscriber: kristina.
Herald added a project: LLVM.

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.


Repository:
  rL LLVM

https://reviews.llvm.org/D59141

Files:
  include/llvm/Support/Endian.h
  include/llvm/Support/SwapByteOrder.h
  unittests/Support/EndianTest.cpp


Index: unittests/Support/EndianTest.cpp
===================================================================
--- unittests/Support/EndianTest.cpp
+++ unittests/Support/EndianTest.cpp
@@ -200,4 +200,13 @@
   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_enum_t<Test>;
+  using BigTest = big_enum_t<Test>;
+  EXPECT_EQ(Test::TWOONE, *reinterpret_cast<LittleTest *>(bytes));
+  EXPECT_EQ(Test::ONETWO, *reinterpret_cast<BigTest *>(bytes));
+}
+
 } // end anon namespace
Index: include/llvm/Support/SwapByteOrder.h
===================================================================
--- include/llvm/Support/SwapByteOrder.h
+++ include/llvm/Support/SwapByteOrder.h
@@ -115,6 +115,13 @@
   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);
Index: include/llvm/Support/Endian.h
===================================================================
--- include/llvm/Support/Endian.h
+++ include/llvm/Support/Endian.h
@@ -338,6 +338,12 @@
 using unaligned_int64_t =
     detail::packed_endian_specific_integral<int64_t, native, unaligned>;
 
+template <typename T>
+using little_enum_t =
+    detail::packed_endian_specific_integral<T, little, unaligned>;
+template <typename T>
+using big_enum_t = detail::packed_endian_specific_integral<T, big, unaligned>;
+
 namespace endian {
 
 template <typename T> inline T read(const void *P, endianness E) {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D59141.189876.patch
Type: text/x-patch
Size: 1812 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190308/190c005d/attachment.bin>


More information about the llvm-commits mailing list