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

Reply via email to