Commit cacbd532 by Jim Wilson

(expand_call): Handle NIL in PARALLEL.

(expand_call): Handle NIL in PARALLEL.  Handle PARALLEL
parameter in REG.  Handle PARALLEL return value in VALREG.
(emit_library_call, emit_library_call_value): Abort for PARALLEL.
(store_one_arg): Delete code for handling EXPR_LIST.

From-SVN: r12188
parent 1853aadd
...@@ -60,7 +60,7 @@ struct arg_data ...@@ -60,7 +60,7 @@ struct arg_data
/* Initially-compute RTL value for argument; only for const functions. */ /* Initially-compute RTL value for argument; only for const functions. */
rtx initial_value; rtx initial_value;
/* Register to pass this argument in, 0 if passed on stack, or an /* 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. */ registers. */
rtx reg; rtx reg;
/* If REG was promoted from the actual mode of the argument expression, /* If REG was promoted from the actual mode of the argument expression,
...@@ -1112,12 +1112,12 @@ expand_call (exp, target, ignore) ...@@ -1112,12 +1112,12 @@ expand_call (exp, target, ignore)
args[i].pass_on_stack = MUST_PASS_IN_STACK (mode, type); args[i].pass_on_stack = MUST_PASS_IN_STACK (mode, type);
/* If FUNCTION_ARG returned an (expr_list (nil) FOO), it means that /* If FUNCTION_ARG returned a (parallel [(expr_list (nil) ...) ...]),
we are to pass this arg in the register(s) designated by FOO, but it means that we are to pass this arg in the register(s) designated
also to pass it in the stack. */ by the PARALLEL, but also to pass it in the stack. */
if (args[i].reg && GET_CODE (args[i].reg) == EXPR_LIST if (args[i].reg && GET_CODE (args[i].reg) == PARALLEL
&& XEXP (args[i].reg, 0) == 0) && XEXP (XVECEXP (args[i].reg, 0, 0), 0) == 0)
args[i].pass_on_stack = 1, args[i].reg = XEXP (args[i].reg, 1); args[i].pass_on_stack = 1;
/* If this is an addressable type, we must preallocate the stack /* If this is an addressable type, we must preallocate the stack
since we must evaluate the object into its final location. since we must evaluate the object into its final location.
...@@ -1846,20 +1846,12 @@ expand_call (exp, target, ignore) ...@@ -1846,20 +1846,12 @@ expand_call (exp, target, ignore)
for (i = 0; i < num_actuals; i++) for (i = 0; i < num_actuals; i++)
{ {
rtx list = args[i].reg; rtx reg = args[i].reg;
int partial = args[i].partial; 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 /* 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 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 we just use a normal move insn. This value can be zero if the
...@@ -1870,11 +1862,17 @@ expand_call (exp, target, ignore) ...@@ -1870,11 +1862,17 @@ expand_call (exp, target, ignore)
+ (UNITS_PER_WORD - 1)) / UNITS_PER_WORD) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
: -1)); : -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 /* If simple case, just do move. If normal partial, store_one_arg
has already loaded the register for us. In all other cases, has already loaded the register for us. In all other cases,
load the register(s) from memory. */ load the register(s) from memory. */
if (nregs == -1) else if (nregs == -1)
emit_move_insn (reg, args[i].value); emit_move_insn (reg, args[i].value);
/* If we have pre-computed the values to put in the registers in /* If we have pre-computed the values to put in the registers in
...@@ -1885,19 +1883,19 @@ expand_call (exp, target, ignore) ...@@ -1885,19 +1883,19 @@ expand_call (exp, target, ignore)
emit_move_insn (gen_rtx (REG, word_mode, REGNO (reg) + j), emit_move_insn (gen_rtx (REG, word_mode, REGNO (reg) + j),
args[i].aligned_regs[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), move_block_to_reg (REGNO (reg),
validize_mem (args[i].value), nregs, validize_mem (args[i].value), nregs,
args[i].mode); 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); use_reg (&call_fusage, reg);
else else
use_regs (&call_fusage, REGNO (reg), nregs == 0 ? 1 : nregs); 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;
} }
} }
...@@ -2032,6 +2030,20 @@ expand_call (exp, target, ignore) ...@@ -2032,6 +2030,20 @@ expand_call (exp, target, ignore)
If they refer to the same register, this move will be a no-op, except If they refer to the same register, this move will be a no-op, except
when function inlining is being done. */ when function inlining is being done. */
emit_move_insn (target, valreg); 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 (BLKmode, 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) else if (TYPE_MODE (TREE_TYPE (exp)) == BLKmode)
{ {
/* Some machines (the PA for example) want to return all small /* Some machines (the PA for example) want to return all small
...@@ -2326,7 +2338,7 @@ emit_library_call VPROTO((rtx orgfun, int no_queue, enum machine_mode outmode, ...@@ -2326,7 +2338,7 @@ emit_library_call VPROTO((rtx orgfun, int no_queue, enum machine_mode outmode,
argvec[count].mode = mode; argvec[count].mode = mode;
argvec[count].reg = FUNCTION_ARG (args_so_far, mode, NULL_TREE, 1); 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 (); abort ();
#ifdef FUNCTION_ARG_PARTIAL_NREGS #ifdef FUNCTION_ARG_PARTIAL_NREGS
argvec[count].partial argvec[count].partial
...@@ -2674,7 +2686,7 @@ emit_library_call_value VPROTO((rtx orgfun, rtx value, int no_queue, ...@@ -2674,7 +2686,7 @@ emit_library_call_value VPROTO((rtx orgfun, rtx value, int no_queue,
argvec[count].mode = mode; argvec[count].mode = mode;
argvec[count].reg = FUNCTION_ARG (args_so_far, mode, NULL_TREE, 1); 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 (); abort ();
#ifdef FUNCTION_ARG_PARTIAL_NREGS #ifdef FUNCTION_ARG_PARTIAL_NREGS
argvec[count].partial argvec[count].partial
...@@ -3030,12 +3042,6 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size, fndecl, ...@@ -3030,12 +3042,6 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size, fndecl,
if (arg->n_aligned_regs != 0) if (arg->n_aligned_regs != 0)
reg = 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 /* If this is being passed partially in a register, we can't evaluate
it directly into its stack slot. Otherwise, we can. */ it directly into its stack slot. Otherwise, we can. */
if (arg->value == 0) if (arg->value == 0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment