X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;ds=sidebyside;f=folly%2FBits.h;h=b22b8d57899801d9cfa76484220789d5930e00e6;hb=7d8fbeb8b9a69cee2a2f26c977ffb3f2b7b6fa92;hp=58833106ebe031a258dd2722d06338e3d1b10837;hpb=820c91a0f9cb1d5c7938a6e9394e625781919772;p=folly.git diff --git a/folly/Bits.h b/folly/Bits.h index 58833106..b22b8d57 100644 --- a/folly/Bits.h +++ b/folly/Bits.h @@ -1,5 +1,5 @@ /* - * Copyright 2013 Facebook, Inc. + * Copyright 2014 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -55,31 +55,31 @@ #ifndef FOLLY_BITS_H_ #define FOLLY_BITS_H_ -#include "folly/Portability.h" - -#ifndef __GNUC__ -#error GCC required -#endif - -#ifndef __clang__ +#if !defined(__clang__) && !defined(_MSC_VER) #define FOLLY_INTRINSIC_CONSTEXPR constexpr #else -// Unlike GCC, in Clang (as of 3.2) intrinsics aren't constexpr. +// GCC is the only compiler with intrinsics constexpr. #define FOLLY_INTRINSIC_CONSTEXPR const #endif -#ifndef FOLLY_NO_CONFIG -#include "folly/folly-config.h" -#endif +#include -#include "folly/detail/BitsDetail.h" -#include "folly/detail/BitIteratorDetail.h" -#include "folly/Likely.h" +#include +#include +#include #if FOLLY_HAVE_BYTESWAP_H # include #endif +#ifdef _MSC_VER +# include +# pragma intrinsic(_BitScanForward) +# pragma intrinsic(_BitScanForward64) +# pragma intrinsic(_BitScanReverse) +# pragma intrinsic(_BitScanReverse64) +#endif + #include #include #include @@ -100,7 +100,12 @@ typename std::enable_if< sizeof(T) <= sizeof(unsigned int)), unsigned int>::type findFirstSet(T x) { +#ifdef _MSC_VER + unsigned long index; + return _BitScanForward(&index, x) ? index : 0; +#else return __builtin_ffs(x); +#endif } template @@ -112,7 +117,12 @@ typename std::enable_if< sizeof(T) <= sizeof(unsigned long)), unsigned int>::type findFirstSet(T x) { +#ifdef _MSC_VER + unsigned long index; + return _BitScanForward(&index, x) ? index : 0; +#else return __builtin_ffsl(x); +#endif } template @@ -124,7 +134,12 @@ typename std::enable_if< sizeof(T) <= sizeof(unsigned long long)), unsigned int>::type findFirstSet(T x) { +#ifdef _MSC_VER + unsigned long index; + return _BitScanForward64(&index, x) ? index : 0; +#else return __builtin_ffsll(x); +#endif } template @@ -149,7 +164,18 @@ typename std::enable_if< sizeof(T) <= sizeof(unsigned int)), unsigned int>::type findLastSet(T x) { +#ifdef _MSC_VER + unsigned long index; + int clz; + if (_BitScanReverse(&index, x)) { + clz = static_cast(31 - index); + } else { + clz = 32; + } + return x ? 8 * sizeof(unsigned int) - clz : 0; +#else return x ? 8 * sizeof(unsigned int) - __builtin_clz(x) : 0; +#endif } template @@ -161,7 +187,18 @@ typename std::enable_if< sizeof(T) <= sizeof(unsigned long)), unsigned int>::type findLastSet(T x) { +#ifdef _MSC_VER + unsigned long index; + int clz; + if (_BitScanReverse(&index, x)) { + clz = static_cast(31 - index); + } else { + clz = 32; + } + return x ? 8 * sizeof(unsigned int) - clz : 0; +#else return x ? 8 * sizeof(unsigned long) - __builtin_clzl(x) : 0; +#endif } template @@ -173,7 +210,18 @@ typename std::enable_if< sizeof(T) <= sizeof(unsigned long long)), unsigned int>::type findLastSet(T x) { +#ifdef _MSC_VER + unsigned long index; + unsigned long long clz; + if (_BitScanReverse(&index, x)) { + clz = static_cast(63 - index); + } else { + clz = 64; + } + return x ? 8 * sizeof(unsigned long long) - clz : 0; +#else return x ? 8 * sizeof(unsigned long long) - __builtin_clzll(x) : 0; +#endif } template @@ -239,6 +287,8 @@ struct EndianIntBase { static T swap(T x); }; +#ifndef _MSC_VER + /** * If we have the bswap_16 macro from byteswap.h, use it; otherwise, provide our * own definition. @@ -256,6 +306,8 @@ our_bswap16(Int16 x) { } #endif +#endif + #define FB_GEN(t, fn) \ template<> inline t EndianIntBase::swap(t x) { return fn(x); } @@ -264,12 +316,21 @@ template<> inline t EndianIntBase::swap(t x) { return fn(x); } // __builtin_bswap16 for some reason, so we have to provide our own. FB_GEN( int8_t,) FB_GEN(uint8_t,) +#ifdef _MSC_VER +FB_GEN( int64_t, _byteswap_uint64) +FB_GEN(uint64_t, _byteswap_uint64) +FB_GEN( int32_t, _byteswap_ulong) +FB_GEN(uint32_t, _byteswap_ulong) +FB_GEN( int16_t, _byteswap_ushort) +FB_GEN(uint16_t, _byteswap_ushort) +#else 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) +#endif #undef FB_GEN @@ -341,10 +402,12 @@ class Endian { return detail::EndianInt::little(x); } +#if !defined(__ANDROID__) FB_GEN(64) FB_GEN(32) FB_GEN(16) FB_GEN(8) +#endif }; #undef FB_GEN @@ -524,6 +587,7 @@ template struct Unaligned; /** * Representation of an unaligned value of a POD type. */ +FOLLY_PACK_PUSH template struct Unaligned< T, @@ -531,7 +595,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.