arm.c: Include "debug.h".
authorDaniel Jacobowitz <drow@mvista.com>
Thu, 22 Jan 2004 17:00:56 +0000 (17:00 +0000)
committerDaniel Jacobowitz <drow@gcc.gnu.org>
Thu, 22 Jan 2004 17:00:56 +0000 (17:00 +0000)
* config/arm/arm.c: Include "debug.h".
(thumb_pushpop): Take two new arguments.  Add some commentary.
Output frame information when pushing.
(thumb_exit, thumb_unexpanded_epilogue): Update calls to
thumb_pushpop.
(thumb_output_function_prologue): Likewise.  Accumulate a CFA
offset, and pass it to thumb_pushpop.  Output CFI information.
(thumb_expand_prologue): Add some frame-related markers and notes.

From-SVN: r76362

gcc/ChangeLog
gcc/config/arm/arm.c

index 2d68f8a9baa385e9cedef7e7aac0aed4b38b921e..57bb86397e6b1e9e2f6248787899d4fbf3d3a073 100644 (file)
@@ -1,3 +1,14 @@
+2004-01-22  Daniel Jacobowitz  <drow@mvista.com>
+
+       * config/arm/arm.c: Include "debug.h".
+       (thumb_pushpop): Take two new arguments.  Add some commentary. 
+       Output frame information when pushing.
+       (thumb_exit, thumb_unexpanded_epilogue): Update calls to
+       thumb_pushpop.
+       (thumb_output_function_prologue): Likewise.  Accumulate a CFA
+       offset, and pass it to thumb_pushpop.  Output CFI information.
+       (thumb_expand_prologue): Add some frame-related markers and notes.
+
 2004-01-22  Ulrich Weigand  <uweigand@de.ibm.com>
 
        * config/s390/s390.c (s390_frame_info): Allow large frame sizes
index 6cf226e2c4cb9ebf74077f6218d21098856e53e5..826bbac0fabf8362e1569c70d0f053e80ff4698b 100644 (file)
@@ -50,6 +50,7 @@
 #include "tm_p.h"
 #include "target.h"
 #include "target-def.h"
+#include "debug.h"
 
 /* Forward definitions of types.  */
 typedef struct minipool_node    Mnode;
@@ -85,7 +86,7 @@ static struct machine_function *arm_init_machine_status (void);
 static int number_of_first_bit_set (int);
 static void replace_symbols_in_block (tree, rtx, rtx);
 static void thumb_exit (FILE *, int, rtx);
-static void thumb_pushpop (FILE *, int, int);
+static void thumb_pushpop (FILE *, int, int, int *, int);
 static rtx is_jump_table (rtx);
 static HOST_WIDE_INT get_jump_table_size (rtx);
 static Mnode *move_minipool_fix_forward_ref (Mnode *, Mnode *, HOST_WIDE_INT);
@@ -11562,7 +11563,8 @@ thumb_exit (FILE *f, int reg_containing_return_addr, rtx eh_ofs)
     }
 
   /* Pop as many registers as we can.  */
-  thumb_pushpop (f, regs_available_for_popping, FALSE);
+  thumb_pushpop (f, regs_available_for_popping, FALSE, NULL,
+                regs_available_for_popping);
 
   /* Process the registers we popped.  */
   if (reg_containing_return_addr == -1)
@@ -11643,7 +11645,8 @@ thumb_exit (FILE *f, int reg_containing_return_addr, rtx eh_ofs)
       int  popped_into;
       int  move_to;
       
-      thumb_pushpop (f, regs_available_for_popping, FALSE);
+      thumb_pushpop (f, regs_available_for_popping, FALSE, NULL,
+                    regs_available_for_popping);
 
       /* We have popped either FP or SP.
         Move whichever one it is into the correct register.  */
@@ -11663,7 +11666,8 @@ thumb_exit (FILE *f, int reg_containing_return_addr, rtx eh_ofs)
     {
       int  popped_into;
       
-      thumb_pushpop (f, regs_available_for_popping, FALSE);
+      thumb_pushpop (f, regs_available_for_popping, FALSE, NULL,
+                    regs_available_for_popping);
 
       popped_into = number_of_first_bit_set (regs_available_for_popping);
 
@@ -11693,12 +11697,20 @@ thumb_exit (FILE *f, int reg_containing_return_addr, rtx eh_ofs)
   asm_fprintf (f, "\tbx\t%r\n", reg_containing_return_addr);
 }
 
-/* Emit code to push or pop registers to or from the stack.  */
+/* Emit code to push or pop registers to or from the stack.  F is the
+   assembly file.  MASK is the registers to push or pop.  PUSH is
+   non-zero if we should push, and zero if we should pop.  For debugging
+   output, if pushing, adjust CFA_OFFSET by the amount of space added
+   to the stack.  REAL_REGS should have the same number of bits set as
+   MASK, and will be used instead (in the same order) to describe which
+   registers were saved - this is used to mark the save slots when we
+   push high registers after moving them to low registers.  */
 static void
-thumb_pushpop (FILE *f, int mask, int push)
+thumb_pushpop (FILE *f, int mask, int push, int *cfa_offset, int real_regs)
 {
   int regno;
   int lo_mask = mask & 0xFF;
+  int pushed_words = 0;
 
   if (lo_mask == 0 && !push && (mask & (1 << 15)))
     {
@@ -11719,6 +11731,8 @@ thumb_pushpop (FILE *f, int mask, int push)
          
          if ((lo_mask & ~1) != 0)
            fprintf (f, ", ");
+
+         pushed_words++;
        }
     }
   
@@ -11729,6 +11743,8 @@ thumb_pushpop (FILE *f, int mask, int push)
        fprintf (f, ", ");
       
       asm_fprintf (f, "%r", LR_REGNUM);
+
+      pushed_words++;
     }
   else if (!push && (mask & (1 << PC_REGNUM)))
     {
@@ -11753,6 +11769,23 @@ thumb_pushpop (FILE *f, int mask, int push)
     }
        
   fprintf (f, "}\n");
+
+  if (push && pushed_words && dwarf2out_do_frame ())
+    {
+      char *l = dwarf2out_cfi_label ();
+      int pushed_mask = real_regs;
+
+      *cfa_offset += pushed_words * 4;
+      dwarf2out_def_cfa (l, SP_REGNUM, *cfa_offset);
+
+      pushed_words = 0;
+      pushed_mask = real_regs;
+      for (regno = 0; regno <= 14; regno++, pushed_mask >>= 1)
+       {
+         if (pushed_mask & 1)
+           dwarf2out_reg_save (l, regno, 4 * pushed_words++ - *cfa_offset);
+       }
+    }
 }
 \f
 void
@@ -11951,7 +11984,7 @@ thumb_unexpanded_epilogue (void)
          mask &= (2 << regno) - 1;     /* A noop if regno == 8 */
 
          /* Pop the values into the low register(s).  */
-         thumb_pushpop (asm_out_file, mask, 0);
+         thumb_pushpop (asm_out_file, mask, 0, NULL, mask);
 
          /* Move the value(s) into the high registers.  */
          for (regno = 0; regno <= LAST_LO_REGNUM; regno++)
@@ -11993,7 +12026,8 @@ thumb_unexpanded_epilogue (void)
         structure was created which includes an adjusted stack
         pointer, so just pop everything.  */
       if (live_regs_mask)
-       thumb_pushpop (asm_out_file, live_regs_mask, FALSE);
+       thumb_pushpop (asm_out_file, live_regs_mask, FALSE, NULL,
+                      live_regs_mask);
       
       if (eh_ofs)
        thumb_exit (asm_out_file, 2, eh_ofs);
@@ -12013,11 +12047,13 @@ thumb_unexpanded_epilogue (void)
       live_regs_mask &= ~(1 << PC_REGNUM);
       
       if (live_regs_mask)
-       thumb_pushpop (asm_out_file, live_regs_mask, FALSE);
+       thumb_pushpop (asm_out_file, live_regs_mask, FALSE, NULL,
+                      live_regs_mask);
 
       if (had_to_push_lr)
        /* Get the return address into a temporary register.  */
-       thumb_pushpop (asm_out_file, 1 << LAST_ARG_REGNUM, 0);
+       thumb_pushpop (asm_out_file, 1 << LAST_ARG_REGNUM, 0, NULL,
+                      1 << LAST_ARG_REGNUM);
       
       /* Remove the argument registers that were pushed onto the stack.  */
       asm_fprintf (asm_out_file, "\tadd\t%r, %r, #%d\n",
@@ -12163,6 +12199,8 @@ thumb_get_frame_size (void)
 void
 thumb_expand_prologue (void)
 {
+  rtx insn, dwarf;
+
   HOST_WIDE_INT amount = (thumb_get_frame_size ()
                          + current_function_outgoing_args_size);
   unsigned long func_type;
@@ -12180,15 +12218,21 @@ thumb_expand_prologue (void)
     }
 
   if (frame_pointer_needed)
-    emit_insn (gen_movsi (hard_frame_pointer_rtx, stack_pointer_rtx));
+    {
+      insn = emit_insn (gen_movsi (hard_frame_pointer_rtx, stack_pointer_rtx));
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
 
   if (amount)
     {
       amount = ROUND_UP_WORD (amount);
       
       if (amount < 512)
-       emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
-                              GEN_INT (- amount)));
+       {
+         insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+                                       GEN_INT (- amount)));
+         RTX_FRAME_RELATED_P (insn) = 1;
+       }
       else
        {
          int regno;
@@ -12228,8 +12272,16 @@ thumb_expand_prologue (void)
 
              /* Decrement the stack.  */
              emit_insn (gen_movsi (reg, GEN_INT (- amount)));
-             emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
-                                    reg));
+             insn = emit_insn (gen_addsi3 (stack_pointer_rtx,
+                                           stack_pointer_rtx, reg));
+             RTX_FRAME_RELATED_P (insn) = 1;
+             dwarf = gen_rtx_SET (SImode, stack_pointer_rtx,
+                                  plus_constant (stack_pointer_rtx,
+                                                 GEN_INT (- amount)));
+             RTX_FRAME_RELATED_P (dwarf) = 1;
+             REG_NOTES (insn)
+               = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
+                                    REG_NOTES (insn));
 
              /* Restore the low register's original value.  */
              emit_insn (gen_movsi (reg, spare));
@@ -12245,8 +12297,17 @@ thumb_expand_prologue (void)
              reg = gen_rtx (REG, SImode, regno);
 
              emit_insn (gen_movsi (reg, GEN_INT (- amount)));
-             emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
-                                    reg));
+
+             insn = emit_insn (gen_addsi3 (stack_pointer_rtx,
+                                           stack_pointer_rtx, reg));
+             RTX_FRAME_RELATED_P (insn) = 1;
+             dwarf = gen_rtx_SET (SImode, stack_pointer_rtx,
+                                  plus_constant (stack_pointer_rtx,
+                                                 GEN_INT (- amount)));
+             RTX_FRAME_RELATED_P (dwarf) = 1;
+             REG_NOTES (insn)
+               = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
+                                    REG_NOTES (insn));
            }
        }
     }
@@ -12307,6 +12368,7 @@ thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
 {
   int live_regs_mask = 0;
   int high_regs_pushed = 0;
+  int cfa_offset = 0;
   int regno;
 
   if (IS_NAKED (arm_current_func_type ()))
@@ -12369,6 +12431,16 @@ thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
        asm_fprintf (f, "\tsub\t%r, %r, #%d\n", 
                     SP_REGNUM, SP_REGNUM,
                     current_function_pretend_args_size);
+
+      /* We don't need to record the stores for unwinding (would it
+        help the debugger any if we did?), but record the change in
+        the stack pointer.  */
+      if (dwarf2out_do_frame ())
+       {
+         char *l = dwarf2out_cfi_label ();
+         cfa_offset = cfa_offset + current_function_pretend_args_size;
+         dwarf2out_def_cfa (l, SP_REGNUM, cfa_offset);
+       }
     }
 
   for (regno = 0; regno <= LAST_LO_REGNUM; regno++)
@@ -12424,9 +12496,16 @@ thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
       asm_fprintf
        (f, "\tsub\t%r, %r, #16\t%@ Create stack backtrace structure\n",
         SP_REGNUM, SP_REGNUM);
-      
+
+      if (dwarf2out_do_frame ())
+       {
+         char *l = dwarf2out_cfi_label ();
+         cfa_offset = cfa_offset + 16;
+         dwarf2out_def_cfa (l, SP_REGNUM, cfa_offset);
+       }
+
       if (live_regs_mask)
-       thumb_pushpop (f, live_regs_mask, 1);
+       thumb_pushpop (f, live_regs_mask, 1, &cfa_offset, live_regs_mask);
       
       for (offset = 0, wr = 1 << 15; wr != 0; wr >>= 1)
        if (wr & live_regs_mask)
@@ -12470,7 +12549,7 @@ thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
                   ARM_HARD_FRAME_POINTER_REGNUM, work_register);
     }
   else if (live_regs_mask)
-    thumb_pushpop (f, live_regs_mask, 1);
+    thumb_pushpop (f, live_regs_mask, 1, &cfa_offset, live_regs_mask);
 
   for (regno = 8; regno < 13; regno++)
     if (THUMB_REG_PUSHED_P (regno))
@@ -12498,6 +12577,8 @@ thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
 
       while (high_regs_pushed > 0)
        {
+         int real_regs_mask = 0;
+
          for (regno = LAST_LO_REGNUM; regno >= 0; regno--)
            {
              if (mask & (1 << regno))
@@ -12505,6 +12586,7 @@ thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
                  asm_fprintf (f, "\tmov\t%r, %r\n", regno, next_hi_reg);
                  
                  high_regs_pushed--;
+                 real_regs_mask |= (1 << next_hi_reg);
                  
                  if (high_regs_pushed)
                    {
@@ -12520,8 +12602,8 @@ thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
                    }
                }
            }
-         
-         thumb_pushpop (f, mask, 1);
+
+         thumb_pushpop (f, mask, 1, &cfa_offset, real_regs_mask);
        }
 
       if (pushable_regs == 0