From e01151f729e8ee172bdcfa80f471a1f783a5c8a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Tue, 26 Aug 2025 07:31:07 +0200 Subject: [PATCH] Rewrite the bit rotate functions using __builtin or generic 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 | 144 ++++++++++++++++------------------ lib/isc/include/isc/fxhash.h | 2 +- lib/isc/include/isc/siphash.h | 24 +++--- meson.build | 11 +++ 4 files changed, 92 insertions(+), 89 deletions(-) diff --git a/lib/isc/include/isc/bit.h b/lib/isc/include/isc/bit.h index 637a68a205..d2cd6d9e71 100644 --- a/lib/isc/include/isc/bit.h +++ b/lib/isc/include/isc/bit.h @@ -62,92 +62,84 @@ #endif /* __has_header() */ -#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))); \ - }) +#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 */ -#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))); \ - }) +static inline uint8_t +isc_rotate_left8(const uint8_t x, uint32_t n) { + return (x << n) | (x >> (8 - 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))); \ - }) +static inline uint16_t +isc_rotate_left16(const uint16_t x, uint32_t n) { + return (x << n) | (x >> (16 - 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))); \ - }) +static inline uint32_t +isc_rotate_left32(const uint32_t x, uint32_t n) { + return (x << n) | (x >> (32 - 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))); \ - }) +static inline uint64_t +isc_rotate_left64(const uint64_t x, uint32_t n) { + return (x << n) | (x >> (64 - 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))); \ - }) +static inline uint8_t +isc_rotate_right8(const uint8_t x, uint32_t n) { + return (x >> n) | (x << (8 - 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))); \ - }) +static inline uint16_t +isc_rotate_right16(const uint16_t x, uint32_t n) { + return (x >> n) | (x << (16 - 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))); \ - }) +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 */ diff --git a/lib/isc/include/isc/fxhash.h b/lib/isc/include/isc/fxhash.h index 55a4f31e3b..8cfbd32377 100644 --- a/lib/isc/include/isc/fxhash.h +++ b/lib/isc/include/isc/fxhash.h @@ -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; } /* diff --git a/lib/isc/include/isc/siphash.h b/lib/isc/include/isc/siphash.h index ea3bd323a1..e4df6aaf8c 100644 --- a/lib/isc/include/isc/siphash.h +++ b/lib/isc/include/isc/siphash.h @@ -44,12 +44,12 @@ #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); \ @@ -57,12 +57,12 @@ #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); \ diff --git a/meson.build b/meson.build index 736f99d8fe..cc2308ca4b 100644 --- a/meson.build +++ b/meson.build @@ -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)