Break dependency on byteswap.h
authorOwen Yamauchi <oyamauchi@fb.com>
Fri, 3 May 2013 17:43:36 +0000 (10:43 -0700)
committerSara Golemon <sgolemon@fb.com>
Mon, 20 May 2013 18:01:27 +0000 (11:01 -0700)
Summary:
Unfortunately, this doesn't exist on all platforms. Fortunately, both
gcc and clang support builtins that do the same thing as the bswap_*
functions we were including byteswap.h for.

I changed the test file to hardcode expected results for the swapping
functions. Is that OK? It seemed a little silly to be testing the
Endian::whatever functions by comparing them against the functions that
they're implemented in terms of.

Test Plan:
fbconfig/fbmake runtests with gcc 4.6 and 4.7. Verified
separately that clang supports these builtins.

Reviewed By: simpkins@fb.com

FB internal diff: D799244

folly/Bits.h
folly/configure.ac
folly/test/EndianTest.cpp

index b206968bd38a3fc5b3051f681dbe6992535c0ec2..d9bf1ad09119ac287d3d6a5758cec706d795205e 100644 (file)
 #error GCC required
 #endif
 
+#include "folly/folly-config.h"
 #include "folly/detail/BitsDetail.h"
 #include "folly/detail/BitIteratorDetail.h"
 #include "folly/Likely.h"
 
-#include <byteswap.h>
+#if FOLLY_HAVE_BYTESWAP_H
+# include <byteswap.h>
+#endif
+
 #include <cassert>
 #include <cinttypes>
 #include <endian.h>
@@ -230,19 +234,37 @@ struct EndianIntBase {
   static T swap(T x);
 };
 
+/**
+ * If we have the bswap_16 macro from byteswap.h, use it; otherwise, provide our
+ * own definition.
+ */
+#ifdef bswap_16
+# define our_bswap16 bswap_16
+#else
+
+template<class Int16>
+inline constexpr typename std::enable_if<
+  sizeof(Int16) == 2,
+  Int16>::type
+our_bswap16(Int16 x) {
+  return ((x >> 8) & 0xff) | ((x & 0xff) << 8);
+}
+#endif
+
 #define FB_GEN(t, fn) \
 template<> inline t EndianIntBase<t>::swap(t x) { return fn(x); }
 
 // fn(x) expands to (x) if the second argument is empty, which is exactly
-// what we want for [u]int8_t
+// what we want for [u]int8_t. Also, gcc 4.7 on Intel doesn't have
+// __builtin_bswap16 for some reason, so we have to provide our own.
 FB_GEN( int8_t,)
 FB_GEN(uint8_t,)
-FB_GEN( int64_t, bswap_64)
-FB_GEN(uint64_t, bswap_64)
-FB_GEN( int32_t, bswap_32)
-FB_GEN(uint32_t, bswap_32)
-FB_GEN( int16_t, bswap_16)
-FB_GEN(uint16_t, bswap_16)
+FB_GEN( int64_t, __builtin_bswap64)
+FB_GEN(uint64_t, __builtin_bswap64)
+FB_GEN( int32_t, __builtin_bswap32)
+FB_GEN(uint32_t, __builtin_bswap32)
+FB_GEN( int16_t, our_bswap16)
+FB_GEN(uint16_t, our_bswap16)
 
 #undef FB_GEN
 
index 8ec537db4f39cd3aaf891a4d84ba6a2b2233439e..38927fb904020743edde41b82d0375ebbcd80bff 100644 (file)
@@ -38,7 +38,7 @@ AX_BOOST_SYSTEM
 
 # Checks for header files.
 AC_HEADER_STDC
-AC_CHECK_HEADERS([fcntl.h inttypes.h limits.h stdint.h stdlib.h string.h sys/time.h unistd.h mutex.h malloc.h emmintrin.h])
+AC_CHECK_HEADERS([fcntl.h inttypes.h limits.h stdint.h stdlib.h string.h sys/time.h unistd.h mutex.h malloc.h emmintrin.h byteswap.h])
 
 AC_CHECK_HEADER(double-conversion.h, [], [AC_MSG_ERROR(
                 [Couldn't find double-conversion.h, please download from \
index e2e5cd81c9b8713bccb39cbd34959ad9cbfa96a7..cc65d8035069e9aa910e6be803fe6ff56a40345c 100644 (file)
@@ -22,13 +22,13 @@ using namespace folly;
 
 TEST(Endian, Basic) {
   uint8_t v8 = 0x12;
-  uint8_t v8s = v8;
+  uint8_t v8s = 0x12;
   uint16_t v16 = 0x1234;
-  uint16_t v16s = bswap_16(v16);
+  uint16_t v16s = 0x3412;
   uint32_t v32 = 0x12345678;
-  uint32_t v32s = bswap_32(v32);
+  uint32_t v32s = 0x78563412;
   uint64_t v64 = 0x123456789abcdef0ULL;
-  uint64_t v64s = bswap_64(v64);
+  uint64_t v64s = 0xf0debc9a78563412ULL;
 
 #if __BYTE_ORDER == __LITTLE_ENDIAN