aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2018-03-09 09:06:52 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2018-03-09 09:06:52 +0000
commit00db1bf12bb2b61f42a81d2bbbadce3fe6b0c358 (patch)
treec782f9705e8c1752cce605cfca8b3b6074d6ea37 /gcc
parent5da6b0135551f0060cd86d62cbbbfa5a4013157d (diff)
downloadgcc-00db1bf12bb2b61f42a81d2bbbadce3fe6b0c358.zip
gcc-00db1bf12bb2b61f42a81d2bbbadce3fe6b0c358.tar.gz
gcc-00db1bf12bb2b61f42a81d2bbbadce3fe6b0c358.tar.bz2
re PR target/84763 (ICE in i386_pe_seh_cold_init)
PR target/84763 * config/i386/winnt.c (i386_pe_seh_cold_init): Use small pre-allocation when the function accesses prior frames. From-SVN: r258381
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/i386/winnt.c24
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20180309-1.c22
4 files changed, 52 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5675cdb..69b7def 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+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-08 Jakub Jelinek <jakub@redhat.com>
PR debug/84456
diff --git a/gcc/config/i386/winnt.c b/gcc/config/i386/winnt.c
index 9b406f4..d5c256b 100644
--- a/gcc/config/i386/winnt.c
+++ b/gcc/config/i386/winnt.c
@@ -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 char *name)
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 char *name)
: (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 char *name)
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);
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 1917aef..80d60c8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2018-03-09 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.c-torture/compile/20180309-1.c: New test.
+
2018-03-08 Jakub Jelinek <jakub@redhat.com>
PR c++/80598
diff --git a/gcc/testsuite/gcc.c-torture/compile/20180309-1.c b/gcc/testsuite/gcc.c-torture/compile/20180309-1.c
new file mode 100644
index 0000000..0784466
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/20180309-1.c
@@ -0,0 +1,22 @@
+/* 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;
+}