From: Elizabeth Smith Date: Wed, 23 Apr 2014 20:02:51 +0000 (-0700) Subject: msvc packed attribute translation X-Git-Tag: v0.22.0~584 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=aafd8ff9151615a8de09682d41d1c29966e4c8fe;p=folly.git msvc packed attribute translation 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 --- diff --git a/folly/Bits.h b/folly/Bits.h index 020955eb..78160533 100644 --- a/folly/Bits.h +++ b/folly/Bits.h @@ -524,6 +524,7 @@ template struct Unaligned; /** * Representation of an unaligned value of a POD type. */ +FOLLY_PACK_PUSH template 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. diff --git a/folly/Portability.h b/folly/Portability.h index 43953f93..a29862c3 100644 --- a/folly/Portability.h +++ b/folly/Portability.h @@ -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__ diff --git a/folly/io/RecordIO-inl.h b/folly/io/RecordIO-inl.h index 56cc5e06..609443f6 100644 --- a/folly/io/RecordIO-inl.h +++ b/folly/io/RecordIO-inl.h @@ -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"); diff --git a/folly/small_vector.h b/folly/small_vector.h index 06d2a305..1696ff8a 100644 --- a/folly/small_vector.h +++ b/folly/small_vector.h @@ -50,9 +50,13 @@ #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( 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& 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 diff --git a/folly/test/PackedSyncPtrTest.cpp b/folly/test/PackedSyncPtrTest.cpp index 8ef3791f..0406b56d 100644 --- a/folly/test/PackedSyncPtrTest.cpp +++ b/folly/test/PackedSyncPtrTest.cpp @@ -28,7 +28,9 @@ namespace { // Compile time check for packability. This requires that // PackedSyncPtr is a POD struct on gcc. -struct ignore { PackedSyncPtr foo; char c; } __attribute__((packed)); +FOLLY_PACK_PUSH +struct ignore { PackedSyncPtr foo; char c; } FOLLY_PACK_ATTR; +FOLLY_PACK_POP static_assert(sizeof(ignore) == 9, "PackedSyncPtr wasn't packable"); } diff --git a/folly/test/SmallLocksTest.cpp b/folly/test/SmallLocksTest.cpp index 292b9afc..3a33f17a 100644 --- a/folly/test/SmallLocksTest.cpp +++ b/folly/test/SmallLocksTest.cpp @@ -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 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() {