This seems to do the trick for sim testing of sh-elf and cris-elf.

I'm interested in advice re debugging experiences with delay slots.
It seems like for calls there's no alternative but to have the unwind
info be incorrect when stopped at the call insn itself.

It also seems like we've similarly been generating unwind info that
was incorrect for branches with frame-related insns in delay slots.
Further, that by delaying the unwind info until after the sequence
we can avoid that incorrectness.

Have any of you experienced that incorrectness before, when debugging
on your respective targets?


r~
diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
index f6ab38d..80cce32 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;

Reply via email to