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

            Bug ID: 127680
           Summary: ucompare_loc_descriptor produces invalid DWARF
                    expressions
           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: ---

The latest GCC  on x86-64 GNU/Linux emits an invalid DWARF expression
for *result* in the following repro.c:

        typedef unsigned long long u64;

        __attribute__((noinline, noclone)) int
        less_than (double input)
        {
          int result = (u64) input < 0x100000000ULL;
          __asm__ volatile ("nop" ::: "memory");
          return 0;
        }

        int
        main (void)
        {
          return less_than (1.25);
        }

Compile with that GCC:

        gcc -O2 -g -fvar-tracking-assignments -fno-pie -no-pie repro.c -o repro

At the nop, the expression is (base-type references shown symbolically):

        DW_OP_regval_type XMM0 <double>
        DW_OP_convert <unsigned long>
        DW_OP_plus_uconst 9223372036854775808
        DW_OP_consts -9223372032559808513
        DW_OP_le
        DW_OP_const1u 255
        DW_OP_and
        DW_OP_stack_value

The referenced double and unsigned integer base types are both 8 bytes.
DW_OP_plus_uconst preserves the unsigned base type left by DW_OP_convert,
while DW_OP_consts pushes a generic value. DW_OP_le therefore consumes
operands with different DWARF types. DWARF 5 ยง2.5.1.5 requires both operands
to be generic or to have the same base type; matching bit widths are
insufficient.

In earlier tests, GDB accepted this expression and returned the expected
values; that does not make its operand types valid.

The cause is the address-sized comparison path in ucompare_loc_descriptor
in gcc/dwarf2out.cc. It adds the sign-bit bias to the typed operand but
rebuilds the constant operand with int_loc_descriptor, then emits the
comparison without reconciling their stack types. The GEU, GTU, LEU and LTU
cases share this helper. The operand types must be reconciled while preserving
the unsigned comparison semantics.

Reply via email to