Commit 48028e21 by Eric Botcazou Committed by Eric Botcazou

re PR target/10142 ([SPARC64] gcc produces wrong code when passing structures by value)

	PR target/10142
	* config/sparc/sparc.c (function_arg_record_value_parms): Add
	new 'stack' field.
	(function_arg_record_value_1): Set 'stack' to 1 if we run out of
	integer slots for an integer field.
	(function_arg_record_value_3): Shift vector index.
	(function_arg_record_value_2): Likewise.
	(function_arg_record_value): Initialize 'stack' to 0.
	Set 'stack' to 1 if we run out of integer slots for an integer field.
	Generate (parallel [(expr_list (nil) ...) ...]) if 'stack' is set to 1.

Co-Authored-By: Christian Ehrhardt <ehrhardt@mathematik.uni-ulm.de>

From-SVN: r67874
parent 28e089c6
2003-06-13 Eric Botcazou <ebotcazou@libertysurf.fr> 2003-06-13 Eric Botcazou <ebotcazou@libertysurf.fr>
Christian Ehrhardt <ehrhardt@mathematik.uni-ulm.de>
PR target/10142
* config/sparc/sparc.c (function_arg_record_value_parms): Add
new 'stack' field.
(function_arg_record_value_1): Set 'stack' to 1 if we run out of
integer slots for an integer field.
(function_arg_record_value_3): Shift vector index.
(function_arg_record_value_2): Likewise.
(function_arg_record_value): Initialize 'stack' to 0.
Set 'stack' to 1 if we run out of integer slots for an integer field.
Generate (parallel [(expr_list (nil) ...) ...]) if 'stack' is set to 1.
2003-06-13 Eric Botcazou <ebotcazou@libertysurf.fr>
PR optimization/10955 PR optimization/10955
* unroll.c (unroll_loop): Fix off-by-one bug. * unroll.c (unroll_loop): Fix off-by-one bug.
......
...@@ -4530,10 +4530,13 @@ function_arg_slotno (cum, mode, type, named, incoming_p, pregno, ppadding) ...@@ -4530,10 +4530,13 @@ function_arg_slotno (cum, mode, type, named, incoming_p, pregno, ppadding)
struct function_arg_record_value_parms struct function_arg_record_value_parms
{ {
rtx ret; rtx ret; /* return expression being built. */
int slotno, named, regbase; int slotno; /* slot number of the argument. */
unsigned int nregs; int named; /* whether the argument is named. */
int intoffset; int regbase; /* regno of the base register. */
int stack; /* 1 if part of the argument is on the stack. */
int intoffset; /* offset of the pending integer field. */
unsigned int nregs; /* number of words passed in registers. */
}; };
static void function_arg_record_value_3 static void function_arg_record_value_3
...@@ -4608,8 +4611,13 @@ function_arg_record_value_1 (type, startbitpos, parms) ...@@ -4608,8 +4611,13 @@ function_arg_record_value_1 (type, startbitpos, parms)
this_slotno = parms->slotno + parms->intoffset this_slotno = parms->slotno + parms->intoffset
/ BITS_PER_WORD; / BITS_PER_WORD;
intslots = MIN (intslots, SPARC_INT_ARG_MAX - this_slotno); if (intslots > 0 && intslots > SPARC_INT_ARG_MAX - this_slotno)
intslots = MAX (intslots, 0); {
intslots = MAX (0, SPARC_INT_ARG_MAX - this_slotno);
/* We need to pass this field on the stack. */
parms->stack = 1;
}
parms->nregs += intslots; parms->nregs += intslots;
parms->intoffset = -1; parms->intoffset = -1;
} }
...@@ -4674,7 +4682,7 @@ function_arg_record_value_3 (bitpos, parms) ...@@ -4674,7 +4682,7 @@ function_arg_record_value_3 (bitpos, parms)
{ {
regno = parms->regbase + this_slotno; regno = parms->regbase + this_slotno;
reg = gen_rtx_REG (mode, regno); reg = gen_rtx_REG (mode, regno);
XVECEXP (parms->ret, 0, parms->nregs) XVECEXP (parms->ret, 0, parms->stack + parms->nregs)
= gen_rtx_EXPR_LIST (VOIDmode, reg, GEN_INT (intoffset)); = gen_rtx_EXPR_LIST (VOIDmode, reg, GEN_INT (intoffset));
this_slotno += 1; this_slotno += 1;
...@@ -4747,7 +4755,7 @@ function_arg_record_value_2 (type, startbitpos, parms) ...@@ -4747,7 +4755,7 @@ function_arg_record_value_2 (type, startbitpos, parms)
default: break; default: break;
} }
reg = gen_rtx_REG (mode, regno); reg = gen_rtx_REG (mode, regno);
XVECEXP (parms->ret, 0, parms->nregs) XVECEXP (parms->ret, 0, parms->stack + parms->nregs)
= gen_rtx_EXPR_LIST (VOIDmode, reg, = gen_rtx_EXPR_LIST (VOIDmode, reg,
GEN_INT (bitpos / BITS_PER_UNIT)); GEN_INT (bitpos / BITS_PER_UNIT));
parms->nregs += 1; parms->nregs += 1;
...@@ -4755,7 +4763,7 @@ function_arg_record_value_2 (type, startbitpos, parms) ...@@ -4755,7 +4763,7 @@ function_arg_record_value_2 (type, startbitpos, parms)
{ {
regno += GET_MODE_SIZE (mode) / 4; regno += GET_MODE_SIZE (mode) / 4;
reg = gen_rtx_REG (mode, regno); reg = gen_rtx_REG (mode, regno);
XVECEXP (parms->ret, 0, parms->nregs) XVECEXP (parms->ret, 0, parms->stack + parms->nregs)
= gen_rtx_EXPR_LIST (VOIDmode, reg, = gen_rtx_EXPR_LIST (VOIDmode, reg,
GEN_INT ((bitpos + GET_MODE_BITSIZE (mode)) GEN_INT ((bitpos + GET_MODE_BITSIZE (mode))
/ BITS_PER_UNIT)); / BITS_PER_UNIT));
...@@ -4772,8 +4780,19 @@ function_arg_record_value_2 (type, startbitpos, parms) ...@@ -4772,8 +4780,19 @@ function_arg_record_value_2 (type, startbitpos, parms)
} }
/* Used by function_arg and function_value to implement the complex /* Used by function_arg and function_value to implement the complex
SPARC64 structure calling conventions. */ conventions of the 64-bit ABI for passing and returning structures.
Return an expression valid as a return value for the two macros
FUNCTION_ARG and FUNCTION_VALUE.
TYPE is the data type of the argument (as a tree).
This is null for libcalls where that information may
not be available.
MODE is the argument's machine mode.
SLOTNO is the index number of the argument's slot in the parameter array.
NAMED is nonzero if this argument is a named parameter
(otherwise it is an extra parameter matching an ellipsis).
REGBASE is the regno of the base register for the parameter array. */
static rtx static rtx
function_arg_record_value (type, mode, slotno, named, regbase) function_arg_record_value (type, mode, slotno, named, regbase)
tree type; tree type;
...@@ -4788,6 +4807,7 @@ function_arg_record_value (type, mode, slotno, named, regbase) ...@@ -4788,6 +4807,7 @@ function_arg_record_value (type, mode, slotno, named, regbase)
parms.slotno = slotno; parms.slotno = slotno;
parms.named = named; parms.named = named;
parms.regbase = regbase; parms.regbase = regbase;
parms.stack = 0;
/* Compute how many registers we need. */ /* Compute how many registers we need. */
parms.nregs = 0; parms.nregs = 0;
...@@ -4804,8 +4824,12 @@ function_arg_record_value (type, mode, slotno, named, regbase) ...@@ -4804,8 +4824,12 @@ function_arg_record_value (type, mode, slotno, named, regbase)
intslots = (endbit - startbit) / BITS_PER_WORD; intslots = (endbit - startbit) / BITS_PER_WORD;
this_slotno = slotno + parms.intoffset / BITS_PER_WORD; this_slotno = slotno + parms.intoffset / BITS_PER_WORD;
intslots = MIN (intslots, SPARC_INT_ARG_MAX - this_slotno); if (intslots > 0 && intslots > SPARC_INT_ARG_MAX - this_slotno)
intslots = MAX (intslots, 0); {
intslots = MAX (0, SPARC_INT_ARG_MAX - this_slotno);
/* We need to pass this field on the stack. */
parms.stack = 1;
}
parms.nregs += intslots; parms.nregs += intslots;
} }
...@@ -4835,7 +4859,17 @@ function_arg_record_value (type, mode, slotno, named, regbase) ...@@ -4835,7 +4859,17 @@ function_arg_record_value (type, mode, slotno, named, regbase)
if (nregs == 0) if (nregs == 0)
abort (); abort ();
parms.ret = gen_rtx_PARALLEL (mode, rtvec_alloc (nregs)); parms.ret = gen_rtx_PARALLEL (mode, rtvec_alloc (parms.stack + nregs));
/* If at least one field must be passed on the stack, generate
(parallel [(expr_list (nil) ...) ...]) so that all fields will
also be passed on the stack. We can't do much better because the
semantics of FUNCTION_ARG_PARTIAL_NREGS doesn't handle the case
of structures for which the fields passed exclusively in registers
are not at the beginning of the structure. */
if (parms.stack)
XVECEXP (parms.ret, 0, 0)
= gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx);
/* Fill in the entries. */ /* Fill in the entries. */
parms.nregs = 0; parms.nregs = 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