Some architectures may use ',' in the attribute string, but it is not
used as the separator for different targets. To avoid conflict, we
introduce a new macro TARGET_CLONES_ATTR_SEPARATOR to separate different
clones.
As an example, according to RISC-V C-API Specification [1], RISC-V allows
',' in the attribute string in the "arch=" option to specify one more
ISA extensions in the same target function, which conflict with the
default separator to separate different clones. This patch introduces
TARGET_CLONES_ATTR_SEPARATOR for RISC-V and choose '#' as the separator,
since '#' is not allowed in the target_clones option string.
[1] https://github.com/riscv-non-isa/riscv-c-api-doc/blob/
c6c5d6d9cf96b342293315a5dff3d25e96ef8191/src/c-api.adoc#__attribute__targetattr-string
Signed-off-by: Yangyu Chen <cyy@cyyself.name>
gcc/ChangeLog:
* defaults.h (TARGET_CLONES_ATTR_SEPARATOR): Define new macro.
* multiple_target.cc (get_attr_str): Use
TARGET_CLONES_ATTR_SEPARATOR to separate attributes.
(separate_attrs): Likewise.
(expand_target_clones): Likewise.
* attribs.cc (attr_strcmp): Likewise.
(sorted_attr_string): Likewise.
* tree.cc (get_target_clone_attr_len): Likewise.
* config/riscv/riscv.h (TARGET_CLONES_ATTR_SEPARATOR): Define
TARGET_CLONES_ATTR_SEPARATOR for RISC-V.
* doc/tm.texi: Document TARGET_CLONES_ATTR_SEPARATOR.
* doc/tm.texi.in: Likewise.
}
/* ARGLIST is the argument to target attribute. This function tokenizes
- the comma separated arguments, sorts them and returns a string which
- is a unique identifier for the comma separated arguments. It also
- replaces non-identifier characters "=,-" with "_". */
+ the TARGET_CLONES_ATTR_SEPARATOR separated arguments, sorts them and
+ returns a string which is a unique identifier for the
+ TARGET_CLONES_ATTR_SEPARATOR separated arguments. It also replaces
+ non-identifier characters "=,-" with "_". */
char *
sorted_attr_string (tree arglist)
char *attr = NULL;
unsigned int argnum = 1;
unsigned int i;
+ static const char separator_str[] = { TARGET_CLONES_ATTR_SEPARATOR, 0 };
for (arg = arglist; arg; arg = TREE_CHAIN (arg))
{
if (arg != arglist)
argnum++;
for (i = 0; i < strlen (str); i++)
- if (str[i] == ',')
+ if (str[i] == TARGET_CLONES_ATTR_SEPARATOR)
argnum++;
}
const char *str = TREE_STRING_POINTER (TREE_VALUE (arg));
size_t len = strlen (str);
memcpy (attr_str + str_len_sum, str, len);
- attr_str[str_len_sum + len] = TREE_CHAIN (arg) ? ',' : '\0';
+ attr_str[str_len_sum + len]
+ = TREE_CHAIN (arg) ? TARGET_CLONES_ATTR_SEPARATOR : '\0';
str_len_sum += len + 1;
}
args = XNEWVEC (char *, argnum);
i = 0;
- attr = strtok (attr_str, ",");
+ attr = strtok (attr_str, separator_str);
while (attr != NULL)
{
args[i] = attr;
i++;
- attr = strtok (NULL, ",");
+ attr = strtok (NULL, separator_str);
}
qsort (args, argnum, sizeof (char *), attr_strcmp);
STACK_BOUNDARY / BITS_PER_UNIT) \
: (crtl->outgoing_args_size + STACK_POINTER_OFFSET))
+/* According to the RISC-V C API, the arch string may contains ','. To avoid
+ the conflict with the default separator, we choose '#' as the separator for
+ the target attribute. */
+#define TARGET_CLONES_ATTR_SEPARATOR '#'
+
#endif /* ! GCC_RISCV_H */
#define TARGET_HAS_FMV_TARGET_ATTRIBUTE 1
#endif
+/* Select a attribute separator for function multiversioning. */
+#ifndef TARGET_CLONES_ATTR_SEPARATOR
+#define TARGET_CLONES_ATTR_SEPARATOR ','
+#endif
/* Select a format to encode pointers in exception handling data. We
prefer those that result in fewer dynamic relocations. Assume no
@code{struct cl_target_option} structure.
@end deftypefn
+@defmac TARGET_CLONES_ATTR_SEPARATOR
+Define this char-typed macro to select a character that separates each
+target specific attributes from the @code{attribute(target_clones("..."))}
+attribute string. This macro should be carefully chosen to avoid conflicts
+with the target specific attributes. The default value is @code{','}.
+@end defmac
+
@deftypefn {Target Hook} void TARGET_OPTION_SAVE (struct cl_target_option *@var{ptr}, struct gcc_options *@var{opts}, struct gcc_options *@var{opts_set})
This hook is called to save any additional target-specific information
in the @code{struct cl_target_option} structure for function-specific
@hook TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P
+@defmac TARGET_CLONES_ATTR_SEPARATOR
+Define this char-typed macro to select a character that separates each
+target specific attributes from the @code{attribute(target_clones("..."))}
+attribute string. This macro should be carefully chosen to avoid conflicts
+with the target specific attributes. The default value is @code{','}.
+@end defmac
+
@hook TARGET_OPTION_SAVE
@hook TARGET_OPTION_RESTORE
}
}
-/* Create string with attributes separated by comma.
+/* Create string with attributes separated by TARGET_CLONES_ATTR_SEPARATOR.
Return number of attributes. */
static int
{
const char *str = TREE_STRING_POINTER (TREE_VALUE (arg));
size_t len = strlen (str);
- for (const char *p = strchr (str, ','); p; p = strchr (p + 1, ','))
+ for (const char *p = strchr (str, TARGET_CLONES_ATTR_SEPARATOR);
+ p;
+ p = strchr (p + 1, TARGET_CLONES_ATTR_SEPARATOR))
argnum++;
memcpy (attr_str + str_len_sum, str, len);
- attr_str[str_len_sum + len] = TREE_CHAIN (arg) ? ',' : '\0';
+ attr_str[str_len_sum + len]
+ = TREE_CHAIN (arg) ? TARGET_CLONES_ATTR_SEPARATOR : '\0';
str_len_sum += len + 1;
argnum++;
}
return argnum;
}
-/* Return number of attributes separated by comma and put them into ARGS.
+/* Return number of attributes separated by TARGET_CLONES_ATTR_SEPARATOR
+ and put them into ARGS.
If there is no DEFAULT attribute return -1.
If there is an empty string in attribute return -2.
If there are multiple DEFAULT attributes return -3.
{
int i = 0;
int default_count = 0;
+ static const char separator_str[] = { TARGET_CLONES_ATTR_SEPARATOR, 0 };
- for (char *attr = strtok (attr_str, ",");
- attr != NULL; attr = strtok (NULL, ","))
+ for (char *attr = strtok (attr_str, separator_str);
+ attr != NULL; attr = strtok (NULL, separator_str))
{
if (strcmp (attr, "default") == 0)
{
expand_target_clones (struct cgraph_node *node, bool definition)
{
int i;
- /* Parsing target attributes separated by comma. */
+ /* Parsing target attributes separated by TARGET_CLONES_ATTR_SEPARATOR. */
tree attr_target = lookup_attribute ("target_clones",
DECL_ATTRIBUTES (node->decl));
/* No targets specified. */
const char *str = TREE_STRING_POINTER (TREE_VALUE (arg));
size_t len = strlen (str);
str_len_sum += len + 1;
- for (const char *p = strchr (str, ','); p; p = strchr (p + 1, ','))
+ for (const char *p = strchr (str, TARGET_CLONES_ATTR_SEPARATOR);
+ p;
+ p = strchr (p + 1, TARGET_CLONES_ATTR_SEPARATOR))
argnum++;
argnum++;
}