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 Clause, typename Separator> struct ModifierList { 27 constexpr ModifierList(Separator sep) : sep_(sep) {} 28 constexpr ModifierList(const ModifierList &) = default; 29 constexpr ModifierList(ModifierList &&) = default; 30 31 using resultType = std::list<typename Clause::Modifier>; 32 33 std::optional<resultType> Parse(ParseState &state) const { 34 auto listp{nonemptySeparated(Parser<typename Clause::Modifier>{}, sep_)}; 35 if (auto result{attempt(listp).Parse(state)}) { 36 if (!attempt(":"_tok).Parse(state)) { 37 return std::nullopt; 38 } 39 return std::move(result); 40 } 41 return resultType{}; 42 } 43 44 private: 45 const Separator sep_; 46 }; 47 48 // Use a function to create ModifierList because functions allow "partial" 49 // template argument deduction: "modifierList<Clause>(sep)" would be legal, 50 // while "ModifierList<Clause>(sep)" would complain about a missing template 51 // argument "Separator". 52 template <typename Clause, typename Separator> 53 constexpr ModifierList<Clause, Separator> modifierList(Separator sep) { 54 return ModifierList<Clause, Separator>(sep); 55 } 56 57 // OpenMP Clauses 58 59 // [5.0] 2.1.6 iterator-specifier -> type-declaration-stmt = subscript-triple | 60 // identifier = subscript-triple 61 // [5.0:47:17-18] In an iterator-specifier, if the iterator-type is not 62 // specified then the type of that iterator is default integer. 63 // [5.0:49:14] The iterator-type must be an integer type. 64 static std::list<EntityDecl> makeEntityList(std::list<ObjectName> &&names) { 65 std::list<EntityDecl> entities; 66 67 for (auto iter = names.begin(), end = names.end(); iter != end; ++iter) { 68 EntityDecl entityDecl( 69 /*ObjectName=*/std::move(*iter), std::optional<ArraySpec>{}, 70 std::optional<CoarraySpec>{}, std::optional<CharLength>{}, 71 std::optional<Initialization>{}); 72 entities.push_back(std::move(entityDecl)); 73 } 74 return entities; 75 } 76 77 static TypeDeclarationStmt makeIterSpecDecl( 78 DeclarationTypeSpec &&spec, std::list<ObjectName> &&names) { 79 return TypeDeclarationStmt( 80 std::move(spec), std::list<AttrSpec>{}, makeEntityList(std::move(names))); 81 } 82 83 static TypeDeclarationStmt makeIterSpecDecl(std::list<ObjectName> &&names) { 84 // Assume INTEGER without kind selector. 85 DeclarationTypeSpec typeSpec( 86 IntrinsicTypeSpec{IntegerTypeSpec{std::nullopt}}); 87 88 return TypeDeclarationStmt(std::move(typeSpec), std::list<AttrSpec>{}, 89 makeEntityList(std::move(names))); 90 } 91 92 // --- Parsers for clause modifiers ----------------------------------- 93 94 TYPE_PARSER(construct<OmpAlignModifier>( // 95 "ALIGN" >> parenthesized(scalarIntExpr))) 96 97 TYPE_PARSER(construct<OmpAllocatorComplexModifier>( 98 "ALLOCATOR" >> parenthesized(scalarIntExpr))) 99 100 TYPE_PARSER(construct<OmpAllocatorSimpleModifier>(scalarIntExpr)) 101 102 TYPE_PARSER(construct<OmpChunkModifier>( // 103 "SIMD" >> pure(OmpChunkModifier::Value::Simd))) 104 105 TYPE_PARSER(construct<OmpDependenceType>( 106 "SINK" >> pure(OmpDependenceType::Value::Sink) || 107 "SOURCE" >> pure(OmpDependenceType::Value::Source))) 108 109 TYPE_PARSER(construct<OmpExpectation>( // 110 "PRESENT" >> pure(OmpExpectation::Value::Present))) 111 112 TYPE_PARSER(construct<OmpIteratorSpecifier>( 113 // Using Parser<TypeDeclarationStmt> or Parser<EntityDecl> has the problem 114 // that they will attempt to treat what follows the '=' as initialization. 115 // There are several issues with that, 116 // 1. integer :: i = 0:10 will be parsed as "integer :: i = 0", followed 117 // by triplet ":10". 118 // 2. integer :: j = i:10 will be flagged as an error because the 119 // initializer 'i' must be constant (in declarations). In an iterator 120 // specifier the 'j' is not an initializer and can be a variable. 121 (applyFunction<TypeDeclarationStmt>(makeIterSpecDecl, 122 Parser<DeclarationTypeSpec>{} / maybe("::"_tok), 123 nonemptyList(Parser<ObjectName>{}) / "="_tok) || 124 applyFunction<TypeDeclarationStmt>( 125 makeIterSpecDecl, nonemptyList(Parser<ObjectName>{}) / "="_tok)), 126 subscriptTriplet)) 127 128 // [5.0] 2.1.6 iterator -> iterator-specifier-list 129 TYPE_PARSER(construct<OmpIterator>( // 130 "ITERATOR" >> 131 parenthesized(nonemptyList(sourced(Parser<OmpIteratorSpecifier>{}))))) 132 133 // 2.15.3.7 LINEAR (linear-list: linear-step) 134 // linear-list -> list | modifier(list) 135 // linear-modifier -> REF | VAL | UVAL 136 TYPE_PARSER(construct<OmpLinearModifier>( // 137 "REF" >> pure(OmpLinearModifier::Value::Ref) || 138 "VAL" >> pure(OmpLinearModifier::Value::Val) || 139 "UVAL" >> pure(OmpLinearModifier::Value::Uval))) 140 141 TYPE_PARSER(construct<OmpMapper>( // 142 "MAPPER"_tok >> parenthesized(Parser<ObjectName>{}))) 143 144 // map-type -> ALLOC | DELETE | FROM | RELEASE | TO | TOFROM 145 TYPE_PARSER(construct<OmpMapType>( // 146 "ALLOC" >> pure(OmpMapType::Value::Alloc) || 147 "DELETE" >> pure(OmpMapType::Value::Delete) || 148 "FROM" >> pure(OmpMapType::Value::From) || 149 "RELEASE" >> pure(OmpMapType::Value::Release) || 150 "TO"_id >> pure(OmpMapType::Value::To) || 151 "TOFROM" >> pure(OmpMapType::Value::Tofrom))) 152 153 // map-type-modifier -> ALWAYS | CLOSE | OMPX_HOLD | PRESENT 154 TYPE_PARSER(construct<OmpMapTypeModifier>( 155 "ALWAYS" >> pure(OmpMapTypeModifier::Value::Always) || 156 "CLOSE" >> pure(OmpMapTypeModifier::Value::Close) || 157 "OMPX_HOLD" >> pure(OmpMapTypeModifier::Value::Ompx_Hold) || 158 "PRESENT" >> pure(OmpMapTypeModifier::Value::Present))) 159 160 // 2.15.3.6 REDUCTION (reduction-identifier: variable-name-list) 161 TYPE_PARSER(construct<OmpReductionIdentifier>(Parser<DefinedOperator>{}) || 162 construct<OmpReductionIdentifier>(Parser<ProcedureDesignator>{})) 163 164 TYPE_PARSER(construct<OmpOrderModifier>( 165 "REPRODUCIBLE" >> pure(OmpOrderModifier::Value::Reproducible) || 166 "UNCONSTRAINED" >> pure(OmpOrderModifier::Value::Unconstrained))) 167 168 TYPE_PARSER(construct<OmpOrderingModifier>( 169 "MONOTONIC" >> pure(OmpOrderingModifier::Value::Monotonic) || 170 "NONMONOTONIC" >> pure(OmpOrderingModifier::Value::Nonmonotonic) || 171 "SIMD" >> pure(OmpOrderingModifier::Value::Simd))) 172 173 TYPE_PARSER(construct<OmpReductionModifier>( 174 "INSCAN" >> pure(OmpReductionModifier::Value::Inscan) || 175 "TASK" >> pure(OmpReductionModifier::Value::Task) || 176 "DEFAULT" >> pure(OmpReductionModifier::Value::Default))) 177 178 TYPE_PARSER(construct<OmpTaskDependenceType>( 179 "DEPOBJ" >> pure(OmpTaskDependenceType::Value::Depobj) || 180 "IN"_id >> pure(OmpTaskDependenceType::Value::In) || 181 "INOUT"_id >> pure(OmpTaskDependenceType::Value::Inout) || 182 "INOUTSET"_id >> pure(OmpTaskDependenceType::Value::Inoutset) || 183 "MUTEXINOUTSET" >> pure(OmpTaskDependenceType::Value::Mutexinoutset) || 184 "OUT" >> pure(OmpTaskDependenceType::Value::Out))) 185 186 TYPE_PARSER(construct<OmpVariableCategory>( 187 "AGGREGATE" >> pure(OmpVariableCategory::Value::Aggregate) || 188 "ALL"_id >> pure(OmpVariableCategory::Value::All) || 189 "ALLOCATABLE" >> pure(OmpVariableCategory::Value::Allocatable) || 190 "POINTER" >> pure(OmpVariableCategory::Value::Pointer) || 191 "SCALAR" >> pure(OmpVariableCategory::Value::Scalar))) 192 193 // This could be auto-generated. 194 TYPE_PARSER(sourced(construct<OmpAllocateClause::Modifier>(sourced( 195 construct<OmpAllocateClause::Modifier>(Parser<OmpAlignModifier>{}) || 196 construct<OmpAllocateClause::Modifier>( 197 Parser<OmpAllocatorComplexModifier>{}) || 198 construct<OmpAllocateClause::Modifier>( 199 Parser<OmpAllocatorSimpleModifier>{}))))) 200 201 TYPE_PARSER(sourced( 202 construct<OmpDefaultmapClause::Modifier>(Parser<OmpVariableCategory>{}))) 203 204 TYPE_PARSER(sourced(construct<OmpFromClause::Modifier>( 205 sourced(construct<OmpFromClause::Modifier>(Parser<OmpExpectation>{}) || 206 construct<OmpFromClause::Modifier>(Parser<OmpMapper>{}) || 207 construct<OmpFromClause::Modifier>(Parser<OmpIterator>{}))))) 208 209 TYPE_PARSER(sourced(construct<OmpMapClause::Modifier>( 210 sourced(construct<OmpMapClause::Modifier>(Parser<OmpMapTypeModifier>{}) || 211 construct<OmpMapClause::Modifier>(Parser<OmpMapper>{}) || 212 construct<OmpMapClause::Modifier>(Parser<OmpIterator>{}) || 213 construct<OmpMapClause::Modifier>(Parser<OmpMapType>{}))))) 214 215 TYPE_PARSER( 216 sourced(construct<OmpOrderClause::Modifier>(Parser<OmpOrderModifier>{}))) 217 218 TYPE_PARSER(sourced(construct<OmpReductionClause::Modifier>(sourced( 219 construct<OmpReductionClause::Modifier>(Parser<OmpReductionModifier>{}) || 220 construct<OmpReductionClause::Modifier>( 221 Parser<OmpReductionIdentifier>{}))))) 222 223 TYPE_PARSER(sourced(construct<OmpScheduleClause::Modifier>(sourced( 224 construct<OmpScheduleClause::Modifier>(Parser<OmpChunkModifier>{}) || 225 construct<OmpScheduleClause::Modifier>(Parser<OmpOrderingModifier>{}))))) 226 227 TYPE_PARSER(sourced(construct<OmpToClause::Modifier>( 228 sourced(construct<OmpToClause::Modifier>(Parser<OmpExpectation>{}) || 229 construct<OmpToClause::Modifier>(Parser<OmpMapper>{}) || 230 construct<OmpToClause::Modifier>(Parser<OmpIterator>{}))))) 231 232 // --- Parsers for clauses -------------------------------------------- 233 234 /// `MOBClause` is a clause that has a 235 /// std::tuple<Modifiers, OmpObjectList, bool>. 236 /// Helper function to create a typical modifiers-objects clause, where the 237 /// commas separating individual modifiers are optional, and the clause 238 /// contains a bool member to indicate whether it was fully comma-separated 239 /// or not. 240 template <bool CommaSeparated, typename MOBClause> 241 static inline MOBClause makeMobClause( 242 std::list<typename MOBClause::Modifier> &&mods, OmpObjectList &&objs) { 243 if (!mods.empty()) { 244 return MOBClause{std::move(mods), std::move(objs), CommaSeparated}; 245 } else { 246 using ListTy = std::list<typename MOBClause::Modifier>; 247 return MOBClause{std::optional<ListTy>{}, std::move(objs), CommaSeparated}; 248 } 249 } 250 251 // [5.0] 2.10.1 affinity([aff-modifier:] locator-list) 252 // aff-modifier: interator-modifier 253 TYPE_PARSER(construct<OmpAffinityClause>( 254 maybe(Parser<OmpIterator>{} / ":"), Parser<OmpObjectList>{})) 255 256 // 2.15.3.1 DEFAULT (PRIVATE | FIRSTPRIVATE | SHARED | NONE) 257 TYPE_PARSER(construct<OmpDefaultClause>( 258 "PRIVATE" >> pure(OmpDefaultClause::DataSharingAttribute::Private) || 259 "FIRSTPRIVATE" >> 260 pure(OmpDefaultClause::DataSharingAttribute::Firstprivate) || 261 "SHARED" >> pure(OmpDefaultClause::DataSharingAttribute::Shared) || 262 "NONE" >> pure(OmpDefaultClause::DataSharingAttribute::None))) 263 264 // 2.5 PROC_BIND (MASTER | CLOSE | PRIMARY | SPREAD) 265 TYPE_PARSER(construct<OmpProcBindClause>( 266 "CLOSE" >> pure(OmpProcBindClause::AffinityPolicy::Close) || 267 "MASTER" >> pure(OmpProcBindClause::AffinityPolicy::Master) || 268 "PRIMARY" >> pure(OmpProcBindClause::AffinityPolicy::Primary) || 269 "SPREAD" >> pure(OmpProcBindClause::AffinityPolicy::Spread))) 270 271 TYPE_PARSER(construct<OmpMapClause>( 272 applyFunction<OmpMapClause>(makeMobClause<true>, 273 modifierList<OmpMapClause>(","_tok), Parser<OmpObjectList>{}) || 274 applyFunction<OmpMapClause>(makeMobClause<false>, 275 modifierList<OmpMapClause>(maybe(","_tok)), Parser<OmpObjectList>{}))) 276 277 // [OpenMP 5.0] 278 // 2.19.7.2 defaultmap(implicit-behavior[:variable-category]) 279 // implicit-behavior -> ALLOC | TO | FROM | TOFROM | FIRSRTPRIVATE | NONE | 280 // DEFAULT 281 // variable-category -> ALL | SCALAR | AGGREGATE | ALLOCATABLE | POINTER 282 TYPE_PARSER(construct<OmpDefaultmapClause>( 283 construct<OmpDefaultmapClause::ImplicitBehavior>( 284 "ALLOC" >> pure(OmpDefaultmapClause::ImplicitBehavior::Alloc) || 285 "TO"_id >> pure(OmpDefaultmapClause::ImplicitBehavior::To) || 286 "FROM" >> pure(OmpDefaultmapClause::ImplicitBehavior::From) || 287 "TOFROM" >> pure(OmpDefaultmapClause::ImplicitBehavior::Tofrom) || 288 "FIRSTPRIVATE" >> 289 pure(OmpDefaultmapClause::ImplicitBehavior::Firstprivate) || 290 "NONE" >> pure(OmpDefaultmapClause::ImplicitBehavior::None) || 291 "DEFAULT" >> pure(OmpDefaultmapClause::ImplicitBehavior::Default)), 292 maybe(":" >> nonemptyList(Parser<OmpDefaultmapClause::Modifier>{})))) 293 294 TYPE_PARSER(construct<OmpScheduleClause::Kind>( 295 "STATIC" >> pure(OmpScheduleClause::Kind::Static) || 296 "DYNAMIC" >> pure(OmpScheduleClause::Kind::Dynamic) || 297 "GUIDED" >> pure(OmpScheduleClause::Kind::Guided) || 298 "AUTO" >> pure(OmpScheduleClause::Kind::Auto) || 299 "RUNTIME" >> pure(OmpScheduleClause::Kind::Runtime))) 300 301 TYPE_PARSER(construct<OmpScheduleClause>( 302 maybe(nonemptyList(Parser<OmpScheduleClause::Modifier>{}) / ":"), 303 Parser<OmpScheduleClause::Kind>{}, maybe("," >> scalarIntExpr))) 304 305 // device([ device-modifier :] scalar-integer-expression) 306 TYPE_PARSER(construct<OmpDeviceClause>( 307 maybe( 308 ("ANCESTOR" >> pure(OmpDeviceClause::DeviceModifier::Ancestor) || 309 "DEVICE_NUM" >> pure(OmpDeviceClause::DeviceModifier::Device_Num)) / 310 ":"), 311 scalarIntExpr)) 312 313 // device_type(any | host | nohost) 314 TYPE_PARSER(construct<OmpDeviceTypeClause>( 315 "ANY" >> pure(OmpDeviceTypeClause::DeviceTypeDescription::Any) || 316 "HOST" >> pure(OmpDeviceTypeClause::DeviceTypeDescription::Host) || 317 "NOHOST" >> pure(OmpDeviceTypeClause::DeviceTypeDescription::Nohost))) 318 319 // 2.12 IF (directive-name-modifier: scalar-logical-expr) 320 TYPE_PARSER(construct<OmpIfClause>( 321 maybe( 322 ("PARALLEL" >> pure(OmpIfClause::DirectiveNameModifier::Parallel) || 323 "SIMD" >> pure(OmpIfClause::DirectiveNameModifier::Simd) || 324 "TARGET ENTER DATA" >> 325 pure(OmpIfClause::DirectiveNameModifier::TargetEnterData) || 326 "TARGET EXIT DATA" >> 327 pure(OmpIfClause::DirectiveNameModifier::TargetExitData) || 328 "TARGET DATA" >> 329 pure(OmpIfClause::DirectiveNameModifier::TargetData) || 330 "TARGET UPDATE" >> 331 pure(OmpIfClause::DirectiveNameModifier::TargetUpdate) || 332 "TARGET" >> pure(OmpIfClause::DirectiveNameModifier::Target) || 333 "TASK"_id >> pure(OmpIfClause::DirectiveNameModifier::Task) || 334 "TASKLOOP" >> pure(OmpIfClause::DirectiveNameModifier::Taskloop) || 335 "TEAMS" >> pure(OmpIfClause::DirectiveNameModifier::Teams)) / 336 ":"), 337 scalarLogicalExpr)) 338 339 TYPE_PARSER(construct<OmpReductionClause>( 340 maybe(nonemptyList(Parser<OmpReductionClause::Modifier>{}) / ":"), 341 Parser<OmpObjectList>{})) 342 343 // OMP 5.0 2.19.5.6 IN_REDUCTION (reduction-identifier: variable-name-list) 344 TYPE_PARSER(construct<OmpInReductionClause>( 345 Parser<OmpReductionIdentifier>{} / ":", Parser<OmpObjectList>{})) 346 347 // OMP 5.0 2.11.4 allocate-clause -> ALLOCATE ([allocator:] variable-name-list) 348 // OMP 5.2 2.13.4 allocate-clause -> ALLOCATE ([allocate-modifier 349 // [, allocate-modifier] :] 350 // variable-name-list) 351 // allocate-modifier -> allocator | align 352 TYPE_PARSER(construct<OmpAllocateClause>( 353 maybe(nonemptyList(Parser<OmpAllocateClause::Modifier>{}) / ":"), 354 Parser<OmpObjectList>{})) 355 356 // iteration-offset -> +/- non-negative-constant-expr 357 TYPE_PARSER(construct<OmpIterationOffset>( 358 Parser<DefinedOperator>{}, scalarIntConstantExpr)) 359 360 // iteration -> iteration-variable [+/- nonnegative-scalar-integer-constant] 361 TYPE_PARSER(construct<OmpIteration>(name, maybe(Parser<OmpIterationOffset>{}))) 362 363 TYPE_PARSER(construct<OmpIterationVector>(nonemptyList(Parser<OmpIteration>{}))) 364 365 TYPE_PARSER(construct<OmpDoacross>( 366 construct<OmpDoacross>(construct<OmpDoacross::Sink>( 367 "SINK"_tok >> ":"_tok >> Parser<OmpIterationVector>{})) || 368 construct<OmpDoacross>(construct<OmpDoacross::Source>("SOURCE"_tok)))) 369 370 TYPE_CONTEXT_PARSER("Omp Depend clause"_en_US, 371 construct<OmpDependClause>( 372 construct<OmpDependClause>(construct<OmpDependClause::TaskDep>( 373 maybe(Parser<OmpIterator>{} / ","_tok), 374 Parser<OmpTaskDependenceType>{} / ":", Parser<OmpObjectList>{})) || 375 construct<OmpDependClause>(Parser<OmpDoacross>{}))) 376 377 TYPE_CONTEXT_PARSER("Omp Doacross clause"_en_US, 378 construct<OmpDoacrossClause>(Parser<OmpDoacross>{})) 379 380 TYPE_PARSER(construct<OmpFromClause>( 381 applyFunction<OmpFromClause>(makeMobClause<true>, 382 modifierList<OmpFromClause>(","_tok), Parser<OmpObjectList>{}) || 383 applyFunction<OmpFromClause>(makeMobClause<false>, 384 modifierList<OmpFromClause>(maybe(","_tok)), Parser<OmpObjectList>{}))) 385 386 TYPE_PARSER(construct<OmpToClause>( 387 applyFunction<OmpToClause>(makeMobClause<true>, 388 modifierList<OmpToClause>(","_tok), Parser<OmpObjectList>{}) || 389 applyFunction<OmpToClause>(makeMobClause<false>, 390 modifierList<OmpToClause>(maybe(","_tok)), Parser<OmpObjectList>{}))) 391 392 TYPE_CONTEXT_PARSER("Omp LINEAR clause"_en_US, 393 construct<OmpLinearClause>( 394 construct<OmpLinearClause>(construct<OmpLinearClause::WithModifier>( 395 Parser<OmpLinearModifier>{}, parenthesized(nonemptyList(name)), 396 maybe(":" >> scalarIntConstantExpr))) || 397 construct<OmpLinearClause>(construct<OmpLinearClause::WithoutModifier>( 398 nonemptyList(name), maybe(":" >> scalarIntConstantExpr))))) 399 400 // OpenMPv5.2 12.5.2 detach-clause -> DETACH (event-handle) 401 TYPE_PARSER(construct<OmpDetachClause>(Parser<OmpObject>{})) 402 403 // 2.8.1 ALIGNED (list: alignment) 404 TYPE_PARSER(construct<OmpAlignedClause>( 405 Parser<OmpObjectList>{}, maybe(":" >> scalarIntConstantExpr))) 406 407 TYPE_PARSER(construct<OmpUpdateClause>( 408 construct<OmpUpdateClause>(Parser<OmpDependenceType>{}) || 409 construct<OmpUpdateClause>(Parser<OmpTaskDependenceType>{}))) 410 411 TYPE_PARSER(construct<OmpOrderClause>( 412 maybe(nonemptyList(Parser<OmpOrderClause::Modifier>{}) / ":"), 413 "CONCURRENT" >> pure(OmpOrderClause::Ordering::Concurrent))) 414 415 // OMP 5.2 12.6.1 grainsize([ prescriptiveness :] scalar-integer-expression) 416 TYPE_PARSER(construct<OmpGrainsizeClause>( 417 maybe("STRICT" >> pure(OmpGrainsizeClause::Prescriptiveness::Strict) / ":"), 418 scalarIntExpr)) 419 420 // OMP 5.2 12.6.2 num_tasks([ prescriptiveness :] scalar-integer-expression) 421 TYPE_PARSER(construct<OmpNumTasksClause>( 422 maybe("STRICT" >> pure(OmpNumTasksClause::Prescriptiveness::Strict) / ":"), 423 scalarIntExpr)) 424 425 TYPE_PARSER( 426 construct<OmpObject>(designator) || construct<OmpObject>("/" >> name / "/")) 427 428 // OMP 5.0 2.19.4.5 LASTPRIVATE ([lastprivate-modifier :] list) 429 TYPE_PARSER(construct<OmpLastprivateClause>( 430 maybe("CONDITIONAL" >> 431 pure(OmpLastprivateClause::LastprivateModifier::Conditional) / ":"), 432 Parser<OmpObjectList>{})) 433 434 // OMP 5.2 11.7.1 BIND ( PARALLEL | TEAMS | THREAD ) 435 TYPE_PARSER(construct<OmpBindClause>( 436 "PARALLEL" >> pure(OmpBindClause::Binding::Parallel) || 437 "TEAMS" >> pure(OmpBindClause::Binding::Teams) || 438 "THREAD" >> pure(OmpBindClause::Binding::Thread))) 439 440 TYPE_PARSER( 441 "ACQUIRE" >> construct<OmpClause>(construct<OmpClause::Acquire>()) || 442 "ACQ_REL" >> construct<OmpClause>(construct<OmpClause::AcqRel>()) || 443 "AFFINITY" >> construct<OmpClause>(construct<OmpClause::Affinity>( 444 parenthesized(Parser<OmpAffinityClause>{}))) || 445 "ALIGNED" >> construct<OmpClause>(construct<OmpClause::Aligned>( 446 parenthesized(Parser<OmpAlignedClause>{}))) || 447 "ALLOCATE" >> construct<OmpClause>(construct<OmpClause::Allocate>( 448 parenthesized(Parser<OmpAllocateClause>{}))) || 449 "ALLOCATOR" >> construct<OmpClause>(construct<OmpClause::Allocator>( 450 parenthesized(scalarIntExpr))) || 451 "ATOMIC_DEFAULT_MEM_ORDER" >> 452 construct<OmpClause>(construct<OmpClause::AtomicDefaultMemOrder>( 453 parenthesized(Parser<OmpAtomicDefaultMemOrderClause>{}))) || 454 "BIND" >> construct<OmpClause>(construct<OmpClause::Bind>( 455 parenthesized(Parser<OmpBindClause>{}))) || 456 "COLLAPSE" >> construct<OmpClause>(construct<OmpClause::Collapse>( 457 parenthesized(scalarIntConstantExpr))) || 458 "COPYIN" >> construct<OmpClause>(construct<OmpClause::Copyin>( 459 parenthesized(Parser<OmpObjectList>{}))) || 460 "COPYPRIVATE" >> construct<OmpClause>(construct<OmpClause::Copyprivate>( 461 (parenthesized(Parser<OmpObjectList>{})))) || 462 "DEFAULT"_id >> construct<OmpClause>(construct<OmpClause::Default>( 463 parenthesized(Parser<OmpDefaultClause>{}))) || 464 "DEFAULTMAP" >> construct<OmpClause>(construct<OmpClause::Defaultmap>( 465 parenthesized(Parser<OmpDefaultmapClause>{}))) || 466 "DEPEND" >> construct<OmpClause>(construct<OmpClause::Depend>( 467 parenthesized(Parser<OmpDependClause>{}))) || 468 "DESTROY" >> 469 construct<OmpClause>(construct<OmpClause::Destroy>(maybe(parenthesized( 470 construct<OmpDestroyClause>(Parser<OmpObject>{}))))) || 471 "DEVICE" >> construct<OmpClause>(construct<OmpClause::Device>( 472 parenthesized(Parser<OmpDeviceClause>{}))) || 473 "DEVICE_TYPE" >> construct<OmpClause>(construct<OmpClause::DeviceType>( 474 parenthesized(Parser<OmpDeviceTypeClause>{}))) || 475 "DIST_SCHEDULE" >> 476 construct<OmpClause>(construct<OmpClause::DistSchedule>( 477 parenthesized("STATIC" >> maybe("," >> scalarIntExpr)))) || 478 "DOACROSS" >> 479 construct<OmpClause>(parenthesized(Parser<OmpDoacrossClause>{})) || 480 "DYNAMIC_ALLOCATORS" >> 481 construct<OmpClause>(construct<OmpClause::DynamicAllocators>()) || 482 "ENTER" >> construct<OmpClause>(construct<OmpClause::Enter>( 483 parenthesized(Parser<OmpObjectList>{}))) || 484 "EXCLUSIVE" >> construct<OmpClause>(construct<OmpClause::Exclusive>( 485 parenthesized(Parser<OmpObjectList>{}))) || 486 "FILTER" >> construct<OmpClause>(construct<OmpClause::Filter>( 487 parenthesized(scalarIntExpr))) || 488 "FINAL" >> construct<OmpClause>(construct<OmpClause::Final>( 489 parenthesized(scalarLogicalExpr))) || 490 "FIRSTPRIVATE" >> construct<OmpClause>(construct<OmpClause::Firstprivate>( 491 parenthesized(Parser<OmpObjectList>{}))) || 492 "FROM" >> construct<OmpClause>(construct<OmpClause::From>( 493 parenthesized(Parser<OmpFromClause>{}))) || 494 "FULL" >> construct<OmpClause>(construct<OmpClause::Full>()) || 495 "GRAINSIZE" >> construct<OmpClause>(construct<OmpClause::Grainsize>( 496 parenthesized(Parser<OmpGrainsizeClause>{}))) || 497 "HAS_DEVICE_ADDR" >> 498 construct<OmpClause>(construct<OmpClause::HasDeviceAddr>( 499 parenthesized(Parser<OmpObjectList>{}))) || 500 "HINT" >> construct<OmpClause>( 501 construct<OmpClause::Hint>(parenthesized(constantExpr))) || 502 "IF" >> construct<OmpClause>(construct<OmpClause::If>( 503 parenthesized(Parser<OmpIfClause>{}))) || 504 "INBRANCH" >> construct<OmpClause>(construct<OmpClause::Inbranch>()) || 505 "INCLUSIVE" >> construct<OmpClause>(construct<OmpClause::Inclusive>( 506 parenthesized(Parser<OmpObjectList>{}))) || 507 "IS_DEVICE_PTR" >> construct<OmpClause>(construct<OmpClause::IsDevicePtr>( 508 parenthesized(Parser<OmpObjectList>{}))) || 509 "LASTPRIVATE" >> construct<OmpClause>(construct<OmpClause::Lastprivate>( 510 parenthesized(Parser<OmpLastprivateClause>{}))) || 511 "LINEAR" >> construct<OmpClause>(construct<OmpClause::Linear>( 512 parenthesized(Parser<OmpLinearClause>{}))) || 513 "LINK" >> construct<OmpClause>(construct<OmpClause::Link>( 514 parenthesized(Parser<OmpObjectList>{}))) || 515 "MAP" >> construct<OmpClause>(construct<OmpClause::Map>( 516 parenthesized(Parser<OmpMapClause>{}))) || 517 "MERGEABLE" >> construct<OmpClause>(construct<OmpClause::Mergeable>()) || 518 "NOGROUP" >> construct<OmpClause>(construct<OmpClause::Nogroup>()) || 519 "NONTEMPORAL" >> construct<OmpClause>(construct<OmpClause::Nontemporal>( 520 parenthesized(nonemptyList(name)))) || 521 "NOTINBRANCH" >> 522 construct<OmpClause>(construct<OmpClause::Notinbranch>()) || 523 "NOWAIT" >> construct<OmpClause>(construct<OmpClause::Nowait>()) || 524 "NUM_TASKS" >> construct<OmpClause>(construct<OmpClause::NumTasks>( 525 parenthesized(Parser<OmpNumTasksClause>{}))) || 526 "NUM_TEAMS" >> construct<OmpClause>(construct<OmpClause::NumTeams>( 527 parenthesized(scalarIntExpr))) || 528 "NUM_THREADS" >> construct<OmpClause>(construct<OmpClause::NumThreads>( 529 parenthesized(scalarIntExpr))) || 530 "ORDER" >> construct<OmpClause>(construct<OmpClause::Order>( 531 parenthesized(Parser<OmpOrderClause>{}))) || 532 "ORDERED" >> construct<OmpClause>(construct<OmpClause::Ordered>( 533 maybe(parenthesized(scalarIntConstantExpr)))) || 534 "PARTIAL" >> construct<OmpClause>(construct<OmpClause::Partial>( 535 maybe(parenthesized(scalarIntConstantExpr)))) || 536 "PRIORITY" >> construct<OmpClause>(construct<OmpClause::Priority>( 537 parenthesized(scalarIntExpr))) || 538 "PRIVATE" >> construct<OmpClause>(construct<OmpClause::Private>( 539 parenthesized(Parser<OmpObjectList>{}))) || 540 "PROC_BIND" >> construct<OmpClause>(construct<OmpClause::ProcBind>( 541 parenthesized(Parser<OmpProcBindClause>{}))) || 542 "REDUCTION" >> construct<OmpClause>(construct<OmpClause::Reduction>( 543 parenthesized(Parser<OmpReductionClause>{}))) || 544 "IN_REDUCTION" >> construct<OmpClause>(construct<OmpClause::InReduction>( 545 parenthesized(Parser<OmpInReductionClause>{}))) || 546 "DETACH" >> construct<OmpClause>(construct<OmpClause::Detach>( 547 parenthesized(Parser<OmpDetachClause>{}))) || 548 "TASK_REDUCTION" >> 549 construct<OmpClause>(construct<OmpClause::TaskReduction>( 550 parenthesized(Parser<OmpReductionClause>{}))) || 551 "RELAXED" >> construct<OmpClause>(construct<OmpClause::Relaxed>()) || 552 "RELEASE" >> construct<OmpClause>(construct<OmpClause::Release>()) || 553 "REVERSE_OFFLOAD" >> 554 construct<OmpClause>(construct<OmpClause::ReverseOffload>()) || 555 "SAFELEN" >> construct<OmpClause>(construct<OmpClause::Safelen>( 556 parenthesized(scalarIntConstantExpr))) || 557 "SCHEDULE" >> construct<OmpClause>(construct<OmpClause::Schedule>( 558 parenthesized(Parser<OmpScheduleClause>{}))) || 559 "SEQ_CST" >> construct<OmpClause>(construct<OmpClause::SeqCst>()) || 560 "SHARED" >> construct<OmpClause>(construct<OmpClause::Shared>( 561 parenthesized(Parser<OmpObjectList>{}))) || 562 "SIMD"_id >> construct<OmpClause>(construct<OmpClause::Simd>()) || 563 "SIMDLEN" >> construct<OmpClause>(construct<OmpClause::Simdlen>( 564 parenthesized(scalarIntConstantExpr))) || 565 "SIZES" >> construct<OmpClause>(construct<OmpClause::Sizes>( 566 parenthesized(nonemptyList(scalarIntExpr)))) || 567 "PERMUTATION" >> construct<OmpClause>(construct<OmpClause::Permutation>( 568 parenthesized(nonemptyList(scalarIntExpr)))) || 569 "THREADS" >> construct<OmpClause>(construct<OmpClause::Threads>()) || 570 "THREAD_LIMIT" >> construct<OmpClause>(construct<OmpClause::ThreadLimit>( 571 parenthesized(scalarIntExpr))) || 572 "TO" >> construct<OmpClause>(construct<OmpClause::To>( 573 parenthesized(Parser<OmpToClause>{}))) || 574 "USE_DEVICE_PTR" >> construct<OmpClause>(construct<OmpClause::UseDevicePtr>( 575 parenthesized(Parser<OmpObjectList>{}))) || 576 "USE_DEVICE_ADDR" >> 577 construct<OmpClause>(construct<OmpClause::UseDeviceAddr>( 578 parenthesized(Parser<OmpObjectList>{}))) || 579 "UNIFIED_ADDRESS" >> 580 construct<OmpClause>(construct<OmpClause::UnifiedAddress>()) || 581 "UNIFIED_SHARED_MEMORY" >> 582 construct<OmpClause>(construct<OmpClause::UnifiedSharedMemory>()) || 583 "UNIFORM" >> construct<OmpClause>(construct<OmpClause::Uniform>( 584 parenthesized(nonemptyList(name)))) || 585 "UNTIED" >> construct<OmpClause>(construct<OmpClause::Untied>()) || 586 "UPDATE" >> construct<OmpClause>(construct<OmpClause::Update>( 587 parenthesized(Parser<OmpUpdateClause>{})))) 588 589 // [Clause, [Clause], ...] 590 TYPE_PARSER(sourced(construct<OmpClauseList>( 591 many(maybe(","_tok) >> sourced(Parser<OmpClause>{}))))) 592 593 // 2.1 (variable | /common-block | array-sections) 594 TYPE_PARSER(construct<OmpObjectList>(nonemptyList(Parser<OmpObject>{}))) 595 596 // Omp directives enclosing do loop 597 TYPE_PARSER(sourced(construct<OmpLoopDirective>(first( 598 "DISTRIBUTE PARALLEL DO SIMD" >> 599 pure(llvm::omp::Directive::OMPD_distribute_parallel_do_simd), 600 "DISTRIBUTE PARALLEL DO" >> 601 pure(llvm::omp::Directive::OMPD_distribute_parallel_do), 602 "DISTRIBUTE SIMD" >> pure(llvm::omp::Directive::OMPD_distribute_simd), 603 "DISTRIBUTE" >> pure(llvm::omp::Directive::OMPD_distribute), 604 "DO SIMD" >> pure(llvm::omp::Directive::OMPD_do_simd), 605 "DO" >> pure(llvm::omp::Directive::OMPD_do), 606 "LOOP" >> pure(llvm::omp::Directive::OMPD_loop), 607 "MASKED TASKLOOP SIMD" >> 608 pure(llvm::omp::Directive::OMPD_masked_taskloop_simd), 609 "MASKED TASKLOOP" >> pure(llvm::omp::Directive::OMPD_masked_taskloop), 610 "MASTER TASKLOOP SIMD" >> 611 pure(llvm::omp::Directive::OMPD_master_taskloop_simd), 612 "MASTER TASKLOOP" >> pure(llvm::omp::Directive::OMPD_master_taskloop), 613 "PARALLEL DO SIMD" >> pure(llvm::omp::Directive::OMPD_parallel_do_simd), 614 "PARALLEL DO" >> pure(llvm::omp::Directive::OMPD_parallel_do), 615 "PARALLEL MASKED TASKLOOP SIMD" >> 616 pure(llvm::omp::Directive::OMPD_parallel_masked_taskloop_simd), 617 "PARALLEL MASKED TASKLOOP" >> 618 pure(llvm::omp::Directive::OMPD_parallel_masked_taskloop), 619 "PARALLEL MASTER TASKLOOP SIMD" >> 620 pure(llvm::omp::Directive::OMPD_parallel_master_taskloop_simd), 621 "PARALLEL MASTER TASKLOOP" >> 622 pure(llvm::omp::Directive::OMPD_parallel_master_taskloop), 623 "SIMD" >> pure(llvm::omp::Directive::OMPD_simd), 624 "TARGET LOOP" >> pure(llvm::omp::Directive::OMPD_target_loop), 625 "TARGET PARALLEL DO SIMD" >> 626 pure(llvm::omp::Directive::OMPD_target_parallel_do_simd), 627 "TARGET PARALLEL DO" >> pure(llvm::omp::Directive::OMPD_target_parallel_do), 628 "TARGET PARALLEL LOOP" >> 629 pure(llvm::omp::Directive::OMPD_target_parallel_loop), 630 "TARGET SIMD" >> pure(llvm::omp::Directive::OMPD_target_simd), 631 "TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD" >> 632 pure(llvm::omp::Directive:: 633 OMPD_target_teams_distribute_parallel_do_simd), 634 "TARGET TEAMS DISTRIBUTE PARALLEL DO" >> 635 pure(llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do), 636 "TARGET TEAMS DISTRIBUTE SIMD" >> 637 pure(llvm::omp::Directive::OMPD_target_teams_distribute_simd), 638 "TARGET TEAMS DISTRIBUTE" >> 639 pure(llvm::omp::Directive::OMPD_target_teams_distribute), 640 "TARGET TEAMS LOOP" >> pure(llvm::omp::Directive::OMPD_target_teams_loop), 641 "TASKLOOP SIMD" >> pure(llvm::omp::Directive::OMPD_taskloop_simd), 642 "TASKLOOP" >> pure(llvm::omp::Directive::OMPD_taskloop), 643 "TEAMS DISTRIBUTE PARALLEL DO SIMD" >> 644 pure(llvm::omp::Directive::OMPD_teams_distribute_parallel_do_simd), 645 "TEAMS DISTRIBUTE PARALLEL DO" >> 646 pure(llvm::omp::Directive::OMPD_teams_distribute_parallel_do), 647 "TEAMS DISTRIBUTE SIMD" >> 648 pure(llvm::omp::Directive::OMPD_teams_distribute_simd), 649 "TEAMS DISTRIBUTE" >> pure(llvm::omp::Directive::OMPD_teams_distribute), 650 "TEAMS LOOP" >> pure(llvm::omp::Directive::OMPD_teams_loop), 651 "TILE" >> pure(llvm::omp::Directive::OMPD_tile), 652 "UNROLL" >> pure(llvm::omp::Directive::OMPD_unroll))))) 653 654 TYPE_PARSER(sourced(construct<OmpBeginLoopDirective>( 655 sourced(Parser<OmpLoopDirective>{}), Parser<OmpClauseList>{}))) 656 657 // 2.14.1 construct-type-clause -> PARALLEL | SECTIONS | DO | TASKGROUP 658 TYPE_PARSER(sourced(construct<OmpCancelType>( 659 first("PARALLEL" >> pure(OmpCancelType::Type::Parallel), 660 "SECTIONS" >> pure(OmpCancelType::Type::Sections), 661 "DO" >> pure(OmpCancelType::Type::Do), 662 "TASKGROUP" >> pure(OmpCancelType::Type::Taskgroup))))) 663 664 // 2.14.2 Cancellation Point construct 665 TYPE_PARSER(sourced(construct<OpenMPCancellationPointConstruct>( 666 verbatim("CANCELLATION POINT"_tok), Parser<OmpCancelType>{}))) 667 668 // 2.14.1 Cancel construct 669 TYPE_PARSER(sourced(construct<OpenMPCancelConstruct>(verbatim("CANCEL"_tok), 670 Parser<OmpCancelType>{}, maybe("IF" >> parenthesized(scalarLogicalExpr))))) 671 672 // 2.17.7 Atomic construct/2.17.8 Flush construct [OpenMP 5.0] 673 // memory-order-clause -> 674 // seq_cst 675 // acq_rel 676 // release 677 // acquire 678 // relaxed 679 TYPE_PARSER(sourced(construct<OmpMemoryOrderClause>( 680 sourced("SEQ_CST" >> construct<OmpClause>(construct<OmpClause::SeqCst>()) || 681 "ACQ_REL" >> construct<OmpClause>(construct<OmpClause::AcqRel>()) || 682 "RELEASE" >> construct<OmpClause>(construct<OmpClause::Release>()) || 683 "ACQUIRE" >> construct<OmpClause>(construct<OmpClause::Acquire>()) || 684 "RELAXED" >> construct<OmpClause>(construct<OmpClause::Relaxed>()))))) 685 686 // 2.4 Requires construct [OpenMP 5.0] 687 // atomic-default-mem-order-clause -> 688 // seq_cst 689 // acq_rel 690 // relaxed 691 TYPE_PARSER(construct<OmpAtomicDefaultMemOrderClause>( 692 "SEQ_CST" >> pure(common::OmpAtomicDefaultMemOrderType::SeqCst) || 693 "ACQ_REL" >> pure(common::OmpAtomicDefaultMemOrderType::AcqRel) || 694 "RELAXED" >> pure(common::OmpAtomicDefaultMemOrderType::Relaxed))) 695 696 // 2.17.7 Atomic construct 697 // atomic-clause -> memory-order-clause | HINT(hint-expression) 698 TYPE_PARSER(sourced(construct<OmpAtomicClause>( 699 construct<OmpAtomicClause>(Parser<OmpMemoryOrderClause>{}) || 700 construct<OmpAtomicClause>("HINT" >> 701 sourced(construct<OmpClause>( 702 construct<OmpClause::Hint>(parenthesized(constantExpr)))))))) 703 704 // atomic-clause-list -> [atomic-clause, [atomic-clause], ...] 705 TYPE_PARSER(sourced(construct<OmpAtomicClauseList>( 706 many(maybe(","_tok) >> sourced(Parser<OmpAtomicClause>{}))))) 707 708 TYPE_PARSER(sourced(construct<OpenMPDepobjConstruct>(verbatim("DEPOBJ"_tok), 709 parenthesized(Parser<OmpObject>{}), sourced(Parser<OmpClause>{})))) 710 711 TYPE_PARSER(sourced(construct<OpenMPFlushConstruct>(verbatim("FLUSH"_tok), 712 many(maybe(","_tok) >> sourced(Parser<OmpMemoryOrderClause>{})), 713 maybe(parenthesized(Parser<OmpObjectList>{}))))) 714 715 // Simple Standalone Directives 716 TYPE_PARSER(sourced(construct<OmpSimpleStandaloneDirective>(first( 717 "BARRIER" >> pure(llvm::omp::Directive::OMPD_barrier), 718 "ORDERED" >> pure(llvm::omp::Directive::OMPD_ordered), 719 "SCAN" >> pure(llvm::omp::Directive::OMPD_scan), 720 "TARGET ENTER DATA" >> pure(llvm::omp::Directive::OMPD_target_enter_data), 721 "TARGET EXIT DATA" >> pure(llvm::omp::Directive::OMPD_target_exit_data), 722 "TARGET UPDATE" >> pure(llvm::omp::Directive::OMPD_target_update), 723 "TASKWAIT" >> pure(llvm::omp::Directive::OMPD_taskwait), 724 "TASKYIELD" >> pure(llvm::omp::Directive::OMPD_taskyield))))) 725 726 TYPE_PARSER(sourced(construct<OpenMPSimpleStandaloneConstruct>( 727 Parser<OmpSimpleStandaloneDirective>{}, Parser<OmpClauseList>{}))) 728 729 // Standalone Constructs 730 TYPE_PARSER( 731 sourced(construct<OpenMPStandaloneConstruct>( 732 Parser<OpenMPSimpleStandaloneConstruct>{}) || 733 construct<OpenMPStandaloneConstruct>(Parser<OpenMPFlushConstruct>{}) || 734 construct<OpenMPStandaloneConstruct>(Parser<OpenMPCancelConstruct>{}) || 735 construct<OpenMPStandaloneConstruct>( 736 Parser<OpenMPCancellationPointConstruct>{}) || 737 construct<OpenMPStandaloneConstruct>(Parser<OpenMPDepobjConstruct>{})) / 738 endOfLine) 739 740 // Directives enclosing structured-block 741 TYPE_PARSER(construct<OmpBlockDirective>(first( 742 "MASKED" >> pure(llvm::omp::Directive::OMPD_masked), 743 "MASTER" >> pure(llvm::omp::Directive::OMPD_master), 744 "ORDERED" >> pure(llvm::omp::Directive::OMPD_ordered), 745 "PARALLEL MASKED" >> pure(llvm::omp::Directive::OMPD_parallel_masked), 746 "PARALLEL MASTER" >> pure(llvm::omp::Directive::OMPD_parallel_master), 747 "PARALLEL WORKSHARE" >> pure(llvm::omp::Directive::OMPD_parallel_workshare), 748 "PARALLEL" >> pure(llvm::omp::Directive::OMPD_parallel), 749 "SCOPE" >> pure(llvm::omp::Directive::OMPD_scope), 750 "SINGLE" >> pure(llvm::omp::Directive::OMPD_single), 751 "TARGET DATA" >> pure(llvm::omp::Directive::OMPD_target_data), 752 "TARGET PARALLEL" >> pure(llvm::omp::Directive::OMPD_target_parallel), 753 "TARGET TEAMS" >> pure(llvm::omp::Directive::OMPD_target_teams), 754 "TARGET" >> pure(llvm::omp::Directive::OMPD_target), 755 "TASK"_id >> pure(llvm::omp::Directive::OMPD_task), 756 "TASKGROUP" >> pure(llvm::omp::Directive::OMPD_taskgroup), 757 "TEAMS" >> pure(llvm::omp::Directive::OMPD_teams), 758 "WORKSHARE" >> pure(llvm::omp::Directive::OMPD_workshare)))) 759 760 TYPE_PARSER(sourced(construct<OmpBeginBlockDirective>( 761 sourced(Parser<OmpBlockDirective>{}), Parser<OmpClauseList>{}))) 762 763 TYPE_PARSER(construct<OmpReductionInitializerClause>( 764 "INITIALIZER" >> parenthesized("OMP_PRIV =" >> expr))) 765 766 // 2.16 Declare Reduction Construct 767 TYPE_PARSER(sourced(construct<OpenMPDeclareReductionConstruct>( 768 verbatim("DECLARE REDUCTION"_tok), 769 "(" >> Parser<OmpReductionIdentifier>{} / ":", 770 nonemptyList(Parser<DeclarationTypeSpec>{}) / ":", 771 Parser<OmpReductionCombiner>{} / ")", 772 maybe(Parser<OmpReductionInitializerClause>{})))) 773 774 // declare-target with list 775 TYPE_PARSER(sourced(construct<OmpDeclareTargetWithList>( 776 parenthesized(Parser<OmpObjectList>{})))) 777 778 // declare-target with clause 779 TYPE_PARSER( 780 sourced(construct<OmpDeclareTargetWithClause>(Parser<OmpClauseList>{}))) 781 782 // declare-target-specifier 783 TYPE_PARSER( 784 construct<OmpDeclareTargetSpecifier>(Parser<OmpDeclareTargetWithList>{}) || 785 construct<OmpDeclareTargetSpecifier>(Parser<OmpDeclareTargetWithClause>{})) 786 787 // 2.10.6 Declare Target Construct 788 TYPE_PARSER(sourced(construct<OpenMPDeclareTargetConstruct>( 789 verbatim("DECLARE TARGET"_tok), Parser<OmpDeclareTargetSpecifier>{}))) 790 791 // declare-mapper-specifier 792 TYPE_PARSER(construct<OmpDeclareMapperSpecifier>( 793 maybe(name / ":" / !":"_tok), typeSpec / "::", name)) 794 795 // OpenMP 5.2: 5.8.8 Declare Mapper Construct 796 TYPE_PARSER(sourced(construct<OpenMPDeclareMapperConstruct>( 797 verbatim("DECLARE MAPPER"_tok), 798 "(" >> Parser<OmpDeclareMapperSpecifier>{} / ")", Parser<OmpClauseList>{}))) 799 800 TYPE_PARSER(construct<OmpReductionCombiner>(Parser<AssignmentStmt>{}) || 801 construct<OmpReductionCombiner>( 802 construct<OmpReductionCombiner::FunctionCombiner>( 803 construct<Call>(Parser<ProcedureDesignator>{}, 804 parenthesized(optionalList(actualArgSpec)))))) 805 806 // 2.17.7 atomic -> ATOMIC [clause [,]] atomic-clause [[,] clause] | 807 // ATOMIC [clause] 808 // clause -> memory-order-clause | HINT(hint-expression) 809 // memory-order-clause -> SEQ_CST | ACQ_REL | RELEASE | ACQUIRE | RELAXED 810 // atomic-clause -> READ | WRITE | UPDATE | CAPTURE 811 812 // OMP END ATOMIC 813 TYPE_PARSER(construct<OmpEndAtomic>(startOmpLine >> "END ATOMIC"_tok)) 814 815 // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] READ [MEMORY-ORDER-CLAUSE-LIST] 816 TYPE_PARSER("ATOMIC" >> 817 sourced(construct<OmpAtomicRead>( 818 Parser<OmpAtomicClauseList>{} / maybe(","_tok), verbatim("READ"_tok), 819 Parser<OmpAtomicClauseList>{} / endOmpLine, statement(assignmentStmt), 820 maybe(Parser<OmpEndAtomic>{} / endOmpLine)))) 821 822 // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] CAPTURE [MEMORY-ORDER-CLAUSE-LIST] 823 TYPE_PARSER("ATOMIC" >> 824 sourced(construct<OmpAtomicCapture>( 825 Parser<OmpAtomicClauseList>{} / maybe(","_tok), verbatim("CAPTURE"_tok), 826 Parser<OmpAtomicClauseList>{} / endOmpLine, statement(assignmentStmt), 827 statement(assignmentStmt), Parser<OmpEndAtomic>{} / endOmpLine))) 828 829 TYPE_PARSER(construct<OmpAtomicCompareIfStmt>(indirect(Parser<IfStmt>{})) || 830 construct<OmpAtomicCompareIfStmt>(indirect(Parser<IfConstruct>{}))) 831 832 // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] COMPARE [MEMORY-ORDER-CLAUSE-LIST] 833 TYPE_PARSER("ATOMIC" >> 834 sourced(construct<OmpAtomicCompare>( 835 Parser<OmpAtomicClauseList>{} / maybe(","_tok), verbatim("COMPARE"_tok), 836 Parser<OmpAtomicClauseList>{} / endOmpLine, 837 Parser<OmpAtomicCompareIfStmt>{}, 838 maybe(Parser<OmpEndAtomic>{} / endOmpLine)))) 839 840 // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] UPDATE [MEMORY-ORDER-CLAUSE-LIST] 841 TYPE_PARSER("ATOMIC" >> 842 sourced(construct<OmpAtomicUpdate>( 843 Parser<OmpAtomicClauseList>{} / maybe(","_tok), verbatim("UPDATE"_tok), 844 Parser<OmpAtomicClauseList>{} / endOmpLine, statement(assignmentStmt), 845 maybe(Parser<OmpEndAtomic>{} / endOmpLine)))) 846 847 // OMP ATOMIC [atomic-clause-list] 848 TYPE_PARSER(sourced(construct<OmpAtomic>(verbatim("ATOMIC"_tok), 849 Parser<OmpAtomicClauseList>{} / endOmpLine, statement(assignmentStmt), 850 maybe(Parser<OmpEndAtomic>{} / endOmpLine)))) 851 852 // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] WRITE [MEMORY-ORDER-CLAUSE-LIST] 853 TYPE_PARSER("ATOMIC" >> 854 sourced(construct<OmpAtomicWrite>( 855 Parser<OmpAtomicClauseList>{} / maybe(","_tok), verbatim("WRITE"_tok), 856 Parser<OmpAtomicClauseList>{} / endOmpLine, statement(assignmentStmt), 857 maybe(Parser<OmpEndAtomic>{} / endOmpLine)))) 858 859 // Atomic Construct 860 TYPE_PARSER(construct<OpenMPAtomicConstruct>(Parser<OmpAtomicRead>{}) || 861 construct<OpenMPAtomicConstruct>(Parser<OmpAtomicCapture>{}) || 862 construct<OpenMPAtomicConstruct>(Parser<OmpAtomicCompare>{}) || 863 construct<OpenMPAtomicConstruct>(Parser<OmpAtomicWrite>{}) || 864 construct<OpenMPAtomicConstruct>(Parser<OmpAtomicUpdate>{}) || 865 construct<OpenMPAtomicConstruct>(Parser<OmpAtomic>{})) 866 867 // 2.13.2 OMP CRITICAL 868 TYPE_PARSER(startOmpLine >> 869 sourced(construct<OmpEndCriticalDirective>( 870 verbatim("END CRITICAL"_tok), maybe(parenthesized(name)))) / 871 endOmpLine) 872 TYPE_PARSER(sourced(construct<OmpCriticalDirective>(verbatim("CRITICAL"_tok), 873 maybe(parenthesized(name)), Parser<OmpClauseList>{})) / 874 endOmpLine) 875 876 TYPE_PARSER(construct<OpenMPCriticalConstruct>( 877 Parser<OmpCriticalDirective>{}, block, Parser<OmpEndCriticalDirective>{})) 878 879 // 2.11.3 Executable Allocate directive 880 TYPE_PARSER( 881 sourced(construct<OpenMPExecutableAllocate>(verbatim("ALLOCATE"_tok), 882 maybe(parenthesized(Parser<OmpObjectList>{})), Parser<OmpClauseList>{}, 883 maybe(nonemptyList(Parser<OpenMPDeclarativeAllocate>{})) / endOmpLine, 884 statement(allocateStmt)))) 885 886 // 6.7 Allocators construct [OpenMP 5.2] 887 // allocators-construct -> ALLOCATORS [allocate-clause [,]] 888 // allocate-stmt 889 // [omp-end-allocators-construct] 890 TYPE_PARSER(sourced(construct<OpenMPAllocatorsConstruct>( 891 verbatim("ALLOCATORS"_tok), Parser<OmpClauseList>{} / endOmpLine, 892 statement(allocateStmt), maybe(Parser<OmpEndAllocators>{} / endOmpLine)))) 893 894 TYPE_PARSER(construct<OmpEndAllocators>(startOmpLine >> "END ALLOCATORS"_tok)) 895 896 // 2.8.2 Declare Simd construct 897 TYPE_PARSER( 898 sourced(construct<OpenMPDeclareSimdConstruct>(verbatim("DECLARE SIMD"_tok), 899 maybe(parenthesized(name)), Parser<OmpClauseList>{}))) 900 901 // 2.4 Requires construct 902 TYPE_PARSER(sourced(construct<OpenMPRequiresConstruct>( 903 verbatim("REQUIRES"_tok), Parser<OmpClauseList>{}))) 904 905 // 2.15.2 Threadprivate directive 906 TYPE_PARSER(sourced(construct<OpenMPThreadprivate>( 907 verbatim("THREADPRIVATE"_tok), parenthesized(Parser<OmpObjectList>{})))) 908 909 // 2.11.3 Declarative Allocate directive 910 TYPE_PARSER( 911 sourced(construct<OpenMPDeclarativeAllocate>(verbatim("ALLOCATE"_tok), 912 parenthesized(Parser<OmpObjectList>{}), Parser<OmpClauseList>{})) / 913 lookAhead(endOmpLine / !statement(allocateStmt))) 914 915 // Declarative constructs 916 TYPE_PARSER(startOmpLine >> 917 withMessage("expected OpenMP construct"_err_en_US, 918 sourced(construct<OpenMPDeclarativeConstruct>( 919 Parser<OpenMPDeclareReductionConstruct>{}) || 920 construct<OpenMPDeclarativeConstruct>( 921 Parser<OpenMPDeclareMapperConstruct>{}) || 922 construct<OpenMPDeclarativeConstruct>( 923 Parser<OpenMPDeclareSimdConstruct>{}) || 924 construct<OpenMPDeclarativeConstruct>( 925 Parser<OpenMPDeclareTargetConstruct>{}) || 926 construct<OpenMPDeclarativeConstruct>( 927 Parser<OpenMPDeclarativeAllocate>{}) || 928 construct<OpenMPDeclarativeConstruct>( 929 Parser<OpenMPRequiresConstruct>{}) || 930 construct<OpenMPDeclarativeConstruct>( 931 Parser<OpenMPThreadprivate>{})) / 932 endOmpLine)) 933 934 // Block Construct 935 TYPE_PARSER(construct<OpenMPBlockConstruct>( 936 Parser<OmpBeginBlockDirective>{} / endOmpLine, block, 937 Parser<OmpEndBlockDirective>{} / endOmpLine)) 938 939 // OMP SECTIONS Directive 940 TYPE_PARSER(construct<OmpSectionsDirective>(first( 941 "SECTIONS" >> pure(llvm::omp::Directive::OMPD_sections), 942 "PARALLEL SECTIONS" >> pure(llvm::omp::Directive::OMPD_parallel_sections)))) 943 944 // OMP BEGIN and END SECTIONS Directive 945 TYPE_PARSER(sourced(construct<OmpBeginSectionsDirective>( 946 sourced(Parser<OmpSectionsDirective>{}), Parser<OmpClauseList>{}))) 947 TYPE_PARSER( 948 startOmpLine >> sourced(construct<OmpEndSectionsDirective>( 949 sourced("END"_tok >> Parser<OmpSectionsDirective>{}), 950 Parser<OmpClauseList>{}))) 951 952 // OMP SECTION-BLOCK 953 954 TYPE_PARSER(construct<OpenMPSectionConstruct>(block)) 955 956 TYPE_PARSER(maybe(startOmpLine >> "SECTION"_tok / endOmpLine) >> 957 construct<OmpSectionBlocks>(nonemptySeparated( 958 construct<OpenMPConstruct>(sourced(Parser<OpenMPSectionConstruct>{})), 959 startOmpLine >> "SECTION"_tok / endOmpLine))) 960 961 // OMP SECTIONS (OpenMP 5.0 - 2.8.1), PARALLEL SECTIONS (OpenMP 5.0 - 2.13.3) 962 TYPE_PARSER(construct<OpenMPSectionsConstruct>( 963 Parser<OmpBeginSectionsDirective>{} / endOmpLine, 964 Parser<OmpSectionBlocks>{}, Parser<OmpEndSectionsDirective>{} / endOmpLine)) 965 966 TYPE_CONTEXT_PARSER("OpenMP construct"_en_US, 967 startOmpLine >> 968 withMessage("expected OpenMP construct"_err_en_US, 969 first(construct<OpenMPConstruct>(Parser<OpenMPSectionsConstruct>{}), 970 construct<OpenMPConstruct>(Parser<OpenMPLoopConstruct>{}), 971 construct<OpenMPConstruct>(Parser<OpenMPBlockConstruct>{}), 972 // OpenMPBlockConstruct is attempted before 973 // OpenMPStandaloneConstruct to resolve !$OMP ORDERED 974 construct<OpenMPConstruct>(Parser<OpenMPStandaloneConstruct>{}), 975 construct<OpenMPConstruct>(Parser<OpenMPAtomicConstruct>{}), 976 construct<OpenMPConstruct>(Parser<OpenMPExecutableAllocate>{}), 977 construct<OpenMPConstruct>(Parser<OpenMPAllocatorsConstruct>{}), 978 construct<OpenMPConstruct>(Parser<OpenMPDeclarativeAllocate>{}), 979 construct<OpenMPConstruct>(Parser<OpenMPCriticalConstruct>{})))) 980 981 // END OMP Block directives 982 TYPE_PARSER( 983 startOmpLine >> sourced(construct<OmpEndBlockDirective>( 984 sourced("END"_tok >> Parser<OmpBlockDirective>{}), 985 Parser<OmpClauseList>{}))) 986 987 // END OMP Loop directives 988 TYPE_PARSER( 989 startOmpLine >> sourced(construct<OmpEndLoopDirective>( 990 sourced("END"_tok >> Parser<OmpLoopDirective>{}), 991 Parser<OmpClauseList>{}))) 992 993 TYPE_PARSER(construct<OpenMPLoopConstruct>( 994 Parser<OmpBeginLoopDirective>{} / endOmpLine)) 995 } // namespace Fortran::parser 996