diff options
-rw-r--r-- | gcc/ChangeLog | 33 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 147 | ||||
-rw-r--r-- | gcc/config/arm/arm.h | 7 | ||||
-rw-r--r-- | gcc/config/m68k/m68k.h | 3 | ||||
-rw-r--r-- | gcc/config/ns32k/ns32k.h | 3 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.h | 6 | ||||
-rw-r--r-- | gcc/dwarf2out.c | 35 | ||||
-rw-r--r-- | gcc/except.c | 10 | ||||
-rw-r--r-- | gcc/frame.c | 4 | ||||
-rw-r--r-- | gcc/frame.h | 3 | ||||
-rw-r--r-- | gcc/function.c | 6 | ||||
-rw-r--r-- | gcc/libgcc2.c | 16 | ||||
-rw-r--r-- | gcc/tm.texi | 14 |
13 files changed, 211 insertions, 76 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fddb52a..9a386b0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,36 @@ +2000-03-22 Jason Merrill <jason@casey.cygnus.com> + + * config/rs6000/rs6000.h (DWARF_FRAME_RETURN_COLUMN): Define. + * config/alpha/alpha.h (DWARF_FRAME_RETURN_COLUMN): Define. + * config/sparc/sparc.h (DWARF_FRAME_RETURN_COLUMN): Define. + * dwarf2out.c (throw_helper): Adjust. + + Implement dwarf2 exception handling for the ARM. + * config/arm/arm.h (INCOMING_RETURN_ADDR_RTX): Define. + (DWARF_FRAME_RETURN_COLUMN): Define. + * config/arm/arm.c (emit_multi_reg_push): Return rtx. Attach + REG_FRAME_RELATED_EXPR note. + (emit_sfm): Likewise. + (arm_expand_prologue): Set RTX_FRAME_RELATED_P on everything. + * dwarf2out.c (reg_save): Handle saving a register to itself. + (dwarf2out_frame_debug_expr): Handle an intermediate cfa reg. + * except.c (eh_regs): Don't use the static chain reg if it's + callee-saved. + * frame.h (frame_state): Add cfa_saved field. + * frame.c (execute_cfa_insn): Set it. + * libgcc2.c (throw_helper): Don't adjust sp if it's restored in + the epilogue. + * function.c (ARG_POINTER_CFA_OFFSET): Default to FIRST_PARM_OFFSET. + Now takes a parm. + (instantiate_virtual_regs): Adjust. + * tm.texi: Adjust. + * config/m68k/m68k.h (ARG_POINTER_CFA_OFFSET): Don't define. + * config/ns32k/ns32k.h (ARG_POINTER_CFA_OFFSET): Don't define. + * config/sparc/sparc.h (ARG_POINTER_CFA_OFFSET): Take a parm. + + * dwarf2out.c (reg_number): Refer to FIRST_PSEUDO_REGISTER. + (initial_return_save): Use DWARF_FRAME_REGNUM, not reg_number. + 2000-03-22 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> * builtins.def: New file. diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 6051cd1..3177a64 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -64,8 +64,8 @@ static int eliminate_lr2ip PARAMS ((rtx *)); static char * shift_op PARAMS ((rtx, HOST_WIDE_INT *)); static int pattern_really_clobbers_lr PARAMS ((rtx)); static int function_really_clobbers_lr PARAMS ((rtx)); -static void emit_multi_reg_push PARAMS ((int)); -static void emit_sfm PARAMS ((int, int)); +static rtx emit_multi_reg_push PARAMS ((int)); +static rtx emit_sfm PARAMS ((int, int)); static enum arm_cond_code get_arm_condition_code PARAMS ((rtx)); static int const_ok_for_op PARAMS ((HOST_WIDE_INT, enum rtx_code)); static void arm_add_gc_roots PARAMS ((void)); @@ -6268,13 +6268,20 @@ output_func_epilogue (frame_size) after_arm_reorg = 0; } -static void +/* Generate and emit an insn that we will recognize as a push_multi. + Unfortunately, since this insn does not reflect very well the actual + semantics of the operation, we need to annotate the insn for the benefit + of DWARF2 frame unwind information. */ + +static rtx emit_multi_reg_push (mask) int mask; { int num_regs = 0; int i, j; rtx par; + rtx dwarf; + rtx tmp, reg; for (i = 0; i < 16; i++) if (mask & (1 << i)) @@ -6284,20 +6291,32 @@ emit_multi_reg_push (mask) abort (); par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_regs)); + dwarf = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_regs)); + RTX_FRAME_RELATED_P (dwarf) = 1; for (i = 0; i < 16; i++) { if (mask & (1 << i)) { + reg = gen_rtx_REG (SImode, i); + XVECEXP (par, 0, 0) = gen_rtx_SET (VOIDmode, gen_rtx_MEM (BLKmode, gen_rtx_PRE_DEC (BLKmode, stack_pointer_rtx)), gen_rtx_UNSPEC (BLKmode, - gen_rtvec (1, - gen_rtx_REG (SImode, i)), + gen_rtvec (1, reg), 2)); + + tmp = gen_rtx_SET (VOIDmode, + gen_rtx_MEM (SImode, + gen_rtx_PRE_DEC (BLKmode, + stack_pointer_rtx)), + reg); + RTX_FRAME_RELATED_P (tmp) = 1; + XVECEXP (dwarf, 0, num_regs - 1) = tmp; + break; } } @@ -6306,38 +6325,77 @@ emit_multi_reg_push (mask) { if (mask & (1 << i)) { - XVECEXP (par, 0, j) - = gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, i)); + reg = gen_rtx_REG (SImode, i); + + XVECEXP (par, 0, j) = gen_rtx_USE (VOIDmode, reg); + + tmp = gen_rtx_SET (VOIDmode, + gen_rtx_MEM (SImode, + gen_rtx_PRE_DEC (BLKmode, + stack_pointer_rtx)), + reg); + RTX_FRAME_RELATED_P (tmp) = 1; + XVECEXP (dwarf, 0, num_regs - j - 1) = tmp; + j++; } } - emit_insn (par); + par = emit_insn (par); + REG_NOTES (par) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf, + REG_NOTES (par)); + return par; } -static void +static rtx emit_sfm (base_reg, count) int base_reg; int count; { rtx par; + rtx dwarf; + rtx tmp, reg; int i; par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count)); + dwarf = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count)); + RTX_FRAME_RELATED_P (dwarf) = 1; + + reg = gen_rtx_REG (XFmode, base_reg++); XVECEXP (par, 0, 0) = gen_rtx_SET (VOIDmode, gen_rtx_MEM (BLKmode, gen_rtx_PRE_DEC (BLKmode, stack_pointer_rtx)), gen_rtx_UNSPEC (BLKmode, - gen_rtvec (1, gen_rtx_REG (XFmode, - base_reg++)), + gen_rtvec (1, reg), 2)); + tmp + = gen_rtx_SET (VOIDmode, + gen_rtx_MEM (XFmode, + gen_rtx_PRE_DEC (BLKmode, stack_pointer_rtx)), + reg); + RTX_FRAME_RELATED_P (tmp) = 1; + XVECEXP (dwarf, 0, count - 1) = tmp; + for (i = 1; i < count; i++) - XVECEXP (par, 0, i) = gen_rtx_USE (VOIDmode, - gen_rtx_REG (XFmode, base_reg++)); + { + reg = gen_rtx_REG (XFmode, base_reg++); + XVECEXP (par, 0, i) = gen_rtx_USE (VOIDmode, reg); + + tmp = gen_rtx_SET (VOIDmode, + gen_rtx_MEM (XFmode, + gen_rtx_PRE_DEC (BLKmode, + stack_pointer_rtx)), + reg); + RTX_FRAME_RELATED_P (tmp) = 1; + XVECEXP (dwarf, 0, count - i - 1) = tmp; + } - emit_insn (par); + par = emit_insn (par); + REG_NOTES (par) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf, + REG_NOTES (par)); + return par; } void @@ -6352,6 +6410,7 @@ arm_expand_prologue () the call-saved regs. */ int volatile_func = (optimize > 0 && TREE_THIS_VOLATILE (current_function_decl)); + rtx insn; /* Naked functions don't have prologues. */ if (arm_naked_function_p (current_function_decl)) @@ -6376,18 +6435,21 @@ arm_expand_prologue () if (frame_pointer_needed) { live_regs_mask |= 0xD800; - emit_insn (gen_movsi (gen_rtx_REG (SImode, IP_REGNUM), - stack_pointer_rtx)); + insn = emit_insn (gen_movsi (gen_rtx_REG (SImode, IP_REGNUM), + stack_pointer_rtx)); + RTX_FRAME_RELATED_P (insn) = 1; } if (current_function_pretend_args_size) { if (store_arg_regs) - emit_multi_reg_push ((0xf0 >> (current_function_pretend_args_size / 4)) - & 0xf); + insn = emit_multi_reg_push + ((0xf0 >> (current_function_pretend_args_size / 4)) & 0xf); else - emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, - GEN_INT (-current_function_pretend_args_size))); + insn = emit_insn + (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (-current_function_pretend_args_size))); + RTX_FRAME_RELATED_P (insn) = 1; } if (live_regs_mask) @@ -6395,10 +6457,11 @@ arm_expand_prologue () /* If we have to push any regs, then we must push lr as well, or we won't get a proper return. */ live_regs_mask |= 1 << LR_REGNUM; - emit_multi_reg_push (live_regs_mask); + insn = emit_multi_reg_push (live_regs_mask); + RTX_FRAME_RELATED_P (insn) = 1; } - /* For now the integer regs are still pushed in output_func_epilogue (). */ + /* And now the floating point regs. */ if (! volatile_func) { @@ -6406,12 +6469,13 @@ arm_expand_prologue () { for (reg = 23; reg > 15; reg--) if (regs_ever_live[reg] && ! call_used_regs[reg]) - emit_insn (gen_rtx_SET - (VOIDmode, - gen_rtx_MEM (XFmode, - gen_rtx_PRE_DEC (XFmode, - stack_pointer_rtx)), - gen_rtx_REG (XFmode, reg))); + { + insn = gen_rtx_PRE_DEC (XFmode, stack_pointer_rtx); + insn = gen_rtx_MEM (XFmode, insn); + insn = emit_insn (gen_rtx_SET (VOIDmode, insn, + gen_rtx_REG (XFmode, reg))); + RTX_FRAME_RELATED_P (insn) = 1; + } } else { @@ -6423,31 +6487,44 @@ arm_expand_prologue () { if (start_reg - reg == 3) { - emit_sfm (reg, 4); + insn = emit_sfm (reg, 4); + RTX_FRAME_RELATED_P (insn) = 1; start_reg = reg - 1; } } else { if (start_reg != reg) - emit_sfm (reg + 1, start_reg - reg); + { + insn = emit_sfm (reg + 1, start_reg - reg); + RTX_FRAME_RELATED_P (insn) = 1; + } start_reg = reg - 1; } } if (start_reg != reg) - emit_sfm (reg + 1, start_reg - reg); + { + insn = emit_sfm (reg + 1, start_reg - reg); + RTX_FRAME_RELATED_P (insn) = 1; + } } } if (frame_pointer_needed) - emit_insn (gen_addsi3 (hard_frame_pointer_rtx, gen_rtx_REG (SImode, IP_REGNUM), - (GEN_INT - (-(4 + current_function_pretend_args_size))))); + { + insn = GEN_INT (-(4 + current_function_pretend_args_size)); + insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx, + gen_rtx_REG (SImode, IP_REGNUM), + insn)); + RTX_FRAME_RELATED_P (insn) = 1; + } if (amount != const0_rtx) { - emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, amount)); + insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, + amount)); + RTX_FRAME_RELATED_P (insn) = 1; emit_insn (gen_rtx_CLOBBER (VOIDmode, gen_rtx_MEM (BLKmode, stack_pointer_rtx))); } diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 23b5d88..b748b74 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -2275,6 +2275,13 @@ extern struct rtx_def * arm_compare_op1; ? gen_rtx_MEM (Pmode, plus_constant (FRAME, -4)) \ : NULL_RTX) +/* Pick up the return address upon entry to a procedure. Used for + dwarf2 unwind information. This also enables the table driven + mechanism. */ + +#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, LR_REGNUM) +#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (LR_REGNUM) + /* Used to mask out junk bits from the return address, such as processor state, interrupt status, condition codes and the like. */ #define MASK_RETURN_ADDR \ diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h index 9c5cd82..5d17042 100644 --- a/gcc/config/m68k/m68k.h +++ b/gcc/config/m68k/m68k.h @@ -925,9 +925,6 @@ extern enum reg_class regno_reg_class[]; /* Offset of first parameter from the argument pointer register value. */ #define FIRST_PARM_OFFSET(FNDECL) 8 -/* Offset of the CFA from the argument pointer register value. */ -#define ARG_POINTER_CFA_OFFSET 8 - /* Value is the number of byte of arguments automatically popped when returning from a subroutine call. FUNDECL is the declaration node of the function (as a tree), diff --git a/gcc/config/ns32k/ns32k.h b/gcc/config/ns32k/ns32k.h index ac984c3..4a0bf43 100644 --- a/gcc/config/ns32k/ns32k.h +++ b/gcc/config/ns32k/ns32k.h @@ -552,9 +552,6 @@ enum reg_class #define INCOMING_FRAME_SP_OFFSET 4 -/* Offset of the CFA from the argument pointer register value. */ -#define ARG_POINTER_CFA_OFFSET 8 - /* If we generate an insn to push BYTES bytes, this says how many the stack pointer really advances by. On the 32000, sp@- in a byte insn really pushes a BYTE. */ diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h index 1f8b61f..0da6cd6 100644 --- a/gcc/config/sparc/sparc.h +++ b/gcc/config/sparc/sparc.h @@ -1603,9 +1603,11 @@ extern char leaf_reg_remap[]; (TARGET_ARCH64 ? (SPARC_STACK_BIAS + 16 * UNITS_PER_WORD) \ : (STRUCT_VALUE_OFFSET + UNITS_PER_WORD)) -/* Offset from the argument pointer register value to the CFA. */ +/* Offset from the argument pointer register value to the CFA. + This is different from FIRST_PARM_OFFSET because the register window + comes between the CFA and the arguments. */ -#define ARG_POINTER_CFA_OFFSET SPARC_STACK_BIAS +#define ARG_POINTER_CFA_OFFSET(FNDECL) SPARC_STACK_BIAS /* When a parameter is passed in a register, stack space is still allocated for it. diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index fb4679c..f181f26 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -559,7 +559,7 @@ reg_number (rtl) { register unsigned regno = REGNO (rtl); - if (regno >= DWARF_FRAME_REGISTERS) + if (regno >= FIRST_PSEUDO_REGISTER) { warning ("internal regno botch: regno = %d\n", regno); regno = 0; @@ -882,6 +882,9 @@ reg_save (label, reg, sreg, offset) } cfi->dw_cfi_oprnd2.dw_cfi_offset = offset; } + else if (sreg == reg) + /* We could emit a DW_CFA_same_value in this case, but don't bother. */ + return; else { cfi->dw_cfi_opc = DW_CFA_register; @@ -975,7 +978,7 @@ initial_return_save (rtl) { case REG: /* RA is in a register. */ - reg = reg_number (rtl); + reg = DWARF_FRAME_REGNUM (REGNO (rtl)); break; case MEM: /* RA is on the stack. */ @@ -1174,10 +1177,11 @@ dwarf2out_frame_debug_expr (expr, label) case REG: if (cfa_reg != (unsigned) REGNO (src)) abort (); - if (REGNO (dest) != STACK_POINTER_REGNUM - && !(frame_pointer_needed - && REGNO (dest) == HARD_FRAME_POINTER_REGNUM)) - abort (); + + /* We used to require that dest be either SP or FP, but the + ARM copies SP to a temporary register, and from there to + FP. So we just rely on the backends to only set + RTX_FRAME_RELATED_P on appropriate insns. */ cfa_reg = REGNO (dest); break; @@ -1221,32 +1225,19 @@ dwarf2out_frame_debug_expr (expr, label) { /* Either setting the FP from an offset of the SP, or adjusting the FP */ - if (! frame_pointer_needed - || REGNO (dest) != HARD_FRAME_POINTER_REGNUM) + if (! frame_pointer_needed) abort (); - if (XEXP (src, 0) == stack_pointer_rtx + if (GET_CODE (XEXP (src, 0)) == REG + && (unsigned) REGNO (XEXP (src, 0)) == cfa_reg && GET_CODE (XEXP (src, 1)) == CONST_INT) { - if (cfa_reg != STACK_POINTER_REGNUM) - abort (); offset = INTVAL (XEXP (src, 1)); if (GET_CODE (src) == PLUS) offset = -offset; cfa_offset += offset; cfa_reg = HARD_FRAME_POINTER_REGNUM; } - else if (XEXP (src, 0) == hard_frame_pointer_rtx - && GET_CODE (XEXP (src, 1)) == CONST_INT) - { - if (cfa_reg != (unsigned) HARD_FRAME_POINTER_REGNUM) - abort (); - offset = INTVAL (XEXP (src, 1)); - if (GET_CODE (src) == PLUS) - offset = -offset; - cfa_offset += offset; - } - else abort(); } diff --git a/gcc/except.c b/gcc/except.c index 3146778..7cf64cc 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -2910,9 +2910,10 @@ expand_builtin_frob_return_addr (addr_tree) The first passes the exception context to the handler. For this we use the return value register for a void*. - The second holds the stack pointer value to be restored. For - this we use the static chain register if it exists and is different - from the previous, otherwise some arbitrary call-clobbered register. + The second holds the stack pointer value to be restored. For this + we use the static chain register if it exists, is different from + the previous, and is call-clobbered; otherwise some arbitrary + call-clobbered register. The third holds the address of the handler itself. Here we use some arbitrary call-clobbered register. */ @@ -2939,7 +2940,8 @@ eh_regs (pcontext, psp, pra, outgoing) rsp = static_chain_incoming_rtx; else rsp = static_chain_rtx; - if (REGNO (rsp) == REGNO (rcontext)) + if (REGNO (rsp) == REGNO (rcontext) + || ! call_used_regs [REGNO (rsp)]) #endif /* STATIC_CHAIN_REGNUM */ rsp = NULL_RTX; diff --git a/gcc/frame.c b/gcc/frame.c index 79ba78a..688355a 100644 --- a/gcc/frame.c +++ b/gcc/frame.c @@ -697,6 +697,8 @@ execute_cfa_insn (void *p, struct frame_state_internal *state, offset *= info->data_align; state->s.saved[reg] = REG_SAVED_OFFSET; state->s.reg_or_offset[reg] = offset; + if (reg == state->s.cfa_reg) + state->s.cfa_saved = 1; } else if (insn & DW_CFA_restore) { @@ -728,6 +730,8 @@ execute_cfa_insn (void *p, struct frame_state_internal *state, offset *= info->data_align; state->s.saved[reg] = REG_SAVED_OFFSET; state->s.reg_or_offset[reg] = offset; + if (reg == state->s.cfa_reg) + state->s.cfa_saved = 1; break; case DW_CFA_restore_extended: p = decode_uleb128 (p, ®); diff --git a/gcc/frame.h b/gcc/frame.h index 330277c..ecaf6b0 100644 --- a/gcc/frame.h +++ b/gcc/frame.h @@ -1,6 +1,6 @@ /* Header file for unwinding stack frames for exception handling. */ /* Compile this one with gcc. */ -/* Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. +/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. Contributed by Jason Merrill <jason@cygnus.com>. This file is part of GNU CC. @@ -34,6 +34,7 @@ typedef struct frame_state long reg_or_offset[DWARF_FRAME_REGISTERS+1]; unsigned short cfa_reg; unsigned short retaddr_column; + char cfa_saved; char saved[DWARF_FRAME_REGISTERS+1]; } frame_state; diff --git a/gcc/function.c b/gcc/function.c index 3308dbb..ae04a5c 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -2760,10 +2760,10 @@ static int cfa_offset; #endif #endif -/* On a few machines, the CFA coincides with the arg pointer. */ +/* On most machines, the CFA coincides with the first incoming parm. */ #ifndef ARG_POINTER_CFA_OFFSET -#define ARG_POINTER_CFA_OFFSET 0 +#define ARG_POINTER_CFA_OFFSET(FNDECL) FIRST_PARM_OFFSET (FNDECL) #endif @@ -3335,7 +3335,7 @@ instantiate_virtual_regs (fndecl, insns) var_offset = STARTING_FRAME_OFFSET; dynamic_offset = STACK_DYNAMIC_OFFSET (fndecl); out_arg_offset = STACK_POINTER_OFFSET; - cfa_offset = ARG_POINTER_CFA_OFFSET; + cfa_offset = ARG_POINTER_CFA_OFFSET (fndecl); /* Scan all variables and parameters of this function. For each that is in memory, instantiate all virtual registers if the result is a valid diff --git a/gcc/libgcc2.c b/gcc/libgcc2.c index e2a852c..aafbe75 100644 --- a/gcc/libgcc2.c +++ b/gcc/libgcc2.c @@ -3679,6 +3679,7 @@ throw_helper (struct eh_context *eh, void *pc, frame_state *my_udata, void *handler; void *handler_p = 0; void *pc_p = 0; + void *restored_cfa = 0; frame_state saved_ustruct; int new_eh_model; int cleanup = 0; @@ -3788,6 +3789,11 @@ throw_helper (struct eh_context *eh, void *pc, frame_state *my_udata, pc = saved_pc; memcpy (udata, my_udata, sizeof (*udata)); + if (udata->cfa_saved) + /* We saved the CFA register into the stack in this frame, so we + will restore it in the __throw epilogue. Remember the value. */ + restored_cfa = udata->cfa; + while (pc != handler_pc) { frame_state *p = udata; @@ -3808,6 +3814,9 @@ throw_helper (struct eh_context *eh, void *pc, frame_state *my_udata, copy_reg (i, udata, my_udata); } + if (udata->cfa_saved) + restored_cfa = udata->cfa; + pc = get_return_addr (udata, sub_udata) - 1; } @@ -3823,6 +3832,13 @@ throw_helper (struct eh_context *eh, void *pc, frame_state *my_udata, } /* udata now refers to the frame called by the handler frame. */ + if (my_udata->cfa_saved) + /* If we saved the CFA register into the stack (after it became the + CFA register), we'll restore that value into SP in the epilogue, + as on the ARM. So calculate the adjustment based on the value that + will be restored. */ + my_udata->cfa = restored_cfa; + /* We adjust SP by the difference between __throw's CFA and the CFA for the frame called by the handler frame, because those CFAs correspond to the SP values at the two call sites. We need to further adjust by diff --git a/gcc/tm.texi b/gcc/tm.texi index 633281a..3a1b9eb 100644 --- a/gcc/tm.texi +++ b/gcc/tm.texi @@ -2292,6 +2292,9 @@ the stack. You only need to define this macro if you want to support call frame debugging information like that provided by DWARF 2. +If this RTL is a @code{REG}, you should also define +DWARF_FRAME_RETURN_COLUMN to @code{DWARF_FRAME_REGNUM (REGNO)}. + @findex INCOMING_FRAME_SP_OFFSET @item INCOMING_FRAME_SP_OFFSET A C expression whose value is an integer giving the offset, in bytes, @@ -2304,15 +2307,20 @@ You only need to define this macro if you want to support call frame debugging information like that provided by DWARF 2. @findex ARG_POINTER_CFA_OFFSET -@item ARG_POINTER_CFA_OFFSET +@item ARG_POINTER_CFA_OFFSET (@var{fundecl}) A C expression whose value is an integer giving the offset, in bytes, from the argument pointer to the canonical frame address (cfa). The final value should coincide with that calculated by @code{INCOMING_FRAME_SP_OFFSET}. Which is unfortunately not usable during virtual register instantiation. -You only need to define this macro if you want to support call frame -debugging information like that provided by DWARF 2. +The default value for this macro is @code{FIRST_PARM_OFFSET (fundecl)}, +which is correct for most machines; in general, the arguments are found +immediately before the stack frame. See @file{function.c} for details. + +You only need to define this macro if this default is incorrect, and you +want to support call frame debugging information like that provided by +DWARF 2. @findex SMALL_STACK @item SMALL_STACK |