aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/gcc/config/rs6000/rs6000.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/gcc/config/rs6000/rs6000.c')
-rw-r--r--gcc-4.9/gcc/config/rs6000/rs6000.c111
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)