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