]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: compiler: add ASSUME_NONNULL() to tell the compiler a pointer is valid
authorWilly Tarreau <w@1wt.eu>
Tue, 17 Dec 2024 09:42:07 +0000 (10:42 +0100)
committerWilly Tarreau <w@1wt.eu>
Tue, 17 Dec 2024 15:46:46 +0000 (16:46 +0100)
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().

include/haproxy/compiler.h

index c3a610aed964ee79cdd226d5ecfbeb1a4592f2aa..ced25b229cf65842deb5cb2aa93c8bc145e0b8c8 100644 (file)
  * 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