static void precompute_arguments (int, int, struct arg_data *);
static int compute_argument_block_size (int, struct args_size *, int);
static void initialize_argument_information (int, struct arg_data *,
- struct args_size *, int, tree,
+ struct args_size *, int,
+ tree, tree,
tree, CUMULATIVE_ARGS *, int,
rtx *, int *, int *, int *,
bool *, bool);
static int combine_pending_stack_adjustment_and_call (int, struct args_size *,
unsigned int);
-static tree split_complex_values (tree);
static tree split_complex_types (tree);
#ifdef REG_PARM_STACK_SPACE
}
/* Fill in ARGS_SIZE and ARGS array based on the parameters found in
- ACTPARMS.
+ CALL_EXPR EXP.
NUM_ACTUALS is the total number of parameters.
N_NAMED_ARGS is the total number of named arguments.
+ STRUCT_VALUE_ADDR_VALUE is the implicit argument for a struct return
+ value, or null.
+
FNDECL is the tree code for the target of this call (if known)
ARGS_SO_FAR holds state needed by the target to know where to place
struct arg_data *args,
struct args_size *args_size,
int n_named_args ATTRIBUTE_UNUSED,
- tree actparms, tree fndecl,
+ tree exp, tree struct_value_addr_value,
+ tree fndecl,
CUMULATIVE_ARGS *args_so_far,
int reg_parm_stack_space,
rtx *old_stack_level, int *old_pending_adj,
int argpos;
int i;
- tree p;
args_size->constant = 0;
args_size->var = 0;
i = 0, inc = 1;
}
+ /* First fill in the actual arguments in the ARGS array, splitting
+ complex arguments if necessary. */
+ {
+ int j = i;
+ call_expr_arg_iterator iter;
+ tree arg;
+
+ if (struct_value_addr_value)
+ {
+ args[j].tree_value = struct_value_addr_value;
+ j += inc;
+ }
+ FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
+ {
+ tree argtype = TREE_TYPE (arg);
+ if (targetm.calls.split_complex_arg
+ && argtype
+ && TREE_CODE (argtype) == COMPLEX_TYPE
+ && 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);
+ }
+ else
+ args[j].tree_value = arg;
+ j += inc;
+ }
+ }
+
/* I counts args in order (to be) pushed; ARGPOS counts in order written. */
- for (p = actparms, argpos = 0; p; p = TREE_CHAIN (p), i += inc, argpos++)
+ for (argpos = 0; argpos < num_actuals; i += inc, argpos++)
{
- tree type = TREE_TYPE (TREE_VALUE (p));
+ tree type = TREE_TYPE (args[i].tree_value);
int unsignedp;
enum machine_mode mode;
- args[i].tree_value = TREE_VALUE (p);
-
/* Replace erroneous argument with constant zero. */
if (type == error_mark_node || !COMPLETE_TYPE_P (type))
args[i].tree_value = integer_zero_node, type = integer_type_node;
{
/* This is a variable-sized object. Make space on the stack
for it. */
- rtx size_rtx = expr_size (TREE_VALUE (p));
+ rtx size_rtx = expr_size (args[i].tree_value);
if (*old_stack_level == 0)
{
= size_binop (MAX_EXPR, args_size->var,
ssize_int (reg_parm_stack_space));
-#ifndef OUTGOING_REG_PARM_STACK_SPACE
/* The area corresponding to register parameters is not to count in
the size of the block we need. So make the adjustment. */
- args_size->var
- = size_binop (MINUS_EXPR, args_size->var,
- ssize_int (reg_parm_stack_space));
-#endif
+ if (!OUTGOING_REG_PARM_STACK_SPACE)
+ args_size->var
+ = size_binop (MINUS_EXPR, args_size->var,
+ ssize_int (reg_parm_stack_space));
}
}
else
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 (!OUTGOING_REG_PARM_STACK_SPACE)
+ args_size->constant -= reg_parm_stack_space;
}
return unadjusted_args_size;
}
/* Nonzero if we are currently expanding a call. */
static int currently_expanding_call = 0;
- /* List of actual parameters. */
- /* FIXME: rewrite this so that it doesn't cons up a TREE_LIST. */
- tree actparms = CALL_EXPR_ARGS (exp);
/* RTX for the function to be called. */
rtx funexp;
/* Sequence of insns to perform a normal "call". */
an extra, implicit first parameter. Otherwise,
it is passed by being copied directly into struct_value_rtx. */
int structure_value_addr_parm = 0;
+ /* Holds the value of implicit argument for the struct value. */
+ tree structure_value_addr_value = NULL_TREE;
/* Size of aggregate value wanted, or zero if none wanted
or if we are using the non-reentrant PCC calling convention
or expecting the value in registers. */
/* Number of named args. Args after this are anonymous ones
and they must all go on the stack. */
int n_named_args;
+ /* Number of complex actual arguments that need to be split. */
+ int num_complex_actuals = 0;
/* Vector of information about each argument.
Arguments are numbered in the order they will be pushed,
{
bool volatilep = false;
tree arg;
+ call_expr_arg_iterator iter;
- for (arg = actparms; arg; arg = TREE_CHAIN (arg))
- if (TREE_THIS_VOLATILE (TREE_VALUE (arg)))
+ FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
+ if (TREE_THIS_VOLATILE (arg))
{
volatilep = true;
break;
if (! volatilep)
{
- for (arg = actparms; arg; arg = TREE_CHAIN (arg))
- expand_expr (TREE_VALUE (arg), const0_rtx,
- VOIDmode, EXPAND_NORMAL);
+ FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
+ expand_expr (arg, const0_rtx, VOIDmode, EXPAND_NORMAL);
return const0_rtx;
}
}
reg_parm_stack_space = REG_PARM_STACK_SPACE (fndecl);
#endif
-#ifndef OUTGOING_REG_PARM_STACK_SPACE
- if (reg_parm_stack_space > 0 && PUSH_ARGS)
+ if (!OUTGOING_REG_PARM_STACK_SPACE && reg_parm_stack_space > 0 && PUSH_ARGS)
must_preallocate = 1;
-#endif
/* Set up a place to return a structure. */
gcc_assert (POINTER_TYPE_P (funtype));
funtype = TREE_TYPE (funtype);
- /* Munge the tree to split complex arguments into their imaginary
- and real parts. */
+ /* Count whether there are actual complex arguments that need to be split
+ into their real and imaginary parts. Munge the type_arg_types
+ appropriately here as well. */
if (targetm.calls.split_complex_arg)
{
+ call_expr_arg_iterator iter;
+ tree arg;
+ FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
+ {
+ tree type = TREE_TYPE (arg);
+ if (type && TREE_CODE (type) == COMPLEX_TYPE
+ && targetm.calls.split_complex_arg (type))
+ num_complex_actuals++;
+ }
type_arg_types = split_complex_types (TYPE_ARG_TYPES (funtype));
- actparms = split_complex_values (actparms);
}
else
type_arg_types = TYPE_ARG_TYPES (funtype);
current_function_calls_alloca = 1;
/* If struct_value_rtx is 0, it means pass the address
- as if it were an extra parameter. */
+ as if it were an extra parameter. Put the argument expression
+ in structure_value_addr_value. */
if (structure_value_addr && struct_value == 0)
{
/* If structure_value_addr is a REG other than
(Pmode, structure_value_addr))
: structure_value_addr);
- actparms
- = tree_cons (error_mark_node,
- make_tree (build_pointer_type (TREE_TYPE (funtype)),
- temp),
- actparms);
+ structure_value_addr_value =
+ make_tree (build_pointer_type (TREE_TYPE (funtype)), temp);
structure_value_addr_parm = 1;
}
/* Count the arguments and set NUM_ACTUALS. */
- for (p = actparms, num_actuals = 0; p; p = TREE_CHAIN (p))
- num_actuals++;
+ num_actuals =
+ call_expr_nargs (exp) + num_complex_actuals + structure_value_addr_parm;
/* Compute number of named args.
First, do a raw count of the args for INIT_CUMULATIVE_ARGS. */
/* Build up entries in the ARGS array, compute the size of the
arguments into ARGS_SIZE, etc. */
initialize_argument_information (num_actuals, args, &args_size,
- n_named_args, actparms, fndecl,
+ n_named_args, exp,
+ structure_value_addr_value, fndecl,
&args_so_far, reg_parm_stack_space,
&old_stack_level, &old_pending_adj,
&must_preallocate, &flags,
Another approach might be to try to reorder the argument
evaluations to avoid this conflicting stack usage. */
-#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
+ if (!OUTGOING_REG_PARM_STACK_SPACE)
+ needed += reg_parm_stack_space;
#ifdef ARGS_GROW_DOWNWARD
highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use,
an argument. */
if (stack_arg_under_construction)
{
-#ifndef OUTGOING_REG_PARM_STACK_SPACE
- rtx push_size = GEN_INT (reg_parm_stack_space
- + adjusted_args_size.constant);
-#else
- rtx push_size = GEN_INT (adjusted_args_size.constant);
-#endif
+ rtx push_size
+ = GEN_INT (adjusted_args_size.constant
+ + (OUTGOING_REG_PARM_STACK_SPACE ? 0
+ : reg_parm_stack_space));
if (old_stack_level == 0)
{
emit_stack_save (SAVE_BLOCK, &old_stack_level,
/* If register arguments require space on the stack and stack space
was not preallocated, allocate stack space here for arguments
passed in registers. */
-#ifdef OUTGOING_REG_PARM_STACK_SPACE
- if (!ACCUMULATE_OUTGOING_ARGS
+ if (OUTGOING_REG_PARM_STACK_SPACE && !ACCUMULATE_OUTGOING_ARGS
&& must_preallocate == 0 && reg_parm_stack_space > 0)
anti_adjust_stack (GEN_INT (reg_parm_stack_space));
-#endif
/* Pass the function the address in which to return a
structure value. */
}
}
-/* Traverse an argument list in VALUES and expand all complex
- arguments into their components. */
-static tree
-split_complex_values (tree values)
-{
- tree p;
-
- /* Before allocating memory, check for the common case of no complex. */
- for (p = values; p; p = TREE_CHAIN (p))
- {
- tree type = TREE_TYPE (TREE_VALUE (p));
- if (type && TREE_CODE (type) == COMPLEX_TYPE
- && targetm.calls.split_complex_arg (type))
- goto found;
- }
- return values;
-
- found:
- values = copy_list (values);
-
- for (p = values; p; p = TREE_CHAIN (p))
- {
- tree complex_value = TREE_VALUE (p);
- tree complex_type;
-
- complex_type = TREE_TYPE (complex_value);
- if (!complex_type)
- continue;
-
- if (TREE_CODE (complex_type) == COMPLEX_TYPE
- && targetm.calls.split_complex_arg (complex_type))
- {
- tree subtype;
- tree real, imag, next;
-
- subtype = TREE_TYPE (complex_type);
- complex_value = save_expr (complex_value);
- real = build1 (REALPART_EXPR, subtype, complex_value);
- imag = build1 (IMAGPART_EXPR, subtype, complex_value);
-
- TREE_VALUE (p) = real;
- next = TREE_CHAIN (p);
- imag = build_tree_list (NULL_TREE, imag);
- TREE_CHAIN (p) = imag;
- TREE_CHAIN (imag) = next;
-
- /* Skip the newly created node. */
- p = TREE_CHAIN (p);
- }
- }
-
- return values;
-}
-
/* Traverse a list of TYPES and expand all complex types into their
components. */
static tree
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 (!OUTGOING_REG_PARM_STACK_SPACE)
+ args_size.constant -= reg_parm_stack_space;
if (args_size.constant > current_function_outgoing_args_size)
current_function_outgoing_args_size = args_size.constant;
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
+ if (!OUTGOING_REG_PARM_STACK_SPACE)
+ needed += reg_parm_stack_space;
#ifdef ARGS_GROW_DOWNWARD
highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use,
if (reg != 0 && GET_CODE (reg) == PARALLEL)
use_group_regs (&call_fusage, reg);
else if (reg != 0)
- use_reg (&call_fusage, reg);
+ {
+ int partial = argvec[count].partial;
+ if (partial)
+ {
+ int nregs;
+ gcc_assert (partial % UNITS_PER_WORD == 0);
+ nregs = partial / UNITS_PER_WORD;
+ use_regs (&call_fusage, REGNO (reg), nregs);
+ }
+ else
+ use_reg (&call_fusage, reg);
+ }
}
/* Pass the function the address in which to return a structure value. */