Hi,
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 latest
GDB sources.
Tested on x86-64/Linux, OK for the mainline?
2025-05-12 Eric Botcazou <ebotca...@adacore.com>
* 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.
--
Eric Botcazou
diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc
index 9aecdb9fd5a..713a55108aa 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