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