[llvm-commits] [llvm] r117057 - in /llvm/trunk: cmake/config-ix.cmake include/llvm/Config/config.h.cmake include/llvm/Support/Endian.h unittests/CMakeLists.txt unittests/Support/EndianTest.cpp

Michael J. Spencer bigcheesegs at gmail.com
Thu Oct 21 13:28:21 PDT 2010


Author: mspencer
Date: Thu Oct 21 15:28:21 2010
New Revision: 117057

URL: http://llvm.org/viewvc/llvm-project?rev=117057&view=rev
Log:
Support: Add Endian.h

Added:
    llvm/trunk/include/llvm/Support/Endian.h
    llvm/trunk/unittests/Support/EndianTest.cpp
Modified:
    llvm/trunk/cmake/config-ix.cmake
    llvm/trunk/include/llvm/Config/config.h.cmake
    llvm/trunk/unittests/CMakeLists.txt

Modified: llvm/trunk/cmake/config-ix.cmake
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/cmake/config-ix.cmake?rev=117057&r1=117056&r2=117057&view=diff
==============================================================================
--- llvm/trunk/cmake/config-ix.cmake (original)
+++ llvm/trunk/cmake/config-ix.cmake Thu Oct 21 15:28:21 2010
@@ -3,6 +3,7 @@
 include(CheckSymbolExists)
 include(CheckFunctionExists)
 include(CheckCXXSourceCompiles)
+include(TestBigEndian)
 
 if( UNIX AND NOT BEOS )
   # Used by check_symbol_exists:
@@ -257,6 +258,8 @@
   endif()
 endif()
 
+test_big_endian(LLVM_IS_TARGET_BIG_ENDIAN)
+
 if( ENABLE_THREADS )
   message(STATUS "Threads enabled.")
 else( ENABLE_THREADS )

Modified: llvm/trunk/include/llvm/Config/config.h.cmake
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Config/config.h.cmake?rev=117057&r1=117056&r2=117057&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Config/config.h.cmake (original)
+++ llvm/trunk/include/llvm/Config/config.h.cmake Thu Oct 21 15:28:21 2010
@@ -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}
 

Added: llvm/trunk/include/llvm/Support/Endian.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/Endian.h?rev=117057&view=auto
==============================================================================
--- llvm/trunk/include/llvm/Support/Endian.h (added)
+++ llvm/trunk/include/llvm/Support/Endian.h Thu Oct 21 15:28:21 2010
@@ -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

Modified: llvm/trunk/unittests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/CMakeLists.txt?rev=117057&r1=117056&r2=117057&view=diff
==============================================================================
--- llvm/trunk/unittests/CMakeLists.txt (original)
+++ llvm/trunk/unittests/CMakeLists.txt Thu Oct 21 15:28:21 2010
@@ -92,12 +92,13 @@
   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
   )

Added: llvm/trunk/unittests/Support/EndianTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/EndianTest.cpp?rev=117057&view=auto
==============================================================================
--- llvm/trunk/unittests/Support/EndianTest.cpp (added)
+++ llvm/trunk/unittests/Support/EndianTest.cpp Thu Oct 21 15:28:21 2010
@@ -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);
+}
+
+}





More information about the llvm-commits mailing list