OSDN Git Service

* combine.c (simplify_shift_const): Calculate rotate count
[pf3gnuchains/gcc-fork.git] / gcc / calls.c
index 7e2bc4b..2e23809 100644 (file)
@@ -33,6 +33,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tm_p.h"
 #include "timevar.h"
 #include "sbitmap.h"
+#include "langhooks.h"
+#include "target.h"
 
 #if !defined FUNCTION_OK_FOR_SIBCALL
 #define FUNCTION_OK_FOR_SIBCALL(DECL) 1
@@ -965,11 +967,8 @@ save_fixed_argument_area (reg_parm_stack_space, argblock,
       if (save_mode == BLKmode)
        {
          save_area = assign_stack_temp (BLKmode, num_to_save, 0);
-         /* Cannot use emit_block_move here because it can be done by a
-            library call which in turn gets into this place again and deadly
-            infinite recursion happens.  */
-         move_by_pieces (validize_mem (save_area), stack_area, num_to_save,
-                         PARM_BOUNDARY);
+         emit_block_move (validize_mem (save_area), stack_area,
+                          GEN_INT (num_to_save), BLOCK_OP_CALL_PARM);
        }
       else
        {
@@ -1006,11 +1005,9 @@ restore_fixed_argument_area (save_area, argblock, high_to_save, low_to_save)
   if (save_mode != BLKmode)
     emit_move_insn (stack_area, save_area);
   else
-    /* Cannot use emit_block_move here because it can be done by a library
-       call which in turn gets into this place again and deadly infinite
-       recursion happens.  */
-    move_by_pieces (stack_area, validize_mem (save_area),
-                   high_to_save - low_to_save + 1, PARM_BOUNDARY);
+    emit_block_move (stack_area, validize_mem (save_area),
+                    GEN_INT (high_to_save - low_to_save + 1),
+                    BLOCK_OP_CALL_PARM);
 }
 #endif /* REG_PARM_STACK_SPACE */
 
@@ -1511,14 +1508,9 @@ precompute_arguments (flags, num_actuals, args)
        if (TREE_ADDRESSABLE (TREE_TYPE (args[i].tree_value)))
          abort ();
 
-       push_temp_slots ();
-
        args[i].value
          = expand_expr (args[i].tree_value, NULL_RTX, VOIDmode, 0);
 
-       preserve_temp_slots (args[i].value);
-       pop_temp_slots ();
-
        /* ANSI doesn't require a sequence point here,
           but PCC has one, so this will avoid some problems.  */
        emit_queue ();
@@ -1542,8 +1534,8 @@ precompute_arguments (flags, num_actuals, args)
                args[i].initial_value
                  = gen_lowpart_SUBREG (mode, args[i].value);
                SUBREG_PROMOTED_VAR_P (args[i].initial_value) = 1;
-               SUBREG_PROMOTED_UNSIGNED_P (args[i].initial_value)
-                 = args[i].unsignedp;
+               SUBREG_PROMOTED_UNSIGNED_SET (args[i].initial_value,
+                 args[i].unsignedp);
              }
 #endif
          }
@@ -1884,7 +1876,7 @@ try_to_integrate (fndecl, actparms, target, ignore, type, structure_value_addr)
                                                NULL_RTX, BITS_PER_UNIT);
                  seq = get_insns ();
                  end_sequence ();
-                 emit_insns_before (seq, first_insn);
+                 emit_insn_before (seq, first_insn);
                  emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
                }
            }
@@ -1907,7 +1899,7 @@ try_to_integrate (fndecl, actparms, target, ignore, type, structure_value_addr)
       warning_with_decl (fndecl, "inlining failed in call to `%s'");
       warning ("called from here");
     }
-  mark_addressable (fndecl);
+  (*lang_hooks.mark_addressable) (fndecl);
   return (rtx) (size_t) - 1;
 }
 
@@ -2213,7 +2205,7 @@ expand_call (exp, target, ignore)
              warning_with_decl (fndecl, "can't inline call to `%s'");
              warning ("called from here");
            }
-         mark_addressable (fndecl);
+         (*lang_hooks.mark_addressable) (fndecl);
        }
 
       flags |= flags_from_decl_or_type (fndecl);
@@ -2259,7 +2251,7 @@ expand_call (exp, target, ignore)
            /* In case this is a static function, note that it has been
               used.  */
            if (! TREE_ADDRESSABLE (fndecl))
-             mark_addressable (fndecl);
+             (*lang_hooks.mark_addressable) (fndecl);
            is_integrable = 0;
          }
       }
@@ -2473,7 +2465,7 @@ expand_call (exp, target, ignore)
         != RETURN_POPS_ARGS (current_function_decl,
                              TREE_TYPE (current_function_decl),
                              current_function_args_size))
-  try_tail_call = 0;
+    try_tail_call = 0;
 
   if (try_tail_call || try_tail_recursion)
     {
@@ -2681,10 +2673,6 @@ expand_call (exp, target, ignore)
       if (pass && (flags & ECF_LIBCALL_BLOCK))
        NO_DEFER_POP;
 
-      /* Push the temporary stack slot level so that we can free any
-        temporaries we make.  */
-      push_temp_slots ();
-
 #ifdef FINAL_REG_PARM_STACK_SPACE
       reg_parm_stack_space = FINAL_REG_PARM_STACK_SPACE (args_size.constant,
                                                         args_size.var);
@@ -2717,6 +2705,12 @@ expand_call (exp, target, ignore)
       if (pass == 0)
        {
          argblock = virtual_incoming_args_rtx;
+         argblock
+#ifdef STACK_GROWS_DOWNWARD
+           = plus_constant (argblock, current_function_pretend_args_size);
+#else
+           = plus_constant (argblock, -current_function_pretend_args_size);
+#endif
          stored_args_map = sbitmap_alloc (args_size.constant);
          sbitmap_zero (stored_args_map);
        }
@@ -3080,7 +3074,7 @@ expand_call (exp, target, ignore)
            {
              insns = get_insns ();
              end_sequence ();
-             emit_insns (insns);
+             emit_insn (insns);
            }
          else
            {
@@ -3134,7 +3128,7 @@ expand_call (exp, target, ignore)
          /* Write out the sequence.  */
          insns = get_insns ();
          end_sequence ();
-         emit_insns (insns);
+         emit_insn (insns);
          valreg = temp;
        }
 
@@ -3279,7 +3273,7 @@ expand_call (exp, target, ignore)
          }
          target = gen_rtx_SUBREG (TYPE_MODE (type), target, offset);
          SUBREG_PROMOTED_VAR_P (target) = 1;
-         SUBREG_PROMOTED_UNSIGNED_P (target) = unsignedp;
+         SUBREG_PROMOTED_UNSIGNED_SET (target, unsignedp);
        }
 #endif
 
@@ -3318,9 +3312,9 @@ expand_call (exp, target, ignore)
                if (save_mode != BLKmode)
                  emit_move_insn (stack_area, args[i].save_area);
                else
-                 emit_block_move (stack_area,
-                                  validize_mem (args[i].save_area),
-                                  GEN_INT (args[i].size.constant));
+                 emit_block_move (stack_area, args[i].save_area,
+                                  GEN_INT (args[i].size.constant),
+                                  BLOCK_OP_CALL_PARM);
              }
 
          highest_outgoing_arg_in_use = initial_highest_arg_in_use;
@@ -3334,8 +3328,6 @@ expand_call (exp, target, ignore)
       if ((flags & ECF_MAY_BE_ALLOCA) && nonlocal_goto_handler_slots != 0)
        emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, NULL_RTX);
 
-      pop_temp_slots ();
-
       /* Free up storage we no longer need.  */
       for (i = 0; i < num_actuals; ++i)
        if (args[i].aligned_regs)
@@ -3423,7 +3415,7 @@ expand_call (exp, target, ignore)
                                                tail_recursion_label));
     }
   else
-    emit_insns (normal_call_insns);
+    emit_insn (normal_call_insns);
 
   currently_expanding_call--;
 
@@ -3487,6 +3479,7 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
   int reg_parm_stack_space = 0;
   int needed;
   rtx before_call;
+  tree tfom;                   /* type_for_mode (outmode, 0) */
 
 #ifdef REG_PARM_STACK_SPACE
   /* Define the boundary of the register parm stack space that needs to be
@@ -3548,27 +3541,31 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
 
   /* If this kind of value comes back in memory,
      decide where in memory it should come back.  */
-  if (outmode != VOIDmode && aggregate_value_p (type_for_mode (outmode, 0)))
+  if (outmode != VOIDmode)
     {
+      tfom = (*lang_hooks.types.type_for_mode) (outmode, 0);
+      if (aggregate_value_p (tfom))
+       {
 #ifdef PCC_STATIC_STRUCT_RETURN
-      rtx pointer_reg
-       = hard_function_value (build_pointer_type (type_for_mode (outmode, 0)),
-                              0, 0);
-      mem_value = gen_rtx_MEM (outmode, pointer_reg);
-      pcc_struct_value = 1;
-      if (value == 0)
-       value = gen_reg_rtx (outmode);
+         rtx pointer_reg
+           = hard_function_value (build_pointer_type (tfom), 0, 0);
+         mem_value = gen_rtx_MEM (outmode, pointer_reg);
+         pcc_struct_value = 1;
+         if (value == 0)
+           value = gen_reg_rtx (outmode);
 #else /* not PCC_STATIC_STRUCT_RETURN */
-      struct_value_size = GET_MODE_SIZE (outmode);
-      if (value != 0 && GET_CODE (value) == MEM)
-       mem_value = value;
-      else
-       mem_value = assign_temp (type_for_mode (outmode, 0), 0, 1, 1);
+         struct_value_size = GET_MODE_SIZE (outmode);
+         if (value != 0 && GET_CODE (value) == MEM)
+           mem_value = value;
+         else
+           mem_value = assign_temp (tfom, 0, 1, 1);
 #endif
-
-      /* This call returns a big structure.  */
-      flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
+         /* This call returns a big structure.  */
+         flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
+       }
     }
+  else
+    tfom = void_type_node;
 
   /* ??? Unfinished: must pass the memory address as an argument.  */
 
@@ -3677,16 +3674,27 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
 #endif
            ;
 
+         /* loop.c won't look at CALL_INSN_FUNCTION_USAGE of const/pure
+            functions, so we have to pretend this isn't such a function.  */
+         if (flags & ECF_LIBCALL_BLOCK)
+           {
+             rtx insns = get_insns ();
+             end_sequence ();
+             emit_insn (insns);
+           }
+         flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
+
          if (GET_MODE (val) == MEM && ! must_copy)
            slot = val;
          else if (must_copy)
            {
-             slot = assign_temp (type_for_mode (mode, 0), 0, 1, 1);
+             slot = assign_temp ((*lang_hooks.types.type_for_mode) (mode, 0),
+                                 0, 1, 1);
              emit_move_insn (slot, val);
            }
          else
            {
-             tree type = type_for_mode (mode, 0);
+             tree type = (*lang_hooks.types.type_for_mode) (mode, 0);
 
              slot = gen_rtx_MEM (mode,
                                  expand_expr (build1 (ADDR_EXPR,
@@ -3896,8 +3904,8 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
            {
              save_area = assign_stack_temp (BLKmode, num_to_save, 0);
              set_mem_align (save_area, PARM_BOUNDARY);
-             emit_block_move (validize_mem (save_area), stack_area,
-                              GEN_INT (num_to_save));
+             emit_block_move (save_area, stack_area, GEN_INT (num_to_save),
+                              BLOCK_OP_CALL_PARM);
            }
          else
            {
@@ -3965,8 +3973,9 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
                }
            }
 
-         emit_push_insn (val, mode, NULL_TREE, NULL_RTX, 0, partial, reg, 0,
-                         argblock, GEN_INT (argvec[argnum].offset.constant),
+         emit_push_insn (val, mode, NULL_TREE, NULL_RTX, PARM_BOUNDARY,
+                         partial, reg, 0, argblock,
+                         GEN_INT (argvec[argnum].offset.constant),
                          reg_parm_stack_space, ARGS_SIZE_RTX (alignment_pad));
 
          /* Now mark the segment we just used.  */
@@ -4053,8 +4062,7 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
 
   emit_call_1 (fun,
               get_identifier (XSTR (orgfun, 0)),
-              build_function_type (outmode == VOIDmode ? void_type_node
-                                   : type_for_mode (outmode, 0), NULL_TREE),
+              build_function_type (tfom, NULL_TREE),
               original_args_size.constant, args_size.constant,
               struct_value_size,
               FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
@@ -4098,7 +4106,7 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
        {
          insns = get_insns ();
          end_sequence ();
-         emit_insns (insns);
+         emit_insn (insns);
        }
       else
        {
@@ -4168,8 +4176,9 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
          if (save_mode != BLKmode)
            emit_move_insn (stack_area, save_area);
          else
-           emit_block_move (stack_area, validize_mem (save_area),
-                            GEN_INT (high_to_save - low_to_save + 1));
+           emit_block_move (stack_area, save_area,
+                            GEN_INT (high_to_save - low_to_save + 1),
+                            BLOCK_OP_CALL_PARM);
        }
 #endif
 
@@ -4346,7 +4355,8 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
                  arg->save_area = assign_temp (nt, 0, 1, 1);
                  preserve_temp_slots (arg->save_area);
                  emit_block_move (validize_mem (arg->save_area), stack_area,
-                                  expr_size (arg->tree_value));
+                                  expr_size (arg->tree_value),
+                                  BLOCK_OP_CALL_PARM);
                }
              else
                {
@@ -4367,7 +4377,13 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
   /* If this isn't going to be placed on both the stack and in registers,
      set up the register and number of words.  */
   if (! arg->pass_on_stack)
-    reg = arg->reg, partial = arg->partial;
+    {
+      if (flags & ECF_SIBCALL)
+       reg = arg->tail_call_reg;
+      else
+       reg = arg->reg;
+      partial = arg->partial;
+    }
 
   if (reg != 0 && partial == 0)
     /* Being passed entirely in a register.  We shouldn't be called in
@@ -4461,8 +4477,8 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
 
       /* This isn't already where we want it on the stack, so put it there.
         This can either be done with push or copy insns.  */
-      emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), NULL_RTX, 0,
-                     partial, reg, used - size, argblock,
+      emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), NULL_RTX, 
+                     PARM_BOUNDARY, partial, reg, used - size, argblock,
                      ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space,
                      ARGS_SIZE_RTX (arg->alignment_pad));
 
@@ -4556,18 +4572,18 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
           {
            rtx size_rtx1 = GEN_INT (reg_parm_stack_space - arg->offset.constant);
            emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx1,
-                           TYPE_ALIGN (TREE_TYPE (pval)), partial, reg,
-                           excess, argblock, ARGS_SIZE_RTX (arg->offset),
-                           reg_parm_stack_space,
+                           MAX (PARM_BOUNDARY, TYPE_ALIGN (TREE_TYPE (pval))),
+                           partial, reg, excess, argblock,
+                           ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space,
                            ARGS_SIZE_RTX (arg->alignment_pad));
          }
        }
        
 
       emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx,
-                     TYPE_ALIGN (TREE_TYPE (pval)), partial, reg, excess,
-                     argblock, ARGS_SIZE_RTX (arg->offset),
-                     reg_parm_stack_space,
+                     MAX (PARM_BOUNDARY, TYPE_ALIGN (TREE_TYPE (pval))),
+                     partial, reg, excess, argblock,
+                     ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space,
                      ARGS_SIZE_RTX (arg->alignment_pad));
 
       /* Unless this is a partially-in-register argument, the argument is now