OSDN Git Service

* tree-inline.c (find_builtin_longjmp_call): Save and restore
[pf3gnuchains/gcc-fork.git] / gcc / function.c
index 479ecef..851dd24 100644 (file)
@@ -1,6 +1,6 @@
 /* Expands front end tree to back end RTL for GNU C-Compiler
    Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -40,6 +40,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "rtl.h"
 #include "tree.h"
 #include "flags.h"
@@ -123,7 +125,7 @@ int current_function_uses_only_leaf_regs;
 int virtuals_instantiated;
 
 /* Assign unique numbers to labels generated for profiling, debugging, etc.  */
-static int funcdef_no;
+static GTY(()) int funcdef_no;
 
 /* These variables hold pointers to functions to create and destroy
    target specific, per-function data structures.  */
@@ -450,6 +452,8 @@ free_after_compilation (f)
   f->x_nonlocal_goto_stack_level = NULL;
   f->x_cleanup_label = NULL;
   f->x_return_label = NULL;
+  f->computed_goto_common_label = NULL;
+  f->computed_goto_common_reg = NULL;
   f->x_save_expr_regs = NULL;
   f->x_stack_slot_list = NULL;
   f->x_rtl_expr_chain = NULL;
@@ -582,11 +586,14 @@ assign_stack_local_1 (mode, size, align, function)
      address relative to the frame pointer.  */
   if (function == cfun && virtuals_instantiated)
     addr = plus_constant (frame_pointer_rtx,
+                         trunc_int_for_mode
                          (frame_offset + bigend_correction
-                          + STARTING_FRAME_OFFSET));
+                          + STARTING_FRAME_OFFSET, Pmode));
   else
     addr = plus_constant (virtual_stack_vars_rtx,
-                         function->x_frame_offset + bigend_correction);
+                         trunc_int_for_mode
+                         (function->x_frame_offset + bigend_correction,
+                          Pmode));
 
 #ifndef FRAME_GROWS_DOWNWARD
   function->x_frame_offset += size;
@@ -731,7 +738,7 @@ assign_stack_temp_for_type (mode, size, keep, type)
        abort ();
       p->slot = assign_stack_local (mode,
                                    (mode == BLKmode
-                                    ? CEIL_ROUND (size, align / BITS_PER_UNIT)
+                                    ? CEIL_ROUND (size, (int) align / BITS_PER_UNIT)
                                     : size),
                                    align);
 
@@ -798,7 +805,8 @@ assign_stack_temp_for_type (mode, size, keep, type)
   /* If a type is specified, set the relevant flags.  */
   if (type != 0)
     {
-      RTX_UNCHANGING_P (slot) = TYPE_READONLY (type);
+      RTX_UNCHANGING_P (slot) = (lang_hooks.honor_readonly 
+                                && TYPE_READONLY (type));
       MEM_VOLATILE_P (slot) = TYPE_VOLATILE (type);
       MEM_SET_IN_STRUCT_P (slot, AGGREGATE_TYPE_P (type));
     }
@@ -1251,46 +1259,6 @@ push_temp_slots ()
   temp_slot_level++;
 }
 
-/* Likewise, but save the new level as the place to allocate variables
-   for blocks.  */
-
-#if 0
-void
-push_temp_slots_for_block ()
-{
-  push_temp_slots ();
-
-  var_temp_slot_level = temp_slot_level;
-}
-
-/* Likewise, but save the new level as the place to allocate temporaries
-   for TARGET_EXPRs.  */
-
-void
-push_temp_slots_for_target ()
-{
-  push_temp_slots ();
-
-  target_temp_slot_level = temp_slot_level;
-}
-
-/* Set and get the value of target_temp_slot_level.  The only
-   permitted use of these functions is to save and restore this value.  */
-
-int
-get_target_temp_slot_level ()
-{
-  return target_temp_slot_level;
-}
-
-void
-set_target_temp_slot_level (level)
-     int level;
-{
-  target_temp_slot_level = level;
-}
-#endif
-
 /* Pop a temporary nesting level.  All slots in use in the current level
    are freed.  */
 
@@ -2379,7 +2347,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
               copy SET_SRC (x) to SET_DEST (x) in some way.  So
               we generate the move and see whether it requires more
               than one insn.  If it does, we emit those insns and
-              delete INSN.  Otherwise, we an just replace the pattern
+              delete INSN.  Otherwise, we can just replace the pattern
               of INSN; we have already verified above that INSN has
               no other function that to do X.  */
 
@@ -3044,10 +3012,7 @@ purge_addressof_1 (loc, insn, force, store, ht)
       rtx sub, insns;
 
       if (GET_CODE (XEXP (x, 0)) != MEM)
-       {
-         put_addressof_into_stack (x, ht);
-         return true;
-       }
+       put_addressof_into_stack (x, ht);
 
       /* We must create a copy of the rtx because it was created by
         overwriting a REG rtx which is always shared.  */
@@ -3409,8 +3374,7 @@ purge_addressof (insns)
   compute_insns_for_mem (insns, NULL_RTX, ht);
 
   for (insn = insns; insn; insn = NEXT_INSN (insn))
-    if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
-       || GET_CODE (insn) == CALL_INSN)
+    if (INSN_P (insn))
       {
        if (! purge_addressof_1 (&PATTERN (insn), insn,
                                 asm_noperands (PATTERN (insn)) > 0, 0, ht))
@@ -4045,6 +4009,8 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
     case ABS:
     case SQRT:
     case FFS:
+    case CLZ:          case CTZ:
+    case POPCOUNT:     case PARITY:
       /* These case either have just one operand or we know that we need not
         check the rest of the operands.  */
       loc = &XEXP (x, 0);
@@ -4180,12 +4146,6 @@ delete_handlers ()
     }
 }
 \f
-int
-max_parm_reg_num ()
-{
-  return max_parm_reg;
-}
-
 /* Return the first insn following those generated by `assign_parms'.  */
 
 rtx
@@ -4196,24 +4156,6 @@ get_first_nonparm_insn ()
   return get_insns ();
 }
 
-/* Return the first NOTE_INSN_BLOCK_BEG note in the function.
-   Crash if there is none.  */
-
-rtx
-get_first_block_beg ()
-{
-  rtx searcher;
-  rtx insn = get_first_nonparm_insn ();
-
-  for (searcher = insn; searcher; searcher = NEXT_INSN (searcher))
-    if (GET_CODE (searcher) == NOTE
-       && NOTE_LINE_NUMBER (searcher) == NOTE_INSN_BLOCK_BEG)
-      return searcher;
-
-  abort ();    /* Invalid call to this function.  (See comments above.)  */
-  return NULL_RTX;
-}
-
 /* Return 1 if EXP is an aggregate type (or a value with aggregate type).
    This means a type for which function calls must pass an address to the
    function or get an address back from the function.
@@ -4334,7 +4276,7 @@ assign_parms (fndecl)
 #ifdef INIT_CUMULATIVE_INCOMING_ARGS
   INIT_CUMULATIVE_INCOMING_ARGS (args_so_far, fntype, NULL_RTX);
 #else
-  INIT_CUMULATIVE_ARGS (args_so_far, fntype, NULL_RTX, 0);
+  INIT_CUMULATIVE_ARGS (args_so_far, fntype, NULL_RTX, fndecl);
 #endif
 
   /* We haven't yet found an argument that we must push and pretend the
@@ -4515,6 +4457,10 @@ assign_parms (fndecl)
                                                  offset_rtx));
 
        set_mem_attributes (stack_parm, parm, 1);
+
+       /* Set also REG_ATTRS if parameter was passed in a register.  */
+       if (entry_parm)
+         set_reg_attrs_for_parm (entry_parm, stack_parm);
       }
 
       /* If this parameter was passed both in registers and in the stack,
@@ -4538,6 +4484,12 @@ assign_parms (fndecl)
 
          if (nregs > 0)
            {
+#if defined (REG_PARM_STACK_SPACE) && !defined (MAYBE_REG_PARM_STACK_SPACE)
+             /* When REG_PARM_STACK_SPACE is nonzero, stack space for
+                split parameters was allocated by our caller, so we
+                won't be pushing it in the prolog.  */
+             if (REG_PARM_STACK_SPACE (fndecl) == 0)
+#endif
              current_function_pretend_args_size
                = (((nregs * UNITS_PER_WORD) + (PARM_BOUNDARY / BITS_PER_UNIT) - 1)
                   / (PARM_BOUNDARY / BITS_PER_UNIT)
@@ -5060,15 +5012,6 @@ assign_parms (fndecl)
          set_mem_attributes (x, result, 1);
          SET_DECL_RTL (result, x);
        }
-
-      if (GET_CODE (DECL_RTL (parm)) == REG)
-       REGNO_DECL (REGNO (DECL_RTL (parm))) = parm;
-      else if (GET_CODE (DECL_RTL (parm)) == CONCAT)
-       {
-         REGNO_DECL (REGNO (XEXP (DECL_RTL (parm), 0))) = parm;
-         REGNO_DECL (REGNO (XEXP (DECL_RTL (parm), 1))) = parm;
-       }
-
     }
 
   /* Output all parameter conversion instructions (possibly including calls)
@@ -6230,6 +6173,8 @@ prepare_function_start ()
   current_function_calls_longjmp = 0;
 
   current_function_calls_alloca = 0;
+  current_function_calls_eh_return = 0;
+  current_function_calls_constant_p = 0;
   current_function_contains_functions = 0;
   current_function_is_leaf = 0;
   current_function_nothrow = 0;
@@ -6291,8 +6236,6 @@ prepare_function_start ()
 
   cfun->arc_profile = profile_arc_flag || flag_test_coverage;
 
-  cfun->arc_profile = profile_arc_flag || flag_test_coverage;
-
   cfun->function_frequency = FUNCTION_FREQUENCY_NORMAL;
 
   cfun->max_jumptable_ents = 0;
@@ -6558,18 +6501,17 @@ expand_function_start (subr, parms_have_cleanups)
                               subr, 1);
 
       /* 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);
+        so we may see a PARALLEL or a REG.  */
+      if (REG_P (hard_reg))
+       SET_DECL_RTL (DECL_RESULT (subr), gen_reg_rtx (GET_MODE (hard_reg)));
+      else if (GET_CODE (hard_reg) == PARALLEL)
+       SET_DECL_RTL (DECL_RESULT (subr), gen_group_rtx (hard_reg));
       else
-       {
-         /* Create the pseudo.  */
-         SET_DECL_RTL (DECL_RESULT (subr), gen_reg_rtx (GET_MODE (hard_reg)));
+       abort ();
 
-         /* 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;
-       }
+      /* Set DECL_REGISTER flag so that expand_function_end will copy the
+        result to the real return register(s).  */
+      DECL_REGISTER (DECL_RESULT (subr)) = 1;
     }
 
   /* Initialize rtx for parameters and local variables.
@@ -6853,9 +6795,10 @@ expand_function_end (filename, line, end_bindings)
     }
 
   /* Warn about unused parms if extra warnings were specified.  */
-  /* Either ``-W -Wunused'' or ``-Wunused-parameter'' enables this
+  /* Either ``-Wextra -Wunused'' or ``-Wunused-parameter'' enables this
      warning.  WARN_UNUSED_PARAMETER is negative when set by
-     -Wunused.  */
+     -Wunused.  Note that -Wall implies -Wunused, so ``-Wall -Wextra'' will
+     also give these warnings.  */
   if (warn_unused_parameter > 0
       || (warn_unused_parameter < 0 && extra_warnings))
     {
@@ -6997,8 +6940,16 @@ expand_function_end (filename, line, end_bindings)
              convert_move (real_decl_rtl, decl_rtl, unsignedp);
            }
          else if (GET_CODE (real_decl_rtl) == PARALLEL)
-           emit_group_load (real_decl_rtl, decl_rtl,
-                            int_size_in_bytes (TREE_TYPE (decl_result)));
+           {
+             /* If expand_function_start has created a PARALLEL for decl_rtl,
+                move the result to the real return registers.  Otherwise, do
+                a group load from decl_rtl for a named return.  */
+             if (GET_CODE (decl_rtl) == PARALLEL)
+               emit_group_move (real_decl_rtl, decl_rtl);
+             else
+               emit_group_load (real_decl_rtl, decl_rtl,
+                                int_size_in_bytes (TREE_TYPE (decl_result)));
+           }
          else
            emit_move_insn (real_decl_rtl, decl_rtl);
        }
@@ -7198,10 +7149,7 @@ emit_return_into_block (bb, line_note)
      basic_block bb;
      rtx line_note;
 {
-  rtx p, end;
-
-  p = NEXT_INSN (bb->end);
-  end = emit_jump_insn_after (gen_return (), bb->end);
+  emit_jump_insn_after (gen_return (), bb->end);
   if (line_note)
     emit_line_note_after (NOTE_SOURCE_FILE (line_note),
                          NOTE_LINE_NUMBER (line_note), PREV_INSN (bb->end));
@@ -7857,8 +7805,6 @@ reposition_prologue_and_epilogue_notes (f)
 
       if (last)
        {
-         rtx next;
-
          /* Find the prologue-end note if we haven't already, and
             move it to just after the last prologue insn.  */
          if (note == 0)
@@ -7869,8 +7815,6 @@ reposition_prologue_and_epilogue_notes (f)
                  break;
            }
 
-         next = NEXT_INSN (note);
-
          /* Avoid placing note between CODE_LABEL and BASIC_BLOCK note.  */
          if (GET_CODE (last) == CODE_LABEL)
            last = NEXT_INSN (last);