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