Commit eebc8f37 by Richard Henderson

re PR rtl-optimization/49977 (CFI notes are missed for delayed slot)

PR rtl-opt/49977
        * dwarf2cfi.c (scan_insn_after): Split out of ...
        (scan_trace): ... here.  Correctly place notes wrt sequences.

From-SVN: r177466
parent 6fe818aa
......@@ -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;
......
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