-
- Downloads
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.
Showing
- gcc/c-family/c-common.cc 1 addition, 0 deletionsgcc/c-family/c-common.cc
- gcc/c-family/c-common.h 1 addition, 0 deletionsgcc/c-family/c-common.h
- gcc/c/c-decl.cc 1 addition, 0 deletionsgcc/c/c-decl.cc
- gcc/c/c-parser.cc 79 additions, 0 deletionsgcc/c/c-parser.cc
- gcc/c/c-tree.h 1 addition, 0 deletionsgcc/c/c-tree.h
- gcc/c/c-typeck.cc 24 additions, 9 deletionsgcc/c/c-typeck.cc
- gcc/doc/extend.texi 55 additions, 0 deletionsgcc/doc/extend.texi
- gcc/testsuite/gcc.dg/builtin-counted-by-ref-1.c 135 additions, 0 deletionsgcc/testsuite/gcc.dg/builtin-counted-by-ref-1.c
- gcc/testsuite/gcc.dg/builtin-counted-by-ref.c 61 additions, 0 deletionsgcc/testsuite/gcc.dg/builtin-counted-by-ref.c
Loading
Please register or sign in to comment