This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Patch to merge emit_library_call and emit_library_call_value


> On Tue, Mar 07, 2000 at 03:08:03PM +0100, Jan Hubicka wrote:
> > 	* calls.c (emit_library_call_value_1): Break out from ...; handle
> > 	VOIDmode function calls too.
> > 	(emit_library_call_value): ... here.
> > 	(emit_library_call): Implement by calling emit_library_call_value_1.
> 
> Ok.

Hi
I've reinstalled this patch (reverted by Richard because of the problems
with previous one)
It needed some changes, so here is what I've installed:

*** calls.c.old	Tue Mar 21 21:36:30 2000
--- calls.c	Tue Mar 21 21:42:22 2000
*************** static rtx rtx_for_function_call		PARAMS
*** 172,177 ****
--- 172,180 ----
  static void load_register_parameters		PARAMS ((struct arg_data *,
  							 int, rtx *));
  static int libfunc_nothrow			PARAMS ((rtx));
+ static rtx emit_library_call_value_1 		PARAMS ((int, rtx, rtx, int,
+ 							 enum machine_mode,
+ 							 int, va_list));
  
  #if defined(ACCUMULATE_OUTGOING_ARGS) && defined(REG_PARM_STACK_SPACE)
  static rtx save_fixed_argument_area	PARAMS ((int, rtx, int *, int *));
*************** libfunc_nothrow (fun)
*** 3026,3584 ****
  
    return 1;
  }
- 
- /* Output a library call to function FUN (a SYMBOL_REF rtx)
-    (emitting the queue unless NO_QUEUE is nonzero),
-    for a value of mode OUTMODE,
-    with NARGS different arguments, passed as alternating rtx values
-    and machine_modes to convert them to.
-    The rtx values should have been passed through protect_from_queue already.
- 
-    NO_QUEUE will be true if and only if the library call is a `const' call
-    which will be enclosed in REG_LIBCALL/REG_RETVAL notes; it is equivalent
-    to the variable is_const in expand_call.
- 
-    NO_QUEUE must be true for const calls, because if it isn't, then
-    any pending increment will be emitted between REG_LIBCALL/REG_RETVAL notes,
-    and will be lost if the libcall sequence is optimized away.
- 
-    NO_QUEUE must be false for non-const calls, because if it isn't, the
-    call insn will have its CONST_CALL_P bit set, and it will be incorrectly
-    optimized.  For instance, the instruction scheduler may incorrectly
-    move memory references across the non-const call.  */
- 
- void
- emit_library_call VPARAMS((rtx orgfun, int no_queue, enum machine_mode outmode,
- 			   int nargs, ...))
- {
- #ifndef ANSI_PROTOTYPES
-   rtx orgfun;
-   int no_queue;
-   enum machine_mode outmode;
-   int nargs;
- #endif
-   va_list p;
-   /* Total size in bytes of all the stack-parms scanned so far.  */
-   struct args_size args_size;
-   /* Size of arguments before any adjustments (such as rounding).  */
-   struct args_size original_args_size;
-   register int argnum;
-   rtx fun;
-   int inc;
-   int count;
-   struct args_size alignment_pad;
-   rtx argblock = 0;
-   CUMULATIVE_ARGS args_so_far;
-   struct arg { rtx value; enum machine_mode mode; rtx reg; int partial;
- 	       struct args_size offset; struct args_size size; rtx save_area; };
-   struct arg *argvec;
-   int old_inhibit_defer_pop = inhibit_defer_pop;
-   rtx call_fusage = 0;
-   int reg_parm_stack_space = 0;
-   int nothrow;
- #if defined(ACCUMULATE_OUTGOING_ARGS) && defined(REG_PARM_STACK_SPACE)
-   /* Define the boundary of the register parm stack space that needs to be
-      save, if any.  */
-   int low_to_save = -1, high_to_save = 0;
-   rtx save_area = 0;            /* Place that it is saved */
- #endif
- 
- #ifdef ACCUMULATE_OUTGOING_ARGS
-   int initial_highest_arg_in_use = highest_outgoing_arg_in_use;
-   char *initial_stack_usage_map = stack_usage_map;
-   int needed;
- #endif
- 
- #ifdef REG_PARM_STACK_SPACE
-   /* Size of the stack reserved for parameter registers.  */
- #ifdef MAYBE_REG_PARM_STACK_SPACE
-   reg_parm_stack_space = MAYBE_REG_PARM_STACK_SPACE;
- #else
-   reg_parm_stack_space = REG_PARM_STACK_SPACE ((tree) 0);
- #endif
- #endif
- 
-   VA_START (p, nargs);
- 
- #ifndef ANSI_PROTOTYPES
-   orgfun = va_arg (p, rtx);
-   no_queue = va_arg (p, int);
-   outmode = va_arg (p, enum machine_mode);
-   nargs = va_arg (p, int);
- #endif
- 
-   fun = orgfun;
- 
-   nothrow = libfunc_nothrow (fun);
- 
-   /* Copy all the libcall-arguments out of the varargs data
-      and into a vector ARGVEC.
- 
-      Compute how to pass each argument.  We only support a very small subset
-      of the full argument passing conventions to limit complexity here since
-      library functions shouldn't have many args.  */
- 
-   argvec = (struct arg *) alloca (nargs * sizeof (struct arg));
-   bzero ((char *) argvec, nargs * sizeof (struct arg));
- 
- 
-   INIT_CUMULATIVE_ARGS (args_so_far, NULL_TREE, fun, 0);
- 
-   args_size.constant = 0;
-   args_size.var = 0;
- 
-   push_temp_slots ();
- 
- #ifdef PREFERRED_STACK_BOUNDARY
-   /* Ensure current function's preferred stack boundary is at least
-      what we need.  */
-   if (cfun->preferred_stack_boundary < PREFERRED_STACK_BOUNDARY)
-     cfun->preferred_stack_boundary = PREFERRED_STACK_BOUNDARY;
- #endif
- 
-   for (count = 0; count < nargs; count++)
-     {
-       rtx val = va_arg (p, rtx);
-       enum machine_mode mode = va_arg (p, enum machine_mode);
- 
-       /* We cannot convert the arg value to the mode the library wants here;
- 	 must do it earlier where we know the signedness of the arg.  */
-       if (mode == BLKmode
- 	  || (GET_MODE (val) != mode && GET_MODE (val) != VOIDmode))
- 	abort ();
- 
-       /* On some machines, there's no way to pass a float to a library fcn.
- 	 Pass it as a double instead.  */
- #ifdef LIBGCC_NEEDS_DOUBLE
-       if (LIBGCC_NEEDS_DOUBLE && mode == SFmode)
- 	val = convert_modes (DFmode, SFmode, val, 0), mode = DFmode;
- #endif
- 
-       /* There's no need to call protect_from_queue, because
- 	 either emit_move_insn or emit_push_insn will do that.  */
- 
-       /* Make sure it is a reasonable operand for a move or push insn.  */
-       if (GET_CODE (val) != REG && GET_CODE (val) != MEM
- 	  && ! (CONSTANT_P (val) && LEGITIMATE_CONSTANT_P (val)))
- 	val = force_operand (val, NULL_RTX);
- 
- #ifdef FUNCTION_ARG_PASS_BY_REFERENCE
-       if (FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far, mode, NULL_TREE, 1))
- 	{
- 	  /* We do not support FUNCTION_ARG_CALLEE_COPIES here since it can
- 	     be viewed as just an efficiency improvement.  */
- 	  rtx slot = assign_stack_temp (mode, GET_MODE_SIZE (mode), 0);
- 	  emit_move_insn (slot, val);
- 	  val = force_operand (XEXP (slot, 0), NULL_RTX);
- 	  mode = Pmode;
- 	}
- #endif
- 
-       argvec[count].value = val;
-       argvec[count].mode = mode;
- 
-       argvec[count].reg = FUNCTION_ARG (args_so_far, mode, NULL_TREE, 1);
- 
- #ifdef FUNCTION_ARG_PARTIAL_NREGS
-       argvec[count].partial
- 	= FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode, NULL_TREE, 1);
- #else
-       argvec[count].partial = 0;
- #endif
- 
-       locate_and_pad_parm (mode, NULL_TREE,
- 			   argvec[count].reg && argvec[count].partial == 0,
- 			   NULL_TREE, &args_size, &argvec[count].offset,
- 			   &argvec[count].size, &alignment_pad);
- 
-       if (argvec[count].size.var)
- 	abort ();
- 
-       if (reg_parm_stack_space == 0 && argvec[count].partial)
- 	argvec[count].size.constant -= argvec[count].partial * UNITS_PER_WORD;
- 
-       if (argvec[count].reg == 0 || argvec[count].partial != 0
- 	  || reg_parm_stack_space > 0)
- 	args_size.constant += argvec[count].size.constant;
- 
-       FUNCTION_ARG_ADVANCE (args_so_far, mode, (tree) 0, 1);
-     }
-   va_end (p);
- 
- #ifdef FINAL_REG_PARM_STACK_SPACE
-   reg_parm_stack_space = FINAL_REG_PARM_STACK_SPACE (args_size.constant,
- 						     args_size.var);
- #endif
-       
-   /* If this machine requires an external definition for library
-      functions, write one out.  */
-   assemble_external_libcall (fun);
- 
-   original_args_size = args_size;
- #ifdef PREFERRED_STACK_BOUNDARY
-   args_size.constant = (((args_size.constant + (STACK_BYTES - 1))
- 			 / STACK_BYTES) * STACK_BYTES);
- #endif
- 
-   args_size.constant = MAX (args_size.constant,
- 			    reg_parm_stack_space);
- 
- #ifndef OUTGOING_REG_PARM_STACK_SPACE
-   args_size.constant -= reg_parm_stack_space;
- #endif
- 
-   if (args_size.constant > current_function_outgoing_args_size)
-     current_function_outgoing_args_size = args_size.constant;
- 
- #ifdef ACCUMULATE_OUTGOING_ARGS
-   /* Since the stack pointer will never be pushed, it is possible for
-      the evaluation of a parm to clobber something we have already
-      written to the stack.  Since most function calls on RISC machines
-      do not use the stack, this is uncommon, but must work correctly.
- 
-      Therefore, we save any area of the stack that was already written
-      and that we are using.  Here we set up to do this by making a new
-      stack usage map from the old one.
- 
-      Another approach might be to try to reorder the argument
-      evaluations to avoid this conflicting stack usage.  */
- 
-   needed = args_size.constant;
- 
- #ifndef OUTGOING_REG_PARM_STACK_SPACE
-   /* Since we will be writing into the entire argument area, the
-      map must be allocated for its entire size, not just the part that
-      is the responsibility of the caller.  */
-   needed += reg_parm_stack_space;
- #endif
- 
- #ifdef ARGS_GROW_DOWNWARD
-   highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use,
- 				     needed + 1);
- #else
-   highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use,
- 				     needed);
- #endif
-   stack_usage_map = (char *) alloca (highest_outgoing_arg_in_use);
- 
-   if (initial_highest_arg_in_use)
-     bcopy (initial_stack_usage_map, stack_usage_map,
- 	   initial_highest_arg_in_use);
- 
-   if (initial_highest_arg_in_use != highest_outgoing_arg_in_use)
-     bzero (&stack_usage_map[initial_highest_arg_in_use],
- 	   highest_outgoing_arg_in_use - initial_highest_arg_in_use);
-   needed = 0;
- 
-   /* The address of the outgoing argument list must not be copied to a
-      register here, because argblock would be left pointing to the
-      wrong place after the call to allocate_dynamic_stack_space below.
-      */
- 
-   argblock = virtual_outgoing_args_rtx;
- #else /* not ACCUMULATE_OUTGOING_ARGS */
- #ifndef PUSH_ROUNDING
-   argblock = push_block (GEN_INT (args_size.constant), 0, 0);
- #endif
- #endif
- 
- #ifdef PUSH_ARGS_REVERSED
- #ifdef PREFERRED_STACK_BOUNDARY
-   /* If we push args individually in reverse order, perform stack alignment
-      before the first push (the last arg).  */
-   if (argblock == 0)
-     anti_adjust_stack (GEN_INT (args_size.constant
- 				- original_args_size.constant));
- #endif
- #endif
- 
- #ifdef PUSH_ARGS_REVERSED
-   inc = -1;
-   argnum = nargs - 1;
- #else
-   inc = 1;
-   argnum = 0;
- #endif
- 
- #if defined(ACCUMULATE_OUTGOING_ARGS) && defined(REG_PARM_STACK_SPACE)
-   /* The argument list is the property of the called routine and it
-      may clobber it.  If the fixed area has been used for previous
-      parameters, we must save and restore it.
- 
-      Here we compute the boundary of the that needs to be saved, if any.  */
- 
- #ifdef ARGS_GROW_DOWNWARD
-   for (count = 0; count < reg_parm_stack_space + 1; count++)
- #else
-   for (count = 0; count < reg_parm_stack_space; count++)
- #endif
-     {
-       if (count >=  highest_outgoing_arg_in_use
- 	  || stack_usage_map[count] == 0)
- 	continue;
- 
-       if (low_to_save == -1)
- 	low_to_save = count;
- 
-       high_to_save = count;
-     }
- 
-   if (low_to_save >= 0)
-     {
-       int num_to_save = high_to_save - low_to_save + 1;
-       enum machine_mode save_mode
- 	= mode_for_size (num_to_save * BITS_PER_UNIT, MODE_INT, 1);
-       rtx stack_area;
- 
-       /* If we don't have the required alignment, must do this in BLKmode.  */
-       if ((low_to_save & (MIN (GET_MODE_SIZE (save_mode),
- 			       BIGGEST_ALIGNMENT / UNITS_PER_WORD) - 1)))
- 	save_mode = BLKmode;
- 
- #ifdef ARGS_GROW_DOWNWARD
-       stack_area = gen_rtx_MEM (save_mode,
- 				memory_address (save_mode,
- 						plus_constant (argblock,
- 							       - high_to_save)));
- #else
-       stack_area = gen_rtx_MEM (save_mode,
- 				memory_address (save_mode,
- 						plus_constant (argblock,
- 							       low_to_save)));
- #endif
-       if (save_mode == BLKmode)
- 	{
- 	  save_area = assign_stack_temp (BLKmode, num_to_save, 0);
- 	  emit_block_move (validize_mem (save_area), stack_area,
- 			   GEN_INT (num_to_save),
- 			   PARM_BOUNDARY / BITS_PER_UNIT);
- 	}
-       else
- 	{
- 	  save_area = gen_reg_rtx (save_mode);
- 	  emit_move_insn (save_area, stack_area);
- 	}
-     }
- #endif
- 	  
-   /* Push the args that need to be pushed.  */
- 
-   /* ARGNUM indexes the ARGVEC array in the order in which the arguments
-      are to be pushed.  */
-   for (count = 0; count < nargs; count++, argnum += inc)
-     {
-       register enum machine_mode mode = argvec[argnum].mode;
-       register rtx val = argvec[argnum].value;
-       rtx reg = argvec[argnum].reg;
-       int partial = argvec[argnum].partial;
- #ifdef ACCUMULATE_OUTGOING_ARGS
-       int lower_bound, upper_bound, i;
- #endif
- 
-       if (! (reg != 0 && partial == 0))
- 	{
- #ifdef ACCUMULATE_OUTGOING_ARGS
- 	  /* If this is being stored into a pre-allocated, fixed-size, stack
- 	     area, save any previous data at that location.  */
- 
- #ifdef ARGS_GROW_DOWNWARD
- 	  /* stack_slot is negative, but we want to index stack_usage_map
- 	     with positive values.  */
- 	  upper_bound = -argvec[argnum].offset.constant + 1;
- 	  lower_bound = upper_bound - argvec[argnum].size.constant;
- #else
- 	  lower_bound = argvec[argnum].offset.constant;
- 	  upper_bound = lower_bound + argvec[argnum].size.constant;
- #endif
- 
- 	  for (i = lower_bound; i < upper_bound; i++)
- 	    if (stack_usage_map[i]
- 		/* Don't store things in the fixed argument area at this point;
- 		   it has already been saved.  */
- 		&& i > reg_parm_stack_space)
- 	      break;
- 
- 	  if (i != upper_bound)
- 	    {
- 	      /* We need to make a save area.  See what mode we can make it. */
- 	      enum machine_mode save_mode
- 		= mode_for_size (argvec[argnum].size.constant * BITS_PER_UNIT,
- 				 MODE_INT, 1);
- 	      rtx stack_area
- 		= gen_rtx_MEM
- 		  (save_mode,
- 		   memory_address
- 		   (save_mode,
- 		    plus_constant (argblock,
- 				   argvec[argnum].offset.constant)));
- 
- 	      argvec[argnum].save_area = gen_reg_rtx (save_mode);
- 	      emit_move_insn (argvec[argnum].save_area, stack_area);
- 	    }
- #endif
- 	  emit_push_insn (val, mode, NULL_TREE, NULL_RTX, 0, partial, reg, 0,
- 			  argblock, GEN_INT (argvec[argnum].offset.constant),
- 			  reg_parm_stack_space, ARGS_SIZE_RTX (alignment_pad));
- 
- #ifdef ACCUMULATE_OUTGOING_ARGS
- 	  /* Now mark the segment we just used.  */
- 	  for (i = lower_bound; i < upper_bound; i++)
- 	    stack_usage_map[i] = 1;
- #endif
- 
- 	  NO_DEFER_POP;
- 	}
-     }
- 
- #ifndef PUSH_ARGS_REVERSED
- #ifdef PREFERRED_STACK_BOUNDARY
-   /* If we pushed args in forward order, perform stack alignment
-      after pushing the last arg.  */
-   if (argblock == 0)
-     anti_adjust_stack (GEN_INT (args_size.constant
- 				- original_args_size.constant));
- #endif
- #endif
- 
- #ifdef PUSH_ARGS_REVERSED
-   argnum = nargs - 1;
- #else
-   argnum = 0;
- #endif
- 
-   fun = prepare_call_address (fun, NULL_TREE, &call_fusage, 0);
- 
-   /* Now load any reg parms into their regs.  */
- 
-   /* ARGNUM indexes the ARGVEC array in the order in which the arguments
-      are to be pushed.  */
-   for (count = 0; count < nargs; count++, argnum += inc)
-     {
-       register rtx val = argvec[argnum].value;
-       rtx reg = argvec[argnum].reg;
-       int partial = argvec[argnum].partial;
- 
-       /* Handle calls that pass values in multiple non-contiguous
- 	 locations.  The PA64 has examples of this for library calls.  */
-       if (reg != 0 && GET_CODE (reg) == PARALLEL)
- 	emit_group_load (reg, val,
- 			 GET_MODE_SIZE (GET_MODE (val)),
- 			 GET_MODE_ALIGNMENT (GET_MODE (val)));
-       else if (reg != 0 && partial == 0)
- 	emit_move_insn (reg, val);
- 
-       NO_DEFER_POP;
-     }
- 
-   /* For version 1.37, try deleting this entirely.  */
-   if (! no_queue)
-     emit_queue ();
- 
-   /* Any regs containing parms remain in use through the call.  */
-   for (count = 0; count < nargs; count++)
-     {
-       rtx reg = argvec[count].reg;
-       if (reg != 0 && GET_CODE (argvec[count].reg) == PARALLEL)
- 	use_group_regs (&call_fusage, reg);
-       else if (reg != 0)
- 	use_reg (&call_fusage, reg);
-     }
- 
-   /* Don't allow popping to be deferred, since then
-      cse'ing of library calls could delete a call and leave the pop.  */
-   NO_DEFER_POP;
- 
-   /* We pass the old value of inhibit_defer_pop + 1 to emit_call_1, which
-      will set inhibit_defer_pop to that value.  */
- 
-   /* The return type is needed to decide how many bytes the function pops.
-      Signedness plays no role in that, so for simplicity, we pretend it's
-      always signed.  We also assume that the list of arguments passed has
-      no impact, so we pretend it is unknown.  */
- 
-   emit_call_1 (fun, 
-                get_identifier (XSTR (orgfun, 0)), 
- 	       build_function_type (outmode == VOIDmode ? void_type_node
- 				    : type_for_mode (outmode, 0), NULL_TREE),
- 	       original_args_size.constant, args_size.constant, 0,
- 	       FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
- 	       outmode != VOIDmode ? hard_libcall_value (outmode) : NULL_RTX,
- 	       old_inhibit_defer_pop + 1, call_fusage,
- 	       ((no_queue ? ECF_IS_CONST : 0)
- 		| (nothrow ? ECF_NOTHROW : 0)));
- 
-   pop_temp_slots ();
- 
-   /* Now restore inhibit_defer_pop to its actual original value.  */
-   OK_DEFER_POP;
- 
- #ifdef ACCUMULATE_OUTGOING_ARGS
- #ifdef REG_PARM_STACK_SPACE
-   if (save_area)
-     {
-       enum machine_mode save_mode = GET_MODE (save_area);
- #ifdef ARGS_GROW_DOWNWARD
-       rtx stack_area
- 	= gen_rtx_MEM (save_mode,
- 		       memory_address (save_mode,
- 				       plus_constant (argblock,
- 						       - high_to_save)));
- #else
-       rtx stack_area
- 	= gen_rtx_MEM (save_mode,
- 		       memory_address (save_mode,
- 				       plus_constant (argblock, low_to_save)));
- #endif
- 
-       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),
- 			 PARM_BOUNDARY / BITS_PER_UNIT);
-     }
- #endif
- 	  
-   /* If we saved any argument areas, restore them.  */
-   for (count = 0; count < nargs; count++)
-     if (argvec[count].save_area)
-       {
- 	enum machine_mode save_mode = GET_MODE (argvec[count].save_area);
- 	rtx stack_area
- 	  = gen_rtx_MEM (save_mode,
- 			 memory_address
- 			 (save_mode,
- 			  plus_constant (argblock,
- 					 argvec[count].offset.constant)));
- 
- 	emit_move_insn (stack_area, argvec[count].save_area);
-       }
- 
-   highest_outgoing_arg_in_use = initial_highest_arg_in_use;
-   stack_usage_map = initial_stack_usage_map;
- #endif
- }
  
! /* Like emit_library_call except that an extra argument, VALUE,
!    comes second and says where to store the result.
!    (If VALUE is zero, this function chooses a convenient way
!    to return the value.
! 
!    This function returns an rtx for where the value is to be found.
!    If VALUE is nonzero, VALUE is returned.  */
! 
! rtx
! emit_library_call_value VPARAMS((rtx orgfun, rtx value, int no_queue,
! 				 enum machine_mode outmode, int nargs, ...))
  {
- #ifndef ANSI_PROTOTYPES
-   rtx orgfun;
-   rtx value;
-   int no_queue;
-   enum machine_mode outmode;
-   int nargs;
- #endif
-   va_list p;
    /* Total size in bytes of all the stack-parms scanned so far.  */
    struct args_size args_size;
    /* Size of arguments before any adjustments (such as rounding).  */
--- 3029,3048 ----
  
    return 1;
  }
  
! /* Output a library call to function FUN (a SYMBOL_REF rtx).
!    The RETVAL parameter specifies whether return value needs to be saved, other 
!    parameters are documented in the emit_library_call function bellow.  */
! static rtx
! emit_library_call_value_1 (retval, orgfun, value, no_queue, outmode, nargs, p)
!      int retval;
!      rtx orgfun;
!      rtx value;
!      int no_queue;
!      enum machine_mode outmode;
!      int nargs;
!      va_list p;
  {
    /* Total size in bytes of all the stack-parms scanned so far.  */
    struct args_size args_size;
    /* Size of arguments before any adjustments (such as rounding).  */
*************** emit_library_call_value VPARAMS((rtx org
*** 3626,3641 ****
  #endif
  #endif
  
-   VA_START (p, nargs);
- 
- #ifndef ANSI_PROTOTYPES
-   orgfun = va_arg (p, rtx);
-   value = va_arg (p, rtx);
-   no_queue = va_arg (p, int);
-   outmode = va_arg (p, enum machine_mode);
-   nargs = va_arg (p, int);
- #endif
- 
    is_const = no_queue;
    fun = orgfun;
  
--- 3090,3095 ----
*************** emit_library_call_value VPARAMS((rtx org
*** 3650,3656 ****
  
    /* If this kind of value comes back in memory,
       decide where in memory it should come back.  */
!   if (aggregate_value_p (type_for_mode (outmode, 0)))
      {
  #ifdef PCC_STATIC_STRUCT_RETURN
        rtx pointer_reg
--- 3104,3110 ----
  
    /* 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)))
      {
  #ifdef PCC_STATIC_STRUCT_RETURN
        rtx pointer_reg
*************** emit_library_call_value VPARAMS((rtx org
*** 3763,3769 ****
  	     be viewed as just an efficiency improvement.  */
  	  rtx slot = assign_stack_temp (mode, GET_MODE_SIZE (mode), 0);
  	  emit_move_insn (slot, val);
! 	  val = XEXP (slot, 0);
  	  mode = Pmode;
  	}
  #endif
--- 3217,3223 ----
  	     be viewed as just an efficiency improvement.  */
  	  rtx slot = assign_stack_temp (mode, GET_MODE_SIZE (mode), 0);
  	  emit_move_insn (slot, val);
! 	  val = force_operand (XEXP (slot, 0), NULL_RTX);
  	  mode = Pmode;
  	}
  #endif
*************** emit_library_call_value VPARAMS((rtx org
*** 3797,3803 ****
  
        FUNCTION_ARG_ADVANCE (args_so_far, mode, (tree) 0, 1);
      }
-   va_end (p);
  
  #ifdef FINAL_REG_PARM_STACK_SPACE
    reg_parm_stack_space = FINAL_REG_PARM_STACK_SPACE (args_size.constant,
--- 3251,3256 ----
*************** emit_library_call_value VPARAMS((rtx org
*** 4096,4111 ****
  
    /* We pass the old value of inhibit_defer_pop + 1 to emit_call_1, which
       will set inhibit_defer_pop to that value.  */
!   /* See the comment in emit_library_call about the function type we build
!      and pass here.  */
  
    emit_call_1 (fun, 
                 get_identifier (XSTR (orgfun, 0)),
! 	       build_function_type (type_for_mode (outmode, 0), NULL_TREE),
                 original_args_size.constant, args_size.constant,
  	       struct_value_size,
  	       FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
! 	       mem_value == 0 ? hard_libcall_value (outmode) : NULL_RTX,
  	       old_inhibit_defer_pop + 1, call_fusage,
  	       ((is_const ? ECF_IS_CONST : 0)
  		| (nothrow ? ECF_NOTHROW : 0)));
--- 3549,3567 ----
  
    /* We pass the old value of inhibit_defer_pop + 1 to emit_call_1, which
       will set inhibit_defer_pop to that value.  */
!   /* The return type is needed to decide how many bytes the function pops.
!      Signedness plays no role in that, so for simplicity, we pretend it's
!      always signed.  We also assume that the list of arguments passed has
!      no impact, so we pretend it is unknown.  */
  
    emit_call_1 (fun, 
                 get_identifier (XSTR (orgfun, 0)),
! 	       build_function_type (outmode == VOIDmode ? void_type_node
! 				    : type_for_mode (outmode, 0), NULL_TREE),
                 original_args_size.constant, args_size.constant,
  	       struct_value_size,
  	       FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
! 	       mem_value == 0 && outmode != VOIDmode ? hard_libcall_value (outmode) : NULL_RTX,
  	       old_inhibit_defer_pop + 1, call_fusage,
  	       ((is_const ? ECF_IS_CONST : 0)
  		| (nothrow ? ECF_NOTHROW : 0)));
*************** emit_library_call_value VPARAMS((rtx org
*** 4116,4122 ****
    pop_temp_slots ();
  
    /* Copy the value to the right place.  */
!   if (outmode != VOIDmode)
      {
        if (mem_value)
  	{
--- 3572,3578 ----
    pop_temp_slots ();
  
    /* Copy the value to the right place.  */
!   if (outmode != VOIDmode && retval)
      {
        if (mem_value)
  	{
*************** emit_library_call_value VPARAMS((rtx org
*** 4175,4180 ****
--- 3631,3721 ----
    highest_outgoing_arg_in_use = initial_highest_arg_in_use;
    stack_usage_map = initial_stack_usage_map;
  #endif
+ 
+   return value;
+ 
+ }
+ 
+ /* Output a library call to function FUN (a SYMBOL_REF rtx)
+    (emitting the queue unless NO_QUEUE is nonzero),
+    for a value of mode OUTMODE,
+    with NARGS different arguments, passed as alternating rtx values
+    and machine_modes to convert them to.
+    The rtx values should have been passed through protect_from_queue already.
+ 
+    NO_QUEUE will be true if and only if the library call is a `const' call
+    which will be enclosed in REG_LIBCALL/REG_RETVAL notes; it is equivalent
+    to the variable is_const in expand_call.
+ 
+    NO_QUEUE must be true for const calls, because if it isn't, then
+    any pending increment will be emitted between REG_LIBCALL/REG_RETVAL notes,
+    and will be lost if the libcall sequence is optimized away.
+ 
+    NO_QUEUE must be false for non-const calls, because if it isn't, the
+    call insn will have its CONST_CALL_P bit set, and it will be incorrectly
+    optimized.  For instance, the instruction scheduler may incorrectly
+    move memory references across the non-const call.  */
+ 
+ void
+ emit_library_call VPARAMS((rtx orgfun, int no_queue, enum machine_mode outmode,
+ 			   int nargs, ...))
+ {
+ #ifndef ANSI_PROTOTYPES
+   rtx orgfun;
+   int no_queue;
+   enum machine_mode outmode;
+   int nargs;
+ #endif
+   va_list p;
+ 
+   VA_START (p, nargs);
+ 
+ #ifndef ANSI_PROTOTYPES
+   orgfun = va_arg (p, rtx);
+   no_queue = va_arg (p, int);
+   outmode = va_arg (p, enum machine_mode);
+   nargs = va_arg (p, int);
+ #endif
+ 
+   emit_library_call_value_1 (0, orgfun, NULL_RTX, no_queue, outmode, nargs, p);
+ 
+   va_end (p);
+ }
+ 
+ /* Like emit_library_call except that an extra argument, VALUE,
+    comes second and says where to store the result.
+    (If VALUE is zero, this function chooses a convenient way
+    to return the value.
+ 
+    This function returns an rtx for where the value is to be found.
+    If VALUE is nonzero, VALUE is returned.  */
+ 
+ rtx
+ emit_library_call_value VPARAMS((rtx orgfun, rtx value, int no_queue,
+ 				 enum machine_mode outmode, int nargs, ...))
+ {
+ #ifndef ANSI_PROTOTYPES
+   rtx orgfun;
+   rtx value;
+   int no_queue;
+   enum machine_mode outmode;
+   int nargs;
+ #endif
+   va_list p;
+ 
+   VA_START (p, nargs);
+ 
+ #ifndef ANSI_PROTOTYPES
+   orgfun = va_arg (p, rtx);
+   value = va_arg (p, rtx);
+   no_queue = va_arg (p, int);
+   outmode = va_arg (p, enum machine_mode);
+   nargs = va_arg (p, int);
+ #endif
+ 
+   value = emit_library_call_value_1 (1, orgfun, value, no_queue, outmode, nargs, p);
+ 
+   va_end (p);
  
    return value;
  }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]