]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Rewrite the bit rotate functions using __builtin or generic
authorOndřej Surý <ondrej@isc.org>
Tue, 26 Aug 2025 05:31:07 +0000 (07:31 +0200)
committerOndřej Surý <ondrej@isc.org>
Wed, 27 Aug 2025 09:53:05 +0000 (11:53 +0200)
In gcc 15, __builtin_stdc_rotate_{left,right} was added.  Use these
builtins when available otherwise rewrite the ISC_ROTATE_LEFT and
ISC_ROTATE_RIGHT using _Generic.

lib/isc/include/isc/bit.h
lib/isc/include/isc/fxhash.h
lib/isc/include/isc/siphash.h
meson.build

index 637a68a2052c22419fcb92f8f114aaf17da6bdd6..d2cd6d9e71dad8a0264eefaad5dc5b618ea75cac 100644 (file)
 
 #endif /* __has_header(<stdbit.h>) */
 
-#define ISC_ROTATE_LEFT8(x, n)                                                \
-       ({                                                                    \
-               STATIC_ASSERT(n > 0 && n < 8,                                 \
-                             "rotation must be a constant between 0 and 8"); \
-               STATIC_ASSERT(                                                \
-                       __builtin_types_compatible_p(typeof(x), uint8_t),     \
-                       "rotated value must be uint8_t");                     \
-               ((x) << (n) | (x) >> (8 - (n)));                              \
-       })
-
-#define ISC_ROTATE_LEFT16(x, n)                                                \
-       ({                                                                     \
-               STATIC_ASSERT(n > 0 && n < 16,                                 \
-                             "rotation must be a constant between 0 and 16"); \
-               STATIC_ASSERT(                                                 \
-                       __builtin_types_compatible_p(typeof(x), uint16_t),     \
-                       "rotated value must be uint16_t");                     \
-               ((x) << (n) | (x) >> (16 - (n)));                              \
-       })
-
-#define ISC_ROTATE_LEFT32(x, n)                                                \
-       ({                                                                     \
-               STATIC_ASSERT(n > 0 && n < 32,                                 \
-                             "rotation must be a constant between 0 and 32"); \
-               STATIC_ASSERT(                                                 \
-                       __builtin_types_compatible_p(typeof(x), uint32_t),     \
-                       "rotated value must be uint32_t");                     \
-               ((x) << (n) | (x) >> (32 - (n)));                              \
-       })
-
-#define ISC_ROTATE_LEFT64(x, n)                                                \
-       ({                                                                     \
-               STATIC_ASSERT(n > 0 && n < 64,                                 \
-                             "rotation must be a constant between 0 and 64"); \
-               STATIC_ASSERT(                                                 \
-                       __builtin_types_compatible_p(typeof(x), uint64_t),     \
-                       "rotated value must be uint64_t");                     \
-               ((x) << (n) | (x) >> (64 - (n)));                              \
-       })
-
-#define ISC_ROTATE_RIGHT8(x, n)                                               \
-       ({                                                                    \
-               STATIC_ASSERT(n > 0 && n < 8,                                 \
-                             "rotation must be a constant between 0 and 8"); \
-               STATIC_ASSERT(                                                \
-                       __builtin_types_compatible_p(typeof(x), uint8_t),     \
-                       "rotated value must be uint8_t");                     \
-               ((x) >> (n) | (x) << (8 - (n)));                              \
-       })
-
-#define ISC_ROTATE_RIGHT16(x, n)                                               \
-       ({                                                                     \
-               STATIC_ASSERT(n > 0 && n < 16,                                 \
-                             "rotation must be a constant between 0 and 16"); \
-               STATIC_ASSERT(                                                 \
-                       __builtin_types_compatible_p(typeof(x), uint16_t),     \
-                       "rotated value must be uint16_t");                     \
-               ((x) >> (n) | (x) << (16 - (n)));                              \
-       })
-
-#define ISC_ROTATE_RIGHT32(x, n)                                               \
-       ({                                                                     \
-               STATIC_ASSERT(n > 0 && n < 32,                                 \
-                             "rotation must be a constant between 0 and 32"); \
-               STATIC_ASSERT(                                                 \
-                       __builtin_types_compatible_p(typeof(x), uint32_t),     \
-                       "rotated value must be uint32_t");                     \
-               ((x) >> (n) | (x) << (32 - (n)));                              \
-       })
-
-#define ISC_ROTATE_RIGHT64(x, n)                                               \
-       ({                                                                     \
-               STATIC_ASSERT(n > 0 && n < 64,                                 \
-                             "rotation must be a constant between 0 and 64"); \
-               STATIC_ASSERT(                                                 \
-                       __builtin_types_compatible_p(typeof(x), uint64_t),     \
-                       "rotated value must be uint64_t");                     \
-               ((x) >> (n) | (x) << (64 - (n)));                              \
-       })
+#if HAVE_BUILTIN_STD_ROTATE_LEFT && HAVE_BUILTIN_STD_ROTATE_RIGHT
+#define ISC_ROTATE_LEFT(x, n)  __builtin_stdc_rotate_left(x, n)
+#define ISC_ROTATE_RIGHT(x, n) __builtin_stdc_rotate_right(x, n)
+#else /* HAVE_BUILTIN_STD_ROTATE_LEFT && HAVE_BUILTIN_STD_ROTATE_RIGHT */
+
+static inline uint8_t
+isc_rotate_left8(const uint8_t x, uint32_t n) {
+       return (x << n) | (x >> (8 - n));
+}
+
+static inline uint16_t
+isc_rotate_left16(const uint16_t x, uint32_t n) {
+       return (x << n) | (x >> (16 - n));
+}
+
+static inline uint32_t
+isc_rotate_left32(const uint32_t x, uint32_t n) {
+       return (x << n) | (x >> (32 - n));
+}
+
+static inline uint64_t
+isc_rotate_left64(const uint64_t x, uint32_t n) {
+       return (x << n) | (x >> (64 - n));
+}
+
+static inline uint8_t
+isc_rotate_right8(const uint8_t x, uint32_t n) {
+       return (x >> n) | (x << (8 - n));
+}
+
+static inline uint16_t
+isc_rotate_right16(const uint16_t x, uint32_t n) {
+       return (x >> n) | (x << (16 - n));
+}
+
+static inline uint32_t
+isc_rotate_right32(const uint32_t x, uint32_t n) {
+       return (x >> n) | (x << (32 - n));
+}
+
+static inline uint64_t
+isc_rotate_right64(const uint64_t x, uint32_t n) {
+       return (x >> n) | (x << (64 - n));
+}
+
+#if __APPLE_CC__
+
+/*
+ * Apple compiler doesn't recognize size_t and uintXX_t types as same,
+ * so we need to add kludges for size_t below.
+ */
 
 #if SIZE_MAX == UINT64_MAX
-#define ISC_ROTATE_LEFTSIZE(x, n)  ISC_ROTATE_LEFT64((uint64_t)x, n)
-#define ISC_ROTATE_RIGHTSIZE(x, n) ISC_ROTATE_RIGHT64((uint64_t)x, n)
+#define EXTRA_ROTATE_LEFT  , size_t : isc_rotate_left64
+#define EXTRA_ROTATE_RIGHT , size_t : isc_rotate_right64
 #elif SIZE_MAX == UINT32_MAX
-#define ISC_ROTATE_LEFTSIZE(x, n)  ISC_ROTATE_LEFT32((uint32_t)x, n)
-#define ISC_ROTATE_RIGHTSIZE(x, n) ISC_ROTATE_RIGHT32((uint32_t)x, n)
+#define EXTRA_ROTATE_LEFT  , size_t : isc_rotate_left32
+#define EXTRA_ROTATE_RIGHT , size_t : isc_rotate_right32
 #else
 #error "size_t must be either 32 or 64-bits"
 #endif
+#else
+#define EXTRA_ROTATE_LEFT
+#define EXTRA_ROTATE_RIGHT
+#endif
+
+#define ISC_ROTATE_LEFT(x, n)                \
+       _Generic((x),                        \
+               uint8_t: isc_rotate_left8,   \
+               uint16_t: isc_rotate_left16, \
+               uint32_t: isc_rotate_left32, \
+               uint64_t: isc_rotate_left64 EXTRA_ROTATE_LEFT)(x, n)
+
+#define ISC_ROTATE_RIGHT(x, n)                \
+       _Generic((x),                         \
+               uint8_t: isc_rotate_right8,   \
+               uint16_t: isc_rotate_right16, \
+               uint32_t: isc_rotate_right32, \
+               uint64_t: isc_rotate_right64 EXTRA_ROTATE_RIGHT)(x, n)
+
+#endif /* HAVE_BUILTIN_STD_ROTATE_LEFT && HAVE_BUILTIN_STD_ROTATE_RIGHT */
index 55a4f31e3ba3f76759922e1bad94bcf31c472b91..8cfbd323777ab545e084bf4afe0b063c58a86beb 100644 (file)
@@ -40,7 +40,7 @@
 
 static inline size_t
 fx_add_to_hash(size_t hash, size_t i) {
-       return ISC_ROTATE_LEFTSIZE(hash, 5) ^ i * K;
+       return ISC_ROTATE_LEFT(hash, 5) ^ i * K;
 }
 
 /*
index ea3bd323a1fbc50c0fba0b343db6aa5ee348c881..e4df6aaf8c7c74c31a0f7701a2d331d9c1dd97b1 100644 (file)
 #define cROUNDS 2
 #define dROUNDS 4
 
-#define HALF_ROUND64(a, b, c, d, s, t)   \
-       a += b;                          \
-       c += d;                          \
-       b = ISC_ROTATE_LEFT64(b, s) ^ a; \
-       d = ISC_ROTATE_LEFT64(d, t) ^ c; \
-       a = ISC_ROTATE_LEFT64(a, 32);
+#define HALF_ROUND64(a, b, c, d, s, t) \
+       a += b;                        \
+       c += d;                        \
+       b = ISC_ROTATE_LEFT(b, s) ^ a; \
+       d = ISC_ROTATE_LEFT(d, t) ^ c; \
+       a = ISC_ROTATE_LEFT(a, 32);
 
 #define FULL_ROUND64(v0, v1, v2, v3)          \
        HALF_ROUND64(v0, v1, v2, v3, 13, 16); \
 
 #define SIPROUND FULL_ROUND64
 
-#define HALF_ROUND32(a, b, c, d, s, t)   \
-       a += b;                          \
-       c += d;                          \
-       b = ISC_ROTATE_LEFT32(b, s) ^ a; \
-       d = ISC_ROTATE_LEFT32(d, t) ^ c; \
-       a = ISC_ROTATE_LEFT32(a, 16);
+#define HALF_ROUND32(a, b, c, d, s, t) \
+       a += b;                        \
+       c += d;                        \
+       b = ISC_ROTATE_LEFT(b, s) ^ a; \
+       d = ISC_ROTATE_LEFT(d, t) ^ c; \
+       a = ISC_ROTATE_LEFT(a, 16);
 
 #define FULL_ROUND32(v0, v1, v2, v3)        \
        HALF_ROUND32(v0, v1, v2, v3, 5, 8); \
index 736f99d8fe9d886475921cbea570e46451ec5d4a..cc2308ca4b0d0eaad63b2752e77f5f5d040ee5b2 100644 (file)
@@ -314,6 +314,7 @@ if developer_mode
     config.set('DNS_TYPEPAIR_CHECK', 1)
 endif
 
+# mandatory builtins
 foreach fn : [
     '__builtin_add_overflow',
     '__builtin_expect',
@@ -327,6 +328,16 @@ foreach fn : [
     endif
 endforeach
 
+# optional builtins
+foreach fn : [
+    '__builtin_stdc_rotate_left',
+    '__builtin_stdc_rotate_right',
+]
+    if cc.has_function(fn)
+        config.set('HAVE_@0@'.format(fn.substring(2).to_upper()), 1)
+    endif
+endforeach
+
 # meson_version (>=1.3.0) : required in cc.has_function
 if cc.has_function('__builtin_clzg')
     config.set('HAVE_BUILTIN_CLZG', true)