On 2025-07-07 03:05, Richard Biener wrote:
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
Yes.
is .ACCESS_WITH_SIZE documented? I can't find it documented in the
internals manual, internal-fn.def has
It's documented in tree-object-size.cc as:
/* Compute __builtin_object_size for a CALL to .ACCESS_WITH_SIZE,
OBJECT_SIZE_TYPE is the second argument from __builtin_object_size.
The 2nd, 3rd, and the 4th parameters of the call determine the size of
the CALL:
2nd argument REF_TO_SIZE: The reference to the size of the object,
3rd argument CLASS_OF_SIZE: The size referenced by the REF_TO_SIZE
represents
0: the number of bytes;
1: the number of the elements of the object type;
4th argument TYPE_OF_SIZE: A constant 0 with its TYPE being the same
as the TYPE
of the object referenced by REF_TO_SIZE
6th argument: A constant 0 with the pointer TYPE to the original
flexible
array type or pointer field type.
The size of the element can be retrived from the TYPE of the 6th
argument
of the call, which is the pointer to the original flexible array type or
the type of the original pointer field. */
which doesn't document the return either. This should have more verbose
documentation in the internals, including the rationale for its existence.
/* 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.
In practice the function is a nop, it gets optimized away during RTL
expansion. The aim is simply to pretend that the reference of the size
may escape pointer to make sure that any preceding updates to size don't
get reordered w.r.t. __builtin_dynamic_object_size since the latter
could get expanded to that size.
The return value of .ACCESS_WITH_SIZE clobbering PTR (that subsequently
gets passed to __builtin_dynamic_object_size) should be sufficient to
fully prevent the reordering, it shouldn't have to clobber &PTR, I think.
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];
It is only for __builtin_dynamic_object_size, so it would also include
ubsan/object-size sanitizer cases where it generates
__builtin_dynamic_object_size calls.
Sid