| Message ID | 20250917153912.3187098-1-yury.khrustalev@arm.com |
|---|---|
| State | Superseded |
| Headers |
Return-Path: <gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org> X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id B28C2385801B for <patchwork@sourceware.org>; Wed, 17 Sep 2025 15:43:14 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B28C2385801B X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by sourceware.org (Postfix) with ESMTP id 12E64385743A for <gcc-patches@gcc.gnu.org>; Wed, 17 Sep 2025 15:39:20 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 12E64385743A Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=arm.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 12E64385743A Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1758123560; cv=none; b=W2UjgNjiS3133k6toE3q8sc6KU9p7giEwdpWcDHvbUi+e/1vOduFQWhtrOdhC0nV+4Hc8tBVAw/wsU27KP764p9INW9q2awys8U+QIGO1NND3MZQ6KiFPtFl30U69iMGJspVdDSQtOqsjDDlldM6ALOEiu0Ps2DVBrmU9i+3A8M= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1758123560; c=relaxed/simple; bh=gpuIjREzyqI7o4pbOEuGVGj1OlJleE7CWRtMUmHAVpU=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=r/lR9HMhcmzSYuTkKus19vyGjd1/5au0w0zu3Ny+Wji1OkWCQGrfYyQcUDUK/XpFqZO5GXHtv9y8+i3RVtOnnQrXtgCH7nvN9zzuKNx2CY1bLbVt3ZIZ6IKxbbyhEznweO8bhx4YRXeRgiXcsews2SrKN2N16kEpGORb2qvJrAI= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 12E64385743A Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 3B02A267F; Wed, 17 Sep 2025 08:39:11 -0700 (PDT) Received: from fdebian.localdomain (unknown [10.1.36.163]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 920CC3F694; Wed, 17 Sep 2025 08:39:18 -0700 (PDT) From: Yury Khrustalev <yury.khrustalev@arm.com> To: gcc-patches@gcc.gnu.org Cc: tamar.christina@arm.com, srinath.parvathaneni@arm.com, tejas.belagod@arm.com, jakub@redhat.com Subject: [PATCH] dwarf: Save bit stride information array type entry [PR121964] Date: Wed, 17 Sep 2025 16:39:12 +0100 Message-ID: <20250917153912.3187098-1-yury.khrustalev@arm.com> X-Mailer: git-send-email 2.47.3 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-12.8 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, KAM_LAZY_DOMAIN_SECURITY, KAM_SHORT, RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list <gcc-patches.gcc.gnu.org> List-Unsubscribe: <https://gcc.gnu.org/mailman/options/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe> List-Archive: <https://gcc.gnu.org/pipermail/gcc-patches/> List-Post: <mailto:gcc-patches@gcc.gnu.org> List-Help: <mailto:gcc-patches-request@gcc.gnu.org?subject=help> List-Subscribe: <https://gcc.gnu.org/mailman/listinfo/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe> Errors-To: gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org |
| 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
> -----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
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
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
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
> 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 >
> -----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 > >
> 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 >>>
> -----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 > >>>
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
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
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
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
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
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
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
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
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
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
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); +}