Sync tools/include/linux/bitfield.h with include/linux/bitfield.h
changes since commit 590b949597b1 ("tools: Copy bitfield.h from the kernel
sources"). Preserve the tools-only linux/kernel.h include for endian
helpers; a follow-up selftest uses u64_replace_bits() from the
refreshed header.

Keep the synced native u*_..._bits() helpers on tools-local u* types,
while leaving endian helpers on __le* and __be*. This preserves the
tools convention that u64 is uint64_t and avoids printf format warnings
in selftests.

Add the supporting tools-side pieces required by the newer header:

  - tools/include/linux/typecheck.h for typecheck_pointer();
  - the auto compatibility macro in tools/compiler_types.h, guarded
    with !defined(__STDC_VERSION__) for pre-C99 tools builds and kept
    C-only so perf C++ sources keep the C++ auto keyword;
  - __ffs64() in tools/include/linux/bitops.h for non-constant-mask
    field helpers.

Assisted-by: Codex:gpt-5.5
Signed-off-by: Akihiko Odaki <[email protected]>
---
 tools/include/linux/bitfield.h       | 175 ++++++++++++++++++++++++++++++-----
 tools/include/linux/bitops.h         |  19 ++++
 tools/include/linux/compiler_types.h |  13 +++
 tools/include/linux/typecheck.h      |  34 +++++++
 4 files changed, 217 insertions(+), 24 deletions(-)

diff --git a/tools/include/linux/bitfield.h b/tools/include/linux/bitfield.h
index ddf81f24956b..b9a634b18881 100644
--- a/tools/include/linux/bitfield.h
+++ b/tools/include/linux/bitfield.h
@@ -8,7 +8,9 @@
 #define _LINUX_BITFIELD_H
 
 #include <linux/build_bug.h>
+#include <linux/compiler.h>
 #include <linux/kernel.h>
+#include <linux/typecheck.h>
 #include <asm/byteorder.h>
 
 /*
@@ -17,9 +19,13 @@
  * FIELD_{GET,PREP} macros take as first parameter shifted mask
  * from which they extract the base mask and shift amount.
  * Mask must be a compilation time constant.
+ * field_{get,prep} are variants that take a non-const mask.
  *
  * Example:
  *
+ *  #include <linux/bitfield.h>
+ *  #include <linux/bits.h>
+ *
  *  #define REG_FIELD_A  GENMASK(6, 0)
  *  #define REG_FIELD_B  BIT(7)
  *  #define REG_FIELD_C  GENMASK(15, 8)
@@ -36,8 +42,7 @@
  *       FIELD_PREP(REG_FIELD_D, 0x40);
  *
  * Modify:
- *  reg &= ~REG_FIELD_C;
- *  reg |= FIELD_PREP(REG_FIELD_C, c);
+ *  FIELD_MODIFY(REG_FIELD_C, &reg, c);
  */
 
 #define __bf_shf(x) (__builtin_ffsll(x) - 1)
@@ -58,21 +63,42 @@
 
 #define __bf_cast_unsigned(type, x)    ((__unsigned_scalar_typeof(type))(x))
 
-#define __BF_FIELD_CHECK(_mask, _reg, _val, _pfx)                      \
+#define __BF_FIELD_CHECK_MASK(_mask, _val, _pfx)                       \
        ({                                                              \
                BUILD_BUG_ON_MSG(!__builtin_constant_p(_mask),          \
                                 _pfx "mask is not constant");          \
                BUILD_BUG_ON_MSG((_mask) == 0, _pfx "mask is zero");    \
                BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ?           \
-                                ~((_mask) >> __bf_shf(_mask)) & (_val) : 0, \
+                                ~((_mask) >> __bf_shf(_mask)) &        \
+                                       (0 + (_val)) : 0,               \
                                 _pfx "value too large for the field"); \
-               BUILD_BUG_ON_MSG(__bf_cast_unsigned(_mask, _mask) >     \
-                                __bf_cast_unsigned(_reg, ~0ull),       \
-                                _pfx "type of reg too small for mask"); \
                __BUILD_BUG_ON_NOT_POWER_OF_2((_mask) +                 \
                                              (1ULL << __bf_shf(_mask))); \
        })
 
+#define __BF_FIELD_CHECK_REG(mask, reg, pfx)                           \
+       BUILD_BUG_ON_MSG(__bf_cast_unsigned(mask, mask) >               \
+                        __bf_cast_unsigned(reg, ~0ull),                \
+                        pfx "type of reg too small for mask")
+
+#define __BF_FIELD_CHECK(mask, reg, val, pfx)                          \
+       ({                                                              \
+               __BF_FIELD_CHECK_MASK(mask, val, pfx);                  \
+               __BF_FIELD_CHECK_REG(mask, reg, pfx);                   \
+       })
+
+#define __FIELD_PREP(mask, val, pfx)                                   \
+       ({                                                              \
+               __BF_FIELD_CHECK_MASK(mask, val, pfx);                  \
+               ((typeof(mask))(val) << __bf_shf(mask)) & (mask);       \
+       })
+
+#define __FIELD_GET(mask, reg, pfx)                                    \
+       ({                                                              \
+               __BF_FIELD_CHECK_MASK(mask, 0U, pfx);                   \
+               (typeof(mask))(((reg) & (mask)) >> __bf_shf(mask));     \
+       })
+
 /**
  * FIELD_MAX() - produce the maximum value representable by a field
  * @_mask: shifted mask defining the field's length and position
@@ -109,10 +135,36 @@
  */
 #define FIELD_PREP(_mask, _val)                                                
\
        ({                                                              \
-               __BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_PREP: ");    \
-               ((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask);   \
+               __BF_FIELD_CHECK_REG(_mask, 0ULL, "FIELD_PREP: ");      \
+               __FIELD_PREP(_mask, _val, "FIELD_PREP: ");              \
        })
 
+#define __BF_CHECK_POW2(n)     BUILD_BUG_ON_ZERO(((n) & ((n) - 1)) != 0)
+
+/**
+ * FIELD_PREP_CONST() - prepare a constant bitfield element
+ * @_mask: shifted mask defining the field's length and position
+ * @_val:  value to put in the field
+ *
+ * FIELD_PREP_CONST() masks and shifts up the value.  The result should
+ * be combined with other fields of the bitfield using logical OR.
+ *
+ * Unlike FIELD_PREP() this is a constant expression and can therefore
+ * be used in initializers. Error checking is less comfortable for this
+ * version, and non-constant masks cannot be used.
+ */
+#define FIELD_PREP_CONST(_mask, _val)                                  \
+       (                                                               \
+               /* mask must be non-zero */                             \
+               BUILD_BUG_ON_ZERO((_mask) == 0) +                       \
+               /* check if value fits */                               \
+               BUILD_BUG_ON_ZERO(~((_mask) >> __bf_shf(_mask)) & (_val)) + \
+               /* check if mask is contiguous */                       \
+               __BF_CHECK_POW2((_mask) + (1ULL << __bf_shf(_mask))) +  \
+               /* and create the value */                              \
+               (((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask))  \
+       )
+
 /**
  * FIELD_GET() - extract a bitfield element
  * @_mask: shifted mask defining the field's length and position
@@ -123,8 +175,25 @@
  */
 #define FIELD_GET(_mask, _reg)                                         \
        ({                                                              \
-               __BF_FIELD_CHECK(_mask, _reg, 0U, "FIELD_GET: ");       \
-               (typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \
+               __BF_FIELD_CHECK_REG(_mask, _reg, "FIELD_GET: ");       \
+               __FIELD_GET(_mask, _reg, "FIELD_GET: ");                \
+       })
+
+/**
+ * FIELD_MODIFY() - modify a bitfield element
+ * @_mask: shifted mask defining the field's length and position
+ * @_reg_p: pointer to the memory that should be updated
+ * @_val: value to store in the bitfield
+ *
+ * FIELD_MODIFY() modifies the set of bits in @_reg_p specified by @_mask,
+ * by replacing them with the bitfield value passed in as @_val.
+ */
+#define FIELD_MODIFY(_mask, _reg_p, _val)                                      
        \
+       ({                                                                      
        \
+               typecheck_pointer(_reg_p);                                      
        \
+               __BF_FIELD_CHECK(_mask, *(_reg_p), _val, "FIELD_MODIFY: ");     
        \
+               *(_reg_p) &= ~(_mask);                                          
        \
+               *(_reg_p) |= (((typeof(_mask))(_val) << __bf_shf(_mask)) & 
(_mask));    \
        })
 
 extern void __compiletime_error("value doesn't fit into mask")
@@ -142,36 +211,94 @@ static __always_inline u64 field_mask(u64 field)
        return field / field_multiplier(field);
 }
 #define field_max(field)       ((typeof(field))field_mask(field))
-#define ____MAKE_OP(type,base,to,from)                                 \
-static __always_inline __##type type##_encode_bits(base v, base field) \
+#define ____MAKE_OP(name,type,base,to,from)                            \
+static __always_inline type __must_check name##_encode_bits(base v, base 
field)        \
 {                                                                      \
        if (__builtin_constant_p(v) && (v & ~field_mask(field)))        \
                __field_overflow();                                     \
        return to((v & field_mask(field)) * field_multiplier(field));   \
 }                                                                      \
-static __always_inline __##type type##_replace_bits(__##type old,      \
-                                       base val, base field)           \
+static __always_inline type __must_check name##_replace_bits(type old, \
+                                                       base val, base field)   
\
 {                                                                      \
-       return (old & ~to(field)) | type##_encode_bits(val, field);     \
+       return (old & ~to(field)) | name##_encode_bits(val, field);     \
 }                                                                      \
-static __always_inline void type##p_replace_bits(__##type *p,          \
+static __always_inline void name##p_replace_bits(type *p,              \
                                        base val, base field)           \
 {                                                                      \
-       *p = (*p & ~to(field)) | type##_encode_bits(val, field);        \
+       *p = (*p & ~to(field)) | name##_encode_bits(val, field);        \
 }                                                                      \
-static __always_inline base type##_get_bits(__##type v, base field)    \
+static __always_inline base __must_check name##_get_bits(type v, base field)   
\
 {                                                                      \
        return (from(v) & field)/field_multiplier(field);               \
 }
-#define __MAKE_OP(size)                                                        
\
-       ____MAKE_OP(le##size,u##size,cpu_to_le##size,le##size##_to_cpu) \
-       ____MAKE_OP(be##size,u##size,cpu_to_be##size,be##size##_to_cpu) \
-       ____MAKE_OP(u##size,u##size,,)
-____MAKE_OP(u8,u8,,)
+#define __MAKE_OP(size)                                                        
                \
+       
____MAKE_OP(le##size,__le##size,u##size,cpu_to_le##size,le##size##_to_cpu)      
\
+       
____MAKE_OP(be##size,__be##size,u##size,cpu_to_be##size,be##size##_to_cpu)      
\
+       ____MAKE_OP(u##size,u##size,u##size,,)
+____MAKE_OP(u8,u8,u8,,)
 __MAKE_OP(16)
 __MAKE_OP(32)
 __MAKE_OP(64)
 #undef __MAKE_OP
 #undef ____MAKE_OP
 
+#define __field_prep(mask, val)                                                
\
+       ({                                                              \
+               auto __mask = (mask);                                   \
+               typeof(__mask) __val = (val);                           \
+               unsigned int __shift = BITS_PER_TYPE(__mask) <= 32 ?    \
+                                      __ffs(__mask) : __ffs64(__mask); \
+               (__val << __shift) & __mask;                            \
+       })
+
+#define __field_get(mask, reg)                                         \
+       ({                                                              \
+               auto __mask = (mask);                                   \
+               typeof(__mask) __reg =  (reg);                          \
+               unsigned int __shift = BITS_PER_TYPE(__mask) <= 32 ?    \
+                                      __ffs(__mask) : __ffs64(__mask); \
+               (__reg & __mask) >> __shift;                            \
+       })
+
+/**
+ * field_prep() - prepare a bitfield element
+ * @mask: shifted mask defining the field's length and position, must be
+ *        non-zero
+ * @val:  value to put in the field
+ *
+ * Return: field value masked and shifted to its final destination
+ *
+ * field_prep() masks and shifts up the value.  The result should be
+ * combined with other fields of the bitfield using logical OR.
+ * Unlike FIELD_PREP(), @mask is not limited to a compile-time constant.
+ * Typical usage patterns are a value stored in a table, or calculated by
+ * shifting a constant by a variable number of bits.
+ * If you want to ensure that @mask is a compile-time constant, please use
+ * FIELD_PREP() directly instead.
+ */
+#define field_prep(mask, val)                                          \
+       (__builtin_constant_p(mask) ? __FIELD_PREP(mask, val, "field_prep: ") \
+                                   : __field_prep(mask, val))
+
+/**
+ * field_get() - extract a bitfield element
+ * @mask: shifted mask defining the field's length and position, must be
+ *        non-zero
+ * @reg:  value of entire bitfield
+ *
+ * Return: extracted field value
+ *
+ * field_get() extracts the field specified by @mask from the
+ * bitfield passed in as @reg by masking and shifting it down.
+ * Unlike FIELD_GET(), @mask is not limited to a compile-time constant.
+ * Typical usage patterns are a value stored in a table, or calculated by
+ * shifting a constant by a variable number of bits.
+ * If you want to ensure that @mask is a compile-time constant, please use
+ * FIELD_GET() directly instead.
+ */
+#define field_get(mask, reg)                                           \
+       (__builtin_constant_p(mask) ? __FIELD_GET(mask, reg, "field_get: ") \
+                                   : __field_get(mask, reg))
+
 #endif
diff --git a/tools/include/linux/bitops.h b/tools/include/linux/bitops.h
index b4e4cd071f8c..0dfd61a7a35d 100644
--- a/tools/include/linux/bitops.h
+++ b/tools/include/linux/bitops.h
@@ -100,4 +100,23 @@ static __always_inline __s64 sign_extend64(__u64 value, 
int index)
        return (__s64)(value << shift) >> shift;
 }
 
+/**
+ * __ffs64 - find first set bit in a 64 bit word
+ * @word: The 64 bit word
+ *
+ * On 64 bit arches this is a synonym for __ffs
+ * The result is not defined if no bits are set, so check that @word
+ * is non-zero before calling this.
+ */
+static inline __attribute_const__ unsigned int __ffs64(u64 word)
+{
+#if BITS_PER_LONG == 32
+       if (((u32)word) == 0UL)
+               return __ffs((u32)(word >> 32)) + 32;
+#elif BITS_PER_LONG != 64
+#error BITS_PER_LONG not 32 or 64
+#endif
+       return __ffs((unsigned long)word);
+}
+
 #endif
diff --git a/tools/include/linux/compiler_types.h 
b/tools/include/linux/compiler_types.h
index b3adbf5682f0..287a1a26cb05 100644
--- a/tools/include/linux/compiler_types.h
+++ b/tools/include/linux/compiler_types.h
@@ -13,6 +13,19 @@
 #define __has_builtin(x) (0)
 #endif
 
+/*
+ * C23 introduces "auto" as a standard way to define type-inferred
+ * variables, but "auto" has been a (useless) keyword even since K&R C,
+ * so it has always been "namespace reserved."
+ *
+ * Until at some future time we require C23 support, we need the gcc
+ * extension __auto_type, but there is no reason to put that elsewhere
+ * in the source code.
+ */
+#if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 
202311L)
+# define auto __auto_type
+#endif
+
 #include <linux/compiler-context-analysis.h>
 
 /* Compiler specific macros. */
diff --git a/tools/include/linux/typecheck.h b/tools/include/linux/typecheck.h
new file mode 100644
index 000000000000..46b15e2aaefb
--- /dev/null
+++ b/tools/include/linux/typecheck.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef TYPECHECK_H_INCLUDED
+#define TYPECHECK_H_INCLUDED
+
+/*
+ * Check at compile time that something is of a particular type.
+ * Always evaluates to 1 so you may use it easily in comparisons.
+ */
+#define typecheck(type,x) \
+({     type __dummy; \
+       typeof(x) __dummy2; \
+       (void)(&__dummy == &__dummy2); \
+       1; \
+})
+
+/*
+ * Check at compile time that 'function' is a certain type, or is a pointer
+ * to that type (needs to use typedef for the function type.)
+ */
+#define typecheck_fn(type,function) \
+({     typeof(type) __tmp = function; \
+       (void)__tmp; \
+})
+
+/*
+ * Check at compile time that something is a pointer type.
+ */
+#define typecheck_pointer(x) \
+({     typeof(x) __dummy; \
+       (void)sizeof(*__dummy); \
+       1; \
+})
+
+#endif         /* TYPECHECK_H_INCLUDED */

-- 
2.55.0


Reply via email to