dwarf: Save bit stride information array type entry [PR121964]

Message ID 20250917153912.3187098-1-yury.khrustalev@arm.com
State Superseded
Headers
Series dwarf: Save bit stride information array type entry [PR121964] |

Commit Message

Yury Khrustalev Sept. 17, 2025, 3:39 p.m. UTC
  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.

gcc/testsuite/
	* g++.target/aarch64/sve/dwarf-bit-stride.C: New test.
	* gcc.target/aarch64/sve/dwarf-bit-stride.c: New test.
---

Passes regression on aarch64. OK for trunk?

base-commit: 282c1e682e0

---
 gcc/dwarf2out.cc                                  | 11 ++++++++++-
 .../g++.target/aarch64/sve/dwarf-bit-stride.C     | 15 +++++++++++++++
 .../gcc.target/aarch64/sve/dwarf-bit-stride.c     | 15 +++++++++++++++
 3 files changed, 40 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.target/aarch64/sve/dwarf-bit-stride.C
 create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/dwarf-bit-stride.c
  

Comments

Tamar Christina Sept. 19, 2025, 6:25 a.m. UTC | #1
> -----Original Message-----
> From: Yury Khrustalev <yury.khrustalev@arm.com>
> Sent: Wednesday, September 17, 2025 4:39 PM
> To: gcc-patches@gcc.gnu.org
> Cc: Tamar Christina <Tamar.Christina@arm.com>; Srinath Parvathaneni
> <Srinath.Parvathaneni@arm.com>; Tejas Belagod <Tejas.Belagod@arm.com>;
> jakub@redhat.com
> Subject: [PATCH] dwarf: Save bit stride information array type entry [PR121964]
> 
> 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.
> 
> gcc/testsuite/
> 	* g++.target/aarch64/sve/dwarf-bit-stride.C: New test.
> 	* gcc.target/aarch64/sve/dwarf-bit-stride.c: New test.
> ---
> 
> Passes regression on aarch64. OK for trunk?
> 
> base-commit: 282c1e682e0
> 
> ---
>  gcc/dwarf2out.cc                                  | 11 ++++++++++-
>  .../g++.target/aarch64/sve/dwarf-bit-stride.C     | 15 +++++++++++++++
>  .../gcc.target/aarch64/sve/dwarf-bit-stride.c     | 15 +++++++++++++++
>  3 files changed, 40 insertions(+), 1 deletion(-)
>  create mode 100644 gcc/testsuite/g++.target/aarch64/sve/dwarf-bit-stride.C
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/dwarf-bit-stride.c
> 
> diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc
> index 0bd8474bc37..aaaa578ce56 100644
> --- 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));
> 
>    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));
> +
>    if (collapse_nested_arrays)
>      while (TREE_CODE (element_type) == ARRAY_TYPE)
>        {
> diff --git a/ gcc/testsuite/gcc.target/aarch64/sve/dwarf-bit-stride.C
> b/gcc/testsuite/g++.target/aarch64/sve/dwarf-bit-stride.C
> new file mode 100644
> index 00000000000..bbc967c7ffd
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/aarch64/sve/dwarf-bit-stride.C
> @@ -0,0 +1,15 @@
> +/* { dg-do compile { target aarch64_asm_sve_ok } } */

Since you're only doing a compile test you don't need the assembler
support checks. i.e. just dg-do compile is enough.

Other than that the patch looks good to me but I can't approve the
generic bits.

Thanks,
Tamar

> +// { dg-options "-g -dA" }
> +// { dg-final { scan-assembler-times "DW_AT_bit_stride" 2 } }
> +// { dg-final { scan-assembler-times "DW_AT_GNU_vector" 2 } }
> +// { dg-final { scan-assembler-times "DW_TAG_array_type" 2 } }
> +
> +#include <arm_sve.h>
> +
> +void fun ()
> +{
> +  volatile svbool_t pred8 = svwhilelt_b8_u32 (0u, 1u);
> +  volatile svbool_t pred16 = svwhilelt_b16_u32 (0u, 3u);
> +  volatile svbool_t pred32 = svwhilelt_b32_u32 (0u, 7u);
> +  volatile svbool_t pred64 = svwhilelt_b64_u32 (0u, 11u);
> +}
> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/dwarf-bit-stride.c
> b/gcc/testsuite/gcc.target/aarch64/sve/dwarf-bit-stride.c
> new file mode 100644
> index 00000000000..bbc967c7ffd
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sve/dwarf-bit-stride.c
> @@ -0,0 +1,15 @@
> +/* { dg-do compile { target aarch64_asm_sve_ok } } */
> +// { dg-options "-g -dA" }
> +// { dg-final { scan-assembler-times "DW_AT_bit_stride" 2 } }
> +// { dg-final { scan-assembler-times "DW_AT_GNU_vector" 2 } }
> +// { dg-final { scan-assembler-times "DW_TAG_array_type" 2 } }
> +
> +#include <arm_sve.h>
> +
> +void fun ()
> +{
> +  volatile svbool_t pred8 = svwhilelt_b8_u32 (0u, 1u);
> +  volatile svbool_t pred16 = svwhilelt_b16_u32 (0u, 3u);
> +  volatile svbool_t pred32 = svwhilelt_b32_u32 (0u, 7u);
> +  volatile svbool_t pred64 = svwhilelt_b64_u32 (0u, 11u);
> +}
> --
> 2.47.3
  
Yury Khrustalev Sept. 29, 2025, 10:33 a.m. UTC | #2
A polite ping :)

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.
> 
> gcc/testsuite/
> 	* g++.target/aarch64/sve/dwarf-bit-stride.C: New test.
> 	* gcc.target/aarch64/sve/dwarf-bit-stride.c: New test.
> ---
> 
> Passes regression on aarch64. OK for trunk?
> 
> base-commit: 282c1e682e0
  
Jakub Jelinek Oct. 6, 2025, 12:24 p.m. UTC | #3
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
  
Yury Khrustalev Oct. 7, 2025, 2:50 p.m. UTC | #4
Hi Jakub,

Thanks for a very detailed response!

On Mon, Oct 06, 2025 at 02:24:08PM +0200, Jakub Jelinek wrote:
> 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.
> > ... 
> 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.

Will fix, thanks!

> > ...
> > +  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.

Noted. I agree that this change would be unnecessary for the issue that I
am trying to solve.

> > ...
> > +  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.
> ...

Correct, thanks for pointing this out, I entirely missed this.

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

This makes sense and works for SVE predicate vectors with one caveat...

> types and in that case figure out the right stride (1, 2, 4, 8, ...)


would imply that TYPE_PRECISION (element_type) is always 1? In this case
we can probably use this:

VECTOR_BOOLEAN_TYPE_P (type) && TYPE_PRECISION (element_type) == 1

and set DW_AT_bit_stride to 1?

The issue with GET_MODE_CLASS (TYPE_MODE (type)) is that TYPE_MODE (type)
may return E_BLKmode because TYPE_MODE would adapt to the current ISA.
In the case of SVE, one can use the svbool_t type with the -march=...+sve
command line flag (in which case TYPE_MODE (type) would work), but it
can also be used with the gnu::target attribute (in which case TYPE_MODE (type)
would return E_BLKmode and the check for MODE_VECTOR_BOOL would fail).

I appreciate that this seems like a partial solution, but at least it is
correct in a sense that all boolean vectors with element size 1 bit
should have DW_AT_bit_stride = 1.

Thanks,
Yury
  
Richard Biener Oct. 7, 2025, 4:01 p.m. UTC | #5
> Am 07.10.2025 um 16:54 schrieb Yury Khrustalev <yury.khrustalev@arm.com>:
> 
> Hi Jakub,
> 
> Thanks for a very detailed response!
> 
>> On Mon, Oct 06, 2025 at 02:24:08PM +0200, Jakub Jelinek wrote:
>>> 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.
>>> ...
>> 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.
> 
> Will fix, thanks!
> 
>>> ...
>>> +  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.
> 
> Noted. I agree that this change would be unnecessary for the issue that I
> am trying to solve.
> 
>>> ...
>>> +  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.
>> ...
> 
> Correct, thanks for pointing this out, I entirely missed this.
> 
>> ...
>> 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
> 
> This makes sense and works for SVE predicate vectors with one caveat...
> 
>> types and in that case figure out the right stride (1, 2, 4, 8, ...)
> 
> 
> would imply that TYPE_PRECISION (element_type) is always 1? In this case
> we can probably use this:
> 
> VECTOR_BOOLEAN_TYPE_P (type) && TYPE_PRECISION (element_type) == 1

IIRC this doesn’t work for SVE.

> and set DW_AT_bit_stride to 1?
> 
> The issue with GET_MODE_CLASS (TYPE_MODE (type)) is that TYPE_MODE (type)
> may return E_BLKmode because TYPE_MODE would adapt to the current ISA.
> In the case of SVE, one can use the svbool_t type with the -march=...+sve
> command line flag (in which case TYPE_MODE (type) would work), but it
> can also be used with the gnu::target attribute (in which case TYPE_MODE (type)
> would return E_BLKmode and the check for MODE_VECTOR_BOOL would fail).
> 
> I appreciate that this seems like a partial solution, but at least it is
> correct in a sense that all boolean vectors with element size 1 bit
> should have DW_AT_bit_stride = 1.
> 
> Thanks,
> Yury
>
  
Tamar Christina Oct. 7, 2025, 4:39 p.m. UTC | #6
> -----Original Message-----
> From: Richard Biener <rguenther@suse.de>
> Sent: 07 October 2025 17:01
> To: Yury Khrustalev <Yury.Khrustalev@arm.com>
> Cc: Jakub Jelinek <jakub@redhat.com>; Jason Merrill <jason@redhat.com>;
> Mark Wielaard <mark@klomp.org>; gcc-patches@gcc.gnu.org; Tamar
> Christina <Tamar.Christina@arm.com>; Srinath Parvathaneni
> <Srinath.Parvathaneni@arm.com>; Tejas Belagod <Tejas.Belagod@arm.com>
> Subject: Re: [PATCH] dwarf: Save bit stride information array type entry
> [PR121964]
> 
> 
> 
> > Am 07.10.2025 um 16:54 schrieb Yury Khrustalev
> <yury.khrustalev@arm.com>:
> >
> > Hi Jakub,
> >
> > Thanks for a very detailed response!
> >
> >> On Mon, Oct 06, 2025 at 02:24:08PM +0200, Jakub Jelinek wrote:
> >>> 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.
> >>> ...
> >> 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.
> >
> > Will fix, thanks!
> >
> >>> ...
> >>> +  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.
> >
> > Noted. I agree that this change would be unnecessary for the issue that I
> > am trying to solve.
> >
> >>> ...
> >>> +  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.
> >> ...
> >
> > Correct, thanks for pointing this out, I entirely missed this.
> >
> >> ...
> >> 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
> >
> > This makes sense and works for SVE predicate vectors with one caveat...
> >
> >> types and in that case figure out the right stride (1, 2, 4, 8, ...)
> >
> >
> > would imply that TYPE_PRECISION (element_type) is always 1? In this case
> > we can probably use this:
> >
> > VECTOR_BOOLEAN_TYPE_P (type) && TYPE_PRECISION (element_type) == 1
> 
> IIRC this doesn’t work for SVE.

For a type registered with SVE enabled I think it would work because the associated
mode is BImode then and the precision of BImode is always 1, so I'd expect
the precision of the type to be too.. but I don't know what happens in the case outline
above where SVE is not enabled at the time of DWARF output. e.g. you get BLKmode.

> 
> > and set DW_AT_bit_stride to 1?

I do wonder about this one as well. As Jakub mentioned above you have the partial SVE
modes and if

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

So bit_stride is meant for packed arrays, but the partial modes are unpacked.

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

Yeah, I think that's right looking at bit positions, so VNx8BI every bit controls 2 bytes
in the datavector, and the only relevant bit is every 2 strides.

So the representation is [0,x,1,x,2,x,3,x,4,...]

As such I think bitstride 1 is wrong and only applicable for fully packed vectors.

The difficulty from my understanding is due to mode switching in that unless SVE
was enabled globally, at the time we try to write out the DWARF information SVE
may have been disabled again.

The backend has a method for temporarily re-enabling a target ISA to manipulate
its modes.

Is it possible to call aarch64_target_switcher somehow before dumping the DWARF
output? If so I *think* this might solve the classification issue.

Did I miss anything @Kyrylo Tkachov?

Thanks,
Tamar

> >
> > The issue with GET_MODE_CLASS (TYPE_MODE (type)) is that TYPE_MODE
> (type)
> > may return E_BLKmode because TYPE_MODE would adapt to the current
> ISA.
> > In the case of SVE, one can use the svbool_t type with the -march=...+sve
> > command line flag (in which case TYPE_MODE (type) would work), but it
> > can also be used with the gnu::target attribute (in which case TYPE_MODE
> (type)
> > would return E_BLKmode and the check for MODE_VECTOR_BOOL would
> fail).
> >
> > I appreciate that this seems like a partial solution, but at least it is
> > correct in a sense that all boolean vectors with element size 1 bit
> > should have DW_AT_bit_stride = 1.
> >
> > Thanks,
> > Yury
> >
  
Richard Biener Oct. 7, 2025, 5:16 p.m. UTC | #7
> Am 07.10.2025 um 18:41 schrieb Tamar Christina <tamar.christina@arm.com>:
> 
> 
>> 
>> -----Original Message-----
>> From: Richard Biener <rguenther@suse.de>
>> Sent: 07 October 2025 17:01
>> To: Yury Khrustalev <Yury.Khrustalev@arm.com>
>> Cc: Jakub Jelinek <jakub@redhat.com>; Jason Merrill <jason@redhat.com>;
>> Mark Wielaard <mark@klomp.org>; gcc-patches@gcc.gnu.org; Tamar
>> Christina <Tamar.Christina@arm.com>; Srinath Parvathaneni
>> <Srinath.Parvathaneni@arm.com>; Tejas Belagod <Tejas.Belagod@arm.com>
>> Subject: Re: [PATCH] dwarf: Save bit stride information array type entry
>> [PR121964]
>> 
>> 
>> 
>>> Am 07.10.2025 um 16:54 schrieb Yury Khrustalev
>> <yury.khrustalev@arm.com>:
>>> 
>>> Hi Jakub,
>>> 
>>> Thanks for a very detailed response!
>>> 
>>>> On Mon, Oct 06, 2025 at 02:24:08PM +0200, Jakub Jelinek wrote:
>>>>> 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.
>>>>> ...
>>>> 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.
>>> 
>>> Will fix, thanks!
>>> 
>>>>> ...
>>>>> +  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.
>>> 
>>> Noted. I agree that this change would be unnecessary for the issue that I
>>> am trying to solve.
>>> 
>>>>> ...
>>>>> +  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.
>>>> ...
>>> 
>>> Correct, thanks for pointing this out, I entirely missed this.
>>> 
>>>> ...
>>>> 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
>>> 
>>> This makes sense and works for SVE predicate vectors with one caveat...
>>> 
>>>> types and in that case figure out the right stride (1, 2, 4, 8, ...)
>>> 
>>> 
>>> would imply that TYPE_PRECISION (element_type) is always 1? In this case
>>> we can probably use this:
>>> 
>>> VECTOR_BOOLEAN_TYPE_P (type) && TYPE_PRECISION (element_type) == 1
>> 
>> IIRC this doesn’t work for SVE.
> 
> For a type registered with SVE enabled I think it would work because the associated
> mode is BImode then and the precision of BImode is always 1, so I'd expect
> the precision of the type to be too.. but I don't know what happens in the case outline
> above where SVE is not enabled at the time of DWARF output. e.g. you get BLKmode.
> 
>> 
>>> and set DW_AT_bit_stride to 1?
> 
> I do wonder about this one as well. As Jakub mentioned above you have the partial SVE
> modes and if
> 
>> 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.
> 
> So bit_stride is meant for packed arrays, but the partial modes are unpacked.
> 
>> 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?  
> 
> Yeah, I think that's right looking at bit positions, so VNx8BI every bit controls 2 bytes
> in the datavector, and the only relevant bit is every 2 strides.
> 
> So the representation is [0,x,1,x,2,x,3,x,4,...]
> 
> As such I think bitstride 1 is wrong and only applicable for fully packed vectors.
> 
> The difficulty from my understanding is due to mode switching in that unless SVE
> was enabled globally, at the time we try to write out the DWARF information SVE
> may have been disabled again.
> 
> The backend has a method for temporarily re-enabling a target ISA to manipulate
> its modes.
> 
> Is it possible to call aarch64_target_switcher somehow before dumping the DWARF
> output? If so I *think* this might solve the classification issue.
> 
> Did I miss anything @Kyrylo Tkachov?

In general we should produce DWARF based on the type, not the mode.  It’s supposed to map to the source, not the target.  The layout of a svebool is the same with or without SVE enabled, no?

> 
> Thanks,
> Tamar
> 
>>> 
>>> The issue with GET_MODE_CLASS (TYPE_MODE (type)) is that TYPE_MODE
>> (type)
>>> may return E_BLKmode because TYPE_MODE would adapt to the current
>> ISA.
>>> In the case of SVE, one can use the svbool_t type with the -march=...+sve
>>> command line flag (in which case TYPE_MODE (type) would work), but it
>>> can also be used with the gnu::target attribute (in which case TYPE_MODE
>> (type)
>>> would return E_BLKmode and the check for MODE_VECTOR_BOOL would
>> fail).
>>> 
>>> I appreciate that this seems like a partial solution, but at least it is
>>> correct in a sense that all boolean vectors with element size 1 bit
>>> should have DW_AT_bit_stride = 1.
>>> 
>>> Thanks,
>>> Yury
>>>
  
Tamar Christina Oct. 7, 2025, 6:55 p.m. UTC | #8
> -----Original Message-----
> From: Richard Biener <rguenther@suse.de>
> Sent: 07 October 2025 18:16
> To: Tamar Christina <Tamar.Christina@arm.com>
> Cc: Yury Khrustalev <Yury.Khrustalev@arm.com>; Kyrylo Tkachov
> <ktkachov@nvidia.com>; Jakub Jelinek <jakub@redhat.com>; Jason Merrill
> <jason@redhat.com>; Mark Wielaard <mark@klomp.org>; gcc-
> patches@gcc.gnu.org; Srinath Parvathaneni
> <Srinath.Parvathaneni@arm.com>; Tejas Belagod <Tejas.Belagod@arm.com>
> Subject: Re: [PATCH] dwarf: Save bit stride information array type entry
> [PR121964]
> 
> 
> 
> > Am 07.10.2025 um 18:41 schrieb Tamar Christina
> <tamar.christina@arm.com>:
> >
> > 
> >>
> >> -----Original Message-----
> >> From: Richard Biener <rguenther@suse.de>
> >> Sent: 07 October 2025 17:01
> >> To: Yury Khrustalev <Yury.Khrustalev@arm.com>
> >> Cc: Jakub Jelinek <jakub@redhat.com>; Jason Merrill <jason@redhat.com>;
> >> Mark Wielaard <mark@klomp.org>; gcc-patches@gcc.gnu.org; Tamar
> >> Christina <Tamar.Christina@arm.com>; Srinath Parvathaneni
> >> <Srinath.Parvathaneni@arm.com>; Tejas Belagod
> <Tejas.Belagod@arm.com>
> >> Subject: Re: [PATCH] dwarf: Save bit stride information array type entry
> >> [PR121964]
> >>
> >>
> >>
> >>> Am 07.10.2025 um 16:54 schrieb Yury Khrustalev
> >> <yury.khrustalev@arm.com>:
> >>>
> >>> Hi Jakub,
> >>>
> >>> Thanks for a very detailed response!
> >>>
> >>>> On Mon, Oct 06, 2025 at 02:24:08PM +0200, Jakub Jelinek wrote:
> >>>>> 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.
> >>>>> ...
> >>>> 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.
> >>>
> >>> Will fix, thanks!
> >>>
> >>>>> ...
> >>>>> +  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.
> >>>
> >>> Noted. I agree that this change would be unnecessary for the issue that I
> >>> am trying to solve.
> >>>
> >>>>> ...
> >>>>> +  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.
> >>>> ...
> >>>
> >>> Correct, thanks for pointing this out, I entirely missed this.
> >>>
> >>>> ...
> >>>> 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
> >>>
> >>> This makes sense and works for SVE predicate vectors with one caveat...
> >>>
> >>>> types and in that case figure out the right stride (1, 2, 4, 8, ...)
> >>>
> >>>
> >>> would imply that TYPE_PRECISION (element_type) is always 1? In this case
> >>> we can probably use this:
> >>>
> >>> VECTOR_BOOLEAN_TYPE_P (type) && TYPE_PRECISION (element_type)
> == 1
> >>
> >> IIRC this doesn’t work for SVE.
> >
> > For a type registered with SVE enabled I think it would work because the
> associated
> > mode is BImode then and the precision of BImode is always 1, so I'd expect
> > the precision of the type to be too.. but I don't know what happens in the
> case outline
> > above where SVE is not enabled at the time of DWARF output. e.g. you get
> BLKmode.
> >
> >>
> >>> and set DW_AT_bit_stride to 1?
> >
> > I do wonder about this one as well. As Jakub mentioned above you have the
> partial SVE
> > modes and if
> >
> >> 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.
> >
> > So bit_stride is meant for packed arrays, but the partial modes are unpacked.
> >
> >> 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?
> >
> > Yeah, I think that's right looking at bit positions, so VNx8BI every bit controls
> 2 bytes
> > in the datavector, and the only relevant bit is every 2 strides.
> >
> > So the representation is [0,x,1,x,2,x,3,x,4,...]
> >
> > As such I think bitstride 1 is wrong and only applicable for fully packed
> vectors.
> >
> > The difficulty from my understanding is due to mode switching in that unless
> SVE
> > was enabled globally, at the time we try to write out the DWARF information
> SVE
> > may have been disabled again.
> >
> > The backend has a method for temporarily re-enabling a target ISA to
> manipulate
> > its modes.
> >
> > Is it possible to call aarch64_target_switcher somehow before dumping the
> DWARF
> > output? If so I *think* this might solve the classification issue.
> >
> > Did I miss anything @Kyrylo Tkachov?
> 
> In general we should produce DWARF based on the type, not the mode.  It’s
> supposed to map to the source, not the target.  The layout of a svebool is the
> same with or without SVE enabled, no?

You're right, the svbool_t specifically is always registered with VNx16BI, so
It'll always be single bit precision.  So in that regard Yury's patch is correct if we
only ever put out DWARF for svbool_t.

I however don't know what the expected experience here is.

Consider:

#include <arm_sve.h>

svbool_t f8 ()
{
  return svptrue_b8 ();
}

svbool_t f16 ()
{
  return svptrue_b16 ();
}

The first one has every bit significant, and the second one it's every 2nd bit.
But with DW_AT_bit_stride = 1, I'm not sure how a user in GDB is able to tell
If the register values belong to a predicate where every other lane is inactive
or one where every entry is active.

But as Yury mentioned at the very least DW_AT_bit_stride = 1 would fix the
output corruption in gdb.

Thanks,
Tamar

> 
> >
> > Thanks,
> > Tamar
> >
> >>>
> >>> The issue with GET_MODE_CLASS (TYPE_MODE (type)) is that
> TYPE_MODE
> >> (type)
> >>> may return E_BLKmode because TYPE_MODE would adapt to the current
> >> ISA.
> >>> In the case of SVE, one can use the svbool_t type with the -march=...+sve
> >>> command line flag (in which case TYPE_MODE (type) would work), but it
> >>> can also be used with the gnu::target attribute (in which case TYPE_MODE
> >> (type)
> >>> would return E_BLKmode and the check for MODE_VECTOR_BOOL would
> >> fail).
> >>>
> >>> I appreciate that this seems like a partial solution, but at least it is
> >>> correct in a sense that all boolean vectors with element size 1 bit
> >>> should have DW_AT_bit_stride = 1.
> >>>
> >>> Thanks,
> >>> Yury
> >>>
  
Jakub Jelinek Oct. 7, 2025, 7:32 p.m. UTC | #9
On Tue, Oct 07, 2025 at 06:55:25PM +0000, Tamar Christina wrote:
> Consider:
> 
> #include <arm_sve.h>
> 
> svbool_t f8 ()
> {
>   return svptrue_b8 ();
> }
> 
> svbool_t f16 ()
> {
>   return svptrue_b16 ();
> }
> 
> The first one has every bit significant, and the second one it's every 2nd bit.
> But with DW_AT_bit_stride = 1, I'm not sure how a user in GDB is able to tell
> If the register values belong to a predicate where every other lane is inactive
> or one where every entry is active.

DWARF should describe user types, so if svbool_t is always 1-bit size 1-bit
stride, I think you want for that instead of the current
vec: DW_TAG_array_type
	DW_AT_name	"__SVBool_t"
	DW_AT_GNU_vector
	DW_AT_type inner
	DW_AT_sibling inner
DW_TAG_subrange_type
	DW_AT_upper_bound DW_OP_bregx 0x2e 0 DW_OP_lit8 DW_OP_mul DW_OP_lit1 DW_OP_minus
inner: DW_TAG_base_type
	DW_AT_byte_size 1
	DW_AT_encoding 2
	DW_AT_name "__unknown__"
add DW_AT_bit_stride to DW_TAG_array_type and replace DW_AT_byte_size 1 with
DW_AT_bit_size 1 in DW_TAG_base_type.

But I'll stress out this should be done solely for the targets which have
such kind of VECTOR_BOOLEAN_TYPE_Ps, not all because many have other
implementation.  And even if aarch64 doesn't have 2/4/8-bit strided bool
vectors (really don't know), it is quite likely RISC-V has those.

	Jakub
  
Yury Khrustalev Oct. 8, 2025, 8:24 a.m. UTC | #10
On Tue, Oct 07, 2025 at 06:01:01PM +0200, Richard Biener wrote:
> > ...
> > This makes sense and works for SVE predicate vectors with one caveat...
> > 
> >> types and in that case figure out the right stride (1, 2, 4, 8, ...)
> > 
> > 
> > would imply that TYPE_PRECISION (element_type) is always 1? In this case
> > we can probably use this:
> > 
> > VECTOR_BOOLEAN_TYPE_P (type) && TYPE_PRECISION (element_type) == 1
> 
> IIRC this doesn’t work for SVE.

I've tested that this works well with both SVE enabled globally via command-line
flag and locally for a function.

Yury
  
Yury Khrustalev Oct. 8, 2025, 8:30 a.m. UTC | #11
On Tue, Oct 07, 2025 at 06:55:25PM +0000, Tamar Christina wrote:
> > ...
> >
> > In general we should produce DWARF based on the type, not the mode.  It’s
> > supposed to map to the source, not the target.  The layout of a svebool is the
> > same with or without SVE enabled, no?
> 
> You're right, the svbool_t specifically is always registered with VNx16BI, so
> It'll always be single bit precision.  So in that regard Yury's patch is correct if we
> only ever put out DWARF for svbool_t.
> 
> I however don't know what the expected experience here is.
> 
> Consider:
> 
> #include <arm_sve.h>
> 
> svbool_t f8 ()
> {
>   return svptrue_b8 ();
> }
> 
> svbool_t f16 ()
> {
>   return svptrue_b16 ();
> }
> 
> The first one has every bit significant, and the second one it's every 2nd bit.
> But with DW_AT_bit_stride = 1, I'm not sure how a user in GDB is able to tell
> If the register values belong to a predicate where every other lane is inactive
> or one where every entry is active.

The way I understand it is that DWARF would have information about svbool_t type
only. A variable of this type (i.e. a predicate) would have different meaning
depending on what type it is applied to. A pattern like

1 0 0 0 1 0 0 0 .. 0

might mean

{ true, true, false, ... }

for svuint32_t, but it would mean

{ true, false, true, false, true, false ... }

for svuint16_t. So, as far as the *type* is concerned, using stride of 1 bit
makes sense to me.

Thanks,
Yury
  
Yury Khrustalev Oct. 8, 2025, 8:35 a.m. UTC | #12
On Tue, Oct 07, 2025 at 09:32:03PM +0200, Jakub Jelinek wrote:
> > ...
> > The first one has every bit significant, and the second one it's every 2nd bit.
> > But with DW_AT_bit_stride = 1, I'm not sure how a user in GDB is able to tell
> > If the register values belong to a predicate where every other lane is inactive
> > or one where every entry is active.
> 
> DWARF should describe user types, so if svbool_t is always 1-bit size 1-bit
> stride, I think you want for that instead of the current
> vec: DW_TAG_array_type
> 	DW_AT_name	"__SVBool_t"
> 	DW_AT_GNU_vector
> 	DW_AT_type inner
> 	DW_AT_sibling inner
> DW_TAG_subrange_type
> 	DW_AT_upper_bound DW_OP_bregx 0x2e 0 DW_OP_lit8 DW_OP_mul DW_OP_lit1 DW_OP_minus
> inner: DW_TAG_base_type
> 	DW_AT_byte_size 1
> 	DW_AT_encoding 2
> 	DW_AT_name "__unknown__"
> add DW_AT_bit_stride to DW_TAG_array_type and replace DW_AT_byte_size 1 with
> DW_AT_bit_size 1 in DW_TAG_base_type.

I think we have 2 things here:

1. Detect situation when we work with something like svbool_t
2. Decide what to do in this case (i.e. what attributes to add to
whatever DIEs).

I agree on the latter that we should have DW_AT_bit_stride in the array
type but I think DW_AT_bit_size 1 in the base type (element type) would
not solve the issue with GDB reading 1 byte for each vector element
because it really looks at the type description at this point.

> But I'll stress out this should be done solely for the targets which have
> such kind of VECTOR_BOOLEAN_TYPE_Ps, not all because many have other
> implementation.  And even if aarch64 doesn't have 2/4/8-bit strided bool
> vectors (really don't know), it is quite likely RISC-V has those.

Could you point me in the direction of implementing target dependent
code for generating DWARF information?

Yury
  
Jakub Jelinek Oct. 8, 2025, 8:49 a.m. UTC | #13
On Wed, Oct 08, 2025 at 09:35:06AM +0100, Yury Khrustalev wrote:
> I think we have 2 things here:
> 
> 1. Detect situation when we work with something like svbool_t
> 2. Decide what to do in this case (i.e. what attributes to add to
> whatever DIEs).
> 
> I agree on the latter that we should have DW_AT_bit_stride in the array
> type but I think DW_AT_bit_size 1 in the base type (element type) would
> not solve the issue with GDB reading 1 byte for each vector element
> because it really looks at the type description at this point.

I think both are desirable from the DWARF POV.  What exactly GDB does with
it is a question on GDB.

> > But I'll stress out this should be done solely for the targets which have
> > such kind of VECTOR_BOOLEAN_TYPE_Ps, not all because many have other
> > implementation.  And even if aarch64 doesn't have 2/4/8-bit strided bool
> > vectors (really don't know), it is quite likely RISC-V has those.
> 
> Could you point me in the direction of implementing target dependent
> code for generating DWARF information?

First of all, it should use the VECTOR_BOOLEAN_TYPE_P macro to decide, and
then either it can derive stuff from TYPE_MODE, or if that doesn't work
it can use a target hook.
There are various dwarf related target hooks and language hooks.
Just grep for targetm or lang_hooks in dwarf2out.cc.
So, perhaps have a target hook that given a VECTOR_BOOLEAN_TYPE_P
returns you the bit stride, with 0 meaning handle it as now.

	Jakub
  
Yury Khrustalev Oct. 8, 2025, 9:13 a.m. UTC | #14
On Wed, Oct 08, 2025 at 10:49:21AM +0200, Jakub Jelinek wrote:
> On Wed, Oct 08, 2025 at 09:35:06AM +0100, Yury Khrustalev wrote:
> > I think we have 2 things here:
> > 
> > 1. Detect situation when we work with something like svbool_t
> > 2. Decide what to do in this case (i.e. what attributes to add to
> > whatever DIEs).
> > 
> > I agree on the latter that we should have DW_AT_bit_stride in the array
> > type but I think DW_AT_bit_size 1 in the base type (element type) would
> > not solve the issue with GDB reading 1 byte for each vector element
> > because it really looks at the type description at this point.
> 
> I think both are desirable from the DWARF POV.  What exactly GDB does with
> it is a question on GDB.

Just to confirm, you don't want to add DW_AT_bit_stride to DW_TAG_array_type
entry and *instead* add DW_AT_bit_size 1 in the base type? And if GDB
still doesn't work, then fix it on the GDB side?

If having DW_AT_bit_stride is still OK, I'd rather do that (along with
other things), just to allow current versions of GDB show something
sensible.

> > > But I'll stress out this should be done solely for the targets which have
> > > such kind of VECTOR_BOOLEAN_TYPE_Ps, not all because many have other
> > > implementation.  And even if aarch64 doesn't have 2/4/8-bit strided bool
> > > vectors (really don't know), it is quite likely RISC-V has those.
> > 
> > Could you point me in the direction of implementing target dependent
> > code for generating DWARF information?
> 
> First of all, it should use the VECTOR_BOOLEAN_TYPE_P macro to decide, and
> then either it can derive stuff from TYPE_MODE, or if that doesn't work
> it can use a target hook.
> There are various dwarf related target hooks and language hooks.
> Just grep for targetm or lang_hooks in dwarf2out.cc.
> So, perhaps have a target hook that given a VECTOR_BOOLEAN_TYPE_P
> returns you the bit stride, with 0 meaning handle it as now.

Thanks!

Yury
  
Jakub Jelinek Oct. 8, 2025, 9:25 a.m. UTC | #15
On Wed, Oct 08, 2025 at 10:13:42AM +0100, Yury Khrustalev wrote:
> On Wed, Oct 08, 2025 at 10:49:21AM +0200, Jakub Jelinek wrote:
> > On Wed, Oct 08, 2025 at 09:35:06AM +0100, Yury Khrustalev wrote:
> > > I think we have 2 things here:
> > > 
> > > 1. Detect situation when we work with something like svbool_t
> > > 2. Decide what to do in this case (i.e. what attributes to add to
> > > whatever DIEs).
> > > 
> > > I agree on the latter that we should have DW_AT_bit_stride in the array
> > > type but I think DW_AT_bit_size 1 in the base type (element type) would
> > > not solve the issue with GDB reading 1 byte for each vector element
> > > because it really looks at the type description at this point.
> > 
> > I think both are desirable from the DWARF POV.  What exactly GDB does with
> > it is a question on GDB.
> 
> Just to confirm, you don't want to add DW_AT_bit_stride to DW_TAG_array_type
> entry and *instead* add DW_AT_bit_size 1 in the base type? And if GDB
> still doesn't work, then fix it on the GDB side?

I want both, DW_AT_bit_size 1 on the DW_AT_type referenced DIE (made up
anyway, it isn't reusing the normal bool DW_TAG_base_type) and
DW_AT_bit_stride 1 on the DW_TAG_array_type with DW_AT_GNU_vector flag.
And only if the vector type is the packed boolean vector, not for other
cases.

	Jakub
  
Yury Khrustalev Oct. 10, 2025, 2:47 p.m. UTC | #16
On Wed, Oct 08, 2025 at 11:25:28AM +0200, Jakub Jelinek wrote:
> > ...
> > Just to confirm, you don't want to add DW_AT_bit_stride to DW_TAG_array_type
> > entry and *instead* add DW_AT_bit_size 1 in the base type? And if GDB
> > still doesn't work, then fix it on the GDB side?
> 
> I want both, DW_AT_bit_size 1 on the DW_AT_type referenced DIE (made up
> anyway, it isn't reusing the normal bool DW_TAG_base_type) and
> DW_AT_bit_stride 1 on the DW_TAG_array_type with DW_AT_GNU_vector flag.
> And only if the vector type is the packed boolean vector, not for other
> cases.
> 
> 	Jakub
> 

Question about best way to locate the referenced DIE: I could perhaps
use modified_type_die() with element_type, but it would be call again
shortly after when a reference is added to the DW_TAG_array_type DIE
(from within add_type_attribute()).

Would it be OK to change add_type_attribute() to return type_die that
if finds? I could then use the returned value to add DW_AT_bit_size 1
when I process svbool_t type.

Thanks,
Yury
  
Jakub Jelinek Oct. 10, 2025, 2:53 p.m. UTC | #17
On Fri, Oct 10, 2025 at 03:47:23PM +0100, Yury Khrustalev wrote:
> On Wed, Oct 08, 2025 at 11:25:28AM +0200, Jakub Jelinek wrote:
> > > ...
> > > Just to confirm, you don't want to add DW_AT_bit_stride to DW_TAG_array_type
> > > entry and *instead* add DW_AT_bit_size 1 in the base type? And if GDB
> > > still doesn't work, then fix it on the GDB side?
> > 
> > I want both, DW_AT_bit_size 1 on the DW_AT_type referenced DIE (made up
> > anyway, it isn't reusing the normal bool DW_TAG_base_type) and
> > DW_AT_bit_stride 1 on the DW_TAG_array_type with DW_AT_GNU_vector flag.
> > And only if the vector type is the packed boolean vector, not for other
> > cases.
> > 
> > 	Jakub
> > 
> 
> Question about best way to locate the referenced DIE: I could perhaps
> use modified_type_die() with element_type, but it would be call again
> shortly after when a reference is added to the DW_TAG_array_type DIE
> (from within add_type_attribute()).

Why?  Doesn't get_AT_ref (die, DW_AT_type) work?

	Jakub
  
Yury Khrustalev Oct. 10, 2025, 3:11 p.m. UTC | #18
On Fri, Oct 10, 2025 at 04:53:46PM +0200, Jakub Jelinek wrote:
> > ...
> > Question about best way to locate the referenced DIE: I could perhaps
> > use modified_type_die() with element_type, but it would be call again
> > shortly after when a reference is added to the DW_TAG_array_type DIE
> > (from within add_type_attribute()).
> 
> Why?  Doesn't get_AT_ref (die, DW_AT_type) work?

Yes, it works, thanks!

Yury
  

Patch

diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc
index 0bd8474bc37..aaaa578ce56 100644
--- 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));
 
   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));
+
   if (collapse_nested_arrays)
     while (TREE_CODE (element_type) == ARRAY_TYPE)
       {
diff --git a/gcc/testsuite/g++.target/aarch64/sve/dwarf-bit-stride.C b/gcc/testsuite/g++.target/aarch64/sve/dwarf-bit-stride.C
new file mode 100644
index 00000000000..bbc967c7ffd
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/sve/dwarf-bit-stride.C
@@ -0,0 +1,15 @@ 
+/* { dg-do compile { target aarch64_asm_sve_ok } } */
+// { dg-options "-g -dA" }
+// { dg-final { scan-assembler-times "DW_AT_bit_stride" 2 } }
+// { dg-final { scan-assembler-times "DW_AT_GNU_vector" 2 } }
+// { dg-final { scan-assembler-times "DW_TAG_array_type" 2 } }
+
+#include <arm_sve.h>
+
+void fun ()
+{
+  volatile svbool_t pred8 = svwhilelt_b8_u32 (0u, 1u);
+  volatile svbool_t pred16 = svwhilelt_b16_u32 (0u, 3u);
+  volatile svbool_t pred32 = svwhilelt_b32_u32 (0u, 7u);
+  volatile svbool_t pred64 = svwhilelt_b64_u32 (0u, 11u);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/dwarf-bit-stride.c b/gcc/testsuite/gcc.target/aarch64/sve/dwarf-bit-stride.c
new file mode 100644
index 00000000000..bbc967c7ffd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/dwarf-bit-stride.c
@@ -0,0 +1,15 @@ 
+/* { dg-do compile { target aarch64_asm_sve_ok } } */
+// { dg-options "-g -dA" }
+// { dg-final { scan-assembler-times "DW_AT_bit_stride" 2 } }
+// { dg-final { scan-assembler-times "DW_AT_GNU_vector" 2 } }
+// { dg-final { scan-assembler-times "DW_TAG_array_type" 2 } }
+
+#include <arm_sve.h>
+
+void fun ()
+{
+  volatile svbool_t pred8 = svwhilelt_b8_u32 (0u, 1u);
+  volatile svbool_t pred16 = svwhilelt_b16_u32 (0u, 3u);
+  volatile svbool_t pred32 = svwhilelt_b32_u32 (0u, 7u);
+  volatile svbool_t pred64 = svwhilelt_b64_u32 (0u, 11u);
+}