]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Partially lift restriction from loc_list_from_tree_1
authorEric Botcazou <ebotcazou@adacore.com>
Sun, 18 May 2025 17:10:26 +0000 (19:10 +0200)
committerEric Botcazou <ebotcazou@adacore.com>
Sun, 18 May 2025 17:14:52 +0000 (19:14 +0200)
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.

gcc/dwarf2out.cc

index 9aecdb9fd5a1a844d24008d11e97e1cfcb20aa58..713a55108aa2bf77d2b1c8b0081b9940308b4590 100644 (file)
@@ -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