> On Jul 7, 2025, at 02:05, Richard Biener <richard.guent...@gmail.com> wrote:
> 
> 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, the .ACCESS_WITH_SIZE for the pointer was originally implemented like the 
above, 
 it behaved almost fine, but with a fundamental bug during my testing at that 
time, then I changed 
the returned type of the .ACCESS_WITH_SIZE  from “the original pointer” to "the 
pointer to the original pointer”.

I need to figure out the details of that original fundamental bug with the 
original implementation. 
That bug should be covered by my current testing cases. 

Will update when I locate the original bug.

thanks.

Qing
> 
> 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