On Sat, Jul 5, 2025 at 2:10 PM Siddhesh Poyarekar <siddh...@gotplt.org> wrote:
>
> On 2025-07-05 07:23, Richard Biener wrote:
> >> OK, should I revert right away or can we wait till Qing returns on Monday?
> >
> > Monday is OK with me.
> >
>
> Thanks, so I thought about this some more and I think when I said in
> bugzilla:
>
> "In fact, maybe the .ACCESS_WITH_SIZE handling in objsz probably needs
> improvement to express it better, but that's an orthogonal matter."
>
> I had the right intuition but I was completely wrong about it being an
> orthogonal matter.  That *is* the issue and it only becomes relevant
> when the member being described is a pointer and not a FAM.  e.g. for
> the following:
>
> ```
> struct A
> {
>    int count;
> #ifndef PTR
>    char c[] __attribute ((__counted_by__ (count)));
> #else
>    char *c __attribute ((__counted_by__ (count)));
> #endif
> } a;
>
> unsigned long
> foo (struct A *a)
> {
>    return __builtin_dynamic_object_size (a->c, 1);
> }
> ```
>
> the .ACCESS_WITH_SIZE abstraction records the size using &a->c:
>
>    _2 = &a->c;
>    _3 = &a->count;
>    _1 = .ACCESS_WITH_SIZE (_2, _3, 1, 0, -1, 0B);
>    D.2964 = __builtin_dynamic_object_size (_1, 1);
>
> this doesn't make a difference when c is an array since the & operator
> is a nop.  However when the same is applied to the pointer a->c, it
> becomes an additional dereference, which changes the semantic meaning:
>
>    _2 = &a->c;
>    _3 = &a->count;
>    _1 = .ACCESS_WITH_SIZE (_2, _3, 1, 0, -1, 0B);
>    _4 = *_1;
>    D.2964 = __builtin_dynamic_object_size (_4, 1);
>
> Since the intent of the .ACCESS_WITH_SIZE was to associate the storage
> of count with c to prevent reordering, maybe the semantically correct
> solution here is that when c is a pointer, the frontend emits:
>
>    _2 = a->c;
>    _3 = &a->count;
>    _1 = .ACCESS_WITH_SIZE (_2, _3, 1, 0, -1, 0B);
>    D.2964 = __builtin_dynamic_object_size (_, 1);
>
> so a->c instead of &a->c.

Yes.  That's what I'd have expected happens?  I thought .ACCESS_WITH_SIZE
annotates the pointer, it doesn't perform an access itself - correct?  Where
is .ACCESS_WITH_SIZE documented?  I can't find it documented in the
internals manual, internal-fn.def has

/* A function to associate the access size and access mode information
   with the corresponding reference to an object.  It only reads from the
   2nd argument.  */
DEF_INTERNAL_FN (ACCESS_WITH_SIZE, ECF_PURE | ECF_LEAF | ECF_NOTHROW, NULL)

that suggests .ACCESS_WITH_SIZE performs a read on the size.  It doesn't
say what the function returns at all.

Is the above only happening
when using __builtin_dynamic_object_size (_1, 1) or also when performing
an actual access like

 return a->c[i];

?

>  In fact, maybe taking the address of a->c
> doesn't make sense in general and .ACCESS_WITH_SIZE should always be the
> above even for FAM?  Does that sound correct?
>
> Sid

Reply via email to