From: Willy Tarreau Date: Tue, 17 Dec 2024 09:42:07 +0000 (+0100) Subject: MINOR: compiler: add ASSUME_NONNULL() to tell the compiler a pointer is valid X-Git-Tag: v3.2-dev2~57 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=63798088b300688af2fb480c5c7b91a1ca9970c5;p=thirdparty%2Fhaproxy.git MINOR: compiler: add ASSUME_NONNULL() to tell the compiler a pointer is valid At plenty of places we have ALREADY_CHECKED() or DISGUISE() on a pointer just to avoid "possibly null-deref" warnings. These ones have the side effect of weakening optimizations by passing through an assembly step. Using ASSUME_NONNULL() we can avoid that extra step. And when the __builtin_unreachable() builtin is not present, we fall back to the old method using assembly. The macro returns the input value so that it may be used both as a declarative way to claim non-nullity or directly inside an expression like DISGUISE(). --- diff --git a/include/haproxy/compiler.h b/include/haproxy/compiler.h index c3a610aed9..ced25b229c 100644 --- a/include/haproxy/compiler.h +++ b/include/haproxy/compiler.h @@ -220,13 +220,19 @@ * with compilers that support it, and we do not want to emit any static code * for other ones, so we use a construct that the compiler should easily be * able to optimize away. Clang also has __builtin_assume() since at least 3.x. + * In addition, ASSUME_NONNULL() tells the compiler that the pointer argument + * will never be null. If not supported, it will be disguised via an assembly + * step. */ #if __has_builtin(__builtin_assume) # define ASSUME(expr) __builtin_assume(expr) +# define ASSUME_NONNULL(p) ({ typeof(p) __p = (p); __builtin_assume(__p != NULL); (__p); }) #elif __has_builtin(__builtin_unreachable) # define ASSUME(expr) do { if (!(expr)) __builtin_unreachable(); } while (0) +# define ASSUME_NONNULL(p) ({ typeof(p) __p = (p); if (__p == NULL) __builtin_unreachable(); (__p); }) #else # define ASSUME(expr) do { if (!(expr)) break; } while (0) +# define ASSUME_NONNULL(p) ({ typeof(p) __p = (p); asm("" : "=rm"(__p) : "0"(__p)); __p; }) #endif /* This prevents the compiler from folding multiple identical code paths into a