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
/**
* Representation of an unaligned value of a POD type.
*/
+FOLLY_PACK_PUSH
template <class T>
struct Unaligned<
T,
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.
# 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__
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
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");
#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
}
//////////////////////////////////////////////////////////////////////
-
+FB_PACK_PUSH
template<class Value,
std::size_t RequestedMaxInline = 1,
class PolicyA = void,
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
return static_cast<InternalSizeType*>(
detail::pointerFlagClear(heap_));
}
- } FB_PACKED;
+ } FB_PACK_ATTR;
#if FOLLY_X64
typedef unsigned char InlineStorageType[sizeof(value_type) * MaxInline];
auto vp = detail::pointerFlagClear(pdata_.heap_);
free(vp);
}
- } FB_PACKED u;
-} FB_PACKED;
+ } FB_PACK_ATTR u;
+} FB_PACK_ATTR;
+FB_PACK_POP
//////////////////////////////////////////////////////////////////////
#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
// 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");
}
// 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() {