Fix PR target/86048

Message ID 4512915.JhvSi1tPVi@polaris
State New
Headers show
Series
  • Fix PR target/86048
Related show

Commit Message

Eric Botcazou June 13, 2018, 11:23 a.m.
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  <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-13  Eric Botcazou  <ebotcazou@adacore.com>

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

Comments

Jakub Jelinek June 14, 2018, 7:18 p.m. | #1
On Wed, Jun 13, 2018 at 01:23:41PM +0200, Eric Botcazou wrote:
> 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-13  Eric Botcazou  <ebotcazou@adacore.com>
> 
> 	* gcc.target/i386/pr86048.c: New test.

I've noticed this test fails on i686-linux
gcc/gcc/testsuite/gcc.target/i386/pr86048.c:23:3: error: unknown register name '%xmm6' in 'asm'

Fixed thusly, tested on x86_64-linux and i686-linux, committed to trunk and
8.2.

2018-06-14  Jakub Jelinek  <jakub@redhat.com>

	PR target/86048
	* gcc.target/i386/pr86048.c: Require sse2 effective target.  Add
	-msse2 to dg-options.

--- gcc/testsuite/gcc.target/i386/pr86048.c.jj	2018-06-14 13:14:49.746946234 +0200
+++ gcc/testsuite/gcc.target/i386/pr86048.c	2018-06-14 21:13:37.467684233 +0200
@@ -1,6 +1,6 @@
 /* PR target/86048 */
-/* { dg-do assemble } */
-/* { dg-options "-O2" } */
+/* { dg-do assemble { target sse2 } } */
+/* { dg-options "-O2 -msse2" } */
 /* { dg-require-effective-target return_address } */
 
 extern void abort (void);


	Jakub
Eric Botcazou June 14, 2018, 10:12 p.m. | #2
> I've noticed this test fails on i686-linux
> gcc/gcc/testsuite/gcc.target/i386/pr86048.c:23:3: error: unknown register
> name '%xmm6' in 'asm'
> 
> Fixed thusly, tested on x86_64-linux and i686-linux, committed to trunk and
> 8.2.

Thanks!

Patch

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