DebugServer2
Loading...
Searching...
No Matches
Bits.h
1//
2// Copyright (c) 2014-present, Facebook, Inc.
3// All rights reserved.
4//
5// This source code is licensed under the University of Illinois/NCSA Open
6// Source License found in the LICENSE file in the root directory of this
7// source tree. An additional grant of patent rights can be found in the
8// PATENTS file in the same directory.
9//
10
11#pragma once
12
13#include "DebugServer2/Utils/CompilerSupport.h"
14
15#if defined(OS_WIN32)
16#include <intrin.h>
17#endif
18#include <type_traits>
19
20namespace ds2 {
21namespace Utils {
22
23// We apply the builtin bit functions on chunks of sizeof(int) * 8 bits.
24// However, we can't do full shifts of this size because only the least
25// signifitive bits are used and clang complains, so we shift twice half
26// the size.
27static const size_t kHalfIntBits = sizeof(unsigned int) * 4;
28
29template <typename T>
30static typename std::make_unsigned<T>::type MakeUnsigned(T number) {
31 return static_cast<typename std::make_unsigned<T>::type>(number);
32}
33
34static inline unsigned int FFS(unsigned int number) {
35#if defined(COMPILER_GCC) || defined(COMPILER_CLANG)
36 return __builtin_ffs(number);
37#elif defined(COMPILER_MSVC)
38 unsigned long index;
39 if (_BitScanForward(&index, number)) {
40 return index + 1;
41 }
42 return 0;
43#else
44 for (int i = 1; number != 0; i++, number >>= 1) {
45 if (number & 1) {
46 return i;
47 }
48 }
49 return 0;
50#endif
51}
52
53static inline unsigned int PopCount(unsigned int number) {
54#if defined(COMPILER_GCC) || defined(COMPILER_CLANG)
55 return __builtin_popcount(number);
56#elif defined(COMPILER_MSVC) && defined(ARCH_ARM)
57 return _CountOneBits(number);
58#else
59 unsigned int count = 0;
60 while (number != 0) {
61 count++;
62 number = number & (number - 1);
63 }
64 return count;
65#endif
66}
67
68template <typename T> static inline unsigned int FFS(T number) {
69 auto uNumber = MakeUnsigned(number);
70 unsigned int ffs = 0;
71 while (uNumber > 0) {
72 ffs += FFS(static_cast<unsigned int>(uNumber));
73 if (ffs != 0) {
74 return ffs;
75 }
76 uNumber >>= kHalfIntBits;
77 uNumber >>= kHalfIntBits;
78 ffs += 2 * kHalfIntBits;
79 }
80 return 0;
81}
82
83template <typename T> static inline unsigned int PopCount(T number) {
84 auto uNumber = MakeUnsigned(number);
85 unsigned int count = 0;
86 while (uNumber > 0) {
87 count += PopCount(static_cast<unsigned int>(number));
88 uNumber >>= kHalfIntBits;
89 uNumber >>= kHalfIntBits;
90 }
91 return count;
92}
93
94template <typename T> static inline void EnableBit(T &number, int idx) {
95 number |= static_cast<typename std::make_unsigned<T>::type>(1) << idx;
96}
97
98template <typename T> static inline void DisableBit(T &number, int idx) {
99 number &= ~(static_cast<typename std::make_unsigned<T>::type>(1) << idx);
100}
101
102// Zeros bits from startIdx through (endIdx - 1) in number
103template <typename T>
104static inline void DisableBits(T &number, int startIdx, int endIdx) {
105 auto mask = (static_cast<typename std::make_unsigned<T>::type>(1)
106 << (endIdx - startIdx)) -
107 1;
108 number &= ~(mask << startIdx);
109}
110
111template <typename T>
112static inline void Align(T &number, unsigned int alignment) {
113 unsigned int clear = alignment - 1;
114 number = (number + clear) & ~clear;
115}
116} // namespace Utils
117} // namespace ds2