aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2018-06-13 11:20:23 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2018-06-13 11:20:23 +0000
commit70e18df76ed2ccce4f6695b7f848d25dfa31ce0e (patch)
tree1a324714f7d9bfc0c7a33b273c25abe20f1cda90
parent8c191c89cfde7c74955c21d488702077cca89117 (diff)
downloadgcc-70e18df76ed2ccce4f6695b7f848d25dfa31ce0e.zip
gcc-70e18df76ed2ccce4f6695b7f848d25dfa31ce0e.tar.gz
gcc-70e18df76ed2ccce4f6695b7f848d25dfa31ce0e.tar.bz2
re PR target/86048 (.seh_savexmm offset is negative error when compiling libpng)
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. From-SVN: r261544
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/config/i386/winnt.c25
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.target/i386/pr86048.c26
4 files changed, 58 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 34eb1d9..103877a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+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-12 Claudiu Zissulescu <claziss@synopsys.com>
* config/arc/fpu.md (fmasf4): Force operand to register.
diff --git a/gcc/config/i386/winnt.c b/gcc/config/i386/winnt.c
index 3a857f9..89e4b6e 100644
--- a/gcc/config/i386/winnt.c
+++ b/gcc/config/i386/winnt.c
@@ -922,11 +922,14 @@ i386_pe_seh_cold_init (FILE *f, const char *name)
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 char *name)
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);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index cb680c7..8d5d405 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2018-06-13 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.target/i386/pr86048.c: New test.
+
2018-06-12 Claudiu Zissulescu <claziss@synopsys.com>
* gcc.target/arc/fma-1.c: New test.
diff --git a/gcc/testsuite/gcc.target/i386/pr86048.c b/gcc/testsuite/gcc.target/i386/pr86048.c
new file mode 100644
index 0000000..cd73579
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr86048.c
@@ -0,0 +1,26 @@
+/* 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;
+}