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