This is a follow-up to PR target/84763 present on mainline and 8 branch:
  https://gcc.gnu.org/ml/gcc-patches/2018-03/msg00418.html

Since i386_pe_seh_cold_init now uses a small pre-allocation when there is 
__builtin_{frame,return}_address in the function, it also may need to split 
CFI save directives (.seh_savexmm/.seh_savereg) into a first group emitted 
after the pre-allocation and the rest emitted after the full allocation.

Tested on x86-64/Windows, applied on the mainline and 8 branch as obvious.


2018-06-13  Eric Botcazou  <ebotca...@adacore.com>

        PR target/86048
        * config/i386/winnt.c (i386_pe_seh_cold_init): Do not emit negative
        offsets for register save directives.  Emit a second batch of save
        directives, if need be, when the function accesses prior frames.


2018-06-13  Eric Botcazou  <ebotca...@adacore.com>

        * gcc.target/i386/pr86048.c: New test.

-- 
Eric Botcazou
Index: config/i386/winnt.c
===================================================================
--- config/i386/winnt.c	(revision 261473)
+++ config/i386/winnt.c	(working copy)
@@ -922,11 +922,14 @@ i386_pe_seh_cold_init (FILE *f, const ch
     fprintf (f, "\t.seh_stackalloc\t" HOST_WIDE_INT_PRINT_DEC "\n", offset);
 
   for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
-    if (seh->reg_offset[regno] > 0)
+    if (seh->reg_offset[regno] > 0 && seh->reg_offset[regno] <= alloc_offset)
       {
-	fputs ((SSE_REGNO_P (regno) ? "\t.seh_savexmm\t"
-	       : GENERAL_REGNO_P (regno) ?  "\t.seh_savereg\t"
-		 : (gcc_unreachable (), "")), f);
+	if (SSE_REGNO_P (regno))
+	  fputs ("\t.seh_savexmm\t", f);
+	else if (GENERAL_REGNO_P (regno))
+	  fputs ("\t.seh_savereg\t", f);
+	else
+	  gcc_unreachable ();
 	print_reg (gen_rtx_REG (DImode, regno), 0, f);
 	fprintf (f, ", " HOST_WIDE_INT_PRINT_DEC "\n",
 		 alloc_offset - seh->reg_offset[regno]);
@@ -949,6 +952,20 @@ i386_pe_seh_cold_init (FILE *f, const ch
       offset = seh->sp_offset - alloc_offset;
       if (offset > 0 && offset < SEH_MAX_FRAME_SIZE)
 	fprintf (f, "\t.seh_stackalloc\t" HOST_WIDE_INT_PRINT_DEC "\n", offset);
+
+      for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+	if (seh->reg_offset[regno] > alloc_offset)
+	  {
+	    if (SSE_REGNO_P (regno))
+	      fputs ("\t.seh_savexmm\t", f);
+	    else if (GENERAL_REGNO_P (regno))
+	      fputs ("\t.seh_savereg\t", f);
+	    else
+	      gcc_unreachable ();
+	    print_reg (gen_rtx_REG (DImode, regno), 0, f);
+	    fprintf (f, ", " HOST_WIDE_INT_PRINT_DEC "\n",
+		     seh->sp_offset - seh->reg_offset[regno]);
+	  }
     }
 
   fputs ("\t.seh_endprologue\n", f);
/* PR target/86048 */
/* { dg-do assemble } */
/* { dg-options "-O2" } */
/* { dg-require-effective-target return_address } */

extern void abort (void);

void *foo (unsigned int *data, unsigned int len)
{
  unsigned int local_data[128];

  if (len > 128)
    abort ();

  for (unsigned int i = 0; i < len; i++)
    local_data[i] = data[i] + data[len - 1 - i] * 2;

  void *ret = __builtin_frame_address (0);

  for (unsigned int i = 0; i < len; i++)
    ret = ret + local_data[i] % 8;

  __asm__ __volatile__ ("" : : : "%xmm6");

  return ret;
}

Reply via email to