On Wed, 15 Oct 2025, 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.
>
> We also locate DIE referenced by DW_AT_type and set DW_AT_bit_size 1 in it.
>
> PR debug/121964
>
> gcc/
> * dwarf2out.cc (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/dwarf-bit-stride-func.C: New test.
> * g++.target/aarch64/dwarf-bit-stride-pragma.C: New test.
> * g++.target/aarch64/dwarf-bit-stride-pragma-sme.C: New test.
> * g++.target/aarch64/sve/dwarf-bit-stride.C: New test.
> * gcc.target/aarch64/dwarf-bit-stride-func.c: New test.
> * gcc.target/aarch64/dwarf-bit-stride-pragma.c: New test.
> * gcc.target/aarch64/dwarf-bit-stride-pragma-sme.c: New test.
> * gcc.target/aarch64/sve/dwarf-bit-stride.c: New test.
> ---
> Passes regression on aarch64. OK for trunk?
>
> Base-commit: 599d2902b0a
>
> Changes in v2:
> - Fixed patch based on feedback for v1.
> - Detect if we work with a packed boolean vector using a combination
> of VECTOR_BOOLEAN_TYPE_P and GET_MODE_CLASS (TYPE_MODE_RAW (type)).
> - Set DW_AT_bit_size to 1 in the referenced DIE.
> - Added more tests.
> - v1: https://patchwork.sourceware.org/project/gcc/list/?series=52149
>
> ---
> gcc/dwarf2out.cc | 16 ++++++++++++++++
> .../g++.target/aarch64/dwarf-bit-stride-func.C | 16 ++++++++++++++++
> .../aarch64/dwarf-bit-stride-pragma-sme.C | 16 ++++++++++++++++
> .../aarch64/dwarf-bit-stride-pragma.C | 17 +++++++++++++++++
> .../g++.target/aarch64/sve/dwarf-bit-stride.C | 15 +++++++++++++++
> .../gcc.target/aarch64/dwarf-bit-stride-func.c | 16 ++++++++++++++++
> .../aarch64/dwarf-bit-stride-pragma-sme.c | 14 ++++++++++++++
> .../aarch64/dwarf-bit-stride-pragma.c | 17 +++++++++++++++++
> .../gcc.target/aarch64/sve/dwarf-bit-stride.c | 15 +++++++++++++++
> 9 files changed, 142 insertions(+)
> create mode 100644 gcc/testsuite/g++.target/aarch64/dwarf-bit-stride-func.C
> create mode 100644
> gcc/testsuite/g++.target/aarch64/dwarf-bit-stride-pragma-sme.C
> create mode 100644 gcc/testsuite/g++.target/aarch64/dwarf-bit-stride-pragma.C
> create mode 100644 gcc/testsuite/g++.target/aarch64/sve/dwarf-bit-stride.C
> create mode 100644 gcc/testsuite/gcc.target/aarch64/dwarf-bit-stride-func.c
> create mode 100644
> gcc/testsuite/gcc.target/aarch64/dwarf-bit-stride-pragma-sme.c
> create mode 100644 gcc/testsuite/gcc.target/aarch64/dwarf-bit-stride-pragma.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 a817c69c95a..5e531277804 100644
> --- a/gcc/dwarf2out.cc
> +++ b/gcc/dwarf2out.cc
> @@ -23034,6 +23034,22 @@ gen_array_type_die (tree type, dw_die_ref
> context_die)
> && TYPE_REVERSE_STORAGE_ORDER (type),
> context_die);
>
> + /* Add bit stride information to boolean vectors of single bits so that
> + elements can be correctly read and displayed by a debugger. */
> + if (VECTOR_BOOLEAN_TYPE_P (type)
> + && GET_MODE_CLASS (TYPE_MODE_RAW (type)) == MODE_VECTOR_BOOL)
> + {
> + /* MODE_VECTOR_BOOL implies that bit stride and bit size
> + for element type must be 1. */
Is that so? I thought it wasn't.
I also think you don't want to look at modes, instead why don't
you check known_eq (TYPE_PRECISION (TREE_TYPE (type)), 1)?
> + add_AT_unsigned (array_die, DW_AT_bit_stride, 1);
> + /* Find DIE corresponding to the element type so that we could
> + add DW_AT_bit_size to it. */
> + dw_die_ref elem_die = get_AT_ref (array_die, DW_AT_type);
> + /* Avoid adding DW_AT_bit_size twice. */
> + if (get_AT (elem_die, DW_AT_bit_size) == NULL)
> + add_AT_unsigned (elem_die, DW_AT_bit_size, 1);
> + }
> +
> add_gnat_descriptive_type_attribute (array_die, type, context_die);
> if (TYPE_ARTIFICIAL (type))
> add_AT_flag (array_die, DW_AT_artificial, 1);
> diff --git a/gcc/testsuite/g++.target/aarch64/dwarf-bit-stride-func.C
> b/gcc/testsuite/g++.target/aarch64/dwarf-bit-stride-func.C
> new file mode 100644
> index 00000000000..1917d9116b0
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/aarch64/dwarf-bit-stride-func.C
> @@ -0,0 +1,16 @@
> +/* { dg-do compile } */
> +// { dg-options "-g -dA" }
> +// { dg-final { scan-assembler-times "DW_AT_name: \"svbool_t\"" 1 } }
> +// { dg-final { scan-assembler-times ".byte 0x1 // DW_AT_bit_stride" 1
> } }
> +// { dg-final { scan-assembler-times ".byte 0x1 // DW_AT_bit_size" 1 } }
> +
> +#include <arm_sve.h>
> +
> +[[gnu::target ("arch=armv9-a+sve")]]
> +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/g++.target/aarch64/dwarf-bit-stride-pragma-sme.C
> b/gcc/testsuite/g++.target/aarch64/dwarf-bit-stride-pragma-sme.C
> new file mode 100644
> index 00000000000..4b73cbc55ff
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/aarch64/dwarf-bit-stride-pragma-sme.C
> @@ -0,0 +1,16 @@
> +/* { dg-do compile } */
> +// { dg-options "-g -dA" }
> +// { dg-final { scan-assembler-times "DW_AT_name: \"svbool_t\"" 1 } }
> +// { dg-final { scan-assembler-times "DW_AT_name: \"svcount_t\"" 1 } }
> +// { dg-final { scan-assembler-times ".byte 0x1 // DW_AT_bit_stride" 1
> } }
> +// { dg-final { scan-assembler-times ".byte 0x1 // DW_AT_bit_size" 1 } }
> +
> +#include <arm_sme.h>
> +
> +#pragma GCC target "+sve2p1+sme2"
> +
> +void fun ()
> +{
> + volatile svbool_t pred;
> + volatile svcount_t count;
> +}
> diff --git a/gcc/testsuite/g++.target/aarch64/dwarf-bit-stride-pragma.C
> b/gcc/testsuite/g++.target/aarch64/dwarf-bit-stride-pragma.C
> new file mode 100644
> index 00000000000..64b02cc8927
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/aarch64/dwarf-bit-stride-pragma.C
> @@ -0,0 +1,17 @@
> +/* { dg-do compile } */
> +// { dg-options "-g -dA" }
> +// { dg-final { scan-assembler-times "DW_AT_name: \"svbool_t\"" 1 } }
> +// { dg-final { scan-assembler-times ".byte 0x1 // DW_AT_bit_stride" 1
> } }
> +// { dg-final { scan-assembler-times ".byte 0x1 // DW_AT_bit_size" 1 } }
> +
> +#include <arm_sve.h>
> +
> +#pragma GCC target "+sve"
> +
> +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/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..80224d45f78
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/aarch64/sve/dwarf-bit-stride.C
> @@ -0,0 +1,15 @@
> +/* { dg-do compile } */
> +// { dg-options "-g -dA" }
> +// { dg-final { scan-assembler-times "DW_AT_name: \"svbool_t\"" 1 } }
> +// { dg-final { scan-assembler-times ".byte 0x1 // DW_AT_bit_stride" 1
> } }
> +// { dg-final { scan-assembler-times ".byte 0x1 // DW_AT_bit_size" 1 } }
> +
> +#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/dwarf-bit-stride-func.c
> b/gcc/testsuite/gcc.target/aarch64/dwarf-bit-stride-func.c
> new file mode 100644
> index 00000000000..654bae54e5f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/dwarf-bit-stride-func.c
> @@ -0,0 +1,16 @@
> +/* { dg-do compile } */
> +// { dg-options "-g -dA" }
> +// { dg-final { scan-assembler-times "DW_AT_name: \"__SVBool_t\"" 1 } }
> +// { dg-final { scan-assembler-times ".byte 0x1 // DW_AT_bit_stride" 1
> } }
> +// { dg-final { scan-assembler-times ".byte 0x1 // DW_AT_bit_size" 1 } }
> +
> +#include <arm_sve.h>
> +
> +__attribute__((target("arch=armv9-a+sve")))
> +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/dwarf-bit-stride-pragma-sme.c
> b/gcc/testsuite/gcc.target/aarch64/dwarf-bit-stride-pragma-sme.c
> new file mode 100644
> index 00000000000..4bd0da5a8a5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/dwarf-bit-stride-pragma-sme.c
> @@ -0,0 +1,14 @@
> +/* { dg-do compile } */
> +// { dg-options "-g -dA" }
> +// { dg-final { scan-assembler-times "DW_AT_name: \"__SVBool_t\"" 2 } }
> +// { dg-final { scan-assembler-times "DW_AT_name: \"__SVCount_t\"" 1 } }
> +// { dg-final { scan-assembler-times ".byte 0x1 // DW_AT_bit_stride" 2
> } }
> +// { dg-final { scan-assembler-times ".byte 0x1 // DW_AT_bit_size" 1 } }
> +
> +#pragma GCC target "+sve2p1+sme2"
> +
> +void fun ()
> +{
> + volatile __SVBool_t pred;
> + volatile __SVCount_t count;
> +}
> diff --git a/gcc/testsuite/gcc.target/aarch64/dwarf-bit-stride-pragma.c
> b/gcc/testsuite/gcc.target/aarch64/dwarf-bit-stride-pragma.c
> new file mode 100644
> index 00000000000..77a0d801876
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/dwarf-bit-stride-pragma.c
> @@ -0,0 +1,17 @@
> +/* { dg-do compile } */
> +// { dg-options "-g -dA" }
> +// { dg-final { scan-assembler-times "DW_AT_name: \"__SVBool_t\"" 1 } }
> +// { dg-final { scan-assembler-times ".byte 0x1 // DW_AT_bit_stride" 1
> } }
> +// { dg-final { scan-assembler-times ".byte 0x1 // DW_AT_bit_size" 1 } }
> +
> +#include <arm_sve.h>
> +
> +#pragma GCC target "+sve"
> +
> +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..3f34348ff91
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sve/dwarf-bit-stride.c
> @@ -0,0 +1,15 @@
> +/* { dg-do compile } */
> +// { dg-options "-g -dA" }
> +// { dg-final { scan-assembler-times "DW_AT_name: \"__SVBool_t\"" 1 } }
> +// { dg-final { scan-assembler-times ".byte 0x1 // DW_AT_bit_stride" 1
> } }
> +// { dg-final { scan-assembler-times ".byte 0x1 // DW_AT_bit_size" 1 } }
> +
> +#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);
> +}
>
--
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)