1 //===-- lib/Parser/openmp-parsers.cpp -------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // Top-level grammar specification for OpenMP.
10 // See OpenMP-4.5-grammar.txt for documentation.
11 
12 #include "basic-parsers.h"
13 #include "expr-parsers.h"
14 #include "misc-parsers.h"
15 #include "stmt-parser.h"
16 #include "token-parsers.h"
17 #include "type-parser-implementation.h"
18 #include "flang/Parser/parse-tree.h"
19 
20 // OpenMP Directives and Clauses
21 namespace Fortran::parser {
22 
23 constexpr auto startOmpLine = skipStuffBeforeStatement >> "!$OMP "_sptok;
24 constexpr auto endOmpLine = space >> endOfLine;
25 
26 // OpenMP Clauses
27 // 2.15.3.1 DEFAULT (PRIVATE | FIRSTPRIVATE | SHARED | NONE)
28 TYPE_PARSER(construct<OmpDefaultClause>(
29     "PRIVATE" >> pure(OmpDefaultClause::Type::Private) ||
30     "FIRSTPRIVATE" >> pure(OmpDefaultClause::Type::Firstprivate) ||
31     "SHARED" >> pure(OmpDefaultClause::Type::Shared) ||
32     "NONE" >> pure(OmpDefaultClause::Type::None)))
33 
34 // 2.5 PROC_BIND (MASTER | CLOSE | SPREAD)
35 TYPE_PARSER(construct<OmpProcBindClause>(
36     "CLOSE" >> pure(OmpProcBindClause::Type::Close) ||
37     "MASTER" >> pure(OmpProcBindClause::Type::Master) ||
38     "SPREAD" >> pure(OmpProcBindClause::Type::Spread)))
39 
40 // 2.15.5.1 MAP ([ [ALWAYS[,]] map-type : ] variable-name-list)
41 //          map-type -> TO | FROM | TOFROM | ALLOC | RELEASE | DELETE
42 TYPE_PARSER(construct<OmpMapType>(
43     maybe("ALWAYS" >> construct<OmpMapType::Always>() / maybe(","_tok)),
44     ("TO"_id >> pure(OmpMapType::Type::To) ||
45         "FROM" >> pure(OmpMapType::Type::From) ||
46         "TOFROM" >> pure(OmpMapType::Type::Tofrom) ||
47         "ALLOC" >> pure(OmpMapType::Type::Alloc) ||
48         "RELEASE" >> pure(OmpMapType::Type::Release) ||
49         "DELETE" >> pure(OmpMapType::Type::Delete)) /
50         ":"))
51 
52 TYPE_PARSER(construct<OmpMapClause>(
53     maybe(Parser<OmpMapType>{}), Parser<OmpObjectList>{}))
54 
55 // [OpenMP 5.0]
56 // 2.19.7.2 defaultmap(implicit-behavior[:variable-category])
57 //  implicit-behavior -> ALLOC | TO | FROM | TOFROM | FIRSRTPRIVATE | NONE |
58 //  DEFAULT
59 //  variable-category -> SCALAR | AGGREGATE | ALLOCATABLE | POINTER
60 TYPE_PARSER(construct<OmpDefaultmapClause>(
61     construct<OmpDefaultmapClause::ImplicitBehavior>(
62         "ALLOC" >> pure(OmpDefaultmapClause::ImplicitBehavior::Alloc) ||
63         "TO"_id >> pure(OmpDefaultmapClause::ImplicitBehavior::To) ||
64         "FROM" >> pure(OmpDefaultmapClause::ImplicitBehavior::From) ||
65         "TOFROM" >> pure(OmpDefaultmapClause::ImplicitBehavior::Tofrom) ||
66         "FIRSTPRIVATE" >>
67             pure(OmpDefaultmapClause::ImplicitBehavior::Firstprivate) ||
68         "NONE" >> pure(OmpDefaultmapClause::ImplicitBehavior::None) ||
69         "DEFAULT" >> pure(OmpDefaultmapClause::ImplicitBehavior::Default)),
70     maybe(":" >>
71         construct<OmpDefaultmapClause::VariableCategory>(
72             "SCALAR" >> pure(OmpDefaultmapClause::VariableCategory::Scalar) ||
73             "AGGREGATE" >>
74                 pure(OmpDefaultmapClause::VariableCategory::Aggregate) ||
75             "ALLOCATABLE" >>
76                 pure(OmpDefaultmapClause::VariableCategory::Allocatable) ||
77             "POINTER" >>
78                 pure(OmpDefaultmapClause::VariableCategory::Pointer)))))
79 
80 // 2.7.1 SCHEDULE ([modifier1 [, modifier2]:]kind[, chunk_size])
81 //       Modifier ->  MONITONIC | NONMONOTONIC | SIMD
82 //       kind -> STATIC | DYNAMIC | GUIDED | AUTO | RUNTIME
83 //       chunk_size -> ScalarIntExpr
84 TYPE_PARSER(construct<OmpScheduleModifierType>(
85     "MONOTONIC" >> pure(OmpScheduleModifierType::ModType::Monotonic) ||
86     "NONMONOTONIC" >> pure(OmpScheduleModifierType::ModType::Nonmonotonic) ||
87     "SIMD" >> pure(OmpScheduleModifierType::ModType::Simd)))
88 
89 TYPE_PARSER(construct<OmpScheduleModifier>(Parser<OmpScheduleModifierType>{},
90     maybe("," >> Parser<OmpScheduleModifierType>{}) / ":"))
91 
92 TYPE_PARSER(construct<OmpScheduleClause>(maybe(Parser<OmpScheduleModifier>{}),
93     "STATIC" >> pure(OmpScheduleClause::ScheduleType::Static) ||
94         "DYNAMIC" >> pure(OmpScheduleClause::ScheduleType::Dynamic) ||
95         "GUIDED" >> pure(OmpScheduleClause::ScheduleType::Guided) ||
96         "AUTO" >> pure(OmpScheduleClause::ScheduleType::Auto) ||
97         "RUNTIME" >> pure(OmpScheduleClause::ScheduleType::Runtime),
98     maybe("," >> scalarIntExpr)))
99 
100 // 2.12 IF (directive-name-modifier: scalar-logical-expr)
101 TYPE_PARSER(construct<OmpIfClause>(
102     maybe(
103         ("PARALLEL" >> pure(OmpIfClause::DirectiveNameModifier::Parallel) ||
104             "TARGET ENTER DATA" >>
105                 pure(OmpIfClause::DirectiveNameModifier::TargetEnterData) ||
106             "TARGET EXIT DATA" >>
107                 pure(OmpIfClause::DirectiveNameModifier::TargetExitData) ||
108             "TARGET DATA" >>
109                 pure(OmpIfClause::DirectiveNameModifier::TargetData) ||
110             "TARGET UPDATE" >>
111                 pure(OmpIfClause::DirectiveNameModifier::TargetUpdate) ||
112             "TARGET" >> pure(OmpIfClause::DirectiveNameModifier::Target) ||
113             "TASK"_id >> pure(OmpIfClause::DirectiveNameModifier::Task) ||
114             "TASKLOOP" >> pure(OmpIfClause::DirectiveNameModifier::Taskloop)) /
115         ":"),
116     scalarLogicalExpr))
117 
118 // 2.15.3.6 REDUCTION (reduction-identifier: variable-name-list)
119 TYPE_PARSER(construct<OmpReductionOperator>(Parser<DefinedOperator>{}) ||
120     construct<OmpReductionOperator>(Parser<ProcedureDesignator>{}))
121 
122 TYPE_PARSER(construct<OmpReductionClause>(
123     Parser<OmpReductionOperator>{} / ":", Parser<OmpObjectList>{}))
124 
125 // OMP 5.0 2.19.5.6 IN_REDUCTION (reduction-identifier: variable-name-list)
126 TYPE_PARSER(construct<OmpInReductionClause>(
127     Parser<OmpReductionOperator>{} / ":", Parser<OmpObjectList>{}))
128 
129 // OMP 5.0 2.11.4  ALLOCATE ([allocator:] variable-name-list)
130 TYPE_PARSER(construct<OmpAllocateClause>(
131     maybe(construct<OmpAllocateClause::Allocator>(scalarIntExpr) / ":"),
132     Parser<OmpObjectList>{}))
133 
134 // 2.13.9 DEPEND (SOURCE | SINK : vec | (IN | OUT | INOUT) : list
135 TYPE_PARSER(construct<OmpDependSinkVecLength>(
136     Parser<DefinedOperator>{}, scalarIntConstantExpr))
137 
138 TYPE_PARSER(
139     construct<OmpDependSinkVec>(name, maybe(Parser<OmpDependSinkVecLength>{})))
140 
141 TYPE_PARSER(
142     construct<OmpDependenceType>("IN"_id >> pure(OmpDependenceType::Type::In) ||
143         "INOUT" >> pure(OmpDependenceType::Type::Inout) ||
144         "OUT" >> pure(OmpDependenceType::Type::Out)))
145 
146 TYPE_CONTEXT_PARSER("Omp Depend clause"_en_US,
147     construct<OmpDependClause>(construct<OmpDependClause::Sink>(
148         "SINK :" >> nonemptyList(Parser<OmpDependSinkVec>{}))) ||
149         construct<OmpDependClause>(
150             construct<OmpDependClause::Source>("SOURCE"_tok)) ||
151         construct<OmpDependClause>(construct<OmpDependClause::InOut>(
152             Parser<OmpDependenceType>{}, ":" >> nonemptyList(designator))))
153 
154 // 2.15.3.7 LINEAR (linear-list: linear-step)
155 //          linear-list -> list | modifier(list)
156 //          linear-modifier -> REF | VAL | UVAL
157 TYPE_PARSER(
158     construct<OmpLinearModifier>("REF" >> pure(OmpLinearModifier::Type::Ref) ||
159         "VAL" >> pure(OmpLinearModifier::Type::Val) ||
160         "UVAL" >> pure(OmpLinearModifier::Type::Uval)))
161 
162 TYPE_CONTEXT_PARSER("Omp LINEAR clause"_en_US,
163     construct<OmpLinearClause>(
164         construct<OmpLinearClause>(construct<OmpLinearClause::WithModifier>(
165             Parser<OmpLinearModifier>{}, parenthesized(nonemptyList(name)),
166             maybe(":" >> scalarIntConstantExpr))) ||
167         construct<OmpLinearClause>(construct<OmpLinearClause::WithoutModifier>(
168             nonemptyList(name), maybe(":" >> scalarIntConstantExpr)))))
169 
170 // 2.8.1 ALIGNED (list: alignment)
171 TYPE_PARSER(construct<OmpAlignedClause>(
172     nonemptyList(name), maybe(":" >> scalarIntConstantExpr)))
173 
174 TYPE_PARSER(
175     construct<OmpObject>(designator) || construct<OmpObject>("/" >> name / "/"))
176 
177 TYPE_PARSER(
178     "ACQUIRE" >> construct<OmpClause>(construct<OmpClause::Acquire>()) ||
179     "ACQ_REL" >> construct<OmpClause>(construct<OmpClause::AcqRel>()) ||
180     "ALIGNED" >> construct<OmpClause>(construct<OmpClause::Aligned>(
181                      parenthesized(Parser<OmpAlignedClause>{}))) ||
182     "ALLOCATE" >> construct<OmpClause>(construct<OmpClause::Allocate>(
183                       parenthesized(Parser<OmpAllocateClause>{}))) ||
184     "ALLOCATOR" >> construct<OmpClause>(construct<OmpClause::Allocator>(
185                        parenthesized(scalarIntExpr))) ||
186     "COLLAPSE" >> construct<OmpClause>(construct<OmpClause::Collapse>(
187                       parenthesized(scalarIntConstantExpr))) ||
188     "COPYIN" >> construct<OmpClause>(construct<OmpClause::Copyin>(
189                     parenthesized(Parser<OmpObjectList>{}))) ||
190     "COPYPRIVATE" >> construct<OmpClause>(construct<OmpClause::Copyprivate>(
191                          (parenthesized(Parser<OmpObjectList>{})))) ||
192     "DEFAULT"_id >> construct<OmpClause>(construct<OmpClause::Default>(
193                         parenthesized(Parser<OmpDefaultClause>{}))) ||
194     "DEFAULTMAP" >> construct<OmpClause>(construct<OmpClause::Defaultmap>(
195                         parenthesized(Parser<OmpDefaultmapClause>{}))) ||
196     "DEPEND" >> construct<OmpClause>(construct<OmpClause::Depend>(
197                     parenthesized(Parser<OmpDependClause>{}))) ||
198     "DEVICE" >> construct<OmpClause>(construct<OmpClause::Device>(
199                     parenthesized(scalarIntExpr))) ||
200     "DIST_SCHEDULE" >>
201         construct<OmpClause>(construct<OmpClause::DistSchedule>(
202             parenthesized("STATIC" >> maybe("," >> scalarIntExpr)))) ||
203     "FINAL" >> construct<OmpClause>(construct<OmpClause::Final>(
204                    parenthesized(scalarLogicalExpr))) ||
205     "FIRSTPRIVATE" >> construct<OmpClause>(construct<OmpClause::Firstprivate>(
206                           parenthesized(Parser<OmpObjectList>{}))) ||
207     "FROM" >> construct<OmpClause>(construct<OmpClause::From>(
208                   parenthesized(Parser<OmpObjectList>{}))) ||
209     "GRAINSIZE" >> construct<OmpClause>(construct<OmpClause::Grainsize>(
210                        parenthesized(scalarIntExpr))) ||
211     "HINT" >> construct<OmpClause>(
212                   construct<OmpClause::Hint>(parenthesized(constantExpr))) ||
213     "IF" >> construct<OmpClause>(construct<OmpClause::If>(
214                 parenthesized(Parser<OmpIfClause>{}))) ||
215     "INBRANCH" >> construct<OmpClause>(construct<OmpClause::Inbranch>()) ||
216     "IS_DEVICE_PTR" >> construct<OmpClause>(construct<OmpClause::IsDevicePtr>(
217                            parenthesized(nonemptyList(name)))) ||
218     "LASTPRIVATE" >> construct<OmpClause>(construct<OmpClause::Lastprivate>(
219                          parenthesized(Parser<OmpObjectList>{}))) ||
220     "LINEAR" >> construct<OmpClause>(construct<OmpClause::Linear>(
221                     parenthesized(Parser<OmpLinearClause>{}))) ||
222     "LINK" >> construct<OmpClause>(construct<OmpClause::Link>(
223                   parenthesized(Parser<OmpObjectList>{}))) ||
224     "MAP" >> construct<OmpClause>(construct<OmpClause::Map>(
225                  parenthesized(Parser<OmpMapClause>{}))) ||
226     "MERGEABLE" >> construct<OmpClause>(construct<OmpClause::Mergeable>()) ||
227     "NOGROUP" >> construct<OmpClause>(construct<OmpClause::Nogroup>()) ||
228     "NONTEMPORAL" >> construct<OmpClause>(construct<OmpClause::Nontemporal>(
229                          parenthesized(nonemptyList(name)))) ||
230     "NOTINBRANCH" >>
231         construct<OmpClause>(construct<OmpClause::Notinbranch>()) ||
232     "NOWAIT" >> construct<OmpClause>(construct<OmpClause::Nowait>()) ||
233     "NUM_TASKS" >> construct<OmpClause>(construct<OmpClause::NumTasks>(
234                        parenthesized(scalarIntExpr))) ||
235     "NUM_TEAMS" >> construct<OmpClause>(construct<OmpClause::NumTeams>(
236                        parenthesized(scalarIntExpr))) ||
237     "NUM_THREADS" >> construct<OmpClause>(construct<OmpClause::NumThreads>(
238                          parenthesized(scalarIntExpr))) ||
239     "ORDERED" >> construct<OmpClause>(construct<OmpClause::Ordered>(
240                      maybe(parenthesized(scalarIntConstantExpr)))) ||
241     "PRIORITY" >> construct<OmpClause>(construct<OmpClause::Priority>(
242                       parenthesized(scalarIntExpr))) ||
243     "PRIVATE" >> construct<OmpClause>(construct<OmpClause::Private>(
244                      parenthesized(Parser<OmpObjectList>{}))) ||
245     "PROC_BIND" >> construct<OmpClause>(construct<OmpClause::ProcBind>(
246                        parenthesized(Parser<OmpProcBindClause>{}))) ||
247     "REDUCTION" >> construct<OmpClause>(construct<OmpClause::Reduction>(
248                        parenthesized(Parser<OmpReductionClause>{}))) ||
249     "IN_REDUCTION" >> construct<OmpClause>(construct<OmpClause::InReduction>(
250                           parenthesized(Parser<OmpInReductionClause>{}))) ||
251     "TASK_REDUCTION" >>
252         construct<OmpClause>(construct<OmpClause::TaskReduction>(
253             parenthesized(Parser<OmpReductionClause>{}))) ||
254     "RELAXED" >> construct<OmpClause>(construct<OmpClause::Relaxed>()) ||
255     "RELEASE" >> construct<OmpClause>(construct<OmpClause::Release>()) ||
256     "SAFELEN" >> construct<OmpClause>(construct<OmpClause::Safelen>(
257                      parenthesized(scalarIntConstantExpr))) ||
258     "SCHEDULE" >> construct<OmpClause>(construct<OmpClause::Schedule>(
259                       parenthesized(Parser<OmpScheduleClause>{}))) ||
260     "SEQ_CST" >> construct<OmpClause>(construct<OmpClause::SeqCst>()) ||
261     "SHARED" >> construct<OmpClause>(construct<OmpClause::Shared>(
262                     parenthesized(Parser<OmpObjectList>{}))) ||
263     "SIMD"_id >> construct<OmpClause>(construct<OmpClause::Simd>()) ||
264     "SIMDLEN" >> construct<OmpClause>(construct<OmpClause::Simdlen>(
265                      parenthesized(scalarIntConstantExpr))) ||
266     "THREADS" >> construct<OmpClause>(construct<OmpClause::Threads>()) ||
267     "THREAD_LIMIT" >> construct<OmpClause>(construct<OmpClause::ThreadLimit>(
268                           parenthesized(scalarIntExpr))) ||
269     "TO" >> construct<OmpClause>(construct<OmpClause::To>(
270                 parenthesized(Parser<OmpObjectList>{}))) ||
271     "USE_DEVICE_PTR" >> construct<OmpClause>(construct<OmpClause::UseDevicePtr>(
272                             parenthesized(nonemptyList(name)))) ||
273     "UNIFORM" >> construct<OmpClause>(construct<OmpClause::Uniform>(
274                      parenthesized(nonemptyList(name)))) ||
275     "UNTIED" >> construct<OmpClause>(construct<OmpClause::Untied>()))
276 
277 // [Clause, [Clause], ...]
278 TYPE_PARSER(sourced(construct<OmpClauseList>(
279     many(maybe(","_tok) >> sourced(Parser<OmpClause>{})))))
280 
281 // 2.1 (variable | /common-block | array-sections)
282 TYPE_PARSER(construct<OmpObjectList>(nonemptyList(Parser<OmpObject>{})))
283 
284 // Omp directives enclosing do loop
285 TYPE_PARSER(sourced(construct<OmpLoopDirective>(first(
286     "DISTRIBUTE PARALLEL DO SIMD" >>
287         pure(llvm::omp::Directive::OMPD_distribute_parallel_do_simd),
288     "DISTRIBUTE PARALLEL DO" >>
289         pure(llvm::omp::Directive::OMPD_distribute_parallel_do),
290     "DISTRIBUTE SIMD" >> pure(llvm::omp::Directive::OMPD_distribute_simd),
291     "DISTRIBUTE" >> pure(llvm::omp::Directive::OMPD_distribute),
292     "DO SIMD" >> pure(llvm::omp::Directive::OMPD_do_simd),
293     "DO" >> pure(llvm::omp::Directive::OMPD_do),
294     "PARALLEL DO SIMD" >> pure(llvm::omp::Directive::OMPD_parallel_do_simd),
295     "PARALLEL DO" >> pure(llvm::omp::Directive::OMPD_parallel_do),
296     "SIMD" >> pure(llvm::omp::Directive::OMPD_simd),
297     "TARGET PARALLEL DO SIMD" >>
298         pure(llvm::omp::Directive::OMPD_target_parallel_do_simd),
299     "TARGET PARALLEL DO" >> pure(llvm::omp::Directive::OMPD_target_parallel_do),
300     "TARGET SIMD" >> pure(llvm::omp::Directive::OMPD_target_simd),
301     "TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD" >>
302         pure(llvm::omp::Directive::
303                 OMPD_target_teams_distribute_parallel_do_simd),
304     "TARGET TEAMS DISTRIBUTE PARALLEL DO" >>
305         pure(llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do),
306     "TARGET TEAMS DISTRIBUTE SIMD" >>
307         pure(llvm::omp::Directive::OMPD_target_teams_distribute_simd),
308     "TARGET TEAMS DISTRIBUTE" >>
309         pure(llvm::omp::Directive::OMPD_target_teams_distribute),
310     "TASKLOOP SIMD" >> pure(llvm::omp::Directive::OMPD_taskloop_simd),
311     "TASKLOOP" >> pure(llvm::omp::Directive::OMPD_taskloop),
312     "TEAMS DISTRIBUTE PARALLEL DO SIMD" >>
313         pure(llvm::omp::Directive::OMPD_teams_distribute_parallel_do_simd),
314     "TEAMS DISTRIBUTE PARALLEL DO" >>
315         pure(llvm::omp::Directive::OMPD_teams_distribute_parallel_do),
316     "TEAMS DISTRIBUTE SIMD" >>
317         pure(llvm::omp::Directive::OMPD_teams_distribute_simd),
318     "TEAMS DISTRIBUTE" >> pure(llvm::omp::Directive::OMPD_teams_distribute)))))
319 
320 TYPE_PARSER(sourced(construct<OmpBeginLoopDirective>(
321     sourced(Parser<OmpLoopDirective>{}), Parser<OmpClauseList>{})))
322 
323 // 2.14.1 construct-type-clause -> PARALLEL | SECTIONS | DO | TASKGROUP
324 TYPE_PARSER(sourced(construct<OmpCancelType>(
325     first("PARALLEL" >> pure(OmpCancelType::Type::Parallel),
326         "SECTIONS" >> pure(OmpCancelType::Type::Sections),
327         "DO" >> pure(OmpCancelType::Type::Do),
328         "TASKGROUP" >> pure(OmpCancelType::Type::Taskgroup)))))
329 
330 // 2.14.2 Cancellation Point construct
331 TYPE_PARSER(sourced(construct<OpenMPCancellationPointConstruct>(
332     verbatim("CANCELLATION POINT"_tok), Parser<OmpCancelType>{})))
333 
334 // 2.14.1 Cancel construct
335 TYPE_PARSER(sourced(construct<OpenMPCancelConstruct>(verbatim("CANCEL"_tok),
336     Parser<OmpCancelType>{}, maybe("IF" >> parenthesized(scalarLogicalExpr)))))
337 
338 // 2.17.7 Atomic construct/2.17.8 Flush construct [OpenMP 5.0]
339 //        memory-order-clause ->
340 //                               seq_cst
341 //                               acq_rel
342 //                               release
343 //                               acquire
344 //                               relaxed
345 TYPE_PARSER(sourced(construct<OmpMemoryOrderClause>(
346     sourced("SEQ_CST" >> construct<OmpClause>(construct<OmpClause::SeqCst>()) ||
347         "ACQ_REL" >> construct<OmpClause>(construct<OmpClause::AcqRel>()) ||
348         "RELEASE" >> construct<OmpClause>(construct<OmpClause::Release>()) ||
349         "ACQUIRE" >> construct<OmpClause>(construct<OmpClause::Acquire>()) ||
350         "RELAXED" >> construct<OmpClause>(construct<OmpClause::Relaxed>())))))
351 
352 // 2.17.7 Atomic construct
353 //        atomic-clause -> memory-order-clause | HINT(hint-expression)
354 TYPE_PARSER(sourced(construct<OmpAtomicClause>(
355     construct<OmpAtomicClause>(Parser<OmpMemoryOrderClause>{}) ||
356     construct<OmpAtomicClause>("HINT" >>
357         sourced(construct<OmpClause>(
358             construct<OmpClause::Hint>(parenthesized(constantExpr))))))))
359 
360 // atomic-clause-list -> [atomic-clause, [atomic-clause], ...]
361 TYPE_PARSER(sourced(construct<OmpAtomicClauseList>(
362     many(maybe(","_tok) >> sourced(Parser<OmpAtomicClause>{})))))
363 
364 TYPE_PARSER(sourced(construct<OpenMPFlushConstruct>(verbatim("FLUSH"_tok),
365     many(maybe(","_tok) >> sourced(Parser<OmpMemoryOrderClause>{})),
366     maybe(parenthesized(Parser<OmpObjectList>{})))))
367 
368 // Simple Standalone Directives
369 TYPE_PARSER(sourced(construct<OmpSimpleStandaloneDirective>(first(
370     "BARRIER" >> pure(llvm::omp::Directive::OMPD_barrier),
371     "ORDERED" >> pure(llvm::omp::Directive::OMPD_ordered),
372     "TARGET ENTER DATA" >> pure(llvm::omp::Directive::OMPD_target_enter_data),
373     "TARGET EXIT DATA" >> pure(llvm::omp::Directive::OMPD_target_exit_data),
374     "TARGET UPDATE" >> pure(llvm::omp::Directive::OMPD_target_update),
375     "TASKWAIT" >> pure(llvm::omp::Directive::OMPD_taskwait),
376     "TASKYIELD" >> pure(llvm::omp::Directive::OMPD_taskyield)))))
377 
378 TYPE_PARSER(sourced(construct<OpenMPSimpleStandaloneConstruct>(
379     Parser<OmpSimpleStandaloneDirective>{}, Parser<OmpClauseList>{})))
380 
381 // Standalone Constructs
382 TYPE_PARSER(
383     sourced(construct<OpenMPStandaloneConstruct>(
384                 Parser<OpenMPSimpleStandaloneConstruct>{}) ||
385         construct<OpenMPStandaloneConstruct>(Parser<OpenMPFlushConstruct>{}) ||
386         construct<OpenMPStandaloneConstruct>(Parser<OpenMPCancelConstruct>{}) ||
387         construct<OpenMPStandaloneConstruct>(
388             Parser<OpenMPCancellationPointConstruct>{})) /
389     endOfLine)
390 
391 // Directives enclosing structured-block
392 TYPE_PARSER(construct<OmpBlockDirective>(first(
393     "MASTER" >> pure(llvm::omp::Directive::OMPD_master),
394     "ORDERED" >> pure(llvm::omp::Directive::OMPD_ordered),
395     "PARALLEL WORKSHARE" >> pure(llvm::omp::Directive::OMPD_parallel_workshare),
396     "PARALLEL" >> pure(llvm::omp::Directive::OMPD_parallel),
397     "SINGLE" >> pure(llvm::omp::Directive::OMPD_single),
398     "TARGET DATA" >> pure(llvm::omp::Directive::OMPD_target_data),
399     "TARGET PARALLEL" >> pure(llvm::omp::Directive::OMPD_target_parallel),
400     "TARGET TEAMS" >> pure(llvm::omp::Directive::OMPD_target_teams),
401     "TARGET" >> pure(llvm::omp::Directive::OMPD_target),
402     "TASK"_id >> pure(llvm::omp::Directive::OMPD_task),
403     "TASKGROUP" >> pure(llvm::omp::Directive::OMPD_taskgroup),
404     "TEAMS" >> pure(llvm::omp::Directive::OMPD_teams),
405     "WORKSHARE" >> pure(llvm::omp::Directive::OMPD_workshare))))
406 
407 TYPE_PARSER(sourced(construct<OmpBeginBlockDirective>(
408     sourced(Parser<OmpBlockDirective>{}), Parser<OmpClauseList>{})))
409 
410 TYPE_PARSER(construct<OmpReductionInitializerClause>(
411     "INITIALIZER" >> parenthesized("OMP_PRIV =" >> expr)))
412 
413 // 2.16 Declare Reduction Construct
414 TYPE_PARSER(sourced(construct<OpenMPDeclareReductionConstruct>(
415     verbatim("DECLARE REDUCTION"_tok),
416     "(" >> Parser<OmpReductionOperator>{} / ":",
417     nonemptyList(Parser<DeclarationTypeSpec>{}) / ":",
418     Parser<OmpReductionCombiner>{} / ")",
419     maybe(Parser<OmpReductionInitializerClause>{}))))
420 
421 // declare-target with list
422 TYPE_PARSER(sourced(construct<OmpDeclareTargetWithList>(
423     parenthesized(Parser<OmpObjectList>{}))))
424 
425 // declare-target with clause
426 TYPE_PARSER(
427     sourced(construct<OmpDeclareTargetWithClause>(Parser<OmpClauseList>{})))
428 
429 // declare-target-specifier
430 TYPE_PARSER(
431     construct<OmpDeclareTargetSpecifier>(Parser<OmpDeclareTargetWithList>{}) ||
432     construct<OmpDeclareTargetSpecifier>(Parser<OmpDeclareTargetWithClause>{}))
433 
434 // 2.10.6 Declare Target Construct
435 TYPE_PARSER(sourced(construct<OpenMPDeclareTargetConstruct>(
436     verbatim("DECLARE TARGET"_tok), Parser<OmpDeclareTargetSpecifier>{})))
437 
438 TYPE_PARSER(construct<OmpReductionCombiner>(Parser<AssignmentStmt>{}) ||
439     construct<OmpReductionCombiner>(
440         construct<OmpReductionCombiner::FunctionCombiner>(
441             construct<Call>(Parser<ProcedureDesignator>{},
442                 parenthesized(optionalList(actualArgSpec))))))
443 
444 // 2.17.7 atomic -> ATOMIC [clause [,]] atomic-clause [[,] clause] |
445 //                  ATOMIC [clause]
446 //       clause -> memory-order-clause | HINT(hint-expression)
447 //       memory-order-clause -> SEQ_CST | ACQ_REL | RELEASE | ACQUIRE | RELAXED
448 //       atomic-clause -> READ | WRITE | UPDATE | CAPTURE
449 
450 // OMP END ATOMIC
451 TYPE_PARSER(construct<OmpEndAtomic>(startOmpLine >> "END ATOMIC"_tok))
452 
453 // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] READ [MEMORY-ORDER-CLAUSE-LIST]
454 TYPE_PARSER("ATOMIC" >>
455     construct<OmpAtomicRead>(Parser<OmpAtomicClauseList>{} / maybe(","_tok),
456         verbatim("READ"_tok), Parser<OmpAtomicClauseList>{} / endOmpLine,
457         statement(assignmentStmt), maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
458 
459 // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] CAPTURE [MEMORY-ORDER-CLAUSE-LIST]
460 TYPE_PARSER("ATOMIC" >>
461     construct<OmpAtomicCapture>(Parser<OmpAtomicClauseList>{} / maybe(","_tok),
462         verbatim("CAPTURE"_tok), Parser<OmpAtomicClauseList>{} / endOmpLine,
463         statement(assignmentStmt), statement(assignmentStmt),
464         Parser<OmpEndAtomic>{} / endOmpLine))
465 
466 // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] UPDATE [MEMORY-ORDER-CLAUSE-LIST]
467 TYPE_PARSER("ATOMIC" >>
468     construct<OmpAtomicUpdate>(Parser<OmpAtomicClauseList>{} / maybe(","_tok),
469         verbatim("UPDATE"_tok), Parser<OmpAtomicClauseList>{} / endOmpLine,
470         statement(assignmentStmt), maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
471 
472 // OMP ATOMIC [atomic-clause-list]
473 TYPE_PARSER(construct<OmpAtomic>(verbatim("ATOMIC"_tok),
474     Parser<OmpAtomicClauseList>{} / endOmpLine, statement(assignmentStmt),
475     maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
476 
477 // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] WRITE [MEMORY-ORDER-CLAUSE-LIST]
478 TYPE_PARSER("ATOMIC" >>
479     construct<OmpAtomicWrite>(Parser<OmpAtomicClauseList>{} / maybe(","_tok),
480         verbatim("WRITE"_tok), Parser<OmpAtomicClauseList>{} / endOmpLine,
481         statement(assignmentStmt), maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
482 
483 // Atomic Construct
484 TYPE_PARSER(construct<OpenMPAtomicConstruct>(Parser<OmpAtomicRead>{}) ||
485     construct<OpenMPAtomicConstruct>(Parser<OmpAtomicCapture>{}) ||
486     construct<OpenMPAtomicConstruct>(Parser<OmpAtomicWrite>{}) ||
487     construct<OpenMPAtomicConstruct>(Parser<OmpAtomicUpdate>{}) ||
488     construct<OpenMPAtomicConstruct>(Parser<OmpAtomic>{}))
489 
490 // 2.13.2 OMP CRITICAL
491 TYPE_PARSER(startOmpLine >>
492     sourced(construct<OmpEndCriticalDirective>(
493         verbatim("END CRITICAL"_tok), maybe(parenthesized(name)))) /
494         endOmpLine)
495 TYPE_PARSER(sourced(construct<OmpCriticalDirective>(verbatim("CRITICAL"_tok),
496                 maybe(parenthesized(name)), Parser<OmpClauseList>{})) /
497     endOmpLine)
498 
499 TYPE_PARSER(construct<OpenMPCriticalConstruct>(
500     Parser<OmpCriticalDirective>{}, block, Parser<OmpEndCriticalDirective>{}))
501 
502 // 2.11.3 Executable Allocate directive
503 TYPE_PARSER(
504     sourced(construct<OpenMPExecutableAllocate>(verbatim("ALLOCATE"_tok),
505         maybe(parenthesized(Parser<OmpObjectList>{})), Parser<OmpClauseList>{},
506         maybe(nonemptyList(Parser<OpenMPDeclarativeAllocate>{})) / endOmpLine,
507         statement(allocateStmt))))
508 
509 // 2.8.2 Declare Simd construct
510 TYPE_PARSER(
511     sourced(construct<OpenMPDeclareSimdConstruct>(verbatim("DECLARE SIMD"_tok),
512         maybe(parenthesized(name)), Parser<OmpClauseList>{})))
513 
514 // 2.15.2 Threadprivate directive
515 TYPE_PARSER(sourced(construct<OpenMPThreadprivate>(
516     verbatim("THREADPRIVATE"_tok), parenthesized(Parser<OmpObjectList>{}))))
517 
518 // 2.11.3 Declarative Allocate directive
519 TYPE_PARSER(
520     sourced(construct<OpenMPDeclarativeAllocate>(verbatim("ALLOCATE"_tok),
521         parenthesized(Parser<OmpObjectList>{}), Parser<OmpClauseList>{})) /
522     lookAhead(endOmpLine / !statement(allocateStmt)))
523 
524 // Declarative constructs
525 TYPE_PARSER(startOmpLine >>
526     sourced(construct<OpenMPDeclarativeConstruct>(
527                 Parser<OpenMPDeclareReductionConstruct>{}) ||
528         construct<OpenMPDeclarativeConstruct>(
529             Parser<OpenMPDeclareSimdConstruct>{}) ||
530         construct<OpenMPDeclarativeConstruct>(
531             Parser<OpenMPDeclareTargetConstruct>{}) ||
532         construct<OpenMPDeclarativeConstruct>(
533             Parser<OpenMPDeclarativeAllocate>{}) ||
534         construct<OpenMPDeclarativeConstruct>(Parser<OpenMPThreadprivate>{})) /
535         endOmpLine)
536 
537 // Block Construct
538 TYPE_PARSER(construct<OpenMPBlockConstruct>(
539     Parser<OmpBeginBlockDirective>{} / endOmpLine, block,
540     Parser<OmpEndBlockDirective>{} / endOmpLine))
541 
542 // OMP SECTIONS Directive
543 TYPE_PARSER(construct<OmpSectionsDirective>(first(
544     "SECTIONS" >> pure(llvm::omp::Directive::OMPD_sections),
545     "PARALLEL SECTIONS" >> pure(llvm::omp::Directive::OMPD_parallel_sections))))
546 
547 // OMP BEGIN and END SECTIONS Directive
548 TYPE_PARSER(sourced(construct<OmpBeginSectionsDirective>(
549     sourced(Parser<OmpSectionsDirective>{}), Parser<OmpClauseList>{})))
550 TYPE_PARSER(
551     startOmpLine >> sourced(construct<OmpEndSectionsDirective>(
552                         sourced("END"_tok >> Parser<OmpSectionsDirective>{}),
553                         Parser<OmpClauseList>{})))
554 
555 // OMP SECTION-BLOCK
556 
557 TYPE_PARSER(construct<OpenMPSectionConstruct>(block))
558 
559 TYPE_PARSER(maybe(startOmpLine >> "SECTION"_tok / endOmpLine) >>
560     construct<OmpSectionBlocks>(nonemptySeparated(
561         construct<OpenMPConstruct>(sourced(Parser<OpenMPSectionConstruct>{})),
562         startOmpLine >> "SECTION"_tok / endOmpLine)))
563 
564 // OMP SECTIONS (OpenMP 5.0 - 2.8.1), PARALLEL SECTIONS (OpenMP 5.0 - 2.13.3)
565 TYPE_PARSER(construct<OpenMPSectionsConstruct>(
566     Parser<OmpBeginSectionsDirective>{} / endOmpLine,
567     Parser<OmpSectionBlocks>{}, Parser<OmpEndSectionsDirective>{} / endOmpLine))
568 
569 TYPE_CONTEXT_PARSER("OpenMP construct"_en_US,
570     startOmpLine >>
571         first(construct<OpenMPConstruct>(Parser<OpenMPSectionsConstruct>{}),
572             construct<OpenMPConstruct>(Parser<OpenMPLoopConstruct>{}),
573             construct<OpenMPConstruct>(Parser<OpenMPBlockConstruct>{}),
574             // OpenMPBlockConstruct is attempted before
575             // OpenMPStandaloneConstruct to resolve !$OMP ORDERED
576             construct<OpenMPConstruct>(Parser<OpenMPStandaloneConstruct>{}),
577             construct<OpenMPConstruct>(Parser<OpenMPAtomicConstruct>{}),
578             construct<OpenMPConstruct>(Parser<OpenMPExecutableAllocate>{}),
579             construct<OpenMPConstruct>(Parser<OpenMPDeclarativeAllocate>{}),
580             construct<OpenMPConstruct>(Parser<OpenMPCriticalConstruct>{})))
581 
582 // END OMP Block directives
583 TYPE_PARSER(
584     startOmpLine >> sourced(construct<OmpEndBlockDirective>(
585                         sourced("END"_tok >> Parser<OmpBlockDirective>{}),
586                         Parser<OmpClauseList>{})))
587 
588 // END OMP Loop directives
589 TYPE_PARSER(
590     startOmpLine >> sourced(construct<OmpEndLoopDirective>(
591                         sourced("END"_tok >> Parser<OmpLoopDirective>{}),
592                         Parser<OmpClauseList>{})))
593 
594 TYPE_PARSER(construct<OpenMPLoopConstruct>(
595     Parser<OmpBeginLoopDirective>{} / endOmpLine))
596 } // namespace Fortran::parser
597