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