OSDN Git Service

[pf3gnuchains/gcc-fork.git] / gcc / function.c
index 5ad113c..d2eab67 100644 (file)
@@ -138,6 +138,12 @@ int current_function_has_computed_jump;
 
 int current_function_contains_functions;
 
+/* Nonzero if function being compiled doesn't modify the stack pointer
+   (ignoring the prologue and epilogue).  This is only valid after
+   life_analysis has run. */
+
+int current_function_sp_is_unchanging;
+
 /* Nonzero if the current function is a thunk (a lightweight function that
    just adjusts one of its arguments and forwards to another function), so
    we should try to cut corners where we can.  */
@@ -221,6 +227,9 @@ char *current_function_cannot_inline;
    generated.  */
 int current_function_instrument_entry_exit;
 
+/* Nonzero if memory access checking be enabled in the current function.  */
+int current_function_check_memory_usage;
+
 /* The FUNCTION_DECL for an inline function currently being expanded.  */
 tree inline_function_decl;
 
@@ -543,6 +552,7 @@ push_function_context_to (context)
   p->fixup_var_refs_queue = 0;
   p->epilogue_delay_list = current_function_epilogue_delay_list;
   p->args_info = current_function_args_info;
+  p->check_memory_usage = current_function_check_memory_usage;
   p->instrument_entry_exit = current_function_instrument_entry_exit;
 
   save_tree_status (p, context);
@@ -626,6 +636,7 @@ pop_function_context_from (context)
   current_function_epilogue_delay_list = p->epilogue_delay_list;
   reg_renumber = 0;
   current_function_args_info = p->args_info;
+  current_function_check_memory_usage = p->check_memory_usage;
   current_function_instrument_entry_exit = p->instrument_entry_exit;
 
   restore_tree_status (p, context);
@@ -1484,7 +1495,7 @@ put_var_into_stack (decl)
   else
     return;
   
-  if (flag_check_memory_usage)
+  if (current_function_check_memory_usage)
     emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
                       XEXP (reg, 0), ptr_mode,
                       GEN_INT (GET_MODE_SIZE (GET_MODE (reg))),
@@ -2807,6 +2818,10 @@ put_addressof_into_stack (r)
                      TREE_USED (decl) || DECL_INITIAL (decl) != 0);
 }
 
+/* List of replacements made below in purge_addressof_1 when creating
+   bitfield insertions.  */
+static rtx purge_addressof_replacements;
+
 /* Helper function for purge_addressof.  See if the rtx expression at *LOC
    in INSN needs to be changed.  If FORCE, always put any ADDRESSOFs into
    the stack.  */
@@ -2849,7 +2864,7 @@ purge_addressof_1 (loc, insn, force, store)
 
       insns = gen_sequence ();
       end_sequence ();
-      emit_insns_before (insns, insn);
+      emit_insn_before (insns, insn);
       return;
     }
   else if (code == MEM && GET_CODE (XEXP (x, 0)) == ADDRESSOF && ! force)
@@ -2869,12 +2884,31 @@ purge_addressof_1 (loc, insn, force, store)
        {
          int size_x, size_sub;
 
+         if (!insn)
+           {
+             /* When processing REG_NOTES look at the list of
+                replacements done on the insn to find the register that X
+                was replaced by.  */
+             rtx tem;
+
+             for (tem = purge_addressof_replacements; tem != NULL_RTX;
+                  tem = XEXP (XEXP (tem, 1), 1))
+               if (rtx_equal_p (x, XEXP (tem, 0)))
+                 {
+                   *loc = XEXP (XEXP (tem, 1), 0);
+                   return;
+                 }
+
+             /* There should always be such a replacement.  */
+             abort ();
+           }
+
          size_x = GET_MODE_BITSIZE (GET_MODE (x));
          size_sub = GET_MODE_BITSIZE (GET_MODE (sub));
 
          /* Don't even consider working with paradoxical subregs,
             or the moral equivalent seen here.  */
-         if (size_x < size_sub
+         if (size_x <= size_sub
              && int_mode_for_mode (GET_MODE (sub)) != BLKmode)
            {
              /* Do a bitfield insertion to mirror what would happen
@@ -2884,12 +2918,15 @@ purge_addressof_1 (loc, insn, force, store)
 
              if (store)
                {
-                 /* If we can't replace with a register, be afraid.  */
-
                  start_sequence ();
                  val = gen_reg_rtx (GET_MODE (x));
                  if (! validate_change (insn, loc, val, 0))
-                   abort ();
+                   {
+                     /* Discard the current sequence and put the
+                        ADDRESSOF on stack.  */
+                     end_sequence ();
+                     goto give_up;
+                   }
                  seq = gen_sequence ();
                  end_sequence ();
                  emit_insn_before (seq, insn);
@@ -2911,21 +2948,33 @@ purge_addressof_1 (loc, insn, force, store)
                                           GET_MODE_SIZE (GET_MODE (sub)),
                                           GET_MODE_SIZE (GET_MODE (sub)));
 
-                 /* If we can't replace with a register, be afraid.  */
                  if (! validate_change (insn, loc, val, 0))
-                   abort ();
+                   {
+                     /* Discard the current sequence and put the
+                        ADDRESSOF on stack.  */
+                     end_sequence ();
+                     goto give_up;
+                   }
 
                  seq = gen_sequence ();
                  end_sequence ();
                  emit_insn_before (seq, insn);
                }
 
+             /* Remember the replacement so that the same one can be done
+                on the REG_NOTES.  */
+             purge_addressof_replacements
+               = gen_rtx_EXPR_LIST (VOIDmode, x,
+                                    gen_rtx_EXPR_LIST (VOIDmode, val,
+                                                       purge_addressof_replacements));
+
              /* We replaced with a reg -- all done.  */
              return;
            }
        }
       else if (validate_change (insn, loc, sub, 0))
        goto restart;
+    give_up:;
       /* else give up and put it into the stack */
     }
   else if (code == ADDRESSOF)
@@ -2968,6 +3017,7 @@ purge_addressof (insns)
        purge_addressof_1 (&PATTERN (insn), insn,
                           asm_noperands (PATTERN (insn)) > 0, 0);
        purge_addressof_1 (&REG_NOTES (insn), NULL_RTX, 0, 0);
+       purge_addressof_replacements = 0;
       }
 }
 \f
@@ -4364,7 +4414,7 @@ assign_parms (fndecl, second_time)
 
              store_expr (parm, copy, 0);
              emit_move_insn (parmreg, XEXP (copy, 0));
-             if (flag_check_memory_usage)
+             if (current_function_check_memory_usage)
                emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
                                   XEXP (copy, 0), ptr_mode,
                                   GEN_INT (int_size_in_bytes (type)),
@@ -4529,7 +4579,7 @@ assign_parms (fndecl, second_time)
                emit_move_insn (validize_mem (stack_parm),
                                validize_mem (entry_parm));
            }
-         if (flag_check_memory_usage)
+         if (current_function_check_memory_usage)
            {
              push_to_sequence (conversion_insns);
              emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
@@ -4890,6 +4940,14 @@ uninitialized_vars_warning (block)
          && ! AGGREGATE_TYPE_P (TREE_TYPE (decl))
          && DECL_RTL (decl) != 0
          && GET_CODE (DECL_RTL (decl)) == REG
+         /* Global optimizations can make it difficult to determine if a
+            particular variable has been initialized.  However, a VAR_DECL
+            with a nonzero DECL_INITIAL had an initializer, so do not
+            claim it is potentially uninitialized.
+
+            We do not care about the actual value in DECL_INITIAL, so we do
+            not worry that it may be a dangling pointer.  */
+         && DECL_INITIAL (decl) == NULL_TREE
          && regno_uninitialized (REGNO (DECL_RTL (decl))))
        warning_with_decl (decl,
                           "`%s' might be used uninitialized in this function");
@@ -5421,6 +5479,7 @@ init_function_start (subr, filename, line)
   current_function_has_nonlocal_label = 0;
   current_function_has_nonlocal_goto = 0;
   current_function_contains_functions = 0;
+  current_function_sp_is_unchanging = 0;
   current_function_is_thunk = 0;
 
   current_function_returns_pcc_struct = 0;
@@ -5550,6 +5609,11 @@ expand_function_start (subr, parms_have_cleanups)
      valid operands of arithmetic insns.  */
   init_recog_no_volatile ();
 
+  /* Set this before generating any memory accesses.  */
+  current_function_check_memory_usage
+    = (flag_check_memory_usage
+       && ! DECL_NO_CHECK_MEMORY_USAGE (current_function_decl));
+
   current_function_instrument_entry_exit
     = (flag_instrument_function_entry_exit
        && ! DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (subr));
@@ -6160,7 +6224,7 @@ contains (insn, vec)
 
 void
 thread_prologue_and_epilogue_insns (f)
-     rtx f;
+     rtx f ATTRIBUTE_UNUSED;
 {
 #ifdef HAVE_prologue
   if (HAVE_prologue)
@@ -6261,7 +6325,7 @@ thread_prologue_and_epilogue_insns (f)
 
 void
 reposition_prologue_and_epilogue_notes (f)
-     rtx f;
+     rtx f ATTRIBUTE_UNUSED;
 {
 #if defined (HAVE_prologue) || defined (HAVE_epilogue)
   /* Reposition the prologue and epilogue notes.  */