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