File: | build/gcc/fortran/openmp.cc |
Warning: | line 2443, column 8 Value stored to 'm' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* OpenMP directive matching and resolving. |
2 | Copyright (C) 2005-2023 Free Software Foundation, Inc. |
3 | Contributed by Jakub Jelinek |
4 | |
5 | This file is part of GCC. |
6 | |
7 | GCC is free software; you can redistribute it and/or modify it under |
8 | the terms of the GNU General Public License as published by the Free |
9 | Software Foundation; either version 3, or (at your option) any later |
10 | version. |
11 | |
12 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or |
14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
15 | for more details. |
16 | |
17 | You should have received a copy of the GNU General Public License |
18 | along with GCC; see the file COPYING3. If not see |
19 | <http://www.gnu.org/licenses/>. */ |
20 | |
21 | #include "config.h" |
22 | #include "system.h" |
23 | #include "coretypes.h" |
24 | #include "gfortran.h" |
25 | #include "arith.h" |
26 | #include "match.h" |
27 | #include "parse.h" |
28 | #include "constructor.h" |
29 | #include "diagnostic.h" |
30 | #include "gomp-constants.h" |
31 | #include "target-memory.h" /* For gfc_encode_character. */ |
32 | #include "bitmap.h" |
33 | |
34 | |
35 | static gfc_statement omp_code_to_statement (gfc_code *); |
36 | |
37 | enum gfc_omp_directive_kind { |
38 | GFC_OMP_DIR_DECLARATIVE, |
39 | GFC_OMP_DIR_EXECUTABLE, |
40 | GFC_OMP_DIR_INFORMATIONAL, |
41 | GFC_OMP_DIR_META, |
42 | GFC_OMP_DIR_SUBSIDIARY, |
43 | GFC_OMP_DIR_UTILITY |
44 | }; |
45 | |
46 | struct gfc_omp_directive { |
47 | const char *name; |
48 | enum gfc_omp_directive_kind kind; |
49 | gfc_statement st; |
50 | }; |
51 | |
52 | /* Alphabetically sorted OpenMP clauses, except that longer strings are before |
53 | substrings; excludes combined/composite directives. See note for "ordered" |
54 | and "nothing". */ |
55 | |
56 | static const struct gfc_omp_directive gfc_omp_directives[] = { |
57 | /* {"allocate", GFC_OMP_DIR_DECLARATIVE, ST_OMP_ALLOCATE}, */ |
58 | /* {"allocators", GFC_OMP_DIR_EXECUTABLE, ST_OMP_ALLOCATORS}, */ |
59 | {"assumes", GFC_OMP_DIR_INFORMATIONAL, ST_OMP_ASSUMES}, |
60 | {"assume", GFC_OMP_DIR_INFORMATIONAL, ST_OMP_ASSUME}, |
61 | {"atomic", GFC_OMP_DIR_EXECUTABLE, ST_OMP_ATOMIC}, |
62 | {"barrier", GFC_OMP_DIR_EXECUTABLE, ST_OMP_BARRIER}, |
63 | {"cancellation point", GFC_OMP_DIR_EXECUTABLE, ST_OMP_CANCELLATION_POINT}, |
64 | {"cancel", GFC_OMP_DIR_EXECUTABLE, ST_OMP_CANCEL}, |
65 | {"critical", GFC_OMP_DIR_EXECUTABLE, ST_OMP_CRITICAL}, |
66 | /* {"declare mapper", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_MAPPER}, */ |
67 | {"declare reduction", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_REDUCTION}, |
68 | {"declare simd", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_SIMD}, |
69 | {"declare target", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_TARGET}, |
70 | {"declare variant", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_VARIANT}, |
71 | {"depobj", GFC_OMP_DIR_EXECUTABLE, ST_OMP_DEPOBJ}, |
72 | /* {"dispatch", GFC_OMP_DIR_EXECUTABLE, ST_OMP_DISPATCH}, */ |
73 | {"distribute", GFC_OMP_DIR_EXECUTABLE, ST_OMP_DISTRIBUTE}, |
74 | {"do", GFC_OMP_DIR_EXECUTABLE, ST_OMP_DO}, |
75 | /* "error" becomes GFC_OMP_DIR_EXECUTABLE with at(execution) */ |
76 | {"error", GFC_OMP_DIR_UTILITY, ST_OMP_ERROR}, |
77 | {"flush", GFC_OMP_DIR_EXECUTABLE, ST_OMP_FLUSH}, |
78 | /* {"interop", GFC_OMP_DIR_EXECUTABLE, ST_OMP_INTEROP}, */ |
79 | {"loop", GFC_OMP_DIR_EXECUTABLE, ST_OMP_LOOP}, |
80 | {"masked", GFC_OMP_DIR_EXECUTABLE, ST_OMP_MASKED}, |
81 | /* {"metadirective", GFC_OMP_DIR_META, ST_OMP_METADIRECTIVE}, */ |
82 | /* Note: gfc_match_omp_nothing returns ST_NONE. */ |
83 | {"nothing", GFC_OMP_DIR_UTILITY, ST_OMP_NOTHING}, |
84 | /* Special case; for now map to the first one. |
85 | ordered-blockassoc = ST_OMP_ORDERED |
86 | ordered-standalone = ST_OMP_ORDERED_DEPEND + depend/doacross. */ |
87 | {"ordered", GFC_OMP_DIR_EXECUTABLE, ST_OMP_ORDERED}, |
88 | {"parallel", GFC_OMP_DIR_EXECUTABLE, ST_OMP_PARALLEL}, |
89 | {"requires", GFC_OMP_DIR_INFORMATIONAL, ST_OMP_REQUIRES}, |
90 | {"scan", GFC_OMP_DIR_SUBSIDIARY, ST_OMP_SCAN}, |
91 | {"scope", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SCOPE}, |
92 | {"sections", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SECTIONS}, |
93 | {"section", GFC_OMP_DIR_SUBSIDIARY, ST_OMP_SECTION}, |
94 | {"simd", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SIMD}, |
95 | {"single", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SINGLE}, |
96 | {"target data", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_DATA}, |
97 | {"target enter data", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_ENTER_DATA}, |
98 | {"target exit data", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_EXIT_DATA}, |
99 | {"target update", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_UPDATE}, |
100 | {"target", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET}, |
101 | {"taskloop", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASKLOOP}, |
102 | {"taskwait", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASKWAIT}, |
103 | {"taskyield", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASKYIELD}, |
104 | {"task", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASK}, |
105 | {"teams", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TEAMS}, |
106 | {"threadprivate", GFC_OMP_DIR_DECLARATIVE, ST_OMP_THREADPRIVATE}, |
107 | /* {"tile", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TILE}, */ |
108 | /* {"unroll", GFC_OMP_DIR_EXECUTABLE, ST_OMP_UNROLL}, */ |
109 | {"workshare", GFC_OMP_DIR_EXECUTABLE, ST_OMP_WORKSHARE}, |
110 | }; |
111 | |
112 | |
113 | /* Match an end of OpenMP directive. End of OpenMP directive is optional |
114 | whitespace, followed by '\n' or comment '!'. */ |
115 | |
116 | static match |
117 | gfc_match_omp_eos (void) |
118 | { |
119 | locus old_loc; |
120 | char c; |
121 | |
122 | old_loc = gfc_current_locus; |
123 | gfc_gobble_whitespace (); |
124 | |
125 | c = gfc_next_ascii_char (); |
126 | switch (c) |
127 | { |
128 | case '!': |
129 | do |
130 | c = gfc_next_ascii_char (); |
131 | while (c != '\n'); |
132 | /* Fall through */ |
133 | |
134 | case '\n': |
135 | return MATCH_YES; |
136 | } |
137 | |
138 | gfc_current_locus = old_loc; |
139 | return MATCH_NO; |
140 | } |
141 | |
142 | match |
143 | gfc_match_omp_eos_error (void) |
144 | { |
145 | if (gfc_match_omp_eos() == MATCH_YES) |
146 | return MATCH_YES; |
147 | |
148 | gfc_error ("Unexpected junk at %C"); |
149 | return MATCH_ERROR; |
150 | } |
151 | |
152 | |
153 | /* Free an omp_clauses structure. */ |
154 | |
155 | void |
156 | gfc_free_omp_clauses (gfc_omp_clauses *c) |
157 | { |
158 | int i; |
159 | if (c == NULL__null) |
160 | return; |
161 | |
162 | gfc_free_expr (c->if_expr); |
163 | gfc_free_expr (c->final_expr); |
164 | gfc_free_expr (c->num_threads); |
165 | gfc_free_expr (c->chunk_size); |
166 | gfc_free_expr (c->safelen_expr); |
167 | gfc_free_expr (c->simdlen_expr); |
168 | gfc_free_expr (c->num_teams_lower); |
169 | gfc_free_expr (c->num_teams_upper); |
170 | gfc_free_expr (c->device); |
171 | gfc_free_expr (c->thread_limit); |
172 | gfc_free_expr (c->dist_chunk_size); |
173 | gfc_free_expr (c->grainsize); |
174 | gfc_free_expr (c->hint); |
175 | gfc_free_expr (c->num_tasks); |
176 | gfc_free_expr (c->priority); |
177 | gfc_free_expr (c->detach); |
178 | for (i = 0; i < OMP_IF_LAST; i++) |
179 | gfc_free_expr (c->if_exprs[i]); |
180 | gfc_free_expr (c->async_expr); |
181 | gfc_free_expr (c->gang_num_expr); |
182 | gfc_free_expr (c->gang_static_expr); |
183 | gfc_free_expr (c->worker_expr); |
184 | gfc_free_expr (c->vector_expr); |
185 | gfc_free_expr (c->num_gangs_expr); |
186 | gfc_free_expr (c->num_workers_expr); |
187 | gfc_free_expr (c->vector_length_expr); |
188 | for (i = 0; i < OMP_LIST_NUM; i++) |
189 | gfc_free_omp_namelist (c->lists[i], |
190 | i == OMP_LIST_AFFINITY || i == OMP_LIST_DEPEND, |
191 | i == OMP_LIST_ALLOCATE); |
192 | gfc_free_expr_list (c->wait_list); |
193 | gfc_free_expr_list (c->tile_list); |
194 | free (CONST_CAST (char *, c->critical_name)(const_cast<char *> ((c->critical_name)))); |
195 | if (c->assume) |
196 | { |
197 | free (c->assume->absent); |
198 | free (c->assume->contains); |
199 | gfc_free_expr_list (c->assume->holds); |
200 | free (c->assume); |
201 | } |
202 | free (c); |
203 | } |
204 | |
205 | /* Free oacc_declare structures. */ |
206 | |
207 | void |
208 | gfc_free_oacc_declare_clauses (struct gfc_oacc_declare *oc) |
209 | { |
210 | struct gfc_oacc_declare *decl = oc; |
211 | |
212 | do |
213 | { |
214 | struct gfc_oacc_declare *next; |
215 | |
216 | next = decl->next; |
217 | gfc_free_omp_clauses (decl->clauses); |
218 | free (decl); |
219 | decl = next; |
220 | } |
221 | while (decl); |
222 | } |
223 | |
224 | /* Free expression list. */ |
225 | void |
226 | gfc_free_expr_list (gfc_expr_list *list) |
227 | { |
228 | gfc_expr_list *n; |
229 | |
230 | for (; list; list = n) |
231 | { |
232 | n = list->next; |
233 | free (list); |
234 | } |
235 | } |
236 | |
237 | /* Free an !$omp declare simd construct list. */ |
238 | |
239 | void |
240 | gfc_free_omp_declare_simd (gfc_omp_declare_simd *ods) |
241 | { |
242 | if (ods) |
243 | { |
244 | gfc_free_omp_clauses (ods->clauses); |
245 | free (ods); |
246 | } |
247 | } |
248 | |
249 | void |
250 | gfc_free_omp_declare_simd_list (gfc_omp_declare_simd *list) |
251 | { |
252 | while (list) |
253 | { |
254 | gfc_omp_declare_simd *current = list; |
255 | list = list->next; |
256 | gfc_free_omp_declare_simd (current); |
257 | } |
258 | } |
259 | |
260 | static void |
261 | gfc_free_omp_trait_property_list (gfc_omp_trait_property *list) |
262 | { |
263 | while (list) |
264 | { |
265 | gfc_omp_trait_property *current = list; |
266 | list = list->next; |
267 | switch (current->property_kind) |
268 | { |
269 | case CTX_PROPERTY_ID: |
270 | free (current->name); |
271 | break; |
272 | case CTX_PROPERTY_NAME_LIST: |
273 | if (current->is_name) |
274 | free (current->name); |
275 | break; |
276 | case CTX_PROPERTY_SIMD: |
277 | gfc_free_omp_clauses (current->clauses); |
278 | break; |
279 | default: |
280 | break; |
281 | } |
282 | free (current); |
283 | } |
284 | } |
285 | |
286 | static void |
287 | gfc_free_omp_selector_list (gfc_omp_selector *list) |
288 | { |
289 | while (list) |
290 | { |
291 | gfc_omp_selector *current = list; |
292 | list = list->next; |
293 | gfc_free_omp_trait_property_list (current->properties); |
294 | free (current); |
295 | } |
296 | } |
297 | |
298 | static void |
299 | gfc_free_omp_set_selector_list (gfc_omp_set_selector *list) |
300 | { |
301 | while (list) |
302 | { |
303 | gfc_omp_set_selector *current = list; |
304 | list = list->next; |
305 | gfc_free_omp_selector_list (current->trait_selectors); |
306 | free (current); |
307 | } |
308 | } |
309 | |
310 | /* Free an !$omp declare variant construct list. */ |
311 | |
312 | void |
313 | gfc_free_omp_declare_variant_list (gfc_omp_declare_variant *list) |
314 | { |
315 | while (list) |
316 | { |
317 | gfc_omp_declare_variant *current = list; |
318 | list = list->next; |
319 | gfc_free_omp_set_selector_list (current->set_selectors); |
320 | free (current); |
321 | } |
322 | } |
323 | |
324 | /* Free an !$omp declare reduction. */ |
325 | |
326 | void |
327 | gfc_free_omp_udr (gfc_omp_udr *omp_udr) |
328 | { |
329 | if (omp_udr) |
330 | { |
331 | gfc_free_omp_udr (omp_udr->next); |
332 | gfc_free_namespace (omp_udr->combiner_ns); |
333 | if (omp_udr->initializer_ns) |
334 | gfc_free_namespace (omp_udr->initializer_ns); |
335 | free (omp_udr); |
336 | } |
337 | } |
338 | |
339 | |
340 | static gfc_omp_udr * |
341 | gfc_find_omp_udr (gfc_namespace *ns, const char *name, gfc_typespec *ts) |
342 | { |
343 | gfc_symtree *st; |
344 | |
345 | if (ns == NULL__null) |
346 | ns = gfc_current_ns; |
347 | do |
348 | { |
349 | gfc_omp_udr *omp_udr; |
350 | |
351 | st = gfc_find_symtree (ns->omp_udr_root, name); |
352 | if (st != NULL__null) |
353 | { |
354 | for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next) |
355 | if (ts == NULL__null) |
356 | return omp_udr; |
357 | else if (gfc_compare_types (&omp_udr->ts, ts)) |
358 | { |
359 | if (ts->type == BT_CHARACTER) |
360 | { |
361 | if (omp_udr->ts.u.cl->length == NULL__null) |
362 | return omp_udr; |
363 | if (ts->u.cl->length == NULL__null) |
364 | continue; |
365 | if (gfc_compare_expr (omp_udr->ts.u.cl->length, |
366 | ts->u.cl->length, |
367 | INTRINSIC_EQ) != 0) |
368 | continue; |
369 | } |
370 | return omp_udr; |
371 | } |
372 | } |
373 | |
374 | /* Don't escape an interface block. */ |
375 | if (ns && !ns->has_import_set |
376 | && ns->proc_name && ns->proc_name->attr.if_source == IFSRC_IFBODY) |
377 | break; |
378 | |
379 | ns = ns->parent; |
380 | } |
381 | while (ns != NULL__null); |
382 | |
383 | return NULL__null; |
384 | } |
385 | |
386 | |
387 | /* Match a variable/common block list and construct a namelist from it; |
388 | if has_all_memory != NULL, *has_all_memory is set and omp_all_memory |
389 | yields a list->sym NULL entry. */ |
390 | |
391 | static match |
392 | gfc_match_omp_variable_list (const char *str, gfc_omp_namelist **list, |
393 | bool allow_common, bool *end_colon = NULL__null, |
394 | gfc_omp_namelist ***headp = NULL__null, |
395 | bool allow_sections = false, |
396 | bool allow_derived = false, |
397 | bool *has_all_memory = NULL__null) |
398 | { |
399 | gfc_omp_namelist *head, *tail, *p; |
400 | locus old_loc, cur_loc; |
401 | char n[GFC_MAX_SYMBOL_LEN63+1]; |
402 | gfc_symbol *sym; |
403 | match m; |
404 | gfc_symtree *st; |
405 | |
406 | head = tail = NULL__null; |
407 | |
408 | old_loc = gfc_current_locus; |
409 | if (has_all_memory) |
410 | *has_all_memory = false; |
411 | m = gfc_match (str); |
412 | if (m != MATCH_YES) |
413 | return m; |
414 | |
415 | for (;;) |
416 | { |
417 | cur_loc = gfc_current_locus; |
418 | |
419 | m = gfc_match_name (n); |
420 | if (m == MATCH_YES && strcmp (n, "omp_all_memory") == 0) |
421 | { |
422 | if (!has_all_memory) |
423 | { |
424 | gfc_error ("%<omp_all_memory%> at %C not permitted in this " |
425 | "clause"); |
426 | goto cleanup; |
427 | } |
428 | *has_all_memory = true; |
429 | p = gfc_get_omp_namelist ()((gfc_omp_namelist *) xcalloc (1, sizeof (gfc_omp_namelist))); |
430 | if (head == NULL__null) |
431 | head = tail = p; |
432 | else |
433 | { |
434 | tail->next = p; |
435 | tail = tail->next; |
436 | } |
437 | tail->where = cur_loc; |
438 | goto next_item; |
439 | } |
440 | if (m == MATCH_YES) |
441 | { |
442 | gfc_symtree *st; |
443 | if ((m = gfc_get_ha_sym_tree (n, &st) ? MATCH_ERROR : MATCH_YES) |
444 | == MATCH_YES) |
445 | sym = st->n.sym; |
446 | } |
447 | switch (m) |
448 | { |
449 | case MATCH_YES: |
450 | gfc_expr *expr; |
451 | expr = NULL__null; |
452 | gfc_gobble_whitespace (); |
453 | if ((allow_sections && gfc_peek_ascii_char () == '(') |
454 | || (allow_derived && gfc_peek_ascii_char () == '%')) |
455 | { |
456 | gfc_current_locus = cur_loc; |
457 | m = gfc_match_variable (&expr, 0); |
458 | switch (m) |
459 | { |
460 | case MATCH_ERROR: |
461 | goto cleanup; |
462 | case MATCH_NO: |
463 | goto syntax; |
464 | default: |
465 | break; |
466 | } |
467 | if (gfc_is_coindexed (expr)) |
468 | { |
469 | gfc_error ("List item shall not be coindexed at %C"); |
470 | goto cleanup; |
471 | } |
472 | } |
473 | gfc_set_sym_referenced (sym); |
474 | p = gfc_get_omp_namelist ()((gfc_omp_namelist *) xcalloc (1, sizeof (gfc_omp_namelist))); |
475 | if (head == NULL__null) |
476 | head = tail = p; |
477 | else |
478 | { |
479 | tail->next = p; |
480 | tail = tail->next; |
481 | } |
482 | tail->sym = sym; |
483 | tail->expr = expr; |
484 | tail->where = cur_loc; |
485 | goto next_item; |
486 | case MATCH_NO: |
487 | break; |
488 | case MATCH_ERROR: |
489 | goto cleanup; |
490 | } |
491 | |
492 | if (!allow_common) |
493 | goto syntax; |
494 | |
495 | m = gfc_match (" / %n /", n); |
496 | if (m == MATCH_ERROR) |
497 | goto cleanup; |
498 | if (m == MATCH_NO) |
499 | goto syntax; |
500 | |
501 | st = gfc_find_symtree (gfc_current_ns->common_root, n); |
502 | if (st == NULL__null) |
503 | { |
504 | gfc_error ("COMMON block /%s/ not found at %C", n); |
505 | goto cleanup; |
506 | } |
507 | for (sym = st->n.common->head; sym; sym = sym->common_next) |
508 | { |
509 | gfc_set_sym_referenced (sym); |
510 | p = gfc_get_omp_namelist ()((gfc_omp_namelist *) xcalloc (1, sizeof (gfc_omp_namelist))); |
511 | if (head == NULL__null) |
512 | head = tail = p; |
513 | else |
514 | { |
515 | tail->next = p; |
516 | tail = tail->next; |
517 | } |
518 | tail->sym = sym; |
519 | tail->where = cur_loc; |
520 | } |
521 | |
522 | next_item: |
523 | if (end_colon && gfc_match_char (':') == MATCH_YES) |
524 | { |
525 | *end_colon = true; |
526 | break; |
527 | } |
528 | if (gfc_match_char (')') == MATCH_YES) |
529 | break; |
530 | if (gfc_match_char (',') != MATCH_YES) |
531 | goto syntax; |
532 | } |
533 | |
534 | while (*list) |
535 | list = &(*list)->next; |
536 | |
537 | *list = head; |
538 | if (headp) |
539 | *headp = list; |
540 | return MATCH_YES; |
541 | |
542 | syntax: |
543 | gfc_error ("Syntax error in OpenMP variable list at %C"); |
544 | |
545 | cleanup: |
546 | gfc_free_omp_namelist (head, false, false); |
547 | gfc_current_locus = old_loc; |
548 | return MATCH_ERROR; |
549 | } |
550 | |
551 | /* Match a variable/procedure/common block list and construct a namelist |
552 | from it. */ |
553 | |
554 | static match |
555 | gfc_match_omp_to_link (const char *str, gfc_omp_namelist **list) |
556 | { |
557 | gfc_omp_namelist *head, *tail, *p; |
558 | locus old_loc, cur_loc; |
559 | char n[GFC_MAX_SYMBOL_LEN63+1]; |
560 | gfc_symbol *sym; |
561 | match m; |
562 | gfc_symtree *st; |
563 | |
564 | head = tail = NULL__null; |
565 | |
566 | old_loc = gfc_current_locus; |
567 | |
568 | m = gfc_match (str); |
569 | if (m != MATCH_YES) |
570 | return m; |
571 | |
572 | for (;;) |
573 | { |
574 | cur_loc = gfc_current_locus; |
575 | m = gfc_match_symbol (&sym, 1); |
576 | switch (m) |
577 | { |
578 | case MATCH_YES: |
579 | p = gfc_get_omp_namelist ()((gfc_omp_namelist *) xcalloc (1, sizeof (gfc_omp_namelist))); |
580 | if (head == NULL__null) |
581 | head = tail = p; |
582 | else |
583 | { |
584 | tail->next = p; |
585 | tail = tail->next; |
586 | } |
587 | tail->sym = sym; |
588 | tail->where = cur_loc; |
589 | goto next_item; |
590 | case MATCH_NO: |
591 | break; |
592 | case MATCH_ERROR: |
593 | goto cleanup; |
594 | } |
595 | |
596 | m = gfc_match (" / %n /", n); |
597 | if (m == MATCH_ERROR) |
598 | goto cleanup; |
599 | if (m == MATCH_NO) |
600 | goto syntax; |
601 | |
602 | st = gfc_find_symtree (gfc_current_ns->common_root, n); |
603 | if (st == NULL__null) |
604 | { |
605 | gfc_error ("COMMON block /%s/ not found at %C", n); |
606 | goto cleanup; |
607 | } |
608 | p = gfc_get_omp_namelist ()((gfc_omp_namelist *) xcalloc (1, sizeof (gfc_omp_namelist))); |
609 | if (head == NULL__null) |
610 | head = tail = p; |
611 | else |
612 | { |
613 | tail->next = p; |
614 | tail = tail->next; |
615 | } |
616 | tail->u.common = st->n.common; |
617 | tail->where = cur_loc; |
618 | |
619 | next_item: |
620 | if (gfc_match_char (')') == MATCH_YES) |
621 | break; |
622 | if (gfc_match_char (',') != MATCH_YES) |
623 | goto syntax; |
624 | } |
625 | |
626 | while (*list) |
627 | list = &(*list)->next; |
628 | |
629 | *list = head; |
630 | return MATCH_YES; |
631 | |
632 | syntax: |
633 | gfc_error ("Syntax error in OpenMP variable list at %C"); |
634 | |
635 | cleanup: |
636 | gfc_free_omp_namelist (head, false, false); |
637 | gfc_current_locus = old_loc; |
638 | return MATCH_ERROR; |
639 | } |
640 | |
641 | /* Match detach(event-handle). */ |
642 | |
643 | static match |
644 | gfc_match_omp_detach (gfc_expr **expr) |
645 | { |
646 | locus old_loc = gfc_current_locus; |
647 | |
648 | if (gfc_match ("detach ( ") != MATCH_YES) |
649 | goto syntax_error; |
650 | |
651 | if (gfc_match_variable (expr, 0) != MATCH_YES) |
652 | goto syntax_error; |
653 | |
654 | if (gfc_match_char (')') != MATCH_YES) |
655 | goto syntax_error; |
656 | |
657 | return MATCH_YES; |
658 | |
659 | syntax_error: |
660 | gfc_error ("Syntax error in OpenMP detach clause at %C"); |
661 | gfc_current_locus = old_loc; |
662 | return MATCH_ERROR; |
663 | |
664 | } |
665 | |
666 | /* Match doacross(sink : ...) construct a namelist from it; |
667 | if depend is true, match legacy 'depend(sink : ...)'. */ |
668 | |
669 | static match |
670 | gfc_match_omp_doacross_sink (gfc_omp_namelist **list, bool depend) |
671 | { |
672 | char n[GFC_MAX_SYMBOL_LEN63+1]; |
673 | gfc_omp_namelist *head, *tail, *p; |
674 | locus old_loc, cur_loc; |
675 | gfc_symbol *sym; |
676 | |
677 | head = tail = NULL__null; |
678 | |
679 | old_loc = gfc_current_locus; |
680 | |
681 | for (;;) |
682 | { |
683 | cur_loc = gfc_current_locus; |
684 | |
685 | if (gfc_match_name (n) != MATCH_YES) |
686 | goto syntax; |
687 | if (UNLIKELY (strcmp (n, "omp_all_memory") == 0)(__builtin_expect ((strcmp (n, "omp_all_memory") == 0), 0))) |
688 | { |
689 | gfc_error ("%<omp_all_memory%> used with dependence-type " |
690 | "other than OUT or INOUT at %C"); |
691 | goto cleanup; |
692 | } |
693 | sym = NULL__null; |
694 | if (!(strcmp (n, "omp_cur_iteration") == 0)) |
695 | { |
696 | gfc_symtree *st; |
697 | if (gfc_get_ha_sym_tree (n, &st)) |
698 | goto syntax; |
699 | sym = st->n.sym; |
700 | gfc_set_sym_referenced (sym); |
701 | } |
702 | p = gfc_get_omp_namelist ()((gfc_omp_namelist *) xcalloc (1, sizeof (gfc_omp_namelist))); |
703 | if (head == NULL__null) |
704 | { |
705 | head = tail = p; |
706 | head->u.depend_doacross_op = (depend ? OMP_DEPEND_SINK_FIRST |
707 | : OMP_DOACROSS_SINK_FIRST); |
708 | } |
709 | else |
710 | { |
711 | tail->next = p; |
712 | tail = tail->next; |
713 | tail->u.depend_doacross_op = OMP_DOACROSS_SINK; |
714 | } |
715 | tail->sym = sym; |
716 | tail->expr = NULL__null; |
717 | tail->where = cur_loc; |
718 | if (gfc_match_char ('+') == MATCH_YES) |
719 | { |
720 | if (gfc_match_literal_constant (&tail->expr, 0) != MATCH_YES) |
721 | goto syntax; |
722 | } |
723 | else if (gfc_match_char ('-') == MATCH_YES) |
724 | { |
725 | if (gfc_match_literal_constant (&tail->expr, 0) != MATCH_YES) |
726 | goto syntax; |
727 | tail->expr = gfc_uminus (tail->expr); |
728 | } |
729 | if (gfc_match_char (')') == MATCH_YES) |
730 | break; |
731 | if (gfc_match_char (',') != MATCH_YES) |
732 | goto syntax; |
733 | } |
734 | |
735 | while (*list) |
736 | list = &(*list)->next; |
737 | |
738 | *list = head; |
739 | return MATCH_YES; |
740 | |
741 | syntax: |
742 | gfc_error ("Syntax error in OpenMP SINK dependence-type list at %C"); |
743 | |
744 | cleanup: |
745 | gfc_free_omp_namelist (head, false, false); |
746 | gfc_current_locus = old_loc; |
747 | return MATCH_ERROR; |
748 | } |
749 | |
750 | static match |
751 | match_oacc_expr_list (const char *str, gfc_expr_list **list, |
752 | bool allow_asterisk) |
753 | { |
754 | gfc_expr_list *head, *tail, *p; |
755 | locus old_loc; |
756 | gfc_expr *expr; |
757 | match m; |
758 | |
759 | head = tail = NULL__null; |
760 | |
761 | old_loc = gfc_current_locus; |
762 | |
763 | m = gfc_match (str); |
764 | if (m != MATCH_YES) |
765 | return m; |
766 | |
767 | for (;;) |
768 | { |
769 | m = gfc_match_expr (&expr); |
770 | if (m == MATCH_YES || allow_asterisk) |
771 | { |
772 | p = gfc_get_expr_list ()((gfc_expr_list *) xcalloc (1, sizeof (gfc_expr_list))); |
773 | if (head == NULL__null) |
774 | head = tail = p; |
775 | else |
776 | { |
777 | tail->next = p; |
778 | tail = tail->next; |
779 | } |
780 | if (m == MATCH_YES) |
781 | tail->expr = expr; |
782 | else if (gfc_match (" *") != MATCH_YES) |
783 | goto syntax; |
784 | goto next_item; |
785 | } |
786 | if (m == MATCH_ERROR) |
787 | goto cleanup; |
788 | goto syntax; |
789 | |
790 | next_item: |
791 | if (gfc_match_char (')') == MATCH_YES) |
792 | break; |
793 | if (gfc_match_char (',') != MATCH_YES) |
794 | goto syntax; |
795 | } |
796 | |
797 | while (*list) |
798 | list = &(*list)->next; |
799 | |
800 | *list = head; |
801 | return MATCH_YES; |
802 | |
803 | syntax: |
804 | gfc_error ("Syntax error in OpenACC expression list at %C"); |
805 | |
806 | cleanup: |
807 | gfc_free_expr_list (head); |
808 | gfc_current_locus = old_loc; |
809 | return MATCH_ERROR; |
810 | } |
811 | |
812 | static match |
813 | match_oacc_clause_gwv (gfc_omp_clauses *cp, unsigned gwv) |
814 | { |
815 | match ret = MATCH_YES; |
816 | |
817 | if (gfc_match (" ( ") != MATCH_YES) |
818 | return MATCH_NO; |
819 | |
820 | if (gwv == GOMP_DIM_GANG0) |
821 | { |
822 | /* The gang clause accepts two optional arguments, num and static. |
823 | The num argument may either be explicit (num: <val>) or |
824 | implicit without (<val> without num:). */ |
825 | |
826 | while (ret == MATCH_YES) |
827 | { |
828 | if (gfc_match (" static :") == MATCH_YES) |
829 | { |
830 | if (cp->gang_static) |
831 | return MATCH_ERROR; |
832 | else |
833 | cp->gang_static = true; |
834 | if (gfc_match_char ('*') == MATCH_YES) |
835 | cp->gang_static_expr = NULL__null; |
836 | else if (gfc_match (" %e ", &cp->gang_static_expr) != MATCH_YES) |
837 | return MATCH_ERROR; |
838 | } |
839 | else |
840 | { |
841 | if (cp->gang_num_expr) |
842 | return MATCH_ERROR; |
843 | |
844 | /* The 'num' argument is optional. */ |
845 | gfc_match (" num :"); |
846 | |
847 | if (gfc_match (" %e ", &cp->gang_num_expr) != MATCH_YES) |
848 | return MATCH_ERROR; |
849 | } |
850 | |
851 | ret = gfc_match (" , "); |
852 | } |
853 | } |
854 | else if (gwv == GOMP_DIM_WORKER1) |
855 | { |
856 | /* The 'num' argument is optional. */ |
857 | gfc_match (" num :"); |
858 | |
859 | if (gfc_match (" %e ", &cp->worker_expr) != MATCH_YES) |
860 | return MATCH_ERROR; |
861 | } |
862 | else if (gwv == GOMP_DIM_VECTOR2) |
863 | { |
864 | /* The 'length' argument is optional. */ |
865 | gfc_match (" length :"); |
866 | |
867 | if (gfc_match (" %e ", &cp->vector_expr) != MATCH_YES) |
868 | return MATCH_ERROR; |
869 | } |
870 | else |
871 | gfc_fatal_error ("Unexpected OpenACC parallelism."); |
872 | |
873 | return gfc_match (" )"); |
874 | } |
875 | |
876 | static match |
877 | gfc_match_oacc_clause_link (const char *str, gfc_omp_namelist **list) |
878 | { |
879 | gfc_omp_namelist *head = NULL__null; |
880 | gfc_omp_namelist *tail, *p; |
881 | locus old_loc; |
882 | char n[GFC_MAX_SYMBOL_LEN63+1]; |
883 | gfc_symbol *sym; |
884 | match m; |
885 | gfc_symtree *st; |
886 | |
887 | old_loc = gfc_current_locus; |
888 | |
889 | m = gfc_match (str); |
890 | if (m != MATCH_YES) |
891 | return m; |
892 | |
893 | m = gfc_match (" ("); |
894 | |
895 | for (;;) |
896 | { |
897 | m = gfc_match_symbol (&sym, 0); |
898 | switch (m) |
899 | { |
900 | case MATCH_YES: |
901 | if (sym->attr.in_common) |
902 | { |
903 | gfc_error_now ("Variable at %C is an element of a COMMON block"); |
904 | goto cleanup; |
905 | } |
906 | gfc_set_sym_referenced (sym); |
907 | p = gfc_get_omp_namelist ()((gfc_omp_namelist *) xcalloc (1, sizeof (gfc_omp_namelist))); |
908 | if (head == NULL__null) |
909 | head = tail = p; |
910 | else |
911 | { |
912 | tail->next = p; |
913 | tail = tail->next; |
914 | } |
915 | tail->sym = sym; |
916 | tail->expr = NULL__null; |
917 | tail->where = gfc_current_locus; |
918 | goto next_item; |
919 | case MATCH_NO: |
920 | break; |
921 | |
922 | case MATCH_ERROR: |
923 | goto cleanup; |
924 | } |
925 | |
926 | m = gfc_match (" / %n /", n); |
927 | if (m == MATCH_ERROR) |
928 | goto cleanup; |
929 | if (m == MATCH_NO || n[0] == '\0') |
930 | goto syntax; |
931 | |
932 | st = gfc_find_symtree (gfc_current_ns->common_root, n); |
933 | if (st == NULL__null) |
934 | { |
935 | gfc_error ("COMMON block /%s/ not found at %C", n); |
936 | goto cleanup; |
937 | } |
938 | |
939 | for (sym = st->n.common->head; sym; sym = sym->common_next) |
940 | { |
941 | gfc_set_sym_referenced (sym); |
942 | p = gfc_get_omp_namelist ()((gfc_omp_namelist *) xcalloc (1, sizeof (gfc_omp_namelist))); |
943 | if (head == NULL__null) |
944 | head = tail = p; |
945 | else |
946 | { |
947 | tail->next = p; |
948 | tail = tail->next; |
949 | } |
950 | tail->sym = sym; |
951 | tail->where = gfc_current_locus; |
952 | } |
953 | |
954 | next_item: |
955 | if (gfc_match_char (')') == MATCH_YES) |
956 | break; |
957 | if (gfc_match_char (',') != MATCH_YES) |
958 | goto syntax; |
959 | } |
960 | |
961 | if (gfc_match_omp_eos () != MATCH_YES) |
962 | { |
963 | gfc_error ("Unexpected junk after !$ACC DECLARE at %C"); |
964 | goto cleanup; |
965 | } |
966 | |
967 | while (*list) |
968 | list = &(*list)->next; |
969 | *list = head; |
970 | return MATCH_YES; |
971 | |
972 | syntax: |
973 | gfc_error ("Syntax error in !$ACC DECLARE list at %C"); |
974 | |
975 | cleanup: |
976 | gfc_current_locus = old_loc; |
977 | return MATCH_ERROR; |
978 | } |
979 | |
980 | /* OpenMP clauses. */ |
981 | enum omp_mask1 |
982 | { |
983 | OMP_CLAUSE_PRIVATE, |
984 | OMP_CLAUSE_FIRSTPRIVATE, |
985 | OMP_CLAUSE_LASTPRIVATE, |
986 | OMP_CLAUSE_COPYPRIVATE, |
987 | OMP_CLAUSE_SHARED, |
988 | OMP_CLAUSE_COPYIN, |
989 | OMP_CLAUSE_REDUCTION, |
990 | OMP_CLAUSE_IN_REDUCTION, |
991 | OMP_CLAUSE_TASK_REDUCTION, |
992 | OMP_CLAUSE_IF, |
993 | OMP_CLAUSE_NUM_THREADS, |
994 | OMP_CLAUSE_SCHEDULE, |
995 | OMP_CLAUSE_DEFAULT, |
996 | OMP_CLAUSE_ORDER, |
997 | OMP_CLAUSE_ORDERED, |
998 | OMP_CLAUSE_COLLAPSE, |
999 | OMP_CLAUSE_UNTIED, |
1000 | OMP_CLAUSE_FINAL, |
1001 | OMP_CLAUSE_MERGEABLE, |
1002 | OMP_CLAUSE_ALIGNED, |
1003 | OMP_CLAUSE_DEPEND, |
1004 | OMP_CLAUSE_INBRANCH, |
1005 | OMP_CLAUSE_LINEAR, |
1006 | OMP_CLAUSE_NOTINBRANCH, |
1007 | OMP_CLAUSE_PROC_BIND, |
1008 | OMP_CLAUSE_SAFELEN, |
1009 | OMP_CLAUSE_SIMDLEN, |
1010 | OMP_CLAUSE_UNIFORM, |
1011 | OMP_CLAUSE_DEVICE, |
1012 | OMP_CLAUSE_MAP, |
1013 | OMP_CLAUSE_TO, |
1014 | OMP_CLAUSE_FROM, |
1015 | OMP_CLAUSE_NUM_TEAMS, |
1016 | OMP_CLAUSE_THREAD_LIMIT, |
1017 | OMP_CLAUSE_DIST_SCHEDULE, |
1018 | OMP_CLAUSE_DEFAULTMAP, |
1019 | OMP_CLAUSE_GRAINSIZE, |
1020 | OMP_CLAUSE_HINT, |
1021 | OMP_CLAUSE_IS_DEVICE_PTR, |
1022 | OMP_CLAUSE_LINK, |
1023 | OMP_CLAUSE_NOGROUP, |
1024 | OMP_CLAUSE_NOTEMPORAL, |
1025 | OMP_CLAUSE_NUM_TASKS, |
1026 | OMP_CLAUSE_PRIORITY, |
1027 | OMP_CLAUSE_SIMD, |
1028 | OMP_CLAUSE_THREADS, |
1029 | OMP_CLAUSE_USE_DEVICE_PTR, |
1030 | OMP_CLAUSE_USE_DEVICE_ADDR, /* OpenMP 5.0. */ |
1031 | OMP_CLAUSE_DEVICE_TYPE, /* OpenMP 5.0. */ |
1032 | OMP_CLAUSE_ATOMIC, /* OpenMP 5.0. */ |
1033 | OMP_CLAUSE_CAPTURE, /* OpenMP 5.0. */ |
1034 | OMP_CLAUSE_MEMORDER, /* OpenMP 5.0. */ |
1035 | OMP_CLAUSE_DETACH, /* OpenMP 5.0. */ |
1036 | OMP_CLAUSE_AFFINITY, /* OpenMP 5.0. */ |
1037 | OMP_CLAUSE_ALLOCATE, /* OpenMP 5.0. */ |
1038 | OMP_CLAUSE_BIND, /* OpenMP 5.0. */ |
1039 | OMP_CLAUSE_FILTER, /* OpenMP 5.1. */ |
1040 | OMP_CLAUSE_AT, /* OpenMP 5.1. */ |
1041 | OMP_CLAUSE_MESSAGE, /* OpenMP 5.1. */ |
1042 | OMP_CLAUSE_SEVERITY, /* OpenMP 5.1. */ |
1043 | OMP_CLAUSE_COMPARE, /* OpenMP 5.1. */ |
1044 | OMP_CLAUSE_FAIL, /* OpenMP 5.1. */ |
1045 | OMP_CLAUSE_WEAK, /* OpenMP 5.1. */ |
1046 | OMP_CLAUSE_NOWAIT, |
1047 | /* This must come last. */ |
1048 | OMP_MASK1_LAST |
1049 | }; |
1050 | |
1051 | /* More OpenMP clauses and OpenACC 2.0+ specific clauses. */ |
1052 | enum omp_mask2 |
1053 | { |
1054 | OMP_CLAUSE_ASYNC, |
1055 | OMP_CLAUSE_NUM_GANGS, |
1056 | OMP_CLAUSE_NUM_WORKERS, |
1057 | OMP_CLAUSE_VECTOR_LENGTH, |
1058 | OMP_CLAUSE_COPY, |
1059 | OMP_CLAUSE_COPYOUT, |
1060 | OMP_CLAUSE_CREATE, |
1061 | OMP_CLAUSE_NO_CREATE, |
1062 | OMP_CLAUSE_PRESENT, |
1063 | OMP_CLAUSE_DEVICEPTR, |
1064 | OMP_CLAUSE_GANG, |
1065 | OMP_CLAUSE_WORKER, |
1066 | OMP_CLAUSE_VECTOR, |
1067 | OMP_CLAUSE_SEQ, |
1068 | OMP_CLAUSE_INDEPENDENT, |
1069 | OMP_CLAUSE_USE_DEVICE, |
1070 | OMP_CLAUSE_DEVICE_RESIDENT, |
1071 | OMP_CLAUSE_HOST_SELF, |
1072 | OMP_CLAUSE_WAIT, |
1073 | OMP_CLAUSE_DELETE, |
1074 | OMP_CLAUSE_AUTO, |
1075 | OMP_CLAUSE_TILE, |
1076 | OMP_CLAUSE_IF_PRESENT, |
1077 | OMP_CLAUSE_FINALIZE, |
1078 | OMP_CLAUSE_ATTACH, |
1079 | OMP_CLAUSE_NOHOST, |
1080 | OMP_CLAUSE_HAS_DEVICE_ADDR, /* OpenMP 5.1 */ |
1081 | OMP_CLAUSE_ENTER, /* OpenMP 5.2 */ |
1082 | OMP_CLAUSE_DOACROSS, /* OpenMP 5.2 */ |
1083 | OMP_CLAUSE_ASSUMPTIONS, /* OpenMP 5.1. */ |
1084 | /* This must come last. */ |
1085 | OMP_MASK2_LAST |
1086 | }; |
1087 | |
1088 | struct omp_inv_mask; |
1089 | |
1090 | /* Customized bitset for up to 128-bits. |
1091 | The two enums above provide bit numbers to use, and which of the |
1092 | two enums it is determines which of the two mask fields is used. |
1093 | Supported operations are defining a mask, like: |
1094 | #define XXX_CLAUSES \ |
1095 | (omp_mask (OMP_CLAUSE_XXX) | OMP_CLAUSE_YYY | OMP_CLAUSE_ZZZ) |
1096 | oring such bitsets together or removing selected bits: |
1097 | (XXX_CLAUSES | YYY_CLAUSES) & ~(omp_mask (OMP_CLAUSE_VVV)) |
1098 | and testing individual bits: |
1099 | if (mask & OMP_CLAUSE_UUU) */ |
1100 | |
1101 | struct omp_mask { |
1102 | const uint64_t mask1; |
1103 | const uint64_t mask2; |
1104 | inline omp_mask (); |
1105 | inline omp_mask (omp_mask1); |
1106 | inline omp_mask (omp_mask2); |
1107 | inline omp_mask (uint64_t, uint64_t); |
1108 | inline omp_mask operator| (omp_mask1) const; |
1109 | inline omp_mask operator| (omp_mask2) const; |
1110 | inline omp_mask operator| (omp_mask) const; |
1111 | inline omp_mask operator& (const omp_inv_mask &) const; |
1112 | inline bool operator& (omp_mask1) const; |
1113 | inline bool operator& (omp_mask2) const; |
1114 | inline omp_inv_mask operator~ () const; |
1115 | }; |
1116 | |
1117 | struct omp_inv_mask : public omp_mask { |
1118 | inline omp_inv_mask (const omp_mask &); |
1119 | }; |
1120 | |
1121 | omp_mask::omp_mask () : mask1 (0), mask2 (0) |
1122 | { |
1123 | } |
1124 | |
1125 | omp_mask::omp_mask (omp_mask1 m) : mask1 (((uint64_t) 1) << m), mask2 (0) |
1126 | { |
1127 | } |
1128 | |
1129 | omp_mask::omp_mask (omp_mask2 m) : mask1 (0), mask2 (((uint64_t) 1) << m) |
1130 | { |
1131 | } |
1132 | |
1133 | omp_mask::omp_mask (uint64_t m1, uint64_t m2) : mask1 (m1), mask2 (m2) |
1134 | { |
1135 | } |
1136 | |
1137 | omp_mask |
1138 | omp_mask::operator| (omp_mask1 m) const |
1139 | { |
1140 | return omp_mask (mask1 | (((uint64_t) 1) << m), mask2); |
1141 | } |
1142 | |
1143 | omp_mask |
1144 | omp_mask::operator| (omp_mask2 m) const |
1145 | { |
1146 | return omp_mask (mask1, mask2 | (((uint64_t) 1) << m)); |
1147 | } |
1148 | |
1149 | omp_mask |
1150 | omp_mask::operator| (omp_mask m) const |
1151 | { |
1152 | return omp_mask (mask1 | m.mask1, mask2 | m.mask2); |
1153 | } |
1154 | |
1155 | omp_mask |
1156 | omp_mask::operator& (const omp_inv_mask &m) const |
1157 | { |
1158 | return omp_mask (mask1 & ~m.mask1, mask2 & ~m.mask2); |
1159 | } |
1160 | |
1161 | bool |
1162 | omp_mask::operator& (omp_mask1 m) const |
1163 | { |
1164 | return (mask1 & (((uint64_t) 1) << m)) != 0; |
1165 | } |
1166 | |
1167 | bool |
1168 | omp_mask::operator& (omp_mask2 m) const |
1169 | { |
1170 | return (mask2 & (((uint64_t) 1) << m)) != 0; |
1171 | } |
1172 | |
1173 | omp_inv_mask |
1174 | omp_mask::operator~ () const |
1175 | { |
1176 | return omp_inv_mask (*this); |
1177 | } |
1178 | |
1179 | omp_inv_mask::omp_inv_mask (const omp_mask &m) : omp_mask (m) |
1180 | { |
1181 | } |
1182 | |
1183 | /* Helper function for OpenACC and OpenMP clauses involving memory |
1184 | mapping. */ |
1185 | |
1186 | static bool |
1187 | gfc_match_omp_map_clause (gfc_omp_namelist **list, gfc_omp_map_op map_op, |
1188 | bool allow_common, bool allow_derived) |
1189 | { |
1190 | gfc_omp_namelist **head = NULL__null; |
1191 | if (gfc_match_omp_variable_list ("", list, allow_common, NULL__null, &head, true, |
1192 | allow_derived) |
1193 | == MATCH_YES) |
1194 | { |
1195 | gfc_omp_namelist *n; |
1196 | for (n = *head; n; n = n->next) |
1197 | n->u.map_op = map_op; |
1198 | return true; |
1199 | } |
1200 | |
1201 | return false; |
1202 | } |
1203 | |
1204 | static match |
1205 | gfc_match_iterator (gfc_namespace **ns, bool permit_var) |
1206 | { |
1207 | locus old_loc = gfc_current_locus; |
1208 | |
1209 | if (gfc_match ("iterator ( ") != MATCH_YES) |
1210 | return MATCH_NO; |
1211 | |
1212 | gfc_typespec ts; |
1213 | gfc_symbol *last = NULL__null; |
1214 | gfc_expr *begin, *end, *step; |
1215 | *ns = gfc_build_block_ns (gfc_current_ns); |
1216 | char name[GFC_MAX_SYMBOL_LEN63 + 1]; |
1217 | while (true) |
1218 | { |
1219 | locus prev_loc = gfc_current_locus; |
1220 | if (gfc_match_type_spec (&ts) == MATCH_YES |
1221 | && gfc_match (" :: ") == MATCH_YES) |
1222 | { |
1223 | if (ts.type != BT_INTEGER) |
1224 | { |
1225 | gfc_error ("Expected INTEGER type at %L", &prev_loc); |
1226 | return MATCH_ERROR; |
1227 | } |
1228 | permit_var = false; |
1229 | } |
1230 | else |
1231 | { |
1232 | ts.type = BT_INTEGER; |
1233 | ts.kind = gfc_default_integer_kind; |
1234 | gfc_current_locus = prev_loc; |
1235 | } |
1236 | prev_loc = gfc_current_locus; |
1237 | if (gfc_match_name (name) != MATCH_YES) |
1238 | { |
1239 | gfc_error ("Expected identifier at %C"); |
1240 | goto failed; |
1241 | } |
1242 | if (gfc_find_symtree ((*ns)->sym_root, name)) |
1243 | { |
1244 | gfc_error ("Same identifier %qs specified again at %C", name); |
1245 | goto failed; |
1246 | } |
1247 | |
1248 | gfc_symbol *sym = gfc_new_symbol (name, *ns); |
1249 | if (last) |
1250 | last->tlink = sym; |
1251 | else |
1252 | (*ns)->omp_affinity_iterators = sym; |
1253 | last = sym; |
1254 | sym->declared_at = prev_loc; |
1255 | sym->ts = ts; |
1256 | sym->attr.flavor = FL_VARIABLE; |
1257 | sym->attr.artificial = 1; |
1258 | sym->attr.referenced = 1; |
1259 | sym->refs++; |
1260 | gfc_symtree *st = gfc_new_symtree (&(*ns)->sym_root, name); |
1261 | st->n.sym = sym; |
1262 | |
1263 | prev_loc = gfc_current_locus; |
1264 | if (gfc_match (" = ") != MATCH_YES) |
1265 | goto failed; |
1266 | permit_var = false; |
1267 | begin = end = step = NULL__null; |
1268 | if (gfc_match ("%e : ", &begin) != MATCH_YES |
1269 | || gfc_match ("%e ", &end) != MATCH_YES) |
1270 | { |
1271 | gfc_error ("Expected range-specification at %C"); |
1272 | gfc_free_expr (begin); |
1273 | gfc_free_expr (end); |
1274 | return MATCH_ERROR; |
1275 | } |
1276 | if (':' == gfc_peek_ascii_char ()) |
1277 | { |
1278 | if (gfc_match (": %e ", &step) != MATCH_YES) |
1279 | { |
1280 | gfc_free_expr (begin); |
1281 | gfc_free_expr (end); |
1282 | gfc_free_expr (step); |
1283 | goto failed; |
1284 | } |
1285 | } |
1286 | |
1287 | gfc_expr *e = gfc_get_expr (); |
1288 | e->where = prev_loc; |
1289 | e->expr_type = EXPR_ARRAY; |
1290 | e->ts = ts; |
1291 | e->rank = 1; |
1292 | e->shape = gfc_get_shape (1)(((mpz_t *) xcalloc (((1)), sizeof (mpz_t)))); |
1293 | mpz_init_set_ui__gmpz_init_set_ui (e->shape[0], step ? 3 : 2); |
1294 | gfc_constructor_append_expr (&e->value.constructor, begin, &begin->where); |
1295 | gfc_constructor_append_expr (&e->value.constructor, end, &end->where); |
1296 | if (step) |
1297 | gfc_constructor_append_expr (&e->value.constructor, step, &step->where); |
1298 | sym->value = e; |
1299 | |
1300 | if (gfc_match (") ") == MATCH_YES) |
1301 | break; |
1302 | if (gfc_match (", ") != MATCH_YES) |
1303 | goto failed; |
1304 | } |
1305 | return MATCH_YES; |
1306 | |
1307 | failed: |
1308 | gfc_namespace *prev_ns = NULL__null; |
1309 | for (gfc_namespace *it = gfc_current_ns->contained; it; it = it->sibling) |
1310 | { |
1311 | if (it == *ns) |
1312 | { |
1313 | if (prev_ns) |
1314 | prev_ns->sibling = it->sibling; |
1315 | else |
1316 | gfc_current_ns->contained = it->sibling; |
1317 | gfc_free_namespace (it); |
1318 | break; |
1319 | } |
1320 | prev_ns = it; |
1321 | } |
1322 | *ns = NULL__null; |
1323 | if (!permit_var) |
1324 | return MATCH_ERROR; |
1325 | gfc_current_locus = old_loc; |
1326 | return MATCH_NO; |
1327 | } |
1328 | |
1329 | /* reduction ( reduction-modifier, reduction-operator : variable-list ) |
1330 | in_reduction ( reduction-operator : variable-list ) |
1331 | task_reduction ( reduction-operator : variable-list ) */ |
1332 | |
1333 | static match |
1334 | gfc_match_omp_clause_reduction (char pc, gfc_omp_clauses *c, bool openacc, |
1335 | bool allow_derived, bool openmp_target = false) |
1336 | { |
1337 | if (pc == 'r' && gfc_match ("reduction ( ") != MATCH_YES) |
1338 | return MATCH_NO; |
1339 | else if (pc == 'i' && gfc_match ("in_reduction ( ") != MATCH_YES) |
1340 | return MATCH_NO; |
1341 | else if (pc == 't' && gfc_match ("task_reduction ( ") != MATCH_YES) |
1342 | return MATCH_NO; |
1343 | |
1344 | locus old_loc = gfc_current_locus; |
1345 | int list_idx = 0; |
1346 | |
1347 | if (pc == 'r' && !openacc) |
1348 | { |
1349 | if (gfc_match ("inscan") == MATCH_YES) |
1350 | list_idx = OMP_LIST_REDUCTION_INSCAN; |
1351 | else if (gfc_match ("task") == MATCH_YES) |
1352 | list_idx = OMP_LIST_REDUCTION_TASK; |
1353 | else if (gfc_match ("default") == MATCH_YES) |
1354 | list_idx = OMP_LIST_REDUCTION; |
1355 | if (list_idx != 0 && gfc_match (", ") != MATCH_YES) |
1356 | { |
1357 | gfc_error ("Comma expected at %C"); |
1358 | gfc_current_locus = old_loc; |
1359 | return MATCH_NO; |
1360 | } |
1361 | if (list_idx == 0) |
1362 | list_idx = OMP_LIST_REDUCTION; |
1363 | } |
1364 | else if (pc == 'i') |
1365 | list_idx = OMP_LIST_IN_REDUCTION; |
1366 | else if (pc == 't') |
1367 | list_idx = OMP_LIST_TASK_REDUCTION; |
1368 | else |
1369 | list_idx = OMP_LIST_REDUCTION; |
1370 | |
1371 | gfc_omp_reduction_op rop = OMP_REDUCTION_NONE; |
1372 | char buffer[GFC_MAX_SYMBOL_LEN63 + 3]; |
1373 | if (gfc_match_char ('+') == MATCH_YES) |
1374 | rop = OMP_REDUCTION_PLUS; |
1375 | else if (gfc_match_char ('*') == MATCH_YES) |
1376 | rop = OMP_REDUCTION_TIMES; |
1377 | else if (gfc_match_char ('-') == MATCH_YES) |
1378 | rop = OMP_REDUCTION_MINUS; |
1379 | else if (gfc_match (".and.") == MATCH_YES) |
1380 | rop = OMP_REDUCTION_AND; |
1381 | else if (gfc_match (".or.") == MATCH_YES) |
1382 | rop = OMP_REDUCTION_OR; |
1383 | else if (gfc_match (".eqv.") == MATCH_YES) |
1384 | rop = OMP_REDUCTION_EQV; |
1385 | else if (gfc_match (".neqv.") == MATCH_YES) |
1386 | rop = OMP_REDUCTION_NEQV; |
1387 | if (rop != OMP_REDUCTION_NONE) |
1388 | snprintf (buffer, sizeof buffer, "operator %s", |
1389 | gfc_op2string ((gfc_intrinsic_op) rop)); |
1390 | else if (gfc_match_defined_op_name (buffer + 1, 1) == MATCH_YES) |
1391 | { |
1392 | buffer[0] = '.'; |
1393 | strcat (buffer, "."); |
1394 | } |
1395 | else if (gfc_match_name (buffer) == MATCH_YES) |
1396 | { |
1397 | gfc_symbol *sym; |
1398 | const char *n = buffer; |
1399 | |
1400 | gfc_find_symbol (buffer, NULL__null, 1, &sym); |
1401 | if (sym != NULL__null) |
1402 | { |
1403 | if (sym->attr.intrinsic) |
1404 | n = sym->name; |
1405 | else if ((sym->attr.flavor != FL_UNKNOWN |
1406 | && sym->attr.flavor != FL_PROCEDURE) |
1407 | || sym->attr.external |
1408 | || sym->attr.generic |
1409 | || sym->attr.entry |
1410 | || sym->attr.result |
1411 | || sym->attr.dummy |
1412 | || sym->attr.subroutine |
1413 | || sym->attr.pointer |
1414 | || sym->attr.target |
1415 | || sym->attr.cray_pointer |
1416 | || sym->attr.cray_pointee |
1417 | || (sym->attr.proc != PROC_UNKNOWN |
1418 | && sym->attr.proc != PROC_INTRINSIC) |
1419 | || sym->attr.if_source != IFSRC_UNKNOWN |
1420 | || sym == sym->ns->proc_name) |
1421 | { |
1422 | sym = NULL__null; |
1423 | n = NULL__null; |
1424 | } |
1425 | else |
1426 | n = sym->name; |
1427 | } |
1428 | if (n == NULL__null) |
1429 | rop = OMP_REDUCTION_NONE; |
1430 | else if (strcmp (n, "max") == 0) |
1431 | rop = OMP_REDUCTION_MAX; |
1432 | else if (strcmp (n, "min") == 0) |
1433 | rop = OMP_REDUCTION_MIN; |
1434 | else if (strcmp (n, "iand") == 0) |
1435 | rop = OMP_REDUCTION_IAND; |
1436 | else if (strcmp (n, "ior") == 0) |
1437 | rop = OMP_REDUCTION_IOR; |
1438 | else if (strcmp (n, "ieor") == 0) |
1439 | rop = OMP_REDUCTION_IEOR; |
1440 | if (rop != OMP_REDUCTION_NONE |
1441 | && sym != NULL__null |
1442 | && ! sym->attr.intrinsic |
1443 | && ! sym->attr.use_assoc |
1444 | && ((sym->attr.flavor == FL_UNKNOWN |
1445 | && !gfc_add_flavor (&sym->attr, FL_PROCEDURE, |
1446 | sym->name, NULL__null)) |
1447 | || !gfc_add_intrinsic (&sym->attr, NULL__null))) |
1448 | rop = OMP_REDUCTION_NONE; |
1449 | } |
1450 | else |
1451 | buffer[0] = '\0'; |
1452 | gfc_omp_udr *udr = (buffer[0] ? gfc_find_omp_udr (gfc_current_ns, buffer, NULL__null) |
1453 | : NULL__null); |
1454 | gfc_omp_namelist **head = NULL__null; |
1455 | if (rop == OMP_REDUCTION_NONE && udr) |
1456 | rop = OMP_REDUCTION_USER; |
1457 | |
1458 | if (gfc_match_omp_variable_list (" :", &c->lists[list_idx], false, NULL__null, |
1459 | &head, openacc, allow_derived) != MATCH_YES) |
1460 | { |
1461 | gfc_current_locus = old_loc; |
1462 | return MATCH_NO; |
1463 | } |
1464 | gfc_omp_namelist *n; |
1465 | if (rop == OMP_REDUCTION_NONE) |
1466 | { |
1467 | n = *head; |
1468 | *head = NULL__null; |
1469 | gfc_error_now ("!$OMP DECLARE REDUCTION %s not found at %L", |
1470 | buffer, &old_loc); |
1471 | gfc_free_omp_namelist (n, false, false); |
1472 | } |
1473 | else |
1474 | for (n = *head; n; n = n->next) |
1475 | { |
1476 | n->u.reduction_op = rop; |
1477 | if (udr) |
1478 | { |
1479 | n->u2.udr = gfc_get_omp_namelist_udr ()((gfc_omp_namelist_udr *) xcalloc (1, sizeof (gfc_omp_namelist_udr ))); |
1480 | n->u2.udr->udr = udr; |
1481 | } |
1482 | if (openmp_target && list_idx == OMP_LIST_IN_REDUCTION) |
1483 | { |
1484 | gfc_omp_namelist *p = gfc_get_omp_namelist ()((gfc_omp_namelist *) xcalloc (1, sizeof (gfc_omp_namelist))), **tl; |
1485 | p->sym = n->sym; |
1486 | p->where = p->where; |
1487 | p->u.map_op = OMP_MAP_ALWAYS_TOFROM; |
1488 | |
1489 | tl = &c->lists[OMP_LIST_MAP]; |
1490 | while (*tl) |
1491 | tl = &((*tl)->next); |
1492 | *tl = p; |
1493 | p->next = NULL__null; |
1494 | } |
1495 | } |
1496 | return MATCH_YES; |
1497 | } |
1498 | |
1499 | static match |
1500 | gfc_omp_absent_contains_clause (gfc_omp_assumptions **assume, bool is_absent) |
1501 | { |
1502 | if (*assume == NULL__null) |
1503 | *assume = gfc_get_omp_assumptions ()((gfc_omp_assumptions *) xcalloc (1, sizeof (gfc_omp_assumptions ))); |
1504 | do |
1505 | { |
1506 | gfc_statement st = ST_NONE; |
1507 | gfc_gobble_whitespace (); |
1508 | locus old_loc = gfc_current_locus; |
1509 | char c = gfc_peek_ascii_char (); |
1510 | enum gfc_omp_directive_kind kind |
1511 | = GFC_OMP_DIR_DECLARATIVE; /* Silence warning. */ |
1512 | for (size_t i = 0; i < ARRAY_SIZE (gfc_omp_directives)(sizeof (gfc_omp_directives) / sizeof ((gfc_omp_directives)[0 ])); i++) |
1513 | { |
1514 | if (gfc_omp_directives[i].name[0] > c) |
1515 | break; |
1516 | if (gfc_omp_directives[i].name[0] != c) |
1517 | continue; |
1518 | if (gfc_match (gfc_omp_directives[i].name) == MATCH_YES) |
1519 | { |
1520 | st = gfc_omp_directives[i].st; |
1521 | kind = gfc_omp_directives[i].kind; |
1522 | } |
1523 | } |
1524 | gfc_gobble_whitespace (); |
1525 | c = gfc_peek_ascii_char (); |
1526 | if (st == ST_NONE || (c != ',' && c != ')')) |
1527 | { |
1528 | if (st == ST_NONE) |
1529 | gfc_error ("Unknown directive at %L", &old_loc); |
1530 | else |
1531 | gfc_error ("Invalid combined or composit directive at %L", |
1532 | &old_loc); |
1533 | return MATCH_ERROR; |
1534 | } |
1535 | if (kind == GFC_OMP_DIR_DECLARATIVE |
1536 | || kind == GFC_OMP_DIR_INFORMATIONAL |
1537 | || kind == GFC_OMP_DIR_META) |
1538 | { |
1539 | gfc_error ("Invalid %qs directive at %L in %s clause: declarative, " |
1540 | "informational and meta directives not permitted", |
1541 | gfc_ascii_statement (st, true), &old_loc, |
1542 | is_absent ? "ABSENT" : "CONTAINS"); |
1543 | return MATCH_ERROR; |
1544 | } |
1545 | if (is_absent) |
1546 | { |
1547 | /* Use exponential allocation; equivalent to pow2p(x). */ |
1548 | int i = (*assume)->n_absent; |
1549 | int size = ((i == 0) ? 4 |
1550 | : pow2p_hwi (i) == 1 ? i*2 : 0); |
1551 | if (size != 0) |
1552 | (*assume)->absent = XRESIZEVEC (gfc_statement,((gfc_statement *) xrealloc ((void *) ((*assume)->absent), sizeof (gfc_statement) * (size))) |
1553 | (*assume)->absent, size)((gfc_statement *) xrealloc ((void *) ((*assume)->absent), sizeof (gfc_statement) * (size))); |
1554 | (*assume)->absent[(*assume)->n_absent++] = st; |
1555 | } |
1556 | else |
1557 | { |
1558 | int i = (*assume)->n_contains; |
1559 | int size = ((i == 0) ? 4 |
1560 | : pow2p_hwi (i) == 1 ? i*2 : 0); |
1561 | if (size != 0) |
1562 | (*assume)->contains = XRESIZEVEC (gfc_statement,((gfc_statement *) xrealloc ((void *) ((*assume)->contains ), sizeof (gfc_statement) * (size))) |
1563 | (*assume)->contains, size)((gfc_statement *) xrealloc ((void *) ((*assume)->contains ), sizeof (gfc_statement) * (size))); |
1564 | (*assume)->contains[(*assume)->n_contains++] = st; |
1565 | } |
1566 | gfc_gobble_whitespace (); |
1567 | if (gfc_match(",") == MATCH_YES) |
1568 | continue; |
1569 | if (gfc_match(")") == MATCH_YES) |
1570 | break; |
1571 | gfc_error ("Expected %<,%> or %<)%> at %C"); |
1572 | return MATCH_ERROR; |
1573 | } |
1574 | while (true); |
1575 | |
1576 | return MATCH_YES; |
1577 | } |
1578 | |
1579 | /* Check 'check' argument for duplicated statements in absent and/or contains |
1580 | clauses. If 'merge', merge them from check to 'merge'. */ |
1581 | |
1582 | static match |
1583 | omp_verify_merge_absent_contains (gfc_statement st, gfc_omp_assumptions *check, |
1584 | gfc_omp_assumptions *merge, locus *loc) |
1585 | { |
1586 | if (check == NULL__null) |
1587 | return MATCH_YES; |
1588 | bitmap_head absent_head, contains_head; |
1589 | bitmap_obstack_initialize (NULL__null); |
1590 | bitmap_initialize (&absent_head, &bitmap_default_obstack); |
1591 | bitmap_initialize (&contains_head, &bitmap_default_obstack); |
1592 | |
1593 | match m = MATCH_YES; |
1594 | for (int i = 0; i < check->n_absent; i++) |
1595 | if (!bitmap_set_bit (&absent_head, check->absent[i])) |
1596 | { |
1597 | gfc_error ("%qs directive mentioned multiple times in %s clause in %s " |
1598 | "directive at %L", |
1599 | gfc_ascii_statement (check->absent[i], true), |
1600 | "ABSENT", gfc_ascii_statement (st), loc); |
1601 | m = MATCH_ERROR; |
1602 | } |
1603 | for (int i = 0; i < check->n_contains; i++) |
1604 | { |
1605 | if (!bitmap_set_bit (&contains_head, check->contains[i])) |
1606 | { |
1607 | gfc_error ("%qs directive mentioned multiple times in %s clause in %s " |
1608 | "directive at %L", |
1609 | gfc_ascii_statement (check->contains[i], true), |
1610 | "CONTAINS", gfc_ascii_statement (st), loc); |
1611 | m = MATCH_ERROR; |
1612 | } |
1613 | if (bitmap_bit_p (&absent_head, check->contains[i])) |
1614 | { |
1615 | gfc_error ("%qs directive mentioned both times in ABSENT and CONTAINS " |
1616 | "clauses in %s directive at %L", |
1617 | gfc_ascii_statement (check->absent[i], true), |
1618 | gfc_ascii_statement (st), loc); |
1619 | m = MATCH_ERROR; |
1620 | } |
1621 | } |
1622 | |
1623 | if (m == MATCH_ERROR) |
1624 | return MATCH_ERROR; |
1625 | if (merge == NULL__null) |
1626 | return MATCH_YES; |
1627 | if (merge->absent == NULL__null && check->absent) |
1628 | { |
1629 | merge->n_absent = check->n_absent; |
1630 | merge->absent = check->absent; |
1631 | check->absent = NULL__null; |
1632 | } |
1633 | else if (merge->absent && check->absent) |
1634 | { |
1635 | check->absent = XRESIZEVEC (gfc_statement, check->absent,((gfc_statement *) xrealloc ((void *) (check->absent), sizeof (gfc_statement) * (merge->n_absent + check->n_absent)) ) |
1636 | merge->n_absent + check->n_absent)((gfc_statement *) xrealloc ((void *) (check->absent), sizeof (gfc_statement) * (merge->n_absent + check->n_absent)) ); |
1637 | for (int i = 0; i < merge->n_absent; i++) |
1638 | if (!bitmap_bit_p (&absent_head, merge->absent[i])) |
1639 | check->absent[check->n_absent++] = merge->absent[i]; |
1640 | free (merge->absent); |
1641 | merge->absent = check->absent; |
1642 | merge->n_absent = check->n_absent; |
1643 | check->absent = NULL__null; |
1644 | } |
1645 | if (merge->contains == NULL__null && check->contains) |
1646 | { |
1647 | merge->n_contains = check->n_contains; |
1648 | merge->contains = check->contains; |
1649 | check->contains = NULL__null; |
1650 | } |
1651 | else if (merge->contains && check->contains) |
1652 | { |
1653 | check->contains = XRESIZEVEC (gfc_statement, check->contains,((gfc_statement *) xrealloc ((void *) (check->contains), sizeof (gfc_statement) * (merge->n_contains + check->n_contains ))) |
1654 | merge->n_contains + check->n_contains)((gfc_statement *) xrealloc ((void *) (check->contains), sizeof (gfc_statement) * (merge->n_contains + check->n_contains ))); |
1655 | for (int i = 0; i < merge->n_contains; i++) |
1656 | if (!bitmap_bit_p (&contains_head, merge->contains[i])) |
1657 | check->contains[check->n_contains++] = merge->contains[i]; |
1658 | free (merge->contains); |
1659 | merge->contains = check->contains; |
1660 | merge->n_contains = check->n_contains; |
1661 | check->contains = NULL__null; |
1662 | } |
1663 | return MATCH_YES; |
1664 | } |
1665 | |
1666 | |
1667 | /* Match with duplicate check. Matches 'name'. If expr != NULL, it |
1668 | then matches '(expr)', otherwise, if open_parens is true, |
1669 | it matches a ' ( ' after 'name'. |
1670 | dupl_message requires '%qs %L' - and is used by |
1671 | gfc_match_dupl_memorder and gfc_match_dupl_atomic. */ |
1672 | |
1673 | static match |
1674 | gfc_match_dupl_check (bool not_dupl, const char *name, bool open_parens = false, |
1675 | gfc_expr **expr = NULL__null, const char *dupl_msg = NULL__null) |
1676 | { |
1677 | match m; |
1678 | locus old_loc = gfc_current_locus; |
1679 | if ((m = gfc_match (name)) != MATCH_YES) |
1680 | return m; |
1681 | if (!not_dupl) |
1682 | { |
1683 | if (dupl_msg) |
1684 | gfc_error (dupl_msg, name, &old_loc); |
1685 | else |
1686 | gfc_error ("Duplicated %qs clause at %L", name, &old_loc); |
1687 | return MATCH_ERROR; |
1688 | } |
1689 | if (open_parens || expr) |
1690 | { |
1691 | if (gfc_match (" ( ") != MATCH_YES) |
1692 | { |
1693 | gfc_error ("Expected %<(%> after %qs at %C", name); |
1694 | return MATCH_ERROR; |
1695 | } |
1696 | if (expr) |
1697 | { |
1698 | if (gfc_match ("%e )", expr) != MATCH_YES) |
1699 | { |
1700 | gfc_error ("Invalid expression after %<%s(%> at %C", name); |
1701 | return MATCH_ERROR; |
1702 | } |
1703 | } |
1704 | } |
1705 | return MATCH_YES; |
1706 | } |
1707 | |
1708 | static match |
1709 | gfc_match_dupl_memorder (bool not_dupl, const char *name) |
1710 | { |
1711 | return gfc_match_dupl_check (not_dupl, name, false, NULL__null, |
1712 | "Duplicated memory-order clause: unexpected %s " |
1713 | "clause at %L"); |
1714 | } |
1715 | |
1716 | static match |
1717 | gfc_match_dupl_atomic (bool not_dupl, const char *name) |
1718 | { |
1719 | return gfc_match_dupl_check (not_dupl, name, false, NULL__null, |
1720 | "Duplicated atomic clause: unexpected %s " |
1721 | "clause at %L"); |
1722 | } |
1723 | |
1724 | /* Match OpenMP and OpenACC directive clauses. MASK is a bitmask of |
1725 | clauses that are allowed for a particular directive. */ |
1726 | |
1727 | static match |
1728 | gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask, |
1729 | bool first = true, bool needs_space = true, |
1730 | bool openacc = false, bool context_selector = false, |
1731 | bool openmp_target = false) |
1732 | { |
1733 | bool error = false; |
1734 | gfc_omp_clauses *c = gfc_get_omp_clauses ()((gfc_omp_clauses *) xcalloc (1, sizeof (gfc_omp_clauses))); |
1735 | locus old_loc; |
1736 | /* Determine whether we're dealing with an OpenACC directive that permits |
1737 | derived type member accesses. This in particular disallows |
1738 | "!$acc declare" from using such accesses, because it's not clear if/how |
1739 | that should work. */ |
1740 | bool allow_derived = (openacc |
1741 | && ((mask & OMP_CLAUSE_ATTACH) |
1742 | || (mask & OMP_CLAUSE_DETACH) |
1743 | || (mask & OMP_CLAUSE_HOST_SELF))); |
1744 | |
1745 | gcc_checking_assert (OMP_MASK1_LAST <= 64 && OMP_MASK2_LAST <= 64)((void)(!(OMP_MASK1_LAST <= 64 && OMP_MASK2_LAST <= 64) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/openmp.cc" , 1745, __FUNCTION__), 0 : 0)); |
1746 | *cp = NULL__null; |
1747 | while (1) |
1748 | { |
1749 | match m = MATCH_NO; |
1750 | if ((first || (m = gfc_match_char (',')) != MATCH_YES) |
1751 | && (needs_space && gfc_match_space () != MATCH_YES)) |
1752 | break; |
1753 | needs_space = false; |
1754 | first = false; |
1755 | gfc_gobble_whitespace (); |
1756 | bool end_colon; |
1757 | gfc_omp_namelist **head; |
1758 | old_loc = gfc_current_locus; |
1759 | char pc = gfc_peek_ascii_char (); |
1760 | if (pc == '\n' && m == MATCH_YES) |
1761 | { |
1762 | gfc_error ("Clause expected at %C after trailing comma"); |
1763 | goto error; |
1764 | } |
1765 | switch (pc) |
1766 | { |
1767 | case 'a': |
1768 | end_colon = false; |
1769 | head = NULL__null; |
1770 | if ((mask & OMP_CLAUSE_ASSUMPTIONS) |
1771 | && gfc_match ("absent ( ") == MATCH_YES) |
1772 | { |
1773 | if (gfc_omp_absent_contains_clause (&c->assume, true) |
1774 | != MATCH_YES) |
1775 | goto error; |
1776 | continue; |
1777 | } |
1778 | if ((mask & OMP_CLAUSE_ALIGNED) |
1779 | && gfc_match_omp_variable_list ("aligned (", |
1780 | &c->lists[OMP_LIST_ALIGNED], |
1781 | false, &end_colon, |
1782 | &head) == MATCH_YES) |
1783 | { |
1784 | gfc_expr *alignment = NULL__null; |
1785 | gfc_omp_namelist *n; |
1786 | |
1787 | if (end_colon && gfc_match (" %e )", &alignment) != MATCH_YES) |
1788 | { |
1789 | gfc_free_omp_namelist (*head, false, false); |
1790 | gfc_current_locus = old_loc; |
1791 | *head = NULL__null; |
1792 | break; |
1793 | } |
1794 | for (n = *head; n; n = n->next) |
1795 | if (n->next && alignment) |
1796 | n->expr = gfc_copy_expr (alignment); |
1797 | else |
1798 | n->expr = alignment; |
1799 | continue; |
1800 | } |
1801 | if ((mask & OMP_CLAUSE_MEMORDER) |
1802 | && (m = gfc_match_dupl_memorder ((c->memorder |
1803 | == OMP_MEMORDER_UNSET), |
1804 | "acq_rel")) != MATCH_NO) |
1805 | { |
1806 | if (m == MATCH_ERROR) |
1807 | goto error; |
1808 | c->memorder = OMP_MEMORDER_ACQ_REL; |
1809 | needs_space = true; |
1810 | continue; |
1811 | } |
1812 | if ((mask & OMP_CLAUSE_MEMORDER) |
1813 | && (m = gfc_match_dupl_memorder ((c->memorder |
1814 | == OMP_MEMORDER_UNSET), |
1815 | "acquire")) != MATCH_NO) |
1816 | { |
1817 | if (m == MATCH_ERROR) |
1818 | goto error; |
1819 | c->memorder = OMP_MEMORDER_ACQUIRE; |
1820 | needs_space = true; |
1821 | continue; |
1822 | } |
1823 | if ((mask & OMP_CLAUSE_AFFINITY) |
1824 | && gfc_match ("affinity ( ") == MATCH_YES) |
1825 | { |
1826 | gfc_namespace *ns_iter = NULL__null, *ns_curr = gfc_current_ns; |
1827 | m = gfc_match_iterator (&ns_iter, true); |
1828 | if (m == MATCH_ERROR) |
1829 | break; |
1830 | if (m == MATCH_YES && gfc_match (" : ") != MATCH_YES) |
1831 | { |
1832 | gfc_error ("Expected %<:%> at %C"); |
1833 | break; |
1834 | } |
1835 | if (ns_iter) |
1836 | gfc_current_ns = ns_iter; |
1837 | head = NULL__null; |
1838 | m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_AFFINITY], |
1839 | false, NULL__null, &head, true); |
1840 | gfc_current_ns = ns_curr; |
1841 | if (m == MATCH_ERROR) |
1842 | break; |
1843 | if (ns_iter) |
1844 | { |
1845 | for (gfc_omp_namelist *n = *head; n; n = n->next) |
1846 | { |
1847 | n->u2.ns = ns_iter; |
1848 | ns_iter->refs++; |
1849 | } |
1850 | } |
1851 | continue; |
1852 | } |
1853 | if ((mask & OMP_CLAUSE_ALLOCATE) |
1854 | && gfc_match ("allocate ( ") == MATCH_YES) |
1855 | { |
1856 | gfc_expr *allocator = NULL__null; |
1857 | gfc_expr *align = NULL__null; |
1858 | old_loc = gfc_current_locus; |
1859 | if ((m = gfc_match ("allocator ( %e )", &allocator)) == MATCH_YES) |
1860 | gfc_match (" , align ( %e )", &align); |
1861 | else if ((m = gfc_match ("align ( %e )", &align)) == MATCH_YES) |
1862 | gfc_match (" , allocator ( %e )", &allocator); |
1863 | |
1864 | if (m == MATCH_YES) |
1865 | { |
1866 | if (gfc_match (" : ") != MATCH_YES) |
1867 | { |
1868 | gfc_error ("Expected %<:%> at %C"); |
1869 | goto error; |
1870 | } |
1871 | } |
1872 | else |
1873 | { |
1874 | m = gfc_match_expr (&allocator); |
1875 | if (m == MATCH_YES && gfc_match (" : ") != MATCH_YES) |
1876 | { |
1877 | /* If no ":" then there is no allocator, we backtrack |
1878 | and read the variable list. */ |
1879 | gfc_free_expr (allocator); |
1880 | allocator = NULL__null; |
1881 | gfc_current_locus = old_loc; |
1882 | } |
1883 | } |
1884 | gfc_omp_namelist **head = NULL__null; |
1885 | m = gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_ALLOCATE], |
1886 | true, NULL__null, &head); |
1887 | |
1888 | if (m != MATCH_YES) |
1889 | { |
1890 | gfc_free_expr (allocator); |
1891 | gfc_free_expr (align); |
1892 | gfc_error ("Expected variable list at %C"); |
1893 | goto error; |
1894 | } |
1895 | |
1896 | for (gfc_omp_namelist *n = *head; n; n = n->next) |
1897 | { |
1898 | n->expr = (allocator) ? gfc_copy_expr (allocator) : NULL__null; |
1899 | n->u.align = (align) ? gfc_copy_expr (align) : NULL__null; |
1900 | } |
1901 | gfc_free_expr (allocator); |
1902 | gfc_free_expr (align); |
1903 | continue; |
1904 | } |
1905 | if ((mask & OMP_CLAUSE_AT) |
1906 | && (m = gfc_match_dupl_check (c->at == OMP_AT_UNSET, "at", true)) |
1907 | != MATCH_NO) |
1908 | { |
1909 | if (m == MATCH_ERROR) |
1910 | goto error; |
1911 | if (gfc_match ("compilation )") == MATCH_YES) |
1912 | c->at = OMP_AT_COMPILATION; |
1913 | else if (gfc_match ("execution )") == MATCH_YES) |
1914 | c->at = OMP_AT_EXECUTION; |
1915 | else |
1916 | { |
1917 | gfc_error ("Expected COMPILATION or EXECUTION in AT clause " |
1918 | "at %C"); |
1919 | goto error; |
1920 | } |
1921 | continue; |
1922 | } |
1923 | if ((mask & OMP_CLAUSE_ASYNC) |
1924 | && (m = gfc_match_dupl_check (!c->async, "async")) != MATCH_NO) |
1925 | { |
1926 | if (m == MATCH_ERROR) |
1927 | goto error; |
1928 | c->async = true; |
1929 | m = gfc_match (" ( %e )", &c->async_expr); |
1930 | if (m == MATCH_ERROR) |
1931 | { |
1932 | gfc_current_locus = old_loc; |
1933 | break; |
1934 | } |
1935 | else if (m == MATCH_NO) |
1936 | { |
1937 | c->async_expr |
1938 | = gfc_get_constant_expr (BT_INTEGER, |
1939 | gfc_default_integer_kind, |
1940 | &gfc_current_locus); |
1941 | mpz_set_si__gmpz_set_si (c->async_expr->value.integer, GOMP_ASYNC_NOVAL-1); |
1942 | needs_space = true; |
1943 | } |
1944 | continue; |
1945 | } |
1946 | if ((mask & OMP_CLAUSE_AUTO) |
1947 | && (m = gfc_match_dupl_check (!c->par_auto, "auto")) |
1948 | != MATCH_NO) |
1949 | { |
1950 | if (m == MATCH_ERROR) |
1951 | goto error; |
1952 | c->par_auto = true; |
1953 | needs_space = true; |
1954 | continue; |
1955 | } |
1956 | if ((mask & OMP_CLAUSE_ATTACH) |
1957 | && gfc_match ("attach ( ") == MATCH_YES |
1958 | && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP], |
1959 | OMP_MAP_ATTACH, false, |
1960 | allow_derived)) |
1961 | continue; |
1962 | break; |
1963 | case 'b': |
1964 | if ((mask & OMP_CLAUSE_BIND) |
1965 | && (m = gfc_match_dupl_check (c->bind == OMP_BIND_UNSET, "bind", |
1966 | true)) != MATCH_NO) |
1967 | { |
1968 | if (m == MATCH_ERROR) |
1969 | goto error; |
1970 | if (gfc_match ("teams )") == MATCH_YES) |
1971 | c->bind = OMP_BIND_TEAMS; |
1972 | else if (gfc_match ("parallel )") == MATCH_YES) |
1973 | c->bind = OMP_BIND_PARALLEL; |
1974 | else if (gfc_match ("thread )") == MATCH_YES) |
1975 | c->bind = OMP_BIND_THREAD; |
1976 | else |
1977 | { |
1978 | gfc_error ("Expected TEAMS, PARALLEL or THREAD as binding in " |
1979 | "BIND at %C"); |
1980 | break; |
1981 | } |
1982 | continue; |
1983 | } |
1984 | break; |
1985 | case 'c': |
1986 | if ((mask & OMP_CLAUSE_CAPTURE) |
1987 | && (m = gfc_match_dupl_check (!c->capture, "capture")) |
1988 | != MATCH_NO) |
1989 | { |
1990 | if (m == MATCH_ERROR) |
1991 | goto error; |
1992 | c->capture = true; |
1993 | needs_space = true; |
1994 | continue; |
1995 | } |
1996 | if (mask & OMP_CLAUSE_COLLAPSE) |
1997 | { |
1998 | gfc_expr *cexpr = NULL__null; |
1999 | if ((m = gfc_match_dupl_check (!c->collapse, "collapse", true, |
2000 | &cexpr)) != MATCH_NO) |
2001 | { |
2002 | int collapse; |
2003 | if (m == MATCH_ERROR) |
2004 | goto error; |
2005 | if (gfc_extract_int (cexpr, &collapse, -1)) |
2006 | collapse = 1; |
2007 | else if (collapse <= 0) |
2008 | { |
2009 | gfc_error_now ("COLLAPSE clause argument not constant " |
2010 | "positive integer at %C"); |
2011 | collapse = 1; |
2012 | } |
2013 | gfc_free_expr (cexpr); |
2014 | c->collapse = collapse; |
2015 | continue; |
2016 | } |
2017 | } |
2018 | if ((mask & OMP_CLAUSE_COMPARE) |
2019 | && (m = gfc_match_dupl_check (!c->compare, "compare")) |
2020 | != MATCH_NO) |
2021 | { |
2022 | if (m == MATCH_ERROR) |
2023 | goto error; |
2024 | c->compare = true; |
2025 | needs_space = true; |
2026 | continue; |
2027 | } |
2028 | if ((mask & OMP_CLAUSE_ASSUMPTIONS) |
2029 | && gfc_match ("contains ( ") == MATCH_YES) |
2030 | { |
2031 | if (gfc_omp_absent_contains_clause (&c->assume, false) |
2032 | != MATCH_YES) |
2033 | goto error; |
2034 | continue; |
2035 | } |
2036 | if ((mask & OMP_CLAUSE_COPY) |
2037 | && gfc_match ("copy ( ") == MATCH_YES |
2038 | && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP], |
2039 | OMP_MAP_TOFROM, true, |
2040 | allow_derived)) |
2041 | continue; |
2042 | if (mask & OMP_CLAUSE_COPYIN) |
2043 | { |
2044 | if (openacc) |
2045 | { |
2046 | if (gfc_match ("copyin ( ") == MATCH_YES |
2047 | && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP], |
2048 | OMP_MAP_TO, true, |
2049 | allow_derived)) |
2050 | continue; |
2051 | } |
2052 | else if (gfc_match_omp_variable_list ("copyin (", |
2053 | &c->lists[OMP_LIST_COPYIN], |
2054 | true) == MATCH_YES) |
2055 | continue; |
2056 | } |
2057 | if ((mask & OMP_CLAUSE_COPYOUT) |
2058 | && gfc_match ("copyout ( ") == MATCH_YES |
2059 | && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP], |
2060 | OMP_MAP_FROM, true, allow_derived)) |
2061 | continue; |
2062 | if ((mask & OMP_CLAUSE_COPYPRIVATE) |
2063 | && gfc_match_omp_variable_list ("copyprivate (", |
2064 | &c->lists[OMP_LIST_COPYPRIVATE], |
2065 | true) == MATCH_YES) |
2066 | continue; |
2067 | if ((mask & OMP_CLAUSE_CREATE) |
2068 | && gfc_match ("create ( ") == MATCH_YES |
2069 | && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP], |
2070 | OMP_MAP_ALLOC, true, allow_derived)) |
2071 | continue; |
2072 | break; |
2073 | case 'd': |
2074 | if ((mask & OMP_CLAUSE_DEFAULTMAP) |
2075 | && gfc_match ("defaultmap ( ") == MATCH_YES) |
2076 | { |
2077 | enum gfc_omp_defaultmap behavior; |
2078 | gfc_omp_defaultmap_category category |
2079 | = OMP_DEFAULTMAP_CAT_UNCATEGORIZED; |
2080 | if (gfc_match ("alloc ") == MATCH_YES) |
2081 | behavior = OMP_DEFAULTMAP_ALLOC; |
2082 | else if (gfc_match ("tofrom ") == MATCH_YES) |
2083 | behavior = OMP_DEFAULTMAP_TOFROM; |
2084 | else if (gfc_match ("to ") == MATCH_YES) |
2085 | behavior = OMP_DEFAULTMAP_TO; |
2086 | else if (gfc_match ("from ") == MATCH_YES) |
2087 | behavior = OMP_DEFAULTMAP_FROM; |
2088 | else if (gfc_match ("firstprivate ") == MATCH_YES) |
2089 | behavior = OMP_DEFAULTMAP_FIRSTPRIVATE; |
2090 | else if (gfc_match ("none ") == MATCH_YES) |
2091 | behavior = OMP_DEFAULTMAP_NONE; |
2092 | else if (gfc_match ("default ") == MATCH_YES) |
2093 | behavior = OMP_DEFAULTMAP_DEFAULT; |
2094 | else |
2095 | { |
2096 | gfc_error ("Expected ALLOC, TO, FROM, TOFROM, FIRSTPRIVATE, " |
2097 | "NONE or DEFAULT at %C"); |
2098 | break; |
2099 | } |
2100 | if (')' == gfc_peek_ascii_char ()) |
2101 | ; |
2102 | else if (gfc_match (": ") != MATCH_YES) |
2103 | break; |
2104 | else |
2105 | { |
2106 | if (gfc_match ("scalar ") == MATCH_YES) |
2107 | category = OMP_DEFAULTMAP_CAT_SCALAR; |
2108 | else if (gfc_match ("aggregate ") == MATCH_YES) |
2109 | category = OMP_DEFAULTMAP_CAT_AGGREGATE; |
2110 | else if (gfc_match ("allocatable ") == MATCH_YES) |
2111 | category = OMP_DEFAULTMAP_CAT_ALLOCATABLE; |
2112 | else if (gfc_match ("pointer ") == MATCH_YES) |
2113 | category = OMP_DEFAULTMAP_CAT_POINTER; |
2114 | else |
2115 | { |
2116 | gfc_error ("Expected SCALAR, AGGREGATE, ALLOCATABLE or " |
2117 | "POINTER at %C"); |
2118 | break; |
2119 | } |
2120 | } |
2121 | for (int i = 0; i < OMP_DEFAULTMAP_CAT_NUM; ++i) |
2122 | { |
2123 | if (i != category |
2124 | && category != OMP_DEFAULTMAP_CAT_UNCATEGORIZED) |
2125 | continue; |
2126 | if (c->defaultmap[i] != OMP_DEFAULTMAP_UNSET) |
2127 | { |
2128 | const char *pcategory = NULL__null; |
2129 | switch (i) |
2130 | { |
2131 | case OMP_DEFAULTMAP_CAT_UNCATEGORIZED: break; |
2132 | case OMP_DEFAULTMAP_CAT_SCALAR: pcategory = "SCALAR"; break; |
2133 | case OMP_DEFAULTMAP_CAT_AGGREGATE: |
2134 | pcategory = "AGGREGATE"; |
2135 | break; |
2136 | case OMP_DEFAULTMAP_CAT_ALLOCATABLE: |
2137 | pcategory = "ALLOCATABLE"; |
2138 | break; |
2139 | case OMP_DEFAULTMAP_CAT_POINTER: |
2140 | pcategory = "POINTER"; |
2141 | break; |
2142 | default: gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/openmp.cc" , 2142, __FUNCTION__)); |
2143 | } |
2144 | if (i == OMP_DEFAULTMAP_CAT_UNCATEGORIZED) |
2145 | gfc_error ("DEFAULTMAP at %C but prior DEFAULTMAP with " |
2146 | "unspecified category"); |
2147 | else |
2148 | gfc_error ("DEFAULTMAP at %C but prior DEFAULTMAP for " |
2149 | "category %s", pcategory); |
2150 | goto error; |
2151 | } |
2152 | } |
2153 | c->defaultmap[category] = behavior; |
2154 | if (gfc_match (")") != MATCH_YES) |
2155 | break; |
2156 | continue; |
2157 | } |
2158 | if ((mask & OMP_CLAUSE_DEFAULT) |
2159 | && (m = gfc_match_dupl_check (c->default_sharing |
2160 | == OMP_DEFAULT_UNKNOWN, "default", |
2161 | true)) != MATCH_NO) |
2162 | { |
2163 | if (m == MATCH_ERROR) |
2164 | goto error; |
2165 | if (gfc_match ("none") == MATCH_YES) |
2166 | c->default_sharing = OMP_DEFAULT_NONE; |
2167 | else if (openacc) |
2168 | { |
2169 | if (gfc_match ("present") == MATCH_YES) |
2170 | c->default_sharing = OMP_DEFAULT_PRESENT; |
2171 | } |
2172 | else |
2173 | { |
2174 | if (gfc_match ("firstprivate") == MATCH_YES) |
2175 | c->default_sharing = OMP_DEFAULT_FIRSTPRIVATE; |
2176 | else if (gfc_match ("private") == MATCH_YES) |
2177 | c->default_sharing = OMP_DEFAULT_PRIVATE; |
2178 | else if (gfc_match ("shared") == MATCH_YES) |
2179 | c->default_sharing = OMP_DEFAULT_SHARED; |
2180 | } |
2181 | if (c->default_sharing == OMP_DEFAULT_UNKNOWN) |
2182 | { |
2183 | if (openacc) |
2184 | gfc_error ("Expected NONE or PRESENT in DEFAULT clause " |
2185 | "at %C"); |
2186 | else |
2187 | gfc_error ("Expected NONE, FIRSTPRIVATE, PRIVATE or SHARED " |
2188 | "in DEFAULT clause at %C"); |
2189 | goto error; |
2190 | } |
2191 | if (gfc_match (" )") != MATCH_YES) |
2192 | goto error; |
2193 | continue; |
2194 | } |
2195 | if ((mask & OMP_CLAUSE_DELETE) |
2196 | && gfc_match ("delete ( ") == MATCH_YES |
2197 | && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP], |
2198 | OMP_MAP_RELEASE, true, |
2199 | allow_derived)) |
2200 | continue; |
2201 | /* DOACROSS: match 'doacross' and 'depend' with sink/source. |
2202 | DEPEND: match 'depend' but not sink/source. */ |
2203 | m = MATCH_NO; |
2204 | if (((mask & OMP_CLAUSE_DOACROSS) |
2205 | && gfc_match ("doacross ( ") == MATCH_YES) |
2206 | || (((mask & OMP_CLAUSE_DEPEND) || (mask & OMP_CLAUSE_DOACROSS)) |
2207 | && (m = gfc_match ("depend ( ")) == MATCH_YES)) |
2208 | { |
2209 | bool has_omp_all_memory; |
2210 | bool is_depend = m == MATCH_YES; |
2211 | gfc_namespace *ns_iter = NULL__null, *ns_curr = gfc_current_ns; |
2212 | match m_it = MATCH_NO; |
2213 | if (is_depend) |
2214 | m_it = gfc_match_iterator (&ns_iter, false); |
2215 | if (m_it == MATCH_ERROR) |
2216 | break; |
2217 | if (m_it == MATCH_YES && gfc_match (" , ") != MATCH_YES) |
2218 | break; |
2219 | m = MATCH_YES; |
2220 | gfc_omp_depend_doacross_op depend_op = OMP_DEPEND_OUT; |
2221 | if (gfc_match ("inoutset") == MATCH_YES) |
2222 | depend_op = OMP_DEPEND_INOUTSET; |
2223 | else if (gfc_match ("inout") == MATCH_YES) |
2224 | depend_op = OMP_DEPEND_INOUT; |
2225 | else if (gfc_match ("in") == MATCH_YES) |
2226 | depend_op = OMP_DEPEND_IN; |
2227 | else if (gfc_match ("out") == MATCH_YES) |
2228 | depend_op = OMP_DEPEND_OUT; |
2229 | else if (gfc_match ("mutexinoutset") == MATCH_YES) |
2230 | depend_op = OMP_DEPEND_MUTEXINOUTSET; |
2231 | else if (gfc_match ("depobj") == MATCH_YES) |
2232 | depend_op = OMP_DEPEND_DEPOBJ; |
2233 | else if (gfc_match ("source") == MATCH_YES) |
2234 | { |
2235 | if (m_it == MATCH_YES) |
2236 | { |
2237 | gfc_error ("ITERATOR may not be combined with SOURCE " |
2238 | "at %C"); |
2239 | goto error; |
2240 | } |
2241 | if (!(mask & OMP_CLAUSE_DOACROSS)) |
2242 | { |
2243 | gfc_error ("SOURCE at %C not permitted as dependence-type" |
2244 | " for this directive"); |
2245 | goto error; |
2246 | } |
2247 | if (c->doacross_source) |
2248 | { |
2249 | gfc_error ("Duplicated clause with SOURCE dependence-type" |
2250 | " at %C"); |
2251 | goto error; |
2252 | } |
2253 | gfc_gobble_whitespace (); |
2254 | m = gfc_match (": "); |
2255 | if (m != MATCH_YES && !is_depend) |
2256 | { |
2257 | gfc_error ("Expected %<:%> at %C"); |
2258 | goto error; |
2259 | } |
2260 | if (gfc_match (")") != MATCH_YES |
2261 | && !(m == MATCH_YES |
2262 | && gfc_match ("omp_cur_iteration )") == MATCH_YES)) |
2263 | { |
2264 | gfc_error ("Expected %<)%> or %<omp_cur_iteration)%> " |
2265 | "at %C"); |
2266 | goto error; |
2267 | } |
2268 | c->doacross_source = true; |
2269 | c->depend_source = is_depend; |
2270 | continue; |
2271 | } |
2272 | else if (gfc_match ("sink ") == MATCH_YES) |
2273 | { |
2274 | if (!(mask & OMP_CLAUSE_DOACROSS)) |
2275 | { |
2276 | gfc_error ("SINK at %C not permitted as dependence-type " |
2277 | "for this directive"); |
2278 | goto error; |
2279 | } |
2280 | if (gfc_match (": ") != MATCH_YES) |
2281 | { |
2282 | gfc_error ("Expected %<:%> at %C"); |
2283 | goto error; |
2284 | } |
2285 | if (m_it == MATCH_YES) |
2286 | { |
2287 | gfc_error ("ITERATOR may not be combined with SINK " |
2288 | "at %C"); |
2289 | goto error; |
2290 | } |
2291 | m = gfc_match_omp_doacross_sink (&c->lists[OMP_LIST_DEPEND], |
2292 | is_depend); |
2293 | if (m == MATCH_YES) |
2294 | continue; |
2295 | goto error; |
2296 | } |
2297 | else |
2298 | m = MATCH_NO; |
2299 | if (!(mask & OMP_CLAUSE_DEPEND)) |
2300 | { |
2301 | gfc_error ("Expected dependence-type SINK or SOURCE at %C"); |
2302 | goto error; |
2303 | } |
2304 | head = NULL__null; |
2305 | if (ns_iter) |
2306 | gfc_current_ns = ns_iter; |
2307 | if (m == MATCH_YES) |
2308 | m = gfc_match_omp_variable_list (" : ", |
2309 | &c->lists[OMP_LIST_DEPEND], |
2310 | false, NULL__null, &head, true, |
2311 | false, &has_omp_all_memory); |
2312 | if (m != MATCH_YES) |
2313 | goto error; |
2314 | gfc_current_ns = ns_curr; |
2315 | if (has_omp_all_memory && depend_op != OMP_DEPEND_INOUT |
2316 | && depend_op != OMP_DEPEND_OUT) |
2317 | { |
2318 | gfc_error ("%<omp_all_memory%> used with DEPEND kind " |
2319 | "other than OUT or INOUT at %C"); |
2320 | goto error; |
2321 | } |
2322 | gfc_omp_namelist *n; |
2323 | for (n = *head; n; n = n->next) |
2324 | { |
2325 | n->u.depend_doacross_op = depend_op; |
2326 | n->u2.ns = ns_iter; |
2327 | if (ns_iter) |
2328 | ns_iter->refs++; |
2329 | } |
2330 | continue; |
2331 | } |
2332 | if ((mask & OMP_CLAUSE_DETACH) |
2333 | && !openacc |
2334 | && !c->detach |
2335 | && gfc_match_omp_detach (&c->detach) == MATCH_YES) |
2336 | continue; |
2337 | if ((mask & OMP_CLAUSE_DETACH) |
2338 | && openacc |
2339 | && gfc_match ("detach ( ") == MATCH_YES |
2340 | && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP], |
2341 | OMP_MAP_DETACH, false, |
2342 | allow_derived)) |
2343 | continue; |
2344 | if ((mask & OMP_CLAUSE_DEVICE) |
2345 | && !openacc |
2346 | && ((m = gfc_match_dupl_check (!c->device, "device", true)) |
2347 | != MATCH_NO)) |
2348 | { |
2349 | if (m == MATCH_ERROR) |
2350 | goto error; |
2351 | c->ancestor = false; |
2352 | if (gfc_match ("device_num : ") == MATCH_YES) |
2353 | { |
2354 | if (gfc_match ("%e )", &c->device) != MATCH_YES) |
2355 | { |
2356 | gfc_error ("Expected integer expression at %C"); |
2357 | break; |
2358 | } |
2359 | } |
2360 | else if (gfc_match ("ancestor : ") == MATCH_YES) |
2361 | { |
2362 | bool has_requires = false; |
2363 | c->ancestor = true; |
2364 | for (gfc_namespace *ns = gfc_current_ns; ns; ns = ns->parent) |
2365 | if (ns->omp_requires & OMP_REQ_REVERSE_OFFLOAD) |
2366 | { |
2367 | has_requires = true; |
2368 | break; |
2369 | } |
2370 | if (!has_requires) |
2371 | { |
2372 | gfc_error ("%<ancestor%> device modifier not " |
2373 | "preceded by %<requires%> directive " |
2374 | "with %<reverse_offload%> clause at %C"); |
2375 | break; |
2376 | } |
2377 | locus old_loc2 = gfc_current_locus; |
2378 | if (gfc_match ("%e )", &c->device) == MATCH_YES) |
2379 | { |
2380 | int device = 0; |
2381 | if (!gfc_extract_int (c->device, &device) && device != 1) |
2382 | { |
2383 | gfc_current_locus = old_loc2; |
2384 | gfc_error ("the %<device%> clause expression must " |
2385 | "evaluate to %<1%> at %C"); |
2386 | break; |
2387 | } |
2388 | } |
2389 | else |
2390 | { |
2391 | gfc_error ("Expected integer expression at %C"); |
2392 | break; |
2393 | } |
2394 | } |
2395 | else if (gfc_match ("%e )", &c->device) != MATCH_YES) |
2396 | { |
2397 | gfc_error ("Expected integer expression or a single device-" |
2398 | "modifier %<device_num%> or %<ancestor%> at %C"); |
2399 | break; |
2400 | } |
2401 | continue; |
2402 | } |
2403 | if ((mask & OMP_CLAUSE_DEVICE) |
2404 | && openacc |
2405 | && gfc_match ("device ( ") == MATCH_YES |
2406 | && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP], |
2407 | OMP_MAP_FORCE_TO, true, |
2408 | allow_derived)) |
2409 | continue; |
2410 | if ((mask & OMP_CLAUSE_DEVICEPTR) |
2411 | && gfc_match ("deviceptr ( ") == MATCH_YES |
2412 | && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP], |
2413 | OMP_MAP_FORCE_DEVICEPTR, false, |
2414 | allow_derived)) |
2415 | continue; |
2416 | if ((mask & OMP_CLAUSE_DEVICE_TYPE) |
2417 | && gfc_match ("device_type ( ") == MATCH_YES) |
2418 | { |
2419 | if (gfc_match ("host") == MATCH_YES) |
2420 | c->device_type = OMP_DEVICE_TYPE_HOST; |
2421 | else if (gfc_match ("nohost") == MATCH_YES) |
2422 | c->device_type = OMP_DEVICE_TYPE_NOHOST; |
2423 | else if (gfc_match ("any") == MATCH_YES) |
2424 | c->device_type = OMP_DEVICE_TYPE_ANY; |
2425 | else |
2426 | { |
2427 | gfc_error ("Expected HOST, NOHOST or ANY at %C"); |
2428 | break; |
2429 | } |
2430 | if (gfc_match (" )") != MATCH_YES) |
2431 | break; |
2432 | continue; |
2433 | } |
2434 | if ((mask & OMP_CLAUSE_DEVICE_RESIDENT) |
2435 | && gfc_match_omp_variable_list |
2436 | ("device_resident (", |
2437 | &c->lists[OMP_LIST_DEVICE_RESIDENT], true) == MATCH_YES) |
2438 | continue; |
2439 | if ((mask & OMP_CLAUSE_DIST_SCHEDULE) |
2440 | && c->dist_sched_kind == OMP_SCHED_NONE |
2441 | && gfc_match ("dist_schedule ( static") == MATCH_YES) |
2442 | { |
2443 | m = MATCH_NO; |
Value stored to 'm' is never read | |
2444 | c->dist_sched_kind = OMP_SCHED_STATIC; |
2445 | m = gfc_match (" , %e )", &c->dist_chunk_size); |
2446 | if (m != MATCH_YES) |
2447 | m = gfc_match_char (')'); |
2448 | if (m != MATCH_YES) |
2449 | { |
2450 | c->dist_sched_kind = OMP_SCHED_NONE; |
2451 | gfc_current_locus = old_loc; |
2452 | } |
2453 | else |
2454 | continue; |
2455 | } |
2456 | break; |
2457 | case 'e': |
2458 | if ((mask & OMP_CLAUSE_ENTER)) |
2459 | { |
2460 | m = gfc_match_omp_to_link ("enter (", &c->lists[OMP_LIST_ENTER]); |
2461 | if (m == MATCH_ERROR) |
2462 | goto error; |
2463 | if (m == MATCH_YES) |
2464 | continue; |
2465 | } |
2466 | break; |
2467 | case 'f': |
2468 | if ((mask & OMP_CLAUSE_FAIL) |
2469 | && (m = gfc_match_dupl_check (c->fail == OMP_MEMORDER_UNSET, |
2470 | "fail", true)) != MATCH_NO) |
2471 | { |
2472 | if (m == MATCH_ERROR) |
2473 | goto error; |
2474 | if (gfc_match ("seq_cst") == MATCH_YES) |
2475 | c->fail = OMP_MEMORDER_SEQ_CST; |
2476 | else if (gfc_match ("acquire") == MATCH_YES) |
2477 | c->fail = OMP_MEMORDER_ACQUIRE; |
2478 | else if (gfc_match ("relaxed") == MATCH_YES) |
2479 | c->fail = OMP_MEMORDER_RELAXED; |
2480 | else |
2481 | { |
2482 | gfc_error ("Expected SEQ_CST, ACQUIRE or RELAXED at %C"); |
2483 | break; |
2484 | } |
2485 | if (gfc_match (" )") != MATCH_YES) |
2486 | goto error; |
2487 | continue; |
2488 | } |
2489 | if ((mask & OMP_CLAUSE_FILTER) |
2490 | && (m = gfc_match_dupl_check (!c->filter, "filter", true, |
2491 | &c->filter)) != MATCH_NO) |
2492 | { |
2493 | if (m == MATCH_ERROR) |
2494 | goto error; |
2495 | continue; |
2496 | } |
2497 | if ((mask & OMP_CLAUSE_FINAL) |
2498 | && (m = gfc_match_dupl_check (!c->final_expr, "final", true, |
2499 | &c->final_expr)) != MATCH_NO) |
2500 | { |
2501 | if (m == MATCH_ERROR) |
2502 | goto error; |
2503 | continue; |
2504 | } |
2505 | if ((mask & OMP_CLAUSE_FINALIZE) |
2506 | && (m = gfc_match_dupl_check (!c->finalize, "finalize")) |
2507 | != MATCH_NO) |
2508 | { |
2509 | if (m == MATCH_ERROR) |
2510 | goto error; |
2511 | c->finalize = true; |
2512 | needs_space = true; |
2513 | continue; |
2514 | } |
2515 | if ((mask & OMP_CLAUSE_FIRSTPRIVATE) |
2516 | && gfc_match_omp_variable_list ("firstprivate (", |
2517 | &c->lists[OMP_LIST_FIRSTPRIVATE], |
2518 | true) == MATCH_YES) |
2519 | continue; |
2520 | if ((mask & OMP_CLAUSE_FROM) |
2521 | && (gfc_match_omp_variable_list ("from (", |
2522 | &c->lists[OMP_LIST_FROM], false, |
2523 | NULL__null, &head, true, true) |
2524 | == MATCH_YES)) |
2525 | continue; |
2526 | break; |
2527 | case 'g': |
2528 | if ((mask & OMP_CLAUSE_GANG) |
2529 | && (m = gfc_match_dupl_check (!c->gang, "gang")) != MATCH_NO) |
2530 | { |
2531 | if (m == MATCH_ERROR) |
2532 | goto error; |
2533 | c->gang = true; |
2534 | m = match_oacc_clause_gwv (c, GOMP_DIM_GANG0); |
2535 | if (m == MATCH_ERROR) |
2536 | { |
2537 | gfc_current_locus = old_loc; |
2538 | break; |
2539 | } |
2540 | else if (m == MATCH_NO) |
2541 | needs_space = true; |
2542 | continue; |
2543 | } |
2544 | if ((mask & OMP_CLAUSE_GRAINSIZE) |
2545 | && (m = gfc_match_dupl_check (!c->grainsize, "grainsize", true)) |
2546 | != MATCH_NO) |
2547 | { |
2548 | if (m == MATCH_ERROR) |
2549 | goto error; |
2550 | if (gfc_match ("strict : ") == MATCH_YES) |
2551 | c->grainsize_strict = true; |
2552 | if (gfc_match (" %e )", &c->grainsize) != MATCH_YES) |
2553 | goto error; |
2554 | continue; |
2555 | } |
2556 | break; |
2557 | case 'h': |
2558 | if ((mask & OMP_CLAUSE_HAS_DEVICE_ADDR) |
2559 | && gfc_match_omp_variable_list |
2560 | ("has_device_addr (", &c->lists[OMP_LIST_HAS_DEVICE_ADDR], |
2561 | false, NULL__null, NULL__null, true) == MATCH_YES) |
2562 | continue; |
2563 | if ((mask & OMP_CLAUSE_HINT) |
2564 | && (m = gfc_match_dupl_check (!c->hint, "hint", true, &c->hint)) |
2565 | != MATCH_NO) |
2566 | { |
2567 | if (m == MATCH_ERROR) |
2568 | goto error; |
2569 | continue; |
2570 | } |
2571 | if ((mask & OMP_CLAUSE_ASSUMPTIONS) |
2572 | && gfc_match ("holds ( ") == MATCH_YES) |
2573 | { |
2574 | gfc_expr *e; |
2575 | if (gfc_match ("%e )", &e) != MATCH_YES) |
2576 | goto error; |
2577 | if (c->assume == NULL__null) |
2578 | c->assume = gfc_get_omp_assumptions ()((gfc_omp_assumptions *) xcalloc (1, sizeof (gfc_omp_assumptions ))); |
2579 | gfc_expr_list *el = XCNEW (gfc_expr_list)((gfc_expr_list *) xcalloc (1, sizeof (gfc_expr_list))); |
2580 | el->expr = e; |
2581 | el->next = c->assume->holds; |
2582 | c->assume->holds = el; |
2583 | continue; |
2584 | } |
2585 | if ((mask & OMP_CLAUSE_HOST_SELF) |
2586 | && gfc_match ("host ( ") == MATCH_YES |
2587 | && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP], |
2588 | OMP_MAP_FORCE_FROM, true, |
2589 | allow_derived)) |
2590 | continue; |
2591 | break; |
2592 | case 'i': |
2593 | if ((mask & OMP_CLAUSE_IF_PRESENT) |
2594 | && (m = gfc_match_dupl_check (!c->if_present, "if_present")) |
2595 | != MATCH_NO) |
2596 | { |
2597 | if (m == MATCH_ERROR) |
2598 | goto error; |
2599 | c->if_present = true; |
2600 | needs_space = true; |
2601 | continue; |
2602 | } |
2603 | if ((mask & OMP_CLAUSE_IF) |
2604 | && (m = gfc_match_dupl_check (!c->if_expr, "if", true)) |
2605 | != MATCH_NO) |
2606 | { |
2607 | if (m == MATCH_ERROR) |
2608 | goto error; |
2609 | if (!openacc) |
2610 | { |
2611 | /* This should match the enum gfc_omp_if_kind order. */ |
2612 | static const char *ifs[OMP_IF_LAST] = { |
2613 | "cancel : %e )", |
2614 | "parallel : %e )", |
2615 | "simd : %e )", |
2616 | "task : %e )", |
2617 | "taskloop : %e )", |
2618 | "target : %e )", |
2619 | "target data : %e )", |
2620 | "target update : %e )", |
2621 | "target enter data : %e )", |
2622 | "target exit data : %e )" }; |
2623 | int i; |
2624 | for (i = 0; i < OMP_IF_LAST; i++) |
2625 | if (c->if_exprs[i] == NULL__null |
2626 | && gfc_match (ifs[i], &c->if_exprs[i]) == MATCH_YES) |
2627 | break; |
2628 | if (i < OMP_IF_LAST) |
2629 | continue; |
2630 | } |
2631 | if (gfc_match (" %e )", &c->if_expr) == MATCH_YES) |
2632 | continue; |
2633 | goto error; |
2634 | } |
2635 | if ((mask & OMP_CLAUSE_IN_REDUCTION) |
2636 | && gfc_match_omp_clause_reduction (pc, c, openacc, allow_derived, |
2637 | openmp_target) == MATCH_YES) |
2638 | continue; |
2639 | if ((mask & OMP_CLAUSE_INBRANCH) |
2640 | && (m = gfc_match_dupl_check (!c->inbranch && !c->notinbranch, |
2641 | "inbranch")) != MATCH_NO) |
2642 | { |
2643 | if (m == MATCH_ERROR) |
2644 | goto error; |
2645 | c->inbranch = needs_space = true; |
2646 | continue; |
2647 | } |
2648 | if ((mask & OMP_CLAUSE_INDEPENDENT) |
2649 | && (m = gfc_match_dupl_check (!c->independent, "independent")) |
2650 | != MATCH_NO) |
2651 | { |
2652 | if (m == MATCH_ERROR) |
2653 | goto error; |
2654 | c->independent = true; |
2655 | needs_space = true; |
2656 | continue; |
2657 | } |
2658 | if ((mask & OMP_CLAUSE_IS_DEVICE_PTR) |
2659 | && gfc_match_omp_variable_list |
2660 | ("is_device_ptr (", |
2661 | &c->lists[OMP_LIST_IS_DEVICE_PTR], false) == MATCH_YES) |
2662 | continue; |
2663 | break; |
2664 | case 'l': |
2665 | if ((mask & OMP_CLAUSE_LASTPRIVATE) |
2666 | && gfc_match ("lastprivate ( ") == MATCH_YES) |
2667 | { |
2668 | bool conditional = gfc_match ("conditional : ") == MATCH_YES; |
2669 | head = NULL__null; |
2670 | if (gfc_match_omp_variable_list ("", |
2671 | &c->lists[OMP_LIST_LASTPRIVATE], |
2672 | false, NULL__null, &head) == MATCH_YES) |
2673 | { |
2674 | gfc_omp_namelist *n; |
2675 | for (n = *head; n; n = n->next) |
2676 | n->u.lastprivate_conditional = conditional; |
2677 | continue; |
2678 | } |
2679 | gfc_current_locus = old_loc; |
2680 | break; |
2681 | } |
2682 | end_colon = false; |
2683 | head = NULL__null; |
2684 | if ((mask & OMP_CLAUSE_LINEAR) |
2685 | && gfc_match ("linear (") == MATCH_YES) |
2686 | { |
2687 | bool old_linear_modifier = false; |
2688 | gfc_omp_linear_op linear_op = OMP_LINEAR_DEFAULT; |
2689 | gfc_expr *step = NULL__null; |
2690 | |
2691 | if (gfc_match_omp_variable_list (" ref (", |
2692 | &c->lists[OMP_LIST_LINEAR], |
2693 | false, NULL__null, &head) |
2694 | == MATCH_YES) |
2695 | { |
2696 | linear_op = OMP_LINEAR_REF; |
2697 | old_linear_modifier = true; |
2698 | } |
2699 | else if (gfc_match_omp_variable_list (" val (", |
2700 | &c->lists[OMP_LIST_LINEAR], |
2701 | false, NULL__null, &head) |
2702 | == MATCH_YES) |
2703 | { |
2704 | linear_op = OMP_LINEAR_VAL; |
2705 | old_linear_modifier = true; |
2706 | } |
2707 | else if (gfc_match_omp_variable_list (" uval (", |
2708 | &c->lists[OMP_LIST_LINEAR], |
2709 | false, NULL__null, &head) |
2710 | == MATCH_YES) |
2711 | { |
2712 | linear_op = OMP_LINEAR_UVAL; |
2713 | old_linear_modifier = true; |
2714 | } |
2715 | else if (gfc_match_omp_variable_list ("", |
2716 | &c->lists[OMP_LIST_LINEAR], |
2717 | false, &end_colon, &head) |
2718 | == MATCH_YES) |
2719 | linear_op = OMP_LINEAR_DEFAULT; |
2720 | else |
2721 | { |
2722 | gfc_current_locus = old_loc; |
2723 | break; |
2724 | } |
2725 | if (linear_op != OMP_LINEAR_DEFAULT) |
2726 | { |
2727 | if (gfc_match (" :") == MATCH_YES) |
2728 | end_colon = true; |
2729 | else if (gfc_match (" )") != MATCH_YES) |
2730 | { |
2731 | gfc_free_omp_namelist (*head, false, false); |
2732 | gfc_current_locus = old_loc; |
2733 | *head = NULL__null; |
2734 | break; |
2735 | } |
2736 | } |
2737 | gfc_gobble_whitespace (); |
2738 | if (old_linear_modifier && end_colon) |
2739 | { |
2740 | if (gfc_match (" %e )", &step) != MATCH_YES) |
2741 | { |
2742 | gfc_free_omp_namelist (*head, false, false); |
2743 | gfc_current_locus = old_loc; |
2744 | *head = NULL__null; |
2745 | goto error; |
2746 | } |
2747 | } |
2748 | else if (end_colon) |
2749 | { |
2750 | bool has_error = false; |
2751 | bool has_modifiers = false; |
2752 | bool has_step = false; |
2753 | bool duplicate_step = false; |
2754 | bool duplicate_mod = false; |
2755 | while (true) |
2756 | { |
2757 | old_loc = gfc_current_locus; |
2758 | bool close_paren = gfc_match ("val )") == MATCH_YES; |
2759 | if (close_paren || gfc_match ("val , ") == MATCH_YES) |
2760 | { |
2761 | if (linear_op != OMP_LINEAR_DEFAULT) |
2762 | { |
2763 | duplicate_mod = true; |
2764 | break; |
2765 | } |
2766 | linear_op = OMP_LINEAR_VAL; |
2767 | has_modifiers = true; |
2768 | if (close_paren) |
2769 | break; |
2770 | continue; |
2771 | } |
2772 | close_paren = gfc_match ("uval )") == MATCH_YES; |
2773 | if (close_paren || gfc_match ("uval , ") == MATCH_YES) |
2774 | { |
2775 | if (linear_op != OMP_LINEAR_DEFAULT) |
2776 | { |
2777 | duplicate_mod = true; |
2778 | break; |
2779 | } |
2780 | linear_op = OMP_LINEAR_UVAL; |
2781 | has_modifiers = true; |
2782 | if (close_paren) |
2783 | break; |
2784 | continue; |
2785 | } |
2786 | close_paren = gfc_match ("ref )") == MATCH_YES; |
2787 | if (close_paren || gfc_match ("ref , ") == MATCH_YES) |
2788 | { |
2789 | if (linear_op != OMP_LINEAR_DEFAULT) |
2790 | { |
2791 | duplicate_mod = true; |
2792 | break; |
2793 | } |
2794 | linear_op = OMP_LINEAR_REF; |
2795 | has_modifiers = true; |
2796 | if (close_paren) |
2797 | break; |
2798 | continue; |
2799 | } |
2800 | close_paren = (gfc_match ("step ( %e ) )", &step) |
2801 | == MATCH_YES); |
2802 | if (close_paren |
2803 | || gfc_match ("step ( %e ) , ", &step) == MATCH_YES) |
2804 | { |
2805 | if (has_step) |
2806 | { |
2807 | duplicate_step = true; |
2808 | break; |
2809 | } |
2810 | has_modifiers = has_step = true; |
2811 | if (close_paren) |
2812 | break; |
2813 | continue; |
2814 | } |
2815 | if (!has_modifiers |
2816 | && gfc_match ("%e )", &step) == MATCH_YES) |
2817 | { |
2818 | if ((step->expr_type == EXPR_FUNCTION |
2819 | || step->expr_type == EXPR_VARIABLE) |
2820 | && strcmp (step->symtree->name, "step") == 0) |
2821 | { |
2822 | gfc_current_locus = old_loc; |
2823 | gfc_match ("step ("); |
2824 | has_error = true; |
2825 | } |
2826 | break; |
2827 | } |
2828 | has_error = true; |
2829 | break; |
2830 | } |
2831 | if (duplicate_mod || duplicate_step) |
2832 | { |
2833 | gfc_error ("Multiple %qs modifiers specified at %C", |
2834 | duplicate_mod ? "linear" : "step"); |
2835 | has_error = true; |
2836 | } |
2837 | if (has_error) |
2838 | { |
2839 | gfc_free_omp_namelist (*head, false, false); |
2840 | *head = NULL__null; |
2841 | goto error; |
2842 | } |
2843 | } |
2844 | if (step == NULL__null) |
2845 | { |
2846 | step = gfc_get_constant_expr (BT_INTEGER, |
2847 | gfc_default_integer_kind, |
2848 | &old_loc); |
2849 | mpz_set_si__gmpz_set_si (step->value.integer, 1); |
2850 | } |
2851 | (*head)->expr = step; |
2852 | if (linear_op != OMP_LINEAR_DEFAULT || old_linear_modifier) |
2853 | for (gfc_omp_namelist *n = *head; n; n = n->next) |
2854 | { |
2855 | n->u.linear.op = linear_op; |
2856 | n->u.linear.old_modifier = old_linear_modifier; |
2857 | } |
2858 | continue; |
2859 | } |
2860 | if ((mask & OMP_CLAUSE_LINK) |
2861 | && openacc |
2862 | && (gfc_match_oacc_clause_link ("link (", |
2863 | &c->lists[OMP_LIST_LINK]) |
2864 | == MATCH_YES)) |
2865 | continue; |
2866 | else if ((mask & OMP_CLAUSE_LINK) |
2867 | && !openacc |
2868 | && (gfc_match_omp_to_link ("link (", |
2869 | &c->lists[OMP_LIST_LINK]) |
2870 | == MATCH_YES)) |
2871 | continue; |
2872 | break; |
2873 | case 'm': |
2874 | if ((mask & OMP_CLAUSE_MAP) |
2875 | && gfc_match ("map ( ") == MATCH_YES) |
2876 | { |
2877 | locus old_loc2 = gfc_current_locus; |
2878 | int always_modifier = 0; |
2879 | int close_modifier = 0; |
2880 | locus second_always_locus = old_loc2; |
2881 | locus second_close_locus = old_loc2; |
2882 | |
2883 | for (;;) |
2884 | { |
2885 | locus current_locus = gfc_current_locus; |
2886 | if (gfc_match ("always ") == MATCH_YES) |
2887 | { |
2888 | if (always_modifier++ == 1) |
2889 | second_always_locus = current_locus; |
2890 | } |
2891 | else if (gfc_match ("close ") == MATCH_YES) |
2892 | { |
2893 | if (close_modifier++ == 1) |
2894 | second_close_locus = current_locus; |
2895 | } |
2896 | else |
2897 | break; |
2898 | gfc_match (", "); |
2899 | } |
2900 | |
2901 | gfc_omp_map_op map_op = OMP_MAP_TOFROM; |
2902 | if (gfc_match ("alloc : ") == MATCH_YES) |
2903 | map_op = OMP_MAP_ALLOC; |
2904 | else if (gfc_match ("tofrom : ") == MATCH_YES) |
2905 | map_op = always_modifier ? OMP_MAP_ALWAYS_TOFROM : OMP_MAP_TOFROM; |
2906 | else if (gfc_match ("to : ") == MATCH_YES) |
2907 | map_op = always_modifier ? OMP_MAP_ALWAYS_TO : OMP_MAP_TO; |
2908 | else if (gfc_match ("from : ") == MATCH_YES) |
2909 | map_op = always_modifier ? OMP_MAP_ALWAYS_FROM : OMP_MAP_FROM; |
2910 | else if (gfc_match ("release : ") == MATCH_YES) |
2911 | map_op = OMP_MAP_RELEASE; |
2912 | else if (gfc_match ("delete : ") == MATCH_YES) |
2913 | map_op = OMP_MAP_DELETE; |
2914 | else |
2915 | { |
2916 | gfc_current_locus = old_loc2; |
2917 | always_modifier = 0; |
2918 | close_modifier = 0; |
2919 | } |
2920 | |
2921 | if (always_modifier > 1) |
2922 | { |
2923 | gfc_error ("too many %<always%> modifiers at %L", |
2924 | &second_always_locus); |
2925 | break; |
2926 | } |
2927 | if (close_modifier > 1) |
2928 | { |
2929 | gfc_error ("too many %<close%> modifiers at %L", |
2930 | &second_close_locus); |
2931 | break; |
2932 | } |
2933 | |
2934 | head = NULL__null; |
2935 | if (gfc_match_omp_variable_list ("", &c->lists[OMP_LIST_MAP], |
2936 | false, NULL__null, &head, |
2937 | true, true) == MATCH_YES) |
2938 | { |
2939 | gfc_omp_namelist *n; |
2940 | for (n = *head; n; n = n->next) |
2941 | n->u.map_op = map_op; |
2942 | continue; |
2943 | } |
2944 | gfc_current_locus = old_loc; |
2945 | break; |
2946 | } |
2947 | if ((mask & OMP_CLAUSE_MERGEABLE) |
2948 | && (m = gfc_match_dupl_check (!c->mergeable, "mergeable")) |
2949 | != MATCH_NO) |
2950 | { |
2951 | if (m == MATCH_ERROR) |
2952 | goto error; |
2953 | c->mergeable = needs_space = true; |
2954 | continue; |
2955 | } |
2956 | if ((mask & OMP_CLAUSE_MESSAGE) |
2957 | && (m = gfc_match_dupl_check (!c->message, "message", true, |
2958 | &c->message)) != MATCH_NO) |
2959 | { |
2960 | if (m == MATCH_ERROR) |
2961 | goto error; |
2962 | continue; |
2963 | } |
2964 | break; |
2965 | case 'n': |
2966 | if ((mask & OMP_CLAUSE_NO_CREATE) |
2967 | && gfc_match ("no_create ( ") == MATCH_YES |
2968 | && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP], |
2969 | OMP_MAP_IF_PRESENT, true, |
2970 | allow_derived)) |
2971 | continue; |
2972 | if ((mask & OMP_CLAUSE_ASSUMPTIONS) |
2973 | && (m = gfc_match_dupl_check (!c->assume |
2974 | || !c->assume->no_openmp_routines, |
2975 | "no_openmp_routines")) == MATCH_YES) |
2976 | { |
2977 | if (m == MATCH_ERROR) |
2978 | goto error; |
2979 | if (c->assume == NULL__null) |
2980 | c->assume = gfc_get_omp_assumptions ()((gfc_omp_assumptions *) xcalloc (1, sizeof (gfc_omp_assumptions ))); |
2981 | c->assume->no_openmp_routines = needs_space = true; |
2982 | continue; |
2983 | } |
2984 | if ((mask & OMP_CLAUSE_ASSUMPTIONS) |
2985 | && (m = gfc_match_dupl_check (!c->assume || !c->assume->no_openmp, |
2986 | "no_openmp")) == MATCH_YES) |
2987 | { |
2988 | if (m == MATCH_ERROR) |
2989 | goto error; |
2990 | if (c->assume == NULL__null) |
2991 | c->assume = gfc_get_omp_assumptions ()((gfc_omp_assumptions *) xcalloc (1, sizeof (gfc_omp_assumptions ))); |
2992 | c->assume->no_openmp = needs_space = true; |
2993 | continue; |
2994 | } |
2995 | if ((mask & OMP_CLAUSE_ASSUMPTIONS) |
2996 | && (m = gfc_match_dupl_check (!c->assume |
2997 | || !c->assume->no_parallelism, |
2998 | "no_parallelism")) == MATCH_YES) |
2999 | { |
3000 | if (m == MATCH_ERROR) |
3001 | goto error; |
3002 | if (c->assume == NULL__null) |
3003 | c->assume = gfc_get_omp_assumptions ()((gfc_omp_assumptions *) xcalloc (1, sizeof (gfc_omp_assumptions ))); |
3004 | c->assume->no_parallelism = needs_space = true; |
3005 | continue; |
3006 | } |
3007 | if ((mask & OMP_CLAUSE_NOGROUP) |
3008 | && (m = gfc_match_dupl_check (!c->nogroup, "nogroup")) |
3009 | != MATCH_NO) |
3010 | { |
3011 | if (m == MATCH_ERROR) |
3012 | goto error; |
3013 | c->nogroup = needs_space = true; |
3014 | continue; |
3015 | } |
3016 | if ((mask & OMP_CLAUSE_NOHOST) |
3017 | && (m = gfc_match_dupl_check (!c->nohost, "nohost")) != MATCH_NO) |
3018 | { |
3019 | if (m == MATCH_ERROR) |
3020 | goto error; |
3021 | c->nohost = needs_space = true; |
3022 | continue; |
3023 | } |
3024 | if ((mask & OMP_CLAUSE_NOTEMPORAL) |
3025 | && gfc_match_omp_variable_list ("nontemporal (", |
3026 | &c->lists[OMP_LIST_NONTEMPORAL], |
3027 | true) == MATCH_YES) |
3028 | continue; |
3029 | if ((mask & OMP_CLAUSE_NOTINBRANCH) |
3030 | && (m = gfc_match_dupl_check (!c->notinbranch && !c->inbranch, |
3031 | "notinbranch")) != MATCH_NO) |
3032 | { |
3033 | if (m == MATCH_ERROR) |
3034 | goto error; |
3035 | c->notinbranch = needs_space = true; |
3036 | continue; |
3037 | } |
3038 | if ((mask & OMP_CLAUSE_NOWAIT) |
3039 | && (m = gfc_match_dupl_check (!c->nowait, "nowait")) != MATCH_NO) |
3040 | { |
3041 | if (m == MATCH_ERROR) |
3042 | goto error; |
3043 | c->nowait = needs_space = true; |
3044 | continue; |
3045 | } |
3046 | if ((mask & OMP_CLAUSE_NUM_GANGS) |
3047 | && (m = gfc_match_dupl_check (!c->num_gangs_expr, "num_gangs", |
3048 | true)) != MATCH_NO) |
3049 | { |
3050 | if (m == MATCH_ERROR) |
3051 | goto error; |
3052 | if (gfc_match (" %e )", &c->num_gangs_expr) != MATCH_YES) |
3053 | goto error; |
3054 | continue; |
3055 | } |
3056 | if ((mask & OMP_CLAUSE_NUM_TASKS) |
3057 | && (m = gfc_match_dupl_check (!c->num_tasks, "num_tasks", true)) |
3058 | != MATCH_NO) |
3059 | { |
3060 | if (m == MATCH_ERROR) |
3061 | goto error; |
3062 | if (gfc_match ("strict : ") == MATCH_YES) |
3063 | c->num_tasks_strict = true; |
3064 | if (gfc_match (" %e )", &c->num_tasks) != MATCH_YES) |
3065 | goto error; |
3066 | continue; |
3067 | } |
3068 | if ((mask & OMP_CLAUSE_NUM_TEAMS) |
3069 | && (m = gfc_match_dupl_check (!c->num_teams_upper, "num_teams", |
3070 | true)) != MATCH_NO) |
3071 | { |
3072 | if (m == MATCH_ERROR) |
3073 | goto error; |
3074 | if (gfc_match ("%e ", &c->num_teams_upper) != MATCH_YES) |
3075 | goto error; |
3076 | if (gfc_peek_ascii_char () == ':') |
3077 | { |
3078 | c->num_teams_lower = c->num_teams_upper; |
3079 | c->num_teams_upper = NULL__null; |
3080 | if (gfc_match (": %e ", &c->num_teams_upper) != MATCH_YES) |
3081 | goto error; |
3082 | } |
3083 | if (gfc_match (") ") != MATCH_YES) |
3084 | goto error; |
3085 | continue; |
3086 | } |
3087 | if ((mask & OMP_CLAUSE_NUM_THREADS) |
3088 | && (m = gfc_match_dupl_check (!c->num_threads, "num_threads", true, |
3089 | &c->num_threads)) != MATCH_NO) |
3090 | { |
3091 | if (m == MATCH_ERROR) |
3092 | goto error; |
3093 | continue; |
3094 | } |
3095 | if ((mask & OMP_CLAUSE_NUM_WORKERS) |
3096 | && (m = gfc_match_dupl_check (!c->num_workers_expr, "num_workers", |
3097 | true, &c->num_workers_expr)) |
3098 | != MATCH_NO) |
3099 | { |
3100 | if (m == MATCH_ERROR) |
3101 | goto error; |
3102 | continue; |
3103 | } |
3104 | break; |
3105 | case 'o': |
3106 | if ((mask & OMP_CLAUSE_ORDER) |
3107 | && (m = gfc_match_dupl_check (!c->order_concurrent, "order (")) |
3108 | != MATCH_NO) |
3109 | { |
3110 | if (m == MATCH_ERROR) |
3111 | goto error; |
3112 | if (gfc_match (" reproducible : concurrent )") == MATCH_YES) |
3113 | c->order_reproducible = true; |
3114 | else if (gfc_match (" concurrent )") == MATCH_YES) |
3115 | ; |
3116 | else if (gfc_match (" unconstrained : concurrent )") == MATCH_YES) |
3117 | c->order_unconstrained = true; |
3118 | else |
3119 | { |
3120 | gfc_error ("Expected ORDER(CONCURRENT) at %C " |
3121 | "with optional %<reproducible%> or " |
3122 | "%<unconstrained%> modifier"); |
3123 | goto error; |
3124 | } |
3125 | c->order_concurrent = true; |
3126 | continue; |
3127 | } |
3128 | if ((mask & OMP_CLAUSE_ORDERED) |
3129 | && (m = gfc_match_dupl_check (!c->ordered, "ordered")) |
3130 | != MATCH_NO) |
3131 | { |
3132 | if (m == MATCH_ERROR) |
3133 | goto error; |
3134 | gfc_expr *cexpr = NULL__null; |
3135 | m = gfc_match (" ( %e )", &cexpr); |
3136 | |
3137 | c->ordered = true; |
3138 | if (m == MATCH_YES) |
3139 | { |
3140 | int ordered = 0; |
3141 | if (gfc_extract_int (cexpr, &ordered, -1)) |
3142 | ordered = 0; |
3143 | else if (ordered <= 0) |
3144 | { |
3145 | gfc_error_now ("ORDERED clause argument not" |
3146 | " constant positive integer at %C"); |
3147 | ordered = 0; |
3148 | } |
3149 | c->orderedc = ordered; |
3150 | gfc_free_expr (cexpr); |
3151 | continue; |
3152 | } |
3153 | |
3154 | needs_space = true; |
3155 | continue; |
3156 | } |
3157 | break; |
3158 | case 'p': |
3159 | if ((mask & OMP_CLAUSE_COPY) |
3160 | && gfc_match ("pcopy ( ") == MATCH_YES |
3161 | && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP], |
3162 | OMP_MAP_TOFROM, true, allow_derived)) |
3163 | continue; |
3164 | if ((mask & OMP_CLAUSE_COPYIN) |
3165 | && gfc_match ("pcopyin ( ") == MATCH_YES |
3166 | && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP], |
3167 | OMP_MAP_TO, true, allow_derived)) |
3168 | continue; |
3169 | if ((mask & OMP_CLAUSE_COPYOUT) |
3170 | && gfc_match ("pcopyout ( ") == MATCH_YES |
3171 | && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP], |
3172 | OMP_MAP_FROM, true, allow_derived)) |
3173 | continue; |
3174 | if ((mask & OMP_CLAUSE_CREATE) |
3175 | && gfc_match ("pcreate ( ") == MATCH_YES |
3176 | && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP], |
3177 | OMP_MAP_ALLOC, true, allow_derived)) |
3178 | continue; |
3179 | if ((mask & OMP_CLAUSE_PRESENT) |
3180 | && gfc_match ("present ( ") == MATCH_YES |
3181 | && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP], |
3182 | OMP_MAP_FORCE_PRESENT, false, |
3183 | allow_derived)) |
3184 | continue; |
3185 | if ((mask & OMP_CLAUSE_COPY) |
3186 | && gfc_match ("present_or_copy ( ") == MATCH_YES |
3187 | && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP], |
3188 | OMP_MAP_TOFROM, true, |
3189 | allow_derived)) |
3190 | continue; |
3191 | if ((mask & OMP_CLAUSE_COPYIN) |
3192 | && gfc_match ("present_or_copyin ( ") == MATCH_YES |
3193 | && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP], |
3194 | OMP_MAP_TO, true, allow_derived)) |
3195 | continue; |
3196 | if ((mask & OMP_CLAUSE_COPYOUT) |
3197 | && gfc_match ("present_or_copyout ( ") == MATCH_YES |
3198 | && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP], |
3199 | OMP_MAP_FROM, true, allow_derived)) |
3200 | continue; |
3201 | if ((mask & OMP_CLAUSE_CREATE) |
3202 | && gfc_match ("present_or_create ( ") == MATCH_YES |
3203 | && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP], |
3204 | OMP_MAP_ALLOC, true, allow_derived)) |
3205 | continue; |
3206 | if ((mask & OMP_CLAUSE_PRIORITY) |
3207 | && (m = gfc_match_dupl_check (!c->priority, "priority", true, |
3208 | &c->priority)) != MATCH_NO) |
3209 | { |
3210 | if (m == MATCH_ERROR) |
3211 | goto error; |
3212 | continue; |
3213 | } |
3214 | if ((mask & OMP_CLAUSE_PRIVATE) |
3215 | && gfc_match_omp_variable_list ("private (", |
3216 | &c->lists[OMP_LIST_PRIVATE], |
3217 | true) == MATCH_YES) |
3218 | continue; |
3219 | if ((mask & OMP_CLAUSE_PROC_BIND) |
3220 | && (m = gfc_match_dupl_check ((c->proc_bind |
3221 | == OMP_PROC_BIND_UNKNOWN), |
3222 | "proc_bind", true)) != MATCH_NO) |
3223 | { |
3224 | if (m == MATCH_ERROR) |
3225 | goto error; |
3226 | if (gfc_match ("primary )") == MATCH_YES) |
3227 | c->proc_bind = OMP_PROC_BIND_PRIMARY; |
3228 | else if (gfc_match ("master )") == MATCH_YES) |
3229 | c->proc_bind = OMP_PROC_BIND_MASTER; |
3230 | else if (gfc_match ("spread )") == MATCH_YES) |
3231 | c->proc_bind = OMP_PROC_BIND_SPREAD; |
3232 | else if (gfc_match ("close )") == MATCH_YES) |
3233 | c->proc_bind = OMP_PROC_BIND_CLOSE; |
3234 | else |
3235 | goto error; |
3236 | continue; |
3237 | } |
3238 | break; |
3239 | case 'r': |
3240 | if ((mask & OMP_CLAUSE_ATOMIC) |
3241 | && (m = gfc_match_dupl_atomic ((c->atomic_op |
3242 | == GFC_OMP_ATOMIC_UNSET), |
3243 | "read")) != MATCH_NO) |
3244 | { |
3245 | if (m == MATCH_ERROR) |
3246 | goto error; |
3247 | c->atomic_op = GFC_OMP_ATOMIC_READ; |
3248 | needs_space = true; |
3249 | continue; |
3250 | } |
3251 | if ((mask & OMP_CLAUSE_REDUCTION) |
3252 | && gfc_match_omp_clause_reduction (pc, c, openacc, |
3253 | allow_derived) == MATCH_YES) |
3254 | continue; |
3255 | if ((mask & OMP_CLAUSE_MEMORDER) |
3256 | && (m = gfc_match_dupl_memorder ((c->memorder |
3257 | == OMP_MEMORDER_UNSET), |
3258 | "relaxed")) != MATCH_NO) |
3259 | { |
3260 | if (m == MATCH_ERROR) |
3261 | goto error; |
3262 | c->memorder = OMP_MEMORDER_RELAXED; |
3263 | needs_space = true; |
3264 | continue; |
3265 | } |
3266 | if ((mask & OMP_CLAUSE_MEMORDER) |
3267 | && (m = gfc_match_dupl_memorder ((c->memorder |
3268 | == OMP_MEMORDER_UNSET), |
3269 | "release")) != MATCH_NO) |
3270 | { |
3271 | if (m == MATCH_ERROR) |
3272 | goto error; |
3273 | c->memorder = OMP_MEMORDER_RELEASE; |
3274 | needs_space = true; |
3275 | continue; |
3276 | } |
3277 | break; |
3278 | case 's': |
3279 | if ((mask & OMP_CLAUSE_SAFELEN) |
3280 | && (m = gfc_match_dupl_check (!c->safelen_expr, "safelen", |
3281 | true, &c->safelen_expr)) |
3282 | != MATCH_NO) |
3283 | { |
3284 | if (m == MATCH_ERROR) |
3285 | goto error; |
3286 | continue; |
3287 | } |
3288 | if ((mask & OMP_CLAUSE_SCHEDULE) |
3289 | && (m = gfc_match_dupl_check (c->sched_kind == OMP_SCHED_NONE, |
3290 | "schedule", true)) != MATCH_NO) |
3291 | { |
3292 | if (m == MATCH_ERROR) |
3293 | goto error; |
3294 | int nmodifiers = 0; |
3295 | locus old_loc2 = gfc_current_locus; |
3296 | do |
3297 | { |
3298 | if (gfc_match ("simd") == MATCH_YES) |
3299 | { |
3300 | c->sched_simd = true; |
3301 | nmodifiers++; |
3302 | } |
3303 | else if (gfc_match ("monotonic") == MATCH_YES) |
3304 | { |
3305 | c->sched_monotonic = true; |
3306 | nmodifiers++; |
3307 | } |
3308 | else if (gfc_match ("nonmonotonic") == MATCH_YES) |
3309 | { |
3310 | c->sched_nonmonotonic = true; |
3311 | nmodifiers++; |
3312 | } |
3313 | else |
3314 | { |
3315 | if (nmodifiers) |
3316 | gfc_current_locus = old_loc2; |
3317 | break; |
3318 | } |
3319 | if (nmodifiers == 1 |
3320 | && gfc_match (" , ") == MATCH_YES) |
3321 | continue; |
3322 | else if (gfc_match (" : ") == MATCH_YES) |
3323 | break; |
3324 | gfc_current_locus = old_loc2; |
3325 | break; |
3326 | } |
3327 | while (1); |
3328 | if (gfc_match ("static") == MATCH_YES) |
3329 | c->sched_kind = OMP_SCHED_STATIC; |
3330 | else if (gfc_match ("dynamic") == MATCH_YES) |
3331 | c->sched_kind = OMP_SCHED_DYNAMIC; |
3332 | else if (gfc_match ("guided") == MATCH_YES) |
3333 | c->sched_kind = OMP_SCHED_GUIDED; |
3334 | else if (gfc_match ("runtime") == MATCH_YES) |
3335 | c->sched_kind = OMP_SCHED_RUNTIME; |
3336 | else if (gfc_match ("auto") == MATCH_YES) |
3337 | c->sched_kind = OMP_SCHED_AUTO; |
3338 | if (c->sched_kind != OMP_SCHED_NONE) |
3339 | { |
3340 | m = MATCH_NO; |
3341 | if (c->sched_kind != OMP_SCHED_RUNTIME |
3342 | && c->sched_kind != OMP_SCHED_AUTO) |
3343 | m = gfc_match (" , %e )", &c->chunk_size); |
3344 | if (m != MATCH_YES) |
3345 | m = gfc_match_char (')'); |
3346 | if (m != MATCH_YES) |
3347 | c->sched_kind = OMP_SCHED_NONE; |
3348 | } |
3349 | if (c->sched_kind != OMP_SCHED_NONE) |
3350 | continue; |
3351 | else |
3352 | gfc_current_locus = old_loc; |
3353 | } |
3354 | if ((mask & OMP_CLAUSE_HOST_SELF) |
3355 | && gfc_match ("self ( ") == MATCH_YES |
3356 | && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP], |
3357 | OMP_MAP_FORCE_FROM, true, |
3358 | allow_derived)) |
3359 | continue; |
3360 | if ((mask & OMP_CLAUSE_SEQ) |
3361 | && (m = gfc_match_dupl_check (!c->seq, "seq")) != MATCH_NO) |
3362 | { |
3363 | if (m == MATCH_ERROR) |
3364 | goto error; |
3365 | c->seq = true; |
3366 | needs_space = true; |
3367 | continue; |
3368 | } |
3369 | if ((mask & OMP_CLAUSE_MEMORDER) |
3370 | && (m = gfc_match_dupl_memorder ((c->memorder |
3371 | == OMP_MEMORDER_UNSET), |
3372 | "seq_cst")) != MATCH_NO) |
3373 | { |
3374 | if (m == MATCH_ERROR) |
3375 | goto error; |
3376 | c->memorder = OMP_MEMORDER_SEQ_CST; |
3377 | needs_space = true; |
3378 | continue; |
3379 | } |
3380 | if ((mask & OMP_CLAUSE_SHARED) |
3381 | && gfc_match_omp_variable_list ("shared (", |
3382 | &c->lists[OMP_LIST_SHARED], |
3383 | true) == MATCH_YES) |
3384 | continue; |
3385 | if ((mask & OMP_CLAUSE_SIMDLEN) |
3386 | && (m = gfc_match_dupl_check (!c->simdlen_expr, "simdlen", true, |
3387 | &c->simdlen_expr)) != MATCH_NO) |
3388 | { |
3389 | if (m == MATCH_ERROR) |
3390 | goto error; |
3391 | continue; |
3392 | } |
3393 | if ((mask & OMP_CLAUSE_SIMD) |
3394 | && (m = gfc_match_dupl_check (!c->simd, "simd")) != MATCH_NO) |
3395 | { |
3396 | if (m == MATCH_ERROR) |
3397 | goto error; |
3398 | c->simd = needs_space = true; |
3399 | continue; |
3400 | } |
3401 | if ((mask & OMP_CLAUSE_SEVERITY) |
3402 | && (m = gfc_match_dupl_check (!c->severity, "severity", true)) |
3403 | != MATCH_NO) |
3404 | { |
3405 | if (m == MATCH_ERROR) |
3406 | goto error; |
3407 | if (gfc_match ("fatal )") == MATCH_YES) |
3408 | c->severity = OMP_SEVERITY_FATAL; |
3409 | else if (gfc_match ("warning )") == MATCH_YES) |
3410 | c->severity = OMP_SEVERITY_WARNING; |
3411 | else |
3412 | { |
3413 | gfc_error ("Expected FATAL or WARNING in SEVERITY clause " |
3414 | "at %C"); |
3415 | goto error; |
3416 | } |
3417 | continue; |
3418 | } |
3419 | break; |
3420 | case 't': |
3421 | if ((mask & OMP_CLAUSE_TASK_REDUCTION) |
3422 | && gfc_match_omp_clause_reduction (pc, c, openacc, |
3423 | allow_derived) == MATCH_YES) |
3424 | continue; |
3425 | if ((mask & OMP_CLAUSE_THREAD_LIMIT) |
3426 | && (m = gfc_match_dupl_check (!c->thread_limit, "thread_limit", |
3427 | true, &c->thread_limit)) |
3428 | != MATCH_NO) |
3429 | { |
3430 | if (m == MATCH_ERROR) |
3431 | goto error; |
3432 | continue; |
3433 | } |
3434 | if ((mask & OMP_CLAUSE_THREADS) |
3435 | && (m = gfc_match_dupl_check (!c->threads, "threads")) |
3436 | != MATCH_NO) |
3437 | { |
3438 | if (m == MATCH_ERROR) |
3439 | goto error; |
3440 | c->threads = needs_space = true; |
3441 | continue; |
3442 | } |
3443 | if ((mask & OMP_CLAUSE_TILE) |
3444 | && !c->tile_list |
3445 | && match_oacc_expr_list ("tile (", &c->tile_list, |
3446 | true) == MATCH_YES) |
3447 | continue; |
3448 | if ((mask & OMP_CLAUSE_TO) && (mask & OMP_CLAUSE_LINK)) |
3449 | { |
3450 | /* Declare target: 'to' is an alias for 'enter'; |
3451 | 'to' is deprecated since 5.2. */ |
3452 | m = gfc_match_omp_to_link ("to (", &c->lists[OMP_LIST_TO]); |
3453 | if (m == MATCH_ERROR) |
3454 | goto error; |
3455 | if (m == MATCH_YES) |
3456 | continue; |
3457 | } |
3458 | else if ((mask & OMP_CLAUSE_TO) |
3459 | && (gfc_match_omp_variable_list ("to (", |
3460 | &c->lists[OMP_LIST_TO], false, |
3461 | NULL__null, &head, true, true) |
3462 | == MATCH_YES)) |
3463 | continue; |
3464 | break; |
3465 | case 'u': |
3466 | if ((mask & OMP_CLAUSE_UNIFORM) |
3467 | && gfc_match_omp_variable_list ("uniform (", |
3468 | &c->lists[OMP_LIST_UNIFORM], |
3469 | false) == MATCH_YES) |
3470 | continue; |
3471 | if ((mask & OMP_CLAUSE_UNTIED) |
3472 | && (m = gfc_match_dupl_check (!c->untied, "untied")) != MATCH_NO) |
3473 | { |
3474 | if (m == MATCH_ERROR) |
3475 | goto error; |
3476 | c->untied = needs_space = true; |
3477 | continue; |
3478 | } |
3479 | if ((mask & OMP_CLAUSE_ATOMIC) |
3480 | && (m = gfc_match_dupl_atomic ((c->atomic_op |
3481 | == GFC_OMP_ATOMIC_UNSET), |
3482 | "update")) != MATCH_NO) |
3483 | { |
3484 | if (m == MATCH_ERROR) |
3485 | goto error; |
3486 | c->atomic_op = GFC_OMP_ATOMIC_UPDATE; |
3487 | needs_space = true; |
3488 | continue; |
3489 | } |
3490 | if ((mask & OMP_CLAUSE_USE_DEVICE) |
3491 | && gfc_match_omp_variable_list ("use_device (", |
3492 | &c->lists[OMP_LIST_USE_DEVICE], |
3493 | true) == MATCH_YES) |
3494 | continue; |
3495 | if ((mask & OMP_CLAUSE_USE_DEVICE_PTR) |
3496 | && gfc_match_omp_variable_list |
3497 | ("use_device_ptr (", |
3498 | &c->lists[OMP_LIST_USE_DEVICE_PTR], false) == MATCH_YES) |
3499 | continue; |
3500 | if ((mask & OMP_CLAUSE_USE_DEVICE_ADDR) |
3501 | && gfc_match_omp_variable_list |
3502 | ("use_device_addr (", &c->lists[OMP_LIST_USE_DEVICE_ADDR], |
3503 | false, NULL__null, NULL__null, true) == MATCH_YES) |
3504 | continue; |
3505 | break; |
3506 | case 'v': |
3507 | /* VECTOR_LENGTH must be matched before VECTOR, because the latter |
3508 | doesn't unconditionally match '('. */ |
3509 | if ((mask & OMP_CLAUSE_VECTOR_LENGTH) |
3510 | && (m = gfc_match_dupl_check (!c->vector_length_expr, |
3511 | "vector_length", true, |
3512 | &c->vector_length_expr)) |
3513 | != MATCH_NO) |
3514 | { |
3515 | if (m == MATCH_ERROR) |
3516 | goto error; |
3517 | continue; |
3518 | } |
3519 | if ((mask & OMP_CLAUSE_VECTOR) |
3520 | && (m = gfc_match_dupl_check (!c->vector, "vector")) != MATCH_NO) |
3521 | { |
3522 | if (m == MATCH_ERROR) |
3523 | goto error; |
3524 | c->vector = true; |
3525 | m = match_oacc_clause_gwv (c, GOMP_DIM_VECTOR2); |
3526 | if (m == MATCH_ERROR) |
3527 | goto error; |
3528 | if (m == MATCH_NO) |
3529 | needs_space = true; |
3530 | continue; |
3531 | } |
3532 | break; |
3533 | case 'w': |
3534 | if ((mask & OMP_CLAUSE_WAIT) |
3535 | && gfc_match ("wait") == MATCH_YES) |
3536 | { |
3537 | m = match_oacc_expr_list (" (", &c->wait_list, false); |
3538 | if (m == MATCH_ERROR) |
3539 | goto error; |
3540 | else if (m == MATCH_NO) |
3541 | { |
3542 | gfc_expr *expr |
3543 | = gfc_get_constant_expr (BT_INTEGER, |
3544 | gfc_default_integer_kind, |
3545 | &gfc_current_locus); |
3546 | mpz_set_si__gmpz_set_si (expr->value.integer, GOMP_ASYNC_NOVAL-1); |
3547 | gfc_expr_list **expr_list = &c->wait_list; |
3548 | while (*expr_list) |
3549 | expr_list = &(*expr_list)->next; |
3550 | *expr_list = gfc_get_expr_list ()((gfc_expr_list *) xcalloc (1, sizeof (gfc_expr_list))); |
3551 | (*expr_list)->expr = expr; |
3552 | needs_space = true; |
3553 | } |
3554 | continue; |
3555 | } |
3556 | if ((mask & OMP_CLAUSE_WEAK) |
3557 | && (m = gfc_match_dupl_check (!c->weak, "weak")) |
3558 | != MATCH_NO) |
3559 | { |
3560 | if (m == MATCH_ERROR) |
3561 | goto error; |
3562 | c->weak = true; |
3563 | needs_space = true; |
3564 | continue; |
3565 | } |
3566 | if ((mask & OMP_CLAUSE_WORKER) |
3567 | && (m = gfc_match_dupl_check (!c->worker, "worker")) != MATCH_NO) |
3568 | { |
3569 | if (m == MATCH_ERROR) |
3570 | goto error; |
3571 | c->worker = true; |
3572 | m = match_oacc_clause_gwv (c, GOMP_DIM_WORKER1); |
3573 | if (m == MATCH_ERROR) |
3574 | goto error; |
3575 | else if (m == MATCH_NO) |
3576 | needs_space = true; |
3577 | continue; |
3578 | } |
3579 | if ((mask & OMP_CLAUSE_ATOMIC) |
3580 | && (m = gfc_match_dupl_atomic ((c->atomic_op |
3581 | == GFC_OMP_ATOMIC_UNSET), |
3582 | "write")) != MATCH_NO) |
3583 | { |
3584 | if (m == MATCH_ERROR) |
3585 | goto error; |
3586 | c->atomic_op = GFC_OMP_ATOMIC_WRITE; |
3587 | needs_space = true; |
3588 | continue; |
3589 | } |
3590 | break; |
3591 | } |
3592 | break; |
3593 | } |
3594 | |
3595 | end: |
3596 | if (error |
3597 | || (context_selector && gfc_peek_ascii_char () != ')') |
3598 | || (!context_selector && gfc_match_omp_eos () != MATCH_YES)) |
3599 | { |
3600 | if (!gfc_error_flag_test ()) |
3601 | gfc_error ("Failed to match clause at %C"); |
3602 | gfc_free_omp_clauses (c); |
3603 | return MATCH_ERROR; |
3604 | } |
3605 | |
3606 | *cp = c; |
3607 | return MATCH_YES; |
3608 | |
3609 | error: |
3610 | error = true; |
3611 | goto end; |
3612 | } |
3613 | |
3614 | |
3615 | #define OACC_PARALLEL_CLAUSES(omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH) \ |
3616 | (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS \ |
3617 | | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_REDUCTION \ |
3618 | | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \ |
3619 | | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT \ |
3620 | | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \ |
3621 | | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH) |
3622 | #define OACC_KERNELS_CLAUSES(omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH) \ |
3623 | (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS \ |
3624 | | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_DEVICEPTR \ |
3625 | | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \ |
3626 | | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT \ |
3627 | | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH) |
3628 | #define OACC_SERIAL_CLAUSES(omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH) \ |
3629 | (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_REDUCTION \ |
3630 | | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \ |
3631 | | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT \ |
3632 | | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \ |
3633 | | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH) |
3634 | #define OACC_DATA_CLAUSES(omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_ATTACH ) \ |
3635 | (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_COPY \ |
3636 | | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE \ |
3637 | | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_ATTACH) |
3638 | #define OACC_LOOP_CLAUSES(omp_mask (OMP_CLAUSE_COLLAPSE) | OMP_CLAUSE_GANG | OMP_CLAUSE_WORKER | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ | OMP_CLAUSE_INDEPENDENT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_AUTO | OMP_CLAUSE_TILE) \ |
3639 | (omp_mask (OMP_CLAUSE_COLLAPSE) | OMP_CLAUSE_GANG | OMP_CLAUSE_WORKER \ |
3640 | | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ | OMP_CLAUSE_INDEPENDENT \ |
3641 | | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_AUTO \ |
3642 | | OMP_CLAUSE_TILE) |
3643 | #define OACC_PARALLEL_LOOP_CLAUSES((omp_mask (OMP_CLAUSE_COLLAPSE) | OMP_CLAUSE_GANG | OMP_CLAUSE_WORKER | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ | OMP_CLAUSE_INDEPENDENT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_AUTO | OMP_CLAUSE_TILE) | (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH)) \ |
3644 | (OACC_LOOP_CLAUSES(omp_mask (OMP_CLAUSE_COLLAPSE) | OMP_CLAUSE_GANG | OMP_CLAUSE_WORKER | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ | OMP_CLAUSE_INDEPENDENT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_AUTO | OMP_CLAUSE_TILE) | OACC_PARALLEL_CLAUSES(omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH)) |
3645 | #define OACC_KERNELS_LOOP_CLAUSES((omp_mask (OMP_CLAUSE_COLLAPSE) | OMP_CLAUSE_GANG | OMP_CLAUSE_WORKER | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ | OMP_CLAUSE_INDEPENDENT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_AUTO | OMP_CLAUSE_TILE) | (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH)) \ |
3646 | (OACC_LOOP_CLAUSES(omp_mask (OMP_CLAUSE_COLLAPSE) | OMP_CLAUSE_GANG | OMP_CLAUSE_WORKER | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ | OMP_CLAUSE_INDEPENDENT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_AUTO | OMP_CLAUSE_TILE) | OACC_KERNELS_CLAUSES(omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH)) |
3647 | #define OACC_SERIAL_LOOP_CLAUSES((omp_mask (OMP_CLAUSE_COLLAPSE) | OMP_CLAUSE_GANG | OMP_CLAUSE_WORKER | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ | OMP_CLAUSE_INDEPENDENT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_AUTO | OMP_CLAUSE_TILE) | (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH)) \ |
3648 | (OACC_LOOP_CLAUSES(omp_mask (OMP_CLAUSE_COLLAPSE) | OMP_CLAUSE_GANG | OMP_CLAUSE_WORKER | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ | OMP_CLAUSE_INDEPENDENT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_AUTO | OMP_CLAUSE_TILE) | OACC_SERIAL_CLAUSES(omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH)) |
3649 | #define OACC_HOST_DATA_CLAUSES(omp_mask (OMP_CLAUSE_USE_DEVICE) | OMP_CLAUSE_IF | OMP_CLAUSE_IF_PRESENT ) \ |
3650 | (omp_mask (OMP_CLAUSE_USE_DEVICE) \ |
3651 | | OMP_CLAUSE_IF \ |
3652 | | OMP_CLAUSE_IF_PRESENT) |
3653 | #define OACC_DECLARE_CLAUSES(omp_mask (OMP_CLAUSE_COPY) | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_DEVICE_RESIDENT | OMP_CLAUSE_PRESENT | OMP_CLAUSE_LINK) \ |
3654 | (omp_mask (OMP_CLAUSE_COPY) | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT \ |
3655 | | OMP_CLAUSE_CREATE | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_DEVICE_RESIDENT \ |
3656 | | OMP_CLAUSE_PRESENT \ |
3657 | | OMP_CLAUSE_LINK) |
3658 | #define OACC_UPDATE_CLAUSES(omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_HOST_SELF | OMP_CLAUSE_DEVICE | OMP_CLAUSE_WAIT | OMP_CLAUSE_IF_PRESENT ) \ |
3659 | (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_HOST_SELF \ |
3660 | | OMP_CLAUSE_DEVICE | OMP_CLAUSE_WAIT | OMP_CLAUSE_IF_PRESENT) |
3661 | #define OACC_ENTER_DATA_CLAUSES(omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT | OMP_CLAUSE_COPYIN | OMP_CLAUSE_CREATE | OMP_CLAUSE_ATTACH) \ |
3662 | (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT \ |
3663 | | OMP_CLAUSE_COPYIN | OMP_CLAUSE_CREATE | OMP_CLAUSE_ATTACH) |
3664 | #define OACC_EXIT_DATA_CLAUSES(omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_DELETE | OMP_CLAUSE_FINALIZE | OMP_CLAUSE_DETACH) \ |
3665 | (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT \ |
3666 | | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_DELETE | OMP_CLAUSE_FINALIZE \ |
3667 | | OMP_CLAUSE_DETACH) |
3668 | #define OACC_WAIT_CLAUSESomp_mask (OMP_CLAUSE_ASYNC) \ |
3669 | omp_mask (OMP_CLAUSE_ASYNC) |
3670 | #define OACC_ROUTINE_CLAUSES(omp_mask (OMP_CLAUSE_GANG) | OMP_CLAUSE_WORKER | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ | OMP_CLAUSE_NOHOST) \ |
3671 | (omp_mask (OMP_CLAUSE_GANG) | OMP_CLAUSE_WORKER | OMP_CLAUSE_VECTOR \ |
3672 | | OMP_CLAUSE_SEQ \ |
3673 | | OMP_CLAUSE_NOHOST) |
3674 | |
3675 | |
3676 | static match |
3677 | match_acc (gfc_exec_op op, const omp_mask mask) |
3678 | { |
3679 | gfc_omp_clauses *c; |
3680 | if (gfc_match_omp_clauses (&c, mask, false, false, true) != MATCH_YES) |
3681 | return MATCH_ERROR; |
3682 | new_st.op = op; |
3683 | new_st.ext.omp_clauses = c; |
3684 | return MATCH_YES; |
3685 | } |
3686 | |
3687 | match |
3688 | gfc_match_oacc_parallel_loop (void) |
3689 | { |
3690 | return match_acc (EXEC_OACC_PARALLEL_LOOP, OACC_PARALLEL_LOOP_CLAUSES((omp_mask (OMP_CLAUSE_COLLAPSE) | OMP_CLAUSE_GANG | OMP_CLAUSE_WORKER | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ | OMP_CLAUSE_INDEPENDENT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_AUTO | OMP_CLAUSE_TILE) | (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH))); |
3691 | } |
3692 | |
3693 | |
3694 | match |
3695 | gfc_match_oacc_parallel (void) |
3696 | { |
3697 | return match_acc (EXEC_OACC_PARALLEL, OACC_PARALLEL_CLAUSES(omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH)); |
3698 | } |
3699 | |
3700 | |
3701 | match |
3702 | gfc_match_oacc_kernels_loop (void) |
3703 | { |
3704 | return match_acc (EXEC_OACC_KERNELS_LOOP, OACC_KERNELS_LOOP_CLAUSES((omp_mask (OMP_CLAUSE_COLLAPSE) | OMP_CLAUSE_GANG | OMP_CLAUSE_WORKER | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ | OMP_CLAUSE_INDEPENDENT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_AUTO | OMP_CLAUSE_TILE) | (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH))); |
3705 | } |
3706 | |
3707 | |
3708 | match |
3709 | gfc_match_oacc_kernels (void) |
3710 | { |
3711 | return match_acc (EXEC_OACC_KERNELS, OACC_KERNELS_CLAUSES(omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_NUM_GANGS | OMP_CLAUSE_NUM_WORKERS | OMP_CLAUSE_VECTOR_LENGTH | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH)); |
3712 | } |
3713 | |
3714 | |
3715 | match |
3716 | gfc_match_oacc_serial_loop (void) |
3717 | { |
3718 | return match_acc (EXEC_OACC_SERIAL_LOOP, OACC_SERIAL_LOOP_CLAUSES((omp_mask (OMP_CLAUSE_COLLAPSE) | OMP_CLAUSE_GANG | OMP_CLAUSE_WORKER | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ | OMP_CLAUSE_INDEPENDENT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_AUTO | OMP_CLAUSE_TILE) | (omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH))); |
3719 | } |
3720 | |
3721 | |
3722 | match |
3723 | gfc_match_oacc_serial (void) |
3724 | { |
3725 | return match_acc (EXEC_OACC_SERIAL, OACC_SERIAL_CLAUSES(omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_WAIT | OMP_CLAUSE_ATTACH)); |
3726 | } |
3727 | |
3728 | |
3729 | match |
3730 | gfc_match_oacc_data (void) |
3731 | { |
3732 | return match_acc (EXEC_OACC_DATA, OACC_DATA_CLAUSES(omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_COPY | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE | OMP_CLAUSE_NO_CREATE | OMP_CLAUSE_PRESENT | OMP_CLAUSE_ATTACH )); |
3733 | } |
3734 | |
3735 | |
3736 | match |
3737 | gfc_match_oacc_host_data (void) |
3738 | { |
3739 | return match_acc (EXEC_OACC_HOST_DATA, OACC_HOST_DATA_CLAUSES(omp_mask (OMP_CLAUSE_USE_DEVICE) | OMP_CLAUSE_IF | OMP_CLAUSE_IF_PRESENT )); |
3740 | } |
3741 | |
3742 | |
3743 | match |
3744 | gfc_match_oacc_loop (void) |
3745 | { |
3746 | return match_acc (EXEC_OACC_LOOP, OACC_LOOP_CLAUSES(omp_mask (OMP_CLAUSE_COLLAPSE) | OMP_CLAUSE_GANG | OMP_CLAUSE_WORKER | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ | OMP_CLAUSE_INDEPENDENT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_AUTO | OMP_CLAUSE_TILE)); |
3747 | } |
3748 | |
3749 | |
3750 | match |
3751 | gfc_match_oacc_declare (void) |
3752 | { |
3753 | gfc_omp_clauses *c; |
3754 | gfc_omp_namelist *n; |
3755 | gfc_namespace *ns = gfc_current_ns; |
3756 | gfc_oacc_declare *new_oc; |
3757 | bool module_var = false; |
3758 | locus where = gfc_current_locus; |
3759 | |
3760 | if (gfc_match_omp_clauses (&c, OACC_DECLARE_CLAUSES(omp_mask (OMP_CLAUSE_COPY) | OMP_CLAUSE_COPYIN | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_CREATE | OMP_CLAUSE_DEVICEPTR | OMP_CLAUSE_DEVICE_RESIDENT | OMP_CLAUSE_PRESENT | OMP_CLAUSE_LINK), false, false, true) |
3761 | != MATCH_YES) |
3762 | return MATCH_ERROR; |
3763 | |
3764 | for (n = c->lists[OMP_LIST_DEVICE_RESIDENT]; n != NULL__null; n = n->next) |
3765 | n->sym->attr.oacc_declare_device_resident = 1; |
3766 | |
3767 | for (n = c->lists[OMP_LIST_LINK]; n != NULL__null; n = n->next) |
3768 | n->sym->attr.oacc_declare_link = 1; |
3769 | |
3770 | for (n = c->lists[OMP_LIST_MAP]; n != NULL__null; n = n->next) |
3771 | { |
3772 | gfc_symbol *s = n->sym; |
3773 | |
3774 | if (gfc_current_ns->proc_name |
3775 | && gfc_current_ns->proc_name->attr.flavor == FL_MODULE) |
3776 | { |
3777 | if (n->u.map_op != OMP_MAP_ALLOC && n->u.map_op != OMP_MAP_TO) |
3778 | { |
3779 | gfc_error ("Invalid clause in module with !$ACC DECLARE at %L", |
3780 | &where); |
3781 | return MATCH_ERROR; |
3782 | } |
3783 | |
3784 | module_var = true; |
3785 | } |
3786 | |
3787 | if (s->attr.use_assoc) |
3788 | { |
3789 | gfc_error ("Variable is USE-associated with !$ACC DECLARE at %L", |
3790 | &where); |
3791 | return MATCH_ERROR; |
3792 | } |
3793 | |
3794 | if ((s->result == s && s->ns->contained != gfc_current_ns) |
3795 | || ((s->attr.flavor == FL_UNKNOWN || s->attr.flavor == FL_VARIABLE) |
3796 | && s->ns != gfc_current_ns)) |
3797 | { |
3798 | gfc_error ("Variable %qs shall be declared in the same scoping unit " |
3799 | "as !$ACC DECLARE at %L", s->name, &where); |
3800 | return MATCH_ERROR; |
3801 | } |
3802 | |
3803 | if ((s->attr.dimension || s->attr.codimension) |
3804 | && s->attr.dummy && s->as->type != AS_EXPLICIT) |
3805 | { |
3806 | gfc_error ("Assumed-size dummy array with !$ACC DECLARE at %L", |
3807 | &where); |
3808 | return MATCH_ERROR; |
3809 | } |
3810 | |
3811 | switch (n->u.map_op) |
3812 | { |
3813 | case OMP_MAP_FORCE_ALLOC: |
3814 | case OMP_MAP_ALLOC: |
3815 | s->attr.oacc_declare_create = 1; |
3816 | break; |
3817 | |
3818 | case OMP_MAP_FORCE_TO: |
3819 | case OMP_MAP_TO: |
3820 | s->attr.oacc_declare_copyin = 1; |
3821 | break; |
3822 | |
3823 | case OMP_MAP_FORCE_DEVICEPTR: |
3824 | s->attr.oacc_declare_deviceptr = 1; |
3825 | break; |
3826 | |
3827 | default: |
3828 | break; |
3829 | } |
3830 | } |
3831 | |
3832 | new_oc = gfc_get_oacc_declare ()((gfc_oacc_declare *) xcalloc (1, sizeof (gfc_oacc_declare))); |
3833 | new_oc->next = ns->oacc_declare; |
3834 | new_oc->module_var = module_var; |
3835 | new_oc->clauses = c; |
3836 | new_oc->loc = gfc_current_locus; |
3837 | ns->oacc_declare = new_oc; |
3838 | |
3839 | return MATCH_YES; |
3840 | } |
3841 | |
3842 | |
3843 | match |
3844 | gfc_match_oacc_update (void) |
3845 | { |
3846 | gfc_omp_clauses *c; |
3847 | locus here = gfc_current_locus; |
3848 | |
3849 | if (gfc_match_omp_clauses (&c, OACC_UPDATE_CLAUSES(omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_HOST_SELF | OMP_CLAUSE_DEVICE | OMP_CLAUSE_WAIT | OMP_CLAUSE_IF_PRESENT ), false, false, true) |
3850 | != MATCH_YES) |
3851 | return MATCH_ERROR; |
3852 | |
3853 | if (!c->lists[OMP_LIST_MAP]) |
3854 | { |
3855 | gfc_error ("%<acc update%> must contain at least one " |
3856 | "%<device%> or %<host%> or %<self%> clause at %L", &here); |
3857 | return MATCH_ERROR; |
3858 | } |
3859 | |
3860 | new_st.op = EXEC_OACC_UPDATE; |
3861 | new_st.ext.omp_clauses = c; |
3862 | return MATCH_YES; |
3863 | } |
3864 | |
3865 | |
3866 | match |
3867 | gfc_match_oacc_enter_data (void) |
3868 | { |
3869 | return match_acc (EXEC_OACC_ENTER_DATA, OACC_ENTER_DATA_CLAUSES(omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT | OMP_CLAUSE_COPYIN | OMP_CLAUSE_CREATE | OMP_CLAUSE_ATTACH)); |
3870 | } |
3871 | |
3872 | |
3873 | match |
3874 | gfc_match_oacc_exit_data (void) |
3875 | { |
3876 | return match_acc (EXEC_OACC_EXIT_DATA, OACC_EXIT_DATA_CLAUSES(omp_mask (OMP_CLAUSE_IF) | OMP_CLAUSE_ASYNC | OMP_CLAUSE_WAIT | OMP_CLAUSE_COPYOUT | OMP_CLAUSE_DELETE | OMP_CLAUSE_FINALIZE | OMP_CLAUSE_DETACH)); |
3877 | } |
3878 | |
3879 | |
3880 | match |
3881 | gfc_match_oacc_wait (void) |
3882 | { |
3883 | gfc_omp_clauses *c = gfc_get_omp_clauses ()((gfc_omp_clauses *) xcalloc (1, sizeof (gfc_omp_clauses))); |
3884 | gfc_expr_list *wait_list = NULL__null, *el; |
3885 | bool space = true; |
3886 | match m; |
3887 | |
3888 | m = match_oacc_expr_list (" (", &wait_list, true); |
3889 | if (m == MATCH_ERROR) |
3890 | return m; |
3891 | else if (m == MATCH_YES) |
3892 | space = false; |
3893 | |
3894 | if (gfc_match_omp_clauses (&c, OACC_WAIT_CLAUSESomp_mask (OMP_CLAUSE_ASYNC), space, space, true) |
3895 | == MATCH_ERROR) |
3896 | return MATCH_ERROR; |
3897 | |
3898 | if (wait_list) |
3899 | for (el = wait_list; el; el = el->next) |
3900 | { |
3901 | if (el->expr == NULL__null) |
3902 | { |
3903 | gfc_error ("Invalid argument to !$ACC WAIT at %C"); |
3904 | return MATCH_ERROR; |
3905 | } |
3906 | |
3907 | if (!gfc_resolve_expr (el->expr) |
3908 | || el->expr->ts.type != BT_INTEGER || el->expr->rank != 0) |
3909 | { |
3910 | gfc_error ("WAIT clause at %L requires a scalar INTEGER expression", |
3911 | &el->expr->where); |
3912 | |
3913 | return MATCH_ERROR; |
3914 | } |
3915 | } |
3916 | c->wait_list = wait_list; |
3917 | new_st.op = EXEC_OACC_WAIT; |
3918 | new_st.ext.omp_clauses = c; |
3919 | return MATCH_YES; |
3920 | } |
3921 | |
3922 | |
3923 | match |
3924 | gfc_match_oacc_cache (void) |
3925 | { |
3926 | gfc_omp_clauses *c = gfc_get_omp_clauses ()((gfc_omp_clauses *) xcalloc (1, sizeof (gfc_omp_clauses))); |
3927 | /* The OpenACC cache directive explicitly only allows "array elements or |
3928 | subarrays", which we're currently not checking here. Either check this |
3929 | after the call of gfc_match_omp_variable_list, or add something like a |
3930 | only_sections variant next to its allow_sections parameter. */ |
3931 | match m = gfc_match_omp_variable_list (" (", |
3932 | &c->lists[OMP_LIST_CACHE], true, |
3933 | NULL__null, NULL__null, true); |
3934 | if (m != MATCH_YES) |
3935 | { |
3936 | gfc_free_omp_clauses(c); |
3937 | return m; |
3938 | } |
3939 | |
3940 | if (gfc_current_state()(gfc_state_stack->state) != COMP_DO |
3941 | && gfc_current_state()(gfc_state_stack->state) != COMP_DO_CONCURRENT) |
3942 | { |
3943 | gfc_error ("ACC CACHE directive must be inside of loop %C"); |
3944 | gfc_free_omp_clauses(c); |
3945 | return MATCH_ERROR; |
3946 | } |
3947 | |
3948 | new_st.op = EXEC_OACC_CACHE; |
3949 | new_st.ext.omp_clauses = c; |
3950 | return MATCH_YES; |
3951 | } |
3952 | |
3953 | /* Determine the OpenACC 'routine' directive's level of parallelism. */ |
3954 | |
3955 | static oacc_routine_lop |
3956 | gfc_oacc_routine_lop (gfc_omp_clauses *clauses) |
3957 | { |
3958 | oacc_routine_lop ret = OACC_ROUTINE_LOP_SEQ; |
3959 | |
3960 | if (clauses) |
3961 | { |
3962 | unsigned n_lop_clauses = 0; |
3963 | |
3964 | if (clauses->gang) |
3965 | { |
3966 | ++n_lop_clauses; |
3967 | ret = OACC_ROUTINE_LOP_GANG; |
3968 | } |
3969 | if (clauses->worker) |
3970 | { |
3971 | ++n_lop_clauses; |
3972 | ret = OACC_ROUTINE_LOP_WORKER; |
3973 | } |
3974 | if (clauses->vector) |
3975 | { |
3976 | ++n_lop_clauses; |
3977 | ret = OACC_ROUTINE_LOP_VECTOR; |
3978 | } |
3979 | if (clauses->seq) |
3980 | { |
3981 | ++n_lop_clauses; |
3982 | ret = OACC_ROUTINE_LOP_SEQ; |
3983 | } |
3984 | |
3985 | if (n_lop_clauses > 1) |
3986 | ret = OACC_ROUTINE_LOP_ERROR; |
3987 | } |
3988 | |
3989 | return ret; |
3990 | } |
3991 | |
3992 | match |
3993 | gfc_match_oacc_routine (void) |
3994 | { |
3995 | locus old_loc; |
3996 | match m; |
3997 | gfc_intrinsic_sym *isym = NULL__null; |
3998 | gfc_symbol *sym = NULL__null; |
3999 | gfc_omp_clauses *c = NULL__null; |
4000 | gfc_oacc_routine_name *n = NULL__null; |
4001 | oacc_routine_lop lop = OACC_ROUTINE_LOP_NONE; |
4002 | bool nohost; |
4003 | |
4004 | old_loc = gfc_current_locus; |
4005 | |
4006 | m = gfc_match (" ("); |
4007 | |
4008 | if (gfc_current_ns->proc_name |
4009 | && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY |
4010 | && m == MATCH_YES) |
4011 | { |
4012 | gfc_error ("Only the !$ACC ROUTINE form without " |
4013 | "list is allowed in interface block at %C"); |
4014 | goto cleanup; |
4015 | } |
4016 | |
4017 | if (m == MATCH_YES) |
4018 | { |
4019 | char buffer[GFC_MAX_SYMBOL_LEN63 + 1]; |
4020 | |
4021 | m = gfc_match_name (buffer); |
4022 | if (m == MATCH_YES) |
4023 | { |
4024 | gfc_symtree *st = NULL__null; |
4025 | |
4026 | /* First look for an intrinsic symbol. */ |
4027 | isym = gfc_find_function (buffer); |
4028 | if (!isym) |
4029 | isym = gfc_find_subroutine (buffer); |
4030 | /* If no intrinsic symbol found, search the current namespace. */ |
4031 | if (!isym) |
4032 | st = gfc_find_symtree (gfc_current_ns->sym_root, buffer); |
4033 | if (st) |
4034 | { |
4035 | sym = st->n.sym; |
4036 | /* If the name in a 'routine' directive refers to the containing |
4037 | subroutine or function, then make sure that we'll later handle |
4038 | this accordingly. */ |
4039 | if (gfc_current_ns->proc_name != NULL__null |
4040 | && strcmp (sym->name, gfc_current_ns->proc_name->name) == 0) |
4041 | sym = NULL__null; |
4042 | } |
4043 | |
4044 | if (isym == NULL__null && st == NULL__null) |
4045 | { |
4046 | gfc_error ("Invalid NAME %qs in !$ACC ROUTINE ( NAME ) at %C", |
4047 | buffer); |
4048 | gfc_current_locus = old_loc; |
4049 | return MATCH_ERROR; |
4050 | } |
4051 | } |
4052 | else |
4053 | { |
4054 | gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C"); |
4055 | gfc_current_locus = old_loc; |
4056 | return MATCH_ERROR; |
4057 | } |
4058 | |
4059 | if (gfc_match_char (')') != MATCH_YES) |
4060 | { |
4061 | gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C, expecting" |
4062 | " %<)%> after NAME"); |
4063 | gfc_current_locus = old_loc; |
4064 | return MATCH_ERROR; |
4065 | } |
4066 | } |
4067 | |
4068 | if (gfc_match_omp_eos () != MATCH_YES |
4069 | && (gfc_match_omp_clauses (&c, OACC_ROUTINE_CLAUSES(omp_mask (OMP_CLAUSE_GANG) | OMP_CLAUSE_WORKER | OMP_CLAUSE_VECTOR | OMP_CLAUSE_SEQ | OMP_CLAUSE_NOHOST), false, false, true) |
4070 | != MATCH_YES)) |
4071 | return MATCH_ERROR; |
4072 | |
4073 | lop = gfc_oacc_routine_lop (c); |
4074 | if (lop == OACC_ROUTINE_LOP_ERROR) |
4075 | { |
4076 | gfc_error ("Multiple loop axes specified for routine at %C"); |
4077 | goto cleanup; |
4078 | } |
4079 | nohost = c ? c->nohost : false; |
4080 | |
4081 | if (isym != NULL__null) |
4082 | { |
4083 | /* Diagnose any OpenACC 'routine' directive that doesn't match the |
4084 | (implicit) one with a 'seq' clause. */ |
4085 | if (c && (c->gang || c->worker || c->vector)) |
4086 | { |
4087 | gfc_error ("Intrinsic symbol specified in !$ACC ROUTINE ( NAME )" |
4088 | " at %C marked with incompatible GANG, WORKER, or VECTOR" |
4089 | " clause"); |
4090 | goto cleanup; |
4091 | } |
4092 | /* ..., and no 'nohost' clause. */ |
4093 | if (nohost) |
4094 | { |
4095 | gfc_error ("Intrinsic symbol specified in !$ACC ROUTINE ( NAME )" |
4096 | " at %C marked with incompatible NOHOST clause"); |
4097 | goto cleanup; |
4098 | } |
4099 | } |
4100 | else if (sym != NULL__null) |
4101 | { |
4102 | bool add = true; |
4103 | |
4104 | /* For a repeated OpenACC 'routine' directive, diagnose if it doesn't |
4105 | match the first one. */ |
4106 | for (gfc_oacc_routine_name *n_p = gfc_current_ns->oacc_routine_names; |
4107 | n_p; |
4108 | n_p = n_p->next) |
4109 | if (n_p->sym == sym) |
4110 | { |
4111 | add = false; |
4112 | bool nohost_p = n_p->clauses ? n_p->clauses->nohost : false; |
4113 | if (lop != gfc_oacc_routine_lop (n_p->clauses) |
4114 | || nohost != nohost_p) |
4115 | { |
4116 | gfc_error ("!$ACC ROUTINE already applied at %C"); |
4117 | goto cleanup; |
4118 | } |
4119 | } |
4120 | |
4121 | if (add) |
4122 | { |
4123 | sym->attr.oacc_routine_lop = lop; |
4124 | sym->attr.oacc_routine_nohost = nohost; |
4125 | |
4126 | n = gfc_get_oacc_routine_name ()((gfc_oacc_routine_name *) xcalloc (1, sizeof (gfc_oacc_routine_name ))); |
4127 | n->sym = sym; |
4128 | n->clauses = c; |
4129 | n->next = gfc_current_ns->oacc_routine_names; |
4130 | n->loc = old_loc; |
4131 | gfc_current_ns->oacc_routine_names = n; |
4132 | } |
4133 | } |
4134 | else if (gfc_current_ns->proc_name) |
4135 | { |
4136 | /* For a repeated OpenACC 'routine' directive, diagnose if it doesn't |
4137 | match the first one. */ |
4138 | oacc_routine_lop lop_p = gfc_current_ns->proc_name->attr.oacc_routine_lop; |
4139 | bool nohost_p = gfc_current_ns->proc_name->attr.oacc_routine_nohost; |
4140 | if (lop_p != OACC_ROUTINE_LOP_NONE |
4141 | && (lop != lop_p |
4142 | || nohost != nohost_p)) |
4143 | { |
4144 | gfc_error ("!$ACC ROUTINE already applied at %C"); |
4145 | goto cleanup; |
4146 | } |
4147 | |
4148 | if (!gfc_add_omp_declare_target (&gfc_current_ns->proc_name->attr, |
4149 | gfc_current_ns->proc_name->name, |
4150 | &old_loc)) |
4151 | goto cleanup; |
4152 | gfc_current_ns->proc_name->attr.oacc_routine_lop = lop; |
4153 | gfc_current_ns->proc_name->attr.oacc_routine_nohost = nohost; |
4154 | } |
4155 | else |
4156 | /* Something has gone wrong, possibly a syntax error. */ |
4157 | goto cleanup; |
4158 | |
4159 | if (gfc_pure (NULL__null) && c && (c->gang || c->worker || c->vector)) |
4160 | { |
4161 | gfc_error ("!$ACC ROUTINE with GANG, WORKER, or VECTOR clause is not " |
4162 | "permitted in PURE procedure at %C"); |
4163 | goto cleanup; |
4164 | } |
4165 | |
4166 | |
4167 | if (n) |
4168 | n->clauses = c; |
4169 | else if (gfc_current_ns->oacc_routine) |
4170 | gfc_current_ns->oacc_routine_clauses = c; |
4171 | |
4172 | new_st.op = EXEC_OACC_ROUTINE; |
4173 | new_st.ext.omp_clauses = c; |
4174 | return MATCH_YES; |
4175 | |
4176 | cleanup: |
4177 | gfc_current_locus = old_loc; |
4178 | return MATCH_ERROR; |
4179 | } |
4180 | |
4181 | |
4182 | #define OMP_PARALLEL_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE) \ |
4183 | (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \ |
4184 | | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION \ |
4185 | | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT \ |
4186 | | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE) |
4187 | #define OMP_DECLARE_SIMD_CLAUSES(omp_mask (OMP_CLAUSE_SIMDLEN) | OMP_CLAUSE_LINEAR | OMP_CLAUSE_UNIFORM | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_INBRANCH | OMP_CLAUSE_NOTINBRANCH ) \ |
4188 | (omp_mask (OMP_CLAUSE_SIMDLEN) | OMP_CLAUSE_LINEAR \ |
4189 | | OMP_CLAUSE_UNIFORM | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_INBRANCH \ |
4190 | | OMP_CLAUSE_NOTINBRANCH) |
4191 | #define OMP_DO_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_SCHEDULE | OMP_CLAUSE_ORDERED | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT) \ |
4192 | (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \ |
4193 | | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION \ |
4194 | | OMP_CLAUSE_SCHEDULE | OMP_CLAUSE_ORDERED | OMP_CLAUSE_COLLAPSE \ |
4195 | | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE \ |
4196 | | OMP_CLAUSE_NOWAIT) |
4197 | #define OMP_LOOP_CLAUSES(omp_mask (OMP_CLAUSE_BIND) | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_ORDER | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION ) \ |
4198 | (omp_mask (OMP_CLAUSE_BIND) | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_ORDER \ |
4199 | | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION) |
4200 | |
4201 | #define OMP_SCOPE_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) |OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT) \ |
4202 | (omp_mask (OMP_CLAUSE_PRIVATE) |OMP_CLAUSE_FIRSTPRIVATE \ |
4203 | | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT) |
4204 | #define OMP_SECTIONS_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT ) \ |
4205 | (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \ |
4206 | | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION \ |
4207 | | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT) |
4208 | #define OMP_SIMD_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_SAFELEN | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_SIMDLEN | OMP_CLAUSE_IF | OMP_CLAUSE_ORDER | OMP_CLAUSE_NOTEMPORAL) \ |
4209 | (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_LASTPRIVATE \ |
4210 | | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_SAFELEN \ |
4211 | | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_SIMDLEN \ |
4212 | | OMP_CLAUSE_IF | OMP_CLAUSE_ORDER | OMP_CLAUSE_NOTEMPORAL) |
4213 | #define OMP_TASK_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE | OMP_CLAUSE_DEPEND | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_DETACH | OMP_CLAUSE_AFFINITY | OMP_CLAUSE_ALLOCATE) \ |
4214 | (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \ |
4215 | | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT \ |
4216 | | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE \ |
4217 | | OMP_CLAUSE_DEPEND | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_IN_REDUCTION \ |
4218 | | OMP_CLAUSE_DETACH | OMP_CLAUSE_AFFINITY | OMP_CLAUSE_ALLOCATE) |
4219 | #define OMP_TASKLOOP_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_GRAINSIZE | OMP_CLAUSE_NUM_TASKS | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_NOGROUP | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_ALLOCATE) \ |
4220 | (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \ |
4221 | | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF \ |
4222 | | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL \ |
4223 | | OMP_CLAUSE_MERGEABLE | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_GRAINSIZE \ |
4224 | | OMP_CLAUSE_NUM_TASKS | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_NOGROUP \ |
4225 | | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_ALLOCATE) |
4226 | #define OMP_TASKGROUP_CLAUSES(omp_mask (OMP_CLAUSE_TASK_REDUCTION) | OMP_CLAUSE_ALLOCATE) \ |
4227 | (omp_mask (OMP_CLAUSE_TASK_REDUCTION) | OMP_CLAUSE_ALLOCATE) |
4228 | #define OMP_TARGET_CLAUSES(omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_HAS_DEVICE_ADDR) \ |
4229 | (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \ |
4230 | | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE \ |
4231 | | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP \ |
4232 | | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_IN_REDUCTION \ |
4233 | | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_ALLOCATE \ |
4234 | | OMP_CLAUSE_HAS_DEVICE_ADDR) |
4235 | #define OMP_TARGET_DATA_CLAUSES(omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF | OMP_CLAUSE_USE_DEVICE_PTR | OMP_CLAUSE_USE_DEVICE_ADDR) \ |
4236 | (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \ |
4237 | | OMP_CLAUSE_USE_DEVICE_PTR | OMP_CLAUSE_USE_DEVICE_ADDR) |
4238 | #define OMP_TARGET_ENTER_DATA_CLAUSES(omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT) \ |
4239 | (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \ |
4240 | | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT) |
4241 | #define OMP_TARGET_EXIT_DATA_CLAUSES(omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT) \ |
4242 | (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF \ |
4243 | | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT) |
4244 | #define OMP_TARGET_UPDATE_CLAUSES(omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_IF | OMP_CLAUSE_TO | OMP_CLAUSE_FROM | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT) \ |
4245 | (omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_IF | OMP_CLAUSE_TO \ |
4246 | | OMP_CLAUSE_FROM | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT) |
4247 | #define OMP_TEAMS_CLAUSES(omp_mask (OMP_CLAUSE_NUM_TEAMS) | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE) \ |
4248 | (omp_mask (OMP_CLAUSE_NUM_TEAMS) | OMP_CLAUSE_THREAD_LIMIT \ |
4249 | | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE \ |
4250 | | OMP_CLAUSE_SHARED | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE) |
4251 | #define OMP_DISTRIBUTE_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_DIST_SCHEDULE | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE) \ |
4252 | (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \ |
4253 | | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_DIST_SCHEDULE \ |
4254 | | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE) |
4255 | #define OMP_SINGLE_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_COPYPRIVATE) \ |
4256 | (omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE \ |
4257 | | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_COPYPRIVATE) |
4258 | #define OMP_ORDERED_CLAUSES(omp_mask (OMP_CLAUSE_THREADS) | OMP_CLAUSE_SIMD) \ |
4259 | (omp_mask (OMP_CLAUSE_THREADS) | OMP_CLAUSE_SIMD) |
4260 | #define OMP_DECLARE_TARGET_CLAUSES(omp_mask (OMP_CLAUSE_ENTER) | OMP_CLAUSE_LINK | OMP_CLAUSE_DEVICE_TYPE | OMP_CLAUSE_TO) \ |
4261 | (omp_mask (OMP_CLAUSE_ENTER) | OMP_CLAUSE_LINK | OMP_CLAUSE_DEVICE_TYPE \ |
4262 | | OMP_CLAUSE_TO) |
4263 | #define OMP_ATOMIC_CLAUSES(omp_mask (OMP_CLAUSE_ATOMIC) | OMP_CLAUSE_CAPTURE | OMP_CLAUSE_HINT | OMP_CLAUSE_MEMORDER | OMP_CLAUSE_COMPARE | OMP_CLAUSE_FAIL | OMP_CLAUSE_WEAK) \ |
4264 | (omp_mask (OMP_CLAUSE_ATOMIC) | OMP_CLAUSE_CAPTURE | OMP_CLAUSE_HINT \ |
4265 | | OMP_CLAUSE_MEMORDER | OMP_CLAUSE_COMPARE | OMP_CLAUSE_FAIL \ |
4266 | | OMP_CLAUSE_WEAK) |
4267 | #define OMP_MASKED_CLAUSES(omp_mask (OMP_CLAUSE_FILTER)) \ |
4268 | (omp_mask (OMP_CLAUSE_FILTER)) |
4269 | #define OMP_ERROR_CLAUSES(omp_mask (OMP_CLAUSE_AT) | OMP_CLAUSE_MESSAGE | OMP_CLAUSE_SEVERITY ) \ |
4270 | (omp_mask (OMP_CLAUSE_AT) | OMP_CLAUSE_MESSAGE | OMP_CLAUSE_SEVERITY) |
4271 | #define OMP_WORKSHARE_CLAUSESomp_mask (OMP_CLAUSE_NOWAIT) \ |
4272 | omp_mask (OMP_CLAUSE_NOWAIT) |
4273 | |
4274 | |
4275 | static match |
4276 | match_omp (gfc_exec_op op, const omp_mask mask) |
4277 | { |
4278 | gfc_omp_clauses *c; |
4279 | if (gfc_match_omp_clauses (&c, mask, true, true, false, false, |
4280 | op == EXEC_OMP_TARGET) != MATCH_YES) |
4281 | return MATCH_ERROR; |
4282 | new_st.op = op; |
4283 | new_st.ext.omp_clauses = c; |
4284 | return MATCH_YES; |
4285 | } |
4286 | |
4287 | |
4288 | match |
4289 | gfc_match_omp_assume (void) |
4290 | { |
4291 | gfc_omp_clauses *c; |
4292 | locus loc = gfc_current_locus; |
4293 | if ((gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_ASSUMPTIONS)) |
4294 | != MATCH_YES) |
4295 | || (omp_verify_merge_absent_contains (ST_OMP_ASSUME, c->assume, NULL__null, |
4296 | &loc) != MATCH_YES)) |
4297 | return MATCH_ERROR; |
4298 | new_st.op = EXEC_OMP_ASSUME; |
4299 | new_st.ext.omp_clauses = c; |
4300 | return MATCH_YES; |
4301 | } |
4302 | |
4303 | |
4304 | match |
4305 | gfc_match_omp_assumes (void) |
4306 | { |
4307 | gfc_omp_clauses *c; |
4308 | locus loc = gfc_current_locus; |
4309 | if (!gfc_current_ns->proc_name |
4310 | || (gfc_current_ns->proc_name->attr.flavor != FL_MODULE |
4311 | && !gfc_current_ns->proc_name->attr.subroutine |
4312 | && !gfc_current_ns->proc_name->attr.function)) |
4313 | { |
4314 | gfc_error ("!$OMP ASSUMES at %C must be in the specification part of a " |
4315 | "subprogram or module"); |
4316 | return MATCH_ERROR; |
4317 | } |
4318 | if ((gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_ASSUMPTIONS)) |
4319 | != MATCH_YES) |
4320 | || (omp_verify_merge_absent_contains (ST_OMP_ASSUMES, c->assume, |
4321 | gfc_current_ns->omp_assumes, &loc) |
4322 | != MATCH_YES)) |
4323 | return MATCH_ERROR; |
4324 | if (gfc_current_ns->omp_assumes == NULL__null) |
4325 | { |
4326 | gfc_current_ns->omp_assumes = c->assume; |
4327 | c->assume = NULL__null; |
4328 | } |
4329 | else if (gfc_current_ns->omp_assumes && c->assume) |
4330 | { |
4331 | gfc_current_ns->omp_assumes->no_openmp |= c->assume->no_openmp; |
4332 | gfc_current_ns->omp_assumes->no_openmp_routines |
4333 | |= c->assume->no_openmp_routines; |
4334 | gfc_current_ns->omp_assumes->no_parallelism |= c->assume->no_parallelism; |
4335 | if (gfc_current_ns->omp_assumes->holds && c->assume->holds) |
4336 | { |
4337 | gfc_expr_list *el = gfc_current_ns->omp_assumes->holds; |
4338 | for ( ; el->next ; el = el->next) |
4339 | ; |
4340 | el->next = c->assume->holds; |
4341 | } |
4342 | else if (c->assume->holds) |
4343 | gfc_current_ns->omp_assumes->holds = c->assume->holds; |
4344 | c->assume->holds = NULL__null; |
4345 | } |
4346 | gfc_free_omp_clauses (c); |
4347 | return MATCH_YES; |
4348 | } |
4349 | |
4350 | |
4351 | match |
4352 | gfc_match_omp_critical (void) |
4353 | { |
4354 | char n[GFC_MAX_SYMBOL_LEN63+1]; |
4355 | gfc_omp_clauses *c = NULL__null; |
4356 | |
4357 | if (gfc_match (" ( %n )", n) != MATCH_YES) |
4358 | n[0] = '\0'; |
4359 | |
4360 | if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_HINT), |
4361 | /* first = */ n[0] == '\0') != MATCH_YES) |
4362 | return MATCH_ERROR; |
4363 | |
4364 | new_st.op = EXEC_OMP_CRITICAL; |
4365 | new_st.ext.omp_clauses = c; |
4366 | if (n[0]) |
4367 | c->critical_name = xstrdup (n); |
4368 | return MATCH_YES; |
4369 | } |
4370 | |
4371 | |
4372 | match |
4373 | gfc_match_omp_end_critical (void) |
4374 | { |
4375 | char n[GFC_MAX_SYMBOL_LEN63+1]; |
4376 | |
4377 | if (gfc_match (" ( %n )", n) != MATCH_YES) |
4378 | n[0] = '\0'; |
4379 | if (gfc_match_omp_eos () != MATCH_YES) |
4380 | { |
4381 | gfc_error ("Unexpected junk after $OMP CRITICAL statement at %C"); |
4382 | return MATCH_ERROR; |
4383 | } |
4384 | |
4385 | new_st.op = EXEC_OMP_END_CRITICAL; |
4386 | new_st.ext.omp_name = n[0] ? xstrdup (n) : NULL__null; |
4387 | return MATCH_YES; |
4388 | } |
4389 | |
4390 | /* depobj(depobj) depend(dep-type:loc)|destroy|update(dep-type) |
4391 | dep-type = in/out/inout/mutexinoutset/depobj/source/sink |
4392 | depend: !source, !sink |
4393 | update: !source, !sink, !depobj |
4394 | locator = exactly one list item .*/ |
4395 | match |
4396 | gfc_match_omp_depobj (void) |
4397 | { |
4398 | gfc_omp_clauses *c = NULL__null; |
4399 | gfc_expr *depobj; |
4400 | |
4401 | if (gfc_match (" ( %v ) ", &depobj) != MATCH_YES) |
4402 | { |
4403 | gfc_error ("Expected %<( depobj )%> at %C"); |
4404 | return MATCH_ERROR; |
4405 | } |
4406 | if (gfc_match ("update ( ") == MATCH_YES) |
4407 | { |
4408 | c = gfc_get_omp_clauses ()((gfc_omp_clauses *) xcalloc (1, sizeof (gfc_omp_clauses))); |
4409 | if (gfc_match ("inoutset )") == MATCH_YES) |
4410 | c->depobj_update = OMP_DEPEND_INOUTSET; |
4411 | else if (gfc_match ("inout )") == MATCH_YES) |
4412 | c->depobj_update = OMP_DEPEND_INOUT; |
4413 | else if (gfc_match ("in )") == MATCH_YES) |
4414 | c->depobj_update = OMP_DEPEND_IN; |
4415 | else if (gfc_match ("out )") == MATCH_YES) |
4416 | c->depobj_update = OMP_DEPEND_OUT; |
4417 | else if (gfc_match ("mutexinoutset )") == MATCH_YES) |
4418 | c->depobj_update = OMP_DEPEND_MUTEXINOUTSET; |
4419 | else |
4420 | { |
4421 | gfc_error ("Expected IN, OUT, INOUT, INOUTSET or MUTEXINOUTSET " |
4422 | "followed by %<)%> at %C"); |
4423 | goto error; |
4424 | } |
4425 | } |
4426 | else if (gfc_match ("destroy") == MATCH_YES) |
4427 | { |
4428 | c = gfc_get_omp_clauses ()((gfc_omp_clauses *) xcalloc (1, sizeof (gfc_omp_clauses))); |
4429 | c->destroy = true; |
4430 | } |
4431 | else if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_DEPEND), true, false) |
4432 | != MATCH_YES) |
4433 | goto error; |
4434 | |
4435 | if (c->depobj_update == OMP_DEPEND_UNSET && !c->destroy) |
4436 | { |
4437 | if (!c->doacross_source && !c->lists[OMP_LIST_DEPEND]) |
4438 | { |
4439 | gfc_error ("Expected DEPEND, UPDATE, or DESTROY clause at %C"); |
4440 | goto error; |
4441 | } |
4442 | if (c->lists[OMP_LIST_DEPEND]->u.depend_doacross_op == OMP_DEPEND_DEPOBJ) |
4443 | { |
4444 | gfc_error ("DEPEND clause at %L of OMP DEPOBJ construct shall not " |
4445 | "have dependence-type DEPOBJ", |
4446 | c->lists[OMP_LIST_DEPEND] |
4447 | ? &c->lists[OMP_LIST_DEPEND]->where : &gfc_current_locus); |
4448 | goto error; |
4449 | } |
4450 | if (c->lists[OMP_LIST_DEPEND]->next) |
4451 | { |
4452 | gfc_error ("DEPEND clause at %L of OMP DEPOBJ construct shall have " |
4453 | "only a single locator", |
4454 | &c->lists[OMP_LIST_DEPEND]->next->where); |
4455 | goto error; |
4456 | } |
4457 | } |
4458 | |
4459 | c->depobj = depobj; |
4460 | new_st.op = EXEC_OMP_DEPOBJ; |
4461 | new_st.ext.omp_clauses = c; |
4462 | return MATCH_YES; |
4463 | |
4464 | error: |
4465 | gfc_free_expr (depobj); |
4466 | gfc_free_omp_clauses (c); |
4467 | return MATCH_ERROR; |
4468 | } |
4469 | |
4470 | match |
4471 | gfc_match_omp_distribute (void) |
4472 | { |
4473 | return match_omp (EXEC_OMP_DISTRIBUTE, OMP_DISTRIBUTE_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_DIST_SCHEDULE | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE)); |
4474 | } |
4475 | |
4476 | |
4477 | match |
4478 | gfc_match_omp_distribute_parallel_do (void) |
4479 | { |
4480 | return match_omp (EXEC_OMP_DISTRIBUTE_PARALLEL_DO, |
4481 | (OMP_DISTRIBUTE_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_DIST_SCHEDULE | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE) | OMP_PARALLEL_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE) |
4482 | | OMP_DO_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_SCHEDULE | OMP_CLAUSE_ORDERED | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT)) |
4483 | & ~(omp_mask (OMP_CLAUSE_ORDERED) |
4484 | | OMP_CLAUSE_LINEAR | OMP_CLAUSE_NOWAIT)); |
4485 | } |
4486 | |
4487 | |
4488 | match |
4489 | gfc_match_omp_distribute_parallel_do_simd (void) |
4490 | { |
4491 | return match_omp (EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD, |
4492 | (OMP_DISTRIBUTE_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_DIST_SCHEDULE | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE) | OMP_PARALLEL_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE) |
4493 | | OMP_DO_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_SCHEDULE | OMP_CLAUSE_ORDERED | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT) | OMP_SIMD_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_SAFELEN | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_SIMDLEN | OMP_CLAUSE_IF | OMP_CLAUSE_ORDER | OMP_CLAUSE_NOTEMPORAL)) |
4494 | & ~(omp_mask (OMP_CLAUSE_ORDERED) | OMP_CLAUSE_NOWAIT)); |
4495 | } |
4496 | |
4497 | |
4498 | match |
4499 | gfc_match_omp_distribute_simd (void) |
4500 | { |
4501 | return match_omp (EXEC_OMP_DISTRIBUTE_SIMD, |
4502 | OMP_DISTRIBUTE_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_DIST_SCHEDULE | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE) | OMP_SIMD_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_SAFELEN | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_SIMDLEN | OMP_CLAUSE_IF | OMP_CLAUSE_ORDER | OMP_CLAUSE_NOTEMPORAL)); |
4503 | } |
4504 | |
4505 | |
4506 | match |
4507 | gfc_match_omp_do (void) |
4508 | { |
4509 | return match_omp (EXEC_OMP_DO, OMP_DO_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_SCHEDULE | OMP_CLAUSE_ORDERED | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT)); |
4510 | } |
4511 | |
4512 | |
4513 | match |
4514 | gfc_match_omp_do_simd (void) |
4515 | { |
4516 | return match_omp (EXEC_OMP_DO_SIMD, OMP_DO_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_SCHEDULE | OMP_CLAUSE_ORDERED | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT) | OMP_SIMD_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_SAFELEN | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_SIMDLEN | OMP_CLAUSE_IF | OMP_CLAUSE_ORDER | OMP_CLAUSE_NOTEMPORAL)); |
4517 | } |
4518 | |
4519 | |
4520 | match |
4521 | gfc_match_omp_loop (void) |
4522 | { |
4523 | return match_omp (EXEC_OMP_LOOP, OMP_LOOP_CLAUSES(omp_mask (OMP_CLAUSE_BIND) | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_ORDER | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION )); |
4524 | } |
4525 | |
4526 | |
4527 | match |
4528 | gfc_match_omp_teams_loop (void) |
4529 | { |
4530 | return match_omp (EXEC_OMP_TEAMS_LOOP, OMP_TEAMS_CLAUSES(omp_mask (OMP_CLAUSE_NUM_TEAMS) | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE) | OMP_LOOP_CLAUSES(omp_mask (OMP_CLAUSE_BIND) | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_ORDER | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION )); |
4531 | } |
4532 | |
4533 | |
4534 | match |
4535 | gfc_match_omp_target_teams_loop (void) |
4536 | { |
4537 | return match_omp (EXEC_OMP_TARGET_TEAMS_LOOP, |
4538 | OMP_TARGET_CLAUSES(omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_HAS_DEVICE_ADDR) | OMP_TEAMS_CLAUSES(omp_mask (OMP_CLAUSE_NUM_TEAMS) | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE) | OMP_LOOP_CLAUSES(omp_mask (OMP_CLAUSE_BIND) | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_ORDER | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION )); |
4539 | } |
4540 | |
4541 | |
4542 | match |
4543 | gfc_match_omp_parallel_loop (void) |
4544 | { |
4545 | return match_omp (EXEC_OMP_PARALLEL_LOOP, |
4546 | OMP_PARALLEL_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE) | OMP_LOOP_CLAUSES(omp_mask (OMP_CLAUSE_BIND) | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_ORDER | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION )); |
4547 | } |
4548 | |
4549 | |
4550 | match |
4551 | gfc_match_omp_target_parallel_loop (void) |
4552 | { |
4553 | return match_omp (EXEC_OMP_TARGET_PARALLEL_LOOP, |
4554 | (OMP_TARGET_CLAUSES(omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_HAS_DEVICE_ADDR) | OMP_PARALLEL_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE) |
4555 | | OMP_LOOP_CLAUSES(omp_mask (OMP_CLAUSE_BIND) | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_ORDER | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION ))); |
4556 | } |
4557 | |
4558 | |
4559 | match |
4560 | gfc_match_omp_error (void) |
4561 | { |
4562 | locus loc = gfc_current_locus; |
4563 | match m = match_omp (EXEC_OMP_ERROR, OMP_ERROR_CLAUSES(omp_mask (OMP_CLAUSE_AT) | OMP_CLAUSE_MESSAGE | OMP_CLAUSE_SEVERITY )); |
4564 | if (m != MATCH_YES) |
4565 | return m; |
4566 | |
4567 | gfc_omp_clauses *c = new_st.ext.omp_clauses; |
4568 | if (c->severity == OMP_SEVERITY_UNSET) |
4569 | c->severity = OMP_SEVERITY_FATAL; |
4570 | if (new_st.ext.omp_clauses->at == OMP_AT_EXECUTION) |
4571 | return MATCH_YES; |
4572 | if (c->message |
4573 | && (!gfc_resolve_expr (c->message) |
4574 | || c->message->ts.type != BT_CHARACTER |
4575 | || c->message->ts.kind != gfc_default_character_kind |
4576 | || c->message->rank != 0)) |
4577 | { |
4578 | gfc_error ("MESSAGE clause at %L requires a scalar default-kind " |
4579 | "CHARACTER expression", |
4580 | &new_st.ext.omp_clauses->message->where); |
4581 | return MATCH_ERROR; |
4582 | } |
4583 | if (c->message && !gfc_is_constant_expr (c->message)) |
4584 | { |
4585 | gfc_error ("Constant character expression required in MESSAGE clause " |
4586 | "at %L", &new_st.ext.omp_clauses->message->where); |
4587 | return MATCH_ERROR; |
4588 | } |
4589 | if (c->message) |
4590 | { |
4591 | const char *msg = G_("$OMP ERROR encountered at %L: %s")"$OMP ERROR encountered at %L: %s"; |
4592 | gcc_assert (c->message->expr_type == EXPR_CONSTANT)((void)(!(c->message->expr_type == EXPR_CONSTANT) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/openmp.cc" , 4592, __FUNCTION__), 0 : 0)); |
4593 | gfc_charlen_t slen = c->message->value.character.length; |
4594 | int i = gfc_validate_kind (BT_CHARACTER, gfc_default_character_kind, |
4595 | false); |
4596 | size_t size = slen * gfc_character_kinds[i].bit_size / 8; |
4597 | unsigned char *s = XCNEWVAR (unsigned char, size + 1)((unsigned char *) xcalloc (1, (size + 1))); |
4598 | gfc_encode_character (gfc_default_character_kind, slen, |
4599 | c->message->value.character.string, |
4600 | (unsigned char *) s, size); |
4601 | s[size] = '\0'; |
4602 | if (c->severity == OMP_SEVERITY_WARNING) |
4603 | gfc_warning_now (0, msg, &loc, s); |
4604 | else |
4605 | gfc_error_now (msg, &loc, s); |
4606 | free (s); |
4607 | } |
4608 | else |
4609 | { |
4610 | const char *msg = G_("$OMP ERROR encountered at %L")"$OMP ERROR encountered at %L"; |
4611 | if (c->severity == OMP_SEVERITY_WARNING) |
4612 | gfc_warning_now (0, msg, &loc); |
4613 | else |
4614 | gfc_error_now (msg, &loc); |
4615 | } |
4616 | return MATCH_YES; |
4617 | } |
4618 | |
4619 | match |
4620 | gfc_match_omp_flush (void) |
4621 | { |
4622 | gfc_omp_namelist *list = NULL__null; |
4623 | gfc_omp_clauses *c = NULL__null; |
4624 | gfc_gobble_whitespace (); |
4625 | enum gfc_omp_memorder mo = OMP_MEMORDER_UNSET; |
4626 | if (gfc_match_omp_eos () == MATCH_NO && gfc_peek_ascii_char () != '(') |
4627 | { |
4628 | if (gfc_match ("seq_cst") == MATCH_YES) |
4629 | mo = OMP_MEMORDER_SEQ_CST; |
4630 | else if (gfc_match ("acq_rel") == MATCH_YES) |
4631 | mo = OMP_MEMORDER_ACQ_REL; |
4632 | else if (gfc_match ("release") == MATCH_YES) |
4633 | mo = OMP_MEMORDER_RELEASE; |
4634 | else if (gfc_match ("acquire") == MATCH_YES) |
4635 | mo = OMP_MEMORDER_ACQUIRE; |
4636 | else |
4637 | { |
4638 | gfc_error ("Expected SEQ_CST, AQC_REL, RELEASE, or ACQUIRE at %C"); |
4639 | return MATCH_ERROR; |
4640 | } |
4641 | c = gfc_get_omp_clauses ()((gfc_omp_clauses *) xcalloc (1, sizeof (gfc_omp_clauses))); |
4642 | c->memorder = mo; |
4643 | } |
4644 | gfc_match_omp_variable_list (" (", &list, true); |
4645 | if (list && mo != OMP_MEMORDER_UNSET) |
4646 | { |
4647 | gfc_error ("List specified together with memory order clause in FLUSH " |
4648 | "directive at %C"); |
4649 | gfc_free_omp_namelist (list, false, false); |
4650 | gfc_free_omp_clauses (c); |
4651 | return MATCH_ERROR; |
4652 | } |
4653 | if (gfc_match_omp_eos () != MATCH_YES) |
4654 | { |
4655 | gfc_error ("Unexpected junk after $OMP FLUSH statement at %C"); |
4656 | gfc_free_omp_namelist (list, false, false); |
4657 | gfc_free_omp_clauses (c); |
4658 | return MATCH_ERROR; |
4659 | } |
4660 | new_st.op = EXEC_OMP_FLUSH; |
4661 | new_st.ext.omp_namelist = list; |
4662 | new_st.ext.omp_clauses = c; |
4663 | return MATCH_YES; |
4664 | } |
4665 | |
4666 | |
4667 | match |
4668 | gfc_match_omp_declare_simd (void) |
4669 | { |
4670 | locus where = gfc_current_locus; |
4671 | gfc_symbol *proc_name; |
4672 | gfc_omp_clauses *c; |
4673 | gfc_omp_declare_simd *ods; |
4674 | bool needs_space = false; |
4675 | |
4676 | switch (gfc_match (" ( ")) |
4677 | { |
4678 | case MATCH_YES: |
4679 | if (gfc_match_symbol (&proc_name, /* host assoc = */ true) != MATCH_YES |
4680 | || gfc_match (" ) ") != MATCH_YES) |
4681 | return MATCH_ERROR; |
4682 | break; |
4683 | case MATCH_NO: proc_name = NULL__null; needs_space = true; break; |
4684 | case MATCH_ERROR: return MATCH_ERROR; |
4685 | } |
4686 | |
4687 | if (gfc_match_omp_clauses (&c, OMP_DECLARE_SIMD_CLAUSES(omp_mask (OMP_CLAUSE_SIMDLEN) | OMP_CLAUSE_LINEAR | OMP_CLAUSE_UNIFORM | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_INBRANCH | OMP_CLAUSE_NOTINBRANCH ), true, |
4688 | needs_space) != MATCH_YES) |
4689 | return MATCH_ERROR; |
4690 | |
4691 | if (gfc_current_ns->is_block_data) |
4692 | { |
4693 | gfc_free_omp_clauses (c); |
4694 | return MATCH_YES; |
4695 | } |
4696 | |
4697 | ods = gfc_get_omp_declare_simd ()((gfc_omp_declare_simd *) xcalloc (1, sizeof (gfc_omp_declare_simd ))); |
4698 | ods->where = where; |
4699 | ods->proc_name = proc_name; |
4700 | ods->clauses = c; |
4701 | ods->next = gfc_current_ns->omp_declare_simd; |
4702 | gfc_current_ns->omp_declare_simd = ods; |
4703 | return MATCH_YES; |
4704 | } |
4705 | |
4706 | |
4707 | static bool |
4708 | match_udr_expr (gfc_symtree *omp_sym1, gfc_symtree *omp_sym2) |
4709 | { |
4710 | match m; |
4711 | locus old_loc = gfc_current_locus; |
4712 | char sname[GFC_MAX_SYMBOL_LEN63 + 1]; |
4713 | gfc_symbol *sym; |
4714 | gfc_namespace *ns = gfc_current_ns; |
4715 | gfc_expr *lvalue = NULL__null, *rvalue = NULL__null; |
4716 | gfc_symtree *st; |
4717 | gfc_actual_arglist *arglist; |
4718 | |
4719 | m = gfc_match (" %v =", &lvalue); |
4720 | if (m != MATCH_YES) |
4721 | gfc_current_locus = old_loc; |
4722 | else |
4723 | { |
4724 | m = gfc_match (" %e )", &rvalue); |
4725 | if (m == MATCH_YES) |
4726 | { |
4727 | ns->code = gfc_get_code (EXEC_ASSIGN); |
4728 | ns->code->expr1 = lvalue; |
4729 | ns->code->expr2 = rvalue; |
4730 | ns->code->loc = old_loc; |
4731 | return true; |
4732 | } |
4733 | |
4734 | gfc_current_locus = old_loc; |
4735 | gfc_free_expr (lvalue); |
4736 | } |
4737 | |
4738 | m = gfc_match (" %n", sname); |
4739 | if (m != MATCH_YES) |
4740 | return false; |
4741 | |
4742 | if (strcmp (sname, omp_sym1->name) == 0 |
4743 | || strcmp (sname, omp_sym2->name) == 0) |
4744 | return false; |
4745 | |
4746 | gfc_current_ns = ns->parent; |
4747 | if (gfc_get_ha_sym_tree (sname, &st)) |
4748 | return false; |
4749 | |
4750 | sym = st->n.sym; |
4751 | if (sym->attr.flavor != FL_PROCEDURE |
4752 | && sym->attr.flavor != FL_UNKNOWN) |
4753 | return false; |
4754 | |
4755 | if (!sym->attr.generic |
4756 | && !sym->attr.subroutine |
4757 | && !sym->attr.function) |
4758 | { |
4759 | if (!(sym->attr.external && !sym->attr.referenced)) |
4760 | { |
4761 | /* ...create a symbol in this scope... */ |
4762 | if (sym->ns != gfc_current_ns |
4763 | && gfc_get_sym_tree (sname, NULL__null, &st, false) == 1) |
4764 | return false; |
4765 | |
4766 | if (sym != st->n.sym) |
4767 | sym = st->n.sym; |
4768 | } |
4769 | |
4770 | /* ...and then to try to make the symbol into a subroutine. */ |
4771 | if (!gfc_add_subroutine (&sym->attr, sym->name, NULL__null)) |
4772 | return false; |
4773 | } |
4774 | |
4775 | gfc_set_sym_referenced (sym); |
4776 | gfc_gobble_whitespace (); |
4777 | if (gfc_peek_ascii_char () != '(') |
4778 | return false; |
4779 | |
4780 | gfc_current_ns = ns; |
4781 | m = gfc_match_actual_arglist (1, &arglist); |
4782 | if (m != MATCH_YES) |
4783 | return false; |
4784 | |
4785 | if (gfc_match_char (')') != MATCH_YES) |
4786 | return false; |
4787 | |
4788 | ns->code = gfc_get_code (EXEC_CALL); |
4789 | ns->code->symtree = st; |
4790 | ns->code->ext.actual = arglist; |
4791 | ns->code->loc = old_loc; |
4792 | return true; |
4793 | } |
4794 | |
4795 | static bool |
4796 | gfc_omp_udr_predef (gfc_omp_reduction_op rop, const char *name, |
4797 | gfc_typespec *ts, const char **n) |
4798 | { |
4799 | if (!gfc_numeric_ts (ts) && ts->type != BT_LOGICAL) |
4800 | return false; |
4801 | |
4802 | switch (rop) |
4803 | { |
4804 | case OMP_REDUCTION_PLUS: |
4805 | case OMP_REDUCTION_MINUS: |
4806 | case OMP_REDUCTION_TIMES: |
4807 | return ts->type != BT_LOGICAL; |
4808 | case OMP_REDUCTION_AND: |
4809 | case OMP_REDUCTION_OR: |
4810 | case OMP_REDUCTION_EQV: |
4811 | case OMP_REDUCTION_NEQV: |
4812 | return ts->type == BT_LOGICAL; |
4813 | case OMP_REDUCTION_USER: |
4814 | if (name[0] != '.' && (ts->type == BT_INTEGER || ts->type == BT_REAL)) |
4815 | { |
4816 | gfc_symbol *sym; |
4817 | |
4818 | gfc_find_symbol (name, NULL__null, 1, &sym); |
4819 | if (sym != NULL__null) |
4820 | { |
4821 | if (sym->attr.intrinsic) |
4822 | *n = sym->name; |
4823 | else if ((sym->attr.flavor != FL_UNKNOWN |
4824 | && sym->attr.flavor != FL_PROCEDURE) |
4825 | || sym->attr.external |
4826 | || sym->attr.generic |
4827 | || sym->attr.entry |
4828 | || sym->attr.result |
4829 | || sym->attr.dummy |
4830 | || sym->attr.subroutine |
4831 | || sym->attr.pointer |
4832 | || sym->attr.target |
4833 | || sym->attr.cray_pointer |
4834 | || sym->attr.cray_pointee |
4835 | || (sym->attr.proc != PROC_UNKNOWN |
4836 | && sym->attr.proc != PROC_INTRINSIC) |
4837 | || sym->attr.if_source != IFSRC_UNKNOWN |
4838 | || sym == sym->ns->proc_name) |
4839 | *n = NULL__null; |
4840 | else |
4841 | *n = sym->name; |
4842 | } |
4843 | else |
4844 | *n = name; |
4845 | if (*n |
4846 | && (strcmp (*n, "max") == 0 || strcmp (*n, "min") == 0)) |
4847 | return true; |
4848 | else if (*n |
4849 | && ts->type == BT_INTEGER |
4850 | && (strcmp (*n, "iand") == 0 |
4851 | || strcmp (*n, "ior") == 0 |
4852 | || strcmp (*n, "ieor") == 0)) |
4853 | return true; |
4854 | } |
4855 | break; |
4856 | default: |
4857 | break; |
4858 | } |
4859 | return false; |
4860 | } |
4861 | |
4862 | gfc_omp_udr * |
4863 | gfc_omp_udr_find (gfc_symtree *st, gfc_typespec *ts) |
4864 | { |
4865 | gfc_omp_udr *omp_udr; |
4866 | |
4867 | if (st == NULL__null) |
4868 | return NULL__null; |
4869 | |
4870 | for (omp_udr = st->n.omp_udr; omp_udr; omp_udr = omp_udr->next) |
4871 | if (omp_udr->ts.type == ts->type |
4872 | || ((omp_udr->ts.type == BT_DERIVED || omp_udr->ts.type == BT_CLASS) |
4873 | && (ts->type == BT_DERIVED || ts->type == BT_CLASS))) |
4874 | { |
4875 | if (omp_udr->ts.type == BT_DERIVED || omp_udr->ts.type == BT_CLASS) |
4876 | { |
4877 | if (strcmp (omp_udr->ts.u.derived->name, ts->u.derived->name) == 0) |
4878 | return omp_udr; |
4879 | } |
4880 | else if (omp_udr->ts.kind == ts->kind) |
4881 | { |
4882 | if (omp_udr->ts.type == BT_CHARACTER) |
4883 | { |
4884 | if (omp_udr->ts.u.cl->length == NULL__null |
4885 | || ts->u.cl->length == NULL__null) |
4886 | return omp_udr; |
4887 | if (omp_udr->ts.u.cl->length->expr_type != EXPR_CONSTANT) |
4888 | return omp_udr; |
4889 | if (ts->u.cl->length->expr_type != EXPR_CONSTANT) |
4890 | return omp_udr; |
4891 | if (omp_udr->ts.u.cl->length->ts.type != BT_INTEGER) |
4892 | return omp_udr; |
4893 | if (ts->u.cl->length->ts.type != BT_INTEGER) |
4894 | return omp_udr; |
4895 | if (gfc_compare_expr (omp_udr->ts.u.cl->length, |
4896 | ts->u.cl->length, INTRINSIC_EQ) != 0) |
4897 | continue; |
4898 | } |
4899 | return omp_udr; |
4900 | } |
4901 | } |
4902 | return NULL__null; |
4903 | } |
4904 | |
4905 | match |
4906 | gfc_match_omp_declare_reduction (void) |
4907 | { |
4908 | match m; |
4909 | gfc_intrinsic_op op; |
4910 | char name[GFC_MAX_SYMBOL_LEN63 + 3]; |
4911 | auto_vec<gfc_typespec, 5> tss; |
4912 | gfc_typespec ts; |
4913 | unsigned int i; |
4914 | gfc_symtree *st; |
4915 | locus where = gfc_current_locus; |
4916 | locus end_loc = gfc_current_locus; |
4917 | bool end_loc_set = false; |
4918 | gfc_omp_reduction_op rop = OMP_REDUCTION_NONE; |
4919 | |
4920 | if (gfc_match_char ('(') != MATCH_YES) |
4921 | return MATCH_ERROR; |
4922 | |
4923 | m = gfc_match (" %o : ", &op); |
4924 | if (m == MATCH_ERROR) |
4925 | return MATCH_ERROR; |
4926 | if (m == MATCH_YES) |
4927 | { |
4928 | snprintf (name, sizeof name, "operator %s", gfc_op2string (op)); |
4929 | rop = (gfc_omp_reduction_op) op; |
4930 | } |
4931 | else |
4932 | { |
4933 | m = gfc_match_defined_op_name (name + 1, 1); |
4934 | if (m == MATCH_ERROR) |
4935 | return MATCH_ERROR; |
4936 | if (m == MATCH_YES) |
4937 | { |
4938 | name[0] = '.'; |
4939 | strcat (name, "."); |
4940 | if (gfc_match (" : ") != MATCH_YES) |
4941 | return MATCH_ERROR; |
4942 | } |
4943 | else |
4944 | { |
4945 | if (gfc_match (" %n : ", name) != MATCH_YES) |
4946 | return MATCH_ERROR; |
4947 | } |
4948 | rop = OMP_REDUCTION_USER; |
4949 | } |
4950 | |
4951 | m = gfc_match_type_spec (&ts); |
4952 | if (m != MATCH_YES) |
4953 | return MATCH_ERROR; |
4954 | /* Treat len=: the same as len=*. */ |
4955 | if (ts.type == BT_CHARACTER) |
4956 | ts.deferred = false; |
4957 | tss.safe_push (ts); |
4958 | |
4959 | while (gfc_match_char (',') == MATCH_YES) |
4960 | { |
4961 | m = gfc_match_type_spec (&ts); |
4962 | if (m != MATCH_YES) |
4963 | return MATCH_ERROR; |
4964 | tss.safe_push (ts); |
4965 | } |
4966 | if (gfc_match_char (':') != MATCH_YES) |
4967 | return MATCH_ERROR; |
4968 | |
4969 | st = gfc_find_symtree (gfc_current_ns->omp_udr_root, name); |
4970 | for (i = 0; i < tss.length (); i++) |
4971 | { |
4972 | gfc_symtree *omp_out, *omp_in; |
4973 | gfc_symtree *omp_priv = NULL__null, *omp_orig = NULL__null; |
4974 | gfc_namespace *combiner_ns, *initializer_ns = NULL__null; |
4975 | gfc_omp_udr *prev_udr, *omp_udr; |
4976 | const char *predef_name = NULL__null; |
4977 | |
4978 | omp_udr = gfc_get_omp_udr ()((gfc_omp_udr *) xcalloc (1, sizeof (gfc_omp_udr))); |
4979 | omp_udr->name = gfc_get_string ("%s", name); |
4980 | omp_udr->rop = rop; |
4981 | omp_udr->ts = tss[i]; |
4982 | omp_udr->where = where; |
4983 | |
4984 | gfc_current_ns = combiner_ns = gfc_get_namespace (gfc_current_ns, 1); |
4985 | combiner_ns->proc_name = combiner_ns->parent->proc_name; |
4986 | |
4987 | gfc_get_sym_tree ("omp_out", combiner_ns, &omp_out, false); |
4988 | gfc_get_sym_tree ("omp_in", combiner_ns, &omp_in, false); |
4989 | combiner_ns->omp_udr_ns = 1; |
4990 | omp_out->n.sym->ts = tss[i]; |
4991 | omp_in->n.sym->ts = tss[i]; |
4992 | omp_out->n.sym->attr.omp_udr_artificial_var = 1; |
4993 | omp_in->n.sym->attr.omp_udr_artificial_var = 1; |
4994 | omp_out->n.sym->attr.flavor = FL_VARIABLE; |
4995 | omp_in->n.sym->attr.flavor = FL_VARIABLE; |
4996 | gfc_commit_symbols (); |
4997 | omp_udr->combiner_ns = combiner_ns; |
4998 | omp_udr->omp_out = omp_out->n.sym; |
4999 | omp_udr->omp_in = omp_in->n.sym; |
5000 | |
5001 | locus old_loc = gfc_current_locus; |
5002 | |
5003 | if (!match_udr_expr (omp_out, omp_in)) |
5004 | { |
5005 | syntax: |
5006 | gfc_current_locus = old_loc; |
5007 | gfc_current_ns = combiner_ns->parent; |
5008 | gfc_undo_symbols (); |
5009 | gfc_free_omp_udr (omp_udr); |
5010 | return MATCH_ERROR; |
5011 | } |
5012 | |
5013 | if (gfc_match (" initializer ( ") == MATCH_YES) |
5014 | { |
5015 | gfc_current_ns = combiner_ns->parent; |
5016 | initializer_ns = gfc_get_namespace (gfc_current_ns, 1); |
5017 | gfc_current_ns = initializer_ns; |
5018 | initializer_ns->proc_name = initializer_ns->parent->proc_name; |
5019 | |
5020 | gfc_get_sym_tree ("omp_priv", initializer_ns, &omp_priv, false); |
5021 | gfc_get_sym_tree ("omp_orig", initializer_ns, &omp_orig, false); |
5022 | initializer_ns->omp_udr_ns = 1; |
5023 | omp_priv->n.sym->ts = tss[i]; |
5024 | omp_orig->n.sym->ts = tss[i]; |
5025 | omp_priv->n.sym->attr.omp_udr_artificial_var = 1; |
5026 | omp_orig->n.sym->attr.omp_udr_artificial_var = 1; |
5027 | omp_priv->n.sym->attr.flavor = FL_VARIABLE; |
5028 | omp_orig->n.sym->attr.flavor = FL_VARIABLE; |
5029 | gfc_commit_symbols (); |
5030 | omp_udr->initializer_ns = initializer_ns; |
5031 | omp_udr->omp_priv = omp_priv->n.sym; |
5032 | omp_udr->omp_orig = omp_orig->n.sym; |
5033 | |
5034 | if (!match_udr_expr (omp_priv, omp_orig)) |
5035 | goto syntax; |
5036 | } |
5037 | |
5038 | gfc_current_ns = combiner_ns->parent; |
5039 | if (!end_loc_set) |
5040 | { |
5041 | end_loc_set = true; |
5042 | end_loc = gfc_current_locus; |
5043 | } |
5044 | gfc_current_locus = old_loc; |
5045 | |
5046 | prev_udr = gfc_omp_udr_find (st, &tss[i]); |
5047 | if (gfc_omp_udr_predef (rop, name, &tss[i], &predef_name) |
5048 | /* Don't error on !$omp declare reduction (min : integer : ...) |
5049 | just yet, there could be integer :: min afterwards, |
5050 | making it valid. When the UDR is resolved, we'll get |
5051 | to it again. */ |
5052 | && (rop != OMP_REDUCTION_USER || name[0] == '.')) |
5053 | { |
5054 | if (predef_name) |
5055 | gfc_error_now ("Redefinition of predefined %s " |
5056 | "!$OMP DECLARE REDUCTION at %L", |
5057 | predef_name, &where); |
5058 | else |
5059 | gfc_error_now ("Redefinition of predefined " |
5060 | "!$OMP DECLARE REDUCTION at %L", &where); |
5061 | } |
5062 | else if (prev_udr) |
5063 | { |
5064 | gfc_error_now ("Redefinition of !$OMP DECLARE REDUCTION at %L", |
5065 | &where); |
5066 | gfc_error_now ("Previous !$OMP DECLARE REDUCTION at %L", |
5067 | &prev_udr->where); |
5068 | } |
5069 | else if (st) |
5070 | { |
5071 | omp_udr->next = st->n.omp_udr; |
5072 | st->n.omp_udr = omp_udr; |
5073 | } |
5074 | else |
5075 | { |
5076 | st = gfc_new_symtree (&gfc_current_ns->omp_udr_root, name); |
5077 | st->n.omp_udr = omp_udr; |
5078 | } |
5079 | } |
5080 | |
5081 | if (end_loc_set) |
5082 | { |
5083 | gfc_current_locus = end_loc; |
5084 | if (gfc_match_omp_eos () != MATCH_YES) |
5085 | { |
5086 | gfc_error ("Unexpected junk after !$OMP DECLARE REDUCTION at %C"); |
5087 | gfc_current_locus = where; |
5088 | return MATCH_ERROR; |
5089 | } |
5090 | |
5091 | return MATCH_YES; |
5092 | } |
5093 | gfc_clear_error (); |
5094 | return MATCH_ERROR; |
5095 | } |
5096 | |
5097 | |
5098 | match |
5099 | gfc_match_omp_declare_target (void) |
5100 | { |
5101 | locus old_loc; |
5102 | match m; |
5103 | gfc_omp_clauses *c = NULL__null; |
5104 | int list; |
5105 | gfc_omp_namelist *n; |
5106 | gfc_symbol *s; |
5107 | |
5108 | old_loc = gfc_current_locus; |
5109 | |
5110 | if (gfc_current_ns->proc_name |
5111 | && gfc_match_omp_eos () == MATCH_YES) |
5112 | { |
5113 | if (!gfc_add_omp_declare_target (&gfc_current_ns->proc_name->attr, |
5114 | gfc_current_ns->proc_name->name, |
5115 | &old_loc)) |
5116 | goto cleanup; |
5117 | return MATCH_YES; |
5118 | } |
5119 | |
5120 | if (gfc_current_ns->proc_name |
5121 | && gfc_current_ns->proc_name->attr.if_source == IFSRC_IFBODY) |
5122 | { |
5123 | gfc_error ("Only the !$OMP DECLARE TARGET form without " |
5124 | "clauses is allowed in interface block at %C"); |
5125 | goto cleanup; |
5126 | } |
5127 | |
5128 | m = gfc_match (" ("); |
5129 | if (m == MATCH_YES) |
5130 | { |
5131 | c = gfc_get_omp_clauses ()((gfc_omp_clauses *) xcalloc (1, sizeof (gfc_omp_clauses))); |
5132 | gfc_current_locus = old_loc; |
5133 | m = gfc_match_omp_to_link (" (", &c->lists[OMP_LIST_ENTER]); |
5134 | if (m != MATCH_YES) |
5135 | goto syntax; |
5136 | if (gfc_match_omp_eos () != MATCH_YES) |
5137 | { |
5138 | gfc_error ("Unexpected junk after !$OMP DECLARE TARGET at %C"); |
5139 | goto cleanup; |
5140 | } |
5141 | } |
5142 | else if (gfc_match_omp_clauses (&c, OMP_DECLARE_TARGET_CLAUSES(omp_mask (OMP_CLAUSE_ENTER) | OMP_CLAUSE_LINK | OMP_CLAUSE_DEVICE_TYPE | OMP_CLAUSE_TO)) != MATCH_YES) |
5143 | return MATCH_ERROR; |
5144 | |
5145 | gfc_buffer_error (false); |
5146 | |
5147 | static const int to_enter_link_lists[] |
5148 | = { OMP_LIST_TO, OMP_LIST_ENTER, OMP_LIST_LINK }; |
5149 | for (size_t listn = 0; listn < ARRAY_SIZE (to_enter_link_lists)(sizeof (to_enter_link_lists) / sizeof ((to_enter_link_lists) [0])) |
5150 | && (list = to_enter_link_lists[listn], true); ++listn) |
5151 | for (n = c->lists[list]; n; n = n->next) |
5152 | if (n->sym) |
5153 | n->sym->mark = 0; |
5154 | else if (n->u.common->head) |
5155 | n->u.common->head->mark = 0; |
5156 | |
5157 | for (size_t listn = 0; listn < ARRAY_SIZE (to_enter_link_lists)(sizeof (to_enter_link_lists) / sizeof ((to_enter_link_lists) [0])) |
5158 | && (list = to_enter_link_lists[listn], true); ++listn) |
5159 | for (n = c->lists[list]; n; n = n->next) |
5160 | if (n->sym) |
5161 | { |
5162 | if (n->sym->attr.in_common) |
5163 | gfc_error_now ("OMP DECLARE TARGET variable at %L is an " |
5164 | "element of a COMMON block", &n->where); |
5165 | else if (n->sym->mark) |
5166 | gfc_error_now ("Variable at %L mentioned multiple times in " |
5167 | "clauses of the same OMP DECLARE TARGET directive", |
5168 | &n->where); |
5169 | else if (n->sym->attr.omp_declare_target |
5170 | && n->sym->attr.omp_declare_target_link |
5171 | && list != OMP_LIST_LINK) |
5172 | gfc_error_now ("OMP DECLARE TARGET variable at %L previously " |
5173 | "mentioned in LINK clause and later in %s clause", |
5174 | &n->where, list == OMP_LIST_TO ? "TO" : "ENTER"); |
5175 | else if (n->sym->attr.omp_declare_target |
5176 | && !n->sym->attr.omp_declare_target_link |
5177 | && list == OMP_LIST_LINK) |
5178 | gfc_error_now ("OMP DECLARE TARGET variable at %L previously " |
5179 | "mentioned in TO or ENTER clause and later in " |
5180 | "LINK clause", &n->where); |
5181 | else if (gfc_add_omp_declare_target (&n->sym->attr, n->sym->name, |
5182 | &n->sym->declared_at)) |
5183 | { |
5184 | if (list == OMP_LIST_LINK) |
5185 | gfc_add_omp_declare_target_link (&n->sym->attr, n->sym->name, |
5186 | &n->sym->declared_at); |
5187 | } |
5188 | if (c->device_type != OMP_DEVICE_TYPE_UNSET) |
5189 | { |
5190 | if (n->sym->attr.omp_device_type != OMP_DEVICE_TYPE_UNSET |
5191 | && n->sym->attr.omp_device_type != c->device_type) |
5192 | gfc_error_now ("List item %qs at %L set in previous OMP DECLARE " |
5193 | "TARGET directive to a different DEVICE_TYPE", |
5194 | n->sym->name, &n->where); |
5195 | n->sym->attr.omp_device_type = c->device_type; |
5196 | } |
5197 | n->sym->mark = 1; |
5198 | } |
5199 | else if (n->u.common->omp_declare_target |
5200 | && n->u.common->omp_declare_target_link |
5201 | && list != OMP_LIST_LINK) |
5202 | gfc_error_now ("OMP DECLARE TARGET COMMON at %L previously " |
5203 | "mentioned in LINK clause and later in %s clause", |
5204 | &n->where, list == OMP_LIST_TO ? "TO" : "ENTER"); |
5205 | else if (n->u.common->omp_declare_target |
5206 | && !n->u.common->omp_declare_target_link |
5207 | && list == OMP_LIST_LINK) |
5208 | gfc_error_now ("OMP DECLARE TARGET COMMON at %L previously " |
5209 | "mentioned in TO or ENTER clause and later in " |
5210 | "LINK clause", &n->where); |
5211 | else if (n->u.common->head && n->u.common->head->mark) |
5212 | gfc_error_now ("COMMON at %L mentioned multiple times in " |
5213 | "clauses of the same OMP DECLARE TARGET directive", |
5214 | &n->where); |
5215 | else |
5216 | { |
5217 | n->u.common->omp_declare_target = 1; |
5218 | n->u.common->omp_declare_target_link = (list == OMP_LIST_LINK); |
5219 | if (n->u.common->omp_device_type != OMP_DEVICE_TYPE_UNSET |
5220 | && n->u.common->omp_device_type != c->device_type) |
5221 | gfc_error_now ("COMMON at %L set in previous OMP DECLARE " |
5222 | "TARGET directive to a different DEVICE_TYPE", |
5223 | &n->where); |
5224 | n->u.common->omp_device_type = c->device_type; |
5225 | |
5226 | for (s = n->u.common->head; s; s = s->common_next) |
5227 | { |
5228 | s->mark = 1; |
5229 | if (gfc_add_omp_declare_target (&s->attr, s->name, |
5230 | &s->declared_at)) |
5231 | { |
5232 | if (list == OMP_LIST_LINK) |
5233 | gfc_add_omp_declare_target_link (&s->attr, s->name, |
5234 | &s->declared_at); |
5235 | } |
5236 | if (s->attr.omp_device_type != OMP_DEVICE_TYPE_UNSET |
5237 | && s->attr.omp_device_type != c->device_type) |
5238 | gfc_error_now ("List item %qs at %L set in previous OMP DECLARE" |
5239 | " TARGET directive to a different DEVICE_TYPE", |
5240 | s->name, &n->where); |
5241 | s->attr.omp_device_type = c->device_type; |
5242 | } |
5243 | } |
5244 | if (c->device_type |
5245 | && !c->lists[OMP_LIST_ENTER] |
5246 | && !c->lists[OMP_LIST_TO] |
5247 | && !c->lists[OMP_LIST_LINK]) |
5248 | gfc_warning_now (0, "OMP DECLARE TARGET directive at %L with only " |
5249 | "DEVICE_TYPE clause is ignored", &old_loc); |
5250 | |
5251 | gfc_buffer_error (true); |
5252 | |
5253 | if (c) |
5254 | gfc_free_omp_clauses (c); |
5255 | return MATCH_YES; |
5256 | |
5257 | syntax: |
5258 | gfc_error ("Syntax error in !$OMP DECLARE TARGET list at %C"); |
5259 | |
5260 | cleanup: |
5261 | gfc_current_locus = old_loc; |
5262 | if (c) |
5263 | gfc_free_omp_clauses (c); |
5264 | return MATCH_ERROR; |
5265 | } |
5266 | |
5267 | |
5268 | static const char *const omp_construct_selectors[] = { |
5269 | "simd", "target", "teams", "parallel", "do", NULL__null }; |
5270 | static const char *const omp_device_selectors[] = { |
5271 | "kind", "isa", "arch", NULL__null }; |
5272 | static const char *const omp_implementation_selectors[] = { |
5273 | "vendor", "extension", "atomic_default_mem_order", "unified_address", |
5274 | "unified_shared_memory", "dynamic_allocators", "reverse_offload", NULL__null }; |
5275 | static const char *const omp_user_selectors[] = { |
5276 | "condition", NULL__null }; |
5277 | |
5278 | |
5279 | /* OpenMP 5.0: |
5280 | |
5281 | trait-selector: |
5282 | trait-selector-name[([trait-score:]trait-property[,trait-property[,...]])] |
5283 | |
5284 | trait-score: |
5285 | score(score-expression) */ |
5286 | |
5287 | match |
5288 | gfc_match_omp_context_selector (gfc_omp_set_selector *oss) |
5289 | { |
5290 | do |
5291 | { |
5292 | char selector[GFC_MAX_SYMBOL_LEN63 + 1]; |
5293 | |
5294 | if (gfc_match_name (selector) != MATCH_YES) |
5295 | { |
5296 | gfc_error ("expected trait selector name at %C"); |
5297 | return MATCH_ERROR; |
5298 | } |
5299 | |
5300 | gfc_omp_selector *os = gfc_get_omp_selector ()((gfc_omp_selector *) xcalloc (1, sizeof (gfc_omp_selector))); |
5301 | os->trait_selector_name = XNEWVEC (char, strlen (selector) + 1)((char *) xmalloc (sizeof (char) * (strlen (selector) + 1))); |
5302 | strcpy (os->trait_selector_name, selector); |
5303 | os->next = oss->trait_selectors; |
5304 | oss->trait_selectors = os; |
5305 | |
5306 | const char *const *selectors = NULL__null; |
5307 | bool allow_score = true; |
5308 | bool allow_user = false; |
5309 | int property_limit = 0; |
5310 | enum gfc_omp_trait_property_kind property_kind = CTX_PROPERTY_NONE; |
5311 | switch (oss->trait_set_selector_name[0]) |
5312 | { |
5313 | case 'c': /* construct */ |
5314 | selectors = omp_construct_selectors; |
5315 | allow_score = false; |
5316 | property_limit = 1; |
5317 | property_kind = CTX_PROPERTY_SIMD; |
5318 | break; |
5319 | case 'd': /* device */ |
5320 | selectors = omp_device_selectors; |
5321 | allow_score = false; |
5322 | allow_user = true; |
5323 | property_limit = 3; |
5324 | property_kind = CTX_PROPERTY_NAME_LIST; |
5325 | break; |
5326 | case 'i': /* implementation */ |
5327 | selectors = omp_implementation_selectors; |
5328 | allow_user = true; |
5329 | property_limit = 3; |
5330 | property_kind = CTX_PROPERTY_NAME_LIST; |
5331 | break; |
5332 | case 'u': /* user */ |
5333 | selectors = omp_user_selectors; |
5334 | property_limit = 1; |
5335 | property_kind = CTX_PROPERTY_EXPR; |
5336 | break; |
5337 | default: |
5338 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/openmp.cc" , 5338, __FUNCTION__)); |
5339 | } |
5340 | for (int i = 0; ; i++) |
5341 | { |
5342 | if (selectors[i] == NULL__null) |
5343 | { |
5344 | if (allow_user) |
5345 | { |
5346 | property_kind = CTX_PROPERTY_USER; |
5347 | break; |
5348 | } |
5349 | else |
5350 | { |
5351 | gfc_error ("selector %qs not allowed for context selector " |
5352 | "set %qs at %C", |
5353 | selector, oss->trait_set_selector_name); |
5354 | return MATCH_ERROR; |
5355 | } |
5356 | } |
5357 | if (i == property_limit) |
5358 | property_kind = CTX_PROPERTY_NONE; |
5359 | if (strcmp (selectors[i], selector) == 0) |
5360 | break; |
5361 | } |
5362 | if (property_kind == CTX_PROPERTY_NAME_LIST |
5363 | && oss->trait_set_selector_name[0] == 'i' |
5364 | && strcmp (selector, "atomic_default_mem_order") == 0) |
5365 | property_kind = CTX_PROPERTY_ID; |
5366 | |
5367 | if (gfc_match (" (") == MATCH_YES) |
5368 | { |
5369 | if (property_kind == CTX_PROPERTY_NONE) |
5370 | { |
5371 | gfc_error ("selector %qs does not accept any properties at %C", |
5372 | selector); |
5373 | return MATCH_ERROR; |
5374 | } |
5375 | |
5376 | if (allow_score && gfc_match (" score") == MATCH_YES) |
5377 | { |
5378 | if (gfc_match (" (") != MATCH_YES) |
5379 | { |
5380 | gfc_error ("expected %<(%> at %C"); |
5381 | return MATCH_ERROR; |
5382 | } |
5383 | if (gfc_match_expr (&os->score) != MATCH_YES |
5384 | || !gfc_resolve_expr (os->score) |
5385 | || os->score->ts.type != BT_INTEGER |
5386 | || os->score->rank != 0) |
5387 | { |
5388 | gfc_error ("score argument must be constant integer " |
5389 | "expression at %C"); |
5390 | return MATCH_ERROR; |
5391 | } |
5392 | |
5393 | if (os->score->expr_type == EXPR_CONSTANT |
5394 | && mpz_sgn (os->score->value.integer)((os->score->value.integer)->_mp_size < 0 ? -1 : ( os->score->value.integer)->_mp_size > 0) < 0) |
5395 | { |
5396 | gfc_error ("score argument must be non-negative at %C"); |
5397 | return MATCH_ERROR; |
5398 | } |
5399 | |
5400 | if (gfc_match (" )") != MATCH_YES) |
5401 | { |
5402 | gfc_error ("expected %<)%> at %C"); |
5403 | return MATCH_ERROR; |
5404 | } |
5405 | |
5406 | if (gfc_match (" :") != MATCH_YES) |
5407 | { |
5408 | gfc_error ("expected : at %C"); |
5409 | return MATCH_ERROR; |
5410 | } |
5411 | } |
5412 | |
5413 | gfc_omp_trait_property *otp = gfc_get_omp_trait_property ()((gfc_omp_trait_property *) xcalloc (1, sizeof (gfc_omp_trait_property ))); |
5414 | otp->property_kind = property_kind; |
5415 | otp->next = os->properties; |
5416 | os->properties = otp; |
5417 | |
5418 | switch (property_kind) |
5419 | { |
5420 | case CTX_PROPERTY_USER: |
5421 | do |
5422 | { |
5423 | if (gfc_match_expr (&otp->expr) != MATCH_YES) |
5424 | { |
5425 | gfc_error ("property must be constant integer " |
5426 | "expression or string literal at %C"); |
5427 | return MATCH_ERROR; |
5428 | } |
5429 | |
5430 | if (gfc_match (" ,") != MATCH_YES) |
5431 | break; |
5432 | } |
5433 | while (1); |
5434 | break; |
5435 | case CTX_PROPERTY_ID: |
5436 | { |
5437 | char buf[GFC_MAX_SYMBOL_LEN63 + 1]; |
5438 | if (gfc_match_name (buf) == MATCH_YES) |
5439 | { |
5440 | otp->name = XNEWVEC (char, strlen (buf) + 1)((char *) xmalloc (sizeof (char) * (strlen (buf) + 1))); |
5441 | strcpy (otp->name, buf); |
5442 | } |
5443 | else |
5444 | { |
5445 | gfc_error ("expected identifier at %C"); |
5446 | return MATCH_ERROR; |
5447 | } |
5448 | } |
5449 | break; |
5450 | case CTX_PROPERTY_NAME_LIST: |
5451 | do |
5452 | { |
5453 | char buf[GFC_MAX_SYMBOL_LEN63 + 1]; |
5454 | if (gfc_match_name (buf) == MATCH_YES) |
5455 | { |
5456 | otp->name = XNEWVEC (char, strlen (buf) + 1)((char *) xmalloc (sizeof (char) * (strlen (buf) + 1))); |
5457 | strcpy (otp->name, buf); |
5458 | otp->is_name = true; |
5459 | } |
5460 | else if (gfc_match_literal_constant (&otp->expr, 0) |
5461 | != MATCH_YES |
5462 | || otp->expr->ts.type != BT_CHARACTER) |
5463 | { |
5464 | gfc_error ("expected identifier or string literal " |
5465 | "at %C"); |
5466 | return MATCH_ERROR; |
5467 | } |
5468 | |
5469 | if (gfc_match (" ,") == MATCH_YES) |
5470 | { |
5471 | otp = gfc_get_omp_trait_property ()((gfc_omp_trait_property *) xcalloc (1, sizeof (gfc_omp_trait_property ))); |
5472 | otp->property_kind = property_kind; |
5473 | otp->next = os->properties; |
5474 | os->properties = otp; |
5475 | } |
5476 | else |
5477 | break; |
5478 | } |
5479 | while (1); |
5480 | break; |
5481 | case CTX_PROPERTY_EXPR: |
5482 | if (gfc_match_expr (&otp->expr) != MATCH_YES) |
5483 | { |
5484 | gfc_error ("expected expression at %C"); |
5485 | return MATCH_ERROR; |
5486 | } |
5487 | if (!gfc_resolve_expr (otp->expr) |
5488 | || (otp->expr->ts.type != BT_LOGICAL |
5489 | && otp->expr->ts.type != BT_INTEGER) |
5490 | || otp->expr->rank != 0) |
5491 | { |
5492 | gfc_error ("property must be constant integer or logical " |
5493 | "expression at %C"); |
5494 | return MATCH_ERROR; |
5495 | } |
5496 | break; |
5497 | case CTX_PROPERTY_SIMD: |
5498 | { |
5499 | if (gfc_match_omp_clauses (&otp->clauses, |
5500 | OMP_DECLARE_SIMD_CLAUSES(omp_mask (OMP_CLAUSE_SIMDLEN) | OMP_CLAUSE_LINEAR | OMP_CLAUSE_UNIFORM | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_INBRANCH | OMP_CLAUSE_NOTINBRANCH ), |
5501 | true, false, false, true) |
5502 | != MATCH_YES) |
5503 | { |
5504 | gfc_error ("expected simd clause at %C"); |
5505 | return MATCH_ERROR; |
5506 | } |
5507 | break; |
5508 | } |
5509 | default: |
5510 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/openmp.cc" , 5510, __FUNCTION__)); |
5511 | } |
5512 | |
5513 | if (gfc_match (" )") != MATCH_YES) |
5514 | { |
5515 | gfc_error ("expected %<)%> at %C"); |
5516 | return MATCH_ERROR; |
5517 | } |
5518 | } |
5519 | else if (property_kind == CTX_PROPERTY_NAME_LIST |
5520 | || property_kind == CTX_PROPERTY_ID |
5521 | || property_kind == CTX_PROPERTY_EXPR) |
5522 | { |
5523 | if (gfc_match (" (") != MATCH_YES) |
5524 | { |
5525 | gfc_error ("expected %<(%> at %C"); |
5526 | return MATCH_ERROR; |
5527 | } |
5528 | } |
5529 | |
5530 | if (gfc_match (" ,") != MATCH_YES) |
5531 | break; |
5532 | } |
5533 | while (1); |
5534 | |
5535 | return MATCH_YES; |
5536 | } |
5537 | |
5538 | /* OpenMP 5.0: |
5539 | |
5540 | trait-set-selector[,trait-set-selector[,...]] |
5541 | |
5542 | trait-set-selector: |
5543 | trait-set-selector-name = { trait-selector[, trait-selector[, ...]] } |
5544 | |
5545 | trait-set-selector-name: |
5546 | constructor |
5547 | device |
5548 | implementation |
5549 | user */ |
5550 | |
5551 | match |
5552 | gfc_match_omp_context_selector_specification (gfc_omp_declare_variant *odv) |
5553 | { |
5554 | do |
5555 | { |
5556 | match m; |
5557 | const char *selector_sets[] = { "construct", "device", |
5558 | "implementation", "user" }; |
5559 | const int selector_set_count = ARRAY_SIZE (selector_sets)(sizeof (selector_sets) / sizeof ((selector_sets)[0])); |
5560 | int i; |
5561 | char buf[GFC_MAX_SYMBOL_LEN63 + 1]; |
5562 | |
5563 | m = gfc_match_name (buf); |
5564 | if (m == MATCH_YES) |
5565 | for (i = 0; i < selector_set_count; i++) |
5566 | if (strcmp (buf, selector_sets[i]) == 0) |
5567 | break; |
5568 | |
5569 | if (m != MATCH_YES || i == selector_set_count) |
5570 | { |
5571 | gfc_error ("expected %<construct%>, %<device%>, %<implementation%> " |
5572 | "or %<user%> at %C"); |
5573 | return MATCH_ERROR; |
5574 | } |
5575 | |
5576 | m = gfc_match (" ="); |
5577 | if (m != MATCH_YES) |
5578 | { |
5579 | gfc_error ("expected %<=%> at %C"); |
5580 | return MATCH_ERROR; |
5581 | } |
5582 | |
5583 | m = gfc_match (" {"); |
5584 | if (m != MATCH_YES) |
5585 | { |
5586 | gfc_error ("expected %<{%> at %C"); |
5587 | return MATCH_ERROR; |
5588 | } |
5589 | |
5590 | gfc_omp_set_selector *oss = gfc_get_omp_set_selector ()((gfc_omp_set_selector *) xcalloc (1, sizeof (gfc_omp_set_selector ))); |
5591 | oss->next = odv->set_selectors; |
5592 | oss->trait_set_selector_name = selector_sets[i]; |
5593 | odv->set_selectors = oss; |
5594 | |
5595 | if (gfc_match_omp_context_selector (oss) != MATCH_YES) |
5596 | return MATCH_ERROR; |
5597 | |
5598 | m = gfc_match (" }"); |
5599 | if (m != MATCH_YES) |
5600 | { |
5601 | gfc_error ("expected %<}%> at %C"); |
5602 | return MATCH_ERROR; |
5603 | } |
5604 | |
5605 | m = gfc_match (" ,"); |
5606 | if (m != MATCH_YES) |
5607 | break; |
5608 | } |
5609 | while (1); |
5610 | |
5611 | return MATCH_YES; |
5612 | } |
5613 | |
5614 | |
5615 | match |
5616 | gfc_match_omp_declare_variant (void) |
5617 | { |
5618 | bool first_p = true; |
5619 | char buf[GFC_MAX_SYMBOL_LEN63 + 1]; |
5620 | |
5621 | if (gfc_match (" (") != MATCH_YES) |
5622 | { |
5623 | gfc_error ("expected %<(%> at %C"); |
5624 | return MATCH_ERROR; |
5625 | } |
5626 | |
5627 | gfc_symtree *base_proc_st, *variant_proc_st; |
5628 | if (gfc_match_name (buf) != MATCH_YES) |
5629 | { |
5630 | gfc_error ("expected name at %C"); |
5631 | return MATCH_ERROR; |
5632 | } |
5633 | |
5634 | if (gfc_get_ha_sym_tree (buf, &base_proc_st)) |
5635 | return MATCH_ERROR; |
5636 | |
5637 | if (gfc_match (" :") == MATCH_YES) |
5638 | { |
5639 | if (gfc_match_name (buf) != MATCH_YES) |
5640 | { |
5641 | gfc_error ("expected variant name at %C"); |
5642 | return MATCH_ERROR; |
5643 | } |
5644 | |
5645 | if (gfc_get_ha_sym_tree (buf, &variant_proc_st)) |
5646 | return MATCH_ERROR; |
5647 | } |
5648 | else |
5649 | { |
5650 | /* Base procedure not specified. */ |
5651 | variant_proc_st = base_proc_st; |
5652 | base_proc_st = NULL__null; |
5653 | } |
5654 | |
5655 | gfc_omp_declare_variant *odv; |
5656 | odv = gfc_get_omp_declare_variant ()((gfc_omp_declare_variant *) xcalloc (1, sizeof (gfc_omp_declare_variant ))); |
5657 | odv->where = gfc_current_locus; |
5658 | odv->variant_proc_symtree = variant_proc_st; |
5659 | odv->base_proc_symtree = base_proc_st; |
5660 | odv->next = NULL__null; |
5661 | odv->error_p = false; |
5662 | |
5663 | /* Add the new declare variant to the end of the list. */ |
5664 | gfc_omp_declare_variant **prev_next = &gfc_current_ns->omp_declare_variant; |
5665 | while (*prev_next) |
5666 | prev_next = &((*prev_next)->next); |
5667 | *prev_next = odv; |
5668 | |
5669 | if (gfc_match (" )") != MATCH_YES) |
5670 | { |
5671 | gfc_error ("expected %<)%> at %C"); |
5672 | return MATCH_ERROR; |
5673 | } |
5674 | |
5675 | for (;;) |
5676 | { |
5677 | if (gfc_match (" match") != MATCH_YES) |
5678 | { |
5679 | if (first_p) |
5680 | { |
5681 | gfc_error ("expected %<match%> at %C"); |
5682 | return MATCH_ERROR; |
5683 | } |
5684 | else |
5685 | break; |
5686 | } |
5687 | |
5688 | if (gfc_match (" (") != MATCH_YES) |
5689 | { |
5690 | gfc_error ("expected %<(%> at %C"); |
5691 | return MATCH_ERROR; |
5692 | } |
5693 | |
5694 | if (gfc_match_omp_context_selector_specification (odv) != MATCH_YES) |
5695 | return MATCH_ERROR; |
5696 | |
5697 | if (gfc_match (" )") != MATCH_YES) |
5698 | { |
5699 | gfc_error ("expected %<)%> at %C"); |
5700 | return MATCH_ERROR; |
5701 | } |
5702 | |
5703 | first_p = false; |
5704 | } |
5705 | |
5706 | return MATCH_YES; |
5707 | } |
5708 | |
5709 | |
5710 | match |
5711 | gfc_match_omp_threadprivate (void) |
5712 | { |
5713 | locus old_loc; |
5714 | char n[GFC_MAX_SYMBOL_LEN63+1]; |
5715 | gfc_symbol *sym; |
5716 | match m; |
5717 | gfc_symtree *st; |
5718 | |
5719 | old_loc = gfc_current_locus; |
5720 | |
5721 | m = gfc_match (" ("); |
5722 | if (m != MATCH_YES) |
5723 | return m; |
5724 | |
5725 | for (;;) |
5726 | { |
5727 | m = gfc_match_symbol (&sym, 0); |
5728 | switch (m) |
5729 | { |
5730 | case MATCH_YES: |
5731 | if (sym->attr.in_common) |
5732 | gfc_error_now ("Threadprivate variable at %C is an element of " |
5733 | "a COMMON block"); |
5734 | else if (!gfc_add_threadprivate (&sym->attr, sym->name, &sym->declared_at)) |
5735 | goto cleanup; |
5736 | goto next_item; |
5737 | case MATCH_NO: |
5738 | break; |
5739 | case MATCH_ERROR: |
5740 | goto cleanup; |
5741 | } |
5742 | |
5743 | m = gfc_match (" / %n /", n); |
5744 | if (m == MATCH_ERROR) |
5745 | goto cleanup; |
5746 | if (m == MATCH_NO || n[0] == '\0') |
5747 | goto syntax; |
5748 | |
5749 | st = gfc_find_symtree (gfc_current_ns->common_root, n); |
5750 | if (st == NULL__null) |
5751 | { |
5752 | gfc_error ("COMMON block /%s/ not found at %C", n); |
5753 | goto cleanup; |
5754 | } |
5755 | st->n.common->threadprivate = 1; |
5756 | for (sym = st->n.common->head; sym; sym = sym->common_next) |
5757 | if (!gfc_add_threadprivate (&sym->attr, sym->name, &sym->declared_at)) |
5758 | goto cleanup; |
5759 | |
5760 | next_item: |
5761 | if (gfc_match_char (')') == MATCH_YES) |
5762 | break; |
5763 | if (gfc_match_char (',') != MATCH_YES) |
5764 | goto syntax; |
5765 | } |
5766 | |
5767 | if (gfc_match_omp_eos () != MATCH_YES) |
5768 | { |
5769 | gfc_error ("Unexpected junk after OMP THREADPRIVATE at %C"); |
5770 | goto cleanup; |
5771 | } |
5772 | |
5773 | return MATCH_YES; |
5774 | |
5775 | syntax: |
5776 | gfc_error ("Syntax error in !$OMP THREADPRIVATE list at %C"); |
5777 | |
5778 | cleanup: |
5779 | gfc_current_locus = old_loc; |
5780 | return MATCH_ERROR; |
5781 | } |
5782 | |
5783 | |
5784 | match |
5785 | gfc_match_omp_parallel (void) |
5786 | { |
5787 | return match_omp (EXEC_OMP_PARALLEL, OMP_PARALLEL_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE)); |
5788 | } |
5789 | |
5790 | |
5791 | match |
5792 | gfc_match_omp_parallel_do (void) |
5793 | { |
5794 | return match_omp (EXEC_OMP_PARALLEL_DO, |
5795 | (OMP_PARALLEL_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE) | OMP_DO_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_SCHEDULE | OMP_CLAUSE_ORDERED | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT)) |
5796 | & ~(omp_mask (OMP_CLAUSE_NOWAIT))); |
5797 | } |
5798 | |
5799 | |
5800 | match |
5801 | gfc_match_omp_parallel_do_simd (void) |
5802 | { |
5803 | return match_omp (EXEC_OMP_PARALLEL_DO_SIMD, |
5804 | (OMP_PARALLEL_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE) | OMP_DO_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_SCHEDULE | OMP_CLAUSE_ORDERED | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT) | OMP_SIMD_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_SAFELEN | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_SIMDLEN | OMP_CLAUSE_IF | OMP_CLAUSE_ORDER | OMP_CLAUSE_NOTEMPORAL)) |
5805 | & ~(omp_mask (OMP_CLAUSE_NOWAIT))); |
5806 | } |
5807 | |
5808 | |
5809 | match |
5810 | gfc_match_omp_parallel_masked (void) |
5811 | { |
5812 | return match_omp (EXEC_OMP_PARALLEL_MASKED, |
5813 | OMP_PARALLEL_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE) | OMP_MASKED_CLAUSES(omp_mask (OMP_CLAUSE_FILTER))); |
5814 | } |
5815 | |
5816 | match |
5817 | gfc_match_omp_parallel_masked_taskloop (void) |
5818 | { |
5819 | return match_omp (EXEC_OMP_PARALLEL_MASKED_TASKLOOP, |
5820 | (OMP_PARALLEL_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE) | OMP_MASKED_CLAUSES(omp_mask (OMP_CLAUSE_FILTER)) |
5821 | | OMP_TASKLOOP_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_GRAINSIZE | OMP_CLAUSE_NUM_TASKS | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_NOGROUP | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_ALLOCATE)) |
5822 | & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION))); |
5823 | } |
5824 | |
5825 | match |
5826 | gfc_match_omp_parallel_masked_taskloop_simd (void) |
5827 | { |
5828 | return match_omp (EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD, |
5829 | (OMP_PARALLEL_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE) | OMP_MASKED_CLAUSES(omp_mask (OMP_CLAUSE_FILTER)) |
5830 | | OMP_TASKLOOP_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_GRAINSIZE | OMP_CLAUSE_NUM_TASKS | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_NOGROUP | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_ALLOCATE) | OMP_SIMD_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_SAFELEN | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_SIMDLEN | OMP_CLAUSE_IF | OMP_CLAUSE_ORDER | OMP_CLAUSE_NOTEMPORAL)) |
5831 | & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION))); |
5832 | } |
5833 | |
5834 | match |
5835 | gfc_match_omp_parallel_master (void) |
5836 | { |
5837 | return match_omp (EXEC_OMP_PARALLEL_MASTER, OMP_PARALLEL_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE)); |
5838 | } |
5839 | |
5840 | match |
5841 | gfc_match_omp_parallel_master_taskloop (void) |
5842 | { |
5843 | return match_omp (EXEC_OMP_PARALLEL_MASTER_TASKLOOP, |
5844 | (OMP_PARALLEL_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE) | OMP_TASKLOOP_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_GRAINSIZE | OMP_CLAUSE_NUM_TASKS | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_NOGROUP | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_ALLOCATE)) |
5845 | & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION))); |
5846 | } |
5847 | |
5848 | match |
5849 | gfc_match_omp_parallel_master_taskloop_simd (void) |
5850 | { |
5851 | return match_omp (EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD, |
5852 | (OMP_PARALLEL_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE) | OMP_TASKLOOP_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE | OMP_CLAUSE_PRIORITY | OMP_CLAUSE_GRAINSIZE | OMP_CLAUSE_NUM_TASKS | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_NOGROUP | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_ALLOCATE) |
5853 | | OMP_SIMD_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_SAFELEN | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_SIMDLEN | OMP_CLAUSE_IF | OMP_CLAUSE_ORDER | OMP_CLAUSE_NOTEMPORAL)) |
5854 | & ~(omp_mask (OMP_CLAUSE_IN_REDUCTION))); |
5855 | } |
5856 | |
5857 | match |
5858 | gfc_match_omp_parallel_sections (void) |
5859 | { |
5860 | return match_omp (EXEC_OMP_PARALLEL_SECTIONS, |
5861 | (OMP_PARALLEL_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE) | OMP_SECTIONS_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT )) |
5862 | & ~(omp_mask (OMP_CLAUSE_NOWAIT))); |
5863 | } |
5864 | |
5865 | |
5866 | match |
5867 | gfc_match_omp_parallel_workshare (void) |
5868 | { |
5869 | return match_omp (EXEC_OMP_PARALLEL_WORKSHARE, OMP_PARALLEL_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE)); |
5870 | } |
5871 | |
5872 | void |
5873 | gfc_check_omp_requires (gfc_namespace *ns, int ref_omp_requires) |
5874 | { |
5875 | if (ns->omp_target_seen |
5876 | && (ns->omp_requires & OMP_REQ_TARGET_MASK) |
5877 | != (ref_omp_requires & OMP_REQ_TARGET_MASK)) |
5878 | { |
5879 | gcc_assert (ns->proc_name)((void)(!(ns->proc_name) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/openmp.cc" , 5879, __FUNCTION__), 0 : 0)); |
5880 | if ((ref_omp_requires & OMP_REQ_REVERSE_OFFLOAD) |
5881 | && !(ns->omp_requires & OMP_REQ_REVERSE_OFFLOAD)) |
5882 | gfc_error ("Program unit at %L has OpenMP device constructs/routines " |
5883 | "but does not set !$OMP REQUIRES REVERSE_OFFLOAD but other " |
5884 | "program units do", &ns->proc_name->declared_at); |
5885 | if ((ref_omp_requires & OMP_REQ_UNIFIED_ADDRESS) |
5886 | && !(ns->omp_requires & OMP_REQ_UNIFIED_ADDRESS)) |
5887 | gfc_error ("Program unit at %L has OpenMP device constructs/routines " |
5888 | "but does not set !$OMP REQUIRES UNIFIED_ADDRESS but other " |
5889 | "program units do", &ns->proc_name->declared_at); |
5890 | if ((ref_omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY) |
5891 | && !(ns->omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY)) |
5892 | gfc_error ("Program unit at %L has OpenMP device constructs/routines " |
5893 | "but does not set !$OMP REQUIRES UNIFIED_SHARED_MEMORY but " |
5894 | "other program units do", &ns->proc_name->declared_at); |
5895 | } |
5896 | } |
5897 | |
5898 | bool |
5899 | gfc_omp_requires_add_clause (gfc_omp_requires_kind clause, |
5900 | const char *clause_name, locus *loc, |
5901 | const char *module_name) |
5902 | { |
5903 | gfc_namespace *prog_unit = gfc_current_ns; |
5904 | while (prog_unit->parent) |
5905 | { |
5906 | if (gfc_state_stack->previous |
5907 | && gfc_state_stack->previous->state == COMP_INTERFACE) |
5908 | break; |
5909 | prog_unit = prog_unit->parent; |
5910 | } |
5911 | |
5912 | /* Requires added after use. */ |
5913 | if (prog_unit->omp_target_seen |
5914 | && (clause & OMP_REQ_TARGET_MASK) |
5915 | && !(prog_unit->omp_requires & clause)) |
5916 | { |
5917 | if (module_name) |
5918 | gfc_error ("!$OMP REQUIRES clause %qs specified via module %qs use " |
5919 | "at %L comes after using a device construct/routine", |
5920 | clause_name, module_name, loc); |
5921 | else |
5922 | gfc_error ("!$OMP REQUIRES clause %qs specified at %L comes after " |
5923 | "using a device construct/routine", clause_name, loc); |
5924 | return false; |
5925 | } |
5926 | |
5927 | /* Overriding atomic_default_mem_order clause value. */ |
5928 | if ((clause & OMP_REQ_ATOMIC_MEM_ORDER_MASK) |
5929 | && (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK) |
5930 | && (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK) |
5931 | != (int) clause) |
5932 | { |
5933 | const char *other; |
5934 | if (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST) |
5935 | other = "seq_cst"; |
5936 | else if (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL) |
5937 | other = "acq_rel"; |
5938 | else if (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_RELAXED) |
5939 | other = "relaxed"; |
5940 | else |
5941 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/fortran/openmp.cc" , 5941, __FUNCTION__)); |
5942 | |
5943 | if (module_name) |
5944 | gfc_error ("!$OMP REQUIRES clause %<atomic_default_mem_order(%s)%> " |
5945 | "specified via module %qs use at %L overrides a previous " |
5946 | "%<atomic_default_mem_order(%s)%> (which might be through " |
5947 | "using a module)", clause_name, module_name, loc, other); |
5948 | else |
5949 | gfc_error ("!$OMP REQUIRES clause %<atomic_default_mem_order(%s)%> " |
5950 | "specified at %L overrides a previous " |
5951 | "%<atomic_default_mem_order(%s)%> (which might be through " |
5952 | "using a module)", clause_name, loc, other); |
5953 | return false; |
5954 | } |
5955 | |
5956 | /* Requires via module not at program-unit level and not repeating clause. */ |
5957 | if (prog_unit != gfc_current_ns && !(prog_unit->omp_requires & clause)) |
5958 | { |
5959 | if (clause & OMP_REQ_ATOMIC_MEM_ORDER_MASK) |
5960 | gfc_error ("!$OMP REQUIRES clause %<atomic_default_mem_order(%s)%> " |
5961 | "specified via module %qs use at %L but same clause is " |
5962 | "not specified for the program unit", clause_name, |
5963 | module_name, loc); |
5964 | else |
5965 | gfc_error ("!$OMP REQUIRES clause %qs specified via module %qs use at " |
5966 | "%L but same clause is not specified for the program unit", |
5967 | clause_name, module_name, loc); |
5968 | return false; |
5969 | } |
5970 | |
5971 | if (!gfc_state_stack->previous |
5972 | || gfc_state_stack->previous->state != COMP_INTERFACE) |
5973 | prog_unit->omp_requires |= clause; |
5974 | return true; |
5975 | } |
5976 | |
5977 | match |
5978 | gfc_match_omp_requires (void) |
5979 | { |
5980 | static const char *clauses[] = {"reverse_offload", |
5981 | "unified_address", |
5982 | "unified_shared_memory", |
5983 | "dynamic_allocators", |
5984 | "atomic_default"}; |
5985 | const char *clause = NULL__null; |
5986 | int requires_clauses = 0; |
5987 | bool first = true; |
5988 | locus old_loc; |
5989 | |
5990 | if (gfc_current_ns->parent |
5991 | && (!gfc_state_stack->previous |
5992 | || gfc_state_stack->previous->state != COMP_INTERFACE)) |
5993 | { |
5994 | gfc_error ("!$OMP REQUIRES at %C must appear in the specification part " |
5995 | "of a program unit"); |
5996 | return MATCH_ERROR; |
5997 | } |
5998 | |
5999 | while (true) |
6000 | { |
6001 | old_loc = gfc_current_locus; |
6002 | gfc_omp_requires_kind requires_clause; |
6003 | if ((first || gfc_match_char (',') != MATCH_YES) |
6004 | && (first && gfc_match_space () != MATCH_YES)) |
6005 | goto error; |
6006 | first = false; |
6007 | gfc_gobble_whitespace (); |
6008 | old_loc = gfc_current_locus; |
6009 | |
6010 | if (gfc_match_omp_eos () != MATCH_NO) |
6011 | break; |
6012 | if (gfc_match (clauses[0]) == MATCH_YES) |
6013 | { |
6014 | clause = clauses[0]; |
6015 | requires_clause = OMP_REQ_REVERSE_OFFLOAD; |
6016 | if (requires_clauses & OMP_REQ_REVERSE_OFFLOAD) |
6017 | goto duplicate_clause; |
6018 | } |
6019 | else if (gfc_match (clauses[1]) == MATCH_YES) |
6020 | { |
6021 | clause = clauses[1]; |
6022 | requires_clause = OMP_REQ_UNIFIED_ADDRESS; |
6023 | if (requires_clauses & OMP_REQ_UNIFIED_ADDRESS) |
6024 | goto duplicate_clause; |
6025 | } |
6026 | else if (gfc_match (clauses[2]) == MATCH_YES) |
6027 | { |
6028 | clause = clauses[2]; |
6029 | requires_clause = OMP_REQ_UNIFIED_SHARED_MEMORY; |
6030 | if (requires_clauses & OMP_REQ_UNIFIED_SHARED_MEMORY) |
6031 | goto duplicate_clause; |
6032 | } |
6033 | else if (gfc_match (clauses[3]) == MATCH_YES) |
6034 | { |
6035 | clause = clauses[3]; |
6036 | requires_clause = OMP_REQ_DYNAMIC_ALLOCATORS; |
6037 | if (requires_clauses & OMP_REQ_DYNAMIC_ALLOCATORS) |
6038 | goto duplicate_clause; |
6039 | } |
6040 | else if (gfc_match ("atomic_default_mem_order (") == MATCH_YES) |
6041 | { |
6042 | clause = clauses[4]; |
6043 | if (requires_clauses & OMP_REQ_ATOMIC_MEM_ORDER_MASK) |
6044 | goto duplicate_clause; |
6045 | if (gfc_match (" seq_cst )") == MATCH_YES) |
6046 | { |
6047 | clause = "seq_cst"; |
6048 | requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST; |
6049 | } |
6050 | else if (gfc_match (" acq_rel )") == MATCH_YES) |
6051 | { |
6052 | clause = "acq_rel"; |
6053 | requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL; |
6054 | } |
6055 | else if (gfc_match (" relaxed )") == MATCH_YES) |
6056 | { |
6057 | clause = "relaxed"; |
6058 | requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_RELAXED; |
6059 | } |
6060 | else |
6061 | { |
6062 | gfc_error ("Expected SEQ_CST, ACQ_REL or RELAXED for " |
6063 | "ATOMIC_DEFAULT_MEM_ORDER clause at %C"); |
6064 | goto error; |
6065 | } |
6066 | } |
6067 | else |
6068 | goto error; |
6069 | |
6070 | if (!gfc_omp_requires_add_clause (requires_clause, clause, &old_loc, NULL__null)) |
6071 | goto error; |
6072 | requires_clauses |= requires_clause; |
6073 | } |
6074 | |
6075 | if (requires_clauses == 0) |
6076 | { |
6077 | if (!gfc_error_flag_test ()) |
6078 | gfc_error ("Clause expected at %C"); |
6079 | goto error; |
6080 | } |
6081 | return MATCH_YES; |
6082 | |
6083 | duplicate_clause: |
6084 | gfc_error ("%qs clause at %L specified more than once", clause, &old_loc); |
6085 | error: |
6086 | if (!gfc_error_flag_test ()) |
6087 | gfc_error ("Expected UNIFIED_ADDRESS, UNIFIED_SHARED_MEMORY, " |
6088 | "DYNAMIC_ALLOCATORS, REVERSE_OFFLOAD, or " |
6089 | "ATOMIC_DEFAULT_MEM_ORDER clause at %L", &old_loc); |
6090 | return MATCH_ERROR; |
6091 | } |
6092 | |
6093 | |
6094 | match |
6095 | gfc_match_omp_scan (void) |
6096 | { |
6097 | bool incl; |
6098 | gfc_omp_clauses *c = gfc_get_omp_clauses ()((gfc_omp_clauses *) xcalloc (1, sizeof (gfc_omp_clauses))); |
6099 | gfc_gobble_whitespace (); |
6100 | if ((incl = (gfc_match ("inclusive") == MATCH_YES)) |
6101 | || gfc_match ("exclusive") == MATCH_YES) |
6102 | { |
6103 | if (gfc_match_omp_variable_list (" (", &c->lists[incl ? OMP_LIST_SCAN_IN |
6104 | : OMP_LIST_SCAN_EX], |
6105 | false) != MATCH_YES) |
6106 | { |
6107 | gfc_free_omp_clauses (c); |
6108 | return MATCH_ERROR; |
6109 | } |
6110 | } |
6111 | else |
6112 | { |
6113 | gfc_error ("Expected INCLUSIVE or EXCLUSIVE clause at %C"); |
6114 | gfc_free_omp_clauses (c); |
6115 | return MATCH_ERROR; |
6116 | } |
6117 | if (gfc_match_omp_eos () != MATCH_YES) |
6118 | { |
6119 | gfc_error ("Unexpected junk after !$OMP SCAN at %C"); |
6120 | gfc_free_omp_clauses (c); |
6121 | return MATCH_ERROR; |
6122 | } |
6123 | |
6124 | new_st.op = EXEC_OMP_SCAN; |
6125 | new_st.ext.omp_clauses = c; |
6126 | return MATCH_YES; |
6127 | } |
6128 | |
6129 | |
6130 | match |
6131 | gfc_match_omp_scope (void) |
6132 | { |
6133 | return match_omp (EXEC_OMP_SCOPE, OMP_SCOPE_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) |OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT)); |
6134 | } |
6135 | |
6136 | |
6137 | match |
6138 | gfc_match_omp_sections (void) |
6139 | { |
6140 | return match_omp (EXEC_OMP_SECTIONS, OMP_SECTIONS_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT )); |
6141 | } |
6142 | |
6143 | |
6144 | match |
6145 | gfc_match_omp_simd (void) |
6146 | { |
6147 | return match_omp (EXEC_OMP_SIMD, OMP_SIMD_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_SAFELEN | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_SIMDLEN | OMP_CLAUSE_IF | OMP_CLAUSE_ORDER | OMP_CLAUSE_NOTEMPORAL)); |
6148 | } |
6149 | |
6150 | |
6151 | match |
6152 | gfc_match_omp_single (void) |
6153 | { |
6154 | return match_omp (EXEC_OMP_SINGLE, OMP_SINGLE_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_COPYPRIVATE)); |
6155 | } |
6156 | |
6157 | |
6158 | match |
6159 | gfc_match_omp_target (void) |
6160 | { |
6161 | return match_omp (EXEC_OMP_TARGET, OMP_TARGET_CLAUSES(omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_HAS_DEVICE_ADDR)); |
6162 | } |
6163 | |
6164 | |
6165 | match |
6166 | gfc_match_omp_target_data (void) |
6167 | { |
6168 | return match_omp (EXEC_OMP_TARGET_DATA, OMP_TARGET_DATA_CLAUSES(omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF | OMP_CLAUSE_USE_DEVICE_PTR | OMP_CLAUSE_USE_DEVICE_ADDR)); |
6169 | } |
6170 | |
6171 | |
6172 | match |
6173 | gfc_match_omp_target_enter_data (void) |
6174 | { |
6175 | return match_omp (EXEC_OMP_TARGET_ENTER_DATA, OMP_TARGET_ENTER_DATA_CLAUSES(omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)); |
6176 | } |
6177 | |
6178 | |
6179 | match |
6180 | gfc_match_omp_target_exit_data (void) |
6181 | { |
6182 | return match_omp (EXEC_OMP_TARGET_EXIT_DATA, OMP_TARGET_EXIT_DATA_CLAUSES(omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT)); |
6183 | } |
6184 | |
6185 | |
6186 | match |
6187 | gfc_match_omp_target_parallel (void) |
6188 | { |
6189 | return match_omp (EXEC_OMP_TARGET_PARALLEL, |
6190 | (OMP_TARGET_CLAUSES(omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_HAS_DEVICE_ADDR) | OMP_PARALLEL_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE)) |
6191 | & ~(omp_mask (OMP_CLAUSE_COPYIN))); |
6192 | } |
6193 | |
6194 | |
6195 | match |
6196 | gfc_match_omp_target_parallel_do (void) |
6197 | { |
6198 | return match_omp (EXEC_OMP_TARGET_PARALLEL_DO, |
6199 | (OMP_TARGET_CLAUSES(omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_HAS_DEVICE_ADDR) | OMP_PARALLEL_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE) |
6200 | | OMP_DO_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_SCHEDULE | OMP_CLAUSE_ORDERED | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT)) & ~(omp_mask (OMP_CLAUSE_COPYIN))); |
6201 | } |
6202 | |
6203 | |
6204 | match |
6205 | gfc_match_omp_target_parallel_do_simd (void) |
6206 | { |
6207 | return match_omp (EXEC_OMP_TARGET_PARALLEL_DO_SIMD, |
6208 | (OMP_TARGET_CLAUSES(omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_HAS_DEVICE_ADDR) | OMP_PARALLEL_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE) | OMP_DO_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_SCHEDULE | OMP_CLAUSE_ORDERED | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT) |
6209 | | OMP_SIMD_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_SAFELEN | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_SIMDLEN | OMP_CLAUSE_IF | OMP_CLAUSE_ORDER | OMP_CLAUSE_NOTEMPORAL)) & ~(omp_mask (OMP_CLAUSE_COPYIN))); |
6210 | } |
6211 | |
6212 | |
6213 | match |
6214 | gfc_match_omp_target_simd (void) |
6215 | { |
6216 | return match_omp (EXEC_OMP_TARGET_SIMD, |
6217 | OMP_TARGET_CLAUSES(omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_HAS_DEVICE_ADDR) | OMP_SIMD_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_SAFELEN | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_SIMDLEN | OMP_CLAUSE_IF | OMP_CLAUSE_ORDER | OMP_CLAUSE_NOTEMPORAL)); |
6218 | } |
6219 | |
6220 | |
6221 | match |
6222 | gfc_match_omp_target_teams (void) |
6223 | { |
6224 | return match_omp (EXEC_OMP_TARGET_TEAMS, |
6225 | OMP_TARGET_CLAUSES(omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_HAS_DEVICE_ADDR) | OMP_TEAMS_CLAUSES(omp_mask (OMP_CLAUSE_NUM_TEAMS) | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE)); |
6226 | } |
6227 | |
6228 | |
6229 | match |
6230 | gfc_match_omp_target_teams_distribute (void) |
6231 | { |
6232 | return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE, |
6233 | OMP_TARGET_CLAUSES(omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_HAS_DEVICE_ADDR) | OMP_TEAMS_CLAUSES(omp_mask (OMP_CLAUSE_NUM_TEAMS) | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE) |
6234 | | OMP_DISTRIBUTE_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_DIST_SCHEDULE | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE)); |
6235 | } |
6236 | |
6237 | |
6238 | match |
6239 | gfc_match_omp_target_teams_distribute_parallel_do (void) |
6240 | { |
6241 | return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO, |
6242 | (OMP_TARGET_CLAUSES(omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_HAS_DEVICE_ADDR) | OMP_TEAMS_CLAUSES(omp_mask (OMP_CLAUSE_NUM_TEAMS) | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE) |
6243 | | OMP_DISTRIBUTE_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_DIST_SCHEDULE | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE) | OMP_PARALLEL_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE) |
6244 | | OMP_DO_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_SCHEDULE | OMP_CLAUSE_ORDERED | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT)) |
6245 | & ~(omp_mask (OMP_CLAUSE_ORDERED)) |
6246 | & ~(omp_mask (OMP_CLAUSE_LINEAR))); |
6247 | } |
6248 | |
6249 | |
6250 | match |
6251 | gfc_match_omp_target_teams_distribute_parallel_do_simd (void) |
6252 | { |
6253 | return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD, |
6254 | (OMP_TARGET_CLAUSES(omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_HAS_DEVICE_ADDR) | OMP_TEAMS_CLAUSES(omp_mask (OMP_CLAUSE_NUM_TEAMS) | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE) |
6255 | | OMP_DISTRIBUTE_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_DIST_SCHEDULE | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE) | OMP_PARALLEL_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_COPYIN | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_IF | OMP_CLAUSE_NUM_THREADS | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PROC_BIND | OMP_CLAUSE_ALLOCATE) |
6256 | | OMP_DO_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_SCHEDULE | OMP_CLAUSE_ORDERED | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ORDER | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_NOWAIT) | OMP_SIMD_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_SAFELEN | OMP_CLAUSE_LINEAR | OMP_CLAUSE_ALIGNED | OMP_CLAUSE_SIMDLEN | OMP_CLAUSE_IF | OMP_CLAUSE_ORDER | OMP_CLAUSE_NOTEMPORAL)) |
6257 | & ~(omp_mask (OMP_CLAUSE_ORDERED))); |
6258 | } |
6259 | |
6260 | |
6261 | match |
6262 | gfc_match_omp_target_teams_distribute_simd (void) |
6263 | { |
6264 | return match_omp (EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD, |
6265 | OMP_TARGET_CLAUSES(omp_mask (OMP_CLAUSE_DEVICE) | OMP_CLAUSE_MAP | OMP_CLAUSE_IF | OMP_CLAUSE_DEPEND | OMP_CLAUSE_NOWAIT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_DEFAULTMAP | OMP_CLAUSE_IS_DEVICE_PTR | OMP_CLAUSE_IN_REDUCTION | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_ALLOCATE | OMP_CLAUSE_HAS_DEVICE_ADDR) | OMP_TEAMS_CLAUSES(omp_mask (OMP_CLAUSE_NUM_TEAMS) | OMP_CLAUSE_THREAD_LIMIT | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED | OMP_CLAUSE_REDUCTION | OMP_CLAUSE_ALLOCATE) |
6266 | | OMP_DISTRIBUTE_CLAUSES(omp_mask (OMP_CLAUSE_PRIVATE) | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_COLLAPSE | OMP_CLAUSE_DIST_SCHEDULE | OMP_CL |