This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Fix PR target/84763


This is a small regression just introduced on the mainline by my patch fixing 
the -freorder-blocks-and-partition optimization on x86-64/Windows.  On this 
platform, the SEH scheme imposes constraints on the prologue of functions, in 
particular the frame pointer is near the bottom of the frame.  But there is an 
exception when __builtin_{frame,return}_address is present in the code and the 
implementation of i386_pe_seh_cold_init fails to account for it.

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


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-09  Eric Botcazou  <ebotcazou@adacore.com>

	* gcc.c-torture/compile/20180309-1.c: New test.

-- 
Eric Botcazou
Index: config/i386/winnt.c
===================================================================
--- config/i386/winnt.c	(revision 258338)
+++ config/i386/winnt.c	(working copy)
@@ -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 ch
   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 ch
 		 : (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 ch
       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);
 }
 
/* 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;
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]