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.