/* Initially-compute RTL value for argument; only for const functions. */
rtx initial_value;
/* Register to pass this argument in, 0 if passed on stack, or an
- EXPR_LIST if the arg is to be copied into multiple different
+ PARALLEL if the arg is to be copied into multiple non-contiguous
registers. */
rtx reg;
/* If REG was promoted from the actual mode of the argument expression,
funexp = protect_from_queue (funexp, 0);
if (fndecl != 0)
- /* Get possible static chain value for nested function in C. */
+ /* Get possible static chain value for nested function in C. */
static_chain_value = lookup_static_chain (fndecl);
/* Make a valid memory address and copy constants thru pseudo-regs,
/* Nonzero if a reg parm has been scanned. */
int reg_parm_seen;
/* Nonzero if this is an indirect function call. */
- int current_call_is_indirect = 0;
/* Nonzero if we must avoid push-insns in the args for this call.
If stack space is allocated for register parameters, but not by the
if (!flag_no_inline
&& fndecl != current_function_decl
&& DECL_INLINE (fndecl)
- && DECL_SAVED_INSNS (fndecl))
+ && DECL_SAVED_INSNS (fndecl)
+ && RTX_INTEGRATED_P (DECL_SAVED_INSNS (fndecl)))
is_integrable = 1;
else if (! TREE_ADDRESSABLE (fndecl))
{
if (stack_arg_under_construction || i >= 0)
{
- rtx insn = NEXT_INSN (before_call), seq;
+ rtx first_insn
+ = before_call ? NEXT_INSN (before_call) : get_insns ();
+ rtx insn, seq;
/* Look for a call in the inline function code.
If OUTGOING_ARGS_SIZE (DECL_SAVED_INSNS (fndecl)) is
to scan the insns. */
if (OUTGOING_ARGS_SIZE (DECL_SAVED_INSNS (fndecl)) == 0)
- for (; insn; insn = NEXT_INSN (insn))
+ for (insn = first_insn; insn; insn = NEXT_INSN (insn))
if (GET_CODE (insn) == CALL_INSN)
break;
NULL_RTX, BITS_PER_UNIT);
seq = get_insns ();
end_sequence ();
- emit_insns_before (seq, NEXT_INSN (before_call));
+ emit_insns_before (seq, first_insn);
emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
}
}
if (fndecl && DECL_NAME (fndecl))
name = IDENTIFIER_POINTER (DECL_NAME (fndecl));
- /* On some machines (such as the PA) indirect calls have a different
- calling convention than normal calls. FUNCTION_ARG in the target
- description can look at current_call_is_indirect to determine which
- calling convention to use. */
- current_call_is_indirect = (fndecl == 0);
-#if 0
- = TREE_CODE (TREE_OPERAND (exp, 0)) == NON_LVALUE_EXPR ? 1 : 0;
-#endif
-
#if 0
/* Unless it's a call to a specific function that isn't alloca,
if it has one argument, we must assume it might be alloca. */
we make. */
push_temp_slots ();
- /* Start updating where the next arg would go. */
- INIT_CUMULATIVE_ARGS (args_so_far, funtype, NULL_RTX);
+ /* Start updating where the next arg would go.
+
+ On some machines (such as the PA) indirect calls have a different
+ calling convention than normal calls. The last argument in
+ INIT_CUMULATIVE_ARGS tells the backend if this is an indirect call
+ or not. */
+ INIT_CUMULATIVE_ARGS (args_so_far, funtype, NULL_RTX, (fndecl == 0));
/* If struct_value_rtx is 0, it means pass the address
as if it were an extra parameter. */
MEM_IN_STRUCT_P (copy) = AGGREGATE_TYPE_P (type);
store_expr (args[i].tree_value, copy, 0);
+ is_const = 0;
args[i].tree_value = build1 (ADDR_EXPR,
build_pointer_type (type),
args[i].pass_on_stack = MUST_PASS_IN_STACK (mode, type);
- /* If FUNCTION_ARG returned an (expr_list (nil) FOO), it means that
- we are to pass this arg in the register(s) designated by FOO, but
- also to pass it in the stack. */
- if (args[i].reg && GET_CODE (args[i].reg) == EXPR_LIST
- && XEXP (args[i].reg, 0) == 0)
- args[i].pass_on_stack = 1, args[i].reg = XEXP (args[i].reg, 1);
+ /* If FUNCTION_ARG returned a (parallel [(expr_list (nil) ...) ...]),
+ it means that we are to pass this arg in the register(s) designated
+ by the PARALLEL, but also to pass it in the stack. */
+ if (args[i].reg && GET_CODE (args[i].reg) == PARALLEL
+ && XEXP (XVECEXP (args[i].reg, 0, 0), 0) == 0)
+ args[i].pass_on_stack = 1;
/* If this is an addressable type, we must preallocate the stack
since we must evaluate the object into its final location.
int needed = args_size.constant;
- /* Store the maximum argument space used. It will be pushed by the
- prologue (if ACCUMULATE_OUTGOING_ARGS, or stack overflow checking). */
+ /* Store the maximum argument space used. It will be pushed by
+ the prologue (if ACCUMULATE_OUTGOING_ARGS, or stack overflow
+ checking). */
if (needed > current_function_outgoing_args_size)
current_function_outgoing_args_size = needed;
}
/* Precompute all register parameters. It isn't safe to compute anything
- once we have started filling any specific hard regs. */
+ once we have started filling any specific hard regs. */
reg_parm_seen = 0;
for (i = 0; i < num_actuals; i++)
if (args[i].reg != 0 && ! args[i].pass_on_stack)
for (i = 0; i < num_actuals; i++)
{
- rtx list = args[i].reg;
+ rtx reg = args[i].reg;
int partial = args[i].partial;
+ int nregs;
- while (list)
+ if (reg)
{
- rtx reg;
- int nregs;
-
- /* Process each register that needs to get this arg. */
- if (GET_CODE (list) == EXPR_LIST)
- reg = XEXP (list, 0), list = XEXP (list, 1);
- else
- reg = list, list = 0;
-
/* 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
+ (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
: -1));
+ /* Handle calls that pass values in multiple non-contiguous
+ locations. The Irix 6 ABI has examples of this. */
+
+ if (GET_CODE (reg) == PARALLEL)
+ emit_group_load (reg, args[i].value);
+
/* If simple case, just do move. If normal partial, store_one_arg
has already loaded the register for us. In all other cases,
load the register(s) from memory. */
- if (nregs == -1)
+ else if (nregs == -1)
emit_move_insn (reg, args[i].value);
/* If we have pre-computed the values to put in the registers in
emit_move_insn (gen_rtx (REG, word_mode, REGNO (reg) + j),
args[i].aligned_regs[j]);
- else if (args[i].partial == 0 || args[i].pass_on_stack)
+ else if (partial == 0 || args[i].pass_on_stack)
move_block_to_reg (REGNO (reg),
validize_mem (args[i].value), nregs,
args[i].mode);
- if (nregs == -1)
+ /* Handle calls that pass values in multiple non-contiguous
+ locations. The Irix 6 ABI has examples of this. */
+ if (GET_CODE (reg) == PARALLEL)
+ use_group_regs (&call_fusage, reg);
+ else if (nregs == -1)
use_reg (&call_fusage, reg);
else
use_regs (&call_fusage, REGNO (reg), nregs == 0 ? 1 : nregs);
-
- /* PARTIAL referred only to the first register, so clear it for the
- next time. */
- partial = 0;
}
}
If they refer to the same register, this move will be a no-op, except
when function inlining is being done. */
emit_move_insn (target, valreg);
+ /* Handle calls that return values in multiple non-contiguous locations.
+ The Irix 6 ABI has examples of this. */
+ else if (GET_CODE (valreg) == PARALLEL)
+ {
+ if (target == 0)
+ {
+ int bytes = int_size_in_bytes (TREE_TYPE (exp));
+ target = assign_stack_temp (TYPE_MODE (TREE_TYPE (exp)), bytes, 0);
+ MEM_IN_STRUCT_P (target) = AGGREGATE_TYPE_P (TREE_TYPE (exp));
+ preserve_temp_slots (target);
+ }
+
+ emit_group_store (target, valreg);
+ }
else if (TYPE_MODE (TREE_TYPE (exp)) == BLKmode)
{
/* Some machines (the PA for example) want to return all small
copy it into a new pseudo which is a full word. */
if (GET_MODE (valreg) != BLKmode
&& GET_MODE_SIZE (GET_MODE (valreg)) < UNITS_PER_WORD)
- valreg = convert_to_mode (SImode, valreg,
+ valreg = convert_to_mode (word_mode, valreg,
TREE_UNSIGNED (TREE_TYPE (exp)));
/* Structures whose size is not a multiple of a word are aligned
/* If this was alloca, record the new stack level for nonlocal gotos.
Check for the handler slots since we might not have a save area
- for non-local gotos. */
+ for non-local gotos. */
if (may_be_alloca && nonlocal_goto_handler_slot != 0)
emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, NULL_RTX);
struct arg *argvec;
int old_inhibit_defer_pop = inhibit_defer_pop;
rtx call_fusage = 0;
- /* library calls are never indirect calls. */
- int current_call_is_indirect = 0;
VA_START (p, nargs);
argvec = (struct arg *) alloca (nargs * sizeof (struct arg));
- INIT_CUMULATIVE_ARGS (args_so_far, NULL_TREE, fun);
+ INIT_CUMULATIVE_ARGS (args_so_far, NULL_TREE, fun, 0);
args_size.constant = 0;
args_size.var = 0;
argvec[count].mode = mode;
argvec[count].reg = FUNCTION_ARG (args_so_far, mode, NULL_TREE, 1);
- if (argvec[count].reg && GET_CODE (argvec[count].reg) == EXPR_LIST)
+ if (argvec[count].reg && GET_CODE (argvec[count].reg) == PARALLEL)
abort ();
#ifdef FUNCTION_ARG_PARTIAL_NREGS
argvec[count].partial
abort ();
#endif
- FUNCTION_ARG_ADVANCE (args_so_far, mode, (tree)0, 1);
+ FUNCTION_ARG_ADVANCE (args_so_far, mode, (tree) 0, 1);
}
va_end (p);
rtx mem_value = 0;
int pcc_struct_value = 0;
int struct_value_size = 0;
- /* library calls are never indirect calls. */
- int current_call_is_indirect = 0;
int is_const;
VA_START (p, nargs);
argvec = (struct arg *) alloca ((nargs + 1) * sizeof (struct arg));
- INIT_CUMULATIVE_ARGS (args_so_far, NULL_TREE, fun);
+ INIT_CUMULATIVE_ARGS (args_so_far, NULL_TREE, fun, 0);
args_size.constant = 0;
args_size.var = 0;
)
args_size.constant += argvec[count].size.constant;
- FUNCTION_ARG_ADVANCE (args_so_far, Pmode, (tree)0, 1);
+ FUNCTION_ARG_ADVANCE (args_so_far, Pmode, (tree) 0, 1);
count++;
}
argvec[count].mode = mode;
argvec[count].reg = FUNCTION_ARG (args_so_far, mode, NULL_TREE, 1);
- if (argvec[count].reg && GET_CODE (argvec[count].reg) == EXPR_LIST)
+ if (argvec[count].reg && GET_CODE (argvec[count].reg) == PARALLEL)
abort ();
#ifdef FUNCTION_ARG_PARTIAL_NREGS
argvec[count].partial
abort ();
#endif
- FUNCTION_ARG_ADVANCE (args_so_far, mode, (tree)0, 1);
+ FUNCTION_ARG_ADVANCE (args_so_far, mode, (tree) 0, 1);
}
va_end (p);
if (argblock && ! variable_size && arg->stack)
{
#ifdef ARGS_GROW_DOWNWARD
- /* stack_slot is negative, but we want to index stack_usage_map */
- /* with positive values. */
+ /* stack_slot is negative, but we want to index stack_usage_map
+ with positive values. */
if (GET_CODE (XEXP (arg->stack_slot, 0)) == PLUS)
upper_bound = -INTVAL (XEXP (XEXP (arg->stack_slot, 0), 1)) + 1;
else
if (arg->n_aligned_regs != 0)
reg = 0;
- /* If this is being partially passed in a register, but multiple locations
- are specified, we assume that the one partially used is the one that is
- listed first. */
- if (reg && GET_CODE (reg) == EXPR_LIST)
- reg = XEXP (reg, 0);
-
/* If this is being passed partially in a register, we can't evaluate
it directly into its stack slot. Otherwise, we can. */
if (arg->value == 0)