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 <ebotca...@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 <ebotca...@adacore.com>
* gcc.target/i386/pr86048.c: New test.
--
Eric Botcazou
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);
/* 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;
}