https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128031

            Bug ID: 128031
           Summary: dw_sra_loc_expr emits an invalid 12-byte piece for an
                    x87 register
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: debug
          Assignee: unassigned at gcc dot gnu.org
          Reporter: wujielun402 at gmail dot com
  Target Milestone: ---

With -m32 -m96bit-long-double, GCC emits an invalid DWARF 5 location for
the local struct record variable value. The structure's fields are tracked
separately after scalar replacement of aggregates (SRA). In an affected
location-list range, the long double field is in st0 and tag is in memory:

        DW_OP_reg11 (st0); DW_OP_piece 12
        DW_OP_fbreg 12; DW_OP_piece 4

The long double field occupies 12 bytes in memory: 10 bytes for the 80-bit
floating-point value and 2 bytes of padding. The x87 register st0 holds
only 10 bytes. DW_OP_piece 12 therefore asks an 80-bit register to supply
96 bits. DWARF 5 section 2.6.1.2 defines the operand as the byte size of
the object piece described by the preceding location.

One suitable description would leave the padding unavailable while
preserving tag's offset of 12 bytes within the structure:

        DW_OP_reg11 (st0); DW_OP_piece 10
        DW_OP_piece 2
        DW_OP_fbreg 12; DW_OP_piece 4

The standalone DW_OP_piece 2 describes unavailable bytes, not zero bytes.

Reproducer source (repro.c):

        struct record
        {
          long double value;
          unsigned int tag;
        };

        __attribute__ ((noinline, noclone)) long double
        sra_x87_piece_live (long double input, unsigned int tag)
        {
          struct record value;
          value.value = input * 3.0L;
          value.tag = tag;
          return value.value + (long double) value.tag;
        }

Compile to an object:

        gcc -m32 -m96bit-long-double -O2 -g -gdwarf-5 -c repro.c -o repro.o

Compiler Explorer example: https://godbolt.org/z/KhfGxKvYx

The oversized piece is appended by dw_sra_loc_expr in gcc/dwarf2out.cc.
For a field location with no existing piece operation, it passes the
decl_piece_bitsize value (96 bits here) to new_loc_descr_op_bit_piece
without checking the width of a register location.

This is a different emission path from PR 128025, where
multiple_reg_loc_descriptor divides one value among general-purpose
registers, and PR 128027, where concat_loc_descriptor combines complex
components. Here dw_sra_loc_expr itself adds the oversized piece to a
single-register field location; fixes confined to those two helpers would
not address this emission site.

Reply via email to