rs6000.h (INIT_EXPANDERS): Delete.
authorFranz Sirl <Franz.Sirl-kernel@lauterbach.com>
Mon, 22 Jan 2001 22:47:25 +0000 (22:47 +0000)
committerFranz Sirl <sirl@gcc.gnu.org>
Mon, 22 Jan 2001 22:47:25 +0000 (22:47 +0000)
        2001-01-22  Franz Sirl  <Franz.Sirl-kernel@lauterbach.com>

        * rs6000.h (INIT_EXPANDERS): Delete.
        (RETURN_ADDR_RTX): Call rs6000_return_addr().
        * rs6000.c (rs6000_override_options): Call *_machine_status from
        here...
        (rs6000_init_expanders): ...instead of here. Delete.
        (rs6000_mark_machine_status): New function.
        (rs6000_init_machine_status): Use xcalloc.
        (rs6000_return_addr): Generate RTX for the return address.
        (rs6000_ra_ever_killed): New, check if LR was ever destroyed.
        (rs6000_stack_info): Use it.

From-SVN: r39188

gcc/ChangeLog
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h

index 5e2f57d45a4277e7a2592df81a374fd4fbf713eb..26d488d35186f565e579ae29df3d3716af229c47 100644 (file)
@@ -1,3 +1,16 @@
+2001-01-22  Franz Sirl  <Franz.Sirl-kernel@lauterbach.com>
+
+       * rs6000.h (INIT_EXPANDERS): Delete.
+       (RETURN_ADDR_RTX): Call rs6000_return_addr().
+       * rs6000.c (rs6000_override_options): Call *_machine_status from
+       here...
+       (rs6000_init_expanders): ...instead of here. Delete.
+       (rs6000_mark_machine_status): New function.
+       (rs6000_init_machine_status): Use xcalloc.
+       (rs6000_return_addr): Generate RTX for the return address.
+       (rs6000_ra_ever_killed): New, check if LR was ever destroyed.
+       (rs6000_stack_info): Use it.
+
 2001-01-22  Thomas Pfaff  <tpfaff@gmx.net>
 
        * gthr-win32.h: Include errno.h to get a declaration for
index 318adb28e7f5bdb05972ac42b48caf26be81add1..3fa0e0a43c1b951e9017931e0d612be96ebb4f88 100644 (file)
@@ -122,6 +122,8 @@ static void toc_hash_mark_table PARAMS ((void *));
 static int constant_pool_expr_1 PARAMS ((rtx, int *, int *));
 static void rs6000_free_machine_status PARAMS ((struct function *));
 static void rs6000_init_machine_status PARAMS ((struct function *));
+static void rs6000_mark_machine_status PARAMS ((struct function *));
+static int rs6000_ra_ever_killed PARAMS ((void));
 \f
 /* Default register names.  */
 char rs6000_reg_names[][8] =
@@ -399,6 +401,11 @@ rs6000_override_options (default_cpu)
 
   if (TARGET_TOC) 
     ASM_GENERATE_INTERNAL_LABEL (toc_label_name, "LCTOC", 1);
+
+  /* Arrange to save and restore machine status around nested functions.  */
+  init_machine_status = rs6000_init_machine_status;
+  mark_machine_status = rs6000_mark_machine_status;
+  free_machine_status = rs6000_free_machine_status;
 }
 
 void
@@ -3619,7 +3626,7 @@ rs6000_got_register (value)
   return pic_offset_table_rtx;
 }
 \f
-/* Functions to save and restore sysv_varargs_p.
+/* Functions to init, mark and free struct machine_function.
    These will be called, via pointer variables,
    from push_function_context and pop_function_context.  */
 
@@ -3627,9 +3634,15 @@ static void
 rs6000_init_machine_status (p)
      struct function *p;
 {
-  p->machine = (machine_function *) xmalloc (sizeof (machine_function));
+  p->machine = (machine_function *) xcalloc (1, sizeof (machine_function));
+}
 
-  p->machine->sysv_varargs_p = 0;
+static void
+rs6000_mark_machine_status (p)
+     struct function *p;
+{
+  if (p->machine)
+    ggc_mark_rtx (p->machine->ra_rtx);
 }
 
 static void
@@ -3643,17 +3656,6 @@ rs6000_free_machine_status (p)
   p->machine = NULL;
 }
 
-
-/* Do anything needed before RTL is emitted for each function.  */
-
-void
-rs6000_init_expanders ()
-{
-  /* Arrange to save and restore machine status around nested functions.  */
-  init_machine_status = rs6000_init_machine_status;
-  free_machine_status = rs6000_free_machine_status;
-}
-
 \f
 /* Print an operand.  Recognize special options, documented below.  */
 
@@ -4824,10 +4826,11 @@ rs6000_stack_info ()
   info_ptr->fp_size = 8 * (64 - info_ptr->first_fp_reg_save);
 
   /* Does this function call anything? */
-  info_ptr->calls_p = ! current_function_is_leaf;
+  info_ptr->calls_p = (! current_function_is_leaf
+                      || cfun->machine->ra_needs_full_frame);
 
   /* Determine if we need to save the link register */
-  if (regs_ever_live[LINK_REGISTER_REGNUM]
+  if (rs6000_ra_ever_killed ()
       || (DEFAULT_ABI == ABI_AIX && profile_flag)
 #ifdef TARGET_RELOCATABLE
       || (TARGET_RELOCATABLE && (get_pool_size () != 0))
@@ -5043,6 +5046,66 @@ debug_stack_info (info)
 
   fprintf (stderr, "\n");
 }
+
+rtx
+rs6000_return_addr (count, frame)
+     int count;
+     rtx frame;
+{
+  rtx init, reg;
+
+  /* Currently we don't optimize very well between prolog and body code and
+     for PIC code the code can be actually quite bad, so don't try to be
+     too clever here.  */
+  if (count != 0 || flag_pic != 0)
+    {
+      cfun->machine->ra_needs_full_frame = 1;
+      return
+       gen_rtx_MEM (Pmode,
+         memory_address (Pmode,
+                         plus_constant (copy_to_reg (gen_rtx_MEM (Pmode,
+                                                                  memory_address (Pmode, frame))),
+                                        RETURN_ADDRESS_OFFSET)));
+    }
+
+  reg = cfun->machine->ra_rtx;
+  if (reg == NULL)
+    {
+      /* No rtx yet.  Invent one, and initialize it from LR in
+         the prologue.  */
+      reg = gen_reg_rtx (Pmode);
+      cfun->machine->ra_rtx = reg;
+      init = gen_rtx_SET (VOIDmode, reg,
+                         gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM));
+
+      /* Emit the insn to the prologue with the other argument copies.  */
+      push_topmost_sequence ();
+      emit_insn_after (init, get_insns ());
+      pop_topmost_sequence ();
+    }
+
+  return reg;
+}
+
+static int
+rs6000_ra_ever_killed ()
+{
+  rtx top;
+
+#ifdef ASM_OUTPUT_MI_THUNK
+  if (current_function_is_thunk)
+    return 0;
+#endif
+  if (!cfun->machine->ra_rtx || cfun->machine->ra_needs_full_frame)
+    return regs_ever_live[LINK_REGISTER_REGNUM];
+
+  push_topmost_sequence ();
+  top = get_insns ();
+  pop_topmost_sequence ();
+
+  return reg_set_between_p (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM), 
+                           top, NULL_RTX);
+}
 \f
 /* Add a REG_MAYBE_DEAD note to the insn.  */
 static void
@@ -5553,7 +5616,7 @@ rs6000_emit_prologue()
 
   /* If we use the link register, get it into r0.  */
   if (info->lr_save_p)
-    emit_move_insn (gen_rtx_REG (Pmode, 0), 
+    emit_move_insn (gen_rtx_REG (Pmode, 0),
                    gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM));
 
   /* If we need to save CR, put it into r12.  */
index 27079b3944c5bbd8c4499c8658f913b331de4f84..54e987424e4a7ff095aac2ffaf5ad9d83dfcb7ad 100644 (file)
@@ -1229,10 +1229,6 @@ typedef struct rs6000_stack {
 /* Align an address */
 #define RS6000_ALIGN(n,a) (((n) + (a) - 1) & ~((a) - 1))
 
-/* Initialize data used by insn expanders.  This is called from
-   init_emit, once for each function, before code is generated. */
-#define INIT_EXPANDERS rs6000_init_expanders ()
-
 /* Size of V.4 varargs area in bytes */
 #define RS6000_VARARGS_SIZE \
   ((GP_ARG_NUM_REG * (TARGET_32BIT ? 4 : 8)) + (FP_ARG_NUM_REG * 8) + 8)
@@ -1388,6 +1384,10 @@ typedef struct machine_function
 {
   /* Whether a System V.4 varargs area was created.  */
   int sysv_varargs_p;
+  /* Set if a return address rtx for loading from LR was created.  */
+  struct rtx_def *ra_rtx;
+  /* Flags if __builtin_return_address (n) with n >= 1 was used.  */
+  int ra_needs_full_frame;
 } machine_function;
 
 /* Define a data type for recording info about an argument list
@@ -1649,17 +1649,12 @@ typedef struct rs6000_args
 /* The current return address is in link register (65).  The return address
    of anything farther back is accessed normally at an offset of 8 from the
    frame pointer.  */
-#define RETURN_ADDR_RTX(COUNT, FRAME)                  \
-  (((COUNT) == -1)                                     \
-   ? gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)         \
-   : gen_rtx_MEM (Pmode,                               \
-                 memory_address                        \
-                 (Pmode,                               \
-                  plus_constant (copy_to_reg           \
-                                 (gen_rtx_MEM (Pmode,  \
-                                               memory_address (Pmode, \
-                                                               (FRAME)))), \
-                                 RETURN_ADDRESS_OFFSET))))
+#define RETURN_ADDR_RTX(COUNT, FRAME)                 \
+  (rs6000_return_addr (COUNT, FRAME))
+
+extern struct rtx_def* rs6000_return_addr (int, struct rtx_def *rtx);
+
+
 \f
 /* Definitions for register eliminations.