Hi,
this is a latent bug exposed on the mainline for the ARM by:
http://gcc.gnu.org/ml/gcc-patches/2013-11/msg01755.html
The problem is that the CFI expressions for:
(insn/f:TI 102 11 103 (parallel [
(set (mem/c:BLK (pre_modify:SI (reg/f:SI 13 sp)
(plus:SI (reg/f:SI 13 sp)
(const_int -8 [0xfffffffffffffff8]))) [2 A8])
(unspec:BLK [
(reg:DF 32 s16)
] UNSPEC_PUSH_MULT))
]) pr59418.c:5 728 {*push_multi_vfp}
(expr_list:REG_DEAD (reg:DF 32 s16)
(expr_list:REG_FRAME_RELATED_EXPR (sequence [
(set/f (reg/f:SI 13 sp)
(plus:SI (reg/f:SI 13 sp)
(const_int -8 [0xfffffffffffffff8])))
(set/f (mem/c:DF (reg/f:SI 13 sp) [2 S8 A64])
(reg:DF 32 s16))
])
(nil))))
and:
(insn/f:TI 113 128 20 (parallel [
(set/f (reg/f:SI 13 sp)
(plus:SI (reg/f:SI 13 sp)
(const_int 8 [0x8])))
(set/f (reg:DF 32 s16)
(mem/c:DF (reg/f:SI 13 sp) [2 S8 A64]))
]) pr59418.c:28 347 {*vfp_pop_multiple_with_writeback}
(expr_list:REG_CFA_ADJUST_CFA (set (reg/f:SI 13 sp)
(plus:SI (reg/f:SI 13 sp)
(const_int 8 [0x8])))
(expr_list:REG_CFA_RESTORE (reg:DF 32 s16)
(nil))))
are treated differently: for the former, the source register (reg:DF 32 s16)
goes through TARGET_DWARF_REGISTER_SPAN but, for the latter, the same register
being restored does not, which results in CFI mismatch caught by the checking.
Fixed by handling TARGET_DWARF_REGISTER_SPAN for REG_CFA_RESTORE, tested on
arm-eabi, OK for the mainline?
2013-12-15 Eric Botcazou <ebotca...@adacore.com>
PR debug/59418
* dwarf2cfi.c (dwarf2out_frame_debug_cfa_offset): Fix comment and clean
up implementation.
(dwarf2out_frame_debug_cfa_restore): Handle TARGET_DWARF_REGISTER_SPAN.
(dwarf2out_frame_debug_expr): Clean up implementation.
2013-12-15 Eric Botcazou <ebotca...@adacore.com>
* gcc.dg/pr59418.c: New test.
--
Eric Botcazou
Index: dwarf2cfi.c
===================================================================
--- dwarf2cfi.c (revision 205982)
+++ dwarf2cfi.c (working copy)
@@ -1149,18 +1149,14 @@ dwarf2out_frame_debug_cfa_offset (rtx se
else
{
/* We have a PARALLEL describing where the contents of SRC live.
- Queue register saves for each piece of the PARALLEL. */
- int par_index;
- int limit;
+ Adjust the offset for each piece of the PARALLEL. */
HOST_WIDE_INT span_offset = offset;
gcc_assert (GET_CODE (span) == PARALLEL);
- limit = XVECLEN (span, 0);
- for (par_index = 0; par_index < limit; par_index++)
+ for (int par_index = 0; par_index < XVECLEN (span, 0); par_index++)
{
rtx elem = XVECEXP (span, 0, par_index);
-
sregno = dwf_regno (src);
reg_save (sregno, INVALID_REGNUM, span_offset);
span_offset += GET_MODE_SIZE (GET_MODE (elem));
@@ -1229,10 +1225,30 @@ dwarf2out_frame_debug_cfa_expression (rt
static void
dwarf2out_frame_debug_cfa_restore (rtx reg)
{
- unsigned int regno = dwf_regno (reg);
+ gcc_assert (REG_P (reg));
+
+ rtx span = targetm.dwarf_register_span (reg);
+ if (!span)
+ {
+ unsigned int regno = dwf_regno (reg);
+ add_cfi_restore (regno);
+ update_row_reg_save (cur_row, regno, NULL);
+ }
+ else
+ {
+ /* We have a PARALLEL describing where the contents of REG live.
+ Restore the register for each piece of the PARALLEL. */
+ gcc_assert (GET_CODE (span) == PARALLEL);
- add_cfi_restore (regno);
- update_row_reg_save (cur_row, regno, NULL);
+ for (int par_index = 0; par_index < XVECLEN (span, 0); par_index++)
+ {
+ reg = XVECEXP (span, 0, par_index);
+ gcc_assert (REG_P (reg));
+ unsigned int regno = dwf_regno (reg);
+ add_cfi_restore (regno);
+ update_row_reg_save (cur_row, regno, NULL);
+ }
+ }
}
/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_WINDOW_SAVE.
@@ -1884,23 +1900,22 @@ dwarf2out_frame_debug_expr (rtx expr)
}
}
- span = NULL;
if (REG_P (src))
span = targetm.dwarf_register_span (src);
+ else
+ span = NULL;
+
if (!span)
queue_reg_save (src, NULL_RTX, offset);
else
{
/* We have a PARALLEL describing where the contents of SRC live.
Queue register saves for each piece of the PARALLEL. */
- int par_index;
- int limit;
HOST_WIDE_INT span_offset = offset;
gcc_assert (GET_CODE (span) == PARALLEL);
- limit = XVECLEN (span, 0);
- for (par_index = 0; par_index < limit; par_index++)
+ for (int par_index = 0; par_index < XVECLEN (span, 0); par_index++)
{
rtx elem = XVECEXP (span, 0, par_index);
queue_reg_save (elem, NULL_RTX, span_offset);
/* PR debug/59418 */
/* Reported by Ryan Mansfield <rmansfi...@qnx.com> */
/* { dg-do compile } */
/* { dg-options "-Os -g" } */
/* { dg-options "-march=armv7-a -mfloat-abi=hard -Os -g" { target arm*-*-* } } */
extern int printf (const char *__format, ...);
void
foo (const char *pptr, int caplen)
{
int type;
const char *tptr;
if (caplen < 4)
{
(void) printf ("foo");
return;
}
while (tptr < pptr)
{
switch (type)
{
case 0x01:
printf ("");
case 0x0b:
printf ("");
case 0x0e:
printf ("");
case 0x10:
printf ("%1.2fW", bar (tptr, caplen) / 1000.0);
}
}
printf ("foo");
}