re PR target/86048 (.seh_savexmm offset is negative error when compiling libpng)
authorEric Botcazou <ebotcazou@adacore.com>
Wed, 13 Jun 2018 11:20:23 +0000 (11:20 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Wed, 13 Jun 2018 11:20:23 +0000 (11:20 +0000)
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.

From-SVN: r261544

gcc/ChangeLog
gcc/config/i386/winnt.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr86048.c [new file with mode: 0644]

index 34eb1d9..103877a 100644 (file)
@@ -1,3 +1,10 @@
+2018-06-13  Eric Botcazou  <ebotcazou@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-12  Claudiu Zissulescu  <claziss@synopsys.com>
 
        * config/arc/fpu.md (fmasf4): Force operand to register.
index 3a857f9..89e4b6e 100644 (file)
@@ -922,11 +922,14 @@ i386_pe_seh_cold_init (FILE *f, const char *name)
     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 char *name)
       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);
index cb680c7..8d5d405 100644 (file)
@@ -1,3 +1,7 @@
+2018-06-13  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc.target/i386/pr86048.c: New test.
+
 2018-06-12  Claudiu Zissulescu  <claziss@synopsys.com>
 
        * gcc.target/arc/fma-1.c: New test.
diff --git a/gcc/testsuite/gcc.target/i386/pr86048.c b/gcc/testsuite/gcc.target/i386/pr86048.c
new file mode 100644 (file)
index 0000000..cd73579
--- /dev/null
@@ -0,0 +1,26 @@
+/* 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;
+}