OSDN Git Service

* config/m32c/m32c.h (LIBGCC2_UNITS_PER_WORD): Define if not
[pf3gnuchains/gcc-fork.git] / gcc / calls.c
index b94d298..7bad365 100644 (file)
@@ -1,6 +1,6 @@
 /* Convert function calls to rtl insns, for GNU C compiler.
    Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -498,10 +498,14 @@ special_function_p (const_tree fndecl, int flags)
               && ! strcmp (name, "__builtin_alloca"))))
        flags |= ECF_MAY_BE_ALLOCA;
 
-      /* Disregard prefix _, __ or __x.  */
+      /* Disregard prefix _, __, __x or __builtin_.  */
       if (name[0] == '_')
        {
-         if (name[1] == '_' && name[2] == 'x')
+         if (name[1] == '_'
+             && name[2] == 'b'
+             && !strncmp (name + 3, "uiltin_", 7))
+           tname += 10;
+         else if (name[1] == '_' && name[2] == 'x')
            tname += 3;
          else if (name[1] == '_')
            tname += 2;
@@ -992,7 +996,6 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
            && targetm.calls.split_complex_arg (argtype))
          {
            tree subtype = TREE_TYPE (argtype);
-           arg = save_expr (arg);
            args[j].tree_value = build1 (REALPART_EXPR, subtype, arg);
            j += inc;
            args[j].tree_value = build1 (IMAGPART_EXPR, subtype, arg);
@@ -2298,10 +2301,12 @@ expand_call (tree exp, rtx target, int ignore)
         It does not seem worth the effort since few optimizable
         sibling calls will return a structure.  */
       || structure_value_addr != NULL_RTX
+#ifdef REG_PARM_STACK_SPACE
       /* If outgoing reg parm stack space changes, we can not do sibcall.  */
       || (OUTGOING_REG_PARM_STACK_SPACE (funtype)
          != OUTGOING_REG_PARM_STACK_SPACE (TREE_TYPE (current_function_decl)))
       || (reg_parm_stack_space != REG_PARM_STACK_SPACE (fndecl))
+#endif
       /* Check whether the target is able to optimize the call
         into a sibcall.  */
       || !targetm.function_ok_for_sibcall (fndecl, exp)
@@ -2328,6 +2333,37 @@ expand_call (tree exp, rtx target, int ignore)
       || !lang_hooks.decls.ok_for_sibcall (fndecl))
     try_tail_call = 0;
 
+  /* Check if caller and callee disagree in promotion of function
+     return value.  */
+  if (try_tail_call)
+    {
+      enum machine_mode caller_mode, caller_promoted_mode;
+      enum machine_mode callee_mode, callee_promoted_mode;
+      int caller_unsignedp, callee_unsignedp;
+      tree caller_res = DECL_RESULT (current_function_decl);
+
+      caller_unsignedp = TYPE_UNSIGNED (TREE_TYPE (caller_res));
+      caller_mode = caller_promoted_mode = DECL_MODE (caller_res);
+      callee_unsignedp = TYPE_UNSIGNED (TREE_TYPE (funtype));
+      callee_mode = callee_promoted_mode = TYPE_MODE (TREE_TYPE (funtype));
+      if (targetm.calls.promote_function_return (TREE_TYPE (current_function_decl)))
+       caller_promoted_mode
+         = promote_mode (TREE_TYPE (caller_res), caller_mode,
+                         &caller_unsignedp, 1);
+      if (targetm.calls.promote_function_return (funtype))
+       callee_promoted_mode
+         = promote_mode (TREE_TYPE (funtype), callee_mode,
+                         &callee_unsignedp, 1);
+      if (caller_mode != VOIDmode
+         && (caller_promoted_mode != callee_promoted_mode
+             || ((caller_mode != caller_promoted_mode
+                  || callee_mode != callee_promoted_mode)
+                 && (caller_unsignedp != callee_unsignedp
+                     || GET_MODE_BITSIZE (caller_mode)
+                        < GET_MODE_BITSIZE (callee_mode)))))
+       try_tail_call = 0;
+    }
+
   /* Ensure current function's preferred stack boundary is at least
      what we need.  Stack alignment may also increase preferred stack
      boundary.  */
@@ -2703,26 +2739,28 @@ expand_call (tree exp, rtx target, int ignore)
         but we do preallocate space here if they want that.  */
 
       for (i = 0; i < num_actuals; i++)
-       if (args[i].reg == 0 || args[i].pass_on_stack)
-         {
-           rtx before_arg = get_last_insn ();
-
-           if (store_one_arg (&args[i], argblock, flags,
-                              adjusted_args_size.var != 0,
-                              reg_parm_stack_space)
-               || (pass == 0
-                   && check_sibcall_argument_overlap (before_arg,
-                                                      &args[i], 1)))
-             sibcall_failure = 1;
-
-           if (flags & ECF_CONST
-               && args[i].stack
-               && args[i].value == args[i].stack)
-             call_fusage = gen_rtx_EXPR_LIST (VOIDmode,
-                                              gen_rtx_USE (VOIDmode,
-                                                           args[i].value),
-                                              call_fusage);
-         }
+       {
+         if (args[i].reg == 0 || args[i].pass_on_stack)
+           {
+             rtx before_arg = get_last_insn ();
+
+             if (store_one_arg (&args[i], argblock, flags,
+                                adjusted_args_size.var != 0,
+                                reg_parm_stack_space)
+                 || (pass == 0
+                     && check_sibcall_argument_overlap (before_arg,
+                                                        &args[i], 1)))
+               sibcall_failure = 1;
+             }
+
+         if (((flags & ECF_CONST)
+              || ((flags & ECF_PURE) && ACCUMULATE_OUTGOING_ARGS))
+             && args[i].stack)
+           call_fusage = gen_rtx_EXPR_LIST (VOIDmode,
+                                            gen_rtx_USE (VOIDmode,
+                                                         args[i].stack),
+                                            call_fusage);
+       }
 
       /* If we have a parm that is passed in registers but not in memory
         and whose alignment does not permit a direct copy into registers,
@@ -3608,10 +3646,10 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
 #ifdef ARGS_GROW_DOWNWARD
              /* stack_slot is negative, but we want to index stack_usage_map
                 with positive values.  */
-             upper_bound = -argvec[argnum].locate.offset.constant + 1;
+             upper_bound = -argvec[argnum].locate.slot_offset.constant + 1;
              lower_bound = upper_bound - argvec[argnum].locate.size.constant;
 #else
-             lower_bound = argvec[argnum].locate.offset.constant;
+             lower_bound = argvec[argnum].locate.slot_offset.constant;
              upper_bound = lower_bound + argvec[argnum].locate.size.constant;
 #endif
 
@@ -3670,7 +3708,8 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
 
          NO_DEFER_POP;
 
-         if (flags & ECF_CONST)
+         if ((flags & ECF_CONST)
+             || ((flags & ECF_PURE) && ACCUMULATE_OUTGOING_ARGS))
            {
              rtx use;