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