aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/s390/s390.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 9807e64..4408d4c 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -452,6 +452,97 @@ struct GTY(()) machine_function
#define PREDICT_DISTANCE (TARGET_Z10 ? 384 : 2048)
+/* Indicate which ABI has been used for passing vector args.
+ 0 - no vector type arguments have been passed where the ABI is relevant
+ 1 - the old ABI has been used
+ 2 - a vector type argument has been passed either in a vector register
+ or on the stack by value */
+static int s390_vector_abi = 0;
+
+/* Set the vector ABI marker if TYPE is subject to the vector ABI
+ switch. The vector ABI affects only vector data types. There are
+ two aspects of the vector ABI relevant here:
+
+ 1. vectors >= 16 bytes have an alignment of 8 bytes with the new
+ ABI and natural alignment with the old.
+
+ 2. vector <= 16 bytes are passed in VRs or by value on the stack
+ with the new ABI but by reference on the stack with the old.
+
+ If ARG_P is true TYPE is used for a function argument or return
+ value. The ABI marker then is set for all vector data types. If
+ ARG_P is false only type 1 vectors are being checked. */
+
+static void
+s390_check_type_for_vector_abi (const_tree type, bool arg_p, bool in_struct_p)
+{
+ static hash_set<const_tree> visited_types_hash;
+
+ if (s390_vector_abi)
+ return;
+
+ if (type == NULL_TREE || TREE_CODE (type) == ERROR_MARK)
+ return;
+
+ if (visited_types_hash.contains (type))
+ return;
+
+ visited_types_hash.add (type);
+
+ if (VECTOR_TYPE_P (type))
+ {
+ int type_size = int_size_in_bytes (type);
+
+ /* Outside arguments only the alignment is changing and this
+ only happens for vector types >= 16 bytes. */
+ if (!arg_p && type_size < 16)
+ return;
+
+ /* In arguments vector types > 16 are passed as before (GCC
+ never enforced the bigger alignment for arguments which was
+ required by the old vector ABI). However, it might still be
+ ABI relevant due to the changed alignment if it is a struct
+ member. */
+ if (arg_p && type_size > 16 && !in_struct_p)
+ return;
+
+ s390_vector_abi = TARGET_VX_ABI ? 2 : 1;
+ }
+ else if (POINTER_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)
+ {
+ /* ARRAY_TYPE: Since with neither of the ABIs we have more than
+ natural alignment there will never be ABI dependent padding
+ in an array type. That's why we do not set in_struct_p to
+ true here. */
+ s390_check_type_for_vector_abi (TREE_TYPE (type), arg_p, in_struct_p);
+ }
+ else if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
+ {
+ tree arg_chain;
+
+ /* Check the return type. */
+ s390_check_type_for_vector_abi (TREE_TYPE (type), true, false);
+
+ for (arg_chain = TYPE_ARG_TYPES (type);
+ arg_chain;
+ arg_chain = TREE_CHAIN (arg_chain))
+ s390_check_type_for_vector_abi (TREE_VALUE (arg_chain), true, false);
+ }
+ else if (RECORD_OR_UNION_TYPE_P (type))
+ {
+ tree field;
+
+ for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+ {
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+
+ s390_check_type_for_vector_abi (TREE_TYPE (field), arg_p, true);
+ }
+ }
+}
+
+
/* System z builtins. */
#include "s390-builtins.h"
@@ -10889,6 +10980,8 @@ s390_function_arg (cumulative_args_t cum_v, machine_mode mode,
{
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
+ if (!named)
+ s390_check_type_for_vector_abi (type, true, false);
if (s390_function_arg_vector (mode, type))
{
@@ -11280,6 +11373,8 @@ s390_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
size = int_size_in_bytes (type);
+ s390_check_type_for_vector_abi (type, true, false);
+
if (pass_by_reference (NULL, TYPE_MODE (type), type, false))
{
if (TARGET_DEBUG_ARG)
@@ -13642,6 +13737,29 @@ s390_vector_alignment (const_tree type)
return MIN (64, tree_to_shwi (TYPE_SIZE (type)));
}
+/* Implement TARGET_ASM_FILE_END. */
+static void
+s390_asm_file_end (void)
+{
+#ifdef HAVE_AS_GNU_ATTRIBUTE
+ varpool_node *vnode;
+ cgraph_node *cnode;
+
+ FOR_EACH_VARIABLE (vnode)
+ if (TREE_PUBLIC (vnode->decl))
+ s390_check_type_for_vector_abi (TREE_TYPE (vnode->decl), false, false);
+
+ FOR_EACH_FUNCTION (cnode)
+ if (TREE_PUBLIC (cnode->decl))
+ s390_check_type_for_vector_abi (TREE_TYPE (cnode->decl), false, false);
+
+
+ if (s390_vector_abi != 0)
+ fprintf (asm_out_file, "\t.gnu_attribute 8, %d\n",
+ s390_vector_abi);
+#endif
+ file_end_indicate_exec_stack ();
+}
/* Return true if TYPE is a vector bool type. */
static inline bool
@@ -13918,6 +14036,9 @@ s390_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1, const_tree ty
#undef TARGET_INVALID_BINARY_OP
#define TARGET_INVALID_BINARY_OP s390_invalid_binary_op
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END s390_asm_file_end
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-s390.h"