diff options
Diffstat (limited to 'gcc/config/rs6000/rs6000.c')
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 45 |
1 files changed, 39 insertions, 6 deletions
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) |