aboutsummaryrefslogtreecommitdiff
path: root/gcc/dwarf2out.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2010-08-04 16:58:26 -0700
committerRichard Henderson <rth@gcc.gnu.org>2010-08-04 16:58:26 -0700
commitc9f4c45115dfba1d84958c1a971a333763976b7f (patch)
treea39862b72529e6b9992873c95bf737f8aca806dd /gcc/dwarf2out.c
parentec7ded37e7550ed1e9f133b959fe92ff6fdf791d (diff)
downloadgcc-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.c51
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,