expr.c (gen_group_rtx, [...]): New functions.
* expr.c (gen_group_rtx, emit_group_move): New functions. * expr.h (gen_group_rtx, emit_group_move): Prototype. * function.c (expand_function_start): Use gen_group_rtx to create a PARALLEL rtx to hold the return value when the real return rtx is a PARALLEL. (expand_function_end): Use emit_group_move to move the return value from a PARALLEL to the real return registers. * rtl.h (REG_FUNCTION_VALUE_P): Allow function values to be returned in PARALLELs. From-SVN: r59554
This commit is contained in:
parent
a16f235752
commit
084a11066f
@ -1,3 +1,15 @@
|
|||||||
|
2002-11-26 John David Anglin <dave@hiauly1.hia.nrc.ca>
|
||||||
|
|
||||||
|
* expr.c (gen_group_rtx, emit_group_move): New functions.
|
||||||
|
* expr.h (gen_group_rtx, emit_group_move): Prototype.
|
||||||
|
* function.c (expand_function_start): Use gen_group_rtx to create a
|
||||||
|
PARALLEL rtx to hold the return value when the real return rtx is a
|
||||||
|
PARALLEL.
|
||||||
|
(expand_function_end): Use emit_group_move to move the return value
|
||||||
|
from a PARALLEL to the real return registers.
|
||||||
|
* rtl.h (REG_FUNCTION_VALUE_P): Allow function values to be returned
|
||||||
|
in PARALLELs.
|
||||||
|
|
||||||
2002-11-26 Jason Thorpe <thorpej@wasabisystems.com>
|
2002-11-26 Jason Thorpe <thorpej@wasabisystems.com>
|
||||||
|
|
||||||
* config/t-libc-ok: Fix typo.
|
* config/t-libc-ok: Fix typo.
|
||||||
|
56
gcc/expr.c
56
gcc/expr.c
@ -2203,6 +2203,42 @@ move_block_from_reg (regno, x, nregs, size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Generate a PARALLEL rtx for a new non-consecutive group of registers from
|
||||||
|
ORIG, where ORIG is a non-consecutive group of registers represented by
|
||||||
|
a PARALLEL. The clone is identical to the original except in that the
|
||||||
|
original set of registers is replaced by a new set of pseudo registers.
|
||||||
|
The new set has the same modes as the original set. */
|
||||||
|
|
||||||
|
rtx
|
||||||
|
gen_group_rtx (orig)
|
||||||
|
rtx orig;
|
||||||
|
{
|
||||||
|
int i, length;
|
||||||
|
rtx *tmps;
|
||||||
|
|
||||||
|
if (GET_CODE (orig) != PARALLEL)
|
||||||
|
abort ();
|
||||||
|
|
||||||
|
length = XVECLEN (orig, 0);
|
||||||
|
tmps = (rtx *) alloca (sizeof (rtx) * length);
|
||||||
|
|
||||||
|
/* Skip a NULL entry in first slot. */
|
||||||
|
i = XEXP (XVECEXP (orig, 0, 0), 0) ? 0 : 1;
|
||||||
|
|
||||||
|
if (i)
|
||||||
|
tmps[0] = 0;
|
||||||
|
|
||||||
|
for (; i < length; i++)
|
||||||
|
{
|
||||||
|
enum machine_mode mode = GET_MODE (XEXP (XVECEXP (orig, 0, i), 0));
|
||||||
|
rtx offset = XEXP (XVECEXP (orig, 0, i), 1);
|
||||||
|
|
||||||
|
tmps[i] = gen_rtx_EXPR_LIST (VOIDmode, gen_reg_rtx (mode), offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return gen_rtx_PARALLEL (GET_MODE (orig), gen_rtvec_v (length, tmps));
|
||||||
|
}
|
||||||
|
|
||||||
/* Emit code to move a block SRC to a block DST, where DST is non-consecutive
|
/* Emit code to move a block SRC to a block DST, where DST is non-consecutive
|
||||||
registers represented by a PARALLEL. SSIZE represents the total size of
|
registers represented by a PARALLEL. SSIZE represents the total size of
|
||||||
block SRC in bytes, or -1 if not known. */
|
block SRC in bytes, or -1 if not known. */
|
||||||
@ -2324,6 +2360,26 @@ emit_group_load (dst, orig_src, ssize)
|
|||||||
emit_move_insn (XEXP (XVECEXP (dst, 0, i), 0), tmps[i]);
|
emit_move_insn (XEXP (XVECEXP (dst, 0, i), 0), tmps[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Emit code to move a block SRC to block DST, where SRC and DST are
|
||||||
|
non-consecutive groups of registers, each represented by a PARALLEL. */
|
||||||
|
|
||||||
|
void
|
||||||
|
emit_group_move (dst, src)
|
||||||
|
rtx dst, src;
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (GET_CODE (src) != PARALLEL
|
||||||
|
|| GET_CODE (dst) != PARALLEL
|
||||||
|
|| XVECLEN (src, 0) != XVECLEN (dst, 0))
|
||||||
|
abort ();
|
||||||
|
|
||||||
|
/* Skip first entry if NULL. */
|
||||||
|
for (i = XEXP (XVECEXP (src, 0, 0), 0) ? 0 : 1; i < XVECLEN (src, 0); i++)
|
||||||
|
emit_move_insn (XEXP (XVECEXP (dst, 0, i), 0),
|
||||||
|
XEXP (XVECEXP (src, 0, i), 0));
|
||||||
|
}
|
||||||
|
|
||||||
/* Emit code to move a block SRC to a block DST, where SRC is non-consecutive
|
/* Emit code to move a block SRC to a block DST, where SRC is non-consecutive
|
||||||
registers represented by a PARALLEL. SSIZE represents the total size of
|
registers represented by a PARALLEL. SSIZE represents the total size of
|
||||||
block DST, or -1 if not known. */
|
block DST, or -1 if not known. */
|
||||||
|
@ -412,10 +412,17 @@ extern void move_block_to_reg PARAMS ((int, rtx, int, enum machine_mode));
|
|||||||
The number of registers to be filled is NREGS. */
|
The number of registers to be filled is NREGS. */
|
||||||
extern void move_block_from_reg PARAMS ((int, rtx, int, int));
|
extern void move_block_from_reg PARAMS ((int, rtx, int, int));
|
||||||
|
|
||||||
|
/* Generate a non-consecutive group of registers represented by a PARALLEL. */
|
||||||
|
extern rtx gen_group_rtx PARAMS ((rtx));
|
||||||
|
|
||||||
/* Load a BLKmode value into non-consecutive registers represented by a
|
/* Load a BLKmode value into non-consecutive registers represented by a
|
||||||
PARALLEL. */
|
PARALLEL. */
|
||||||
extern void emit_group_load PARAMS ((rtx, rtx, int));
|
extern void emit_group_load PARAMS ((rtx, rtx, int));
|
||||||
|
|
||||||
|
/* Move a non-consecutive group of registers represented by a PARALLEL into
|
||||||
|
a non-consecutive group of registers represented by a PARALLEL. */
|
||||||
|
extern void emit_group_move PARAMS ((rtx, rtx));
|
||||||
|
|
||||||
/* Store a BLKmode value from non-consecutive registers represented by a
|
/* Store a BLKmode value from non-consecutive registers represented by a
|
||||||
PARALLEL. */
|
PARALLEL. */
|
||||||
extern void emit_group_store PARAMS ((rtx, rtx, int));
|
extern void emit_group_store PARAMS ((rtx, rtx, int));
|
||||||
|
@ -6559,19 +6559,18 @@ expand_function_start (subr, parms_have_cleanups)
|
|||||||
subr, 1);
|
subr, 1);
|
||||||
|
|
||||||
/* Structures that are returned in registers are not aggregate_value_p,
|
/* Structures that are returned in registers are not aggregate_value_p,
|
||||||
so we may see a PARALLEL. Don't play pseudo games with this. */
|
so we may see a PARALLEL or a REG. */
|
||||||
if (! REG_P (hard_reg))
|
if (REG_P (hard_reg))
|
||||||
SET_DECL_RTL (DECL_RESULT (subr), hard_reg);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Create the pseudo. */
|
|
||||||
SET_DECL_RTL (DECL_RESULT (subr), gen_reg_rtx (GET_MODE (hard_reg)));
|
SET_DECL_RTL (DECL_RESULT (subr), gen_reg_rtx (GET_MODE (hard_reg)));
|
||||||
|
else if (GET_CODE (hard_reg) == PARALLEL)
|
||||||
|
SET_DECL_RTL (DECL_RESULT (subr), gen_group_rtx (hard_reg));
|
||||||
|
else
|
||||||
|
abort ();
|
||||||
|
|
||||||
/* Needed because we may need to move this to memory
|
/* Set DECL_REGISTER flag so that expand_function_end will copy the
|
||||||
in case it's a named return value whose address is taken. */
|
result to the real return register(s). */
|
||||||
DECL_REGISTER (DECL_RESULT (subr)) = 1;
|
DECL_REGISTER (DECL_RESULT (subr)) = 1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize rtx for parameters and local variables.
|
/* Initialize rtx for parameters and local variables.
|
||||||
In some cases this requires emitting insns. */
|
In some cases this requires emitting insns. */
|
||||||
@ -6998,8 +6997,16 @@ expand_function_end (filename, line, end_bindings)
|
|||||||
convert_move (real_decl_rtl, decl_rtl, unsignedp);
|
convert_move (real_decl_rtl, decl_rtl, unsignedp);
|
||||||
}
|
}
|
||||||
else if (GET_CODE (real_decl_rtl) == PARALLEL)
|
else if (GET_CODE (real_decl_rtl) == PARALLEL)
|
||||||
|
{
|
||||||
|
/* If expand_function_start has created a PARALLEL for decl_rtl,
|
||||||
|
move the result to the real return registers. Otherwise, do
|
||||||
|
a group load from decl_rtl for a named return. */
|
||||||
|
if (GET_CODE (decl_rtl) == PARALLEL)
|
||||||
|
emit_group_move (real_decl_rtl, decl_rtl);
|
||||||
|
else
|
||||||
emit_group_load (real_decl_rtl, decl_rtl,
|
emit_group_load (real_decl_rtl, decl_rtl,
|
||||||
int_size_in_bytes (TREE_TYPE (decl_result)));
|
int_size_in_bytes (TREE_TYPE (decl_result)));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
emit_move_insn (real_decl_rtl, decl_rtl);
|
emit_move_insn (real_decl_rtl, decl_rtl);
|
||||||
}
|
}
|
||||||
|
@ -185,7 +185,7 @@ struct rtx_def GTY((chain_next ("RTX_NEXT (&%h)"),
|
|||||||
has used it as the function. */
|
has used it as the function. */
|
||||||
unsigned int used : 1;
|
unsigned int used : 1;
|
||||||
/* Nonzero if this rtx came from procedure integration.
|
/* Nonzero if this rtx came from procedure integration.
|
||||||
1 in a REG means this reg refers to the return value
|
1 in a REG or PARALLEL means this rtx refers to the return value
|
||||||
of the current function.
|
of the current function.
|
||||||
1 in a SYMBOL_REF if the symbol is weak. */
|
1 in a SYMBOL_REF if the symbol is weak. */
|
||||||
unsigned integrated : 1;
|
unsigned integrated : 1;
|
||||||
@ -988,9 +988,10 @@ enum label_kind
|
|||||||
#define REGNO(RTX) XCUINT (RTX, 0, REG)
|
#define REGNO(RTX) XCUINT (RTX, 0, REG)
|
||||||
#define ORIGINAL_REGNO(RTX) X0UINT (RTX, 1)
|
#define ORIGINAL_REGNO(RTX) X0UINT (RTX, 1)
|
||||||
|
|
||||||
/* 1 if RTX is a reg that is the current function's return value. */
|
/* 1 if RTX is a reg or parallel that is the current function's return
|
||||||
|
value. */
|
||||||
#define REG_FUNCTION_VALUE_P(RTX) \
|
#define REG_FUNCTION_VALUE_P(RTX) \
|
||||||
(RTL_FLAG_CHECK1("REG_FUNCTION_VALUE_P", (RTX), REG)->integrated)
|
(RTL_FLAG_CHECK2("REG_FUNCTION_VALUE_P", (RTX), REG, PARALLEL)->integrated)
|
||||||
|
|
||||||
/* 1 if RTX is a reg that corresponds to a variable declared by the user. */
|
/* 1 if RTX is a reg that corresponds to a variable declared by the user. */
|
||||||
#define REG_USERVAR_P(RTX) \
|
#define REG_USERVAR_P(RTX) \
|
||||||
|
Loading…
Reference in New Issue
Block a user