As a follow-up to this discussion
(http://gcc.gnu.org/ml/gcc/2012-11/msg00307.html), I have a patch that
makes dwarf2out.c emit correct location information for a FP register spanning
multiple hard regs.
Before the patch, the DW_AT_location for a local variable on the AVR
target (whose FP spans registers R29 and R28) looks like this
<4f> DW_AT_location : 2 byte block: 8c 1 (DW_OP_breg28 (r28): 1)
After the patch, it looks like this
<4f> DW_AT_location : 11 byte block: 6c 93 1 6d 93 1 11 1 22 94 2
(DW_OP_reg28 (r28); DW_OP_piece: 1; DW_OP_reg29 (r29); DW_OP_piece: 1;
DW_OP_consts: 1; DW_OP_plus; DW_OP_deref_size: 2)
What do you guys think?
Regards
Senthil
diff --git gcc/dwarf2out.c gcc/dwarf2out.c
index f0256ae..53a4e56 100644
--- gcc/dwarf2out.c
+++ gcc/dwarf2out.c
@@ -10875,11 +10875,25 @@ based_loc_descr (rtx reg, HOST_WIDE_INT offset,
return new_loc_descr (DW_OP_fbreg, offset, 0);
}
- if (regno <= 31)
- result = new_loc_descr ((enum dwarf_location_atom) (DW_OP_breg0 + regno),
- offset, 0);
+ rtx regs = targetm.dwarf_register_span (reg);
+
+ if (hard_regno_nregs[REGNO (reg)][GET_MODE (reg)] > 1 || regs)
+ {
+ result = multiple_reg_loc_descriptor (reg, regs, initialized);
+ add_loc_descr (&result, new_loc_descr (DW_OP_consts, offset, 0));
+ add_loc_descr (&result, new_loc_descr (DW_OP_plus, 0, 0));
+ add_loc_descr (&result, new_loc_descr (DW_OP_deref_size,
+ GET_MODE_SIZE (GET_MODE (reg)),
+ 0));
+ }
else
- result = new_loc_descr (DW_OP_bregx, regno, offset);
+ {
+ if (regno <= 31)
+ result = new_loc_descr ((enum dwarf_location_atom) (DW_OP_breg0 +
regno),
+ offset, 0);
+ else
+ result = new_loc_descr (DW_OP_bregx, regno, offset);
+ }
if (initialized == VAR_INIT_STATUS_UNINITIALIZED)
add_loc_descr (&result, new_loc_descr (DW_OP_GNU_uninit, 0, 0));