diff options
Diffstat (limited to 'gcc-4.9/gcc/config/rs6000/rs6000.c')
-rw-r--r-- | gcc-4.9/gcc/config/rs6000/rs6000.c | 111 |
1 files changed, 104 insertions, 7 deletions
diff --git a/gcc-4.9/gcc/config/rs6000/rs6000.c b/gcc-4.9/gcc/config/rs6000/rs6000.c index bf67e7298..d7cbc6cde 100644 --- a/gcc-4.9/gcc/config/rs6000/rs6000.c +++ b/gcc-4.9/gcc/config/rs6000/rs6000.c @@ -5871,6 +5871,34 @@ rs6000_data_alignment (tree type, unsigned int align, enum data_align how) return align; } +/* Previous GCC releases forced all vector types to have 16-byte alignment. */ + +bool +rs6000_special_adjust_field_align_p (tree field, unsigned int computed) +{ + if (TARGET_ALTIVEC && TREE_CODE (TREE_TYPE (field)) == VECTOR_TYPE) + { + if (computed != 128) + { + static bool warned; + if (!warned && warn_psabi) + { + warned = true; + inform (input_location, + "the layout of aggregates containing vectors with" + " %d-byte alignment will change in a future GCC release", + computed / BITS_PER_UNIT); + } + } + /* GCC 4.8/4.9 Note: To avoid any ABI change on a release branch, we + keep the special treatment of vector types, but warn if there will + be differences in future GCC releases. */ + return true; + } + + return false; +} + /* AIX increases natural record alignment to doubleword if the first field is an FP double while the FP fields remain word aligned. */ @@ -9180,14 +9208,51 @@ rs6000_function_arg_boundary (enum machine_mode mode, const_tree type) || (type && TREE_CODE (type) == VECTOR_TYPE && int_size_in_bytes (type) >= 16)) return 128; - else if (((TARGET_MACHO && rs6000_darwin64_abi) - || DEFAULT_ABI == ABI_ELFv2 - || (DEFAULT_ABI == ABI_AIX && !rs6000_compat_align_parm)) - && mode == BLKmode - && type && TYPE_ALIGN (type) > 64) + + /* Aggregate types that need > 8 byte alignment are quadword-aligned + in the parameter area in the ELFv2 ABI, and in the AIX ABI unless + -mcompat-align-parm is used. */ + if (((DEFAULT_ABI == ABI_AIX && !rs6000_compat_align_parm) + || DEFAULT_ABI == ABI_ELFv2) + && type && TYPE_ALIGN (type) > 64) + { + /* "Aggregate" means any AGGREGATE_TYPE except for single-element + or homogeneous float/vector aggregates here. We already handled + vector aggregates above, but still need to check for float here. */ + bool aggregate_p = (AGGREGATE_TYPE_P (type) + && !SCALAR_FLOAT_MODE_P (elt_mode)); + + /* We used to check for BLKmode instead of the above aggregate type + check. Warn when this results in any difference to the ABI. */ + if (aggregate_p != (mode == BLKmode)) + { + static bool warned; + if (!warned && warn_psabi) + { + warned = true; + inform (input_location, + "the ABI of passing aggregates with %d-byte alignment" + " will change in a future GCC release", + (int) TYPE_ALIGN (type) / BITS_PER_UNIT); + } + } + + /* GCC 4.8/4.9 Note: To avoid any ABI change on a release branch, we + keep using the BLKmode check, but warn if there will be differences + in future GCC releases. */ + if (mode == BLKmode) + return 128; + } + + /* Similar for the Darwin64 ABI. Note that for historical reasons we + implement the "aggregate type" check as a BLKmode check here; this + means certain aggregate types are in fact not aligned. */ + if (TARGET_MACHO && rs6000_darwin64_abi + && mode == BLKmode + && type && TYPE_ALIGN (type) > 64) return 128; - else - return PARM_BOUNDARY; + + return PARM_BOUNDARY; } /* The offset in words to the start of the parameter save area. */ @@ -10225,6 +10290,7 @@ rs6000_function_arg (cumulative_args_t cum_v, enum machine_mode mode, rtx r, off; int i, k = 0; unsigned long n_fpreg = (GET_MODE_SIZE (elt_mode) + 7) >> 3; + int fpr_words; /* Do we also need to pass this argument in the parameter save area? */ @@ -10253,6 +10319,37 @@ rs6000_function_arg (cumulative_args_t cum_v, enum machine_mode mode, rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, off); } + /* If there were not enough FPRs to hold the argument, the rest + usually goes into memory. However, if the current position + is still within the register parameter area, a portion may + actually have to go into GPRs. + + Note that it may happen that the portion of the argument + passed in the first "half" of the first GPR was already + passed in the last FPR as well. + + For unnamed arguments, we already set up GPRs to cover the + whole argument in rs6000_psave_function_arg, so there is + nothing further to do at this point. + + GCC 4.8/4.9 Note: This was implemented incorrectly in earlier + GCC releases. To avoid any ABI change on the release branch, + we retain that original implementation here, but warn if we + encounter a case where the ABI will change in the future. */ + fpr_words = (i * GET_MODE_SIZE (elt_mode)) / (TARGET_32BIT ? 4 : 8); + if (i < n_elts && align_words + fpr_words < GP_ARG_NUM_REG + && cum->nargs_prototype > 0) + { + static bool warned; + if (!warned && warn_psabi) + { + warned = true; + inform (input_location, + "the ABI of passing homogeneous float aggregates" + " will change in a future GCC release"); + } + } + return rs6000_finish_function_arg (mode, rvec, k); } else if (align_words < GP_ARG_NUM_REG) |