On Wed, Sep 17, 2025 at 04:39:12PM +0100, Yury Khrustalev wrote:
> Lack of DW_AT_bit_stride in a DW_TAG_array_type entry causes GDB to infer
> incorrect element size for vector types. The causes incorrect display of
> SVE predicate variables as well as out of bounds memory access when reading
> contents of SVE predicates from memory in GDB.
>
> PR debug/121964
>
> gcc/
> * dwarf2out.cc
> (base_type_die): add DW_AT_bit_size attribute
> for boolean types.
> (gen_array_type_die): add DW_AT_bit_stride attribute for
> array types based on element type bit precision for integer
> and boolean element types.
Some nits in the ChangeLog entry, there should be no newline after
* dwarf2out.cc
line unless the filename + name of the function is too long to fit
on one line (not the case here). Plus, both add should be Add
because after : it starts a sentence.
> --- a/gcc/dwarf2out.cc
> +++ b/gcc/dwarf2out.cc
> @@ -13360,7 +13360,8 @@ base_type_die (tree type, bool reverse)
> add_AT_unsigned (base_type_result, DW_AT_byte_size,
> int_size_in_bytes (type));
> add_AT_unsigned (base_type_result, DW_AT_encoding, encoding);
> - if (TREE_CODE (type) == BITINT_TYPE)
> + if (TREE_CODE (type) == BITINT_TYPE
> + || TREE_CODE (type) == BOOLEAN_TYPE)
> add_AT_unsigned (base_type_result, DW_AT_bit_size, TYPE_PRECISION
> (type));
This looks wrong to me (and after all, is probably wrong also for
BITINT_TYPE, but it isn't clear to me how else to represent the _BitInt
precision in the debug info other than having to parse the name of the type).
So perhaps something we should discuss in the DWARF committee.
DWARF5 seems to say that DIEs have either DW_AT_byte_size or DW_AT_bit_size,
one being in bytes, one being in bits. For _BitInt it is always a type
with size in bytes but it is interesting to know for how many bits it has
been declared. For bool/_Bool that number would be 1 and I guess all
debuggers ought to be handling that fine already without being told.
I'd certainly not change this for bool/_Bool at this point.
> if (need_endianity_attribute_p (reverse))
> @@ -22765,6 +22766,14 @@ gen_array_type_die (tree type, dw_die_ref
> context_die)
> /* Add representation of the type of the elements of this array type and
> emit the corresponding DIE if we haven't done it already. */
> element_type = TREE_TYPE (type);
> +
> + /* Add bit stride information so that elements can be correctly
> + read and displayed by a debugger. */
> + if (TREE_CODE (element_type) == BITINT_TYPE
> + || TREE_CODE (element_type) == BOOLEAN_TYPE)
> + add_AT_unsigned (array_die,
> + DW_AT_bit_stride, TYPE_PRECISION (element_type));
This looks also wrong and actually much worse.
DWARF5 again says that it is either DW_AT_byte_stride or DW_AT_bit_stride
that should be specified. I think we generally don't emit DW_AT_byte_stride
attribute on arrays except for e.g. some Fortran arrays or in Ada.
But, as even showed in examples in DWARF5, DW_AT_bit_stride is meant for
say Pascal PACKED ARRAY (see D.2.7), I think Ada has similar things.
If in C one uses:
bool a[10];
_BitInt(129) b[10];
then using DW_AT_bit_stride 1 or 129 is completely wrong on those.
Those would mean that a[1] is at bit position 1 (while it is at sizeof
(bool)), a[2] is at bit position 2 (while it is at sizeof (bool) * 2), or
that b[1] starts at bit position 129 into the array, while it starts at
sizeof (_BitInt(129)) * CHAR_BIT, typically 192 or 256).
So, DW_AT_bit_stride certainly must not be added for normal arrays, only
VECTOR_TYPEs (i.e. what we represent in DWARF as DW_TAG_array_type with
DW_AT_GNU_vector attribute). And even in that case what exactly
DW_AT_bit_stride should be used (and we probably should also in that case
arrange to have DW_AT_byte_size on the same DIE at least in some cases).
Note, we don't support vectors of _BitInt, so that case should be left out,
the only thing to handle is VECTOR_BOOLEAN_TYPE_P.
Either the type has MODE_VECTOR_BOOL class mode (aarch64, arm, riscv
currently), in that case
VECTOR_BOOL_MODE (NAME, COUNT, COMPONENT, BYTESIZE)
Create a vector mode called NAME that contains COUNT boolean
elements and occupies BYTESIZE bytes in total. Each boolean
element is of COMPONENT type and occupies (COUNT * BITS_PER_UNIT) /
BYTESIZE bits, with the element at index 0 occupying the lsb of the
first byte in memory. Only the lowest bit of each element is
significant.
documentation applies. That isn't always 1-bit stride, guess sometimes
can be more than 1, e.g. 2 or 4, even on aarch64. What strides do
config/aarch64/aarch64-modes.def:VECTOR_BOOL_MODE (VNx8BI, 8, BI, 2);
config/aarch64/aarch64-modes.def:VECTOR_BOOL_MODE (VNx4BI, 4, BI, 2);
config/aarch64/aarch64-modes.def:VECTOR_BOOL_MODE (VNx2BI, 2, BI, 2);
modes have? Isn't that 2, 4 and 8? Though the comment looks wrong,
I think each boolean element occupies (BYTESIZE * BITS_PER_UNIT) / COUNT
bits, not the other way around. And perhaps we need to specify also
DW_AT_bit_size on the DW_AT_type referenced DIE (but only on that, not
generally all bools). Then other targets like e.g. x86 with -mavx512vl
have VECTOR_BOOLEAN_TYPE_P with MODE_INT modes where it is from least
significant bit up mode mask in an integer, not really sure how to represent
that in DWARF (and if we actually need to at all, we don't support
typedef bool V __attribute__((vector_size (64)));
), and last case of VECTOR_BOOLEAN_TYPE_P is when it has some MODE_VECTOR_INT
(or MODE_VECTOR_FLOAT?) mode, that is e.g. for x86 with -mavx2, where
it is a vector of all zero or all ones elements (and true is if the most
significant bit is set).
Unless boolean vectors on non-aarch64/arm/riscv targets can make it,
I'd suggest to try to handle only
VECTOR_BOOLEAN_TYPE_P (type)
&& GET_MODE_CLASS (TYPE_MODE (type)) == MODE_VECTOR_BOOL
types and in that case figure out the right stride (1, 2, 4, 8, ...)
and add also DW_AT_byte_size to the type (at least if constant) and
as DW_AT_type use some special variant of bool with DW_AT_bit_size (and no
DW_AT_byte_size) set to 1, 2, 4 or 8 (whatever the bit stride is).
Jakub