> On Jul 17, 2025, at 11:40, Jakub Jelinek <ja...@redhat.com> wrote: > > On Thu, Jul 17, 2025 at 03:26:05PM +0000, Qing Zhao wrote: >> How about add a new flag to distinguish these two cases, and put it to the >> 3th argument: >> >> ACCESS_WITH_SIZE (REF_TO_OBJ, REF_TO_SIZE, >> TYPE_OF_SIZE + ACCESS_MODE + IS_POINTER, TYPE_SIZE_UNIT >> for element) >> which returns the REF_TO_OBJ same as the 1st argument; >> >> 1st argument REF_TO_OBJ: The reference to the object when IS_POINTER is >> false; >> The address of the reference to the object when IS_POINTER is true; >> 2nd argument REF_TO_SIZE: The reference to the size of the object, >> 3rd argument TYPE_OF_SIZE + ACCESS_MODE + IS_POINTER An integer constant >> with a pointer >> TYPE. >> The pointee TYPE of the pointer TYPE is the TYPE of the object referenced >> by REF_TO_SIZE. >> The integer constant value represents the ACCESS_MODE + IS_POINTER: >> 00: none >> 01: read_only >> 10: write_only >> 11: read_write >> 100: IS_POINTER > > Sure, I was talking about it before, the value of the 3rd argument can be a > set of various bit flags. > I still don't understand what do you want to use that > read_only/write_only/read_write flags for,
It will be used for implementing the attribute “access” with .ACCESS_WITH_SIZE: (a future work) https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-access-function-attribute access (access-mode, ref-index) The ACCESS_MODE flag in the 3rd argument is for carrying the above “access_mode” of the first argument of the “access” attribute. > if you mark loads from the > pointer, those will be always reads and whether something is load, store or > load/store of data pointed by that pointer is something normally visible in > the IL (plus you probably don't know it in the FE). Since I haven’t study this in details yet, not sure whether this is necessary or not to encode it into .ACCESS_WITH_SIZE. Maybe just this flag now? And add it later if we really need it? > > So say for > struct S { int s; int *p __attribute__((counted_by (s))); }; > > int > foo (struct S *x, int y) > { > return x->p[y]; > } > I would have expected you emit something like > _1 = x->p; > _6 = &x->s; > _5 = .ACCESS_WITH_SIZE (_1, _6, IS_POINTER, 4); > _2 = (long unsigned int) y; > _3 = _2 * 4; > _4 = _5 + _3; > D.2965 = *_4; The above IL doesn’t require an additional IS_POINTER flag for the .ACCESS_WITH_SIZE since The first argument is still the pointer for the object, same as the FAM case. With IS_POINTER flag added, we can pass the ADDRESS of the pointer as the first argument to .ACCESS_WITH_SIZE, and also return the ADDRESS of the pointer for the pointer with counted_by. i.e: _1 = &x->p; _6 = &x->s; _5 = .ACCESS_WITH_SIZE (_1, _6, IS_POINTER, 4); _2 = (long unsigned int) y; _3 = _2 * 4; _4 = *_5 + _3; D.2965 = *_4; > and for > x->p = whatever; > no .ACCESS_WITH_SIZE. With the IS_POINTER flag, and pass and return the ADDRESS of the pointer to .ACCESS_WITH_SIZE, It will be no correctness issue when we generate .ACCESS_WITH_SIZE for the above case. The only issue is for such case, the call to .ACCESS_WITH_SIZE is useless. Is this reasonable? Qing