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, 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).

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;
and for
  x->p = whatever;
no .ACCESS_WITH_SIZE.

        Jakub

Reply via email to