--- config/arm/arm.c | 5 config/ia64/ia64.c | 6 config/sparc/sparc.c | 7 config/vax/vax.c | 2 dwarf2out.c | 467 ++++++++++++++++++++++++--------------------------- dwarf2out.h | 32 +++ final.c | 5 target.def | 2 tree.h | 31 --- 9 files changed, 270 insertions(+), 287 deletions(-) Index: gcc/config/arm/arm.c =================================================================== --- gcc.orig/config/arm/arm.c +++ gcc/config/arm/arm.c @@ -19977,18 +19977,19 @@ thumb_pushpop (FILE *f, unsigned long ma if (push && pushed_words && dwarf2out_do_frame ()) { - char *l = dwarf2out_cfi_label (false); int pushed_mask = real_regs; + dwarf2out_maybe_emit_cfi_label (); + *cfa_offset += pushed_words * 4; - dwarf2out_def_cfa (l, SP_REGNUM, *cfa_offset); + dwarf2out_def_cfa (SP_REGNUM, *cfa_offset); pushed_words = 0; pushed_mask = real_regs; for (regno = 0; regno <= 14; regno++, pushed_mask >>= 1) { if (pushed_mask & 1) - dwarf2out_reg_save (l, regno, 4 * pushed_words++ - *cfa_offset); + dwarf2out_reg_save (regno, 4 * pushed_words++ - *cfa_offset); } } } @@ -20997,10 +20998,9 @@ thumb1_output_function_prologue (FILE *f the stack pointer. */ if (dwarf2out_do_frame ()) { - char *l = dwarf2out_cfi_label (false); - + dwarf2out_maybe_emit_cfi_label (); cfa_offset = cfa_offset + crtl->args.pretend_args_size; - dwarf2out_def_cfa (l, SP_REGNUM, cfa_offset); + dwarf2out_def_cfa (SP_REGNUM, cfa_offset); } } @@ -21046,10 +21046,10 @@ thumb1_output_function_prologue (FILE *f if (dwarf2out_do_frame ()) { - char *l = dwarf2out_cfi_label (false); + dwarf2out_maybe_emit_cfi_label (); cfa_offset = cfa_offset + 16; - dwarf2out_def_cfa (l, SP_REGNUM, cfa_offset); + dwarf2out_def_cfa (SP_REGNUM, cfa_offset); } if (l_mask) @@ -22749,7 +22749,7 @@ arm_except_unwind_info (struct gcc_optio stack alignment. */ static void -arm_dwarf_handle_frame_unspec (const char *label, rtx pattern, int index) +arm_dwarf_handle_frame_unspec (rtx pattern, int index) { rtx unspec = SET_SRC (pattern); gcc_assert (GET_CODE (unspec) == UNSPEC); @@ -22760,8 +22760,7 @@ arm_dwarf_handle_frame_unspec (const cha /* ??? We should set the CFA = (SP & ~7). At this point we haven't put anything on the stack, so hopefully it won't matter. CFA = SP will be correct after alignment. */ - dwarf2out_reg_save_reg (label, stack_pointer_rtx, - SET_DEST (pattern)); + dwarf2out_reg_save_reg (stack_pointer_rtx, SET_DEST (pattern)); break; default: gcc_unreachable (); Index: gcc/config/ia64/ia64.c =================================================================== --- gcc.orig/config/ia64/ia64.c +++ gcc/config/ia64/ia64.c @@ -330,7 +330,7 @@ static enum machine_mode ia64_promote_fu static void ia64_trampoline_init (rtx, tree, rtx); static void ia64_override_options_after_change (void); -static void ia64_dwarf_handle_frame_unspec (const char *, rtx, int); +static void ia64_dwarf_handle_frame_unspec (rtx, int); static tree ia64_builtin_decl (unsigned, bool); static reg_class_t ia64_preferred_reload_class (rtx, reg_class_t); @@ -9710,9 +9710,7 @@ ia64_dwarf2out_def_steady_cfa (rtx insn, processing. The real CFA definition is set up above. */ static void -ia64_dwarf_handle_frame_unspec (const char * ARG_UNUSED (label), - rtx ARG_UNUSED (pattern), - int index) +ia64_dwarf_handle_frame_unspec (rtx ARG_UNUSED (pattern), int index) { gcc_assert (index == UNSPECV_ALLOC); } Index: gcc/config/sparc/sparc.c =================================================================== --- gcc.orig/config/sparc/sparc.c +++ gcc/config/sparc/sparc.c @@ -454,7 +454,7 @@ static unsigned int sparc_function_arg_b const_tree); static int sparc_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, tree, bool); -static void sparc_dwarf_handle_frame_unspec (const char *, rtx, int); +static void sparc_dwarf_handle_frame_unspec (rtx, int); static void sparc_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED; static void sparc_file_end (void); static bool sparc_frame_pointer_required (void); @@ -9423,12 +9423,11 @@ get_some_local_dynamic_name_1 (rtx *px, This is called from dwarf2out.c to emit call frame instructions for frame-related insns containing UNSPECs and UNSPEC_VOLATILEs. */ static void -sparc_dwarf_handle_frame_unspec (const char *label, - rtx pattern ATTRIBUTE_UNUSED, +sparc_dwarf_handle_frame_unspec (rtx pattern ATTRIBUTE_UNUSED, int index ATTRIBUTE_UNUSED) { gcc_assert (index == UNSPECV_SAVEW); - dwarf2out_window_save (label); + dwarf2out_window_save (); } /* This is called from dwarf2out.c via TARGET_ASM_OUTPUT_DWARF_DTPREL. Index: gcc/config/vax/vax.c =================================================================== --- gcc.orig/config/vax/vax.c +++ gcc/config/vax/vax.c @@ -163,17 +163,18 @@ vax_output_function_prologue (FILE * fil if (dwarf2out_do_frame ()) { - const char *label = dwarf2out_cfi_label (false); int offset = 0; + dwarf2out_maybe_emit_cfi_label (); + for (regno = FIRST_PSEUDO_REGISTER-1; regno >= 0; --regno) if (df_regs_ever_live_p (regno) && !call_used_regs[regno]) - dwarf2out_reg_save (label, regno, offset -= 4); + dwarf2out_reg_save (regno, offset -= 4); - dwarf2out_reg_save (label, PC_REGNUM, offset -= 4); - dwarf2out_reg_save (label, FRAME_POINTER_REGNUM, offset -= 4); - dwarf2out_reg_save (label, ARG_POINTER_REGNUM, offset -= 4); - dwarf2out_def_cfa (label, FRAME_POINTER_REGNUM, -(offset - 4)); + dwarf2out_reg_save (PC_REGNUM, offset -= 4); + dwarf2out_reg_save (FRAME_POINTER_REGNUM, offset -= 4); + dwarf2out_reg_save (ARG_POINTER_REGNUM, offset -= 4); + dwarf2out_def_cfa (false, FRAME_POINTER_REGNUM, -(offset - 4)); } size -= STARTING_FRAME_OFFSET; Index: gcc/dwarf2out.c =================================================================== --- gcc.orig/dwarf2out.c +++ gcc/dwarf2out.c @@ -456,11 +456,11 @@ static GTY(()) section *cold_text_sectio static char *stripattributes (const char *); static const char *dwarf_cfi_name (unsigned); static dw_cfi_ref new_cfi (void); -static void add_cfi (cfi_vec *, dw_cfi_ref); -static void add_fde_cfi (const char *, dw_cfi_ref); +static void add_fde_cfi (dw_cfi_ref); +static void add_cie_cfi (dw_cfi_ref); static void lookup_cfa_1 (dw_cfi_ref, dw_cfa_location *, dw_cfa_location *); static void lookup_cfa (dw_cfa_location *); -static void reg_save (const char *, unsigned, unsigned, HOST_WIDE_INT); +static void reg_save (bool, unsigned, unsigned, HOST_WIDE_INT); static void initial_return_save (rtx); static HOST_WIDE_INT stack_adjust_offset (const_rtx, HOST_WIDE_INT, HOST_WIDE_INT); @@ -469,7 +469,7 @@ static void output_cfi_directive (dw_cfi static void output_call_frame_info (int); static void dwarf2out_note_section_used (void); static bool clobbers_queued_reg_save (const_rtx); -static void dwarf2out_frame_debug_expr (rtx, const char *); +static void dwarf2out_frame_debug_expr (rtx); static void dwarf2out_cfi_begin_epilogue (rtx); static void dwarf2out_frame_debug_restore_state (void); @@ -482,7 +482,7 @@ static struct dw_loc_descr_struct *build (dw_cfa_location *, HOST_WIDE_INT); static struct dw_loc_descr_struct *build_cfa_aligned_loc (HOST_WIDE_INT, HOST_WIDE_INT); -static void def_cfa_1 (const char *, dw_cfa_location *); +static void def_cfa_1 (bool, dw_cfa_location *); static struct dw_loc_descr_struct *mem_loc_descriptor (rtx, enum machine_mode mode, enum var_init_status); @@ -820,35 +820,6 @@ new_cfi (void) return cfi; } -/* Add a Call Frame Instruction to list of instructions. */ - -static inline void -add_cfi (cfi_vec *vec, dw_cfi_ref cfi) -{ - dw_fde_ref fde = current_fde (); - - /* When DRAP is used, CFA is defined with an expression. Redefine - CFA may lead to a different CFA value. */ - /* ??? Of course, this heuristic fails when we're annotating epilogues, - because of course we'll always want to redefine the CFA back to the - stack pointer on the way out. Where should we move this check? */ - if (0 && fde && fde->drap_reg != INVALID_REGNUM) - switch (cfi->dw_cfi_opc) - { - case DW_CFA_def_cfa_register: - case DW_CFA_def_cfa_offset: - case DW_CFA_def_cfa_offset_sf: - case DW_CFA_def_cfa: - case DW_CFA_def_cfa_sf: - gcc_unreachable (); - - default: - break; - } - - VEC_safe_push (dw_cfi_ref, gc, *vec, cfi); -} - /* The insn after which a new CFI note should be emitted. */ static rtx cfi_insn; @@ -858,45 +829,51 @@ static bool emit_cfa_remember; /* True if any CFI directives were emitted at the current insn. */ static bool any_cfis_emitted; -/* Generate a new label for the CFI info to refer to. FORCE is true - if a label needs to be output even when using .cfi_* directives. */ +/* Generate a new label for the CFI info to refer to. */ -char * -dwarf2out_cfi_label (bool force) +static char * +dwarf2out_cfi_label (void) { static char label[20]; - if (!force && dwarf2out_do_cfi_asm ()) - { - /* In this case, we will be emitting the asm directive instead of - the label, so just return a placeholder to keep the rest of the - interfaces happy. */ - strcpy (label, ""); - } - else - { - int num = dwarf2out_cfi_label_num++; - ASM_GENERATE_INTERNAL_LABEL (label, "LCFI", num); - cfi_insn = emit_note_after (NOTE_INSN_CFI_LABEL, cfi_insn); - NOTE_LABEL_NUMBER (cfi_insn) = num; - } + int num = dwarf2out_cfi_label_num++; + ASM_GENERATE_INTERNAL_LABEL (label, "LCFI", num); return label; } +/* Called by target specific code if it wants to emit CFI insns in the text + prologue. If necessary, emit a CFI label and an advance_loc CFI. See + also cfi_label_required_p. */ +void +dwarf2out_maybe_emit_cfi_label (void) +{ + if ((dwarf_version == 2 + && debug_info_level > DINFO_LEVEL_TERSE + && (write_symbols == DWARF2_DEBUG + || write_symbols == VMS_AND_DWARF2_DEBUG)) + || !dwarf2out_do_cfi_asm ()) + { + const char *l; + dw_cfi_ref xcfi; + + ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LCFI", dwarf2out_cfi_label_num); + l = dwarf2out_cfi_label (); + l = xstrdup (l); + + xcfi = new_cfi (); + xcfi->dw_cfi_opc = DW_CFA_advance_loc4; + xcfi->dw_cfi_oprnd1.dw_cfi_addr = l; + add_fde_cfi (xcfi); + } +} + /* Add CFI to the current fde at the PC value indicated by LABEL if specified, or to the CIE if LABEL is NULL. */ static void -add_fde_cfi (const char *label, dw_cfi_ref cfi) +add_fde_cfi (dw_cfi_ref cfi) { - cfi_vec *vec; - - if (cie_cfi_vec == NULL) - cie_cfi_vec = VEC_alloc (dw_cfi_ref, gc, 20); - - vec = &cie_cfi_vec; - if (emit_cfa_remember) { dw_cfi_ref cfi_remember; @@ -905,110 +882,30 @@ add_fde_cfi (const char *label, dw_cfi_r emit_cfa_remember = false; cfi_remember = new_cfi (); cfi_remember->dw_cfi_opc = DW_CFA_remember_state; - add_fde_cfi (label, cfi_remember); + add_fde_cfi (cfi_remember); } - if (dwarf2out_do_cfi_asm ()) + any_cfis_emitted = true; + if (cfi_insn != NULL) { - if (label) - { - dw_fde_ref fde = current_fde (); - - gcc_assert (fde != NULL); - - /* We still have to add the cfi to the list so that lookup_cfa - works later on. When -g2 and above we even need to force - emitting of CFI labels and add to list a DW_CFA_set_loc for - convert_cfa_to_fb_loc_list purposes. If we're generating - DWARF3 output we use DW_OP_call_frame_cfa and so don't use - convert_cfa_to_fb_loc_list. */ - if (dwarf_version == 2 - && debug_info_level > DINFO_LEVEL_TERSE - && (write_symbols == DWARF2_DEBUG - || write_symbols == VMS_AND_DWARF2_DEBUG)) - { - switch (cfi->dw_cfi_opc) - { - case DW_CFA_def_cfa_offset: - case DW_CFA_def_cfa_offset_sf: - case DW_CFA_def_cfa_register: - case DW_CFA_def_cfa: - case DW_CFA_def_cfa_sf: - case DW_CFA_def_cfa_expression: - case DW_CFA_restore_state: - if (*label == 0 || strcmp (label, "") == 0) - label = dwarf2out_cfi_label (true); - - if (fde->dw_fde_current_label == NULL - || strcmp (label, fde->dw_fde_current_label) != 0) - { - dw_cfi_ref xcfi; - - label = xstrdup (label); - - /* Set the location counter to the new label. */ - xcfi = new_cfi (); - /* It doesn't metter whether DW_CFA_set_loc - or DW_CFA_advance_loc4 is added here, those aren't - emitted into assembly, only looked up by - convert_cfa_to_fb_loc_list. */ - xcfi->dw_cfi_opc = DW_CFA_set_loc; - xcfi->dw_cfi_oprnd1.dw_cfi_addr = label; - add_cfi (&fde->dw_fde_cfi, xcfi); - fde->dw_fde_current_label = label; - } - break; - default: - break; - } - } - - cfi_insn = emit_note_after (NOTE_INSN_CFI, cfi_insn); - NOTE_CFI (cfi_insn) = cfi; - - vec = &fde->dw_fde_cfi; - any_cfis_emitted = true; - } - /* ??? If this is a CFI for the CIE, we don't emit. This - assumes that the standard CIE contents that the assembler - uses matches the standard CIE contents that the compiler - uses. This is probably a bad assumption. I'm not quite - sure how to address this for now. */ + cfi_insn = emit_note_after (NOTE_INSN_CFI, cfi_insn); + NOTE_CFI (cfi_insn) = cfi; } - else if (label) + else { dw_fde_ref fde = current_fde (); - - gcc_assert (fde != NULL); - - if (*label == 0) - label = dwarf2out_cfi_label (false); - - if (fde->dw_fde_current_label == NULL - || strcmp (label, fde->dw_fde_current_label) != 0) - { - dw_cfi_ref xcfi; - - label = xstrdup (label); - - /* Set the location counter to the new label. */ - xcfi = new_cfi (); - /* If we have a current label, advance from there, otherwise - set the location directly using set_loc. */ - xcfi->dw_cfi_opc = fde->dw_fde_current_label - ? DW_CFA_advance_loc4 - : DW_CFA_set_loc; - xcfi->dw_cfi_oprnd1.dw_cfi_addr = label; - add_cfi (&fde->dw_fde_cfi, xcfi); - - fde->dw_fde_current_label = label; - } - - vec = &fde->dw_fde_cfi; - any_cfis_emitted = true; + VEC_safe_push (dw_cfi_ref, gc, fde->dw_fde_cfi, cfi); + dwarf2out_emit_cfi (cfi); } +} + +static void +add_cie_cfi (dw_cfi_ref cfi) +{ + if (cie_cfi_vec == NULL) + cie_cfi_vec = VEC_alloc (dw_cfi_ref, gc, 20); - add_cfi (vec, cfi); + VEC_safe_push (dw_cfi_ref, gc, cie_cfi_vec, cfi); } /* Subroutine of lookup_cfa. */ @@ -1076,6 +973,9 @@ lookup_cfa (dw_cfa_location *loc) /* The current rule for calculating the DWARF2 canonical frame address. */ static dw_cfa_location cfa; +/* A copy of CFA, for comparison purposes */ +static dw_cfa_location old_cfa; + /* The register used for saving registers to the stack, and its offset from the CFA. */ static dw_cfa_location cfa_store; @@ -1083,25 +983,27 @@ static dw_cfa_location cfa_store; /* The current save location around an epilogue. */ static dw_cfa_location cfa_remember; +/* Like cfa_remember, but a copy of old_cfa. */ +static dw_cfa_location old_cfa_remember; + /* The running total of the size of arguments pushed onto the stack. */ static HOST_WIDE_INT args_size; /* The last args_size we actually output. */ static HOST_WIDE_INT old_args_size; -/* Entry point to update the canonical frame address (CFA). - LABEL is passed to add_fde_cfi. The value of CFA is now to be - calculated from REG+OFFSET. */ +/* Entry point to update the canonical frame address (CFA). The value + of CFA is now to be calculated from REG+OFFSET. */ void -dwarf2out_def_cfa (const char *label, unsigned int reg, HOST_WIDE_INT offset) +dwarf2out_def_cfa (bool for_cie, unsigned int reg, HOST_WIDE_INT offset) { dw_cfa_location loc; loc.indirect = 0; loc.base_offset = 0; loc.reg = reg; loc.offset = offset; - def_cfa_1 (label, &loc); + def_cfa_1 (for_cie, &loc); } /* Determine if two dw_cfa_location structures define the same data. */ @@ -1120,10 +1022,10 @@ cfa_equal_p (const dw_cfa_location *loc1 the dw_cfa_location structure. */ static void -def_cfa_1 (const char *label, dw_cfa_location *loc_p) +def_cfa_1 (bool for_cie, dw_cfa_location *loc_p) { dw_cfi_ref cfi; - dw_cfa_location old_cfa, loc; + dw_cfa_location loc; cfa = *loc_p; loc = *loc_p; @@ -1132,7 +1034,6 @@ def_cfa_1 (const char *label, dw_cfa_loc cfa_store.offset = loc.offset; loc.reg = DWARF_FRAME_REGNUM (loc.reg); - lookup_cfa (&old_cfa); /* If nothing changed, no need to issue any call frame instructions. */ if (cfa_equal_p (&loc, &old_cfa)) @@ -1193,16 +1094,19 @@ def_cfa_1 (const char *label, dw_cfa_loc cfi->dw_cfi_oprnd1.dw_cfi_loc = loc_list; } - add_fde_cfi (label, cfi); + if (for_cie) + add_cie_cfi (cfi); + else + add_fde_cfi (cfi); + old_cfa = loc; } /* Add the CFI for saving a register. REG is the CFA column number. - LABEL is passed to add_fde_cfi. If SREG is -1, the register is saved at OFFSET from the CFA; otherwise it is saved in SREG. */ static void -reg_save (const char *label, unsigned int reg, unsigned int sreg, HOST_WIDE_INT offset) +reg_save (bool for_cie, unsigned int reg, unsigned int sreg, HOST_WIDE_INT offset) { dw_cfi_ref cfi = new_cfi (); dw_fde_ref fde = current_fde (); @@ -1238,10 +1142,13 @@ reg_save (const char *label, unsigned in cfi->dw_cfi_oprnd2.dw_cfi_reg_num = sreg; } - add_fde_cfi (label, cfi); + if (for_cie) + add_cie_cfi (cfi); + else + add_fde_cfi (cfi); } -/* Add the CFI for saving a register window. LABEL is passed to reg_save. +/* Add the CFI for saving a register window. This CFI tells the unwinder that it needs to restore the window registers from the previous frame's window save area. @@ -1249,39 +1156,39 @@ reg_save (const char *label, unsigned in assuming 0(cfa)) and what registers are in the window. */ void -dwarf2out_window_save (const char *label) +dwarf2out_window_save (void) { dw_cfi_ref cfi = new_cfi (); cfi->dw_cfi_opc = DW_CFA_GNU_window_save; - add_fde_cfi (label, cfi); + add_fde_cfi (cfi); } /* Entry point for saving a register to the stack. REG is the GCC register number. LABEL and OFFSET are passed to reg_save. */ void -dwarf2out_reg_save (const char *label, unsigned int reg, HOST_WIDE_INT offset) +dwarf2out_reg_save (unsigned int reg, HOST_WIDE_INT offset) { - reg_save (label, DWARF_FRAME_REGNUM (reg), INVALID_REGNUM, offset); + reg_save (false, DWARF_FRAME_REGNUM (reg), INVALID_REGNUM, offset); } /* Entry point for saving the return address in the stack. LABEL and OFFSET are passed to reg_save. */ void -dwarf2out_return_save (const char *label, HOST_WIDE_INT offset) +dwarf2out_return_save (HOST_WIDE_INT offset) { - reg_save (label, DWARF_FRAME_RETURN_COLUMN, INVALID_REGNUM, offset); + reg_save (false, DWARF_FRAME_RETURN_COLUMN, INVALID_REGNUM, offset); } /* Entry point for saving the return address in a register. LABEL and SREG are passed to reg_save. */ void -dwarf2out_return_reg (const char *label, unsigned int sreg) +dwarf2out_return_reg (unsigned int sreg) { - reg_save (label, DWARF_FRAME_RETURN_COLUMN, DWARF_FRAME_REGNUM (sreg), 0); + reg_save (false, DWARF_FRAME_RETURN_COLUMN, DWARF_FRAME_REGNUM (sreg), 0); } /* Record the initial position of the return address. RTL is @@ -1339,7 +1246,7 @@ initial_return_save (rtx rtl) } if (reg != DWARF_FRAME_RETURN_COLUMN) - reg_save (NULL, DWARF_FRAME_RETURN_COLUMN, reg, offset - cfa.offset); + reg_save (true, DWARF_FRAME_RETURN_COLUMN, reg, offset - cfa.offset); } /* Given a SET, calculate the amount of stack adjustment it @@ -1609,7 +1516,7 @@ compute_barrier_args_size (void) pushed onto the stack. */ static void -dwarf2out_args_size (const char *label, HOST_WIDE_INT size) +dwarf2out_args_size (HOST_WIDE_INT size) { dw_cfi_ref cfi; @@ -1621,13 +1528,13 @@ dwarf2out_args_size (const char *label, cfi = new_cfi (); cfi->dw_cfi_opc = DW_CFA_GNU_args_size; cfi->dw_cfi_oprnd1.dw_cfi_offset = size; - add_fde_cfi (label, cfi); + add_fde_cfi (cfi); } /* Record a stack adjustment of OFFSET bytes. */ static void -dwarf2out_stack_adjust (HOST_WIDE_INT offset, const char *label) +dwarf2out_stack_adjust (HOST_WIDE_INT offset) { if (cfa.reg == STACK_POINTER_REGNUM) cfa.offset += offset; @@ -1646,9 +1553,9 @@ dwarf2out_stack_adjust (HOST_WIDE_INT of if (args_size < 0) args_size = 0; - def_cfa_1 (label, &cfa); + def_cfa_1 (false, &cfa); if (flag_asynchronous_unwind_tables) - dwarf2out_args_size (label, args_size); + dwarf2out_args_size (args_size); } /* Check INSN to see if it looks like a push or a stack adjustment, and @@ -1659,7 +1566,6 @@ static void dwarf2out_notice_stack_adjust (rtx insn, bool after_p) { HOST_WIDE_INT offset; - const char *label; int i; /* Don't handle epilogues at all. Certainly it would be wrong to do so @@ -1690,7 +1596,7 @@ dwarf2out_notice_stack_adjust (rtx insn, if (GET_CODE (insn) == SET) insn = SET_SRC (insn); gcc_assert (GET_CODE (insn) == CALL); - dwarf2out_args_size ("", INTVAL (XEXP (insn, 1))); + dwarf2out_args_size (INTVAL (XEXP (insn, 1))); } return; } @@ -1698,7 +1604,7 @@ dwarf2out_notice_stack_adjust (rtx insn, if (CALL_P (insn) && !after_p) { if (!flag_asynchronous_unwind_tables) - dwarf2out_args_size ("", args_size); + dwarf2out_args_size (args_size); return; } else if (BARRIER_P (insn)) @@ -1739,8 +1645,7 @@ dwarf2out_notice_stack_adjust (rtx insn, if (offset == 0) return; - label = dwarf2out_cfi_label (false); - dwarf2out_stack_adjust (offset, label); + dwarf2out_stack_adjust (offset); } /* We delay emitting a register save until either (a) we reach the end @@ -1769,13 +1674,11 @@ struct GTY(()) reg_saved_in_data { static GTY(()) struct reg_saved_in_data regs_saved_in_regs[4]; static GTY(()) size_t num_regs_saved_in_regs; -static const char *last_reg_save_label; - /* Add an entry to QUEUED_REG_SAVES saying that REG is now saved at SREG, or if SREG is NULL then it is saved at OFFSET to the CFA. */ static void -queue_reg_save (const char *label, rtx reg, rtx sreg, HOST_WIDE_INT offset) +queue_reg_save (rtx reg, rtx sreg, HOST_WIDE_INT offset) { struct queued_reg_save *q; @@ -1796,8 +1699,6 @@ queue_reg_save (const char *label, rtx r q->reg = reg; q->cfa_offset = offset; q->saved_reg = sreg; - - last_reg_save_label = label; } /* Output all the entries in QUEUED_REG_SAVES. */ @@ -1831,11 +1732,10 @@ dwarf2out_flush_queued_reg_saves (void) sreg = DWARF_FRAME_REGNUM (REGNO (q->saved_reg)); else sreg = INVALID_REGNUM; - reg_save (last_reg_save_label, reg, sreg, q->cfa_offset); + reg_save (false, reg, sreg, q->cfa_offset); } queued_reg_saves = NULL; - last_reg_save_label = NULL; } /* Does INSN clobber any register which QUEUED_REG_SAVES lists a saved @@ -1865,7 +1765,7 @@ clobbers_queued_reg_save (const_rtx insn /* Entry point for saving the first register into the second. */ void -dwarf2out_reg_save_reg (const char *label, rtx reg, rtx sreg) +dwarf2out_reg_save_reg (rtx reg, rtx sreg) { size_t i; unsigned int regno, sregno; @@ -1883,7 +1783,7 @@ dwarf2out_reg_save_reg (const char *labe regno = DWARF_FRAME_REGNUM (REGNO (reg)); sregno = DWARF_FRAME_REGNUM (REGNO (sreg)); - reg_save (label, regno, sregno, 0); + reg_save (false, regno, sregno, 0); } /* What register, if any, is currently saved in REG? */ @@ -1916,7 +1816,7 @@ static dw_cfa_location cfa_temp; /* A subroutine of dwarf2out_frame_debug, process a REG_DEF_CFA note. */ static void -dwarf2out_frame_debug_def_cfa (rtx pat, const char *label) +dwarf2out_frame_debug_def_cfa (rtx pat) { memset (&cfa, 0, sizeof (cfa)); @@ -1947,13 +1847,13 @@ dwarf2out_frame_debug_def_cfa (rtx pat, gcc_unreachable (); } - def_cfa_1 (label, &cfa); + def_cfa_1 (false, &cfa); } /* A subroutine of dwarf2out_frame_debug, process a REG_ADJUST_CFA note. */ static void -dwarf2out_frame_debug_adjust_cfa (rtx pat, const char *label) +dwarf2out_frame_debug_adjust_cfa (rtx pat) { rtx src, dest; @@ -1978,13 +1878,13 @@ dwarf2out_frame_debug_adjust_cfa (rtx pa cfa.reg = REGNO (dest); gcc_assert (cfa.indirect == 0); - def_cfa_1 (label, &cfa); + def_cfa_1 (false, &cfa); } /* A subroutine of dwarf2out_frame_debug, process a REG_CFA_OFFSET note. */ static void -dwarf2out_frame_debug_cfa_offset (rtx set, const char *label) +dwarf2out_frame_debug_cfa_offset (rtx set) { HOST_WIDE_INT offset; rtx src, addr, span; @@ -2014,7 +1914,7 @@ dwarf2out_frame_debug_cfa_offset (rtx se /* ??? We'd like to use queue_reg_save, but we need to come up with a different flushing heuristic for epilogues. */ if (!span) - reg_save (label, DWARF_FRAME_REGNUM (REGNO (src)), INVALID_REGNUM, offset); + reg_save (false, DWARF_FRAME_REGNUM (REGNO (src)), INVALID_REGNUM, offset); else { /* We have a PARALLEL describing where the contents of SRC live. @@ -2030,7 +1930,7 @@ dwarf2out_frame_debug_cfa_offset (rtx se { rtx elem = XVECEXP (span, 0, par_index); - reg_save (label, DWARF_FRAME_REGNUM (REGNO (elem)), + reg_save (false, DWARF_FRAME_REGNUM (REGNO (elem)), INVALID_REGNUM, span_offset); span_offset += GET_MODE_SIZE (GET_MODE (elem)); } @@ -2040,7 +1940,7 @@ dwarf2out_frame_debug_cfa_offset (rtx se /* A subroutine of dwarf2out_frame_debug, process a REG_CFA_REGISTER note. */ static void -dwarf2out_frame_debug_cfa_register (rtx set, const char *label) +dwarf2out_frame_debug_cfa_register (rtx set) { rtx src, dest; unsigned sregno, dregno; @@ -2057,13 +1957,13 @@ dwarf2out_frame_debug_cfa_register (rtx /* ??? We'd like to use queue_reg_save, but we need to come up with a different flushing heuristic for epilogues. */ - reg_save (label, sregno, dregno, 0); + reg_save (false, sregno, dregno, 0); } /* A subroutine of dwarf2out_frame_debug, process a REG_CFA_EXPRESSION note. */ static void -dwarf2out_frame_debug_cfa_expression (rtx set, const char *label) +dwarf2out_frame_debug_cfa_expression (rtx set) { rtx src, dest, span; dw_cfi_ref cfi = new_cfi (); @@ -2085,13 +1985,13 @@ dwarf2out_frame_debug_cfa_expression (rt /* ??? We'd like to use queue_reg_save, were the interface different, and, as above, we could manage flushing for epilogues. */ - add_fde_cfi (label, cfi); + add_fde_cfi (cfi); } /* A subroutine of dwarf2out_frame_debug, process a REG_CFA_RESTORE note. */ static void -dwarf2out_frame_debug_cfa_restore (rtx reg, const char *label) +dwarf2out_frame_debug_cfa_restore (rtx reg) { dw_cfi_ref cfi = new_cfi (); unsigned int regno = DWARF_FRAME_REGNUM (REGNO (reg)); @@ -2099,7 +1999,102 @@ dwarf2out_frame_debug_cfa_restore (rtx r cfi->dw_cfi_opc = (regno & ~0x3f ? DW_CFA_restore_extended : DW_CFA_restore); cfi->dw_cfi_oprnd1.dw_cfi_reg_num = regno; - add_fde_cfi (label, cfi); + add_fde_cfi (cfi); +} + +/* Examine CFI and return true if a cfi label and set_loc is needed before + it. Even when generating CFI assembler instructions, we still have to + add the cfi to the list so that lookup_cfa works later on. When + -g2 and above we even need to force emitting of CFI labels and add + to list a DW_CFA_set_loc for convert_cfa_to_fb_loc_list purposes. + If we're generating DWARF3 output we use DW_OP_call_frame_cfa and + so don't use convert_cfa_to_fb_loc_list. */ + +static bool +cfi_label_required_p (dw_cfi_ref cfi) +{ + if (!dwarf2out_do_cfi_asm ()) + return true; + + if (dwarf_version == 2 + && debug_info_level > DINFO_LEVEL_TERSE + && (write_symbols == DWARF2_DEBUG + || write_symbols == VMS_AND_DWARF2_DEBUG)) + { + switch (cfi->dw_cfi_opc) + { + case DW_CFA_def_cfa_offset: + case DW_CFA_def_cfa_offset_sf: + case DW_CFA_def_cfa_register: + case DW_CFA_def_cfa: + case DW_CFA_def_cfa_sf: + case DW_CFA_def_cfa_expression: + case DW_CFA_restore_state: + return true; + default: + return false; + } + } + return false; +} + +/* Walk the functino, looking for NOTE_INSN_CFI notes. Add the CFIs to the + function's FDE, adding CFI labels and set_loc/advance_loc opcodes as + necessary. */ +static void +add_cfis_to_fde (void) +{ + dw_fde_ref fde = current_fde (); + rtx insn, next; + /* We always start with a function_begin label. */ + bool first = false; + + for (insn = get_insns (); insn; insn = next) + { + next = NEXT_INSN (insn); + + if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS) + /* Don't attempt to advance_loc4 between labels in different + sections. */ + first = true; + + if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_CFI) + { + bool required = cfi_label_required_p (NOTE_CFI (insn)); + while (next && NOTE_P (next) && NOTE_KIND (next) == NOTE_INSN_CFI) + { + required |= cfi_label_required_p (NOTE_CFI (next)); + next = NEXT_INSN (next); + } + if (required) + { + int num = dwarf2out_cfi_label_num; + const char *label = dwarf2out_cfi_label (); + dw_cfi_ref xcfi; + rtx tmp; + + label = xstrdup (label); + + /* Set the location counter to the new label. */ + xcfi = new_cfi (); + xcfi->dw_cfi_opc = (first ? DW_CFA_set_loc + : DW_CFA_advance_loc4); + xcfi->dw_cfi_oprnd1.dw_cfi_addr = label; + VEC_safe_push (dw_cfi_ref, gc, fde->dw_fde_cfi, xcfi); + + tmp = emit_note_before (NOTE_INSN_CFI_LABEL, insn); + NOTE_LABEL_NUMBER (tmp) = num; + } + + do + { + VEC_safe_push (dw_cfi_ref, gc, fde->dw_fde_cfi, NOTE_CFI (insn)); + insn = NEXT_INSN (insn); + } + while (insn != next); + first = false; + } + } } /* Record call frame debugging information for an expression EXPR, @@ -2298,7 +2293,7 @@ dwarf2out_frame_debug_cfa_restore (rtx r cfa.reg == fde->drap_reg */ static void -dwarf2out_frame_debug_expr (rtx expr, const char *label) +dwarf2out_frame_debug_expr (rtx expr) { rtx src, dest, span; HOST_WIDE_INT offset; @@ -2327,7 +2322,7 @@ dwarf2out_frame_debug_expr (rtx expr, co if (GET_CODE (elem) == SET && MEM_P (SET_DEST (elem)) && (RTX_FRAME_RELATED_P (elem) || par_index == 0)) - dwarf2out_frame_debug_expr (elem, label); + dwarf2out_frame_debug_expr (elem); } for (par_index = 0; par_index < limit; par_index++) @@ -2336,7 +2331,7 @@ dwarf2out_frame_debug_expr (rtx expr, co if (GET_CODE (elem) == SET && (!MEM_P (SET_DEST (elem)) || GET_CODE (expr) == SEQUENCE) && (RTX_FRAME_RELATED_P (elem) || par_index == 0)) - dwarf2out_frame_debug_expr (elem, label); + dwarf2out_frame_debug_expr (elem); else if (GET_CODE (elem) == SET && par_index != 0 && !RTX_FRAME_RELATED_P (elem)) @@ -2346,7 +2341,7 @@ dwarf2out_frame_debug_expr (rtx expr, co HOST_WIDE_INT offset = stack_adjust_offset (elem, args_size, 0); if (offset != 0) - dwarf2out_stack_adjust (offset, label); + dwarf2out_stack_adjust (offset); } } return; @@ -2406,7 +2401,7 @@ dwarf2out_frame_debug_expr (rtx expr, co && fde->drap_reg != INVALID_REGNUM && cfa.reg != REGNO (src)); else - queue_reg_save (label, src, dest, 0); + queue_reg_save (src, dest, 0); } break; @@ -2536,7 +2531,7 @@ dwarf2out_frame_debug_expr (rtx expr, co case UNSPEC: case UNSPEC_VOLATILE: gcc_assert (targetm.dwarf_handle_frame_unspec); - targetm.dwarf_handle_frame_unspec (label, expr, XINT (src, 1)); + targetm.dwarf_handle_frame_unspec (expr, XINT (src, 1)); return; /* Rule 16 */ @@ -2565,7 +2560,7 @@ dwarf2out_frame_debug_expr (rtx expr, co gcc_unreachable (); } - def_cfa_1 (label, &cfa); + def_cfa_1 (false, &cfa); break; case MEM: @@ -2721,15 +2716,15 @@ dwarf2out_frame_debug_expr (rtx expr, co fde->drap_reg_saved = 1; - def_cfa_1 (label, &cfa_exp); + def_cfa_1 (false, &cfa_exp); break; } /* If the source register is exactly the CFA, assume we're saving SP like any other register; this happens on the ARM. */ - def_cfa_1 (label, &cfa); - queue_reg_save (label, stack_pointer_rtx, NULL_RTX, offset); + def_cfa_1 (false, &cfa); + queue_reg_save (stack_pointer_rtx, NULL_RTX, offset); break; } else @@ -2745,17 +2740,17 @@ dwarf2out_frame_debug_expr (rtx expr, co cfa.reg = REGNO (x); cfa.base_offset = offset; cfa.indirect = 1; - def_cfa_1 (label, &cfa); + def_cfa_1 (false, &cfa); break; } } - def_cfa_1 (label, &cfa); + def_cfa_1 (false, &cfa); { span = targetm.dwarf_register_span (src); if (!span) - queue_reg_save (label, src, NULL_RTX, offset); + queue_reg_save (src, NULL_RTX, offset); else { /* We have a PARALLEL describing where the contents of SRC @@ -2772,7 +2767,7 @@ dwarf2out_frame_debug_expr (rtx expr, co { rtx elem = XVECEXP (span, 0, par_index); - queue_reg_save (label, elem, NULL_RTX, span_offset); + queue_reg_save (elem, NULL_RTX, span_offset); span_offset += GET_MODE_SIZE (GET_MODE (elem)); } } @@ -2794,7 +2789,6 @@ dwarf2out_frame_debug_expr (rtx expr, co void dwarf2out_frame_debug (rtx insn, bool after_p) { - const char *label; rtx note, n; bool handled_one = false; @@ -2813,10 +2807,10 @@ dwarf2out_frame_debug (rtx insn, bool af is still used to save registers. */ if (!ACCUMULATE_OUTGOING_ARGS) dwarf2out_notice_stack_adjust (insn, after_p); + cfi_insn = NULL; return; } - label = dwarf2out_cfi_label (false); any_cfis_emitted = false; for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) @@ -2827,7 +2821,7 @@ dwarf2out_frame_debug (rtx insn, bool af goto found; case REG_CFA_DEF_CFA: - dwarf2out_frame_debug_def_cfa (XEXP (note, 0), label); + dwarf2out_frame_debug_def_cfa (XEXP (note, 0)); handled_one = true; break; @@ -2839,7 +2833,7 @@ dwarf2out_frame_debug (rtx insn, bool af if (GET_CODE (n) == PARALLEL) n = XVECEXP (n, 0, 0); } - dwarf2out_frame_debug_adjust_cfa (n, label); + dwarf2out_frame_debug_adjust_cfa (n); handled_one = true; break; @@ -2847,7 +2841,7 @@ dwarf2out_frame_debug (rtx insn, bool af n = XEXP (note, 0); if (n == NULL) n = single_set (insn); - dwarf2out_frame_debug_cfa_offset (n, label); + dwarf2out_frame_debug_cfa_offset (n); handled_one = true; break; @@ -2859,7 +2853,7 @@ dwarf2out_frame_debug (rtx insn, bool af if (GET_CODE (n) == PARALLEL) n = XVECEXP (n, 0, 0); } - dwarf2out_frame_debug_cfa_register (n, label); + dwarf2out_frame_debug_cfa_register (n); handled_one = true; break; @@ -2867,7 +2861,7 @@ dwarf2out_frame_debug (rtx insn, bool af n = XEXP (note, 0); if (n == NULL) n = single_set (insn); - dwarf2out_frame_debug_cfa_expression (n, label); + dwarf2out_frame_debug_cfa_expression (n); handled_one = true; break; @@ -2880,7 +2874,7 @@ dwarf2out_frame_debug (rtx insn, bool af n = XVECEXP (n, 0, 0); n = XEXP (n, 0); } - dwarf2out_frame_debug_cfa_restore (n, label); + dwarf2out_frame_debug_cfa_restore (n); handled_one = true; break; @@ -2906,18 +2900,20 @@ dwarf2out_frame_debug (rtx insn, bool af { if (any_cfis_emitted) dwarf2out_flush_queued_reg_saves (); + cfi_insn = NULL; return; } insn = PATTERN (insn); found: - dwarf2out_frame_debug_expr (insn, label); + dwarf2out_frame_debug_expr (insn); /* Check again. A parallel can save and update the same register. We could probably check just once, here, but this is safer than removing the check above. */ if (any_cfis_emitted || clobbers_queued_reg_save (insn)) dwarf2out_flush_queued_reg_saves (); + cfi_insn = NULL; } /* Called once at the start of final to initialize some data for the @@ -2926,7 +2922,6 @@ void dwarf2out_frame_debug_init (void) { size_t i; - rtx insn; /* Flush any queued register saves. */ dwarf2out_flush_queued_reg_saves (); @@ -2936,6 +2931,7 @@ dwarf2out_frame_debug_init (void) gcc_assert (cfa.reg == (unsigned long)DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM)); + old_cfa = cfa; cfa.reg = STACK_POINTER_REGNUM; cfa_store = cfa; cfa_temp.reg = -1; @@ -2947,7 +2943,15 @@ dwarf2out_frame_debug_init (void) regs_saved_in_regs[i].saved_in_reg = NULL_RTX; } num_regs_saved_in_regs = 0; +} + +/* After the (optional) text prologue has been written, emit CFI insns + and update the FDE for frame-related instructions. */ +void +dwarf2out_frame_debug_after_prologue (void) +{ + rtx insn; if (barrier_args_size) { XDELETEVEC (barrier_args_size); @@ -2973,6 +2977,7 @@ dwarf2out_frame_debug_init (void) case NOTE_INSN_CFA_RESTORE_STATE: cfi_insn = insn; dwarf2out_frame_debug_restore_state (); + cfi_insn = NULL; break; } continue; @@ -2999,12 +3004,15 @@ dwarf2out_frame_debug_init (void) ) dwarf2out_frame_debug (insn, true); } + + add_cfis_to_fde (); } void dwarf2out_emit_cfi (dw_cfi_ref cfi) { - output_cfi_directive (cfi); + if (dwarf2out_do_cfi_asm ()) + output_cfi_directive (cfi); } /* Determine if we need to save and restore CFI information around @@ -3085,23 +3093,24 @@ dwarf2out_cfi_begin_epilogue (rtx insn) /* And emulate the state save. */ gcc_assert (!cfa_remember.in_use); cfa_remember = cfa; + old_cfa_remember = old_cfa; cfa_remember.in_use = 1; } /* A "subroutine" of dwarf2out_cfi_begin_epilogue. Emit the restore required. */ -void +static void dwarf2out_frame_debug_restore_state (void) { dw_cfi_ref cfi = new_cfi (); - const char *label = dwarf2out_cfi_label (false); cfi->dw_cfi_opc = DW_CFA_restore_state; - add_fde_cfi (label, cfi); + add_fde_cfi (cfi); gcc_assert (cfa_remember.in_use); cfa = cfa_remember; + old_cfa = old_cfa_remember; cfa_remember.in_use = 0; } @@ -4296,7 +4305,8 @@ dwarf2out_frame_init (void) sake of lookup_cfa. */ /* On entry, the Canonical Frame Address is at SP. */ - dwarf2out_def_cfa (NULL, STACK_POINTER_REGNUM, INCOMING_FRAME_SP_OFFSET); + old_cfa.reg = INVALID_REGNUM; + dwarf2out_def_cfa (true, STACK_POINTER_REGNUM, INCOMING_FRAME_SP_OFFSET); if (targetm.debug_unwind_info () == UI_DWARF2 || targetm.except_unwind_info (&global_options) == UI_DWARF2) @@ -4353,10 +4363,6 @@ dwarf2out_switch_text_section (void) } have_multiple_function_sections = true; - /* Reset the current label on switching text sections, so that we - don't attempt to advance_loc4 between labels in different sections. */ - fde->dw_fde_current_label = NULL; - /* There is no need to mark used sections when not debugging. */ if (cold_text_section != NULL) dwarf2out_note_section_used (); Index: gcc/dwarf2out.h =================================================================== --- gcc.orig/dwarf2out.h +++ gcc/dwarf2out.h @@ -19,9 +19,41 @@ along with GCC; see the file COPYING3. . */ struct dw_cfi_struct; +/* In dwarf2out.c */ +/* Interface of the DWARF2 unwind info support. */ + +/* Generate a new label for the CFI info to refer to. */ + +extern void dwarf2out_maybe_emit_cfi_label (void); + +/* Entry point to update the canonical frame address (CFA). */ + +extern void dwarf2out_def_cfa (bool, unsigned, HOST_WIDE_INT); + +/* Add the CFI for saving a register window. */ + +extern void dwarf2out_window_save (void); + +/* Entry point for saving a register to the stack. */ + +extern void dwarf2out_reg_save (unsigned, HOST_WIDE_INT); + +/* Entry point for saving the return address in the stack. */ + +extern void dwarf2out_return_save (HOST_WIDE_INT); + +/* Entry point for saving the return address in a register. */ + +extern void dwarf2out_return_reg (unsigned); + +/* Entry point for saving the first register into the second. */ + +extern void dwarf2out_reg_save_reg (rtx, rtx); + extern void dwarf2out_decl (tree); extern void dwarf2out_frame_debug (rtx, bool); extern void dwarf2out_frame_debug_init (void); +extern void dwarf2out_frame_debug_after_prologue (void); extern void dwarf2out_emit_cfi (struct dw_cfi_struct *); extern void dwarf2out_flush_queued_reg_saves (void); Index: gcc/final.c =================================================================== --- gcc.orig/final.c +++ gcc/final.c @@ -1588,6 +1588,11 @@ final_start_function (rtx first ATTRIBUT /* First output the function prologue: code to set up the stack frame. */ targetm.asm_out.function_prologue (file, get_frame_size ()); +#if defined (HAVE_prologue) + if (dwarf2out_do_frame ()) + dwarf2out_frame_debug_after_prologue (); +#endif + /* If the machine represents the prologue as RTL, the profiling code must be emitted when NOTE_INSN_PROLOGUE_END is scanned. */ #ifdef HAVE_prologue Index: gcc/target.def =================================================================== --- gcc.orig/target.def +++ gcc/target.def @@ -1792,7 +1792,7 @@ DEFHOOK DEFHOOK (dwarf_handle_frame_unspec, "", - void, (const char *label, rtx pattern, int index), NULL) + void, (rtx pattern, int index), NULL) /* ??? Documenting this hook requires a GFDL license grant. */ DEFHOOK_UNDOC Index: gcc/tree.h =================================================================== --- gcc.orig/tree.h +++ gcc/tree.h @@ -5424,37 +5424,6 @@ extern tree tree_overlaps_hard_reg_set ( #endif -/* In dwarf2out.c */ -/* Interface of the DWARF2 unwind info support. */ - -/* Generate a new label for the CFI info to refer to. */ - -extern char *dwarf2out_cfi_label (bool); - -/* Entry point to update the canonical frame address (CFA). */ - -extern void dwarf2out_def_cfa (const char *, unsigned, HOST_WIDE_INT); - -/* Add the CFI for saving a register window. */ - -extern void dwarf2out_window_save (const char *); - -/* Entry point for saving a register to the stack. */ - -extern void dwarf2out_reg_save (const char *, unsigned, HOST_WIDE_INT); - -/* Entry point for saving the return address in the stack. */ - -extern void dwarf2out_return_save (const char *, HOST_WIDE_INT); - -/* Entry point for saving the return address in a register. */ - -extern void dwarf2out_return_reg (const char *, unsigned); - -/* Entry point for saving the first register into the second. */ - -extern void dwarf2out_reg_save_reg (const char *, rtx, rtx); - /* In tree-inline.c */ /* The type of a set of already-visited pointers. Functions for creating Index: gcc/doc/tm.texi =================================================================== --- gcc.orig/doc/tm.texi +++ gcc/doc/tm.texi @@ -3203,7 +3203,7 @@ someone decided it was a good idea to us terminate the stack backtrace. New ports should avoid this. @end defmac -@deftypefn {Target Hook} void TARGET_DWARF_HANDLE_FRAME_UNSPEC (const char *@var{label}, rtx @var{pattern}, int @var{index}) +@deftypefn {Target Hook} void TARGET_DWARF_HANDLE_FRAME_UNSPEC (rtx @var{pattern}, int @var{index}) This target hook allows the backend to emit frame-related insns that contain UNSPECs or UNSPEC_VOLATILEs. The DWARF 2 call frame debugging info engine will invoke it on insns of the form