diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 74482ede3af..ed624bb35f5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2011-09-22 Richard Sandiford + + 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 * ipa-inline-analysis.c: Fix overly long lines. diff --git a/gcc/calls.c b/gcc/calls.c index 1413c8d9dd6..3fa70b571f4 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, -#ifdef STACK_PARMS_IN_REG_PARM_AREA - 1, -#else - argvec[count].reg != 0, -#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 + if (argvec[count].reg == 0 + || argvec[count].partial != 0 || reg_parm_stack_space > 0) - args_size.constant += argvec[count].locate.size.constant; + { + locate_and_pad_parm (mode, NULL_TREE, +#ifdef STACK_PARMS_IN_REG_PARM_AREA + 1, +#else + 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 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 b45f9392e2f..e730881f40b 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;