summaryrefslogtreecommitdiff
path: root/gcc/dwarf2cfi.c
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2011-08-05 16:17:46 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2011-08-05 16:17:46 +0000
commit4d256106847a01fcf5d8ff2cac02f26005d1f03f (patch)
tree322910cdab185612d3da8d03235bce92660f2588 /gcc/dwarf2cfi.c
parentb0fb421ce3aa2e7a3ac111c8eafe8e5ed2594d19 (diff)
downloadgcc-4d256106847a01fcf5d8ff2cac02f26005d1f03f.tar.gz
PR rtl-opt/49977
* dwarf2cfi.c (scan_insn_after): Split out of ... (scan_trace): ... here. Correctly place notes wrt sequences. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@177466 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/dwarf2cfi.c')
-rw-r--r--gcc/dwarf2cfi.c100
1 files changed, 72 insertions, 28 deletions
diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
index f6ab38d4b2c..80cce3209fc 100644
--- a/gcc/dwarf2cfi.c
+++ b/gcc/dwarf2cfi.c
@@ -2355,13 +2355,23 @@ create_trace_edges (rtx insn)
}
}
+/* A subroutine of scan_trace. Do what needs to be done "after" INSN. */
+
+static void
+scan_insn_after (rtx insn)
+{
+ if (RTX_FRAME_RELATED_P (insn))
+ dwarf2out_frame_debug (insn);
+ notice_args_size (insn);
+}
+
/* Scan the trace beginning at INSN and create the CFI notes for the
instructions therein. */
static void
scan_trace (dw_trace_info *trace)
{
- rtx insn = trace->head;
+ rtx prev, insn = trace->head;
dw_cfa_location this_cfa;
if (dump_file)
@@ -2378,10 +2388,14 @@ scan_trace (dw_trace_info *trace)
this_cfa = cur_row->cfa;
cur_cfa = &this_cfa;
- for (insn = NEXT_INSN (insn); insn ; insn = NEXT_INSN (insn))
+ for (prev = insn, insn = NEXT_INSN (insn);
+ insn;
+ prev = insn, insn = NEXT_INSN (insn))
{
+ rtx control;
+
/* Do everything that happens "before" the insn. */
- add_cfi_insn = PREV_INSN (insn);
+ add_cfi_insn = prev;
/* Notice the end of a trace. */
if (BARRIER_P (insn))
@@ -2401,34 +2415,25 @@ scan_trace (dw_trace_info *trace)
if (DEBUG_INSN_P (insn) || !inside_basic_block_p (insn))
continue;
- /* Flush data before calls and jumps, and of course if necessary. */
- if (can_throw_internal (insn))
- {
- dwarf2out_flush_queued_reg_saves ();
- notice_eh_throw (insn);
- }
- else if (!NONJUMP_INSN_P (insn)
- || clobbers_queued_reg_save (insn)
- || find_reg_note (insn, REG_CFA_FLUSH_QUEUE, NULL))
- dwarf2out_flush_queued_reg_saves ();
-
- /* Do everything that happens "after" the insn. */
- add_cfi_insn = insn;
-
- /* Handle changes to the row state. */
- if (RTX_FRAME_RELATED_P (insn))
- dwarf2out_frame_debug (insn);
-
- /* Look for REG_ARGS_SIZE, and handle it. */
+ /* Handle all changes to the row state. Sequences require special
+ handling for the positioning of the notes. */
if (GET_CODE (PATTERN (insn)) == SEQUENCE)
{
rtx elt, pat = PATTERN (insn);
int i, n = XVECLEN (pat, 0);
- if (INSN_ANNULLED_BRANCH_P (XVECEXP (pat, 0, 0)))
+ control = XVECEXP (pat, 0, 0);
+ if (can_throw_internal (control))
+ notice_eh_throw (control);
+ dwarf2out_flush_queued_reg_saves ();
+
+ if (INSN_ANNULLED_BRANCH_P (control))
{
/* ??? Hopefully multiple delay slots are not annulled. */
gcc_assert (n == 2);
+ gcc_assert (!RTX_FRAME_RELATED_P (control));
+ gcc_assert (!find_reg_note (control, REG_ARGS_SIZE, NULL));
+
elt = XVECEXP (pat, 0, 1);
/* If ELT is an instruction from target of an annulled branch,
@@ -2438,11 +2443,16 @@ scan_trace (dw_trace_info *trace)
{
HOST_WIDE_INT restore_args_size;
+ add_cfi_insn = NULL;
restore_args_size = cur_trace->end_true_args_size;
cur_cfa = &cur_row->cfa;
- notice_args_size (elt);
- create_trace_edges (insn);
+ scan_insn_after (elt);
+
+ /* ??? Should we instead save the entire row state? */
+ gcc_assert (!VEC_length (queued_reg_save, queued_reg_saves));
+
+ create_trace_edges (control);
cur_trace->end_true_args_size = restore_args_size;
cur_row->cfa = this_cfa;
@@ -2451,14 +2461,48 @@ scan_trace (dw_trace_info *trace)
}
}
+ /* The insns in the delay slot should all be considered to happen
+ "before" a call insn. Consider a call with a stack pointer
+ adjustment in the delay slot. The backtrace from the callee
+ should include the sp adjustment. Unfortunately, that leaves
+ us with an unavoidable unwinding error exactly at the call insn
+ itself. For jump insns we'd prefer to avoid this error by
+ placing the notes after the sequence. */
+ if (JUMP_P (control))
+ add_cfi_insn = insn;
+
for (i = 1; i < n; ++i)
{
elt = XVECEXP (pat, 0, i);
- notice_args_size (elt);
+ scan_insn_after (elt);
}
+
+ /* Make sure any register saves are visible at the jump target. */
+ dwarf2out_flush_queued_reg_saves ();
+
+ /* However, if there is some adjustment on the call itself, e.g.
+ a call_pop, that action should be considered to happen after
+ the call returns. */
+ add_cfi_insn = insn;
+ scan_insn_after (control);
}
else
- notice_args_size (insn);
+ {
+ /* Flush data before calls and jumps, and of course if necessary. */
+ if (can_throw_internal (insn))
+ {
+ notice_eh_throw (insn);
+ dwarf2out_flush_queued_reg_saves ();
+ }
+ else if (!NONJUMP_INSN_P (insn)
+ || clobbers_queued_reg_save (insn)
+ || find_reg_note (insn, REG_CFA_FLUSH_QUEUE, NULL))
+ dwarf2out_flush_queued_reg_saves ();
+
+ add_cfi_insn = insn;
+ scan_insn_after (insn);
+ control = insn;
+ }
/* Between frame-related-p and args_size we might have otherwise
emitted two cfa adjustments. Do it now. */
@@ -2468,7 +2512,7 @@ scan_trace (dw_trace_info *trace)
same tests as are done to actually create the edges. So
always call the routine and let it not create edges for
non-control-flow insns. */
- create_trace_edges (insn);
+ create_trace_edges (control);
}
add_cfi_insn = NULL;