summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriains <iains@138bc75d-0d04-0410-961f-82ee72b054a4>2016-12-11 16:10:48 +0000
committeriains <iains@138bc75d-0d04-0410-961f-82ee72b054a4>2016-12-11 16:10:48 +0000
commit30ab9654d4023334c8b5f2fcc061110b7ef8bec2 (patch)
tree738c4a937be02e28986e9beeef99bf2e1153c82d
parent39c6919bb5237832eb9c50010f3d2b89fb33398f (diff)
downloadgcc-30ab9654d4023334c8b5f2fcc061110b7ef8bec2.tar.gz
[Darwin] Back-port fix for PR57438.
gcc/ 2016-12-11 Iain Sandoe <iain@codesourcery.com> Backport from mainline 2016-11-27 Iain Sandoe <iain@codesourcery.com> PR target/57438 * config/i386/i386.c (ix86_code_end): Note that we emitted code where the function might otherwise appear empty for picbase thunks. (ix86_output_function_epilogue): If we find a zero-sized function assume that reaching it is UB and trap. If we find a trailing label append a nop. * config/rs6000/rs6000.c (rs6000_output_function_epilogue): If we find a zero-sized function assume that reaching it is UB and trap. If we find a trailing label, append a nop. gcc/testsuite/ 2016-12-11 Iain Sandoe <iain@codesourcery.com> Backport from mainline 2016-11-27 Iain Sandoe <iain@codesourcery.com> PR target/57438 * gcc.dg/pr57438-1.c: New Test. * gcc.dg/pr57438-2.c: New Test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-6-branch@243525 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/config/i386/i386.c91
-rw-r--r--gcc/config/rs6000/rs6000.c45
-rw-r--r--gcc/testsuite/ChangeLog10
-rw-r--r--gcc/testsuite/gcc.dg/pr57438-1.c16
-rw-r--r--gcc/testsuite/gcc.dg/pr57438-2.c23
6 files changed, 165 insertions, 35 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5eb4bad303a..50578c8002a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -3,6 +3,21 @@
Backport from mainline
2016-11-27 Iain Sandoe <iain@codesourcery.com>
+ PR target/57438
+ * config/i386/i386.c (ix86_code_end): Note that we emitted code
+ where the function might otherwise appear empty for picbase thunks.
+ (ix86_output_function_epilogue): If we find a zero-sized function
+ assume that reaching it is UB and trap. If we find a trailing label
+ append a nop.
+ * config/rs6000/rs6000.c (rs6000_output_function_epilogue): If we
+ find a zero-sized function assume that reaching it is UB and trap.
+ If we find a trailing label, append a nop.
+
+2016-12-11 Iain Sandoe <iain@codesourcery.com>
+
+ Backport from mainline
+ 2016-11-27 Iain Sandoe <iain@codesourcery.com>
+
PR target/71767
* config/darwin-sections.def (picbase_thunk_section): New.
* config/darwin.c (darwin_init_sections): Set up picbase thunk
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 9cbc4ccf4c1..c0855c94a17 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -11084,6 +11084,9 @@ ix86_code_end (void)
current_function_decl = decl;
allocate_struct_function (decl, false);
init_function_start (decl);
+ /* We're about to hide the function body from callees of final_* by
+ emitting it directly; tell them we're a thunk, if they care. */
+ cfun->is_thunk = true;
first_function_block_is_cold = false;
/* Make sure unwind info is emitted for the thunk if needed. */
final_start_function (emit_barrier (), asm_out_file, 1);
@@ -13709,36 +13712,68 @@ ix86_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED, HOST_WIDE_INT)
if (pic_offset_table_rtx
&& !ix86_use_pseudo_pic_reg ())
SET_REGNO (pic_offset_table_rtx, REAL_PIC_OFFSET_TABLE_REGNUM);
-#if TARGET_MACHO
- /* Mach-O doesn't support labels at the end of objects, so if
- it looks like we might want one, insert a NOP. */
- {
- rtx_insn *insn = get_last_insn ();
- rtx_insn *deleted_debug_label = NULL;
- while (insn
- && NOTE_P (insn)
- && NOTE_KIND (insn) != NOTE_INSN_DELETED_LABEL)
- {
- /* Don't insert a nop for NOTE_INSN_DELETED_DEBUG_LABEL
- notes only, instead set their CODE_LABEL_NUMBER to -1,
- otherwise there would be code generation differences
- in between -g and -g0. */
- if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_DELETED_DEBUG_LABEL)
- deleted_debug_label = insn;
+
+ if (TARGET_MACHO)
+ {
+ rtx_insn *insn = get_last_insn ();
+ rtx_insn *deleted_debug_label = NULL;
+
+ /* Mach-O doesn't support labels at the end of objects, so if
+ it looks like we might want one, take special action.
+ First, collect any sequence of deleted debug labels. */
+ while (insn
+ && NOTE_P (insn)
+ && NOTE_KIND (insn) != NOTE_INSN_DELETED_LABEL)
+ {
+ /* Don't insert a nop for NOTE_INSN_DELETED_DEBUG_LABEL
+ notes only, instead set their CODE_LABEL_NUMBER to -1,
+ otherwise there would be code generation differences
+ in between -g and -g0. */
+ if (NOTE_P (insn) && NOTE_KIND (insn)
+ == NOTE_INSN_DELETED_DEBUG_LABEL)
+ deleted_debug_label = insn;
+ insn = PREV_INSN (insn);
+ }
+
+ /* If we have:
+ label:
+ barrier
+ then this needs to be detected, so skip past the barrier. */
+
+ if (insn && BARRIER_P (insn))
insn = PREV_INSN (insn);
- }
- if (insn
- && (LABEL_P (insn)
- || (NOTE_P (insn)
- && NOTE_KIND (insn) == NOTE_INSN_DELETED_LABEL)))
- fputs ("\tnop\n", file);
- else if (deleted_debug_label)
- for (insn = deleted_debug_label; insn; insn = NEXT_INSN (insn))
- if (NOTE_KIND (insn) == NOTE_INSN_DELETED_DEBUG_LABEL)
- CODE_LABEL_NUMBER (insn) = -1;
- }
-#endif
+ /* Up to now we've only seen notes or barriers. */
+ if (insn)
+ {
+ if (LABEL_P (insn)
+ || (NOTE_P (insn)
+ && NOTE_KIND (insn) == NOTE_INSN_DELETED_LABEL))
+ /* Trailing label. */
+ fputs ("\tnop\n", file);
+ else if (cfun && ! cfun->is_thunk)
+ {
+ /* See if we have a completely empty function body, skipping
+ the special case of the picbase thunk emitted as asm. */
+ while (insn && ! INSN_P (insn))
+ insn = PREV_INSN (insn);
+ /* If we don't find any insns, we've got an empty function body;
+ I.e. completely empty - without a return or branch. This is
+ taken as the case where a function body has been removed
+ because it contains an inline __builtin_unreachable(). GCC
+ declares that reaching __builtin_unreachable() means UB so
+ we're not obliged to do anything special; however, we want
+ non-zero-sized function bodies. To meet this, and help the
+ user out, let's trap the case. */
+ if (insn == NULL)
+ fputs ("\tud2\n", file);
+ }
+ }
+ else if (deleted_debug_label)
+ for (insn = deleted_debug_label; insn; insn = NEXT_INSN (insn))
+ if (NOTE_KIND (insn) == NOTE_INSN_DELETED_DEBUG_LABEL)
+ CODE_LABEL_NUMBER (insn) = -1;
+ }
}
/* Return a scratch register to use in the split stack prologue. The
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 8907aed2c3f..e319b26755c 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -28446,11 +28446,15 @@ rs6000_output_function_epilogue (FILE *file,
{
#if TARGET_MACHO
macho_branch_islands ();
- /* Mach-O doesn't support labels at the end of objects, so if
- it looks like we might want one, insert a NOP. */
+
{
rtx_insn *insn = get_last_insn ();
rtx_insn *deleted_debug_label = NULL;
+
+ /* Mach-O doesn't support labels at the end of objects, so if
+ it looks like we might want one, take special action.
+
+ First, collect any sequence of deleted debug labels. */
while (insn
&& NOTE_P (insn)
&& NOTE_KIND (insn) != NOTE_INSN_DELETED_LABEL)
@@ -28463,11 +28467,40 @@ rs6000_output_function_epilogue (FILE *file,
deleted_debug_label = insn;
insn = PREV_INSN (insn);
}
- if (insn
- && (LABEL_P (insn)
+
+ /* Second, if we have:
+ label:
+ barrier
+ then this needs to be detected, so skip past the barrier. */
+
+ if (insn && BARRIER_P (insn))
+ insn = PREV_INSN (insn);
+
+ /* Up to now we've only seen notes or barriers. */
+ if (insn)
+ {
+ if (LABEL_P (insn)
|| (NOTE_P (insn)
- && NOTE_KIND (insn) == NOTE_INSN_DELETED_LABEL)))
- fputs ("\tnop\n", file);
+ && NOTE_KIND (insn) == NOTE_INSN_DELETED_LABEL))
+ /* Trailing label: <barrier>. */
+ fputs ("\tnop\n", file);
+ else
+ {
+ /* Lastly, see if we have a completely empty function body. */
+ while (insn && ! INSN_P (insn))
+ insn = PREV_INSN (insn);
+ /* If we don't find any insns, we've got an empty function body;
+ I.e. completely empty - without a return or branch. This is
+ taken as the case where a function body has been removed
+ because it contains an inline __builtin_unreachable(). GCC
+ states that reaching __builtin_unreachable() means UB so we're
+ not obliged to do anything special; however, we want
+ non-zero-sized function bodies. To meet this, and help the
+ user out, let's trap the case. */
+ if (insn == NULL)
+ fputs ("\ttrap\n", file);
+ }
+ }
else if (deleted_debug_label)
for (insn = deleted_debug_label; insn; insn = NEXT_INSN (insn))
if (NOTE_KIND (insn) == NOTE_INSN_DELETED_DEBUG_LABEL)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 97148591382..a3146c3a4b6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,6 +1,15 @@
2016-12-11 Iain Sandoe <iain@codesourcery.com>
Backport from mainline
+ 2016-11-27 Iain Sandoe <iain@codesourcery.com>
+
+ PR target/57438
+ * gcc.dg/pr57438-1.c: New Test.
+ * gcc.dg/pr57438-2.c: New Test.
+
+2016-12-11 Iain Sandoe <iain@codesourcery.com>
+
+ Backport from mainline
2016-11-27 Dominique d'Humieres <dominiq@lps.ens.fr>
Iain Sandoe <iain@codesourcery.com>
@@ -10,7 +19,6 @@
* g++.dg/torture/darwin-cfstring-3.C: Likewise.
* gcc.dg/const-uniq-1.c: Likewise.
* gcc.dg/torture/darwin-cfstring-3.c: Likewise.
- * gcc.target/i386/pr70799-1.c: Likewise.
2016-12-09 Thomas Preud'homme <thomas.preudhomme@arm.com>
diff --git a/gcc/testsuite/gcc.dg/pr57438-1.c b/gcc/testsuite/gcc.dg/pr57438-1.c
new file mode 100644
index 00000000000..9bfd8b9d911
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr57438-1.c
@@ -0,0 +1,16 @@
+/* { dg-do compile { target *-*-darwin* } } */
+/* { dg-options "-O1" } */
+/* { dg-additional-options "-mdynamic-no-pic" { target powerpc*-*-darwin* } }
+
+/* This is testing that a completely empty function body results in the
+ insertion of a ud2/trap instruction to prevent a zero-sized FDE, and/or
+ the function label apparently pointing to following code. */
+
+__attribute__((noinline))
+void foo (void)
+{
+ __builtin_unreachable();
+}
+
+/* { dg-final { scan-assembler "ud2" { target { i?86-*-darwin* x86_64-*-darwin* } } } } */
+/* { dg-final { scan-assembler "trap" { target { powerpc*-*-darwin* } } } } */
diff --git a/gcc/testsuite/gcc.dg/pr57438-2.c b/gcc/testsuite/gcc.dg/pr57438-2.c
new file mode 100644
index 00000000000..c64a31353a5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr57438-2.c
@@ -0,0 +1,23 @@
+/* { dg-do compile { target *-*-darwin* } } */
+/* { dg-options "--param case-values-threshold=3 -O2" } */
+/* { dg-additional-options "-funwind-tables" { target powerpc*-*-darwin* } }
+
+/* This is testing that a trailing local label is followed by a
+ nop where required. */
+
+int foo (int x)
+{
+ switch (x)
+ {
+ case 0:
+ return 10;
+ case 3:
+ return -1;
+ case 5:
+ return 29;
+ default:
+ __builtin_unreachable();
+ }
+}
+
+/* { dg-final { scan-assembler "nop\\nLFE.*" { target { *-*-darwin* } } } } */