msvc packed attribute translation
authorElizabeth Smith <elizabeths@fb.com>
Wed, 23 Apr 2014 20:02:51 +0000 (13:02 -0700)
committerDave Watson <davejwatson@fb.com>
Tue, 20 May 2014 19:53:49 +0000 (12:53 -0700)
Summary:
Provide translations for gcc packed

MSVC has a very very ugly syntax for packing using pragmas which is very different from the gcc attribute
this makes it very hard to macro around, but lots of ifdefs are also painful - cleanest of the hackery is to simply have push, pop, and attribute macros for packed that define properly depending on the compiler

Test Plan: fbmake runtests

Reviewed By: njormrod@fb.com

FB internal diff: D1279966

folly/Bits.h
folly/Portability.h
folly/io/RecordIO-inl.h
folly/small_vector.h
folly/test/PackedSyncPtrTest.cpp
folly/test/SmallLocksTest.cpp

index 020955eb996802a3febdcf83894a5b74fd8a695b..78160533959ab4b7b43b84e8917ef9a20da907d7 100644 (file)
@@ -524,6 +524,7 @@ template <class T, class Enable=void> struct Unaligned;
 /**
  * Representation of an unaligned value of a POD type.
  */
+FOLLY_PACK_PUSH
 template <class T>
 struct Unaligned<
     T,
@@ -531,7 +532,8 @@ struct Unaligned<
   Unaligned() = default;  // uninitialized
   /* implicit */ Unaligned(T v) : value(v) { }
   T value;
-} __attribute__((packed));
+} FOLLY_PACK_ATTR;
+FOLLY_PACK_POP
 
 /**
  * Read an unaligned value of type T and return it.
index 43953f931a064c4afeb55d8a606afa8f65b1b928..a29862c35a770044c71a522a3c41f4c6dfd52da2 100644 (file)
@@ -79,6 +79,21 @@ struct MaxAlign { char c; } __attribute__((aligned));
 # define FOLLY_X64 0
 #endif
 
+// packing is very ugly in msvc
+#ifdef _MSC_VER
+# define FOLLY_PACK_ATTR /**/
+# define FOLLY_PACK_PUSH __pragma(pack(push, 1))
+# define FOLLY_PACK_POP __pragma(pack(pop))
+#elif defined(__clang__) || defined(__GNUC__)
+# define FOLLY_PACK_ATTR __attribute__((packed))
+# define FOLLY_PACK_PUSH /**/
+# define FOLLY_PACK_POP /**/
+#else
+# define FOLLY_PACK_ATTR /**/
+# define FOLLY_PACK_PUSH /**/
+# define FOLLY_PACK_POP /**/
+#endif
+
 // portable version check
 #ifndef __GNUC_PREREQ
 # if defined __GNUC__ && defined __GNUC_MINOR__
index 56cc5e0694507a5a99c9276d6c37d9632c374bef..609443f6cf33ada56869a7b434fdbd121df3f89a 100644 (file)
@@ -61,6 +61,7 @@ namespace recordio_helpers {
 
 namespace detail {
 
+FOLLY_PACK_PUSH
 struct Header {
   // First 4 bytes of SHA1("zuck"), big-endian
   // Any values will do, except that the sequence must not have a
@@ -75,7 +76,8 @@ struct Header {
   uint32_t dataLength;
   uint64_t dataHash;
   uint32_t headerHash;  // must be last
-} __attribute__((packed));
+} FOLLY_PACK_ATTR;
+FOLLY_PACK_POP
 
 static_assert(offsetof(Header, headerHash) + sizeof(Header::headerHash) ==
               sizeof(Header), "invalid header layout");
index 06d2a3050ec25ec9c1b340406e27bcfc117f0daf..1696ff8a0322f517bd977b95321ee3990c3b1027 100644 (file)
 
 #if defined(__GNUC__) && FOLLY_X64
 # include "folly/SmallLocks.h"
-# define FB_PACKED __attribute__((packed))
+# define FB_PACK_ATTR FOLLY_PACK_ATTR
+# define FB_PACK_PUSH FOLLY_PACK_PUSH
+# define FB_PACK_POP FOLLY_PACK_POP
 #else
-# define FB_PACKED
+# define FB_PACK_ATTR
+# define FB_PACK_PUSH
+# define FB_PACK_POP
 #endif
 
 #if FOLLY_HAVE_MALLOC_SIZE
@@ -427,7 +431,7 @@ namespace detail {
 }
 
 //////////////////////////////////////////////////////////////////////
-
+FB_PACK_PUSH
 template<class Value,
          std::size_t RequestedMaxInline    = 1,
          class PolicyA                     = void,
@@ -1086,7 +1090,7 @@ private:
     InternalSizeType* getCapacity() {
       return &capacity_;
     }
-  } FB_PACKED;
+  } FB_PACK_ATTR;
 
   struct HeapPtr {
     // Lower order bit of heap_ is used as flag to indicate whether capacity is
@@ -1098,7 +1102,7 @@ private:
       return static_cast<InternalSizeType*>(
         detail::pointerFlagClear(heap_));
     }
-  } FB_PACKED;
+  } FB_PACK_ATTR;
 
 #if FOLLY_X64
   typedef unsigned char InlineStorageType[sizeof(value_type) * MaxInline];
@@ -1167,8 +1171,9 @@ private:
       auto vp = detail::pointerFlagClear(pdata_.heap_);
       free(vp);
     }
-  } FB_PACKED u;
-} FB_PACKED;
+  } FB_PACK_ATTR u;
+} FB_PACK_ATTR;
+FB_PACK_POP
 
 //////////////////////////////////////////////////////////////////////
 
@@ -1186,8 +1191,10 @@ void swap(small_vector<T,MaxInline,A,B,C>& a,
 
 #pragma GCC diagnostic pop
 
-#ifdef FB_PACKED
-# undef FB_PACKED
+#ifdef FB_PACK_ATTR
+# undef FB_PACK_ATTR
+# undef FB_PACK_PUSH
+# undef FB_PACK_POP
 #endif
 
 #endif
index 8ef3791f1334d7fd83b456b94b4b0f17c90ae03d..0406b56d1f1ab2a4d8b4f6dca550e4f37db33abb 100644 (file)
@@ -28,7 +28,9 @@ namespace {
 
 // Compile time check for packability.  This requires that
 // PackedSyncPtr is a POD struct on gcc.
-struct ignore { PackedSyncPtr<int> foo; char c; } __attribute__((packed));
+FOLLY_PACK_PUSH
+struct ignore { PackedSyncPtr<int> foo; char c; } FOLLY_PACK_ATTR;
+FOLLY_PACK_POP
 static_assert(sizeof(ignore) == 9, "PackedSyncPtr wasn't packable");
 
 }
index 292b9afcda0c6533874f3cbefd4378d655b14090..3a33f17a5bb0475d7e45b14cba0f9962b996da4a 100644 (file)
@@ -46,11 +46,13 @@ struct LockedVal {
 
 // Compile time test for packed struct support (requires that both of
 // these classes are POD).
-struct ignore1 { MicroSpinLock msl; int16_t foo; } __attribute__((packed));
+FOLLY_PACK_PUSH
+struct ignore1 { MicroSpinLock msl; int16_t foo; } FOLLY_PACK_ATTR;
 struct ignore2 { PicoSpinLock<uint32_t> psl; int16_t foo; }
-  __attribute__((packed));
+  FOLLY_PACK_ATTR;
 static_assert(sizeof(ignore1) == 3, "Size check failed");
 static_assert(sizeof(ignore2) == 6, "Size check failed");
+FOLLY_PACK_POP
 
 LockedVal v;
 void splock_test() {