diff options
author | Richard Sandiford <rsandifo@nildram.co.uk> | 2007-11-12 20:05:46 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2007-11-12 20:05:46 +0000 |
commit | fd0d4c1fbba96c6ddfe7377557ab8b184551cf3a (patch) | |
tree | de116c6b422106648505aac5c6f0de56f8003ba6 /gcc | |
parent | 3aa64f2ccc63b2982910d9d59d0a5f7e99f640ab (diff) | |
download | gcc-fd0d4c1fbba96c6ddfe7377557ab8b184551cf3a.zip gcc-fd0d4c1fbba96c6ddfe7377557ab8b184551cf3a.tar.gz gcc-fd0d4c1fbba96c6ddfe7377557ab8b184551cf3a.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/config/mips/mips.c | 40 |
2 files changed, 45 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5b6c730..3c2875f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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> PR middle-end/34070 diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index e7eddf7..54e2d62 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -4451,6 +4451,31 @@ mips_return_mode_in_fpr_p (enum machine_mode mode) && 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. 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 @@ -4502,7 +4527,8 @@ mips_function_value (const_tree valtype, enum machine_mode mode) switch (mips_fpr_return_fields (valtype, fields)) { case 1: - return gen_rtx_REG (mode, FP_RETURN); + return mips_return_fpr_single (mode, + TYPE_MODE (TREE_TYPE (fields[0]))); case 2: 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)); else if (GET_CODE (result) == PARALLEL && XVECLEN (result, 0) == 2) { + /* Handle return values created by mips_return_fpr_pair. */ rtx reg1, reg2; 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)); } else - pattern = (sibcall_p - ? gen_sibcall_value_internal (result, addr, args_size) - : gen_call_value_internal (result, addr, args_size)); + { + /* Handle return values created by mips_return_fpr_single. */ + 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); |