https://gcc.gnu.org/g:809b46d2ccc9a4a0ab3a5b6015cbe9738b74b0a5
commit r16-717-g809b46d2ccc9a4a0ab3a5b6015cbe9738b74b0a5 Author: Eric Botcazou <ebotca...@adacore.com> Date: Sun May 18 19:10:26 2025 +0200 Partially lift restriction from loc_list_from_tree_1 The function accepts all handled_component_p expressions and decodes them by means of get_inner_reference as expected, but bails out on bitfields: /* TODO: We can extract value of the small expression via shifting even for nonzero bitpos. */ if (list_ret == 0) return 0; if (!multiple_p (bitpos, BITS_PER_UNIT, &bytepos) || !multiple_p (bitsize, BITS_PER_UNIT)) { expansion_failed (loc, NULL_RTX, "bitfield access"); return 0; } This lifts the second part of the restriction, which helps for obscure cases of packed discriminated record types in Ada, although this requires the very latest GDB sources. gcc/ * dwarf2out.cc (loc_list_from_tree_1) <COMPONENT_REF>: Do not bail out when the size is not a multiple of a byte. Deal with bit-fields whose size is not a multiple of a byte when dereferencing an address. Diff: --- gcc/dwarf2out.cc | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc index 9aecdb9fd5a1..713a55108aa2 100644 --- a/gcc/dwarf2out.cc +++ b/gcc/dwarf2out.cc @@ -19161,11 +19161,9 @@ loc_list_from_tree_1 (tree loc, int want_address, for nonzero bitpos. */ if (list_ret == 0) return 0; - if (!multiple_p (bitpos, BITS_PER_UNIT, &bytepos) - || !multiple_p (bitsize, BITS_PER_UNIT)) + if (!multiple_p (bitpos, BITS_PER_UNIT, &bytepos)) { - expansion_failed (loc, NULL_RTX, - "bitfield access"); + expansion_failed (loc, NULL_RTX, "bitfield access"); return 0; } @@ -19724,11 +19722,10 @@ loc_list_from_tree_1 (tree loc, int want_address, dw_die_ref type_die; dw_loc_descr_ref deref; - /* If the size is greater than DWARF2_ADDR_SIZE, bail out. */ - if (size > DWARF2_ADDR_SIZE || size == -1) + /* Bail out if the size is variable or greater than DWARF2_ADDR_SIZE. */ + if (size < 0 || size > DWARF2_ADDR_SIZE) { - expansion_failed (loc, NULL_RTX, - "DWARF address size mismatch"); + expansion_failed (loc, NULL_RTX, "DWARF address size mismatch"); return 0; } @@ -19757,6 +19754,33 @@ loc_list_from_tree_1 (tree loc, int want_address, new_loc_descr (dwarf_OP (DW_OP_convert), 0, 0)); } + /* Deal with bit-fields whose size is not a multiple of a byte. */ + if (TREE_CODE (loc) == COMPONENT_REF + && DECL_BIT_FIELD (TREE_OPERAND (loc, 1))) + { + const unsigned HOST_WIDE_INT bitsize + = tree_to_uhwi (DECL_SIZE (TREE_OPERAND (loc, 1))); + if (bitsize < (unsigned HOST_WIDE_INT)size * BITS_PER_UNIT) + { + if (TYPE_UNSIGNED (TREE_TYPE (loc))) + { + const unsigned HOST_WIDE_INT mask + = (HOST_WIDE_INT_1U << bitsize) - 1; + add_loc_descr (&deref, uint_loc_descriptor (mask)); + add_loc_descr (&deref, new_loc_descr (DW_OP_and, 0, 0)); + } + else + { + const unsigned HOST_WIDE_INT shift + = DWARF2_ADDR_SIZE * BITS_PER_UNIT - bitsize; + add_loc_descr (&deref, uint_loc_descriptor (shift)); + add_loc_descr (&deref, new_loc_descr (DW_OP_shl, 0, 0)); + add_loc_descr (&deref, uint_loc_descriptor (shift)); + add_loc_descr (&deref, new_loc_descr (DW_OP_shra, 0, 0)); + } + } + } + if (ret) add_loc_descr (&ret, deref); else