From: ZAMBAR
This patch implements the TARGET_CLONES attribute for Fortran functions,
using C-style comma-separated syntax for target specifications.
The implementation adds:
- Parsing support for TARGET_CLONES("target1", "target2", ...)
- Integration with existing multiple target infrastructure
- Proper memory management for target arguments
- Error handling for malformed syntax
Example usage:
!GCC$ ATTRIBUTES TARGET_CLONES("default", "avx", "avx512f") :: function_name
---
gcc/fortran/decl.cc | 116
gcc/fortran/f95-lang.cc | 34
gcc/fortran/gfortran.h | 5 ++
gcc/fortran/symbol.cc | 8 +++
gcc/multiple_target.cc | 9 +++-
5 files changed, 170 insertions(+), 2 deletions(-)
diff --git a/gcc/fortran/decl.cc b/gcc/fortran/decl.cc
index 69acd2da981..ed7c82dd8a3 100644
--- a/gcc/fortran/decl.cc
+++ b/gcc/fortran/decl.cc
@@ -11879,6 +11879,7 @@ const ext_attr_t ext_attr_list[] = {
{ "noinline", EXT_ATTR_NOINLINE, NULL },
{ "noreturn", EXT_ATTR_NORETURN, NULL },
{ "weak",EXT_ATTR_WEAK, NULL},
+ { "target_clones", EXT_ATTR_TARGET_CLONES, NULL },
{ NULL, EXT_ATTR_LAST, NULL}
};
@@ -11896,6 +11897,13 @@ const ext_attr_t ext_attr_list[] = {
As there is absolutely no risk of confusion, we should never return
MATCH_NO. */
+
+/* Structure to temporarily hold target_clones arguments during parsing */
+typedef struct {
+ char **args;
+ int count;
+} target_clones_args_t;
+
match
gfc_match_gcc_attributes (void)
{
@@ -11904,6 +11912,7 @@ gfc_match_gcc_attributes (void)
unsigned id;
gfc_symbol *sym;
match m;
+ target_clones_args_t target_clones_data = { NULL, 0 };
gfc_clear_attr (&attr);
for(;;)
@@ -11926,6 +11935,85 @@ gfc_match_gcc_attributes (void)
if (!gfc_add_ext_attribute (&attr, (ext_attr_id_t)id,
&gfc_current_locus))
return MATCH_ERROR;
+ /* Handle target_clones attribute with arguments */
+ if (id == EXT_ATTR_TARGET_CLONES)
+ {
+ /* Expect opening parenthesis for target_clones */
+ if (gfc_match_char ('(') != MATCH_YES)
+ {
+ gfc_error ("Expected '(' after TARGET_CLONES attribute at %C");
+ return MATCH_ERROR;
+ }
+
+ /* Parse comma-separated list of target specifications */
+ for (;;)
+ {
+ gfc_expr *expr = NULL;
+
+ /* Match quoted string argument */
+ if (gfc_match_literal_constant (&expr, 0) == MATCH_YES)
+ {
+ /* Verify it's a character constant */
+ if (expr->expr_type == EXPR_CONSTANT && expr->ts.type ==
BT_CHARACTER)
+ {
+ target_clones_data.count++;
+ target_clones_data.args = (char **) xrealloc
(target_clones_data.args,
+
target_clones_data.count * sizeof (char *));
+
+ /* Convert gfc_char_t* to char* */
+ int len = expr->value.character.length;
+ char *arg_str = (char *) xmalloc (len + 1);
+ for (int i = 0; i < len; i++)
+ arg_str[i] = (char) expr->value.character.string[i];
+ arg_str[len] = '\0';
+
+ target_clones_data.args[target_clones_data.count - 1] =
arg_str;
+ gfc_free_expr (expr);
+
+ /* Check for comma (more arguments) or closing
parenthesis */
+ gfc_gobble_whitespace ();
+ if (gfc_match_char (',') == MATCH_YES)
+ {
+ gfc_gobble_whitespace ();
+ continue;
+ }
+ else if (gfc_match_char (')') == MATCH_YES)
+ break;
+ else
+ {
+ gfc_error ("Expected ',' or ')' in TARGET_CLONES
argument list at %C");
+ goto target_clones_error;
+ }
+ }
+ else
+ {
+ gfc_free_expr (expr);
+ gfc_error ("TARGET_CLONES arguments must be character
constants at %C");
+ goto target_clones_error;
+ }
+ }
+ else
+ {
+ gfc_error ("Expected quoted string argument in TARGET_CLONES
at %C");
+