diff options
author | Tobias Burnus <tburnus@baylibre.com> | 2024-09-13 16:48:57 +0200 |
---|---|---|
committer | Tobias Burnus <tburnus@baylibre.com> | 2024-09-13 16:48:57 +0200 |
commit | 99988464fc86354f0359c0fd91eee444fb5bd8a2 (patch) | |
tree | 7077436e7a92d198838ca9006a40032a6b8229c3 /gcc/fortran | |
parent | 508ef585243d4674d06b0737bfe8769fc18f824f (diff) | |
download | gcc-99988464fc86354f0359c0fd91eee444fb5bd8a2.zip gcc-99988464fc86354f0359c0fd91eee444fb5bd8a2.tar.gz gcc-99988464fc86354f0359c0fd91eee444fb5bd8a2.tar.bz2 |
Fortran: Fixes to OpenMP 'interop' directive parsing support
Handle lists as argument to 'fr' and 'attr'; fix parsing corner cases.
Additionally, 'fr' values are now internally stored as integer, permitting
the diagnoses (warning) for values not defined in the OpenMP additional
definitions document.
PR fortran/116661
gcc/fortran/ChangeLog:
* gfortran.h (gfc_omp_namelist): Rename 'init' members for clarity.
* match.cc (gfc_free_omp_namelist): Handle renaming.
* dump-parse-tree.cc (show_omp_namelist): Update for new format
and features.
* openmp.cc (gfc_match_omp_prefer_type): Parse list to 'fr' and 'attr';
store 'fr' values as integer.
(gfc_match_omp_init): Rename variable names.
gcc/ChangeLog:
* omp-api.h (omp_get_fr_id_from_name, omp_get_name_from_fr_id): New
prototypes.
* omp-general.cc (omp_get_fr_id_from_name, omp_get_name_from_fr_id):
New.
include/ChangeLog:
* gomp-constants.h (GOMP_INTEROP_IFR_LAST,
GOMP_INTEROP_IFR_SEPARATOR, GOMP_INTEROP_IFR_NONE): New.
gcc/testsuite/ChangeLog:
* gfortran.dg/gomp/interop-1.f90: Extend, update dg-*.
* gfortran.dg/gomp/interop-2.f90: Update dg-error.
* gfortran.dg/gomp/interop-3.f90: Add dg-warning.
Diffstat (limited to 'gcc/fortran')
-rw-r--r-- | gcc/fortran/dump-parse-tree.cc | 84 | ||||
-rw-r--r-- | gcc/fortran/gfortran.h | 4 | ||||
-rw-r--r-- | gcc/fortran/match.cc | 10 | ||||
-rw-r--r-- | gcc/fortran/openmp.cc | 305 |
4 files changed, 249 insertions, 154 deletions
diff --git a/gcc/fortran/dump-parse-tree.cc b/gcc/fortran/dump-parse-tree.cc index 8fc6141..3547d7f 100644 --- a/gcc/fortran/dump-parse-tree.cc +++ b/gcc/fortran/dump-parse-tree.cc @@ -37,6 +37,8 @@ along with GCC; see the file COPYING3. If not see #include "constructor.h" #include "version.h" #include "parse.h" /* For gfc_ascii_statement. */ +#include "omp-api.h" /* For omp_get_name_from_fr_id. */ +#include "gomp-constants.h" /* For GOMP_INTEROP_IFR_SEPARATOR. */ /* Keep track of indentation for symbol tree dumps. */ static int show_level = 0; @@ -1537,35 +1539,69 @@ show_omp_namelist (int list_type, gfc_omp_namelist *n) } else if (list_type == OMP_LIST_INIT) { - int i = 0; if (n->u.init.target) fputs ("target,", dumpfile); if (n->u.init.targetsync) fputs ("targetsync,", dumpfile); - char *prefer_type = n->u.init.str; - if (n->u.init.len) - fputs ("prefer_type(", dumpfile); - if (n->u.init.len) - while (*prefer_type) - { - fputc ('{', dumpfile); - if (n->u2.interop_int && n->u2.interop_int[i] != 0) - fprintf (dumpfile, "fr(%d),", n->u2.interop_int[i]); - else if (prefer_type[0] != ' ' || prefer_type[1] != '\0') - fprintf (dumpfile, "fr(\"%s\"),", prefer_type); - prefer_type += 1 + strlen (prefer_type); - - while (*prefer_type) - { - fprintf (dumpfile, "attr(\"%s\"),", prefer_type); - prefer_type += 1 + strlen (prefer_type); - } - fputc ('}', dumpfile); - ++prefer_type; - ++i; + if (n->u2.init_interop_fr) + { + char *attr_str = n->u.init.attr; + int idx = 0; + int fr_id; + fputs ("prefer_type(", dumpfile); + do + { + fr_id = n->u2.init_interop_fr[idx]; + fputc ('{', dumpfile); + if (fr_id != GOMP_INTEROP_IFR_NONE) + { + fputs ("fr(", dumpfile); + do + { + const char *fr_str = omp_get_name_from_fr_id (fr_id); + if (fr_str) + fprintf (dumpfile, "\"%s\"", fr_str); + else + fprintf (dumpfile, "%d", fr_id); + fr_id = n->u2.init_interop_fr[++idx]; + if (fr_id != GOMP_INTEROP_IFR_SEPARATOR) + fputc (',', dumpfile); + } + while (fr_id != GOMP_INTEROP_IFR_SEPARATOR); + fputc (')', dumpfile); + if (attr_str && (attr_str[0] != ' ' || attr_str[1] != '\0')) + fputc (',', dumpfile); + } + else + fr_id = n->u2.init_interop_fr[++idx]; + if (attr_str && attr_str[0] == ' ' && attr_str[1] == '\0') + attr_str += 2; + else if (attr_str) + { + fputs ("attr(\"", dumpfile); + do + { + fputs ((char *) attr_str, dumpfile); + fputc ('"', dumpfile); + attr_str += strlen (attr_str) + 1; + if (attr_str[0] == '\0') + break; + fputs (",\"", dumpfile); + } + while (true); + fputc (')', dumpfile); + } + fputc ('}', dumpfile); + fr_id = n->u2.init_interop_fr[++idx]; + if (fr_id == GOMP_INTEROP_IFR_SEPARATOR) + break; + fputc (',', dumpfile); + if (attr_str) + ++attr_str; + } + while (true); + fputc (')', dumpfile); } - if (n->u.init.len) - fputc (')', dumpfile); fputc (':', dumpfile); } fprintf (dumpfile, "%s", n->sym ? n->sym->name : "omp_all_memory"); diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 797d4ed..37c2869 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -1389,7 +1389,7 @@ typedef struct gfc_omp_namelist bool present_modifier; struct { - char *str; + char *attr; int len; bool target; bool targetsync; @@ -1402,7 +1402,7 @@ typedef struct gfc_omp_namelist gfc_expr *allocator; struct gfc_symbol *traits_sym; struct gfc_omp_namelist *duplicate_of; - int *interop_int; + char *init_interop_fr; } u2; struct gfc_omp_namelist *next; locus where; diff --git a/gcc/fortran/match.cc b/gcc/fortran/match.cc index f3767c9..0cd78a5 100644 --- a/gcc/fortran/match.cc +++ b/gcc/fortran/match.cc @@ -5551,7 +5551,7 @@ gfc_free_omp_namelist (gfc_omp_namelist *name, bool free_ns, { gfc_omp_namelist *n; gfc_expr *last_allocator = NULL; - char *last_init_str = NULL; + char *last_init_attr = NULL; for (; name; name = n) { @@ -5575,11 +5575,11 @@ gfc_free_omp_namelist (gfc_omp_namelist *name, bool free_ns, { } /* name->u2.traits_sym: shall not call gfc_free_symbol here. */ else if (free_init) { - if (name->u.init.str != last_init_str) + if (name->u.init.attr != last_init_attr) { - last_init_str = name->u.init.str; - free (name->u.init.str); - free (name->u2.interop_int); + last_init_attr = name->u.init.attr; + free (name->u.init.attr); + free (name->u2.init_interop_fr); } } else if (name->u2.udr) diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc index 1145e2f..050409e 100644 --- a/gcc/fortran/openmp.cc +++ b/gcc/fortran/openmp.cc @@ -1827,16 +1827,31 @@ error: where 'fr' takes an integer named constant or a string literal and 'attr takes a string literal, starting with 'ompx_') -Document string + int format -*/ + For the foreign runtime identifiers, string values are converted to + their integer value; unknown string or integer values are set to 0. + + For the simple syntax, pref_int_array contains alternatingly the + fr_id integer value and GOMP_INTEROP_IFR_SEPARATOR followed by a + GOMP_INTEROP_IFR_SEPARATOR as last item. + For the complex syntax, it contains the values associated with a + 'fr(...)' followed by GOMP_INTEROP_IFR_SEPARATOR. If there is no + 'fr' in a curly-brace block, it is GOMP_INTEROP_IFR_NONE followed + by GOMP_INTEROP_IFR_SEPARATOR. An additional GOMP_INTEROP_IFR_SEPARATOR + at the end terminates the array. + + For attributes, if the simply syntax is used, it is NULL - likewise if no + 'attr' appears. For the complex syntax it is: For reach curly-brace block, + it is \0\0 is no attr appears and otherwise a concatenation (including + the \0) of all 'attr' strings followed by a tailing '\0'. At the end, + another '\0' follows. */ static match -gfc_match_omp_prefer_type (char **pref_str, int *pref_str_len, int **pref_int_array) +gfc_match_omp_prefer_type (char **fr_int_array, char **attr_str, int *attr_str_len) { gfc_expr *e; - size_t cnt = 0; - std::vector<int> int_list; - std::string pref_string; + int cnt_brace_grp = 0; + std::vector<char> int_list; + std::string attr_string; /* New syntax. */ if (gfc_peek_ascii_char () == '{') do @@ -1846,8 +1861,8 @@ gfc_match_omp_prefer_type (char **pref_str, int *pref_str_len, int **pref_int_ar gfc_error ("Expected %<{%> at %C"); return MATCH_ERROR; } - std::string attr; bool fr_found = false; + bool attr_found = false; do { if (gfc_match ("fr ( ") == MATCH_YES) @@ -1859,99 +1874,129 @@ gfc_match_omp_prefer_type (char **pref_str, int *pref_str_len, int **pref_int_ar return MATCH_ERROR; } fr_found = true; - gfc_symbol *sym = NULL; - e = NULL; - locus loc = gfc_current_locus; - if (gfc_match_symbol (&sym, 0) != MATCH_YES - || gfc_match (" _") == MATCH_YES) + do { - gfc_current_locus = loc; - if (gfc_match_expr (&e) == MATCH_ERROR) + if (gfc_match_expr (&e) != MATCH_YES) return MATCH_ERROR; - } - if ((!sym && !e) - || (e && (!gfc_resolve_expr (e) - || e->expr_type != EXPR_CONSTANT - || e->ts.type != BT_CHARACTER - || e->ts.kind != gfc_default_character_kind - || e->value.character.length == 0)) - || (sym && (sym->attr.flavor != FL_PARAMETER - || sym->ts.type != BT_INTEGER - || !mpz_fits_sint_p (sym->value->value.integer) - || sym->attr.dimension))) - { - gfc_error ("Expected constant integer identifier or " - "non-empty default-kind character literal at %L", - &loc); - gfc_free_expr (e); + if (e->expr_type != EXPR_CONSTANT + || e->ref != NULL + || !gfc_resolve_expr (e) + || (e->ts.type != BT_INTEGER + && e->ts.type != BT_CHARACTER) + || (e->ts.type == BT_INTEGER + && (!e->symtree + || e->symtree->n.sym->attr.flavor != FL_PARAMETER + || !mpz_fits_sint_p (e->value.integer))) + || (e->ts.type == BT_CHARACTER + && (e->ts.kind != gfc_default_character_kind + || e->value.character.length == 0))) + { + gfc_error ("Expected scalar integer parameter or " + "non-empty default-kind character literal " + "at %L", &e->where); + gfc_free_expr (e); + return MATCH_ERROR; + } + gfc_gobble_whitespace (); + int val; + if (e->ts.type == BT_INTEGER) + { + val = mpz_get_si (e->value.integer); + if (val < 1 || val > GOMP_INTEROP_IFR_LAST) + { + gfc_warning (OPT_Wopenmp, + "Unknown foreign runtime identifier " + "%qd at %L", val, &e->where); + val = 0; + } + } + else + { + char *str = XALLOCAVEC (char, + e->value.character.length+1); + for (int i = 0; i < e->value.character.length + 1; i++) + str[i] = e->value.character.string[i]; + if (memchr (str, '\0', e->value.character.length) != 0) + { + gfc_error ("Unexpected null character in character " + "literal at %L", &e->where); + return MATCH_ERROR; + } + val = omp_get_fr_id_from_name (str); + if (val == 0) + gfc_warning (OPT_Wopenmp, + "Unknown foreign runtime identifier %qs " + "at %L", str, &e->where); + } + int_list.push_back (val); + if (gfc_match (", ") == MATCH_YES) + continue; + if (gfc_match (") ") == MATCH_YES) + break; + gfc_error ("Expected %<,%> or %<)%> at %C"); return MATCH_ERROR; } - if (sym) - { - for (size_t i = int_list.size(); i < cnt; ++i) - int_list.push_back (0); - int_list.push_back (mpz_get_si (sym->value->value.integer)); - pref_string += ' '; - pref_string += '\0'; - } - else - { - char *str = XALLOCAVEC (char, e->value.character.length+1); - for (int i = 0; i < e->value.character.length + 1; i++) - str[i] = e->value.character.string[i]; - if (memchr (str, '\0', e->value.character.length) != 0) - { - gfc_error ("Unexpected null character in character " - "literal at %L", &loc); - return MATCH_ERROR; - } - pref_string += str; - pref_string += '\0'; - } + while (true); } else if (gfc_match ("attr ( ") == MATCH_YES) { - locus loc = gfc_current_locus; - if (gfc_match_expr (&e) != MATCH_YES - || e->expr_type != EXPR_CONSTANT - || e->ts.type != BT_CHARACTER) - { - gfc_error ("Expected default-kind character literal at %L", - &loc); - gfc_free_expr (e); - return MATCH_ERROR; - } - char *str = XALLOCAVEC (char, e->value.character.length+1); - for (int i = 0; i < e->value.character.length + 1; i++) - str[i] = e->value.character.string[i]; - if (!startswith (str, "ompx_")) - { - gfc_error ("Character literal at %L must start with " - "%<ompx_%>", &e->where); - gfc_free_expr (e); - return MATCH_ERROR; - } - if (memchr (str, '\0', e->value.character.length) != 0 - || memchr (str, ',', e->value.character.length) != 0) + attr_found = true; + if (attr_string.empty ()) + for (int i = 0; i < cnt_brace_grp; ++i) + { + /* Add dummy elements for previous curly-brace blocks. */ + attr_string += ' '; + attr_string += '\0'; + attr_string += '\0'; + } + do { - gfc_error ("Unexpected null or %<,%> character in " - "character literal at %L", &e->where); + if (gfc_match_expr (&e) != MATCH_YES) + return MATCH_ERROR; + if (e->expr_type != EXPR_CONSTANT + || e->rank != 0 + || e->ts.type != BT_CHARACTER + || e->ts.kind != gfc_default_character_kind) + { + gfc_error ("Expected default-kind character literal " + "at %L", &e->where); + gfc_free_expr (e); + return MATCH_ERROR; + } + gfc_gobble_whitespace (); + char *str = XALLOCAVEC (char, e->value.character.length+1); + for (int i = 0; i < e->value.character.length + 1; i++) + str[i] = e->value.character.string[i]; + if (!startswith (str, "ompx_")) + { + gfc_error ("Character literal at %L must start with " + "%<ompx_%>", &e->where); + gfc_free_expr (e); + return MATCH_ERROR; + } + if (memchr (str, '\0', e->value.character.length) != 0 + || memchr (str, ',', e->value.character.length) != 0) + { + gfc_error ("Unexpected null or %<,%> character in " + "character literal at %L", &e->where); + return MATCH_ERROR; + } + attr_string += str; + attr_string += '\0'; + if (gfc_match (", ") == MATCH_YES) + continue; + if (gfc_match (") ") == MATCH_YES) + break; + gfc_error ("Expected %<,%> or %<)%> at %C"); return MATCH_ERROR; } - attr += str; - attr += '\0'; + while (true); } else { gfc_error ("Expected %<fr(%> or %<attr(%> at %C"); return MATCH_ERROR; } - ++cnt; - if (gfc_match (") ") != MATCH_YES) - { - gfc_error ("Expected %<)%> at %C"); - return MATCH_ERROR; - } if (gfc_match (", ") == MATCH_YES) continue; if (gfc_match ("} ") == MATCH_YES) @@ -1960,13 +2005,20 @@ gfc_match_omp_prefer_type (char **pref_str, int *pref_str_len, int **pref_int_ar return MATCH_ERROR; } while (true); + ++cnt_brace_grp; if (!fr_found) + int_list.push_back (GOMP_INTEROP_IFR_NONE); + int_list.push_back (GOMP_INTEROP_IFR_SEPARATOR); + if (!attr_string.empty ()) { - pref_string += ' '; - pref_string += '\0'; + if (!attr_found) + { + /* Dummy entry. */ + attr_string += ' '; + attr_string += '\0'; + } + attr_string += '\0'; } - pref_string += attr; - pref_string += '\0'; if (gfc_match (", ") == MATCH_YES) continue; @@ -1982,6 +2034,7 @@ gfc_match_omp_prefer_type (char **pref_str, int *pref_str_len, int **pref_int_ar if (gfc_match_expr (&e) != MATCH_YES) return MATCH_ERROR; if (!gfc_resolve_expr (e) + || e->rank != 0 || e->expr_type != EXPR_CONSTANT || (e->ts.type != BT_INTEGER && e->ts.type != BT_CHARACTER) || (e->ts.type == BT_INTEGER @@ -1990,17 +2043,23 @@ gfc_match_omp_prefer_type (char **pref_str, int *pref_str_len, int **pref_int_ar && (e->ts.kind != gfc_default_character_kind || e->value.character.length == 0))) { - gfc_error ("Expected constant integer expression or non-empty " - "default-kind character literal at %L", &e->where); + gfc_error ("Expected constant scalar integer expression or " + "non-empty default-kind character literal at %L", &e->where); gfc_free_expr (e); return MATCH_ERROR; } + gfc_gobble_whitespace (); + int val; if (e->ts.type == BT_INTEGER) { - for (size_t i = int_list.size(); i < cnt; ++i) - int_list.push_back (0); - int_list.push_back (mpz_get_si (e->value.integer)); - pref_string += ' '; + val = mpz_get_si (e->value.integer); + if (val < 1 || val > GOMP_INTEROP_IFR_LAST) + { + gfc_warning (OPT_Wopenmp, + "Unknown foreign runtime identifier %qd at %L", + val, &e->where); + val = 0; + } } else { @@ -2009,15 +2068,18 @@ gfc_match_omp_prefer_type (char **pref_str, int *pref_str_len, int **pref_int_ar str[i] = e->value.character.string[i]; if (memchr (str, '\0', e->value.character.length) != 0) { - gfc_error ("Unexpected null character in character literal " - "at %L", &e->where); + gfc_error ("Unexpected null character in character " + "literal at %L", &e->where); return MATCH_ERROR; } - pref_string += str; + val = omp_get_fr_id_from_name (str); + if (val == 0) + gfc_warning (OPT_Wopenmp, + "Unknown foreign runtime identifier %qs at %L", + str, &e->where); } - pref_string += '\0'; - pref_string += '\0'; - ++cnt; + int_list.push_back (val); + int_list.push_back (GOMP_INTEROP_IFR_SEPARATOR); gfc_free_expr (e); if (gfc_match (", ") == MATCH_YES) continue; @@ -2027,19 +2089,16 @@ gfc_match_omp_prefer_type (char **pref_str, int *pref_str_len, int **pref_int_ar return MATCH_ERROR; } while (true); - if (!int_list.empty()) - for (size_t i = int_list.size(); i < cnt; ++i) - int_list.push_back (0); - - pref_string += '\0'; + int_list.push_back (GOMP_INTEROP_IFR_SEPARATOR); + *fr_int_array = XNEWVEC (char, int_list.size ()); + memcpy (*fr_int_array, int_list.data (), sizeof (char) * int_list.size ()); - *pref_str_len = pref_string.length(); - *pref_str = XNEWVEC (char, pref_string.length ()); - memcpy (*pref_str, pref_string.data (), pref_string.length ()); - if (!int_list.empty ()) + if (!attr_string.empty ()) { - *pref_int_array = XNEWVEC (int, cnt); - memcpy (*pref_int_array, int_list.data (), sizeof (int) * cnt); + attr_string += '\0'; + *attr_str_len = attr_string.length(); + *attr_str = XNEWVEC (char, attr_string.length ()); + memcpy (*attr_str, attr_string.data (), attr_string.length ()); } return MATCH_YES; } @@ -2052,21 +2111,21 @@ static match gfc_match_omp_init (gfc_omp_namelist **list) { bool target = false, targetsync = false; - char *pref_str = NULL; - int pref_str_len = 0; - int *pref_int_array = NULL; + char *fr_int_array = NULL; + char *attr_str = NULL; + int attr_str_len = 0; match m; locus old_loc = gfc_current_locus; do { if (gfc_match ("prefer_type ( ") == MATCH_YES) { - if (pref_str) + if (fr_int_array) { gfc_error ("Duplicate %<prefer_type%> modifier at %C"); return MATCH_ERROR; } - m = gfc_match_omp_prefer_type (&pref_str, &pref_str_len, - &pref_int_array); + m = gfc_match_omp_prefer_type (&fr_int_array, &attr_str, + &attr_str_len); if (m != MATCH_YES) return m; if (gfc_match (", ") == MATCH_YES) @@ -2084,7 +2143,7 @@ gfc_match_omp_init (gfc_omp_namelist **list) if (gfc_match (": ") == MATCH_YES) break; gfc_char_t c = gfc_peek_char (); - if (!pref_str + if (!fr_int_array && (c == ')' || (gfc_current_form != FORM_FREE && (c == '_' || ISALPHA (c))))) @@ -2103,7 +2162,7 @@ gfc_match_omp_init (gfc_omp_namelist **list) if (gfc_match (": ") == MATCH_YES) break; gfc_char_t c = gfc_peek_char (); - if (!pref_str + if (!fr_int_array && (c == ')' || (gfc_current_form != FORM_FREE && (c == '_' || ISALPHA (c))))) @@ -2114,7 +2173,7 @@ gfc_match_omp_init (gfc_omp_namelist **list) gfc_error ("Expected %<,%> or %<:%> at %C"); return MATCH_ERROR; } - if (pref_str) + if (fr_int_array) { gfc_error ("Expected %<target%> or %<targetsync%> at %C"); return MATCH_ERROR; @@ -2131,9 +2190,9 @@ gfc_match_omp_init (gfc_omp_namelist **list) { n->u.init.target = target; n->u.init.targetsync = targetsync; - n->u.init.str = pref_str; - n->u.init.len = pref_str_len; - n->u2.interop_int = pref_int_array; + n->u.init.attr = attr_str; + n->u.init.len = attr_str_len; + n->u2.init_interop_fr = fr_int_array; } return MATCH_YES; } |