OSDN Git Service

2005-09-08 Andrew Pinski <pinskia@physics.uc.edu>
[pf3gnuchains/gcc-fork.git] / gcc / calls.c
index 8e87886..4074dbd 100644 (file)
@@ -1444,7 +1444,7 @@ rtx_for_function_call (tree fndecl, tree addr)
    Mark all register-parms as living through the call, putting these USE
    insns in the CALL_INSN_FUNCTION_USAGE field.
 
-   When IS_SIBCALL, perform the check_sibcall_overlap_argument_overlap
+   When IS_SIBCALL, perform the check_sibcall_argument_overlap
    checking, setting *SIBCALL_FAILURE if appropriate.  */
 
 static void
@@ -2247,6 +2247,9 @@ expand_call (tree exp, rtx target, int ignore)
       if (pass && (flags & (ECF_LIBCALL_BLOCK | ECF_MALLOC)))
        start_sequence ();
 
+      if (pass == 0 && cfun->stack_protect_guard)
+       stack_protect_epilogue ();
+
       adjusted_args_size = args_size;
       /* Compute the actual size of the argument block required.  The variable
         and constant sizes must be combined, the size may have to be rounded,
@@ -3634,7 +3637,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
                use = plus_constant (argblock,
                                     argvec[argnum].locate.offset.constant);
              else
-               /* When arguemnts are pushed, trying to tell alias.c where
+               /* When arguments are pushed, trying to tell alias.c where
                   exactly this argument is won't work, because the
                   auto-increment causes confusion.  So we merely indicate
                   that we access something with a known mode somewhere on
@@ -4076,6 +4079,43 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags,
        stack_arg_under_construction--;
     }
 
+  /* Check for overlap with already clobbered argument area.  */
+  if ((flags & ECF_SIBCALL) && MEM_P (arg->value))
+    {
+      int i = -1;
+      unsigned HOST_WIDE_INT k;
+      rtx x = arg->value;
+
+      if (XEXP (x, 0) == current_function_internal_arg_pointer)
+       i = 0;
+      else if (GET_CODE (XEXP (x, 0)) == PLUS
+              && XEXP (XEXP (x, 0), 0) ==
+                 current_function_internal_arg_pointer
+              && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
+       i = INTVAL (XEXP (XEXP (x, 0), 1));
+      else
+       i = -1;
+
+      if (i >= 0)
+       {
+#ifdef ARGS_GROW_DOWNWARD
+         i = -i - arg->locate.size.constant;
+#endif
+         if (arg->locate.size.constant > 0)
+           {
+             unsigned HOST_WIDE_INT sc = arg->locate.size.constant;
+
+             for (k = 0; k < sc; k++)
+               if (i + k < stored_args_map->n_bits
+                   && TEST_BIT (stored_args_map, i + k))
+                 {
+                   sibcall_failure = 1;
+                   break;
+                 }
+           }
+       }
+    }
+
   /* Don't allow anything left on stack from computation
      of argument to alloca.  */
   if (flags & ECF_MAY_BE_ALLOCA)