calls.c (load_register_parameters): Add is_sibcall, sibcall_failure parameters.
authorDale Johannesen <dalej@apple.com>
Fri, 10 Jan 2003 19:49:09 +0000 (19:49 +0000)
committerDale Johannesen <dalej@gcc.gnu.org>
Fri, 10 Jan 2003 19:49:09 +0000 (19:49 +0000)
2003-01-10  Dale Johannesen <dalej@apple.com>
        * calls.c (load_register_parameters):  Add is_sibcall, sibcall_failure
        parameters.  Call check_sibcall_argument_overlap if indicated.
        (check_sibcall_argument_overlap):  Add mark_stored_args_map
        parameter.  Don't mark parameter area as clobbered if not set.
        (expand_call):  Adjust calls to above.

From-SVN: r61165

gcc/ChangeLog
gcc/calls.c

index 1a63339f9aa8ffd2907fb14c38855b3a063680cd..9111be51088bc8eb1c167b7f8bc40ae197db8399 100644 (file)
@@ -1,4 +1,12 @@
-2003-01-10 Kelley Cook <kelleycook@comcast.net>
+2003-01-10  Dale Johannesen <dalej@apple.com>
+        * calls.c (load_register_parameters):  Add is_sibcall, sibcall_failure
+        parameters.  Call check_sibcall_argument_overlap if indicated.
+        (check_sibcall_argument_overlap):  Add mark_stored_args_map
+        parameter.  Don't mark parameter area as clobbered if not set.
+        (expand_call):  Adjust calls to above.
+ 2003-01-10 Kelley Cook <kelleycook@comcast.net>
 
        * configure.in (linker read-only and read-write section mixing):
        Squelch some assembler warnings.
index 2be53a85d13d9a65f414fb188a7649e069f4aa3f..18c7f604f5ce22f7f461f75ac166b76fd4c396eb 100644 (file)
@@ -182,7 +182,8 @@ static void compute_argument_addresses              PARAMS ((struct arg_data *,
                                                         rtx, int));
 static rtx rtx_for_function_call               PARAMS ((tree, tree));
 static void load_register_parameters           PARAMS ((struct arg_data *,
-                                                        int, rtx *, int));
+                                                        int, rtx *, int,
+                                                        int, int *));
 static rtx emit_library_call_value_1           PARAMS ((int, rtx, rtx,
                                                         enum libcall_type,
                                                         enum machine_mode,
@@ -191,7 +192,8 @@ static int special_function_p                       PARAMS ((tree, int));
 static rtx try_to_integrate                    PARAMS ((tree, tree, rtx,
                                                         int, tree, rtx));
 static int check_sibcall_argument_overlap_1    PARAMS ((rtx));
-static int check_sibcall_argument_overlap      PARAMS ((rtx, struct arg_data *));
+static int check_sibcall_argument_overlap      PARAMS ((rtx, struct arg_data *,
+                                                        int));
 
 static int combine_pending_stack_adjustment_and_call
                                                 PARAMS ((int, struct args_size *, int));
@@ -1698,14 +1700,20 @@ rtx_for_function_call (fndecl, exp)
    expressions were already evaluated.
 
    Mark all register-parms as living through the call, putting these USE
-   insns in the CALL_INSN_FUNCTION_USAGE field.  */
+   insns in the CALL_INSN_FUNCTION_USAGE field.  
+   When IS_SIBCALL, perform the check_sibcall_overlap_argument_overlap
+   checking, setting *SIBCALL_FAILURE if appropriate.  */
 
 static void
-load_register_parameters (args, num_actuals, call_fusage, flags)
+load_register_parameters (args, num_actuals, call_fusage, flags, 
+                           is_sibcall, sibcall_failure)
      struct arg_data *args;
      int num_actuals;
      rtx *call_fusage;
      int flags;
+     int is_sibcall;
+     int *sibcall_failure;
 {
   int i, j;
 
@@ -1722,6 +1730,7 @@ load_register_parameters (args, num_actuals, call_fusage, flags)
 
       if (reg)
        {
+         rtx before_arg = get_last_insn ();
          /* Set to non-negative if must move a word at a time, even if just
             one word (e.g, partial == 1 && mode == DFmode).  Set to -1 if
             we just use a normal move insn.  This value can be zero if the
@@ -1759,6 +1768,13 @@ load_register_parameters (args, num_actuals, call_fusage, flags)
                               validize_mem (args[i].value), nregs,
                               args[i].mode);
 
+         /* When a parameter is a block, and perhaps in other cases, it is
+            possible that it did a load from an argument slot that was
+            already clobbered. */
+         if (is_sibcall
+             && check_sibcall_argument_overlap (before_arg, &args[i], 0))
+           *sibcall_failure = 1;
+
          /* Handle calls that pass values in multiple non-contiguous
             locations.  The Irix 6 ABI has examples of this.  */
          if (GET_CODE (reg) == PARALLEL)
@@ -2015,14 +2031,16 @@ check_sibcall_argument_overlap_1 (x)
 
 /* Scan sequence after INSN if it does not dereference any argument slots
    we already clobbered by tail call arguments (as noted in stored_args_map
-   bitmap).  Add stack slots for ARG to stored_args_map bitmap afterwards.
-   Return nonzero if sequence after INSN dereferences such argument slots,
-   zero otherwise.  */
+   bitmap).  If MARK_STORED_ARGS_MAP, add stack slots for ARG to
+   stored_args_map bitmap afterwards (when ARG is a register MARK_STORED_ARGS_MAP
+   should be 0).  Return nonzero if sequence after INSN dereferences such argument
+   slots, zero otherwise.  */
 
 static int
-check_sibcall_argument_overlap (insn, arg)
+check_sibcall_argument_overlap (insn, arg, mark_stored_args_map)
      rtx insn;
      struct arg_data *arg;
+     int mark_stored_args_map;
 {
   int low, high;
 
@@ -2036,14 +2054,17 @@ check_sibcall_argument_overlap (insn, arg)
        && check_sibcall_argument_overlap_1 (PATTERN (insn)))
       break;
 
+  if (mark_stored_args_map)
+    {
 #ifdef ARGS_GROW_DOWNWARD
-  low = -arg->slot_offset.constant - arg->size.constant;
+      low = -arg->slot_offset.constant - arg->size.constant;
 #else
-  low = arg->slot_offset.constant;
+      low = arg->slot_offset.constant;
 #endif
 
-  for (high = low + arg->size.constant; low < high; low++)
-    SET_BIT (stored_args_map, low);
+      for (high = low + arg->size.constant; low < high; low++)
+       SET_BIT (stored_args_map, low);
+    }
   return insn != NULL_RTX;
 }
 
@@ -2959,7 +2980,7 @@ expand_call (exp, target, ignore)
                               reg_parm_stack_space)
                || (pass == 0
                    && check_sibcall_argument_overlap (before_arg,
-                                                      &args[i])))
+                                                      &args[i], 1)))
              sibcall_failure = 1;
          }
 
@@ -2983,7 +3004,7 @@ expand_call (exp, target, ignore)
                                 reg_parm_stack_space)
                  || (pass == 0
                      && check_sibcall_argument_overlap (before_arg,
-                                                        &args[i])))
+                                                        &args[i], 1)))
                sibcall_failure = 1;
            }
 
@@ -3018,7 +3039,8 @@ expand_call (exp, target, ignore)
       funexp = prepare_call_address (funexp, fndecl, &call_fusage,
                                     reg_parm_seen, pass == 0);
 
-      load_register_parameters (args, num_actuals, &call_fusage, flags);
+      load_register_parameters (args, num_actuals, &call_fusage, flags,
+                               pass == 0, &sibcall_failure);
 
       /* Perform postincrements before actually calling the function.  */
       emit_queue ();