X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FBits.h;h=4c1182a633c99dbac620a4e251065d47e77631f6;hb=b44cacfd2c3ef9aab6abfc32e9d820b9de3d8d79;hp=6b2fef765466d82273d968b23dd9308b2b21ad30;hpb=d82103b898d2c831ee86a17f57656cad22e99fb1;p=folly.git diff --git a/folly/Bits.h b/folly/Bits.h index 6b2fef76..4c1182a6 100644 --- a/folly/Bits.h +++ b/folly/Bits.h @@ -1,5 +1,5 @@ /* - * Copyright 2013 Facebook, Inc. + * Copyright 2015 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 @@ -373,7 +436,7 @@ class BitIterator /** * Return the number of bits in an element of the underlying iterator. */ - static size_t bitsPerBlock() { + static unsigned int bitsPerBlock() { return std::numeric_limits< typename std::make_unsigned< typename std::iterator_traits::value_type @@ -385,11 +448,14 @@ class BitIterator * Construct a BitIterator that points at a given bit offset (default 0) * in iter. */ + #pragma GCC diagnostic push // bitOffset shadows a member + #pragma GCC diagnostic ignored "-Wshadow" explicit BitIterator(const BaseIter& iter, size_t bitOffset=0) : bititerator_detail::BitIteratorBase::type(iter), bitOffset_(bitOffset) { assert(bitOffset_ < bitsPerBlock()); } + #pragma GCC diagnostic pop size_t bitOffset() const { return bitOffset_; @@ -456,10 +522,10 @@ class BitIterator ssize_t distance_to(const BitIterator& other) const { return (other.base_reference() - this->base_reference()) * bitsPerBlock() + - (other.bitOffset_ - bitOffset_); + other.bitOffset_ - bitOffset_; } - ssize_t bitOffset_; + unsigned int bitOffset_; }; /** @@ -521,6 +587,7 @@ template struct Unaligned; /** * Representation of an unaligned value of a POD type. */ +FOLLY_PACK_PUSH template struct Unaligned< T, @@ -528,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. @@ -553,4 +621,3 @@ inline void storeUnaligned(void* p, T value) { } // namespace folly #endif /* FOLLY_BITS_H_ */ -