https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116016

--- Comment #67 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Qing Zhao <qinz...@gcc.gnu.org>:

https://gcc.gnu.org/g:e7380688fa5917011c3fb85b5e06fb00f776a95d

commit r15-4370-ge7380688fa5917011c3fb85b5e06fb00f776a95d
Author: Qing Zhao <qing.z...@oracle.com>
Date:   Tue Oct 15 17:55:22 2024 +0000

    Provide new GCC builtin __builtin_counted_by_ref [PR116016]

    With the addition of the 'counted_by' attribute and its wide roll-out
    within the Linux kernel, a use case has been found that would be very
    nice to have for object allocators: being able to set the counted_by
    counter variable without knowing its name.

    For example, given:

      struct foo {
        ...
        int counter;
        ...
        struct bar array[] __attribute__((counted_by (counter)));
      } *p;

    The existing Linux object allocators are roughly:

      #define MAX(A, B) (A > B) ? (A) : (B)
      #define alloc(P, FAM, COUNT) ({ \
        __auto_type __p = &(P); \
        size_t __size = MAX (sizeof(*P),
                             __builtin_offsetof (__typeof(*P), FAM)
                             + sizeof (*(P->FAM)) * COUNT); \
        *__p = kmalloc(__size); \
      })

    Right now, any addition of a counted_by annotation must also
    include an open-coded assignment of the counter variable after
    the allocation:

      p = alloc(p, array, how_many);
      p->counter = how_many;

    In order to avoid the tedious and error-prone work of manually adding
    the open-coded counted-by intializations everywhere in the Linux
    kernel, a new GCC builtin __builtin_counted_by_ref will be very useful
    to be added to help the adoption of the counted-by attribute.

     -- Built-in Function: TYPE __builtin_counted_by_ref (PTR)
         The built-in function '__builtin_counted_by_ref' checks whether the
         array object pointed by the pointer PTR has another object
         associated with it that represents the number of elements in the
         array object through the 'counted_by' attribute (i.e.  the
         counted-by object).  If so, returns a pointer to the corresponding
         counted-by object.  If such counted-by object does not exist,
         returns a null pointer.

         This built-in function is only available in C for now.

         The argument PTR must be a pointer to an array.  The TYPE of the
         returned value is a pointer type pointing to the corresponding
         type of the counted-by object or a void pointer type in case of a
         null pointer being returned.

    With this new builtin, the central allocator could be updated to:

      #define MAX(A, B) (A > B) ? (A) : (B)
      #define alloc(P, FAM, COUNT) ({ \
        __auto_type __p = &(P); \
        __auto_type __c = (COUNT); \
        size_t __size = MAX (sizeof (*(*__p)),\
                             __builtin_offsetof (__typeof(*(*__p)),FAM) \
                             + sizeof (*((*__p)->FAM)) * __c); \
        if ((*__p = kmalloc(__size))) { \
          __auto_type ret = __builtin_counted_by_ref((*__p)->FAM); \
          *_Generic(ret, void *: &(size_t){0}, default: ret) = __c; \
        } \
      })

    And then structs can gain the counted_by attribute without needing
    additional open-coded counter assignments for each struct, and
    unannotated structs could still use the same allocator.

            PR c/116016

    gcc/c-family/ChangeLog:

            * c-common.cc: Add new __builtin_counted_by_ref.
            * c-common.h (enum rid): Add RID_BUILTIN_COUNTED_BY_REF.

    gcc/c/ChangeLog:

            * c-decl.cc (names_builtin_p): Add RID_BUILTIN_COUNTED_BY_REF.
            * c-parser.cc (has_counted_by_object): New routine.
            (get_counted_by_ref): New routine.
            (c_parser_postfix_expression): Handle New
RID_BUILTIN_COUNTED_BY_REF.
            * c-tree.h: New routine handle_counted_by_for_component_ref.
            * c-typeck.cc (handle_counted_by_for_component_ref): New routine.
            (build_component_ref): Call the new routine.

    gcc/ChangeLog:

            * doc/extend.texi: Add documentation for __builtin_counted_by_ref.

    gcc/testsuite/ChangeLog:

            * gcc.dg/builtin-counted-by-ref-1.c: New test.
            * gcc.dg/builtin-counted-by-ref.c: New test.

Reply via email to