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

Reply via email to