diff options
author | Richard Henderson <rth@redhat.com> | 2005-11-17 17:19:10 -0800 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2005-11-17 17:19:10 -0800 |
commit | f6672e8e52276dcaf1a27e636247383f316ce221 (patch) | |
tree | c03bdda31c81403f3bcd5fcf610248b9f27ee02a /gcc/dwarf2out.c | |
parent | ca9e049bc145ae985bc0e2dd6079dacdd51717ac (diff) | |
download | gcc-f6672e8e52276dcaf1a27e636247383f316ce221.zip gcc-f6672e8e52276dcaf1a27e636247383f316ce221.tar.gz gcc-f6672e8e52276dcaf1a27e636247383f316ce221.tar.bz2 |
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
Diffstat (limited to 'gcc/dwarf2out.c')
-rw-r--r-- | gcc/dwarf2out.c | 126 |
1 files changed, 76 insertions, 50 deletions
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index f7a006e..60a7d55 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -214,7 +214,7 @@ enum dw_cfi_oprnd_type { 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; 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; @@ -671,6 +671,10 @@ lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc) case DW_CFA_def_cfa_offset: loc->offset = cfi->dw_cfi_oprnd1.dw_cfi_offset; 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: loc->reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num; break; @@ -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->offset = cfi->dw_cfi_oprnd2.dw_cfi_offset; 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: get_cfa_from_loc_descr (loc, cfi->dw_cfi_oprnd1.dw_cfi_loc); break; @@ -775,11 +784,21 @@ def_cfa_1 (const char *label, dw_cfa_location *loc_p) if (loc.reg == old_cfa.reg && !loc.indirect) { - /* Construct a "DW_CFA_def_cfa_offset <offset>" instruction, - indicating the CFA register did not change but the offset - did. */ - cfi->dw_cfi_opc = DW_CFA_def_cfa_offset; - cfi->dw_cfi_oprnd1.dw_cfi_offset = loc.offset; + /* Construct a "DW_CFA_def_cfa_offset <offset>" instruction, indicating + the CFA register did not change but the offset did. */ + if (loc.offset < 0) + { + 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. */ @@ -800,9 +819,21 @@ def_cfa_1 (const char *label, dw_cfa_location *loc_p) /* Construct a "DW_CFA_def_cfa <register> <offset>" instruction, indicating the CFA register has changed to <register> with the specified offset. */ - 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; + if (loc.offset < 0) + { + 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 { @@ -8460,12 +8491,6 @@ dbx_reg_number (rtx 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); #ifdef LEAF_REG_REMAP @@ -8619,32 +8644,12 @@ int_loc_descriptor (HOST_WIDE_INT i) 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. */ static dw_loc_descr_ref 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 post-prologue local stack frame. We do this by *not* running @@ -8652,22 +8657,28 @@ based_loc_descr (rtx reg, HOST_WIDE_INT offset) argument pointer and soft frame pointer rtx's. */ if (reg == arg_pointer_rtx || reg == frame_pointer_rtx) { - offset += eliminate_reg_to_offset (reg); - offset += frame_pointer_cfa_offset; + rtx elim = eliminate_regs (reg, VOIDmode, NULL_RTX); - loc_result = new_loc_descr (DW_OP_fbreg, offset, 0); - } - else - { - unsigned int regno = dbx_reg_number (reg); + if (elim != reg) + { + 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)); + offset += frame_pointer_cfa_offset; - if (regno <= 31) - loc_result = new_loc_descr (DW_OP_breg0 + regno, offset, 0); - else - loc_result = new_loc_descr (DW_OP_bregx, regno, offset); + return new_loc_descr (DW_OP_fbreg, offset, 0); + } } - 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. */ @@ -10406,9 +10417,24 @@ static void compute_frame_pointer_to_cfa_displacement (void) { 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); - offset += ARG_POINTER_CFA_OFFSET (current_function_decl); + elim = eliminate_regs (reg, VOIDmode, NULL_RTX); + 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; } |