From 7b7c853c07f2f469e3e8d89310a13286f6613556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ayd=C4=B1n=20Mercan?= Date: Thu, 21 Aug 2025 15:24:40 +0300 Subject: [PATCH] switch bit rotation functions to statement expressions Using `static inline` functions in the headers break gcov as it cannot properly track the hits. To fix the issue, convert the expressions to statement macros. The added static assertions will ensure integer promotion cannot occur unlike its previous function counterpart. --- lib/isc/include/isc/bit.h | 128 ++++++++++++++++++++++------------ lib/isc/include/isc/fxhash.h | 2 +- lib/isc/include/isc/siphash.h | 12 ++-- 3 files changed, 91 insertions(+), 51 deletions(-) diff --git a/lib/isc/include/isc/bit.h b/lib/isc/include/isc/bit.h index 59c11e47ec..0ef6a69c90 100644 --- a/lib/isc/include/isc/bit.h +++ b/lib/isc/include/isc/bit.h @@ -72,52 +72,92 @@ #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))); \ + }) + +#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 SIZE_MAX == UINT64_MAX -#define isc_rotate_leftsize(x, n) isc_rotate_left64(x, n) -#define isc_rotate_rightsize(x, n) isc_rotate_right64(x, n) +#define ISC_ROTATE_LEFTSIZE(x, n) ISC_ROTATE_LEFT64(x, n) +#define ISC_ROTATE_RIGHTSIZE(x, n) ISC_ROTATE_RIGHT64(x, n) #elif SIZE_MAX == UINT32_MAX -#define isc_rotate_leftsize(x, n) isc_rotate_left32(x, n) -#define isc_rotate_rightsize(x, n) isc_rotate_right32(x, n) +#define ISC_ROTATE_LEFTSIZE(x, n) ISC_ROTATE_LEFT32(x, n) +#define ISC_ROTATE_RIGHTSIZE(x, n) ISC_ROTATE_RIGHT32(x, n) #else #error "size_t must be either 32 or 64-bits" #endif - -static inline uint8_t __attribute__((always_inline)) -isc_rotate_left8(const uint8_t x, uint32_t n) { - return (x << n) | (x >> (8 - n)); -} - -static inline uint16_t __attribute__((always_inline)) -isc_rotate_left16(const uint16_t x, uint32_t n) { - return (x << n) | (x >> (16 - n)); -} - -static inline uint32_t __attribute__((always_inline)) -isc_rotate_left32(const uint32_t x, uint32_t n) { - return (x << n) | (x >> (32 - n)); -} - -static inline uint64_t __attribute__((always_inline)) -isc_rotate_left64(const uint64_t x, uint32_t n) { - return (x << n) | (x >> (64 - n)); -} - -static inline uint8_t __attribute__((always_inline)) -isc_rotate_right8(const uint8_t x, uint32_t n) { - return (x >> n) | (x << (8 - n)); -} - -static inline uint16_t __attribute__((always_inline)) -isc_rotate_right16(const uint16_t x, uint32_t n) { - return (x >> n) | (x << (16 - n)); -} - -static inline uint32_t __attribute__((always_inline)) -isc_rotate_right32(const uint32_t x, uint32_t n) { - return (x >> n) | (x << (32 - n)); -} - -static inline uint64_t __attribute__((always_inline)) -isc_rotate_right64(const uint64_t x, uint32_t n) { - return (x >> n) | (x << (64 - n)); -} diff --git a/lib/isc/include/isc/fxhash.h b/lib/isc/include/isc/fxhash.h index 0ee1cb0b03..ac19d0ac4e 100644 --- a/lib/isc/include/isc/fxhash.h +++ b/lib/isc/include/isc/fxhash.h @@ -36,7 +36,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_LEFTSIZE(hash, 5) ^ i * K; } /* diff --git a/lib/isc/include/isc/siphash.h b/lib/isc/include/isc/siphash.h index 81cfaf30c3..ea3bd323a1 100644 --- a/lib/isc/include/isc/siphash.h +++ b/lib/isc/include/isc/siphash.h @@ -47,9 +47,9 @@ #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); + b = ISC_ROTATE_LEFT64(b, s) ^ a; \ + d = ISC_ROTATE_LEFT64(d, t) ^ c; \ + a = ISC_ROTATE_LEFT64(a, 32); #define FULL_ROUND64(v0, v1, v2, v3) \ HALF_ROUND64(v0, v1, v2, v3, 13, 16); \ @@ -60,9 +60,9 @@ #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); + b = ISC_ROTATE_LEFT32(b, s) ^ a; \ + d = ISC_ROTATE_LEFT32(d, t) ^ c; \ + a = ISC_ROTATE_LEFT32(a, 16); #define FULL_ROUND32(v0, v1, v2, v3) \ HALF_ROUND32(v0, v1, v2, v3, 5, 8); \