OSDN Git Service

* config/mips/iris5.h (UNALIGNED_INT_ASM_OP,
[pf3gnuchains/gcc-fork.git] / gcc / function.c
index 54dd308..6ecf099 100644 (file)
@@ -57,6 +57,7 @@ Boston, MA 02111-1307, USA.  */
 #include "hash.h"
 #include "ggc.h"
 #include "tm_p.h"
+#include "integrate.h"
 
 #ifndef TRAMPOLINE_ALIGNMENT
 #define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY
@@ -2873,8 +2874,11 @@ gen_mem_addressof (reg, decl)
   if (decl)
     {
       tree type = TREE_TYPE (decl);
+      enum machine_mode decl_mode
+       = (TREE_CODE (decl) == SAVE_EXPR ? TYPE_MODE (TREE_TYPE (decl))
+          : DECL_MODE (decl));
 
-      PUT_MODE (reg, DECL_MODE (decl));
+      PUT_MODE (reg, decl_mode);
       MEM_VOLATILE_P (reg) = TREE_SIDE_EFFECTS (decl);
       MEM_SET_IN_STRUCT_P (reg, AGGREGATE_TYPE_P (type));
       MEM_ALIAS_SET (reg) = get_alias_set (decl);
@@ -6270,6 +6274,29 @@ expand_main_function ()
 \f
 extern struct obstack permanent_obstack;
 
+/* The PENDING_SIZES represent the sizes of variable-sized types.
+   Create RTL for the various sizes now (using temporary variables),
+   so that we can refer to the sizes from the RTL we are generating
+   for the current function.  The PENDING_SIZES are a TREE_LIST.  The
+   TREE_VALUE of each node is a SAVE_EXPR.  */
+
+void
+expand_pending_sizes (pending_sizes)
+     tree pending_sizes;
+{
+  tree tem;
+
+  /* Evaluate now the sizes of any types declared among the arguments.  */
+  for (tem = pending_sizes; tem; tem = TREE_CHAIN (tem))
+    {
+      expand_expr (TREE_VALUE (tem), const0_rtx, VOIDmode,
+                  EXPAND_MEMORY_USE_BAD);
+      /* Flush the queue in case this parameter declaration has
+        side-effects.  */
+      emit_queue ();
+    }
+}
+
 /* Start the RTL for a new function, and set variables used for
    emitting RTL.
    SUBR is the FUNCTION_DECL node.
@@ -6366,13 +6393,10 @@ expand_function_start (subr, parms_have_cleanups)
   else if (DECL_MODE (DECL_RESULT (subr)) == VOIDmode)
     /* If return mode is void, this decl rtl should not be used.  */
     SET_DECL_RTL (DECL_RESULT (subr), NULL_RTX);
-  else if (parms_have_cleanups
-          || current_function_instrument_entry_exit
-          || (flag_exceptions && USING_SJLJ_EXCEPTIONS))
+  else
     {
-      /* If function will end with cleanup code for parms, compute the
-        return values into a pseudo reg, which we will copy into the
-        true return register after the cleanups are done.  */
+      /* Compute the return values into a pseudo reg, which we will copy
+        into the true return register after the cleanups are done.  */
 
       /* In order to figure out what mode to use for the pseudo, we
         figure out what the mode of the eventual return register will
@@ -6381,29 +6405,15 @@ expand_function_start (subr, parms_have_cleanups)
        = hard_function_value (TREE_TYPE (DECL_RESULT (subr)),
                               subr, 1);
 
-      /* Since we know the return value is not an aggregate, we should
-        have a REG here.  */
-      if (!REG_P (hard_reg))
-       abort ();
-
-      /* Create the pseudo.  */
-      SET_DECL_RTL (DECL_RESULT (subr), 
-                   gen_reg_rtx (GET_MODE (hard_reg)));
-      /* Needed because we may need to move this to memory
-        in case it's a named return value whose address is taken.  */
-      DECL_REGISTER (DECL_RESULT (subr)) = 1;
-    }
-  else
-    {
-      /* Scalar, returned in a register.  */
-      SET_DECL_RTL (DECL_RESULT (subr),
-                   hard_function_value (TREE_TYPE (DECL_RESULT (subr)), 
-                                        subr, 1));
-
-      /* Mark this reg as the function's return value.  */
-      if (GET_CODE (DECL_RTL (DECL_RESULT (subr))) == REG)
+      /* Structures that are returned in registers are not aggregate_value_p,
+        so we may see a PARALLEL.  Don't play pseudo games with this.  */
+      if (! REG_P (hard_reg))
+       SET_DECL_RTL (DECL_RESULT (subr), hard_reg);
+      else
        {
-         REG_FUNCTION_VALUE_P (DECL_RTL (DECL_RESULT (subr))) = 1;
+         /* Create the pseudo.  */
+         SET_DECL_RTL (DECL_RESULT (subr), gen_reg_rtx (GET_MODE (hard_reg)));
+
          /* Needed because we may need to move this to memory
             in case it's a named return value whose address is taken.  */
          DECL_REGISTER (DECL_RESULT (subr)) = 1;
@@ -6504,14 +6514,7 @@ expand_function_start (subr, parms_have_cleanups)
   tail_recursion_reentry = emit_note (NULL, NOTE_INSN_DELETED);
 
   /* Evaluate now the sizes of any types declared among the arguments.  */
-  for (tem = nreverse (get_pending_sizes ()); tem; tem = TREE_CHAIN (tem))
-    {
-      expand_expr (TREE_VALUE (tem), const0_rtx, VOIDmode,
-                  EXPAND_MEMORY_USE_BAD);
-      /* Flush the queue in case this parameter declaration has
-        side-effects.  */
-      emit_queue ();
-    }
+  expand_pending_sizes (nreverse (get_pending_sizes ()));
 
   /* Make sure there is a line number after the function entry setup code.  */
   force_next_line_note ();
@@ -6543,37 +6546,10 @@ diddle_return_value (doit, arg)
      void *arg;
 {
   rtx outgoing = current_function_return_rtx;
-  int pcc;
 
   if (! outgoing)
     return;
 
-  pcc = (current_function_returns_struct
-        || current_function_returns_pcc_struct);
-
-  if ((GET_CODE (outgoing) == REG
-       && REGNO (outgoing) >= FIRST_PSEUDO_REGISTER)
-      || pcc)
-    {
-      tree type = TREE_TYPE (DECL_RESULT (current_function_decl));
-
-      /* A PCC-style return returns a pointer to the memory in which
-        the structure is stored.  */
-      if (pcc)
-       type = build_pointer_type (type);
-
-#ifdef FUNCTION_OUTGOING_VALUE
-      outgoing = FUNCTION_OUTGOING_VALUE (type, current_function_decl);
-#else
-      outgoing = FUNCTION_VALUE (type, current_function_decl);
-#endif
-      /* If this is a BLKmode structure being returned in registers, then use
-        the mode computed in expand_return.  */
-      if (GET_MODE (outgoing) == BLKmode)
-       PUT_MODE (outgoing, GET_MODE (current_function_return_rtx));
-      REG_FUNCTION_VALUE_P (outgoing) = 1;
-    }
-
   if (GET_CODE (outgoing) == REG)
     (*doit) (outgoing, arg);
   else if (GET_CODE (outgoing) == PARALLEL)
@@ -6602,6 +6578,17 @@ void
 clobber_return_register ()
 {
   diddle_return_value (do_clobber_return_reg, NULL);
+
+  /* In case we do use pseudo to return value, clobber it too.  */
+  if (DECL_RTL_SET_P (DECL_RESULT (current_function_decl)))
+    {
+      tree decl_result = DECL_RESULT (current_function_decl);
+      rtx decl_rtl = DECL_RTL (decl_result);
+      if (REG_P (decl_rtl) && REGNO (decl_rtl) >= FIRST_PSEUDO_REGISTER)
+       {
+         do_clobber_return_reg (decl_rtl, NULL);
+       }
+    }
 }
 
 static void
@@ -6631,6 +6618,7 @@ expand_function_end (filename, line, end_bindings)
      int end_bindings;
 {
   tree link;
+  rtx clobber_after;
 
 #ifdef TRAMPOLINE_TEMPLATE
   static rtx initial_trampoline;
@@ -6777,17 +6765,11 @@ expand_function_end (filename, line, end_bindings)
      registers so that they are not propogated live to the rest of
      the function.  This can only happen with functions that drop
      through; if there had been a return statement, there would
-     have either been a return rtx, or a jump to the return label.  */
-  {
-    rtx before, after;
-    
-    before = get_last_insn ();
-    clobber_return_register ();
-    after = get_last_insn ();
-    
-    if (before != after)
-      cfun->x_clobber_return_insn = after;
-  }
+     have either been a return rtx, or a jump to the return label.
+
+     We delay actual code generation after the current_function_value_rtx
+     is computed.  */
+  clobber_after = get_last_insn ();
 
   /* Output the label for the actual return from the function,
      if one is expected.  This happens either because a function epilogue
@@ -6936,6 +6918,21 @@ expand_function_end (filename, line, end_bindings)
      communicate between __builtin_eh_return and the epilogue.  */
   expand_eh_return ();
 
+  /* Emit the actual code to clobber return register.  */
+  {
+    rtx seq, after;
+    
+    start_sequence ();
+    clobber_return_register ();
+    seq = gen_sequence ();
+    end_sequence ();
+
+    after = emit_insn_after (seq, clobber_after);
+    
+    if (clobber_after != after)
+      cfun->x_clobber_return_insn = after;
+  }
+
   /* ??? This should no longer be necessary since stupid is no longer with
      us, but there are some parts of the compiler (eg reload_combine, and
      sh mach_dep_reorg) that still try and compute their own lifetime info
@@ -7605,6 +7602,8 @@ mark_function_status (p)
   ggc_mark_rtx (p->x_nonlocal_goto_handler_labels);
   ggc_mark_rtx (p->x_nonlocal_goto_stack_level);
   ggc_mark_tree (p->x_nonlocal_labels);
+
+  mark_hard_reg_initial_vals (p);
 }
 
 /* Mark the function chain ARG (which is really a struct function **)