diff mbox series

Fix PR target/84763

Message ID 1866458.YVN6egk9NU@polaris
State New
Headers show
Series Fix PR target/84763 | expand

Commit Message

Eric Botcazou March 9, 2018, 9:07 a.m. UTC
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.
diff mbox series

Patch

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