re PR target/84763 (ICE in i386_pe_seh_cold_init)
authorEric Botcazou <ebotcazou@adacore.com>
Fri, 9 Mar 2018 09:06:52 +0000 (09:06 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Fri, 9 Mar 2018 09:06:52 +0000 (09:06 +0000)
PR target/84763
* config/i386/winnt.c (i386_pe_seh_cold_init): Use small pre-allocation
when the function accesses prior frames.

From-SVN: r258381

gcc/ChangeLog
gcc/config/i386/winnt.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/20180309-1.c [new file with mode: 0644]

index 5675cdb7c3b6395d6d03486600d0b9dff4172714..69b7def90bf33f75d7396ef2124b483c842c8e6d 100644 (file)
@@ -1,3 +1,9 @@
+2018-03-09  Eric Botcazou  <ebotcazou@adacore.com>
+
+       PR target/84763
+       * config/i386/winnt.c (i386_pe_seh_cold_init): Use small pre-allocation
+       when the function accesses prior frames.
+
 2018-03-08  Jakub Jelinek  <jakub@redhat.com>
 
        PR debug/84456
index 9b406f490944cde67c8981a853be66f0fa6c5d3b..d5c256b23ceb811622a098ccbaedac77466968de 100644 (file)
@@ -879,7 +879,7 @@ void
 i386_pe_seh_cold_init (FILE *f, const char *name)
 {
   struct seh_frame_state *seh;
-  HOST_WIDE_INT offset;
+  HOST_WIDE_INT alloc_offset, offset;
 
   if (!TARGET_SEH)
     return;
@@ -891,7 +891,16 @@ i386_pe_seh_cold_init (FILE *f, const char *name)
   assemble_name (f, name);
   fputc ('\n', f);
 
-  offset = seh->sp_offset - INCOMING_FRAME_SP_OFFSET;
+  /* In the normal case, the frame pointer is near the bottom of the frame
+     so we can do the full stack allocation and set it afterwards.  There
+     is an exception when the function accesses prior frames so, in this
+     case, we need to pre-allocate a small chunk before setting it.  */
+  if (crtl->accesses_prior_frames)
+    alloc_offset = seh->cfa_offset;
+  else
+    alloc_offset = seh->sp_offset;
+
+  offset = alloc_offset - INCOMING_FRAME_SP_OFFSET;
   if (offset > 0 && offset < SEH_MAX_FRAME_SIZE)
     fprintf (f, "\t.seh_stackalloc\t" HOST_WIDE_INT_PRINT_DEC "\n", offset);
 
@@ -903,12 +912,12 @@ i386_pe_seh_cold_init (FILE *f, const char *name)
                 : (gcc_unreachable (), "")), f);
        print_reg (gen_rtx_REG (DImode, regno), 0, f);
        fprintf (f, ", " HOST_WIDE_INT_PRINT_DEC "\n",
-                seh->sp_offset - seh->reg_offset[regno]);
+                alloc_offset - seh->reg_offset[regno]);
       }
 
   if (seh->cfa_reg != stack_pointer_rtx)
     {
-      offset = seh->sp_offset - seh->cfa_offset;
+      offset = alloc_offset - seh->cfa_offset;
 
       gcc_assert ((offset & 15) == 0);
       gcc_assert (IN_RANGE (offset, 0, 240));
@@ -918,6 +927,13 @@ i386_pe_seh_cold_init (FILE *f, const char *name)
       fprintf (f, ", " HOST_WIDE_INT_PRINT_DEC "\n", offset);
     }
 
+  if (crtl->accesses_prior_frames)
+    {
+      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);
+    }
+
   fputs ("\t.seh_endprologue\n", f);
 }
 
index 1917aef3cf17710ac33528ef5e9bd045462e5aba..80d60c880f84912df1f43620e9dd59200791f199 100644 (file)
@@ -1,3 +1,7 @@
+2018-03-09  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc.c-torture/compile/20180309-1.c: New test.
+
 2018-03-08  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/80598
diff --git a/gcc/testsuite/gcc.c-torture/compile/20180309-1.c b/gcc/testsuite/gcc.c-torture/compile/20180309-1.c
new file mode 100644 (file)
index 0000000..0784466
--- /dev/null
@@ -0,0 +1,22 @@
+/* PR target/84763 */
+/* { 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;
+
+  return ret;
+}