h8300: Generate correct unwind info around swap_into/out_of_er6.
authorRichard Henderson <rth@redhat.com>
Tue, 2 Aug 2011 19:56:29 +0000 (12:56 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Tue, 2 Aug 2011 19:56:29 +0000 (12:56 -0700)
Minimal bug fix is to unset RTX_FRAME_RELATED_P on the PUSH
insn generated in h8300_swap_into_er6.  But with a tiny bit
of effort we can generate real unwind info around the sequence.

From-SVN: r177209

gcc/ChangeLog
gcc/config/h8300/h8300.c
gcc/dwarf2cfi.c

index caf57be..6745886 100644 (file)
@@ -1,3 +1,9 @@
+2011-08-02  Richard Henderson  <rth@redhat.com>
+
+       * config/h8300/h8300.c (push, pop): Return the insn.
+       (h8300_swap_into_er6): Generate correct unwind info.
+       (h8300_swap_out_of_er6): Likewise.
+
 2011-08-02  H.J. Lu  <hongjiu.lu@intel.com>
 
        * config/i386/driver-i386.c (host_detect_local_cpu): Fix a typo.
index ef48395..a929a28 100644 (file)
@@ -87,8 +87,6 @@ static int h8300_os_task_function_p (tree);
 static void h8300_emit_stack_adjustment (int, HOST_WIDE_INT, bool);
 static HOST_WIDE_INT round_frame_size (HOST_WIDE_INT);
 static unsigned int compute_saved_regs (void);
-static void push (int);
-static void pop (int);
 static const char *cond_string (enum rtx_code);
 static unsigned int h8300_asm_insn_count (const char *);
 static tree h8300_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
@@ -556,7 +554,7 @@ compute_saved_regs (void)
 
 /* Emit an insn to push register RN.  */
 
-static void
+static rtx
 push (int rn)
 {
   rtx reg = gen_rtx_REG (word_mode, rn);
@@ -570,11 +568,12 @@ push (int rn)
     x = gen_push_h8300hs_normal (reg);
   x = F (emit_insn (x), true);
   add_reg_note (x, REG_INC, stack_pointer_rtx);
+  return x;
 }
 
 /* Emit an insn to pop register RN.  */
 
-static void
+static rtx
 pop (int rn)
 {
   rtx reg = gen_rtx_REG (word_mode, rn);
@@ -588,6 +587,7 @@ pop (int rn)
     x = gen_pop_h8300hs_normal (reg);
   x = emit_insn (x);
   add_reg_note (x, REG_INC, stack_pointer_rtx);
+  return x;
 }
 
 /* Emit an instruction to push or pop NREGS consecutive registers
@@ -2678,7 +2678,16 @@ h8sx_emit_movmd (rtx dest, rtx src, rtx length,
 void
 h8300_swap_into_er6 (rtx addr)
 {
-  push (HARD_FRAME_POINTER_REGNUM);
+  rtx insn = push (HARD_FRAME_POINTER_REGNUM);
+  if (frame_pointer_needed)
+    add_reg_note (insn, REG_CFA_DEF_CFA,
+                 plus_constant (gen_rtx_MEM (Pmode, stack_pointer_rtx),
+                                2 * UNITS_PER_WORD));
+  else
+    add_reg_note (insn, REG_CFA_ADJUST_CFA,
+                 gen_rtx_SET (VOIDmode, stack_pointer_rtx,
+                              plus_constant (stack_pointer_rtx, 4)));
+
   emit_move_insn (hard_frame_pointer_rtx, addr);
   if (REGNO (addr) == SP_REG)
     emit_move_insn (hard_frame_pointer_rtx,
@@ -2692,9 +2701,20 @@ h8300_swap_into_er6 (rtx addr)
 void
 h8300_swap_out_of_er6 (rtx addr)
 {
+  rtx insn;
+
   if (REGNO (addr) != SP_REG)
     emit_move_insn (addr, hard_frame_pointer_rtx);
-  pop (HARD_FRAME_POINTER_REGNUM);
+
+  insn = pop (HARD_FRAME_POINTER_REGNUM);
+  RTX_FRAME_RELATED_P (insn) = 1;
+  if (frame_pointer_needed)
+    add_reg_note (insn, REG_CFA_DEF_CFA,
+                 plus_constant (hard_frame_pointer_rtx, 2 * UNITS_PER_WORD));
+  else
+    add_reg_note (insn, REG_CFA_ADJUST_CFA,
+                 gen_rtx_SET (VOIDmode, stack_pointer_rtx,
+                              plus_constant (stack_pointer_rtx, -4)));
 }
 \f
 /* Return the length of mov instruction.  */
index 99b37ab..69218cb 100644 (file)
@@ -778,8 +778,8 @@ def_cfa_1 (dw_cfa_location *new_cfa)
   if (cfi)
     {
       cur_row->cfa = *new_cfa;
-      if (cfi->dw_cfi_opc == DW_CFA_def_cfa_expression)
-        cur_row->cfa_cfi = cfi;
+      cur_row->cfa_cfi = (cfi->dw_cfi_opc == DW_CFA_def_cfa_expression
+                         ? cfi : NULL);
 
       add_cfi (cfi);
     }
@@ -1205,18 +1205,13 @@ dwarf2out_frame_debug_def_cfa (rtx pat)
 
   memset (&loc, 0, sizeof (loc));
 
-  switch (GET_CODE (pat))
+  if (GET_CODE (pat) == PLUS)
     {
-    case PLUS:
-      loc.reg = dwf_regno (XEXP (pat, 0));
       loc.offset = INTVAL (XEXP (pat, 1));
-      break;
-
-    case REG:
-      loc.reg = dwf_regno (pat);
-      break;
-
-    case MEM:
+      pat = XEXP (pat, 0);
+    }
+  if (MEM_P (pat))
+    {
       loc.indirect = 1;
       pat = XEXP (pat, 0);
       if (GET_CODE (pat) == PLUS)
@@ -1224,13 +1219,11 @@ dwarf2out_frame_debug_def_cfa (rtx pat)
          loc.base_offset = INTVAL (XEXP (pat, 1));
          pat = XEXP (pat, 0);
        }
-      loc.reg = dwf_regno (pat);
-      break;
-
-    default:
-      /* Recurse and define an expression.  */
-      gcc_unreachable ();
     }
+  /* ??? If this fails, we could be calling into the _loc functions to
+     define a full expression.  So far no port does that.  */
+  gcc_assert (REG_P (pat));
+  loc.reg = dwf_regno (pat);
 
   def_cfa_1 (&loc);
 }