diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2020-08-25 13:31:17 +0100 |
---|---|---|
committer | Richard Sandiford <richard.sandiford@arm.com> | 2020-08-25 13:31:17 +0100 |
commit | 9ded41a39c1bb29f356485a9ec3a573fb75ded12 (patch) | |
tree | 92e2c333a5be0ba32da131fc8cfc02e73c78eb5f /gcc/config/aarch64/aarch64-sve-builtins.cc | |
parent | dcb043351307001a85fc1e7d56669f5adc9628f7 (diff) | |
download | gcc-9ded41a39c1bb29f356485a9ec3a573fb75ded12.zip gcc-9ded41a39c1bb29f356485a9ec3a573fb75ded12.tar.gz gcc-9ded41a39c1bb29f356485a9ec3a573fb75ded12.tar.bz2 |
aarch64: Tweaks to the handling of fixed-length SVE types
This patch is really four things rolled into one, since separating
them seemed artificial:
- Update the mangling of the fixed-length SVE ACLE types to match
the upcoming spec. The idea is to mangle:
VLAT __attribute__((arm_sve_vector_bits(N)))
as an instance __SVE_VLS<VLAT, N> of the template:
__SVE_VLS<typename, unsigned>
- Give the fixed-length types their own TYPE_DECL. This is needed
to make the above mangling fix work, but should also be a minor
QoI improvement for error reporting. Unfortunately, the names are
quite verbose, e.g.:
svint8_t __attribute__((arm_sve_vector_bits(512)))
but anything shorter would be ad-hoc syntax and so might be more
confusing.
- Improve the error message reported when arm_sve_vector_bits is
applied to tuples, such as:
svint32x2_t __attribute__((arm_sve_vector_bits(N)))
Previously we would complain that the type isn't an SVE type;
now we complain that it isn't a vector type.
- Don't allow arm_sve_vector_bits(N) to be applied to existing
fixed-length SVE types.
gcc/
* config/aarch64/aarch64-sve-builtins.cc (add_sve_type_attribute):
Take the ACLE name of the type as a parameter and add it as fourth
argument to the "SVE type" attribute.
(register_builtin_types): Update call accordingly.
(register_tuple_type): Likewise. Construct the name of the type
earlier in order to do this.
(get_arm_sve_vector_bits_attributes): New function.
(handle_arm_sve_vector_bits_attribute): Report a more sensible
error message if the attribute is applied to an SVE tuple type.
Don't allow the attribute to be applied to an existing fixed-length
SVE type. Mangle the new type as __SVE_VLS<type, vector-bits>.
Add a dummy TYPE_DECL to the new type.
gcc/testsuite/
* g++.target/aarch64/sve/acle/general-c++/attributes_2.C: New test.
* g++.target/aarch64/sve/acle/general-c++/mangle_6.C: Likewise.
* g++.target/aarch64/sve/acle/general-c++/mangle_7.C: Likewise.
* g++.target/aarch64/sve/acle/general-c++/mangle_8.C: Likewise.
* g++.target/aarch64/sve/acle/general-c++/mangle_9.C: Likewise.
* g++.target/aarch64/sve/acle/general-c++/mangle_10.C: Likewise.
* gcc.target/aarch64/sve/acle/general/attributes_7.c: Check the
error messages reported when arm_sve_vector_bits is applied to
SVE tuple types or to existing fixed-length SVE types.
Diffstat (limited to 'gcc/config/aarch64/aarch64-sve-builtins.cc')
-rw-r--r-- | gcc/config/aarch64/aarch64-sve-builtins.cc | 130 |
1 files changed, 113 insertions, 17 deletions
diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc index 3150659..e753966 100644 --- a/gcc/config/aarch64/aarch64-sve-builtins.cc +++ b/gcc/config/aarch64/aarch64-sve-builtins.cc @@ -564,15 +564,16 @@ static bool reported_missing_registers_p; /* Record that TYPE is an ABI-defined SVE type that contains NUM_ZR SVE vectors and NUM_PR SVE predicates. MANGLED_NAME, if nonnull, is the ABI-defined - mangling of the type. */ + mangling of the type. ACLE_NAME is the <arm_sve.h> name of the type. */ static void add_sve_type_attribute (tree type, unsigned int num_zr, unsigned int num_pr, - const char *mangled_name) + const char *mangled_name, const char *acle_name) { tree mangled_name_tree = (mangled_name ? get_identifier (mangled_name) : NULL_TREE); - tree value = tree_cons (NULL_TREE, mangled_name_tree, NULL_TREE); + tree value = tree_cons (NULL_TREE, get_identifier (acle_name), NULL_TREE); + value = tree_cons (NULL_TREE, mangled_name_tree, value); value = tree_cons (NULL_TREE, size_int (num_pr), value); value = tree_cons (NULL_TREE, size_int (num_zr), value); TYPE_ATTRIBUTES (type) = tree_cons (get_identifier ("SVE type"), value, @@ -3363,7 +3364,8 @@ register_builtin_types () TYPE_ARTIFICIAL (vectype) = 1; TYPE_INDIVISIBLE_P (vectype) = 1; add_sve_type_attribute (vectype, num_zr, num_pr, - vector_types[i].mangled_name); + vector_types[i].mangled_name, + vector_types[i].acle_name); make_type_sizeless (vectype); abi_vector_types[i] = vectype; lang_hooks.types.register_builtin_type (vectype, @@ -3409,6 +3411,13 @@ register_tuple_type (unsigned int num_vectors, vector_type_index type) { tree tuple_type = lang_hooks.types.make_type (RECORD_TYPE); + /* Work out the structure name. */ + char buffer[sizeof ("svbfloat16x4_t")]; + const char *vector_type_name = vector_types[type].acle_name; + snprintf (buffer, sizeof (buffer), "%.*sx%d_t", + (int) strlen (vector_type_name) - 2, vector_type_name, + num_vectors); + /* The contents of the type are opaque, so we can define them in any way that maps to the correct ABI type. @@ -3432,20 +3441,13 @@ register_tuple_type (unsigned int num_vectors, vector_type_index type) get_identifier ("__val"), array_type); DECL_FIELD_CONTEXT (field) = tuple_type; TYPE_FIELDS (tuple_type) = field; - add_sve_type_attribute (tuple_type, num_vectors, 0, NULL); + add_sve_type_attribute (tuple_type, num_vectors, 0, NULL, buffer); make_type_sizeless (tuple_type); layout_type (tuple_type); gcc_assert (VECTOR_MODE_P (TYPE_MODE (tuple_type)) && TYPE_MODE_RAW (tuple_type) == TYPE_MODE (tuple_type) && TYPE_ALIGN (tuple_type) == 128); - /* Work out the structure name. */ - char buffer[sizeof ("svbfloat16x4_t")]; - const char *vector_type_name = vector_types[type].acle_name; - snprintf (buffer, sizeof (buffer), "%.*sx%d_t", - (int) strlen (vector_type_name) - 2, vector_type_name, - num_vectors); - tree decl = build_decl (input_location, TYPE_DECL, get_identifier (buffer), tuple_type); TYPE_NAME (tuple_type) = decl; @@ -3646,6 +3648,29 @@ builtin_type_p (const_tree type, unsigned int *num_zr, unsigned int *num_pr) return false; } +/* ATTRS is the attribute list for a sizeless SVE type. Return the + attributes of the associated fixed-length SVE type, taking the + "SVE type" attributes from NEW_SVE_TYPE_ARGS. */ +static tree +get_arm_sve_vector_bits_attributes (tree old_attrs, tree new_sve_type_args) +{ + tree new_attrs = NULL_TREE; + tree *ptr = &new_attrs; + for (tree attr = old_attrs; attr; attr = TREE_CHAIN (attr)) + { + tree name = get_attribute_name (attr); + if (is_attribute_p ("SVE sizeless type", name)) + continue; + + tree args = TREE_VALUE (attr); + if (is_attribute_p ("SVE type", name)) + args = new_sve_type_args; + *ptr = tree_cons (TREE_PURPOSE (attr), args, NULL_TREE); + ptr = &TREE_CHAIN (*ptr); + } + return new_attrs; +} + /* An attribute callback for the "arm_sve_vector_bits" attribute. */ tree handle_arm_sve_vector_bits_attribute (tree *node, tree, tree args, int, @@ -3654,12 +3679,27 @@ handle_arm_sve_vector_bits_attribute (tree *node, tree, tree args, int, *no_add_attrs = true; tree type = *node; - if (!VECTOR_TYPE_P (type) || !builtin_type_p (type)) + tree attr = lookup_sve_type_attribute (type); + if (!attr) { error ("%qs applied to non-SVE type %qT", "arm_sve_vector_bits", type); return NULL_TREE; } + if (!VECTOR_TYPE_P (type)) + { + error ("%qs applied to non-vector type %qT", + "arm_sve_vector_bits", type); + return NULL_TREE; + } + + if (!sizeless_type_p (type)) + { + error ("%qs applied to type %qT, which already has a size", + "arm_sve_vector_bits", type); + return NULL_TREE; + } + tree size = TREE_VALUE (args); if (TREE_CODE (size) != INTEGER_CST) { @@ -3675,6 +3715,23 @@ handle_arm_sve_vector_bits_attribute (tree *node, tree, tree args, int, return NULL_TREE; } + /* Construct a new list of "SVE type" attribute arguments. */ + tree new_sve_type_args = copy_list (TREE_VALUE (attr)); + + /* Mangle the type as an instance of the imaginary template: + + __SVE_VLS<typename, unsigned> + + where the first parameter is the SVE type and where the second + parameter is the SVE vector length in bits. */ + tree mangled_name_node = chain_index (2, new_sve_type_args); + const char *old_mangled_name + = IDENTIFIER_POINTER (TREE_VALUE (mangled_name_node)); + char *new_mangled_name + = xasprintf ("9__SVE_VLSI%sLj%dEE", old_mangled_name, (int) value); + TREE_VALUE (mangled_name_node) = get_identifier (new_mangled_name); + free (new_mangled_name); + /* FIXME: The type ought to be a distinct copy in all cases, but currently that makes the C frontend reject conversions between svbool_t and its fixed-length variants. Using a type variant @@ -3687,6 +3744,44 @@ handle_arm_sve_vector_bits_attribute (tree *node, tree, tree args, int, else new_type = build_distinct_type_copy (base_type); + /* Construct a TYPE_DECL for the new type. This serves two purposes: + + - It ensures we don't print the original TYPE_DECL in error messages. + Printing the original name would be confusing because there are + situations in which the distinction between the original type and + the new type matters. For example: + + __SVInt8_t __attribute__((arm_sve_vector_bits(512))) *a; + __SVInt8_t *b; + + a = b; + + is invalid in C++, but without this, we'd print both types in + the same way. + + - Having a separate TYPE_DECL is necessary to ensure that C++ + mangling works correctly. See mangle_builtin_type for details. + + The name of the decl is something like: + + svint8_t __attribute__((arm_sve_vector_bits(512))) + + This is a compromise. It would be more accurate to use something like: + + __SVInt8_t __attribute__((arm_sve_vector_bits(512))) + + but the <arm_sve.h> name is likely to be more meaningful. */ + tree acle_name_node = TREE_CHAIN (mangled_name_node); + const char *old_type_name = IDENTIFIER_POINTER (TREE_VALUE (acle_name_node)); + char *new_type_name + = xasprintf ("%s __attribute__((arm_sve_vector_bits(%d)))", + old_type_name, (int) value); + tree decl = build_decl (BUILTINS_LOCATION, TYPE_DECL, + get_identifier (new_type_name), new_type); + DECL_ARTIFICIAL (decl) = 1; + TYPE_NAME (new_type) = decl; + free (new_type_name); + /* Allow the GNU vector extensions to be applied to vectors. The extensions aren't yet defined for packed predicates, so continue to treat them as abstract entities for now. */ @@ -3696,16 +3791,17 @@ handle_arm_sve_vector_bits_attribute (tree *node, tree, tree args, int, /* The new type is a normal sized type; it doesn't have the same restrictions as sizeless types. */ TYPE_ATTRIBUTES (new_type) - = remove_attribute ("SVE sizeless type", - copy_list (TYPE_ATTRIBUTES (new_type))); + = get_arm_sve_vector_bits_attributes (TYPE_ATTRIBUTES (new_type), + new_sve_type_args); /* Apply the relevant attributes, qualifiers and alignment of TYPE, if they differ from the original (sizeless) BASE_TYPE. */ if (TYPE_ATTRIBUTES (base_type) != TYPE_ATTRIBUTES (type) || TYPE_QUALS (base_type) != TYPE_QUALS (type)) { - tree attrs = remove_attribute ("SVE sizeless type", - copy_list (TYPE_ATTRIBUTES (type))); + tree attrs + = get_arm_sve_vector_bits_attributes (TYPE_ATTRIBUTES (type), + new_sve_type_args); new_type = build_type_attribute_qual_variant (new_type, attrs, TYPE_QUALS (type)); } |