Index: include/dwarf2.h =================================================================== --- include/dwarf2.h (revision 163221) +++ include/dwarf2.h (working copy) @@ -854,7 +854,8 @@ enum dwarf_call_frame_info /* GNU extensions. */ DW_CFA_GNU_window_save = 0x2d, DW_CFA_GNU_args_size = 0x2e, - DW_CFA_GNU_negative_offset_extended = 0x2f + DW_CFA_GNU_negative_offset_extended = 0x2f, + DW_CFA_GNU_start_epilogue = 0x30 }; #define DW_CIE_ID 0xffffffff Index: gcc/dwarf2out.c =================================================================== --- gcc/dwarf2out.c (revision 163221) +++ gcc/dwarf2out.c (working copy) @@ -720,7 +724,9 @@ dwarf_cfi_name (unsigned int cfi_opc) return "DW_CFA_GNU_args_size"; case DW_CFA_GNU_negative_offset_extended: return "DW_CFA_GNU_negative_offset_extended"; - + case DW_CFA_GNU_start_epilogue: + return "DW_CFA_GNU_start_epilogue"; + default: return "DW_CFA_"; } @@ -801,6 +807,9 @@ dwarf2out_cfi_label (bool force) /* True if remember_state should be emitted before following CFI directive. */ static bool emit_cfa_remember; +/* True if start_epilogue should be emitted before following CFI directive. */ +static bool emit_cfa_start_epilogue; + /* Add CFI to the current fde at the PC value indicated by LABEL if specified, or to the CIE if LABEL is NULL. */ @@ -809,6 +818,17 @@ add_fde_cfi (const char *label, dw_cfi_ref cfi) { dw_cfi_ref *list_head; + if (emit_cfa_start_epilogue) + { + dw_cfi_ref cfi_epi_start; + + /* Emit the state save. */ + emit_cfa_start_epilogue = false; + cfi_epi_start = new_cfi (); + cfi_epi_start->dw_cfi_opc = DW_CFA_GNU_start_epilogue; + add_fde_cfi (label, cfi_epi_start); + } + if (emit_cfa_remember) { dw_cfi_ref cfi_remember; @@ -2898,7 +2918,12 @@ dwarf2out_cfi_begin_epilogue (rtx insn) gcc_assert (i != NULL); i = next_real_insn (i); if (i == NULL) - return; + { + /* But we do mark the start of the epilogue to allow it to be skipped + in _eh frames. */ + emit_cfa_start_epilogue = true; + return; + } /* Insert the restore before that next real insn in the stream, and before a potential NOTE_INSN_EPILOGUE_BEG -- we do need these notes to be @@ -2953,6 +2978,7 @@ dw_cfi_oprnd1_desc (enum dwarf_call_frame_info cfi case DW_CFA_GNU_window_save: case DW_CFA_remember_state: case DW_CFA_restore_state: + case DW_CFA_GNU_start_epilogue: return dw_cfi_oprnd_unused; case DW_CFA_set_loc: @@ -3121,6 +3148,10 @@ output_cfi (dw_cfi_ref cfi, dw_fde_ref fde, int fo dw2_asm_output_data (1, (cfi->dw_cfi_opc | (r & 0x3f)), "DW_CFA_restore, column %#lx", r); } + else if (cfi->dw_cfi_opc == DW_CFA_GNU_start_epilogue) +/* DEBUG */ + fputs (ASM_COMMENT_START"\t\t\t"ASM_COMMENT_START + " DW_CFA_GNU_start_epilogue\n",asm_out_file); else { dw2_asm_output_data (1, cfi->dw_cfi_opc, @@ -3303,6 +3334,12 @@ output_cfi_directive (dw_cfi_ref cfi) cfi->dw_cfi_oprnd1.dw_cfi_offset); break; + case DW_CFA_GNU_start_epilogue: +/*DEBUG */ + fputs (ASM_COMMENT_START"\t\t\t"ASM_COMMENT_START + " DW_CFA_GNU_start_epilogue\n",asm_out_file); + break; + case DW_CFA_remember_state: fprintf (asm_out_file, "\t.cfi_remember_state\n"); break; @@ -3498,6 +3535,41 @@ output_cfis (dw_cfi_ref cfi, bool do_cfi_asm, dw_f } } +/* Output cfi skipping save/restore and epilogues in _eh frames + for targets that do not want them. */ + +static dw_cfi_ref +emit_cfi_or_skip_epilogue (dw_cfi_ref cfi, dw_fde_ref fde, bool for_eh) +{ + if (for_eh + && targetm.asm_out.suppress_eh_epilogue_p()) + { + if (cfi->dw_cfi_opc == DW_CFA_remember_state) + { + /* Skip to the restore, unless there's an error and we fall off + the end. */ + while (cfi->dw_cfi_next + && cfi->dw_cfi_opc != DW_CFA_restore_state) + cfi = cfi->dw_cfi_next; + return cfi; + } + if (cfi->dw_cfi_opc == DW_CFA_GNU_start_epilogue) + { +/*DEBUG */ + fputs (ASM_COMMENT_START"\t\t\t"ASM_COMMENT_START + " DW_CFA_GNU_start_epilogue\n",asm_out_file); + while (cfi->dw_cfi_next) + /* Skip to the end. */ + cfi = cfi->dw_cfi_next; + return cfi; + } + } + + /* if it's not a special case, then just emit it. */ + output_cfi (cfi, fde, for_eh); + return cfi; +} + /* Output one FDE. */ static void @@ -3613,13 +3685,13 @@ output_fde (dw_fde_ref fde, bool for_eh, bool seco fde->dw_fde_current_label = begin; if (!fde->dw_fde_switched_sections) for (cfi = fde->dw_fde_cfi; cfi != NULL; cfi = cfi->dw_cfi_next) - output_cfi (cfi, fde, for_eh); + cfi = emit_cfi_or_skip_epilogue (cfi, fde, for_eh); else if (!second) { if (fde->dw_fde_switch_cfi) for (cfi = fde->dw_fde_cfi; cfi != NULL; cfi = cfi->dw_cfi_next) { - output_cfi (cfi, fde, for_eh); + cfi = emit_cfi_or_skip_epilogue (cfi, fde, for_eh); if (cfi == fde->dw_fde_switch_cfi) break; } @@ -3636,7 +3707,7 @@ output_fde (dw_fde_ref fde, bool for_eh, bool seco fde->dw_fde_switch_cfi->dw_cfi_next = cfi_next; } for (cfi = cfi_next; cfi != NULL; cfi = cfi->dw_cfi_next) - output_cfi (cfi, fde, for_eh); + cfi = emit_cfi_or_skip_epilogue (cfi, fde, for_eh); } /* If we are to emit a ref/link from function bodies to their frame tables, Index: gcc/target.def =================================================================== --- gcc/target.def (revision 163221) +++ gcc/target.def (working copy) @@ -390,6 +406,15 @@ DEFHOOK void, (FILE *file, int size, rtx x), NULL) +/* Targets might not need epilogue information in dwarf2 _eh frames. This + hook should return true if the epilogue should be suppressed in such frames. + Epilogues will still be emitted in _debug_frames. */ +DEFHOOK_UNDOC +(suppress_eh_epilogue_p, + "", + bool, (void), + hook_bool_void_false) + /* Some target machines need to postscan each insn after it is output. */ DEFHOOK (final_postscan_insn, Index: gcc/config/darwin-protos.h =================================================================== --- gcc/config/darwin-protos.h (revision 163221) +++ gcc/config/darwin-protos.h (working copy) @@ -83,10 +84,15 @@ extern tree darwin_handle_weak_import_attribute (t extern void machopic_output_stub (FILE *, const char *, const char *); extern void darwin_globalize_label (FILE *, const char *); extern void darwin_assemble_visibility (tree, int); + +extern bool darwin_asm_suppress_eh_epilogue_p (void); +extern void darwin_asm_output_dwarf_section_start_label (FILE *file, + section *sect); extern void darwin_asm_output_dwarf_delta (FILE *, int, const char *, const char *); extern void darwin_asm_output_dwarf_offset (FILE *, int, const char *, section *); + extern void darwin_asm_declare_constant_name (FILE *, const char *, const_tree, HOST_WIDE_INT); extern bool darwin_binds_local_p (const_tree); Index: gcc/config/darwin.h =================================================================== --- gcc/config/darwin.h (revision 163221) +++ gcc/config/darwin.h (working copy) @@ -669,7 +675,6 @@ extern GTY(()) int darwin_ms_struct; Make Objective-C internal symbols local and in doing this, we need to accommodate the name mangling done by c++ on file scope locals. */ - int darwin_label_is_anonymous_local_objc_name (const char *name); #undef ASM_OUTPUT_LABELREF @@ -927,6 +932,16 @@ enum machopic_addr_class { ? (DW_EH_PE_pcrel | DW_EH_PE_indirect | DW_EH_PE_sdata4) : \ ((CODE) == 1 || (GLOBAL) == 0) ? DW_EH_PE_pcrel : DW_EH_PE_absptr) +/* Mark the start of each dwarf debug section to allow us to compute local + offsets within the sections. We do this in darwin, rather than emitting + relocs. */ +#define TARGET_ASM_OUTPUT_DWARF_SECTION_START_LABEL \ + darwin_asm_output_dwarf_section_start_label + +/* For OSX compatibility we do not want to emit epilogues in _eh frames. */ +#define TARGET_ASM_SUPPRESS_EH_EPILOGUE_P \ + darwin_asm_suppress_eh_epilogue_p + #define ASM_OUTPUT_DWARF_DELTA(FILE,SIZE,LABEL1,LABEL2) \ darwin_asm_output_dwarf_delta (FILE, SIZE, LABEL1, LABEL2) Index: gcc/config/darwin.c =================================================================== --- gcc/config/darwin.c (revision 163221) +++ gcc/config/darwin.c (working copy) @@ -1666,6 +1666,36 @@ darwin_assemble_visibility (tree decl, int vis) "not supported in this configuration; ignored"); } +/* For compatibility with OSX versions that do not emit epilogues in _eh + frames we suppress them. This is made a predicate function to permit + us to add an OSX/FSF compatibility switch should that be required. */ + +bool +darwin_asm_suppress_eh_epilogue_p (void) +{ + return true; +} + +/* So that we can compute dwarf offsets within sections, we emit a known + section marker at the begining of the section. This is distinct from + the ones emitted by dwarf2out. The label is constructed by extracting + sectname from __DWARF,__sectname,etc,etc. The hook should be invoked + once, after the first switch to the section. */ + +void +darwin_asm_output_dwarf_section_start_label (FILE *file, section *sect) +{ + const char *dnam; + int namelen; + gcc_assert (sect && (sect->common.flags & (SECTION_NAMED|SECTION_DEBUG))); + dnam = ((struct named_section *)sect)->name; + gcc_assert (strncmp (dnam, "__DWARF,", 8) == 0); + gcc_assert (strchr (dnam + 8, ',')); + + namelen = strchr (dnam + 8, ',') - (dnam + 8); + fprintf (file, "Lsection%.*s:\n", namelen, dnam + 8); +} + /* Output a difference of two labels that will be an assembly time constant if the two labels are local. (.long lab1-lab2 will be very different if lab1 is at the boundary between two sections; it