diff options
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/i386/i386.c | 91 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 45 |
2 files changed, 102 insertions, 34 deletions
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) |