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");
}

Reply via email to