aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Sandiford <rdsandiford@googlemail.com>2011-09-22 12:26:41 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2011-09-22 12:26:41 +0000
commit3576f984e8e8cc65385cffcba23f403632aa88c8 (patch)
treeea10f15658f10eca2def948025beed6db152833c
parent9e990d143674829b6583da2ab91030abbb8257dc (diff)
downloadgcc-3576f984e8e8cc65385cffcba23f403632aa88c8.zip
gcc-3576f984e8e8cc65385cffcba23f403632aa88c8.tar.gz
gcc-3576f984e8e8cc65385cffcba23f403632aa88c8.tar.bz2
re PR middle-end/50113 (soft-float MIPS64 compiler is miscompiling ggc-page.c)
gcc/ PR middle-end/50113 PR middle-end/50061 * calls.c (emit_library_call_value_1): Use BLOCK_REG_PADDING to get the locate.where_pad value for register-only arguments. * config/arm/arm.c (arm_pad_arg_upward): Remove HFmode handling. (arm_pad_reg_upward): Handle null types. From-SVN: r179085
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/calls.c31
-rw-r--r--gcc/config/arm/arm.c46
3 files changed, 53 insertions, 33 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 74482ed..ed624bb 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2011-09-22 Richard Sandiford <rdsandiford@googlemail.com>
+
+ PR middle-end/50113
+ PR middle-end/50061
+ * calls.c (emit_library_call_value_1): Use BLOCK_REG_PADDING to
+ get the locate.where_pad value for register-only arguments.
+ * config/arm/arm.c (arm_pad_arg_upward): Remove HFmode handling.
+ (arm_pad_reg_upward): Handle null types.
+
2011-09-22 Jan Hubicka <jh@suse.cz>
* ipa-inline-analysis.c: Fix overly long lines.
diff --git a/gcc/calls.c b/gcc/calls.c
index 1413c8d..3fa70b5 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -3577,20 +3577,29 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
argvec[count].partial
= targetm.calls.arg_partial_bytes (args_so_far, mode, NULL_TREE, 1);
- locate_and_pad_parm (mode, NULL_TREE,
+ if (argvec[count].reg == 0
+ || argvec[count].partial != 0
+ || reg_parm_stack_space > 0)
+ {
+ locate_and_pad_parm (mode, NULL_TREE,
#ifdef STACK_PARMS_IN_REG_PARM_AREA
- 1,
+ 1,
#else
- argvec[count].reg != 0,
+ argvec[count].reg != 0,
+#endif
+ argvec[count].partial,
+ NULL_TREE, &args_size, &argvec[count].locate);
+ args_size.constant += argvec[count].locate.size.constant;
+ gcc_assert (!argvec[count].locate.size.var);
+ }
+#ifdef BLOCK_REG_PADDING
+ else
+ /* The argument is passed entirely in registers. See at which
+ end it should be padded. */
+ argvec[count].locate.where_pad =
+ BLOCK_REG_PADDING (mode, NULL_TREE,
+ GET_MODE_SIZE (mode) <= UNITS_PER_WORD);
#endif
- argvec[count].partial,
- NULL_TREE, &args_size, &argvec[count].locate);
-
- gcc_assert (!argvec[count].locate.size.var);
-
- if (argvec[count].reg == 0 || argvec[count].partial != 0
- || reg_parm_stack_space > 0)
- args_size.constant += argvec[count].locate.size.constant;
targetm.calls.function_arg_advance (args_so_far, mode, (tree) 0, true);
}
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index b45f939..e730881 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -11573,7 +11573,7 @@ arm_must_pass_in_stack (enum machine_mode mode, const_tree type)
aggregate types are placed in the lowest memory address. */
bool
-arm_pad_arg_upward (enum machine_mode mode, const_tree type)
+arm_pad_arg_upward (enum machine_mode mode ATTRIBUTE_UNUSED, const_tree type)
{
if (!TARGET_AAPCS_BASED)
return DEFAULT_FUNCTION_ARG_PADDING(mode, type) == upward;
@@ -11581,36 +11581,38 @@ arm_pad_arg_upward (enum machine_mode mode, const_tree type)
if (type && BYTES_BIG_ENDIAN && INTEGRAL_TYPE_P (type))
return false;
- /* Half-float values are only passed to libcalls, not regular functions.
- They should be passed and returned as "short"s (see RTABI). To achieve
- that effect in big-endian mode, pad downwards so the value is passed in
- the least-significant end of the register. ??? This needs to be here
- rather than in arm_pad_reg_upward due to peculiarity in the handling of
- libcall arguments. */
- if (BYTES_BIG_ENDIAN && mode == HFmode)
- return false;
-
return true;
}
/* Similarly, for use by BLOCK_REG_PADDING (MODE, TYPE, FIRST).
- For non-AAPCS, return !BYTES_BIG_ENDIAN if the least significant
- byte of the register has useful data, and return the opposite if the
- most significant byte does.
- For AAPCS, small aggregates and small complex types are always padded
- upwards. */
+ Return !BYTES_BIG_ENDIAN if the least significant byte of the
+ register has useful data, and return the opposite if the most
+ significant byte does. */
bool
-arm_pad_reg_upward (enum machine_mode mode ATTRIBUTE_UNUSED,
+arm_pad_reg_upward (enum machine_mode mode,
tree type, int first ATTRIBUTE_UNUSED)
{
- if (TARGET_AAPCS_BASED
- && BYTES_BIG_ENDIAN
- && (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == COMPLEX_TYPE
- || FIXED_POINT_TYPE_P (type))
- && int_size_in_bytes (type) <= 4)
- return true;
+ if (TARGET_AAPCS_BASED && BYTES_BIG_ENDIAN)
+ {
+ /* For AAPCS, small aggregates, small fixed-point types,
+ and small complex types are always padded upwards. */
+ if (type)
+ {
+ if ((AGGREGATE_TYPE_P (type)
+ || TREE_CODE (type) == COMPLEX_TYPE
+ || FIXED_POINT_TYPE_P (type))
+ && int_size_in_bytes (type) <= 4)
+ return true;
+ }
+ else
+ {
+ if ((COMPLEX_MODE_P (mode) || ALL_FIXED_POINT_MODE_P (mode))
+ && GET_MODE_SIZE (mode) <= 4)
+ return true;
+ }
+ }
/* Otherwise, use default padding. */
return !BYTES_BIG_ENDIAN;