re PR target/34042 (Segfault in mips_cannot_change_mode_class)

gcc/
	PR target/34042
	* config/mips/mips.c (mips_return_fpr_single): New function.
	(mips_function_value): Use it when returning single-field
	aggregates in FPRs.
	(mips_expand_call): Handle the PARALLELs created by
	mips_return_fpr_single.

From-SVN: r130119
This commit is contained in:
Richard Sandiford 2007-11-12 20:05:46 +00:00 committed by Richard Sandiford
parent 3aa64f2ccc
commit fd0d4c1fbb
2 changed files with 45 additions and 4 deletions

View file

@ -1,3 +1,12 @@
2007-11-12 Richard Sandiford <rsandifo@nildram.co.uk>
PR target/34042
* config/mips/mips.c (mips_return_fpr_single): New function.
(mips_function_value): Use it when returning single-field
aggregates in FPRs.
(mips_expand_call): Handle the PARALLELs created by
mips_return_fpr_single.
2007-11-12 Richard Guenther <rguenther@suse.de> 2007-11-12 Richard Guenther <rguenther@suse.de>
PR middle-end/34070 PR middle-end/34070

View file

@ -4451,6 +4451,31 @@ mips_return_mode_in_fpr_p (enum machine_mode mode)
&& GET_MODE_UNIT_SIZE (mode) <= UNITS_PER_HWFPVALUE); && GET_MODE_UNIT_SIZE (mode) <= UNITS_PER_HWFPVALUE);
} }
/* Return the representation of an FPR return register when the
value being returned in FP_RETURN has mode VALUE_MODE and the
return type itself has mode TYPE_MODE. On NewABI targets,
the two modes may be different for structures like:
struct __attribute__((packed)) foo { float f; }
where we return the SFmode value of "f" in FP_RETURN, but where
the structure itself has mode BLKmode. */
static rtx
mips_return_fpr_single (enum machine_mode type_mode,
enum machine_mode value_mode)
{
rtx x;
x = gen_rtx_REG (value_mode, FP_RETURN);
if (type_mode != value_mode)
{
x = gen_rtx_EXPR_LIST (VOIDmode, x, const0_rtx);
x = gen_rtx_PARALLEL (type_mode, gen_rtvec (1, x));
}
return x;
}
/* Return a composite value in a pair of floating-point registers. /* Return a composite value in a pair of floating-point registers.
MODE1 and OFFSET1 are the mode and byte offset for the first value, MODE1 and OFFSET1 are the mode and byte offset for the first value,
likewise MODE2 and OFFSET2 for the second. MODE is the mode of the likewise MODE2 and OFFSET2 for the second. MODE is the mode of the
@ -4502,7 +4527,8 @@ mips_function_value (const_tree valtype, enum machine_mode mode)
switch (mips_fpr_return_fields (valtype, fields)) switch (mips_fpr_return_fields (valtype, fields))
{ {
case 1: case 1:
return gen_rtx_REG (mode, FP_RETURN); return mips_return_fpr_single (mode,
TYPE_MODE (TREE_TYPE (fields[0])));
case 2: case 2:
return mips_return_fpr_pair (mode, return mips_return_fpr_pair (mode,
@ -5536,6 +5562,7 @@ mips_expand_call (rtx result, rtx addr, rtx args_size, rtx aux, bool sibcall_p)
: gen_call_internal (addr, args_size)); : gen_call_internal (addr, args_size));
else if (GET_CODE (result) == PARALLEL && XVECLEN (result, 0) == 2) else if (GET_CODE (result) == PARALLEL && XVECLEN (result, 0) == 2)
{ {
/* Handle return values created by mips_return_fpr_pair. */
rtx reg1, reg2; rtx reg1, reg2;
reg1 = XEXP (XVECEXP (result, 0, 0), 0); reg1 = XEXP (XVECEXP (result, 0, 0), 0);
@ -5546,9 +5573,14 @@ mips_expand_call (rtx result, rtx addr, rtx args_size, rtx aux, bool sibcall_p)
: gen_call_value_multiple_internal (reg1, addr, args_size, reg2)); : gen_call_value_multiple_internal (reg1, addr, args_size, reg2));
} }
else else
pattern = (sibcall_p {
? gen_sibcall_value_internal (result, addr, args_size) /* Handle return values created by mips_return_fpr_single. */
: gen_call_value_internal (result, addr, args_size)); if (GET_CODE (result) == PARALLEL && XVECLEN (result, 0) == 1)
result = XEXP (XVECEXP (result, 0, 0), 0);
pattern = (sibcall_p
? gen_sibcall_value_internal (result, addr, args_size)
: gen_call_value_internal (result, addr, args_size));
}
insn = emit_call_insn (pattern); insn = emit_call_insn (pattern);