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 #include "llvm/ADT/ArrayRef.h" 20 #include "llvm/ADT/STLExtras.h" 21 #include "llvm/ADT/StringRef.h" 22 #include "llvm/Frontend/OpenMP/OMP.h" 23 24 // OpenMP Directives and Clauses 25 namespace Fortran::parser { 26 27 constexpr auto startOmpLine = skipStuffBeforeStatement >> "!$OMP "_sptok; 28 constexpr auto endOmpLine = space >> endOfLine; 29 30 /// Parse OpenMP directive name (this includes compound directives). 31 struct OmpDirectiveNameParser { 32 using resultType = llvm::omp::Directive; 33 using Token = TokenStringMatch<false, false>; 34 35 std::optional<resultType> Parse(ParseState &state) const { 36 for (const NameWithId &nid : directives()) { 37 if (attempt(Token(nid.first.data())).Parse(state)) { 38 return nid.second; 39 } 40 } 41 return std::nullopt; 42 } 43 44 private: 45 using NameWithId = std::pair<std::string, llvm::omp::Directive>; 46 47 llvm::iterator_range<const NameWithId *> directives() const; 48 void initTokens(NameWithId *) const; 49 }; 50 51 llvm::iterator_range<const OmpDirectiveNameParser::NameWithId *> 52 OmpDirectiveNameParser::directives() const { 53 static NameWithId table[llvm::omp::Directive_enumSize]; 54 [[maybe_unused]] static bool init = (initTokens(table), true); 55 return llvm::make_range(std::cbegin(table), std::cend(table)); 56 } 57 58 void OmpDirectiveNameParser::initTokens(NameWithId *table) const { 59 for (size_t i{0}, e{llvm::omp::Directive_enumSize}; i != e; ++i) { 60 auto id{static_cast<llvm::omp::Directive>(i)}; 61 llvm::StringRef name{llvm::omp::getOpenMPDirectiveName(id)}; 62 table[i] = std::make_pair(name.str(), id); 63 } 64 // Sort the table with respect to the directive name length in a descending 65 // order. This is to make sure that longer names are tried first, before 66 // any potential prefix (e.g. "target update" before "target"). 67 std::sort(table, table + llvm::omp::Directive_enumSize, 68 [](auto &a, auto &b) { return a.first.size() > b.first.size(); }); 69 } 70 71 template <typename Clause, typename Separator> struct ModifierList { 72 constexpr ModifierList(Separator sep) : sep_(sep) {} 73 constexpr ModifierList(const ModifierList &) = default; 74 constexpr ModifierList(ModifierList &&) = default; 75 76 using resultType = std::list<typename Clause::Modifier>; 77 78 std::optional<resultType> Parse(ParseState &state) const { 79 auto listp{nonemptySeparated(Parser<typename Clause::Modifier>{}, sep_)}; 80 if (auto result{attempt(listp).Parse(state)}) { 81 if (!attempt(":"_tok).Parse(state)) { 82 return std::nullopt; 83 } 84 return std::move(result); 85 } 86 return resultType{}; 87 } 88 89 private: 90 const Separator sep_; 91 }; 92 93 // Use a function to create ModifierList because functions allow "partial" 94 // template argument deduction: "modifierList<Clause>(sep)" would be legal, 95 // while "ModifierList<Clause>(sep)" would complain about a missing template 96 // argument "Separator". 97 template <typename Clause, typename Separator> 98 constexpr ModifierList<Clause, Separator> modifierList(Separator sep) { 99 return ModifierList<Clause, Separator>(sep); 100 } 101 102 // Parse the input as any modifier from ClauseTy, but only succeed if 103 // the result was the SpecificTy. It requires that SpecificTy is one 104 // of the alternatives in ClauseTy::Modifier. 105 // The reason to have this is that ClauseTy::Modifier has "source", 106 // while specific modifiers don't. This class allows to parse a specific 107 // modifier together with obtaining its location. 108 template <typename SpecificTy, typename ClauseTy> 109 struct SpecificModifierParser { 110 using resultType = typename ClauseTy::Modifier; 111 std::optional<resultType> Parse(ParseState &state) const { 112 if (auto result{attempt(Parser<resultType>{}).Parse(state)}) { 113 if (std::holds_alternative<SpecificTy>(result->u)) { 114 return result; 115 } 116 } 117 return std::nullopt; 118 } 119 }; 120 121 // OpenMP Clauses 122 123 // [5.0] 2.1.6 iterator-specifier -> type-declaration-stmt = subscript-triple | 124 // identifier = subscript-triple 125 // [5.0:47:17-18] In an iterator-specifier, if the iterator-type is not 126 // specified then the type of that iterator is default integer. 127 // [5.0:49:14] The iterator-type must be an integer type. 128 static std::list<EntityDecl> makeEntityList(std::list<ObjectName> &&names) { 129 std::list<EntityDecl> entities; 130 131 for (auto iter = names.begin(), end = names.end(); iter != end; ++iter) { 132 EntityDecl entityDecl( 133 /*ObjectName=*/std::move(*iter), std::optional<ArraySpec>{}, 134 std::optional<CoarraySpec>{}, std::optional<CharLength>{}, 135 std::optional<Initialization>{}); 136 entities.push_back(std::move(entityDecl)); 137 } 138 return entities; 139 } 140 141 static TypeDeclarationStmt makeIterSpecDecl( 142 DeclarationTypeSpec &&spec, std::list<ObjectName> &&names) { 143 return TypeDeclarationStmt( 144 std::move(spec), std::list<AttrSpec>{}, makeEntityList(std::move(names))); 145 } 146 147 static TypeDeclarationStmt makeIterSpecDecl(std::list<ObjectName> &&names) { 148 // Assume INTEGER without kind selector. 149 DeclarationTypeSpec typeSpec( 150 IntrinsicTypeSpec{IntegerTypeSpec{std::nullopt}}); 151 152 return TypeDeclarationStmt(std::move(typeSpec), std::list<AttrSpec>{}, 153 makeEntityList(std::move(names))); 154 } 155 156 TYPE_PARSER(sourced(construct<OmpDirectiveSpecification>( 157 OmpDirectiveNameParser{}, maybe(indirect(Parser<OmpClauseList>{}))))) 158 159 // --- Parsers for context traits ------------------------------------- 160 161 static std::string nameToString(Name &&name) { return name.ToString(); } 162 163 TYPE_PARSER(sourced(construct<OmpTraitPropertyName>( // 164 construct<OmpTraitPropertyName>(space >> charLiteralConstantWithoutKind) || 165 construct<OmpTraitPropertyName>( 166 applyFunction(nameToString, Parser<Name>{}))))) 167 168 TYPE_PARSER(sourced(construct<OmpTraitScore>( // 169 "SCORE"_id >> parenthesized(scalarIntExpr)))) 170 171 TYPE_PARSER(sourced(construct<OmpTraitPropertyExtension::Complex>( 172 Parser<OmpTraitPropertyName>{}, 173 parenthesized(nonemptySeparated( 174 indirect(Parser<OmpTraitPropertyExtension>{}), ","))))) 175 176 TYPE_PARSER(sourced(construct<OmpTraitPropertyExtension>( 177 construct<OmpTraitPropertyExtension>( 178 Parser<OmpTraitPropertyExtension::Complex>{}) || 179 construct<OmpTraitPropertyExtension>(Parser<OmpTraitPropertyName>{}) || 180 construct<OmpTraitPropertyExtension>(scalarExpr)))) 181 182 TYPE_PARSER(construct<OmpTraitSelectorName::Value>( 183 "ARCH"_id >> pure(OmpTraitSelectorName::Value::Arch) || 184 "ATOMIC_DEFAULT_MEM_ORDER"_id >> 185 pure(OmpTraitSelectorName::Value::Atomic_Default_Mem_Order) || 186 "CONDITION"_id >> pure(OmpTraitSelectorName::Value::Condition) || 187 "DEVICE_NUM"_id >> pure(OmpTraitSelectorName::Value::Device_Num) || 188 "EXTENSION"_id >> pure(OmpTraitSelectorName::Value::Extension) || 189 "ISA"_id >> pure(OmpTraitSelectorName::Value::Isa) || 190 "KIND"_id >> pure(OmpTraitSelectorName::Value::Kind) || 191 "REQUIRES"_id >> pure(OmpTraitSelectorName::Value::Requires) || 192 "SIMD"_id >> pure(OmpTraitSelectorName::Value::Simd) || 193 "UID"_id >> pure(OmpTraitSelectorName::Value::Uid) || 194 "VENDOR"_id >> pure(OmpTraitSelectorName::Value::Vendor))) 195 196 TYPE_PARSER(sourced(construct<OmpTraitSelectorName>( 197 // Parse predefined names first (because of SIMD). 198 construct<OmpTraitSelectorName>(Parser<OmpTraitSelectorName::Value>{}) || 199 construct<OmpTraitSelectorName>(OmpDirectiveNameParser{}) || 200 // identifier-or-string for extensions 201 construct<OmpTraitSelectorName>( 202 applyFunction(nameToString, Parser<Name>{})) || 203 construct<OmpTraitSelectorName>(space >> charLiteralConstantWithoutKind)))) 204 205 // Parser for OmpTraitSelector::Properties 206 template <typename... PropParser> 207 static constexpr auto propertyListParser(PropParser... pp) { 208 // Parse the property list "(score(expr): item1...)" in three steps: 209 // 1. Parse the "(" 210 // 2. Parse the optional "score(expr):" 211 // 3. Parse the "item1, ...)", together with the ")". 212 // The reason for including the ")" in the 3rd step is to force parsing 213 // the entire list in each of the alternative property parsers. Otherwise, 214 // the name parser could stop after "foo" in "(foo, bar(1))", without 215 // allowing the next parser to give the list a try. 216 auto listOf{[](auto parser) { // 217 return nonemptySeparated(parser, ","); 218 }}; 219 220 using P = OmpTraitProperty; 221 return maybe("(" >> // 222 construct<OmpTraitSelector::Properties>( 223 maybe(Parser<OmpTraitScore>{} / ":"), 224 (attempt(listOf(sourced(construct<P>(pp))) / ")") || ...))); 225 } 226 227 // Parser for OmpTraitSelector 228 struct TraitSelectorParser { 229 using resultType = OmpTraitSelector; 230 231 constexpr TraitSelectorParser(Parser<OmpTraitSelectorName> p) : np(p) {} 232 233 std::optional<resultType> Parse(ParseState &state) const { 234 auto name{attempt(np).Parse(state)}; 235 if (!name.has_value()) { 236 return std::nullopt; 237 } 238 239 // Default fallback parser for lists that cannot be parser using the 240 // primary property parser. 241 auto extParser{Parser<OmpTraitPropertyExtension>{}}; 242 243 if (auto *v{std::get_if<OmpTraitSelectorName::Value>(&name->u)}) { 244 // (*) The comments below show the sections of the OpenMP spec that 245 // describe given trait. The cases marked with a (*) are those where 246 // the spec doesn't assign any list-type to these traits, but for 247 // convenience they can be treated as if they were. 248 switch (*v) { 249 // name-list properties 250 case OmpTraitSelectorName::Value::Arch: // [6.0:319:18] 251 case OmpTraitSelectorName::Value::Extension: // [6.0:319:30] 252 case OmpTraitSelectorName::Value::Isa: // [6.0:319:15] 253 case OmpTraitSelectorName::Value::Kind: // [6.0:319:10] 254 case OmpTraitSelectorName::Value::Uid: // [6.0:319:23](*) 255 case OmpTraitSelectorName::Value::Vendor: { // [6.0:319:27] 256 auto pp{propertyListParser(Parser<OmpTraitPropertyName>{}, extParser)}; 257 return OmpTraitSelector(std::move(*name), std::move(*pp.Parse(state))); 258 } 259 // clause-list 260 case OmpTraitSelectorName::Value::Atomic_Default_Mem_Order: 261 // [6.0:321:26-29](*) 262 case OmpTraitSelectorName::Value::Requires: // [6.0:319:33] 263 case OmpTraitSelectorName::Value::Simd: { // [6.0:318:31] 264 auto pp{propertyListParser(indirect(Parser<OmpClause>{}), extParser)}; 265 return OmpTraitSelector(std::move(*name), std::move(*pp.Parse(state))); 266 } 267 // expr-list 268 case OmpTraitSelectorName::Value::Condition: // [6.0:321:33](*) 269 case OmpTraitSelectorName::Value::Device_Num: { // [6.0:321:23-24](*) 270 auto pp{propertyListParser(scalarExpr, extParser)}; 271 return OmpTraitSelector(std::move(*name), std::move(*pp.Parse(state))); 272 } 273 } // switch 274 } else { 275 // The other alternatives are `llvm::omp::Directive`, and `std::string`. 276 // The former doesn't take any properties[1], the latter is a name of an 277 // extension[2]. 278 // [1] [6.0:319:1-2] 279 // [2] [6.0:319:36-37] 280 auto pp{propertyListParser(extParser)}; 281 return OmpTraitSelector(std::move(*name), std::move(*pp.Parse(state))); 282 } 283 284 llvm_unreachable("Unhandled trait name?"); 285 } 286 287 private: 288 const Parser<OmpTraitSelectorName> np; 289 }; 290 291 TYPE_PARSER(sourced(construct<OmpTraitSelector>( 292 sourced(TraitSelectorParser(Parser<OmpTraitSelectorName>{}))))) 293 294 TYPE_PARSER(construct<OmpTraitSetSelectorName::Value>( 295 "CONSTRUCT"_id >> pure(OmpTraitSetSelectorName::Value::Construct) || 296 "DEVICE"_id >> pure(OmpTraitSetSelectorName::Value::Device) || 297 "IMPLEMENTATION"_id >> 298 pure(OmpTraitSetSelectorName::Value::Implementation) || 299 "TARGET_DEVICE"_id >> pure(OmpTraitSetSelectorName::Value::Target_Device) || 300 "USER"_id >> pure(OmpTraitSetSelectorName::Value::User))) 301 302 TYPE_PARSER(sourced(construct<OmpTraitSetSelectorName>( 303 Parser<OmpTraitSetSelectorName::Value>{}))) 304 305 TYPE_PARSER(sourced(construct<OmpTraitSetSelector>( // 306 Parser<OmpTraitSetSelectorName>{}, 307 "=" >> braced(nonemptySeparated(Parser<OmpTraitSelector>{}, ","))))) 308 309 TYPE_PARSER(sourced(construct<OmpContextSelectorSpecification>( 310 nonemptySeparated(Parser<OmpTraitSetSelector>{}, ",")))) 311 312 // Parser<OmpContextSelector> == Parser<traits::OmpContextSelectorSpecification> 313 314 // --- Parsers for clause modifiers ----------------------------------- 315 316 TYPE_PARSER(construct<OmpAlignment>(scalarIntExpr)) 317 318 TYPE_PARSER(construct<OmpAlignModifier>( // 319 "ALIGN" >> parenthesized(scalarIntExpr))) 320 321 TYPE_PARSER(construct<OmpAllocatorComplexModifier>( 322 "ALLOCATOR" >> parenthesized(scalarIntExpr))) 323 324 TYPE_PARSER(construct<OmpAllocatorSimpleModifier>(scalarIntExpr)) 325 326 TYPE_PARSER(construct<OmpChunkModifier>( // 327 "SIMD" >> pure(OmpChunkModifier::Value::Simd))) 328 329 TYPE_PARSER(construct<OmpDependenceType>( 330 "SINK" >> pure(OmpDependenceType::Value::Sink) || 331 "SOURCE" >> pure(OmpDependenceType::Value::Source))) 332 333 TYPE_PARSER(construct<OmpDeviceModifier>( 334 "ANCESTOR" >> pure(OmpDeviceModifier::Value::Ancestor) || 335 "DEVICE_NUM" >> pure(OmpDeviceModifier::Value::Device_Num))) 336 337 TYPE_PARSER(construct<OmpExpectation>( // 338 "PRESENT" >> pure(OmpExpectation::Value::Present))) 339 340 TYPE_PARSER(construct<OmpIteratorSpecifier>( 341 // Using Parser<TypeDeclarationStmt> or Parser<EntityDecl> has the problem 342 // that they will attempt to treat what follows the '=' as initialization. 343 // There are several issues with that, 344 // 1. integer :: i = 0:10 will be parsed as "integer :: i = 0", followed 345 // by triplet ":10". 346 // 2. integer :: j = i:10 will be flagged as an error because the 347 // initializer 'i' must be constant (in declarations). In an iterator 348 // specifier the 'j' is not an initializer and can be a variable. 349 (applyFunction<TypeDeclarationStmt>(makeIterSpecDecl, 350 Parser<DeclarationTypeSpec>{} / maybe("::"_tok), 351 nonemptyList(Parser<ObjectName>{}) / "="_tok) || 352 applyFunction<TypeDeclarationStmt>( 353 makeIterSpecDecl, nonemptyList(Parser<ObjectName>{}) / "="_tok)), 354 subscriptTriplet)) 355 356 // [5.0] 2.1.6 iterator -> iterator-specifier-list 357 TYPE_PARSER(construct<OmpIterator>( // 358 "ITERATOR" >> 359 parenthesized(nonemptyList(sourced(Parser<OmpIteratorSpecifier>{}))))) 360 361 TYPE_PARSER(construct<OmpLastprivateModifier>( 362 "CONDITIONAL" >> pure(OmpLastprivateModifier::Value::Conditional))) 363 364 // 2.15.3.7 LINEAR (linear-list: linear-step) 365 // linear-list -> list | modifier(list) 366 // linear-modifier -> REF | VAL | UVAL 367 TYPE_PARSER(construct<OmpLinearModifier>( // 368 "REF" >> pure(OmpLinearModifier::Value::Ref) || 369 "VAL" >> pure(OmpLinearModifier::Value::Val) || 370 "UVAL" >> pure(OmpLinearModifier::Value::Uval))) 371 372 TYPE_PARSER(construct<OmpMapper>( // 373 "MAPPER"_tok >> parenthesized(Parser<ObjectName>{}))) 374 375 // map-type -> ALLOC | DELETE | FROM | RELEASE | TO | TOFROM 376 TYPE_PARSER(construct<OmpMapType>( // 377 "ALLOC" >> pure(OmpMapType::Value::Alloc) || 378 "DELETE" >> pure(OmpMapType::Value::Delete) || 379 "FROM" >> pure(OmpMapType::Value::From) || 380 "RELEASE" >> pure(OmpMapType::Value::Release) || 381 "TO"_id >> pure(OmpMapType::Value::To) || 382 "TOFROM" >> pure(OmpMapType::Value::Tofrom))) 383 384 // map-type-modifier -> ALWAYS | CLOSE | OMPX_HOLD | PRESENT 385 TYPE_PARSER(construct<OmpMapTypeModifier>( 386 "ALWAYS" >> pure(OmpMapTypeModifier::Value::Always) || 387 "CLOSE" >> pure(OmpMapTypeModifier::Value::Close) || 388 "OMPX_HOLD" >> pure(OmpMapTypeModifier::Value::Ompx_Hold) || 389 "PRESENT" >> pure(OmpMapTypeModifier::Value::Present))) 390 391 // 2.15.3.6 REDUCTION (reduction-identifier: variable-name-list) 392 TYPE_PARSER(construct<OmpReductionIdentifier>(Parser<DefinedOperator>{}) || 393 construct<OmpReductionIdentifier>(Parser<ProcedureDesignator>{})) 394 395 TYPE_PARSER(construct<OmpOrderModifier>( 396 "REPRODUCIBLE" >> pure(OmpOrderModifier::Value::Reproducible) || 397 "UNCONSTRAINED" >> pure(OmpOrderModifier::Value::Unconstrained))) 398 399 TYPE_PARSER(construct<OmpOrderingModifier>( 400 "MONOTONIC" >> pure(OmpOrderingModifier::Value::Monotonic) || 401 "NONMONOTONIC" >> pure(OmpOrderingModifier::Value::Nonmonotonic) || 402 "SIMD" >> pure(OmpOrderingModifier::Value::Simd))) 403 404 TYPE_PARSER(construct<OmpPrescriptiveness>( 405 "STRICT" >> pure(OmpPrescriptiveness::Value::Strict))) 406 407 TYPE_PARSER(construct<OmpReductionModifier>( 408 "INSCAN" >> pure(OmpReductionModifier::Value::Inscan) || 409 "TASK" >> pure(OmpReductionModifier::Value::Task) || 410 "DEFAULT" >> pure(OmpReductionModifier::Value::Default))) 411 412 TYPE_PARSER(construct<OmpStepComplexModifier>( // 413 "STEP" >> parenthesized(scalarIntExpr))) 414 415 TYPE_PARSER(construct<OmpStepSimpleModifier>(scalarIntExpr)) 416 417 TYPE_PARSER(construct<OmpTaskDependenceType>( 418 "DEPOBJ" >> pure(OmpTaskDependenceType::Value::Depobj) || 419 "IN"_id >> pure(OmpTaskDependenceType::Value::In) || 420 "INOUT"_id >> pure(OmpTaskDependenceType::Value::Inout) || 421 "INOUTSET"_id >> pure(OmpTaskDependenceType::Value::Inoutset) || 422 "MUTEXINOUTSET" >> pure(OmpTaskDependenceType::Value::Mutexinoutset) || 423 "OUT" >> pure(OmpTaskDependenceType::Value::Out))) 424 425 TYPE_PARSER(construct<OmpVariableCategory>( 426 "AGGREGATE" >> pure(OmpVariableCategory::Value::Aggregate) || 427 "ALL"_id >> pure(OmpVariableCategory::Value::All) || 428 "ALLOCATABLE" >> pure(OmpVariableCategory::Value::Allocatable) || 429 "POINTER" >> pure(OmpVariableCategory::Value::Pointer) || 430 "SCALAR" >> pure(OmpVariableCategory::Value::Scalar))) 431 432 // This could be auto-generated. 433 TYPE_PARSER( 434 sourced(construct<OmpAffinityClause::Modifier>(Parser<OmpIterator>{}))) 435 436 TYPE_PARSER( 437 sourced(construct<OmpAlignedClause::Modifier>(Parser<OmpAlignment>{}))) 438 439 TYPE_PARSER(sourced(construct<OmpAllocateClause::Modifier>(sourced( 440 construct<OmpAllocateClause::Modifier>(Parser<OmpAlignModifier>{}) || 441 construct<OmpAllocateClause::Modifier>( 442 Parser<OmpAllocatorComplexModifier>{}) || 443 construct<OmpAllocateClause::Modifier>( 444 Parser<OmpAllocatorSimpleModifier>{}))))) 445 446 TYPE_PARSER(sourced( 447 construct<OmpDefaultmapClause::Modifier>(Parser<OmpVariableCategory>{}))) 448 449 TYPE_PARSER(sourced(construct<OmpDependClause::TaskDep::Modifier>(sourced( 450 construct<OmpDependClause::TaskDep::Modifier>(Parser<OmpIterator>{}) || 451 construct<OmpDependClause::TaskDep::Modifier>( 452 Parser<OmpTaskDependenceType>{}))))) 453 454 TYPE_PARSER( 455 sourced(construct<OmpDeviceClause::Modifier>(Parser<OmpDeviceModifier>{}))) 456 457 TYPE_PARSER(sourced(construct<OmpFromClause::Modifier>( 458 sourced(construct<OmpFromClause::Modifier>(Parser<OmpExpectation>{}) || 459 construct<OmpFromClause::Modifier>(Parser<OmpMapper>{}) || 460 construct<OmpFromClause::Modifier>(Parser<OmpIterator>{}))))) 461 462 TYPE_PARSER(sourced( 463 construct<OmpGrainsizeClause::Modifier>(Parser<OmpPrescriptiveness>{}))) 464 465 TYPE_PARSER(sourced(construct<OmpIfClause::Modifier>(OmpDirectiveNameParser{}))) 466 467 TYPE_PARSER(sourced(construct<OmpInReductionClause::Modifier>( 468 Parser<OmpReductionIdentifier>{}))) 469 470 TYPE_PARSER(sourced(construct<OmpLastprivateClause::Modifier>( 471 Parser<OmpLastprivateModifier>{}))) 472 473 TYPE_PARSER(sourced( 474 construct<OmpLinearClause::Modifier>(Parser<OmpLinearModifier>{}) || 475 construct<OmpLinearClause::Modifier>(Parser<OmpStepComplexModifier>{}) || 476 construct<OmpLinearClause::Modifier>(Parser<OmpStepSimpleModifier>{}))) 477 478 TYPE_PARSER(sourced(construct<OmpMapClause::Modifier>( 479 sourced(construct<OmpMapClause::Modifier>(Parser<OmpMapTypeModifier>{}) || 480 construct<OmpMapClause::Modifier>(Parser<OmpMapper>{}) || 481 construct<OmpMapClause::Modifier>(Parser<OmpIterator>{}) || 482 construct<OmpMapClause::Modifier>(Parser<OmpMapType>{}))))) 483 484 TYPE_PARSER( 485 sourced(construct<OmpOrderClause::Modifier>(Parser<OmpOrderModifier>{}))) 486 487 TYPE_PARSER(sourced( 488 construct<OmpNumTasksClause::Modifier>(Parser<OmpPrescriptiveness>{}))) 489 490 TYPE_PARSER(sourced(construct<OmpReductionClause::Modifier>(sourced( 491 construct<OmpReductionClause::Modifier>(Parser<OmpReductionModifier>{}) || 492 construct<OmpReductionClause::Modifier>( 493 Parser<OmpReductionIdentifier>{}))))) 494 495 TYPE_PARSER(sourced(construct<OmpScheduleClause::Modifier>(sourced( 496 construct<OmpScheduleClause::Modifier>(Parser<OmpChunkModifier>{}) || 497 construct<OmpScheduleClause::Modifier>(Parser<OmpOrderingModifier>{}))))) 498 499 TYPE_PARSER(sourced(construct<OmpTaskReductionClause::Modifier>( 500 Parser<OmpReductionIdentifier>{}))) 501 502 TYPE_PARSER(sourced(construct<OmpToClause::Modifier>( 503 sourced(construct<OmpToClause::Modifier>(Parser<OmpExpectation>{}) || 504 construct<OmpToClause::Modifier>(Parser<OmpMapper>{}) || 505 construct<OmpToClause::Modifier>(Parser<OmpIterator>{}))))) 506 507 TYPE_PARSER(sourced(construct<OmpWhenClause::Modifier>( // 508 Parser<OmpContextSelector>{}))) 509 510 // --- Parsers for clauses -------------------------------------------- 511 512 /// `MOBClause` is a clause that has a 513 /// std::tuple<Modifiers, OmpObjectList, bool>. 514 /// Helper function to create a typical modifiers-objects clause, where the 515 /// commas separating individual modifiers are optional, and the clause 516 /// contains a bool member to indicate whether it was fully comma-separated 517 /// or not. 518 template <bool CommaSeparated, typename MOBClause> 519 static inline MOBClause makeMobClause( 520 std::list<typename MOBClause::Modifier> &&mods, OmpObjectList &&objs) { 521 if (!mods.empty()) { 522 return MOBClause{std::move(mods), std::move(objs), CommaSeparated}; 523 } else { 524 using ListTy = std::list<typename MOBClause::Modifier>; 525 return MOBClause{std::optional<ListTy>{}, std::move(objs), CommaSeparated}; 526 } 527 } 528 529 // [5.0] 2.10.1 affinity([aff-modifier:] locator-list) 530 // aff-modifier: interator-modifier 531 TYPE_PARSER(construct<OmpAffinityClause>( 532 maybe(nonemptyList(Parser<OmpAffinityClause::Modifier>{}) / ":"), 533 Parser<OmpObjectList>{})) 534 535 // 2.15.3.1 DEFAULT (PRIVATE | FIRSTPRIVATE | SHARED | NONE) 536 TYPE_PARSER(construct<OmpDefaultClause::DataSharingAttribute>( 537 "PRIVATE" >> pure(OmpDefaultClause::DataSharingAttribute::Private) || 538 "FIRSTPRIVATE" >> 539 pure(OmpDefaultClause::DataSharingAttribute::Firstprivate) || 540 "SHARED" >> pure(OmpDefaultClause::DataSharingAttribute::Shared) || 541 "NONE" >> pure(OmpDefaultClause::DataSharingAttribute::None))) 542 543 TYPE_PARSER(construct<OmpDefaultClause>( 544 construct<OmpDefaultClause>( 545 Parser<OmpDefaultClause::DataSharingAttribute>{}) || 546 construct<OmpDefaultClause>(Parser<OmpDirectiveSpecification>{}))) 547 548 // 2.5 PROC_BIND (MASTER | CLOSE | PRIMARY | SPREAD) 549 TYPE_PARSER(construct<OmpProcBindClause>( 550 "CLOSE" >> pure(OmpProcBindClause::AffinityPolicy::Close) || 551 "MASTER" >> pure(OmpProcBindClause::AffinityPolicy::Master) || 552 "PRIMARY" >> pure(OmpProcBindClause::AffinityPolicy::Primary) || 553 "SPREAD" >> pure(OmpProcBindClause::AffinityPolicy::Spread))) 554 555 TYPE_PARSER(construct<OmpMapClause>( 556 applyFunction<OmpMapClause>(makeMobClause<true>, 557 modifierList<OmpMapClause>(","_tok), Parser<OmpObjectList>{}) || 558 applyFunction<OmpMapClause>(makeMobClause<false>, 559 modifierList<OmpMapClause>(maybe(","_tok)), Parser<OmpObjectList>{}))) 560 561 // [OpenMP 5.0] 562 // 2.19.7.2 defaultmap(implicit-behavior[:variable-category]) 563 // implicit-behavior -> ALLOC | TO | FROM | TOFROM | FIRSRTPRIVATE | NONE | 564 // DEFAULT 565 // variable-category -> ALL | SCALAR | AGGREGATE | ALLOCATABLE | POINTER 566 TYPE_PARSER(construct<OmpDefaultmapClause>( 567 construct<OmpDefaultmapClause::ImplicitBehavior>( 568 "ALLOC" >> pure(OmpDefaultmapClause::ImplicitBehavior::Alloc) || 569 "TO"_id >> pure(OmpDefaultmapClause::ImplicitBehavior::To) || 570 "FROM" >> pure(OmpDefaultmapClause::ImplicitBehavior::From) || 571 "TOFROM" >> pure(OmpDefaultmapClause::ImplicitBehavior::Tofrom) || 572 "FIRSTPRIVATE" >> 573 pure(OmpDefaultmapClause::ImplicitBehavior::Firstprivate) || 574 "NONE" >> pure(OmpDefaultmapClause::ImplicitBehavior::None) || 575 "DEFAULT" >> pure(OmpDefaultmapClause::ImplicitBehavior::Default)), 576 maybe(":" >> nonemptyList(Parser<OmpDefaultmapClause::Modifier>{})))) 577 578 TYPE_PARSER(construct<OmpScheduleClause::Kind>( 579 "STATIC" >> pure(OmpScheduleClause::Kind::Static) || 580 "DYNAMIC" >> pure(OmpScheduleClause::Kind::Dynamic) || 581 "GUIDED" >> pure(OmpScheduleClause::Kind::Guided) || 582 "AUTO" >> pure(OmpScheduleClause::Kind::Auto) || 583 "RUNTIME" >> pure(OmpScheduleClause::Kind::Runtime))) 584 585 TYPE_PARSER(construct<OmpScheduleClause>( 586 maybe(nonemptyList(Parser<OmpScheduleClause::Modifier>{}) / ":"), 587 Parser<OmpScheduleClause::Kind>{}, maybe("," >> scalarIntExpr))) 588 589 // device([ device-modifier :] scalar-integer-expression) 590 TYPE_PARSER(construct<OmpDeviceClause>( 591 maybe(nonemptyList(Parser<OmpDeviceClause::Modifier>{}) / ":"), 592 scalarIntExpr)) 593 594 // device_type(any | host | nohost) 595 TYPE_PARSER(construct<OmpDeviceTypeClause>( 596 "ANY" >> pure(OmpDeviceTypeClause::DeviceTypeDescription::Any) || 597 "HOST" >> pure(OmpDeviceTypeClause::DeviceTypeDescription::Host) || 598 "NOHOST" >> pure(OmpDeviceTypeClause::DeviceTypeDescription::Nohost))) 599 600 // 2.12 IF (directive-name-modifier: scalar-logical-expr) 601 TYPE_PARSER(construct<OmpIfClause>( 602 maybe(nonemptyList(Parser<OmpIfClause::Modifier>{}) / ":"), 603 scalarLogicalExpr)) 604 605 TYPE_PARSER(construct<OmpReductionClause>( 606 maybe(nonemptyList(Parser<OmpReductionClause::Modifier>{}) / ":"), 607 Parser<OmpObjectList>{})) 608 609 // OMP 5.0 2.19.5.6 IN_REDUCTION (reduction-identifier: variable-name-list) 610 TYPE_PARSER(construct<OmpInReductionClause>( 611 maybe(nonemptyList(Parser<OmpInReductionClause::Modifier>{}) / ":"), 612 Parser<OmpObjectList>{})) 613 614 TYPE_PARSER(construct<OmpTaskReductionClause>( 615 maybe(nonemptyList(Parser<OmpTaskReductionClause::Modifier>{}) / ":"), 616 Parser<OmpObjectList>{})) 617 618 // OMP 5.0 2.11.4 allocate-clause -> ALLOCATE ([allocator:] variable-name-list) 619 // OMP 5.2 2.13.4 allocate-clause -> ALLOCATE ([allocate-modifier 620 // [, allocate-modifier] :] 621 // variable-name-list) 622 // allocate-modifier -> allocator | align 623 TYPE_PARSER(construct<OmpAllocateClause>( 624 maybe(nonemptyList(Parser<OmpAllocateClause::Modifier>{}) / ":"), 625 Parser<OmpObjectList>{})) 626 627 // iteration-offset -> +/- non-negative-constant-expr 628 TYPE_PARSER(construct<OmpIterationOffset>( 629 Parser<DefinedOperator>{}, scalarIntConstantExpr)) 630 631 // iteration -> iteration-variable [+/- nonnegative-scalar-integer-constant] 632 TYPE_PARSER(construct<OmpIteration>(name, maybe(Parser<OmpIterationOffset>{}))) 633 634 TYPE_PARSER(construct<OmpIterationVector>(nonemptyList(Parser<OmpIteration>{}))) 635 636 TYPE_PARSER(construct<OmpDoacross>( 637 construct<OmpDoacross>(construct<OmpDoacross::Sink>( 638 "SINK"_tok >> ":"_tok >> Parser<OmpIterationVector>{})) || 639 construct<OmpDoacross>(construct<OmpDoacross::Source>("SOURCE"_tok)))) 640 641 TYPE_CONTEXT_PARSER("Omp Depend clause"_en_US, 642 construct<OmpDependClause>( 643 // Try to parse OmpDoacross first, because TaskDep will succeed on 644 // "sink: xxx", interpreting it to not have any modifiers, and "sink" 645 // being an OmpObject. Parsing of the TaskDep variant will stop right 646 // after the "sink", leaving the ": xxx" unvisited. 647 construct<OmpDependClause>(Parser<OmpDoacross>{}) || 648 // Parse TaskDep after Doacross. 649 construct<OmpDependClause>(construct<OmpDependClause::TaskDep>( 650 maybe(nonemptyList(Parser<OmpDependClause::TaskDep::Modifier>{}) / 651 ": "), 652 Parser<OmpObjectList>{})))) 653 654 TYPE_CONTEXT_PARSER("Omp Doacross clause"_en_US, 655 construct<OmpDoacrossClause>(Parser<OmpDoacross>{})) 656 657 TYPE_PARSER(construct<OmpFromClause>( 658 applyFunction<OmpFromClause>(makeMobClause<true>, 659 modifierList<OmpFromClause>(","_tok), Parser<OmpObjectList>{}) || 660 applyFunction<OmpFromClause>(makeMobClause<false>, 661 modifierList<OmpFromClause>(maybe(","_tok)), Parser<OmpObjectList>{}))) 662 663 TYPE_PARSER(construct<OmpToClause>( 664 applyFunction<OmpToClause>(makeMobClause<true>, 665 modifierList<OmpToClause>(","_tok), Parser<OmpObjectList>{}) || 666 applyFunction<OmpToClause>(makeMobClause<false>, 667 modifierList<OmpToClause>(maybe(","_tok)), Parser<OmpObjectList>{}))) 668 669 OmpLinearClause makeLinearFromOldSyntax(OmpLinearClause::Modifier &&lm, 670 OmpObjectList &&objs, std::optional<OmpLinearClause::Modifier> &&ssm) { 671 std::list<OmpLinearClause::Modifier> mods; 672 mods.emplace_back(std::move(lm)); 673 if (ssm) { 674 mods.emplace_back(std::move(*ssm)); 675 } 676 return OmpLinearClause{std::move(objs), 677 mods.empty() ? decltype(mods){} : std::move(mods), 678 /*PostModified=*/false}; 679 } 680 681 TYPE_PARSER( 682 // Parse the "modifier(x)" first, because syntacticaly it will match 683 // an array element (i.e. a list item). 684 // LINEAR(linear-modifier(list) [: step-simple-modifier]) 685 construct<OmpLinearClause>( // 686 applyFunction<OmpLinearClause>(makeLinearFromOldSyntax, 687 SpecificModifierParser<OmpLinearModifier, OmpLinearClause>{}, 688 parenthesized(Parser<OmpObjectList>{}), 689 maybe(":"_tok >> SpecificModifierParser<OmpStepSimpleModifier, 690 OmpLinearClause>{}))) || 691 // LINEAR(list [: modifiers]) 692 construct<OmpLinearClause>( // 693 Parser<OmpObjectList>{}, 694 maybe(":"_tok >> nonemptyList(Parser<OmpLinearClause::Modifier>{})), 695 /*PostModified=*/pure(true))) 696 697 // OpenMPv5.2 12.5.2 detach-clause -> DETACH (event-handle) 698 TYPE_PARSER(construct<OmpDetachClause>(Parser<OmpObject>{})) 699 700 // 2.8.1 ALIGNED (list: alignment) 701 TYPE_PARSER(construct<OmpAlignedClause>(Parser<OmpObjectList>{}, 702 maybe(":" >> nonemptyList(Parser<OmpAlignedClause::Modifier>{})))) 703 704 TYPE_PARSER(construct<OmpUpdateClause>( 705 construct<OmpUpdateClause>(Parser<OmpDependenceType>{}) || 706 construct<OmpUpdateClause>(Parser<OmpTaskDependenceType>{}))) 707 708 TYPE_PARSER(construct<OmpOrderClause>( 709 maybe(nonemptyList(Parser<OmpOrderClause::Modifier>{}) / ":"), 710 "CONCURRENT" >> pure(OmpOrderClause::Ordering::Concurrent))) 711 712 TYPE_PARSER(construct<OmpMatchClause>( 713 Parser<traits::OmpContextSelectorSpecification>{})) 714 715 TYPE_PARSER(construct<OmpOtherwiseClause>( 716 maybe(sourced(Parser<OmpDirectiveSpecification>{})))) 717 718 TYPE_PARSER(construct<OmpWhenClause>( 719 maybe(nonemptyList(Parser<OmpWhenClause::Modifier>{}) / ":"), 720 maybe(sourced(Parser<OmpDirectiveSpecification>{})))) 721 722 // OMP 5.2 12.6.1 grainsize([ prescriptiveness :] scalar-integer-expression) 723 TYPE_PARSER(construct<OmpGrainsizeClause>( 724 maybe(nonemptyList(Parser<OmpGrainsizeClause::Modifier>{}) / ":"), 725 scalarIntExpr)) 726 727 // OMP 5.2 12.6.2 num_tasks([ prescriptiveness :] scalar-integer-expression) 728 TYPE_PARSER(construct<OmpNumTasksClause>( 729 maybe(nonemptyList(Parser<OmpNumTasksClause::Modifier>{}) / ":"), 730 scalarIntExpr)) 731 732 TYPE_PARSER( 733 construct<OmpObject>(designator) || construct<OmpObject>("/" >> name / "/")) 734 735 // OMP 5.0 2.19.4.5 LASTPRIVATE ([lastprivate-modifier :] list) 736 TYPE_PARSER(construct<OmpLastprivateClause>( 737 maybe(nonemptyList(Parser<OmpLastprivateClause::Modifier>{}) / ":"), 738 Parser<OmpObjectList>{})) 739 740 // OMP 5.2 11.7.1 BIND ( PARALLEL | TEAMS | THREAD ) 741 TYPE_PARSER(construct<OmpBindClause>( 742 "PARALLEL" >> pure(OmpBindClause::Binding::Parallel) || 743 "TEAMS" >> pure(OmpBindClause::Binding::Teams) || 744 "THREAD" >> pure(OmpBindClause::Binding::Thread))) 745 746 TYPE_PARSER(construct<OmpAlignClause>(scalarIntExpr)) 747 748 TYPE_PARSER(construct<OmpAtClause>( 749 "EXECUTION" >> pure(OmpAtClause::ActionTime::Execution) || 750 "COMPILATION" >> pure(OmpAtClause::ActionTime::Compilation))) 751 752 TYPE_PARSER(construct<OmpSeverityClause>( 753 "FATAL" >> pure(OmpSeverityClause::Severity::Fatal) || 754 "WARNING" >> pure(OmpSeverityClause::Severity::Warning))) 755 756 TYPE_PARSER(construct<OmpMessageClause>(expr)) 757 758 TYPE_PARSER( 759 "ACQUIRE" >> construct<OmpClause>(construct<OmpClause::Acquire>()) || 760 "ACQ_REL" >> construct<OmpClause>(construct<OmpClause::AcqRel>()) || 761 "AFFINITY" >> construct<OmpClause>(construct<OmpClause::Affinity>( 762 parenthesized(Parser<OmpAffinityClause>{}))) || 763 "ALIGN" >> construct<OmpClause>(construct<OmpClause::Align>( 764 parenthesized(Parser<OmpAlignClause>{}))) || 765 "ALIGNED" >> construct<OmpClause>(construct<OmpClause::Aligned>( 766 parenthesized(Parser<OmpAlignedClause>{}))) || 767 "ALLOCATE" >> construct<OmpClause>(construct<OmpClause::Allocate>( 768 parenthesized(Parser<OmpAllocateClause>{}))) || 769 "ALLOCATOR" >> construct<OmpClause>(construct<OmpClause::Allocator>( 770 parenthesized(scalarIntExpr))) || 771 "AT" >> construct<OmpClause>(construct<OmpClause::At>( 772 parenthesized(Parser<OmpAtClause>{}))) || 773 "ATOMIC_DEFAULT_MEM_ORDER" >> 774 construct<OmpClause>(construct<OmpClause::AtomicDefaultMemOrder>( 775 parenthesized(Parser<OmpAtomicDefaultMemOrderClause>{}))) || 776 "BIND" >> construct<OmpClause>(construct<OmpClause::Bind>( 777 parenthesized(Parser<OmpBindClause>{}))) || 778 "COLLAPSE" >> construct<OmpClause>(construct<OmpClause::Collapse>( 779 parenthesized(scalarIntConstantExpr))) || 780 "COPYIN" >> construct<OmpClause>(construct<OmpClause::Copyin>( 781 parenthesized(Parser<OmpObjectList>{}))) || 782 "COPYPRIVATE" >> construct<OmpClause>(construct<OmpClause::Copyprivate>( 783 (parenthesized(Parser<OmpObjectList>{})))) || 784 "DEFAULT"_id >> construct<OmpClause>(construct<OmpClause::Default>( 785 parenthesized(Parser<OmpDefaultClause>{}))) || 786 "DEFAULTMAP" >> construct<OmpClause>(construct<OmpClause::Defaultmap>( 787 parenthesized(Parser<OmpDefaultmapClause>{}))) || 788 "DEPEND" >> construct<OmpClause>(construct<OmpClause::Depend>( 789 parenthesized(Parser<OmpDependClause>{}))) || 790 "DESTROY" >> 791 construct<OmpClause>(construct<OmpClause::Destroy>(maybe(parenthesized( 792 construct<OmpDestroyClause>(Parser<OmpObject>{}))))) || 793 "DEVICE" >> construct<OmpClause>(construct<OmpClause::Device>( 794 parenthesized(Parser<OmpDeviceClause>{}))) || 795 "DEVICE_TYPE" >> construct<OmpClause>(construct<OmpClause::DeviceType>( 796 parenthesized(Parser<OmpDeviceTypeClause>{}))) || 797 "DIST_SCHEDULE" >> 798 construct<OmpClause>(construct<OmpClause::DistSchedule>( 799 parenthesized("STATIC" >> maybe("," >> scalarIntExpr)))) || 800 "DOACROSS" >> 801 construct<OmpClause>(parenthesized(Parser<OmpDoacrossClause>{})) || 802 "DYNAMIC_ALLOCATORS" >> 803 construct<OmpClause>(construct<OmpClause::DynamicAllocators>()) || 804 "ENTER" >> construct<OmpClause>(construct<OmpClause::Enter>( 805 parenthesized(Parser<OmpObjectList>{}))) || 806 "EXCLUSIVE" >> construct<OmpClause>(construct<OmpClause::Exclusive>( 807 parenthesized(Parser<OmpObjectList>{}))) || 808 "FILTER" >> construct<OmpClause>(construct<OmpClause::Filter>( 809 parenthesized(scalarIntExpr))) || 810 "FINAL" >> construct<OmpClause>(construct<OmpClause::Final>( 811 parenthesized(scalarLogicalExpr))) || 812 "FIRSTPRIVATE" >> construct<OmpClause>(construct<OmpClause::Firstprivate>( 813 parenthesized(Parser<OmpObjectList>{}))) || 814 "FROM" >> construct<OmpClause>(construct<OmpClause::From>( 815 parenthesized(Parser<OmpFromClause>{}))) || 816 "FULL" >> construct<OmpClause>(construct<OmpClause::Full>()) || 817 "GRAINSIZE" >> construct<OmpClause>(construct<OmpClause::Grainsize>( 818 parenthesized(Parser<OmpGrainsizeClause>{}))) || 819 "HAS_DEVICE_ADDR" >> 820 construct<OmpClause>(construct<OmpClause::HasDeviceAddr>( 821 parenthesized(Parser<OmpObjectList>{}))) || 822 "HINT" >> construct<OmpClause>( 823 construct<OmpClause::Hint>(parenthesized(constantExpr))) || 824 "IF" >> construct<OmpClause>(construct<OmpClause::If>( 825 parenthesized(Parser<OmpIfClause>{}))) || 826 "INBRANCH" >> construct<OmpClause>(construct<OmpClause::Inbranch>()) || 827 "INCLUSIVE" >> construct<OmpClause>(construct<OmpClause::Inclusive>( 828 parenthesized(Parser<OmpObjectList>{}))) || 829 "IS_DEVICE_PTR" >> construct<OmpClause>(construct<OmpClause::IsDevicePtr>( 830 parenthesized(Parser<OmpObjectList>{}))) || 831 "LASTPRIVATE" >> construct<OmpClause>(construct<OmpClause::Lastprivate>( 832 parenthesized(Parser<OmpLastprivateClause>{}))) || 833 "LINEAR" >> construct<OmpClause>(construct<OmpClause::Linear>( 834 parenthesized(Parser<OmpLinearClause>{}))) || 835 "LINK" >> construct<OmpClause>(construct<OmpClause::Link>( 836 parenthesized(Parser<OmpObjectList>{}))) || 837 "MAP" >> construct<OmpClause>(construct<OmpClause::Map>( 838 parenthesized(Parser<OmpMapClause>{}))) || 839 "MATCH" >> construct<OmpClause>(construct<OmpClause::Match>( 840 parenthesized(Parser<OmpMatchClause>{}))) || 841 "MERGEABLE" >> construct<OmpClause>(construct<OmpClause::Mergeable>()) || 842 "MESSAGE" >> construct<OmpClause>(construct<OmpClause::Message>( 843 parenthesized(Parser<OmpMessageClause>{}))) || 844 "NOCONTEXT" >> construct<OmpClause>(construct<OmpClause::Nocontext>( 845 parenthesized(scalarLogicalExpr))) || 846 "NOGROUP" >> construct<OmpClause>(construct<OmpClause::Nogroup>()) || 847 "NONTEMPORAL" >> construct<OmpClause>(construct<OmpClause::Nontemporal>( 848 parenthesized(nonemptyList(name)))) || 849 "NOTINBRANCH" >> 850 construct<OmpClause>(construct<OmpClause::Notinbranch>()) || 851 "NOVARIANTS" >> construct<OmpClause>(construct<OmpClause::Novariants>( 852 parenthesized(scalarLogicalExpr))) || 853 "NOWAIT" >> construct<OmpClause>(construct<OmpClause::Nowait>()) || 854 "NUM_TASKS" >> construct<OmpClause>(construct<OmpClause::NumTasks>( 855 parenthesized(Parser<OmpNumTasksClause>{}))) || 856 "NUM_TEAMS" >> construct<OmpClause>(construct<OmpClause::NumTeams>( 857 parenthesized(scalarIntExpr))) || 858 "NUM_THREADS" >> construct<OmpClause>(construct<OmpClause::NumThreads>( 859 parenthesized(scalarIntExpr))) || 860 "OMPX_BARE" >> construct<OmpClause>(construct<OmpClause::OmpxBare>()) || 861 "ORDER" >> construct<OmpClause>(construct<OmpClause::Order>( 862 parenthesized(Parser<OmpOrderClause>{}))) || 863 "ORDERED" >> construct<OmpClause>(construct<OmpClause::Ordered>( 864 maybe(parenthesized(scalarIntConstantExpr)))) || 865 "OTHERWISE" >> construct<OmpClause>(construct<OmpClause::Otherwise>( 866 maybe(parenthesized(Parser<OmpOtherwiseClause>{})))) || 867 "PARTIAL" >> construct<OmpClause>(construct<OmpClause::Partial>( 868 maybe(parenthesized(scalarIntConstantExpr)))) || 869 "PRIORITY" >> construct<OmpClause>(construct<OmpClause::Priority>( 870 parenthesized(scalarIntExpr))) || 871 "PRIVATE" >> construct<OmpClause>(construct<OmpClause::Private>( 872 parenthesized(Parser<OmpObjectList>{}))) || 873 "PROC_BIND" >> construct<OmpClause>(construct<OmpClause::ProcBind>( 874 parenthesized(Parser<OmpProcBindClause>{}))) || 875 "REDUCTION"_id >> construct<OmpClause>(construct<OmpClause::Reduction>( 876 parenthesized(Parser<OmpReductionClause>{}))) || 877 "IN_REDUCTION" >> construct<OmpClause>(construct<OmpClause::InReduction>( 878 parenthesized(Parser<OmpInReductionClause>{}))) || 879 "DETACH" >> construct<OmpClause>(construct<OmpClause::Detach>( 880 parenthesized(Parser<OmpDetachClause>{}))) || 881 "TASK_REDUCTION" >> 882 construct<OmpClause>(construct<OmpClause::TaskReduction>( 883 parenthesized(Parser<OmpTaskReductionClause>{}))) || 884 "RELAXED" >> construct<OmpClause>(construct<OmpClause::Relaxed>()) || 885 "RELEASE" >> construct<OmpClause>(construct<OmpClause::Release>()) || 886 "REVERSE_OFFLOAD" >> 887 construct<OmpClause>(construct<OmpClause::ReverseOffload>()) || 888 "SAFELEN" >> construct<OmpClause>(construct<OmpClause::Safelen>( 889 parenthesized(scalarIntConstantExpr))) || 890 "SCHEDULE" >> construct<OmpClause>(construct<OmpClause::Schedule>( 891 parenthesized(Parser<OmpScheduleClause>{}))) || 892 "SEQ_CST" >> construct<OmpClause>(construct<OmpClause::SeqCst>()) || 893 "SEVERITY" >> construct<OmpClause>(construct<OmpClause::Severity>( 894 parenthesized(Parser<OmpSeverityClause>{}))) || 895 "SHARED" >> construct<OmpClause>(construct<OmpClause::Shared>( 896 parenthesized(Parser<OmpObjectList>{}))) || 897 "SIMD"_id >> construct<OmpClause>(construct<OmpClause::Simd>()) || 898 "SIMDLEN" >> construct<OmpClause>(construct<OmpClause::Simdlen>( 899 parenthesized(scalarIntConstantExpr))) || 900 "SIZES" >> construct<OmpClause>(construct<OmpClause::Sizes>( 901 parenthesized(nonemptyList(scalarIntExpr)))) || 902 "PERMUTATION" >> construct<OmpClause>(construct<OmpClause::Permutation>( 903 parenthesized(nonemptyList(scalarIntExpr)))) || 904 "THREADS" >> construct<OmpClause>(construct<OmpClause::Threads>()) || 905 "THREAD_LIMIT" >> construct<OmpClause>(construct<OmpClause::ThreadLimit>( 906 parenthesized(scalarIntExpr))) || 907 "TO" >> construct<OmpClause>(construct<OmpClause::To>( 908 parenthesized(Parser<OmpToClause>{}))) || 909 "USE_DEVICE_PTR" >> construct<OmpClause>(construct<OmpClause::UseDevicePtr>( 910 parenthesized(Parser<OmpObjectList>{}))) || 911 "USE_DEVICE_ADDR" >> 912 construct<OmpClause>(construct<OmpClause::UseDeviceAddr>( 913 parenthesized(Parser<OmpObjectList>{}))) || 914 "UNIFIED_ADDRESS" >> 915 construct<OmpClause>(construct<OmpClause::UnifiedAddress>()) || 916 "UNIFIED_SHARED_MEMORY" >> 917 construct<OmpClause>(construct<OmpClause::UnifiedSharedMemory>()) || 918 "UNIFORM" >> construct<OmpClause>(construct<OmpClause::Uniform>( 919 parenthesized(nonemptyList(name)))) || 920 "UNTIED" >> construct<OmpClause>(construct<OmpClause::Untied>()) || 921 "UPDATE" >> construct<OmpClause>(construct<OmpClause::Update>( 922 parenthesized(Parser<OmpUpdateClause>{}))) || 923 "WHEN" >> construct<OmpClause>(construct<OmpClause::When>( 924 parenthesized(Parser<OmpWhenClause>{})))) 925 926 // [Clause, [Clause], ...] 927 TYPE_PARSER(sourced(construct<OmpClauseList>( 928 many(maybe(","_tok) >> sourced(Parser<OmpClause>{}))))) 929 930 // 2.1 (variable | /common-block/ | array-sections) 931 TYPE_PARSER(construct<OmpObjectList>(nonemptyList(Parser<OmpObject>{}))) 932 933 TYPE_PARSER(sourced(construct<OmpErrorDirective>( 934 verbatim("ERROR"_tok), Parser<OmpClauseList>{}))) 935 936 TYPE_PARSER(sourced(construct<OmpNothingDirective>("NOTHING" >> ok))) 937 938 TYPE_PARSER(sourced(construct<OpenMPUtilityConstruct>( 939 sourced(construct<OpenMPUtilityConstruct>( 940 sourced(Parser<OmpErrorDirective>{}))) || 941 sourced(construct<OpenMPUtilityConstruct>( 942 sourced(Parser<OmpNothingDirective>{})))))) 943 944 TYPE_PARSER(sourced(construct<OmpMetadirectiveDirective>( 945 "METADIRECTIVE" >> Parser<OmpClauseList>{}))) 946 947 // Omp directives enclosing do loop 948 TYPE_PARSER(sourced(construct<OmpLoopDirective>(first( 949 "DISTRIBUTE PARALLEL DO SIMD" >> 950 pure(llvm::omp::Directive::OMPD_distribute_parallel_do_simd), 951 "DISTRIBUTE PARALLEL DO" >> 952 pure(llvm::omp::Directive::OMPD_distribute_parallel_do), 953 "DISTRIBUTE SIMD" >> pure(llvm::omp::Directive::OMPD_distribute_simd), 954 "DISTRIBUTE" >> pure(llvm::omp::Directive::OMPD_distribute), 955 "DO SIMD" >> pure(llvm::omp::Directive::OMPD_do_simd), 956 "DO" >> pure(llvm::omp::Directive::OMPD_do), 957 "LOOP" >> pure(llvm::omp::Directive::OMPD_loop), 958 "MASKED TASKLOOP SIMD" >> 959 pure(llvm::omp::Directive::OMPD_masked_taskloop_simd), 960 "MASKED TASKLOOP" >> pure(llvm::omp::Directive::OMPD_masked_taskloop), 961 "MASTER TASKLOOP SIMD" >> 962 pure(llvm::omp::Directive::OMPD_master_taskloop_simd), 963 "MASTER TASKLOOP" >> pure(llvm::omp::Directive::OMPD_master_taskloop), 964 "PARALLEL DO SIMD" >> pure(llvm::omp::Directive::OMPD_parallel_do_simd), 965 "PARALLEL DO" >> pure(llvm::omp::Directive::OMPD_parallel_do), 966 "PARALLEL MASKED TASKLOOP SIMD" >> 967 pure(llvm::omp::Directive::OMPD_parallel_masked_taskloop_simd), 968 "PARALLEL MASKED TASKLOOP" >> 969 pure(llvm::omp::Directive::OMPD_parallel_masked_taskloop), 970 "PARALLEL MASTER TASKLOOP SIMD" >> 971 pure(llvm::omp::Directive::OMPD_parallel_master_taskloop_simd), 972 "PARALLEL MASTER TASKLOOP" >> 973 pure(llvm::omp::Directive::OMPD_parallel_master_taskloop), 974 "SIMD" >> pure(llvm::omp::Directive::OMPD_simd), 975 "TARGET LOOP" >> pure(llvm::omp::Directive::OMPD_target_loop), 976 "TARGET PARALLEL DO SIMD" >> 977 pure(llvm::omp::Directive::OMPD_target_parallel_do_simd), 978 "TARGET PARALLEL DO" >> pure(llvm::omp::Directive::OMPD_target_parallel_do), 979 "TARGET PARALLEL LOOP" >> 980 pure(llvm::omp::Directive::OMPD_target_parallel_loop), 981 "TARGET SIMD" >> pure(llvm::omp::Directive::OMPD_target_simd), 982 "TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD" >> 983 pure(llvm::omp::Directive:: 984 OMPD_target_teams_distribute_parallel_do_simd), 985 "TARGET TEAMS DISTRIBUTE PARALLEL DO" >> 986 pure(llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do), 987 "TARGET TEAMS DISTRIBUTE SIMD" >> 988 pure(llvm::omp::Directive::OMPD_target_teams_distribute_simd), 989 "TARGET TEAMS DISTRIBUTE" >> 990 pure(llvm::omp::Directive::OMPD_target_teams_distribute), 991 "TARGET TEAMS LOOP" >> pure(llvm::omp::Directive::OMPD_target_teams_loop), 992 "TASKLOOP SIMD" >> pure(llvm::omp::Directive::OMPD_taskloop_simd), 993 "TASKLOOP" >> pure(llvm::omp::Directive::OMPD_taskloop), 994 "TEAMS DISTRIBUTE PARALLEL DO SIMD" >> 995 pure(llvm::omp::Directive::OMPD_teams_distribute_parallel_do_simd), 996 "TEAMS DISTRIBUTE PARALLEL DO" >> 997 pure(llvm::omp::Directive::OMPD_teams_distribute_parallel_do), 998 "TEAMS DISTRIBUTE SIMD" >> 999 pure(llvm::omp::Directive::OMPD_teams_distribute_simd), 1000 "TEAMS DISTRIBUTE" >> pure(llvm::omp::Directive::OMPD_teams_distribute), 1001 "TEAMS LOOP" >> pure(llvm::omp::Directive::OMPD_teams_loop), 1002 "TILE" >> pure(llvm::omp::Directive::OMPD_tile), 1003 "UNROLL" >> pure(llvm::omp::Directive::OMPD_unroll))))) 1004 1005 TYPE_PARSER(sourced(construct<OmpBeginLoopDirective>( 1006 sourced(Parser<OmpLoopDirective>{}), Parser<OmpClauseList>{}))) 1007 1008 // 2.14.1 construct-type-clause -> PARALLEL | SECTIONS | DO | TASKGROUP 1009 TYPE_PARSER(sourced(construct<OmpCancelType>( 1010 first("PARALLEL" >> pure(OmpCancelType::Type::Parallel), 1011 "SECTIONS" >> pure(OmpCancelType::Type::Sections), 1012 "DO" >> pure(OmpCancelType::Type::Do), 1013 "TASKGROUP" >> pure(OmpCancelType::Type::Taskgroup))))) 1014 1015 // 2.14.2 Cancellation Point construct 1016 TYPE_PARSER(sourced(construct<OpenMPCancellationPointConstruct>( 1017 verbatim("CANCELLATION POINT"_tok), Parser<OmpCancelType>{}))) 1018 1019 // 2.14.1 Cancel construct 1020 TYPE_PARSER(sourced(construct<OpenMPCancelConstruct>(verbatim("CANCEL"_tok), 1021 Parser<OmpCancelType>{}, maybe("IF" >> parenthesized(scalarLogicalExpr))))) 1022 1023 TYPE_PARSER(sourced(construct<OmpFailClause>( 1024 parenthesized(indirect(Parser<OmpMemoryOrderClause>{}))))) 1025 1026 // 2.17.7 Atomic construct/2.17.8 Flush construct [OpenMP 5.0] 1027 // memory-order-clause -> 1028 // seq_cst 1029 // acq_rel 1030 // release 1031 // acquire 1032 // relaxed 1033 TYPE_PARSER(sourced(construct<OmpMemoryOrderClause>( 1034 sourced("SEQ_CST" >> construct<OmpClause>(construct<OmpClause::SeqCst>()) || 1035 "ACQ_REL" >> construct<OmpClause>(construct<OmpClause::AcqRel>()) || 1036 "RELEASE" >> construct<OmpClause>(construct<OmpClause::Release>()) || 1037 "ACQUIRE" >> construct<OmpClause>(construct<OmpClause::Acquire>()) || 1038 "RELAXED" >> construct<OmpClause>(construct<OmpClause::Relaxed>()))))) 1039 1040 // 2.4 Requires construct [OpenMP 5.0] 1041 // atomic-default-mem-order-clause -> 1042 // seq_cst 1043 // acq_rel 1044 // relaxed 1045 TYPE_PARSER(construct<OmpAtomicDefaultMemOrderClause>( 1046 "SEQ_CST" >> pure(common::OmpAtomicDefaultMemOrderType::SeqCst) || 1047 "ACQ_REL" >> pure(common::OmpAtomicDefaultMemOrderType::AcqRel) || 1048 "RELAXED" >> pure(common::OmpAtomicDefaultMemOrderType::Relaxed))) 1049 1050 // 2.17.7 Atomic construct 1051 // atomic-clause -> memory-order-clause | HINT(hint-expression) 1052 TYPE_PARSER(sourced(construct<OmpAtomicClause>( 1053 construct<OmpAtomicClause>(Parser<OmpMemoryOrderClause>{}) || 1054 construct<OmpAtomicClause>("FAIL" >> Parser<OmpFailClause>{}) || 1055 construct<OmpAtomicClause>("HINT" >> 1056 sourced(construct<OmpClause>( 1057 construct<OmpClause::Hint>(parenthesized(constantExpr)))))))) 1058 1059 // atomic-clause-list -> [atomic-clause, [atomic-clause], ...] 1060 TYPE_PARSER(sourced(construct<OmpAtomicClauseList>( 1061 many(maybe(","_tok) >> sourced(Parser<OmpAtomicClause>{}))))) 1062 1063 TYPE_PARSER(sourced(construct<OpenMPDepobjConstruct>(verbatim("DEPOBJ"_tok), 1064 parenthesized(Parser<OmpObject>{}), sourced(Parser<OmpClause>{})))) 1065 1066 TYPE_PARSER(sourced(construct<OpenMPFlushConstruct>(verbatim("FLUSH"_tok), 1067 many(maybe(","_tok) >> sourced(Parser<OmpMemoryOrderClause>{})), 1068 maybe(parenthesized(Parser<OmpObjectList>{}))))) 1069 1070 // Simple Standalone Directives 1071 TYPE_PARSER(sourced(construct<OmpSimpleStandaloneDirective>(first( 1072 "BARRIER" >> pure(llvm::omp::Directive::OMPD_barrier), 1073 "ORDERED" >> pure(llvm::omp::Directive::OMPD_ordered), 1074 "SCAN" >> pure(llvm::omp::Directive::OMPD_scan), 1075 "TARGET ENTER DATA" >> pure(llvm::omp::Directive::OMPD_target_enter_data), 1076 "TARGET EXIT DATA" >> pure(llvm::omp::Directive::OMPD_target_exit_data), 1077 "TARGET UPDATE" >> pure(llvm::omp::Directive::OMPD_target_update), 1078 "TASKWAIT" >> pure(llvm::omp::Directive::OMPD_taskwait), 1079 "TASKYIELD" >> pure(llvm::omp::Directive::OMPD_taskyield))))) 1080 1081 TYPE_PARSER(sourced(construct<OpenMPSimpleStandaloneConstruct>( 1082 Parser<OmpSimpleStandaloneDirective>{}, Parser<OmpClauseList>{}))) 1083 1084 // Standalone Constructs 1085 TYPE_PARSER( 1086 sourced(construct<OpenMPStandaloneConstruct>( 1087 Parser<OpenMPSimpleStandaloneConstruct>{}) || 1088 construct<OpenMPStandaloneConstruct>(Parser<OpenMPFlushConstruct>{}) || 1089 construct<OpenMPStandaloneConstruct>(Parser<OpenMPCancelConstruct>{}) || 1090 construct<OpenMPStandaloneConstruct>( 1091 Parser<OpenMPCancellationPointConstruct>{}) || 1092 construct<OpenMPStandaloneConstruct>( 1093 Parser<OmpMetadirectiveDirective>{}) || 1094 construct<OpenMPStandaloneConstruct>(Parser<OpenMPDepobjConstruct>{})) / 1095 endOfLine) 1096 1097 // Directives enclosing structured-block 1098 TYPE_PARSER(construct<OmpBlockDirective>(first( 1099 "MASKED" >> pure(llvm::omp::Directive::OMPD_masked), 1100 "MASTER" >> pure(llvm::omp::Directive::OMPD_master), 1101 "ORDERED" >> pure(llvm::omp::Directive::OMPD_ordered), 1102 "PARALLEL MASKED" >> pure(llvm::omp::Directive::OMPD_parallel_masked), 1103 "PARALLEL MASTER" >> pure(llvm::omp::Directive::OMPD_parallel_master), 1104 "PARALLEL WORKSHARE" >> pure(llvm::omp::Directive::OMPD_parallel_workshare), 1105 "PARALLEL" >> pure(llvm::omp::Directive::OMPD_parallel), 1106 "SCOPE" >> pure(llvm::omp::Directive::OMPD_scope), 1107 "SINGLE" >> pure(llvm::omp::Directive::OMPD_single), 1108 "TARGET DATA" >> pure(llvm::omp::Directive::OMPD_target_data), 1109 "TARGET PARALLEL" >> pure(llvm::omp::Directive::OMPD_target_parallel), 1110 "TARGET TEAMS" >> pure(llvm::omp::Directive::OMPD_target_teams), 1111 "TARGET" >> pure(llvm::omp::Directive::OMPD_target), 1112 "TASK"_id >> pure(llvm::omp::Directive::OMPD_task), 1113 "TASKGROUP" >> pure(llvm::omp::Directive::OMPD_taskgroup), 1114 "TEAMS" >> pure(llvm::omp::Directive::OMPD_teams), 1115 "WORKSHARE" >> pure(llvm::omp::Directive::OMPD_workshare)))) 1116 1117 TYPE_PARSER(sourced(construct<OmpBeginBlockDirective>( 1118 sourced(Parser<OmpBlockDirective>{}), Parser<OmpClauseList>{}))) 1119 1120 TYPE_PARSER(construct<OmpReductionInitializerClause>( 1121 "INITIALIZER" >> parenthesized("OMP_PRIV =" >> expr))) 1122 1123 // 2.16 Declare Reduction Construct 1124 TYPE_PARSER(sourced(construct<OpenMPDeclareReductionConstruct>( 1125 verbatim("DECLARE REDUCTION"_tok), 1126 "(" >> Parser<OmpReductionIdentifier>{} / ":", 1127 nonemptyList(Parser<DeclarationTypeSpec>{}) / ":", 1128 Parser<OmpReductionCombiner>{} / ")", 1129 maybe(Parser<OmpReductionInitializerClause>{})))) 1130 1131 // declare-target with list 1132 TYPE_PARSER(sourced(construct<OmpDeclareTargetWithList>( 1133 parenthesized(Parser<OmpObjectList>{})))) 1134 1135 // declare-target with clause 1136 TYPE_PARSER( 1137 sourced(construct<OmpDeclareTargetWithClause>(Parser<OmpClauseList>{}))) 1138 1139 // declare-target-specifier 1140 TYPE_PARSER( 1141 construct<OmpDeclareTargetSpecifier>(Parser<OmpDeclareTargetWithList>{}) || 1142 construct<OmpDeclareTargetSpecifier>(Parser<OmpDeclareTargetWithClause>{})) 1143 1144 // 2.10.6 Declare Target Construct 1145 TYPE_PARSER(sourced(construct<OpenMPDeclareTargetConstruct>( 1146 verbatim("DECLARE TARGET"_tok), Parser<OmpDeclareTargetSpecifier>{}))) 1147 1148 // declare-mapper-specifier 1149 TYPE_PARSER(construct<OmpDeclareMapperSpecifier>( 1150 maybe(name / ":" / !":"_tok), typeSpec / "::", name)) 1151 1152 // OpenMP 5.2: 5.8.8 Declare Mapper Construct 1153 TYPE_PARSER(sourced(construct<OpenMPDeclareMapperConstruct>( 1154 verbatim("DECLARE MAPPER"_tok), 1155 "(" >> Parser<OmpDeclareMapperSpecifier>{} / ")", Parser<OmpClauseList>{}))) 1156 1157 TYPE_PARSER(construct<OmpReductionCombiner>(Parser<AssignmentStmt>{}) || 1158 construct<OmpReductionCombiner>( 1159 construct<OmpReductionCombiner::FunctionCombiner>( 1160 construct<Call>(Parser<ProcedureDesignator>{}, 1161 parenthesized(optionalList(actualArgSpec)))))) 1162 1163 // 2.17.7 atomic -> ATOMIC [clause [,]] atomic-clause [[,] clause] | 1164 // ATOMIC [clause] 1165 // clause -> memory-order-clause | HINT(hint-expression) 1166 // memory-order-clause -> SEQ_CST | ACQ_REL | RELEASE | ACQUIRE | RELAXED 1167 // atomic-clause -> READ | WRITE | UPDATE | CAPTURE 1168 1169 // OMP END ATOMIC 1170 TYPE_PARSER(construct<OmpEndAtomic>(startOmpLine >> "END ATOMIC"_tok)) 1171 1172 // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] READ [MEMORY-ORDER-CLAUSE-LIST] 1173 TYPE_PARSER("ATOMIC" >> 1174 sourced(construct<OmpAtomicRead>( 1175 Parser<OmpAtomicClauseList>{} / maybe(","_tok), verbatim("READ"_tok), 1176 Parser<OmpAtomicClauseList>{} / endOmpLine, statement(assignmentStmt), 1177 maybe(Parser<OmpEndAtomic>{} / endOmpLine)))) 1178 1179 // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] CAPTURE [MEMORY-ORDER-CLAUSE-LIST] 1180 TYPE_PARSER("ATOMIC" >> 1181 sourced(construct<OmpAtomicCapture>( 1182 Parser<OmpAtomicClauseList>{} / maybe(","_tok), verbatim("CAPTURE"_tok), 1183 Parser<OmpAtomicClauseList>{} / endOmpLine, statement(assignmentStmt), 1184 statement(assignmentStmt), Parser<OmpEndAtomic>{} / endOmpLine))) 1185 1186 TYPE_PARSER(construct<OmpAtomicCompareIfStmt>(indirect(Parser<IfStmt>{})) || 1187 construct<OmpAtomicCompareIfStmt>(indirect(Parser<IfConstruct>{}))) 1188 1189 // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] COMPARE [MEMORY-ORDER-CLAUSE-LIST] 1190 TYPE_PARSER("ATOMIC" >> 1191 sourced(construct<OmpAtomicCompare>( 1192 Parser<OmpAtomicClauseList>{} / maybe(","_tok), verbatim("COMPARE"_tok), 1193 Parser<OmpAtomicClauseList>{} / endOmpLine, 1194 Parser<OmpAtomicCompareIfStmt>{}, 1195 maybe(Parser<OmpEndAtomic>{} / endOmpLine)))) 1196 1197 // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] UPDATE [MEMORY-ORDER-CLAUSE-LIST] 1198 TYPE_PARSER("ATOMIC" >> 1199 sourced(construct<OmpAtomicUpdate>( 1200 Parser<OmpAtomicClauseList>{} / maybe(","_tok), verbatim("UPDATE"_tok), 1201 Parser<OmpAtomicClauseList>{} / endOmpLine, statement(assignmentStmt), 1202 maybe(Parser<OmpEndAtomic>{} / endOmpLine)))) 1203 1204 // OMP ATOMIC [atomic-clause-list] 1205 TYPE_PARSER(sourced(construct<OmpAtomic>(verbatim("ATOMIC"_tok), 1206 Parser<OmpAtomicClauseList>{} / endOmpLine, statement(assignmentStmt), 1207 maybe(Parser<OmpEndAtomic>{} / endOmpLine)))) 1208 1209 // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] WRITE [MEMORY-ORDER-CLAUSE-LIST] 1210 TYPE_PARSER("ATOMIC" >> 1211 sourced(construct<OmpAtomicWrite>( 1212 Parser<OmpAtomicClauseList>{} / maybe(","_tok), verbatim("WRITE"_tok), 1213 Parser<OmpAtomicClauseList>{} / endOmpLine, statement(assignmentStmt), 1214 maybe(Parser<OmpEndAtomic>{} / endOmpLine)))) 1215 1216 // Atomic Construct 1217 TYPE_PARSER(construct<OpenMPAtomicConstruct>(Parser<OmpAtomicRead>{}) || 1218 construct<OpenMPAtomicConstruct>(Parser<OmpAtomicCapture>{}) || 1219 construct<OpenMPAtomicConstruct>(Parser<OmpAtomicCompare>{}) || 1220 construct<OpenMPAtomicConstruct>(Parser<OmpAtomicWrite>{}) || 1221 construct<OpenMPAtomicConstruct>(Parser<OmpAtomicUpdate>{}) || 1222 construct<OpenMPAtomicConstruct>(Parser<OmpAtomic>{})) 1223 1224 // 2.13.2 OMP CRITICAL 1225 TYPE_PARSER(startOmpLine >> 1226 sourced(construct<OmpEndCriticalDirective>( 1227 verbatim("END CRITICAL"_tok), maybe(parenthesized(name)))) / 1228 endOmpLine) 1229 TYPE_PARSER(sourced(construct<OmpCriticalDirective>(verbatim("CRITICAL"_tok), 1230 maybe(parenthesized(name)), Parser<OmpClauseList>{})) / 1231 endOmpLine) 1232 1233 TYPE_PARSER(construct<OpenMPCriticalConstruct>( 1234 Parser<OmpCriticalDirective>{}, block, Parser<OmpEndCriticalDirective>{})) 1235 1236 TYPE_PARSER(sourced(construct<OmpDispatchDirective>( 1237 verbatim("DISPATCH"_tok), Parser<OmpClauseList>{}))) 1238 1239 TYPE_PARSER( 1240 construct<OmpEndDispatchDirective>(startOmpLine >> "END DISPATCH"_tok)) 1241 1242 TYPE_PARSER(sourced(construct<OpenMPDispatchConstruct>( 1243 Parser<OmpDispatchDirective>{} / endOmpLine, block, 1244 maybe(Parser<OmpEndDispatchDirective>{} / endOmpLine)))) 1245 1246 // 2.11.3 Executable Allocate directive 1247 TYPE_PARSER( 1248 sourced(construct<OpenMPExecutableAllocate>(verbatim("ALLOCATE"_tok), 1249 maybe(parenthesized(Parser<OmpObjectList>{})), Parser<OmpClauseList>{}, 1250 maybe(nonemptyList(Parser<OpenMPDeclarativeAllocate>{})) / endOmpLine, 1251 statement(allocateStmt)))) 1252 1253 // 6.7 Allocators construct [OpenMP 5.2] 1254 // allocators-construct -> ALLOCATORS [allocate-clause [,]] 1255 // allocate-stmt 1256 // [omp-end-allocators-construct] 1257 TYPE_PARSER(sourced(construct<OpenMPAllocatorsConstruct>( 1258 verbatim("ALLOCATORS"_tok), Parser<OmpClauseList>{} / endOmpLine, 1259 statement(allocateStmt), maybe(Parser<OmpEndAllocators>{} / endOmpLine)))) 1260 1261 TYPE_PARSER(construct<OmpEndAllocators>(startOmpLine >> "END ALLOCATORS"_tok)) 1262 1263 // 2.8.2 Declare Simd construct 1264 TYPE_PARSER( 1265 sourced(construct<OpenMPDeclareSimdConstruct>(verbatim("DECLARE SIMD"_tok), 1266 maybe(parenthesized(name)), Parser<OmpClauseList>{}))) 1267 1268 // 2.4 Requires construct 1269 TYPE_PARSER(sourced(construct<OpenMPRequiresConstruct>( 1270 verbatim("REQUIRES"_tok), Parser<OmpClauseList>{}))) 1271 1272 // 2.15.2 Threadprivate directive 1273 TYPE_PARSER(sourced(construct<OpenMPThreadprivate>( 1274 verbatim("THREADPRIVATE"_tok), parenthesized(Parser<OmpObjectList>{})))) 1275 1276 // 2.11.3 Declarative Allocate directive 1277 TYPE_PARSER( 1278 sourced(construct<OpenMPDeclarativeAllocate>(verbatim("ALLOCATE"_tok), 1279 parenthesized(Parser<OmpObjectList>{}), Parser<OmpClauseList>{})) / 1280 lookAhead(endOmpLine / !statement(allocateStmt))) 1281 1282 // Declarative constructs 1283 TYPE_PARSER(startOmpLine >> 1284 withMessage("expected OpenMP construct"_err_en_US, 1285 sourced(construct<OpenMPDeclarativeConstruct>( 1286 Parser<OpenMPDeclareReductionConstruct>{}) || 1287 construct<OpenMPDeclarativeConstruct>( 1288 Parser<OpenMPDeclareMapperConstruct>{}) || 1289 construct<OpenMPDeclarativeConstruct>( 1290 Parser<OpenMPDeclareSimdConstruct>{}) || 1291 construct<OpenMPDeclarativeConstruct>( 1292 Parser<OpenMPDeclareTargetConstruct>{}) || 1293 construct<OpenMPDeclarativeConstruct>( 1294 Parser<OpenMPDeclarativeAllocate>{}) || 1295 construct<OpenMPDeclarativeConstruct>( 1296 Parser<OpenMPRequiresConstruct>{}) || 1297 construct<OpenMPDeclarativeConstruct>( 1298 Parser<OpenMPThreadprivate>{}) || 1299 construct<OpenMPDeclarativeConstruct>( 1300 Parser<OpenMPUtilityConstruct>{})) / 1301 endOmpLine)) 1302 1303 // Block Construct 1304 TYPE_PARSER(construct<OpenMPBlockConstruct>( 1305 Parser<OmpBeginBlockDirective>{} / endOmpLine, block, 1306 Parser<OmpEndBlockDirective>{} / endOmpLine)) 1307 1308 // OMP SECTIONS Directive 1309 TYPE_PARSER(construct<OmpSectionsDirective>(first( 1310 "SECTIONS" >> pure(llvm::omp::Directive::OMPD_sections), 1311 "PARALLEL SECTIONS" >> pure(llvm::omp::Directive::OMPD_parallel_sections)))) 1312 1313 // OMP BEGIN and END SECTIONS Directive 1314 TYPE_PARSER(sourced(construct<OmpBeginSectionsDirective>( 1315 sourced(Parser<OmpSectionsDirective>{}), Parser<OmpClauseList>{}))) 1316 TYPE_PARSER( 1317 startOmpLine >> sourced(construct<OmpEndSectionsDirective>( 1318 sourced("END"_tok >> Parser<OmpSectionsDirective>{}), 1319 Parser<OmpClauseList>{}))) 1320 1321 // OMP SECTION-BLOCK 1322 1323 TYPE_PARSER(construct<OpenMPSectionConstruct>(block)) 1324 1325 TYPE_PARSER(maybe(startOmpLine >> "SECTION"_tok / endOmpLine) >> 1326 construct<OmpSectionBlocks>(nonemptySeparated( 1327 construct<OpenMPConstruct>(sourced(Parser<OpenMPSectionConstruct>{})), 1328 startOmpLine >> "SECTION"_tok / endOmpLine))) 1329 1330 // OMP SECTIONS (OpenMP 5.0 - 2.8.1), PARALLEL SECTIONS (OpenMP 5.0 - 2.13.3) 1331 TYPE_PARSER(construct<OpenMPSectionsConstruct>( 1332 Parser<OmpBeginSectionsDirective>{} / endOmpLine, 1333 Parser<OmpSectionBlocks>{}, Parser<OmpEndSectionsDirective>{} / endOmpLine)) 1334 1335 TYPE_CONTEXT_PARSER("OpenMP construct"_en_US, 1336 startOmpLine >> 1337 withMessage("expected OpenMP construct"_err_en_US, 1338 first(construct<OpenMPConstruct>(Parser<OpenMPSectionsConstruct>{}), 1339 construct<OpenMPConstruct>(Parser<OpenMPLoopConstruct>{}), 1340 construct<OpenMPConstruct>(Parser<OpenMPBlockConstruct>{}), 1341 // OpenMPBlockConstruct is attempted before 1342 // OpenMPStandaloneConstruct to resolve !$OMP ORDERED 1343 construct<OpenMPConstruct>(Parser<OpenMPStandaloneConstruct>{}), 1344 construct<OpenMPConstruct>(Parser<OpenMPAtomicConstruct>{}), 1345 construct<OpenMPConstruct>(Parser<OpenMPUtilityConstruct>{}), 1346 construct<OpenMPConstruct>(Parser<OpenMPDispatchConstruct>{}), 1347 construct<OpenMPConstruct>(Parser<OpenMPExecutableAllocate>{}), 1348 construct<OpenMPConstruct>(Parser<OpenMPAllocatorsConstruct>{}), 1349 construct<OpenMPConstruct>(Parser<OpenMPDeclarativeAllocate>{}), 1350 construct<OpenMPConstruct>(Parser<OpenMPCriticalConstruct>{})))) 1351 1352 // END OMP Block directives 1353 TYPE_PARSER( 1354 startOmpLine >> sourced(construct<OmpEndBlockDirective>( 1355 sourced("END"_tok >> Parser<OmpBlockDirective>{}), 1356 Parser<OmpClauseList>{}))) 1357 1358 // END OMP Loop directives 1359 TYPE_PARSER( 1360 startOmpLine >> sourced(construct<OmpEndLoopDirective>( 1361 sourced("END"_tok >> Parser<OmpLoopDirective>{}), 1362 Parser<OmpClauseList>{}))) 1363 1364 TYPE_PARSER(construct<OpenMPLoopConstruct>( 1365 Parser<OmpBeginLoopDirective>{} / endOmpLine)) 1366 } // namespace Fortran::parser 1367