|
16 | 16 | #include "token-parsers.h" |
17 | 17 | #include "type-parser-implementation.h" |
18 | 18 | #include "flang/Parser/parse-tree.h" |
| 19 | +#include "llvm/ADT/ArrayRef.h" |
| 20 | +#include "llvm/ADT/STLExtras.h" |
| 21 | +#include "llvm/ADT/StringRef.h" |
| 22 | +#include "llvm/Frontend/OpenMP/OMP.h" |
19 | 23 |
|
20 | 24 | // OpenMP Directives and Clauses |
21 | 25 | namespace Fortran::parser { |
22 | 26 |
|
23 | 27 | constexpr auto startOmpLine = skipStuffBeforeStatement >> "!$OMP "_sptok; |
24 | 28 | constexpr auto endOmpLine = space >> endOfLine; |
25 | 29 |
|
| 30 | +/// Parse OpenMP directive name (this includes compound directives). |
| 31 | +struct OmpDirectiveNameParser { |
| 32 | + using resultType = llvm::omp::Directive; |
| 33 | + using Token = TokenStringMatch<false, false>; |
| 34 | + |
| 35 | + std::optional<resultType> Parse(ParseState &state) const { |
| 36 | + for (const NameWithId &nid : directives()) { |
| 37 | + if (attempt(Token(nid.first.data())).Parse(state)) { |
| 38 | + return nid.second; |
| 39 | + } |
| 40 | + } |
| 41 | + return std::nullopt; |
| 42 | + } |
| 43 | + |
| 44 | +private: |
| 45 | + using NameWithId = std::pair<std::string, llvm::omp::Directive>; |
| 46 | + |
| 47 | + llvm::iterator_range<const NameWithId *> directives() const; |
| 48 | + void initTokens(NameWithId *) const; |
| 49 | +}; |
| 50 | + |
| 51 | +llvm::iterator_range<const OmpDirectiveNameParser::NameWithId *> |
| 52 | +OmpDirectiveNameParser::directives() const { |
| 53 | + static NameWithId table[llvm::omp::Directive_enumSize]; |
| 54 | + [[maybe_unused]] static bool init = (initTokens(table), true); |
| 55 | + return llvm::make_range(std::cbegin(table), std::cend(table)); |
| 56 | +} |
| 57 | + |
| 58 | +void OmpDirectiveNameParser::initTokens(NameWithId *table) const { |
| 59 | + for (size_t i{0}, e{llvm::omp::Directive_enumSize}; i != e; ++i) { |
| 60 | + auto id{static_cast<llvm::omp::Directive>(i)}; |
| 61 | + llvm::StringRef name{llvm::omp::getOpenMPDirectiveName(id)}; |
| 62 | + table[i] = std::make_pair(name.str(), id); |
| 63 | + } |
| 64 | + // Sort the table with respect to the directive name length in a descending |
| 65 | + // order. This is to make sure that longer names are tried first, before |
| 66 | + // any potential prefix (e.g. "target update" before "target"). |
| 67 | + std::sort(table, table + llvm::omp::Directive_enumSize, |
| 68 | + [](auto &a, auto &b) { return a.first.size() > b.first.size(); }); |
| 69 | +} |
| 70 | + |
26 | 71 | template <typename Clause, typename Separator> struct ModifierList { |
27 | 72 | constexpr ModifierList(Separator sep) : sep_(sep) {} |
28 | 73 | constexpr ModifierList(const ModifierList &) = default; |
@@ -136,6 +181,9 @@ TYPE_PARSER(construct<OmpIterator>( // |
136 | 181 | "ITERATOR" >> |
137 | 182 | parenthesized(nonemptyList(sourced(Parser<OmpIteratorSpecifier>{}))))) |
138 | 183 |
|
| 184 | +TYPE_PARSER(construct<OmpLastprivateModifier>( |
| 185 | + "CONDITIONAL" >> pure(OmpLastprivateModifier::Value::Conditional))) |
| 186 | + |
139 | 187 | // 2.15.3.7 LINEAR (linear-list: linear-step) |
140 | 188 | // linear-list -> list | modifier(list) |
141 | 189 | // linear-modifier -> REF | VAL | UVAL |
@@ -232,6 +280,11 @@ TYPE_PARSER(sourced(construct<OmpFromClause::Modifier>( |
232 | 280 | TYPE_PARSER(sourced( |
233 | 281 | construct<OmpGrainsizeClause::Modifier>(Parser<OmpPrescriptiveness>{}))) |
234 | 282 |
|
| 283 | +TYPE_PARSER(sourced(construct<OmpIfClause::Modifier>(OmpDirectiveNameParser{}))) |
| 284 | + |
| 285 | +TYPE_PARSER(sourced(construct<OmpLastprivateClause::Modifier>( |
| 286 | + Parser<OmpLastprivateModifier>{}))) |
| 287 | + |
235 | 288 | TYPE_PARSER(sourced(construct<OmpMapClause::Modifier>( |
236 | 289 | sourced(construct<OmpMapClause::Modifier>(Parser<OmpMapTypeModifier>{}) || |
237 | 290 | construct<OmpMapClause::Modifier>(Parser<OmpMapper>{}) || |
@@ -345,22 +398,7 @@ TYPE_PARSER(construct<OmpDeviceTypeClause>( |
345 | 398 |
|
346 | 399 | // 2.12 IF (directive-name-modifier: scalar-logical-expr) |
347 | 400 | TYPE_PARSER(construct<OmpIfClause>( |
348 | | - maybe( |
349 | | - ("PARALLEL" >> pure(OmpIfClause::DirectiveNameModifier::Parallel) || |
350 | | - "SIMD" >> pure(OmpIfClause::DirectiveNameModifier::Simd) || |
351 | | - "TARGET ENTER DATA" >> |
352 | | - pure(OmpIfClause::DirectiveNameModifier::TargetEnterData) || |
353 | | - "TARGET EXIT DATA" >> |
354 | | - pure(OmpIfClause::DirectiveNameModifier::TargetExitData) || |
355 | | - "TARGET DATA" >> |
356 | | - pure(OmpIfClause::DirectiveNameModifier::TargetData) || |
357 | | - "TARGET UPDATE" >> |
358 | | - pure(OmpIfClause::DirectiveNameModifier::TargetUpdate) || |
359 | | - "TARGET" >> pure(OmpIfClause::DirectiveNameModifier::Target) || |
360 | | - "TASK"_id >> pure(OmpIfClause::DirectiveNameModifier::Task) || |
361 | | - "TASKLOOP" >> pure(OmpIfClause::DirectiveNameModifier::Taskloop) || |
362 | | - "TEAMS" >> pure(OmpIfClause::DirectiveNameModifier::Teams)) / |
363 | | - ":"), |
| 401 | + maybe(nonemptyList(Parser<OmpIfClause::Modifier>{}) / ":"), |
364 | 402 | scalarLogicalExpr)) |
365 | 403 |
|
366 | 404 | TYPE_PARSER(construct<OmpReductionClause>( |
@@ -460,8 +498,7 @@ TYPE_PARSER( |
460 | 498 |
|
461 | 499 | // OMP 5.0 2.19.4.5 LASTPRIVATE ([lastprivate-modifier :] list) |
462 | 500 | TYPE_PARSER(construct<OmpLastprivateClause>( |
463 | | - maybe("CONDITIONAL" >> |
464 | | - pure(OmpLastprivateClause::LastprivateModifier::Conditional) / ":"), |
| 501 | + maybe(nonemptyList(Parser<OmpLastprivateClause::Modifier>{}) / ":"), |
465 | 502 | Parser<OmpObjectList>{})) |
466 | 503 |
|
467 | 504 | // OMP 5.2 11.7.1 BIND ( PARALLEL | TEAMS | THREAD ) |
|
0 commit comments