diff options
author | Richard Henderson <rth@redhat.com> | 2010-08-04 16:58:26 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2010-08-04 16:58:26 -0700 |
commit | c9f4c45115dfba1d84958c1a971a333763976b7f (patch) | |
tree | a39862b72529e6b9992873c95bf737f8aca806dd /gcc/dwarf2out.c | |
parent | ec7ded37e7550ed1e9f133b959fe92ff6fdf791d (diff) | |
download | gcc-c9f4c45115dfba1d84958c1a971a333763976b7f.zip gcc-c9f4c45115dfba1d84958c1a971a333763976b7f.tar.gz gcc-c9f4c45115dfba1d84958c1a971a333763976b7f.tar.bz2 |
Describe unwinding for realigned frames explicitly.
We had been relying on some extremely fragile code within
dwarf2out in order to guess what to do with aligned stack
frames, which broke when we decided to perform the stores
to the aligned stack frame via EBP instead of ESP.
Instead, emit the appropriate unwinding instructions from
the backend. This requires adding a new reg-note in order
to describe a register save at an arbitrary address.
From-SVN: r162889
Diffstat (limited to 'gcc/dwarf2out.c')
-rw-r--r-- | gcc/dwarf2out.c | 51 |
1 files changed, 49 insertions, 2 deletions
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 54585e9..2c79c69 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -479,6 +479,8 @@ static struct dw_loc_descr_struct *build_cfa_loc 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 struct dw_loc_descr_struct *mem_loc_descriptor + (rtx, enum machine_mode mode, enum var_init_status); /* How to start an assembler comment. */ #ifndef ASM_COMMENT_START @@ -1833,6 +1835,17 @@ dwarf2out_frame_debug_def_cfa (rtx pat, const char *label) cfa.reg = REGNO (pat); break; + case MEM: + cfa.indirect = 1; + pat = XEXP (pat, 0); + if (GET_CODE (pat) == PLUS) + { + cfa.base_offset = INTVAL (XEXP (pat, 1)); + pat = XEXP (pat, 0); + } + cfa.reg = REGNO (pat); + break; + default: /* Recurse and define an expression. */ gcc_unreachable (); @@ -1951,6 +1964,34 @@ dwarf2out_frame_debug_cfa_register (rtx set, const char *label) reg_save (label, 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) +{ + rtx src, dest, span; + dw_cfi_ref cfi = new_cfi (); + + dest = SET_DEST (set); + src = SET_SRC (set); + + gcc_assert (REG_P (src)); + gcc_assert (MEM_P (dest)); + + span = targetm.dwarf_register_span (src); + gcc_assert (!span); + + cfi->dw_cfi_opc = DW_CFA_expression; + cfi->dw_cfi_oprnd1.dw_cfi_reg_num = DWARF_FRAME_REGNUM (REGNO (src)); + cfi->dw_cfi_oprnd2.dw_cfi_loc + = mem_loc_descriptor (XEXP (dest, 0), GET_MODE (dest), + VAR_INIT_STATUS_INITIALIZED); + + /* ??? 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); +} + /* A subroutine of dwarf2out_frame_debug, process a REG_CFA_RESTORE note. */ static void @@ -2740,6 +2781,14 @@ dwarf2out_frame_debug (rtx insn, bool after_p) handled_one = true; break; + case REG_CFA_EXPRESSION: + n = XEXP (note, 0); + if (n == NULL) + n = single_set (insn); + dwarf2out_frame_debug_cfa_expression (n, label); + handled_one = true; + break; + case REG_CFA_RESTORE: n = XEXP (note, 0); if (n == NULL) @@ -6181,8 +6230,6 @@ static dw_loc_descr_ref based_loc_descr (rtx, HOST_WIDE_INT, enum var_init_status); static int is_based_loc (const_rtx); static int resolve_one_addr (rtx *, void *); -static dw_loc_descr_ref mem_loc_descriptor (rtx, enum machine_mode mode, - enum var_init_status); static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx, enum var_init_status); static dw_loc_descr_ref loc_descriptor (rtx, enum machine_mode mode, |