/* 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,
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,
{
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.
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;
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,
*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)
{
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
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. */
/* 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));
}