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
21namespace Fortran::parser {
22
23constexpr auto startOmpLine = skipStuffBeforeStatement >> "!$OMP "_sptok;
24constexpr auto endOmpLine = space >> endOfLine;
25
26// OpenMP Clauses
27// 2.15.3.1 DEFAULT (PRIVATE | FIRSTPRIVATE | SHARED | NONE)
28TYPE_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)
35TYPE_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
42TYPE_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
52TYPE_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
60TYPE_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
84TYPE_PARSER(construct<OmpScheduleModifierType>(
85 "MONOTONIC" >> pure(OmpScheduleModifierType::ModType::Monotonic) ||
86 "NONMONOTONIC" >> pure(OmpScheduleModifierType::ModType::Nonmonotonic) ||
87 "SIMD" >> pure(OmpScheduleModifierType::ModType::Simd)))
88
89TYPE_PARSER(construct<OmpScheduleModifier>(Parser<OmpScheduleModifierType>{},
90 maybe("," >> Parser<OmpScheduleModifierType>{}) / ":"))
91
92TYPE_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// device([ device-modifier :] scalar-integer-expression)
101TYPE_PARSER(construct<OmpDeviceClause>(
102 maybe(
103 ("ANCESTOR" >> pure(OmpDeviceClause::DeviceModifier::Ancestor) ||
104 "DEVICE_NUM" >> pure(OmpDeviceClause::DeviceModifier::Device_Num)) /
105 ":"),
106 scalarIntExpr))
107
108// device_type(any | host | nohost)
109TYPE_PARSER(construct<OmpDeviceTypeClause>(
110 "ANY" >> pure(OmpDeviceTypeClause::Type::Any) ||
111 "HOST" >> pure(OmpDeviceTypeClause::Type::Host) ||
112 "NOHOST" >> pure(OmpDeviceTypeClause::Type::Nohost)))
113
114// 2.12 IF (directive-name-modifier: scalar-logical-expr)
115TYPE_PARSER(construct<OmpIfClause>(
116 maybe(
117 ("PARALLEL" >> pure(OmpIfClause::DirectiveNameModifier::Parallel) ||
118 "SIMD" >> pure(OmpIfClause::DirectiveNameModifier::Simd) ||
119 "TARGET ENTER DATA" >>
120 pure(OmpIfClause::DirectiveNameModifier::TargetEnterData) ||
121 "TARGET EXIT DATA" >>
122 pure(OmpIfClause::DirectiveNameModifier::TargetExitData) ||
123 "TARGET DATA" >>
124 pure(OmpIfClause::DirectiveNameModifier::TargetData) ||
125 "TARGET UPDATE" >>
126 pure(OmpIfClause::DirectiveNameModifier::TargetUpdate) ||
127 "TARGET" >> pure(OmpIfClause::DirectiveNameModifier::Target) ||
128 "TASK"_id >> pure(OmpIfClause::DirectiveNameModifier::Task) ||
129 "TASKLOOP" >> pure(OmpIfClause::DirectiveNameModifier::Taskloop) ||
130 "TEAMS" >> pure(OmpIfClause::DirectiveNameModifier::Teams)) /
131 ":"),
132 scalarLogicalExpr))
133
134// 2.15.3.6 REDUCTION (reduction-identifier: variable-name-list)
135TYPE_PARSER(construct<OmpReductionOperator>(Parser<DefinedOperator>{}) ||
136 construct<OmpReductionOperator>(Parser<ProcedureDesignator>{}))
137
138TYPE_PARSER(construct<OmpReductionClause>(
139 maybe(
140 ("INSCAN" >> pure(OmpReductionClause::ReductionModifier::Inscan) ||
141 "TASK" >> pure(OmpReductionClause::ReductionModifier::Task) ||
142 "DEFAULT" >> pure(OmpReductionClause::ReductionModifier::Default)) /
143 ","),
144 Parser<OmpReductionOperator>{} / ":", Parser<OmpObjectList>{}))
145
146// OMP 5.0 2.19.5.6 IN_REDUCTION (reduction-identifier: variable-name-list)
147TYPE_PARSER(construct<OmpInReductionClause>(
148 Parser<OmpReductionOperator>{} / ":", Parser<OmpObjectList>{}))
149
150// OMP 5.0 2.11.4 allocate-clause -> ALLOCATE ([allocator:] variable-name-list)
151// OMP 5.2 2.13.4 allocate-clause -> ALLOCATE ([allocate-modifier
152// [, allocate-modifier] :]
153// variable-name-list)
154// allocate-modifier -> allocator | align
155TYPE_PARSER(construct<OmpAllocateClause>(
156 maybe(
157 first(
158 construct<OmpAllocateClause::AllocateModifier>("ALLOCATOR" >>
159 construct<OmpAllocateClause::AllocateModifier::ComplexModifier>(
160 parenthesized(construct<
161 OmpAllocateClause::AllocateModifier::Allocator>(
162 scalarIntExpr)) /
163 ",",
164 "ALIGN" >> parenthesized(construct<
165 OmpAllocateClause::AllocateModifier::Align>(
166 scalarIntExpr)))),
167 construct<OmpAllocateClause::AllocateModifier>("ALLOCATOR" >>
168 parenthesized(
169 construct<OmpAllocateClause::AllocateModifier::Allocator>(
170 scalarIntExpr))),
171 construct<OmpAllocateClause::AllocateModifier>("ALIGN" >>
172 parenthesized(
173 construct<OmpAllocateClause::AllocateModifier::Align>(
174 scalarIntExpr))),
175 construct<OmpAllocateClause::AllocateModifier>(
176 construct<OmpAllocateClause::AllocateModifier::Allocator>(
177 scalarIntExpr))) /
178 ":"),
179 Parser<OmpObjectList>{}))
180
181// 2.13.9 DEPEND (SOURCE | SINK : vec | (IN | OUT | INOUT) : list
182TYPE_PARSER(construct<OmpDependSinkVecLength>(
183 Parser<DefinedOperator>{}, scalarIntConstantExpr))
184
185TYPE_PARSER(
186 construct<OmpDependSinkVec>(name, maybe(Parser<OmpDependSinkVecLength>{})))
187
188TYPE_PARSER(
189 construct<OmpDependenceType>("IN"_id >> pure(OmpDependenceType::Type::In) ||
190 "INOUT" >> pure(OmpDependenceType::Type::Inout) ||
191 "OUT" >> pure(OmpDependenceType::Type::Out)))
192
193TYPE_CONTEXT_PARSER("Omp Depend clause"_en_US,
194 construct<OmpDependClause>(construct<OmpDependClause::Sink>(
195 "SINK :" >> nonemptyList(Parser<OmpDependSinkVec>{}))) ||
196 construct<OmpDependClause>(
197 construct<OmpDependClause::Source>("SOURCE"_tok)) ||
198 construct<OmpDependClause>(construct<OmpDependClause::InOut>(
199 Parser<OmpDependenceType>{}, ":" >> nonemptyList(designator))))
200
201// 2.15.3.7 LINEAR (linear-list: linear-step)
202// linear-list -> list | modifier(list)
203// linear-modifier -> REF | VAL | UVAL
204TYPE_PARSER(
205 construct<OmpLinearModifier>("REF" >> pure(OmpLinearModifier::Type::Ref) ||
206 "VAL" >> pure(OmpLinearModifier::Type::Val) ||
207 "UVAL" >> pure(OmpLinearModifier::Type::Uval)))
208
209TYPE_CONTEXT_PARSER("Omp LINEAR clause"_en_US,
210 construct<OmpLinearClause>(
211 construct<OmpLinearClause>(construct<OmpLinearClause::WithModifier>(
212 Parser<OmpLinearModifier>{}, parenthesized(nonemptyList(name)),
213 maybe(":" >> scalarIntConstantExpr))) ||
214 construct<OmpLinearClause>(construct<OmpLinearClause::WithoutModifier>(
215 nonemptyList(name), maybe(":" >> scalarIntConstantExpr)))))
216
217// 2.8.1 ALIGNED (list: alignment)
218TYPE_PARSER(construct<OmpAlignedClause>(
219 Parser<OmpObjectList>{}, maybe(":" >> scalarIntConstantExpr)))
220
221// 2.9.5 ORDER ([order-modifier :]concurrent)
222TYPE_PARSER(construct<OmpOrderModifier>(
223 "REPRODUCIBLE" >> pure(OmpOrderModifier::Kind::Reproducible)) ||
224 construct<OmpOrderModifier>(
225 "UNCONSTRAINED" >> pure(OmpOrderModifier::Kind::Unconstrained)))
226
227TYPE_PARSER(construct<OmpOrderClause>(
228 maybe(Parser<OmpOrderModifier>{} / ":"),
229 "CONCURRENT" >> pure(OmpOrderClause::Type::Concurrent)))
230
231TYPE_PARSER(
232 construct<OmpObject>(designator) || construct<OmpObject>("/" >> name / "/"))
233
234TYPE_PARSER(
235 "ACQUIRE" >> construct<OmpClause>(construct<OmpClause::Acquire>()) ||
236 "ACQ_REL" >> construct<OmpClause>(construct<OmpClause::AcqRel>()) ||
237 "ALIGNED" >> construct<OmpClause>(construct<OmpClause::Aligned>(
238 parenthesized(Parser<OmpAlignedClause>{}))) ||
239 "ALLOCATE" >> construct<OmpClause>(construct<OmpClause::Allocate>(
240 parenthesized(Parser<OmpAllocateClause>{}))) ||
241 "ALLOCATOR" >> construct<OmpClause>(construct<OmpClause::Allocator>(
242 parenthesized(scalarIntExpr))) ||
243 "ATOMIC_DEFAULT_MEM_ORDER" >>
244 construct<OmpClause>(construct<OmpClause::AtomicDefaultMemOrder>(
245 parenthesized(Parser<OmpAtomicDefaultMemOrderClause>{}))) ||
246 "COLLAPSE" >> construct<OmpClause>(construct<OmpClause::Collapse>(
247 parenthesized(scalarIntConstantExpr))) ||
248 "COPYIN" >> construct<OmpClause>(construct<OmpClause::Copyin>(
249 parenthesized(Parser<OmpObjectList>{}))) ||
250 "COPYPRIVATE" >> construct<OmpClause>(construct<OmpClause::Copyprivate>(
251 (parenthesized(Parser<OmpObjectList>{})))) ||
252 "DEFAULT"_id >> construct<OmpClause>(construct<OmpClause::Default>(
253 parenthesized(Parser<OmpDefaultClause>{}))) ||
254 "DEFAULTMAP" >> construct<OmpClause>(construct<OmpClause::Defaultmap>(
255 parenthesized(Parser<OmpDefaultmapClause>{}))) ||
256 "DEPEND" >> construct<OmpClause>(construct<OmpClause::Depend>(
257 parenthesized(Parser<OmpDependClause>{}))) ||
258 "DEVICE" >> construct<OmpClause>(construct<OmpClause::Device>(
259 parenthesized(Parser<OmpDeviceClause>{}))) ||
260 "DEVICE_TYPE" >> construct<OmpClause>(construct<OmpClause::DeviceType>(
261 parenthesized(Parser<OmpDeviceTypeClause>{}))) ||
262 "DIST_SCHEDULE" >>
263 construct<OmpClause>(construct<OmpClause::DistSchedule>(
264 parenthesized("STATIC" >> maybe("," >> scalarIntExpr)))) ||
265 "DYNAMIC_ALLOCATORS" >>
266 construct<OmpClause>(construct<OmpClause::DynamicAllocators>()) ||
267 "ENTER" >> construct<OmpClause>(construct<OmpClause::Enter>(
268 parenthesized(Parser<OmpObjectList>{}))) ||
269 "FINAL" >> construct<OmpClause>(construct<OmpClause::Final>(
270 parenthesized(scalarLogicalExpr))) ||
271 "FULL" >> construct<OmpClause>(construct<OmpClause::Full>()) ||
272 "FIRSTPRIVATE" >> construct<OmpClause>(construct<OmpClause::Firstprivate>(
273 parenthesized(Parser<OmpObjectList>{}))) ||
274 "FROM" >> construct<OmpClause>(construct<OmpClause::From>(
275 parenthesized(Parser<OmpObjectList>{}))) ||
276 "GRAINSIZE" >> construct<OmpClause>(construct<OmpClause::Grainsize>(
277 parenthesized(scalarIntExpr))) ||
278 "HAS_DEVICE_ADDR" >>
279 construct<OmpClause>(construct<OmpClause::HasDeviceAddr>(
280 parenthesized(Parser<OmpObjectList>{}))) ||
281 "HINT" >> construct<OmpClause>(
282 construct<OmpClause::Hint>(parenthesized(constantExpr))) ||
283 "IF" >> construct<OmpClause>(construct<OmpClause::If>(
284 parenthesized(Parser<OmpIfClause>{}))) ||
285 "INBRANCH" >> construct<OmpClause>(construct<OmpClause::Inbranch>()) ||
286 "IS_DEVICE_PTR" >> construct<OmpClause>(construct<OmpClause::IsDevicePtr>(
287 parenthesized(Parser<OmpObjectList>{}))) ||
288 "LASTPRIVATE" >> construct<OmpClause>(construct<OmpClause::Lastprivate>(
289 parenthesized(Parser<OmpObjectList>{}))) ||
290 "LINEAR" >> construct<OmpClause>(construct<OmpClause::Linear>(
291 parenthesized(Parser<OmpLinearClause>{}))) ||
292 "LINK" >> construct<OmpClause>(construct<OmpClause::Link>(
293 parenthesized(Parser<OmpObjectList>{}))) ||
294 "MAP" >> construct<OmpClause>(construct<OmpClause::Map>(
295 parenthesized(Parser<OmpMapClause>{}))) ||
296 "MERGEABLE" >> construct<OmpClause>(construct<OmpClause::Mergeable>()) ||
297 "NOGROUP" >> construct<OmpClause>(construct<OmpClause::Nogroup>()) ||
298 "NONTEMPORAL" >> construct<OmpClause>(construct<OmpClause::Nontemporal>(
299 parenthesized(nonemptyList(name)))) ||
300 "NOTINBRANCH" >>
301 construct<OmpClause>(construct<OmpClause::Notinbranch>()) ||
302 "NOWAIT" >> construct<OmpClause>(construct<OmpClause::Nowait>()) ||
303 "NUM_TASKS" >> construct<OmpClause>(construct<OmpClause::NumTasks>(
304 parenthesized(scalarIntExpr))) ||
305 "NUM_TEAMS" >> construct<OmpClause>(construct<OmpClause::NumTeams>(
306 parenthesized(scalarIntExpr))) ||
307 "NUM_THREADS" >> construct<OmpClause>(construct<OmpClause::NumThreads>(
308 parenthesized(scalarIntExpr))) ||
309 "ORDER" >> construct<OmpClause>(construct<OmpClause::Order>(
310 parenthesized(Parser<OmpOrderClause>{}))) ||
311 "ORDERED" >> construct<OmpClause>(construct<OmpClause::Ordered>(
312 maybe(parenthesized(scalarIntConstantExpr)))) ||
313 "PARTIAL" >> construct<OmpClause>(construct<OmpClause::Partial>(
314 maybe(parenthesized(scalarIntConstantExpr)))) ||
315 "PRIORITY" >> construct<OmpClause>(construct<OmpClause::Priority>(
316 parenthesized(scalarIntExpr))) ||
317 "PRIVATE" >> construct<OmpClause>(construct<OmpClause::Private>(
318 parenthesized(Parser<OmpObjectList>{}))) ||
319 "PROC_BIND" >> construct<OmpClause>(construct<OmpClause::ProcBind>(
320 parenthesized(Parser<OmpProcBindClause>{}))) ||
321 "REDUCTION" >> construct<OmpClause>(construct<OmpClause::Reduction>(
322 parenthesized(Parser<OmpReductionClause>{}))) ||
323 "IN_REDUCTION" >> construct<OmpClause>(construct<OmpClause::InReduction>(
324 parenthesized(Parser<OmpInReductionClause>{}))) ||
325 "TASK_REDUCTION" >>
326 construct<OmpClause>(construct<OmpClause::TaskReduction>(
327 parenthesized(Parser<OmpReductionClause>{}))) ||
328 "RELAXED" >> construct<OmpClause>(construct<OmpClause::Relaxed>()) ||
329 "RELEASE" >> construct<OmpClause>(construct<OmpClause::Release>()) ||
330 "REVERSE_OFFLOAD" >>
331 construct<OmpClause>(construct<OmpClause::ReverseOffload>()) ||
332 "SAFELEN" >> construct<OmpClause>(construct<OmpClause::Safelen>(
333 parenthesized(scalarIntConstantExpr))) ||
334 "SCHEDULE" >> construct<OmpClause>(construct<OmpClause::Schedule>(
335 parenthesized(Parser<OmpScheduleClause>{}))) ||
336 "SEQ_CST" >> construct<OmpClause>(construct<OmpClause::SeqCst>()) ||
337 "SHARED" >> construct<OmpClause>(construct<OmpClause::Shared>(
338 parenthesized(Parser<OmpObjectList>{}))) ||
339 "SIMD"_id >> construct<OmpClause>(construct<OmpClause::Simd>()) ||
340 "SIMDLEN" >> construct<OmpClause>(construct<OmpClause::Simdlen>(
341 parenthesized(scalarIntConstantExpr))) ||
342 "SIZES" >> construct<OmpClause>(construct<OmpClause::Sizes>(
343 parenthesized(nonemptyList(scalarIntExpr)))) ||
344 "THREADS" >> construct<OmpClause>(construct<OmpClause::Threads>()) ||
345 "THREAD_LIMIT" >> construct<OmpClause>(construct<OmpClause::ThreadLimit>(
346 parenthesized(scalarIntExpr))) ||
347 "TO" >> construct<OmpClause>(construct<OmpClause::To>(
348 parenthesized(Parser<OmpObjectList>{}))) ||
349 "USE_DEVICE_PTR" >> construct<OmpClause>(construct<OmpClause::UseDevicePtr>(
350 parenthesized(Parser<OmpObjectList>{}))) ||
351 "USE_DEVICE_ADDR" >>
352 construct<OmpClause>(construct<OmpClause::UseDeviceAddr>(
353 parenthesized(Parser<OmpObjectList>{}))) ||
354 "UNIFIED_ADDRESS" >>
355 construct<OmpClause>(construct<OmpClause::UnifiedAddress>()) ||
356 "UNIFIED_SHARED_MEMORY" >>
357 construct<OmpClause>(construct<OmpClause::UnifiedSharedMemory>()) ||
358 "UNIFORM" >> construct<OmpClause>(construct<OmpClause::Uniform>(
359 parenthesized(nonemptyList(name)))) ||
360 "UNTIED" >> construct<OmpClause>(construct<OmpClause::Untied>()))
361
362// [Clause, [Clause], ...]
363TYPE_PARSER(sourced(construct<OmpClauseList>(
364 many(maybe(","_tok) >> sourced(Parser<OmpClause>{})))))
365
366// 2.1 (variable | /common-block | array-sections)
367TYPE_PARSER(construct<OmpObjectList>(nonemptyList(Parser<OmpObject>{})))
368
369// Omp directives enclosing do loop
370TYPE_PARSER(sourced(construct<OmpLoopDirective>(first(
371 "DISTRIBUTE PARALLEL DO SIMD" >>
372 pure(llvm::omp::Directive::OMPD_distribute_parallel_do_simd),
373 "DISTRIBUTE PARALLEL DO" >>
374 pure(llvm::omp::Directive::OMPD_distribute_parallel_do),
375 "DISTRIBUTE SIMD" >> pure(llvm::omp::Directive::OMPD_distribute_simd),
376 "DISTRIBUTE" >> pure(llvm::omp::Directive::OMPD_distribute),
377 "DO SIMD" >> pure(llvm::omp::Directive::OMPD_do_simd),
378 "DO" >> pure(llvm::omp::Directive::OMPD_do),
379 "PARALLEL DO SIMD" >> pure(llvm::omp::Directive::OMPD_parallel_do_simd),
380 "PARALLEL DO" >> pure(llvm::omp::Directive::OMPD_parallel_do),
381 "SIMD" >> pure(llvm::omp::Directive::OMPD_simd),
382 "TARGET PARALLEL DO SIMD" >>
383 pure(llvm::omp::Directive::OMPD_target_parallel_do_simd),
384 "TARGET PARALLEL DO" >> pure(llvm::omp::Directive::OMPD_target_parallel_do),
385 "TARGET SIMD" >> pure(llvm::omp::Directive::OMPD_target_simd),
386 "TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD" >>
387 pure(llvm::omp::Directive::
388 OMPD_target_teams_distribute_parallel_do_simd),
389 "TARGET TEAMS DISTRIBUTE PARALLEL DO" >>
390 pure(llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do),
391 "TARGET TEAMS DISTRIBUTE SIMD" >>
392 pure(llvm::omp::Directive::OMPD_target_teams_distribute_simd),
393 "TARGET TEAMS DISTRIBUTE" >>
394 pure(llvm::omp::Directive::OMPD_target_teams_distribute),
395 "TASKLOOP SIMD" >> pure(llvm::omp::Directive::OMPD_taskloop_simd),
396 "TASKLOOP" >> pure(llvm::omp::Directive::OMPD_taskloop),
397 "TEAMS DISTRIBUTE PARALLEL DO SIMD" >>
398 pure(llvm::omp::Directive::OMPD_teams_distribute_parallel_do_simd),
399 "TEAMS DISTRIBUTE PARALLEL DO" >>
400 pure(llvm::omp::Directive::OMPD_teams_distribute_parallel_do),
401 "TEAMS DISTRIBUTE SIMD" >>
402 pure(llvm::omp::Directive::OMPD_teams_distribute_simd),
403 "TEAMS DISTRIBUTE" >> pure(llvm::omp::Directive::OMPD_teams_distribute),
404 "TILE" >> pure(llvm::omp::Directive::OMPD_tile),
405 "UNROLL" >> pure(llvm::omp::Directive::OMPD_unroll)))))
406
407TYPE_PARSER(sourced(construct<OmpBeginLoopDirective>(
408 sourced(Parser<OmpLoopDirective>{}), Parser<OmpClauseList>{})))
409
410// 2.14.1 construct-type-clause -> PARALLEL | SECTIONS | DO | TASKGROUP
411TYPE_PARSER(sourced(construct<OmpCancelType>(
412 first("PARALLEL" >> pure(OmpCancelType::Type::Parallel),
413 "SECTIONS" >> pure(OmpCancelType::Type::Sections),
414 "DO" >> pure(OmpCancelType::Type::Do),
415 "TASKGROUP" >> pure(OmpCancelType::Type::Taskgroup)))))
416
417// 2.14.2 Cancellation Point construct
418TYPE_PARSER(sourced(construct<OpenMPCancellationPointConstruct>(
419 verbatim("CANCELLATION POINT"_tok), Parser<OmpCancelType>{})))
420
421// 2.14.1 Cancel construct
422TYPE_PARSER(sourced(construct<OpenMPCancelConstruct>(verbatim("CANCEL"_tok),
423 Parser<OmpCancelType>{}, maybe("IF" >> parenthesized(scalarLogicalExpr)))))
424
425// 2.17.7 Atomic construct/2.17.8 Flush construct [OpenMP 5.0]
426// memory-order-clause ->
427// seq_cst
428// acq_rel
429// release
430// acquire
431// relaxed
432TYPE_PARSER(sourced(construct<OmpMemoryOrderClause>(
433 sourced("SEQ_CST" >> construct<OmpClause>(construct<OmpClause::SeqCst>()) ||
434 "ACQ_REL" >> construct<OmpClause>(construct<OmpClause::AcqRel>()) ||
435 "RELEASE" >> construct<OmpClause>(construct<OmpClause::Release>()) ||
436 "ACQUIRE" >> construct<OmpClause>(construct<OmpClause::Acquire>()) ||
437 "RELAXED" >> construct<OmpClause>(construct<OmpClause::Relaxed>())))))
438
439// 2.4 Requires construct [OpenMP 5.0]
440// atomic-default-mem-order-clause ->
441// seq_cst
442// acq_rel
443// relaxed
444TYPE_PARSER(construct<OmpAtomicDefaultMemOrderClause>(
445 "SEQ_CST" >> pure(common::OmpAtomicDefaultMemOrderType::SeqCst) ||
446 "ACQ_REL" >> pure(common::OmpAtomicDefaultMemOrderType::AcqRel) ||
447 "RELAXED" >> pure(common::OmpAtomicDefaultMemOrderType::Relaxed)))
448
449// 2.17.7 Atomic construct
450// atomic-clause -> memory-order-clause | HINT(hint-expression)
451TYPE_PARSER(sourced(construct<OmpAtomicClause>(
452 construct<OmpAtomicClause>(Parser<OmpMemoryOrderClause>{}) ||
453 construct<OmpAtomicClause>("HINT" >>
454 sourced(construct<OmpClause>(
455 construct<OmpClause::Hint>(parenthesized(constantExpr))))))))
456
457// atomic-clause-list -> [atomic-clause, [atomic-clause], ...]
458TYPE_PARSER(sourced(construct<OmpAtomicClauseList>(
459 many(maybe(","_tok) >> sourced(Parser<OmpAtomicClause>{})))))
460
461TYPE_PARSER(sourced(construct<OpenMPFlushConstruct>(verbatim("FLUSH"_tok),
462 many(maybe(","_tok) >> sourced(Parser<OmpMemoryOrderClause>{})),
463 maybe(parenthesized(Parser<OmpObjectList>{})))))
464
465// Simple Standalone Directives
466TYPE_PARSER(sourced(construct<OmpSimpleStandaloneDirective>(first(
467 "BARRIER" >> pure(llvm::omp::Directive::OMPD_barrier),
468 "ORDERED" >> pure(llvm::omp::Directive::OMPD_ordered),
469 "TARGET ENTER DATA" >> pure(llvm::omp::Directive::OMPD_target_enter_data),
470 "TARGET EXIT DATA" >> pure(llvm::omp::Directive::OMPD_target_exit_data),
471 "TARGET UPDATE" >> pure(llvm::omp::Directive::OMPD_target_update),
472 "TASKWAIT" >> pure(llvm::omp::Directive::OMPD_taskwait),
473 "TASKYIELD" >> pure(llvm::omp::Directive::OMPD_taskyield)))))
474
475TYPE_PARSER(sourced(construct<OpenMPSimpleStandaloneConstruct>(
476 Parser<OmpSimpleStandaloneDirective>{}, Parser<OmpClauseList>{})))
477
478// Standalone Constructs
479TYPE_PARSER(
480 sourced(construct<OpenMPStandaloneConstruct>(
481 Parser<OpenMPSimpleStandaloneConstruct>{}) ||
482 construct<OpenMPStandaloneConstruct>(Parser<OpenMPFlushConstruct>{}) ||
483 construct<OpenMPStandaloneConstruct>(Parser<OpenMPCancelConstruct>{}) ||
484 construct<OpenMPStandaloneConstruct>(
485 Parser<OpenMPCancellationPointConstruct>{})) /
486 endOfLine)
487
488// Directives enclosing structured-block
489TYPE_PARSER(construct<OmpBlockDirective>(first(
490 "MASTER" >> pure(llvm::omp::Directive::OMPD_master),
491 "ORDERED" >> pure(llvm::omp::Directive::OMPD_ordered),
492 "PARALLEL WORKSHARE" >> pure(llvm::omp::Directive::OMPD_parallel_workshare),
493 "PARALLEL" >> pure(llvm::omp::Directive::OMPD_parallel),
494 "SINGLE" >> pure(llvm::omp::Directive::OMPD_single),
495 "TARGET DATA" >> pure(llvm::omp::Directive::OMPD_target_data),
496 "TARGET PARALLEL" >> pure(llvm::omp::Directive::OMPD_target_parallel),
497 "TARGET TEAMS" >> pure(llvm::omp::Directive::OMPD_target_teams),
498 "TARGET" >> pure(llvm::omp::Directive::OMPD_target),
499 "TASK"_id >> pure(llvm::omp::Directive::OMPD_task),
500 "TASKGROUP" >> pure(llvm::omp::Directive::OMPD_taskgroup),
501 "TEAMS" >> pure(llvm::omp::Directive::OMPD_teams),
502 "WORKSHARE" >> pure(llvm::omp::Directive::OMPD_workshare))))
503
504TYPE_PARSER(sourced(construct<OmpBeginBlockDirective>(
505 sourced(Parser<OmpBlockDirective>{}), Parser<OmpClauseList>{})))
506
507TYPE_PARSER(construct<OmpReductionInitializerClause>(
508 "INITIALIZER" >> parenthesized("OMP_PRIV =" >> expr)))
509
510// 2.16 Declare Reduction Construct
511TYPE_PARSER(sourced(construct<OpenMPDeclareReductionConstruct>(
512 verbatim("DECLARE REDUCTION"_tok),
513 "(" >> Parser<OmpReductionOperator>{} / ":",
514 nonemptyList(Parser<DeclarationTypeSpec>{}) / ":",
515 Parser<OmpReductionCombiner>{} / ")",
516 maybe(Parser<OmpReductionInitializerClause>{}))))
517
518// declare-target with list
519TYPE_PARSER(sourced(construct<OmpDeclareTargetWithList>(
520 parenthesized(Parser<OmpObjectList>{}))))
521
522// declare-target with clause
523TYPE_PARSER(
524 sourced(construct<OmpDeclareTargetWithClause>(Parser<OmpClauseList>{})))
525
526// declare-target-specifier
527TYPE_PARSER(
528 construct<OmpDeclareTargetSpecifier>(Parser<OmpDeclareTargetWithList>{}) ||
529 construct<OmpDeclareTargetSpecifier>(Parser<OmpDeclareTargetWithClause>{}))
530
531// 2.10.6 Declare Target Construct
532TYPE_PARSER(sourced(construct<OpenMPDeclareTargetConstruct>(
533 verbatim("DECLARE TARGET"_tok), Parser<OmpDeclareTargetSpecifier>{})))
534
535TYPE_PARSER(construct<OmpReductionCombiner>(Parser<AssignmentStmt>{}) ||
536 construct<OmpReductionCombiner>(
537 construct<OmpReductionCombiner::FunctionCombiner>(
538 construct<Call>(Parser<ProcedureDesignator>{},
539 parenthesized(optionalList(actualArgSpec))))))
540
541// 2.17.7 atomic -> ATOMIC [clause [,]] atomic-clause [[,] clause] |
542// ATOMIC [clause]
543// clause -> memory-order-clause | HINT(hint-expression)
544// memory-order-clause -> SEQ_CST | ACQ_REL | RELEASE | ACQUIRE | RELAXED
545// atomic-clause -> READ | WRITE | UPDATE | CAPTURE
546
547// OMP END ATOMIC
548TYPE_PARSER(construct<OmpEndAtomic>(startOmpLine >> "END ATOMIC"_tok))
549
550// OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] READ [MEMORY-ORDER-CLAUSE-LIST]
551TYPE_PARSER("ATOMIC" >>
552 construct<OmpAtomicRead>(Parser<OmpAtomicClauseList>{} / maybe(","_tok),
553 verbatim("READ"_tok), Parser<OmpAtomicClauseList>{} / endOmpLine,
554 statement(assignmentStmt), maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
555
556// OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] CAPTURE [MEMORY-ORDER-CLAUSE-LIST]
557TYPE_PARSER("ATOMIC" >>
558 construct<OmpAtomicCapture>(Parser<OmpAtomicClauseList>{} / maybe(","_tok),
559 verbatim("CAPTURE"_tok), Parser<OmpAtomicClauseList>{} / endOmpLine,
560 statement(assignmentStmt), statement(assignmentStmt),
561 Parser<OmpEndAtomic>{} / endOmpLine))
562
563// OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] UPDATE [MEMORY-ORDER-CLAUSE-LIST]
564TYPE_PARSER("ATOMIC" >>
565 construct<OmpAtomicUpdate>(Parser<OmpAtomicClauseList>{} / maybe(","_tok),
566 verbatim("UPDATE"_tok), Parser<OmpAtomicClauseList>{} / endOmpLine,
567 statement(assignmentStmt), maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
568
569// OMP ATOMIC [atomic-clause-list]
570TYPE_PARSER(construct<OmpAtomic>(verbatim("ATOMIC"_tok),
571 Parser<OmpAtomicClauseList>{} / endOmpLine, statement(assignmentStmt),
572 maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
573
574// OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] WRITE [MEMORY-ORDER-CLAUSE-LIST]
575TYPE_PARSER("ATOMIC" >>
576 construct<OmpAtomicWrite>(Parser<OmpAtomicClauseList>{} / maybe(","_tok),
577 verbatim("WRITE"_tok), Parser<OmpAtomicClauseList>{} / endOmpLine,
578 statement(assignmentStmt), maybe(Parser<OmpEndAtomic>{} / endOmpLine)))
579
580// Atomic Construct
581TYPE_PARSER(construct<OpenMPAtomicConstruct>(Parser<OmpAtomicRead>{}) ||
582 construct<OpenMPAtomicConstruct>(Parser<OmpAtomicCapture>{}) ||
583 construct<OpenMPAtomicConstruct>(Parser<OmpAtomicWrite>{}) ||
584 construct<OpenMPAtomicConstruct>(Parser<OmpAtomicUpdate>{}) ||
585 construct<OpenMPAtomicConstruct>(Parser<OmpAtomic>{}))
586
587// 2.13.2 OMP CRITICAL
588TYPE_PARSER(startOmpLine >>
589 sourced(construct<OmpEndCriticalDirective>(
590 verbatim("END CRITICAL"_tok), maybe(parenthesized(name)))) /
591 endOmpLine)
592TYPE_PARSER(sourced(construct<OmpCriticalDirective>(verbatim("CRITICAL"_tok),
593 maybe(parenthesized(name)), Parser<OmpClauseList>{})) /
594 endOmpLine)
595
596TYPE_PARSER(construct<OpenMPCriticalConstruct>(
597 Parser<OmpCriticalDirective>{}, block, Parser<OmpEndCriticalDirective>{}))
598
599// 2.11.3 Executable Allocate directive
600TYPE_PARSER(
601 sourced(construct<OpenMPExecutableAllocate>(verbatim("ALLOCATE"_tok),
602 maybe(parenthesized(Parser<OmpObjectList>{})), Parser<OmpClauseList>{},
603 maybe(nonemptyList(Parser<OpenMPDeclarativeAllocate>{})) / endOmpLine,
604 statement(allocateStmt))))
605
606// 6.7 Allocators construct [OpenMP 5.2]
607// allocators-construct -> ALLOCATORS [allocate-clause [,]]
608// allocate-stmt
609// [omp-end-allocators-construct]
610TYPE_PARSER(sourced(construct<OpenMPAllocatorsConstruct>(
611 verbatim("ALLOCATORS"_tok), Parser<OmpClauseList>{} / endOmpLine,
612 statement(allocateStmt), maybe(Parser<OmpEndAllocators>{} / endOmpLine))))
613
614TYPE_PARSER(construct<OmpEndAllocators>(startOmpLine >> "END ALLOCATORS"_tok))
615
616// 2.8.2 Declare Simd construct
617TYPE_PARSER(
618 sourced(construct<OpenMPDeclareSimdConstruct>(verbatim("DECLARE SIMD"_tok),
619 maybe(parenthesized(name)), Parser<OmpClauseList>{})))
620
621// 2.4 Requires construct
622TYPE_PARSER(sourced(construct<OpenMPRequiresConstruct>(
623 verbatim("REQUIRES"_tok), Parser<OmpClauseList>{})))
624
625// 2.15.2 Threadprivate directive
626TYPE_PARSER(sourced(construct<OpenMPThreadprivate>(
627 verbatim("THREADPRIVATE"_tok), parenthesized(Parser<OmpObjectList>{}))))
628
629// 2.11.3 Declarative Allocate directive
630TYPE_PARSER(
631 sourced(construct<OpenMPDeclarativeAllocate>(verbatim("ALLOCATE"_tok),
632 parenthesized(Parser<OmpObjectList>{}), Parser<OmpClauseList>{})) /
633 lookAhead(endOmpLine / !statement(allocateStmt)))
634
635// Declarative constructs
636TYPE_PARSER(startOmpLine >>
637 sourced(construct<OpenMPDeclarativeConstruct>(
638 Parser<OpenMPDeclareReductionConstruct>{}) ||
639 construct<OpenMPDeclarativeConstruct>(
640 Parser<OpenMPDeclareSimdConstruct>{}) ||
641 construct<OpenMPDeclarativeConstruct>(
642 Parser<OpenMPDeclareTargetConstruct>{}) ||
643 construct<OpenMPDeclarativeConstruct>(
644 Parser<OpenMPDeclarativeAllocate>{}) ||
645 construct<OpenMPDeclarativeConstruct>(
646 Parser<OpenMPRequiresConstruct>{}) ||
647 construct<OpenMPDeclarativeConstruct>(Parser<OpenMPThreadprivate>{})) /
648 endOmpLine)
649
650// Block Construct
651TYPE_PARSER(construct<OpenMPBlockConstruct>(
652 Parser<OmpBeginBlockDirective>{} / endOmpLine, block,
653 Parser<OmpEndBlockDirective>{} / endOmpLine))
654
655// OMP SECTIONS Directive
656TYPE_PARSER(construct<OmpSectionsDirective>(first(
657 "SECTIONS" >> pure(llvm::omp::Directive::OMPD_sections),
658 "PARALLEL SECTIONS" >> pure(llvm::omp::Directive::OMPD_parallel_sections))))
659
660// OMP BEGIN and END SECTIONS Directive
661TYPE_PARSER(sourced(construct<OmpBeginSectionsDirective>(
662 sourced(Parser<OmpSectionsDirective>{}), Parser<OmpClauseList>{})))
663TYPE_PARSER(
664 startOmpLine >> sourced(construct<OmpEndSectionsDirective>(
665 sourced("END"_tok >> Parser<OmpSectionsDirective>{}),
666 Parser<OmpClauseList>{})))
667
668// OMP SECTION-BLOCK
669
670TYPE_PARSER(construct<OpenMPSectionConstruct>(block))
671
672TYPE_PARSER(maybe(startOmpLine >> "SECTION"_tok / endOmpLine) >>
673 construct<OmpSectionBlocks>(nonemptySeparated(
674 construct<OpenMPConstruct>(sourced(Parser<OpenMPSectionConstruct>{})),
675 startOmpLine >> "SECTION"_tok / endOmpLine)))
676
677// OMP SECTIONS (OpenMP 5.0 - 2.8.1), PARALLEL SECTIONS (OpenMP 5.0 - 2.13.3)
678TYPE_PARSER(construct<OpenMPSectionsConstruct>(
679 Parser<OmpBeginSectionsDirective>{} / endOmpLine,
680 Parser<OmpSectionBlocks>{}, Parser<OmpEndSectionsDirective>{} / endOmpLine))
681
682TYPE_CONTEXT_PARSER("OpenMP construct"_en_US,
683 startOmpLine >>
684 first(construct<OpenMPConstruct>(Parser<OpenMPSectionsConstruct>{}),
685 construct<OpenMPConstruct>(Parser<OpenMPLoopConstruct>{}),
686 construct<OpenMPConstruct>(Parser<OpenMPBlockConstruct>{}),
687 // OpenMPBlockConstruct is attempted before
688 // OpenMPStandaloneConstruct to resolve !$OMP ORDERED
689 construct<OpenMPConstruct>(Parser<OpenMPStandaloneConstruct>{}),
690 construct<OpenMPConstruct>(Parser<OpenMPAtomicConstruct>{}),
691 construct<OpenMPConstruct>(Parser<OpenMPExecutableAllocate>{}),
692 construct<OpenMPConstruct>(Parser<OpenMPAllocatorsConstruct>{}),
693 construct<OpenMPConstruct>(Parser<OpenMPDeclarativeAllocate>{}),
694 construct<OpenMPConstruct>(Parser<OpenMPCriticalConstruct>{})))
695
696// END OMP Block directives
697TYPE_PARSER(
698 startOmpLine >> sourced(construct<OmpEndBlockDirective>(
699 sourced("END"_tok >> Parser<OmpBlockDirective>{}),
700 Parser<OmpClauseList>{})))
701
702// END OMP Loop directives
703TYPE_PARSER(
704 startOmpLine >> sourced(construct<OmpEndLoopDirective>(
705 sourced("END"_tok >> Parser<OmpLoopDirective>{}),
706 Parser<OmpClauseList>{})))
707
708TYPE_PARSER(construct<OpenMPLoopConstruct>(
709 Parser<OmpBeginLoopDirective>{} / endOmpLine))
710} // namespace Fortran::parser
711

source code of flang/lib/Parser/openmp-parsers.cpp