Commit f6672e8e by Richard Henderson Committed by Richard Henderson

dwarf2out.c (dw_cfi_oprnd_struct): Reduce dw_cfi_reg_num to int.

        * dwarf2out.c (dw_cfi_oprnd_struct): Reduce dw_cfi_reg_num to int.
        (lookup_cfa_1): Apply data alignment to DW_CFA_def_cfa_offset_sf
        and DW_CFA_def_cfa_sf.
        (def_cfa_1): Use DW_CFA_def_cfa_offset_sf with negative values.
        (dbx_reg_number): Don't assert particular registers here.
        (based_loc_descr): ... do it here instead.  Fold in ...
        (eliminate_reg_to_offset): ... this function.
        (compute_frame_pointer_to_cfa_displacement): Fold in the effects
        of eliminate_reg_to_offset; use FRAME_POINTER_CFA_OFFSET.
        * unwind-dw2.c (execute_cfa_program): Apply data align factor
        to DW_CFA_def_cfa_offset_sf and DW_CFA_def_cfa_sf.
        * function.c (instantiate_new_reg): Use FRAME_POINTER_CFA_OFFSET.
        (instantiate_virtual_regs): Likewise.
        * var-tracking.c (adjust_stack_reference): Likewise.
        * doc/tm.texi (FRAME_POINTER_CFA_OFFSET): New.

From-SVN: r107154
parent ca9e049b
2005-11-17 Richard Henderson <rth@redhat.com>
* dwarf2out.c (dw_cfi_oprnd_struct): Reduce dw_cfi_reg_num to int.
(lookup_cfa_1): Apply data alignment to DW_CFA_def_cfa_offset_sf
and DW_CFA_def_cfa_sf.
(def_cfa_1): Use DW_CFA_def_cfa_offset_sf with negative values.
(dbx_reg_number): Don't assert particular registers here.
(based_loc_descr): ... do it here instead. Fold in ...
(eliminate_reg_to_offset): ... this function.
(compute_frame_pointer_to_cfa_displacement): Fold in the effects
of eliminate_reg_to_offset; use FRAME_POINTER_CFA_OFFSET.
* unwind-dw2.c (execute_cfa_program): Apply data align factor
to DW_CFA_def_cfa_offset_sf and DW_CFA_def_cfa_sf.
* function.c (instantiate_new_reg): Use FRAME_POINTER_CFA_OFFSET.
(instantiate_virtual_regs): Likewise.
* var-tracking.c (adjust_stack_reference): Likewise.
* doc/tm.texi (FRAME_POINTER_CFA_OFFSET): New.
2005-11-17 Bernd Schmidt <bernd.schmidt@analog.com> 2005-11-17 Bernd Schmidt <bernd.schmidt@analog.com>
* config/bfin/elf.h (STARTFILE_SPEC): Add "crtlibid%O%s" * config/bfin/elf.h (STARTFILE_SPEC): Add "crtlibid%O%s"
......
...@@ -2926,6 +2926,21 @@ want to support call frame debugging information like that provided by ...@@ -2926,6 +2926,21 @@ want to support call frame debugging information like that provided by
DWARF 2. DWARF 2.
@end defmac @end defmac
@defmac FRAME_POINTER_CFA_OFFSET (@var{fundecl})
If defined, a C expression whose value is an integer giving the offset
in bytes from the frame pointer to the canonical frame address (cfa).
The final value should conincide with that calculated by
@code{INCOMING_FRAME_SP_OFFSET}.
Normally the CFA is calculated as an offset from the argument pointer,
via @code{ARG_POINTER_CFA_OFFSET}, but if the argument pointer is
variable due to the ABI, this may not be possible. If this macro is
defined, it imples that the virtual register instantiation should be
based on the frame pointer instead of the argument pointer. Only one
of @code{FRAME_POINTER_CFA_OFFSET} and @code{ARG_POINTER_CFA_OFFSET}
should be defined.
@end defmac
@node Exception Handling @node Exception Handling
@subsection Exception Handling Support @subsection Exception Handling Support
@cindex exception handling @cindex exception handling
......
...@@ -214,7 +214,7 @@ enum dw_cfi_oprnd_type { ...@@ -214,7 +214,7 @@ enum dw_cfi_oprnd_type {
typedef union dw_cfi_oprnd_struct GTY(()) typedef union dw_cfi_oprnd_struct GTY(())
{ {
unsigned long GTY ((tag ("dw_cfi_oprnd_reg_num"))) dw_cfi_reg_num; unsigned int GTY ((tag ("dw_cfi_oprnd_reg_num"))) dw_cfi_reg_num;
HOST_WIDE_INT GTY ((tag ("dw_cfi_oprnd_offset"))) dw_cfi_offset; HOST_WIDE_INT GTY ((tag ("dw_cfi_oprnd_offset"))) dw_cfi_offset;
const char * GTY ((tag ("dw_cfi_oprnd_addr"))) dw_cfi_addr; const char * GTY ((tag ("dw_cfi_oprnd_addr"))) dw_cfi_addr;
struct dw_loc_descr_struct * GTY ((tag ("dw_cfi_oprnd_loc"))) dw_cfi_loc; struct dw_loc_descr_struct * GTY ((tag ("dw_cfi_oprnd_loc"))) dw_cfi_loc;
...@@ -671,6 +671,10 @@ lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc) ...@@ -671,6 +671,10 @@ lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc)
case DW_CFA_def_cfa_offset: case DW_CFA_def_cfa_offset:
loc->offset = cfi->dw_cfi_oprnd1.dw_cfi_offset; loc->offset = cfi->dw_cfi_oprnd1.dw_cfi_offset;
break; break;
case DW_CFA_def_cfa_offset_sf:
loc->offset
= cfi->dw_cfi_oprnd1.dw_cfi_offset * DWARF_CIE_DATA_ALIGNMENT;
break;
case DW_CFA_def_cfa_register: case DW_CFA_def_cfa_register:
loc->reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num; loc->reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
break; break;
...@@ -678,6 +682,11 @@ lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc) ...@@ -678,6 +682,11 @@ lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc)
loc->reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num; loc->reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
loc->offset = cfi->dw_cfi_oprnd2.dw_cfi_offset; loc->offset = cfi->dw_cfi_oprnd2.dw_cfi_offset;
break; break;
case DW_CFA_def_cfa_sf:
loc->reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
loc->offset
= cfi->dw_cfi_oprnd2.dw_cfi_offset * DWARF_CIE_DATA_ALIGNMENT;
break;
case DW_CFA_def_cfa_expression: case DW_CFA_def_cfa_expression:
get_cfa_from_loc_descr (loc, cfi->dw_cfi_oprnd1.dw_cfi_loc); get_cfa_from_loc_descr (loc, cfi->dw_cfi_oprnd1.dw_cfi_loc);
break; break;
...@@ -775,11 +784,21 @@ def_cfa_1 (const char *label, dw_cfa_location *loc_p) ...@@ -775,11 +784,21 @@ def_cfa_1 (const char *label, dw_cfa_location *loc_p)
if (loc.reg == old_cfa.reg && !loc.indirect) if (loc.reg == old_cfa.reg && !loc.indirect)
{ {
/* Construct a "DW_CFA_def_cfa_offset <offset>" instruction, /* Construct a "DW_CFA_def_cfa_offset <offset>" instruction, indicating
indicating the CFA register did not change but the offset the CFA register did not change but the offset did. */
did. */ if (loc.offset < 0)
cfi->dw_cfi_opc = DW_CFA_def_cfa_offset; {
cfi->dw_cfi_oprnd1.dw_cfi_offset = loc.offset; HOST_WIDE_INT f_offset = loc.offset / DWARF_CIE_DATA_ALIGNMENT;
gcc_assert (f_offset * DWARF_CIE_DATA_ALIGNMENT == loc.offset);
cfi->dw_cfi_opc = DW_CFA_def_cfa_offset_sf;
cfi->dw_cfi_oprnd1.dw_cfi_offset = f_offset;
}
else
{
cfi->dw_cfi_opc = DW_CFA_def_cfa_offset;
cfi->dw_cfi_oprnd1.dw_cfi_offset = loc.offset;
}
} }
#ifndef MIPS_DEBUGGING_INFO /* SGI dbx thinks this means no offset. */ #ifndef MIPS_DEBUGGING_INFO /* SGI dbx thinks this means no offset. */
...@@ -800,9 +819,21 @@ def_cfa_1 (const char *label, dw_cfa_location *loc_p) ...@@ -800,9 +819,21 @@ def_cfa_1 (const char *label, dw_cfa_location *loc_p)
/* Construct a "DW_CFA_def_cfa <register> <offset>" instruction, /* Construct a "DW_CFA_def_cfa <register> <offset>" instruction,
indicating the CFA register has changed to <register> with indicating the CFA register has changed to <register> with
the specified offset. */ the specified offset. */
cfi->dw_cfi_opc = DW_CFA_def_cfa; if (loc.offset < 0)
cfi->dw_cfi_oprnd1.dw_cfi_reg_num = loc.reg; {
cfi->dw_cfi_oprnd2.dw_cfi_offset = loc.offset; HOST_WIDE_INT f_offset = loc.offset / DWARF_CIE_DATA_ALIGNMENT;
gcc_assert (f_offset * DWARF_CIE_DATA_ALIGNMENT == loc.offset);
cfi->dw_cfi_opc = DW_CFA_def_cfa_sf;
cfi->dw_cfi_oprnd1.dw_cfi_reg_num = loc.reg;
cfi->dw_cfi_oprnd2.dw_cfi_offset = f_offset;
}
else
{
cfi->dw_cfi_opc = DW_CFA_def_cfa;
cfi->dw_cfi_oprnd1.dw_cfi_reg_num = loc.reg;
cfi->dw_cfi_oprnd2.dw_cfi_offset = loc.offset;
}
} }
else else
{ {
...@@ -8460,12 +8491,6 @@ dbx_reg_number (rtx rtl) ...@@ -8460,12 +8491,6 @@ dbx_reg_number (rtx rtl)
{ {
unsigned regno = REGNO (rtl); unsigned regno = REGNO (rtl);
/* We do not want to see registers that should have been eliminated. */
gcc_assert (HARD_FRAME_POINTER_REGNUM == ARG_POINTER_REGNUM
|| rtl != arg_pointer_rtx);
gcc_assert (HARD_FRAME_POINTER_REGNUM == FRAME_POINTER_REGNUM
|| rtl != frame_pointer_rtx);
gcc_assert (regno < FIRST_PSEUDO_REGISTER); gcc_assert (regno < FIRST_PSEUDO_REGISTER);
#ifdef LEAF_REG_REMAP #ifdef LEAF_REG_REMAP
...@@ -8619,32 +8644,12 @@ int_loc_descriptor (HOST_WIDE_INT i) ...@@ -8619,32 +8644,12 @@ int_loc_descriptor (HOST_WIDE_INT i)
return new_loc_descr (op, i, 0); return new_loc_descr (op, i, 0);
} }
/* Return an offset from an eliminable register to the post-prologue
frame pointer. */
static HOST_WIDE_INT
eliminate_reg_to_offset (rtx reg)
{
HOST_WIDE_INT offset = 0;
reg = eliminate_regs (reg, VOIDmode, NULL_RTX);
if (GET_CODE (reg) == PLUS)
{
offset = INTVAL (XEXP (reg, 1));
reg = XEXP (reg, 0);
}
gcc_assert (reg == (frame_pointer_needed ? hard_frame_pointer_rtx
: stack_pointer_rtx));
return offset;
}
/* Return a location descriptor that designates a base+offset location. */ /* Return a location descriptor that designates a base+offset location. */
static dw_loc_descr_ref static dw_loc_descr_ref
based_loc_descr (rtx reg, HOST_WIDE_INT offset) based_loc_descr (rtx reg, HOST_WIDE_INT offset)
{ {
dw_loc_descr_ref loc_result; unsigned int regno;
/* We only use "frame base" when we're sure we're talking about the /* We only use "frame base" when we're sure we're talking about the
post-prologue local stack frame. We do this by *not* running post-prologue local stack frame. We do this by *not* running
...@@ -8652,22 +8657,28 @@ based_loc_descr (rtx reg, HOST_WIDE_INT offset) ...@@ -8652,22 +8657,28 @@ based_loc_descr (rtx reg, HOST_WIDE_INT offset)
argument pointer and soft frame pointer rtx's. */ argument pointer and soft frame pointer rtx's. */
if (reg == arg_pointer_rtx || reg == frame_pointer_rtx) if (reg == arg_pointer_rtx || reg == frame_pointer_rtx)
{ {
offset += eliminate_reg_to_offset (reg); rtx elim = eliminate_regs (reg, VOIDmode, NULL_RTX);
offset += frame_pointer_cfa_offset;
loc_result = new_loc_descr (DW_OP_fbreg, offset, 0); if (elim != reg)
} {
else if (GET_CODE (elim) == PLUS)
{ {
unsigned int regno = dbx_reg_number (reg); offset += INTVAL (XEXP (elim, 1));
elim = XEXP (elim, 0);
}
gcc_assert (elim == (frame_pointer_needed ? hard_frame_pointer_rtx
: stack_pointer_rtx));
offset += frame_pointer_cfa_offset;
if (regno <= 31) return new_loc_descr (DW_OP_fbreg, offset, 0);
loc_result = new_loc_descr (DW_OP_breg0 + regno, offset, 0); }
else
loc_result = new_loc_descr (DW_OP_bregx, regno, offset);
} }
return loc_result; regno = dbx_reg_number (reg);
if (regno <= 31)
return new_loc_descr (DW_OP_breg0 + regno, offset, 0);
else
return new_loc_descr (DW_OP_bregx, regno, offset);
} }
/* Return true if this RTL expression describes a base+offset calculation. */ /* Return true if this RTL expression describes a base+offset calculation. */
...@@ -10406,9 +10417,24 @@ static void ...@@ -10406,9 +10417,24 @@ static void
compute_frame_pointer_to_cfa_displacement (void) compute_frame_pointer_to_cfa_displacement (void)
{ {
HOST_WIDE_INT offset; HOST_WIDE_INT offset;
rtx reg, elim;
#ifdef FRAME_POINTER_CFA_OFFSET
reg = frame_pointer_rtx;
offset = FRAME_POINTER_CFA_OFFSET (current_function_decl);
#else
reg = arg_pointer_rtx;
offset = ARG_POINTER_CFA_OFFSET (current_function_decl);
#endif
offset = eliminate_reg_to_offset (arg_pointer_rtx); elim = eliminate_regs (reg, VOIDmode, NULL_RTX);
offset += ARG_POINTER_CFA_OFFSET (current_function_decl); if (GET_CODE (elim) == PLUS)
{
offset += INTVAL (XEXP (elim, 1));
elim = XEXP (elim, 0);
}
gcc_assert (elim == (frame_pointer_needed ? hard_frame_pointer_rtx
: stack_pointer_rtx));
frame_pointer_cfa_offset = -offset; frame_pointer_cfa_offset = -offset;
} }
......
...@@ -1246,7 +1246,14 @@ instantiate_new_reg (rtx x, HOST_WIDE_INT *poffset) ...@@ -1246,7 +1246,14 @@ instantiate_new_reg (rtx x, HOST_WIDE_INT *poffset)
else if (x == virtual_outgoing_args_rtx) else if (x == virtual_outgoing_args_rtx)
new = stack_pointer_rtx, offset = out_arg_offset; new = stack_pointer_rtx, offset = out_arg_offset;
else if (x == virtual_cfa_rtx) else if (x == virtual_cfa_rtx)
new = arg_pointer_rtx, offset = cfa_offset; {
#ifdef FRAME_POINTER_CFA_OFFSET
new = frame_pointer_rtx;
#else
new = arg_pointer_rtx;
#endif
offset = cfa_offset;
}
else else
return NULL_RTX; return NULL_RTX;
...@@ -1632,7 +1639,11 @@ instantiate_virtual_regs (void) ...@@ -1632,7 +1639,11 @@ instantiate_virtual_regs (void)
var_offset = STARTING_FRAME_OFFSET; var_offset = STARTING_FRAME_OFFSET;
dynamic_offset = STACK_DYNAMIC_OFFSET (current_function_decl); dynamic_offset = STACK_DYNAMIC_OFFSET (current_function_decl);
out_arg_offset = STACK_POINTER_OFFSET; out_arg_offset = STACK_POINTER_OFFSET;
#ifdef FRAME_POINTER_CFA_OFFSET
cfa_offset = FRAME_POINTER_CFA_OFFSET (current_function_decl);
#else
cfa_offset = ARG_POINTER_CFA_OFFSET (current_function_decl); cfa_offset = ARG_POINTER_CFA_OFFSET (current_function_decl);
#endif
/* Initialize recognition, indicating that volatile is OK. */ /* Initialize recognition, indicating that volatile is OK. */
init_recog (); init_recog ();
......
...@@ -902,7 +902,7 @@ execute_cfa_program (const unsigned char *insn_ptr, ...@@ -902,7 +902,7 @@ execute_cfa_program (const unsigned char *insn_ptr,
insn_ptr += utmp; insn_ptr += utmp;
break; break;
/* From the 2.1 draft. */ /* From the dwarf3 draft. */
case DW_CFA_offset_extended_sf: case DW_CFA_offset_extended_sf:
insn_ptr = read_uleb128 (insn_ptr, &reg); insn_ptr = read_uleb128 (insn_ptr, &reg);
insn_ptr = read_sleb128 (insn_ptr, &stmp); insn_ptr = read_sleb128 (insn_ptr, &stmp);
...@@ -916,10 +916,12 @@ execute_cfa_program (const unsigned char *insn_ptr, ...@@ -916,10 +916,12 @@ execute_cfa_program (const unsigned char *insn_ptr,
insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_reg); insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_reg);
insn_ptr = read_sleb128 (insn_ptr, &fs->cfa_offset); insn_ptr = read_sleb128 (insn_ptr, &fs->cfa_offset);
fs->cfa_how = CFA_REG_OFFSET; fs->cfa_how = CFA_REG_OFFSET;
fs->cfa_offset *= fs->data_align;
break; break;
case DW_CFA_def_cfa_offset_sf: case DW_CFA_def_cfa_offset_sf:
insn_ptr = read_sleb128 (insn_ptr, &fs->cfa_offset); insn_ptr = read_sleb128 (insn_ptr, &fs->cfa_offset);
fs->cfa_offset *= fs->data_align;
/* cfa_how deliberately not set. */ /* cfa_how deliberately not set. */
break; break;
......
...@@ -557,8 +557,13 @@ adjust_stack_reference (rtx mem, HOST_WIDE_INT adjustment) ...@@ -557,8 +557,13 @@ adjust_stack_reference (rtx mem, HOST_WIDE_INT adjustment)
{ {
rtx addr, cfa, tmp; rtx addr, cfa, tmp;
#ifdef FRAME_POINTER_CFA_OFFSET
adjustment -= FRAME_POINTER_CFA_OFFSET (current_function_decl);
cfa = plus_constant (frame_pointer_rtx, adjustment);
#else
adjustment -= ARG_POINTER_CFA_OFFSET (current_function_decl); adjustment -= ARG_POINTER_CFA_OFFSET (current_function_decl);
cfa = plus_constant (arg_pointer_rtx, adjustment); cfa = plus_constant (arg_pointer_rtx, adjustment);
#endif
addr = replace_rtx (copy_rtx (XEXP (mem, 0)), stack_pointer_rtx, cfa); addr = replace_rtx (copy_rtx (XEXP (mem, 0)), stack_pointer_rtx, cfa);
tmp = simplify_rtx (addr); tmp = simplify_rtx (addr);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment