1From 881ceef5adda6f1cc5f5a9a15ae74b068bf85dd4 Mon Sep 17 00:00:00 2001
2From: Michael Forney <mforney@mforney.org>
3Date: Fri, 30 Apr 2021 18:45:18 -0700
4Subject: [PATCH] Add portable fallback for ctz, clz, and clzll
5
6---
7 include/common/attributes.h | 27 +++++++++++++++++++++++++--
8 1 file changed, 25 insertions(+), 2 deletions(-)
9
10diff --git a/include/common/attributes.h b/include/common/attributes.h
11index 4ccc421..72d5202 100644
12--- a/include/common/attributes.h
13+++ b/include/common/attributes.h
14@@ -32,6 +32,7 @@
15
16 #include <stddef.h>
17 #include <assert.h>
18+#include <strings.h>
19
20 #ifndef __has_attribute
21 #define __has_attribute(x) 0
22@@ -156,7 +157,7 @@ static inline int clzll(const unsigned long long mask) {
23 return clz((unsigned)mask) + 32;
24 }
25 #endif /* _WIN64 */
26-#else /* !_MSC_VER */
27+#elif defined(__GNUC__)
28 static inline int ctz(const unsigned int mask) {
29 return __builtin_ctz(mask);
30 }
31@@ -168,7 +169,29 @@ static inline int clz(const unsigned int mask) {
32 static inline int clzll(const unsigned long long mask) {
33 return __builtin_clzll(mask);
34 }
35-#endif /* !_MSC_VER */
36+#else /* __GNUC__ */
37+static inline int ctz(const unsigned int mask) {
38+ return ffs(mask) - 1;
39+}
40+
41+static inline int clz(unsigned int mask) {
42+ mask >>= 1;
43+ mask |= mask >> 1;
44+ mask |= mask >> 2;
45+ mask |= mask >> 4;
46+ mask |= mask >> 8;
47+ mask |= mask >> 16;
48+ mask++;
49+ return 32 - ffs(mask);
50+}
51+
52+static inline int clzll(unsigned long long mask) {
53+ if (mask >> 32)
54+ return clz((unsigned)(mask >> 32));
55+ else
56+ return clz((unsigned)mask) + 32;
57+}
58+#endif /* !_MSC_VER && !__GNUC__ */
59
60 #ifndef static_assert
61 #define CHECK_OFFSET(type, field, name) \
62--
632.32.0
64