
Again, this simplifies the semantic checks and lowering quite a bit. Update the check for positive alignment to use a more informative message, and to highlight the modifier itsef, not the whole clause. Remove the checks for the allocator expression itself being positive: there is nothing in the spec that says that it should be positive. Remove the "simple" modifier from the AllocateT template, since both simple and complex modifiers are the same thing, only differing in syntax.
983 lines
47 KiB
C++
983 lines
47 KiB
C++
//===-- lib/Parser/openmp-parsers.cpp -------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Top-level grammar specification for OpenMP.
|
|
// See OpenMP-4.5-grammar.txt for documentation.
|
|
|
|
#include "basic-parsers.h"
|
|
#include "expr-parsers.h"
|
|
#include "misc-parsers.h"
|
|
#include "stmt-parser.h"
|
|
#include "token-parsers.h"
|
|
#include "type-parser-implementation.h"
|
|
#include "flang/Parser/parse-tree.h"
|
|
|
|
// OpenMP Directives and Clauses
|
|
namespace Fortran::parser {
|
|
|
|
constexpr auto startOmpLine = skipStuffBeforeStatement >> "!$OMP "_sptok;
|
|
constexpr auto endOmpLine = space >> endOfLine;
|
|
|
|
template <typename Clause, typename Separator> struct ModifierList {
|
|
constexpr ModifierList(Separator sep) : sep_(sep) {}
|
|
constexpr ModifierList(const ModifierList &) = default;
|
|
constexpr ModifierList(ModifierList &&) = default;
|
|
|
|
using resultType = std::list<typename Clause::Modifier>;
|
|
|
|
std::optional<resultType> Parse(ParseState &state) const {
|
|
auto listp{nonemptySeparated(Parser<typename Clause::Modifier>{}, sep_)};
|
|
if (auto result{attempt(listp).Parse(state)}) {
|
|
if (!attempt(":"_tok).Parse(state)) {
|
|
return std::nullopt;
|
|
}
|
|
return std::move(result);
|
|
}
|
|
return resultType{};
|
|
}
|
|
|
|
private:
|
|
const Separator sep_;
|
|
};
|
|
|
|
// Use a function to create ModifierList because functions allow "partial"
|
|
// template argument deduction: "modifierList<Clause>(sep)" would be legal,
|
|
// while "ModifierList<Clause>(sep)" would complain about a missing template
|
|
// argument "Separator".
|
|
template <typename Clause, typename Separator>
|
|
constexpr ModifierList<Clause, Separator> modifierList(Separator sep) {
|
|
return ModifierList<Clause, Separator>(sep);
|
|
}
|
|
|
|
// OpenMP Clauses
|
|
|
|
// [5.0] 2.1.6 iterator-specifier -> type-declaration-stmt = subscript-triple |
|
|
// identifier = subscript-triple
|
|
// [5.0:47:17-18] In an iterator-specifier, if the iterator-type is not
|
|
// specified then the type of that iterator is default integer.
|
|
// [5.0:49:14] The iterator-type must be an integer type.
|
|
static std::list<EntityDecl> makeEntityList(std::list<ObjectName> &&names) {
|
|
std::list<EntityDecl> entities;
|
|
|
|
for (auto iter = names.begin(), end = names.end(); iter != end; ++iter) {
|
|
EntityDecl entityDecl(
|
|
/*ObjectName=*/std::move(*iter), std::optional<ArraySpec>{},
|
|
std::optional<CoarraySpec>{}, std::optional<CharLength>{},
|
|
std::optional<Initialization>{});
|
|
entities.push_back(std::move(entityDecl));
|
|
}
|
|
return entities;
|
|
}
|
|
|
|
static TypeDeclarationStmt makeIterSpecDecl(
|
|
DeclarationTypeSpec &&spec, std::list<ObjectName> &&names) {
|
|
return TypeDeclarationStmt(
|
|
std::move(spec), std::list<AttrSpec>{}, makeEntityList(std::move(names)));
|
|
}
|
|
|
|
static TypeDeclarationStmt makeIterSpecDecl(std::list<ObjectName> &&names) {
|
|
// Assume INTEGER without kind selector.
|
|
DeclarationTypeSpec typeSpec(
|
|
IntrinsicTypeSpec{IntegerTypeSpec{std::nullopt}});
|
|
|
|
return TypeDeclarationStmt(std::move(typeSpec), std::list<AttrSpec>{},
|
|
makeEntityList(std::move(names)));
|
|
}
|
|
|
|
// --- Parsers for clause modifiers -----------------------------------
|
|
|
|
TYPE_PARSER(construct<OmpAlignModifier>( //
|
|
"ALIGN" >> parenthesized(scalarIntExpr)))
|
|
|
|
TYPE_PARSER(construct<OmpAllocatorComplexModifier>(
|
|
"ALLOCATOR" >> parenthesized(scalarIntExpr)))
|
|
|
|
TYPE_PARSER(construct<OmpAllocatorSimpleModifier>(scalarIntExpr))
|
|
|
|
TYPE_PARSER(construct<OmpChunkModifier>( //
|
|
"SIMD" >> pure(OmpChunkModifier::Value::Simd)))
|
|
|
|
TYPE_PARSER(construct<OmpDependenceType>(
|
|
"SINK" >> pure(OmpDependenceType::Value::Sink) ||
|
|
"SOURCE" >> pure(OmpDependenceType::Value::Source)))
|
|
|
|
TYPE_PARSER(construct<OmpExpectation>( //
|
|
"PRESENT" >> pure(OmpExpectation::Value::Present)))
|
|
|
|
TYPE_PARSER(construct<OmpIteratorSpecifier>(
|
|
// Using Parser<TypeDeclarationStmt> or Parser<EntityDecl> has the problem
|
|
// that they will attempt to treat what follows the '=' as initialization.
|
|
// There are several issues with that,
|
|
// 1. integer :: i = 0:10 will be parsed as "integer :: i = 0", followed
|
|
// by triplet ":10".
|
|
// 2. integer :: j = i:10 will be flagged as an error because the
|
|
// initializer 'i' must be constant (in declarations). In an iterator
|
|
// specifier the 'j' is not an initializer and can be a variable.
|
|
(applyFunction<TypeDeclarationStmt>(makeIterSpecDecl,
|
|
Parser<DeclarationTypeSpec>{} / maybe("::"_tok),
|
|
nonemptyList(Parser<ObjectName>{}) / "="_tok) ||
|
|
applyFunction<TypeDeclarationStmt>(
|
|
makeIterSpecDecl, nonemptyList(Parser<ObjectName>{}) / "="_tok)),
|
|
subscriptTriplet))
|
|
|
|
// [5.0] 2.1.6 iterator -> iterator-specifier-list
|
|
TYPE_PARSER(construct<OmpIterator>( //
|
|
"ITERATOR" >>
|
|
parenthesized(nonemptyList(sourced(Parser<OmpIteratorSpecifier>{})))))
|
|
|
|
// 2.15.3.7 LINEAR (linear-list: linear-step)
|
|
// linear-list -> list | modifier(list)
|
|
// linear-modifier -> REF | VAL | UVAL
|
|
TYPE_PARSER(construct<OmpLinearModifier>( //
|
|
"REF" >> pure(OmpLinearModifier::Value::Ref) ||
|
|
"VAL" >> pure(OmpLinearModifier::Value::Val) ||
|
|
"UVAL" >> pure(OmpLinearModifier::Value::Uval)))
|
|
|
|
TYPE_PARSER(construct<OmpMapper>( //
|
|
"MAPPER"_tok >> parenthesized(Parser<ObjectName>{})))
|
|
|
|
// map-type -> ALLOC | DELETE | FROM | RELEASE | TO | TOFROM
|
|
TYPE_PARSER(construct<OmpMapType>( //
|
|
"ALLOC" >> pure(OmpMapType::Value::Alloc) ||
|
|
"DELETE" >> pure(OmpMapType::Value::Delete) ||
|
|
"FROM" >> pure(OmpMapType::Value::From) ||
|
|
"RELEASE" >> pure(OmpMapType::Value::Release) ||
|
|
"TO"_id >> pure(OmpMapType::Value::To) ||
|
|
"TOFROM" >> pure(OmpMapType::Value::Tofrom)))
|
|
|
|
// map-type-modifier -> ALWAYS | CLOSE | OMPX_HOLD | PRESENT
|
|
TYPE_PARSER(construct<OmpMapTypeModifier>(
|
|
"ALWAYS" >> pure(OmpMapTypeModifier::Value::Always) ||
|
|
"CLOSE" >> pure(OmpMapTypeModifier::Value::Close) ||
|
|
"OMPX_HOLD" >> pure(OmpMapTypeModifier::Value::Ompx_Hold) ||
|
|
"PRESENT" >> pure(OmpMapTypeModifier::Value::Present)))
|
|
|
|
// 2.15.3.6 REDUCTION (reduction-identifier: variable-name-list)
|
|
TYPE_PARSER(construct<OmpReductionIdentifier>(Parser<DefinedOperator>{}) ||
|
|
construct<OmpReductionIdentifier>(Parser<ProcedureDesignator>{}))
|
|
|
|
TYPE_PARSER(construct<OmpOrderModifier>(
|
|
"REPRODUCIBLE" >> pure(OmpOrderModifier::Value::Reproducible) ||
|
|
"UNCONSTRAINED" >> pure(OmpOrderModifier::Value::Unconstrained)))
|
|
|
|
TYPE_PARSER(construct<OmpOrderingModifier>(
|
|
"MONOTONIC" >> pure(OmpOrderingModifier::Value::Monotonic) ||
|
|
"NONMONOTONIC" >> pure(OmpOrderingModifier::Value::Nonmonotonic) ||
|
|
"SIMD" >> pure(OmpOrderingModifier::Value::Simd)))
|
|
|
|
TYPE_PARSER(construct<OmpReductionModifier>(
|
|
"INSCAN" >> pure(OmpReductionModifier::Value::Inscan) ||
|
|
"TASK" >> pure(OmpReductionModifier::Value::Task) ||
|
|
"DEFAULT" >> pure(OmpReductionModifier::Value::Default)))
|
|
|
|
TYPE_PARSER(construct<OmpTaskDependenceType>(
|
|
"DEPOBJ" >> pure(OmpTaskDependenceType::Value::Depobj) ||
|
|
"IN"_id >> pure(OmpTaskDependenceType::Value::In) ||
|
|
"INOUT"_id >> pure(OmpTaskDependenceType::Value::Inout) ||
|
|
"INOUTSET"_id >> pure(OmpTaskDependenceType::Value::Inoutset) ||
|
|
"MUTEXINOUTSET" >> pure(OmpTaskDependenceType::Value::Mutexinoutset) ||
|
|
"OUT" >> pure(OmpTaskDependenceType::Value::Out)))
|
|
|
|
TYPE_PARSER(construct<OmpVariableCategory>(
|
|
"AGGREGATE" >> pure(OmpVariableCategory::Value::Aggregate) ||
|
|
"ALL"_id >> pure(OmpVariableCategory::Value::All) ||
|
|
"ALLOCATABLE" >> pure(OmpVariableCategory::Value::Allocatable) ||
|
|
"POINTER" >> pure(OmpVariableCategory::Value::Pointer) ||
|
|
"SCALAR" >> pure(OmpVariableCategory::Value::Scalar)))
|
|
|
|
// This could be auto-generated.
|
|
TYPE_PARSER(sourced(construct<OmpAllocateClause::Modifier>(sourced(
|
|
construct<OmpAllocateClause::Modifier>(Parser<OmpAlignModifier>{}) ||
|
|
construct<OmpAllocateClause::Modifier>(
|
|
Parser<OmpAllocatorComplexModifier>{}) ||
|
|
construct<OmpAllocateClause::Modifier>(
|
|
Parser<OmpAllocatorSimpleModifier>{})))))
|
|
|
|
TYPE_PARSER(sourced(
|
|
construct<OmpDefaultmapClause::Modifier>(Parser<OmpVariableCategory>{})))
|
|
|
|
TYPE_PARSER(sourced(construct<OmpFromClause::Modifier>(
|
|
sourced(construct<OmpFromClause::Modifier>(Parser<OmpExpectation>{}) ||
|
|
construct<OmpFromClause::Modifier>(Parser<OmpMapper>{}) ||
|
|
construct<OmpFromClause::Modifier>(Parser<OmpIterator>{})))))
|
|
|
|
TYPE_PARSER(sourced(construct<OmpMapClause::Modifier>(
|
|
sourced(construct<OmpMapClause::Modifier>(Parser<OmpMapTypeModifier>{}) ||
|
|
construct<OmpMapClause::Modifier>(Parser<OmpMapper>{}) ||
|
|
construct<OmpMapClause::Modifier>(Parser<OmpIterator>{}) ||
|
|
construct<OmpMapClause::Modifier>(Parser<OmpMapType>{})))))
|
|
|
|
TYPE_PARSER(
|
|
sourced(construct<OmpOrderClause::Modifier>(Parser<OmpOrderModifier>{})))
|
|
|
|
TYPE_PARSER(sourced(construct<OmpReductionClause::Modifier>(sourced(
|
|
construct<OmpReductionClause::Modifier>(Parser<OmpReductionModifier>{}) ||
|
|
construct<OmpReductionClause::Modifier>(
|
|
Parser<OmpReductionIdentifier>{})))))
|
|
|
|
TYPE_PARSER(sourced(construct<OmpScheduleClause::Modifier>(sourced(
|
|
construct<OmpScheduleClause::Modifier>(Parser<OmpChunkModifier>{}) ||
|
|
construct<OmpScheduleClause::Modifier>(Parser<OmpOrderingModifier>{})))))
|
|
|
|
TYPE_PARSER(sourced(construct<OmpToClause::Modifier>(
|
|
sourced(construct<OmpToClause::Modifier>(Parser<OmpExpectation>{}) ||
|
|
construct<OmpToClause::Modifier>(Parser<OmpMapper>{}) ||
|
|
construct<OmpToClause::Modifier>(Parser<OmpIterator>{})))))
|
|
|
|
// --- Parsers for clauses --------------------------------------------
|
|
|
|
/// `MOBClause` is a clause that has a
|
|
/// std::tuple<Modifiers, OmpObjectList, bool>.
|
|
/// Helper function to create a typical modifiers-objects clause, where the
|
|
/// commas separating individual modifiers are optional, and the clause
|
|
/// contains a bool member to indicate whether it was fully comma-separated
|
|
/// or not.
|
|
template <bool CommaSeparated, typename MOBClause>
|
|
static inline MOBClause makeMobClause(
|
|
std::list<typename MOBClause::Modifier> &&mods, OmpObjectList &&objs) {
|
|
if (!mods.empty()) {
|
|
return MOBClause{std::move(mods), std::move(objs), CommaSeparated};
|
|
} else {
|
|
using ListTy = std::list<typename MOBClause::Modifier>;
|
|
return MOBClause{std::optional<ListTy>{}, std::move(objs), CommaSeparated};
|
|
}
|
|
}
|
|
|
|
// [5.0] 2.10.1 affinity([aff-modifier:] locator-list)
|
|
// aff-modifier: interator-modifier
|
|
TYPE_PARSER(construct<OmpAffinityClause>(
|
|
maybe(Parser<OmpIterator>{} / ":"), Parser<OmpObjectList>{}))
|
|
|
|
// 2.15.3.1 DEFAULT (PRIVATE | FIRSTPRIVATE | SHARED | NONE)
|
|
TYPE_PARSER(construct<OmpDefaultClause>(
|
|
"PRIVATE" >> pure(OmpDefaultClause::Type::Private) ||
|
|
"FIRSTPRIVATE" >> pure(OmpDefaultClause::Type::Firstprivate) ||
|
|
"SHARED" >> pure(OmpDefaultClause::Type::Shared) ||
|
|
"NONE" >> pure(OmpDefaultClause::Type::None)))
|
|
|
|
// 2.5 PROC_BIND (MASTER | CLOSE | PRIMARY | SPREAD)
|
|
TYPE_PARSER(construct<OmpProcBindClause>(
|
|
"CLOSE" >> pure(OmpProcBindClause::Type::Close) ||
|
|
"MASTER" >> pure(OmpProcBindClause::Type::Master) ||
|
|
"PRIMARY" >> pure(OmpProcBindClause::Type::Primary) ||
|
|
"SPREAD" >> pure(OmpProcBindClause::Type::Spread)))
|
|
|
|
TYPE_PARSER(construct<OmpMapClause>(
|
|
applyFunction<OmpMapClause>(makeMobClause<true>,
|
|
modifierList<OmpMapClause>(","_tok), Parser<OmpObjectList>{}) ||
|
|
applyFunction<OmpMapClause>(makeMobClause<false>,
|
|
modifierList<OmpMapClause>(maybe(","_tok)), Parser<OmpObjectList>{})))
|
|
|
|
// [OpenMP 5.0]
|
|
// 2.19.7.2 defaultmap(implicit-behavior[:variable-category])
|
|
// implicit-behavior -> ALLOC | TO | FROM | TOFROM | FIRSRTPRIVATE | NONE |
|
|
// DEFAULT
|
|
// variable-category -> ALL | SCALAR | AGGREGATE | ALLOCATABLE | POINTER
|
|
TYPE_PARSER(construct<OmpDefaultmapClause>(
|
|
construct<OmpDefaultmapClause::ImplicitBehavior>(
|
|
"ALLOC" >> pure(OmpDefaultmapClause::ImplicitBehavior::Alloc) ||
|
|
"TO"_id >> pure(OmpDefaultmapClause::ImplicitBehavior::To) ||
|
|
"FROM" >> pure(OmpDefaultmapClause::ImplicitBehavior::From) ||
|
|
"TOFROM" >> pure(OmpDefaultmapClause::ImplicitBehavior::Tofrom) ||
|
|
"FIRSTPRIVATE" >>
|
|
pure(OmpDefaultmapClause::ImplicitBehavior::Firstprivate) ||
|
|
"NONE" >> pure(OmpDefaultmapClause::ImplicitBehavior::None) ||
|
|
"DEFAULT" >> pure(OmpDefaultmapClause::ImplicitBehavior::Default)),
|
|
maybe(":" >> nonemptyList(Parser<OmpDefaultmapClause::Modifier>{}))))
|
|
|
|
TYPE_PARSER(construct<OmpScheduleClause::Kind>(
|
|
"STATIC" >> pure(OmpScheduleClause::Kind::Static) ||
|
|
"DYNAMIC" >> pure(OmpScheduleClause::Kind::Dynamic) ||
|
|
"GUIDED" >> pure(OmpScheduleClause::Kind::Guided) ||
|
|
"AUTO" >> pure(OmpScheduleClause::Kind::Auto) ||
|
|
"RUNTIME" >> pure(OmpScheduleClause::Kind::Runtime)))
|
|
|
|
TYPE_PARSER(construct<OmpScheduleClause>(
|
|
maybe(nonemptyList(Parser<OmpScheduleClause::Modifier>{}) / ":"),
|
|
Parser<OmpScheduleClause::Kind>{}, maybe("," >> scalarIntExpr)))
|
|
|
|
// device([ device-modifier :] scalar-integer-expression)
|
|
TYPE_PARSER(construct<OmpDeviceClause>(
|
|
maybe(
|
|
("ANCESTOR" >> pure(OmpDeviceClause::DeviceModifier::Ancestor) ||
|
|
"DEVICE_NUM" >> pure(OmpDeviceClause::DeviceModifier::Device_Num)) /
|
|
":"),
|
|
scalarIntExpr))
|
|
|
|
// device_type(any | host | nohost)
|
|
TYPE_PARSER(construct<OmpDeviceTypeClause>(
|
|
"ANY" >> pure(OmpDeviceTypeClause::Type::Any) ||
|
|
"HOST" >> pure(OmpDeviceTypeClause::Type::Host) ||
|
|
"NOHOST" >> pure(OmpDeviceTypeClause::Type::Nohost)))
|
|
|
|
// 2.12 IF (directive-name-modifier: scalar-logical-expr)
|
|
TYPE_PARSER(construct<OmpIfClause>(
|
|
maybe(
|
|
("PARALLEL" >> pure(OmpIfClause::DirectiveNameModifier::Parallel) ||
|
|
"SIMD" >> pure(OmpIfClause::DirectiveNameModifier::Simd) ||
|
|
"TARGET ENTER DATA" >>
|
|
pure(OmpIfClause::DirectiveNameModifier::TargetEnterData) ||
|
|
"TARGET EXIT DATA" >>
|
|
pure(OmpIfClause::DirectiveNameModifier::TargetExitData) ||
|
|
"TARGET DATA" >>
|
|
pure(OmpIfClause::DirectiveNameModifier::TargetData) ||
|
|
"TARGET UPDATE" >>
|
|
pure(OmpIfClause::DirectiveNameModifier::TargetUpdate) ||
|
|
"TARGET" >> pure(OmpIfClause::DirectiveNameModifier::Target) ||
|
|
"TASK"_id >> pure(OmpIfClause::DirectiveNameModifier::Task) ||
|
|
"TASKLOOP" >> pure(OmpIfClause::DirectiveNameModifier::Taskloop) ||
|
|
"TEAMS" >> pure(OmpIfClause::DirectiveNameModifier::Teams)) /
|
|
":"),
|
|
scalarLogicalExpr))
|
|
|
|
TYPE_PARSER(construct<OmpReductionClause>(
|
|
maybe(nonemptyList(Parser<OmpReductionClause::Modifier>{}) / ":"),
|
|
Parser<OmpObjectList>{}))
|
|
|
|
// OMP 5.0 2.19.5.6 IN_REDUCTION (reduction-identifier: variable-name-list)
|
|
TYPE_PARSER(construct<OmpInReductionClause>(
|
|
Parser<OmpReductionIdentifier>{} / ":", Parser<OmpObjectList>{}))
|
|
|
|
// OMP 5.0 2.11.4 allocate-clause -> ALLOCATE ([allocator:] variable-name-list)
|
|
// OMP 5.2 2.13.4 allocate-clause -> ALLOCATE ([allocate-modifier
|
|
// [, allocate-modifier] :]
|
|
// variable-name-list)
|
|
// allocate-modifier -> allocator | align
|
|
TYPE_PARSER(construct<OmpAllocateClause>(
|
|
maybe(nonemptyList(Parser<OmpAllocateClause::Modifier>{}) / ":"),
|
|
Parser<OmpObjectList>{}))
|
|
|
|
// iteration-offset -> +/- non-negative-constant-expr
|
|
TYPE_PARSER(construct<OmpIterationOffset>(
|
|
Parser<DefinedOperator>{}, scalarIntConstantExpr))
|
|
|
|
// iteration -> iteration-variable [+/- nonnegative-scalar-integer-constant]
|
|
TYPE_PARSER(construct<OmpIteration>(name, maybe(Parser<OmpIterationOffset>{})))
|
|
|
|
TYPE_PARSER(construct<OmpIterationVector>(nonemptyList(Parser<OmpIteration>{})))
|
|
|
|
TYPE_PARSER(construct<OmpDoacross>(
|
|
construct<OmpDoacross>(construct<OmpDoacross::Sink>(
|
|
"SINK"_tok >> ":"_tok >> Parser<OmpIterationVector>{})) ||
|
|
construct<OmpDoacross>(construct<OmpDoacross::Source>("SOURCE"_tok))))
|
|
|
|
TYPE_CONTEXT_PARSER("Omp Depend clause"_en_US,
|
|
construct<OmpDependClause>(
|
|
construct<OmpDependClause>(construct<OmpDependClause::TaskDep>(
|
|
maybe(Parser<OmpIterator>{} / ","_tok),
|
|
Parser<OmpTaskDependenceType>{} / ":", Parser<OmpObjectList>{})) ||
|
|
construct<OmpDependClause>(Parser<OmpDoacross>{})))
|
|
|
|
TYPE_CONTEXT_PARSER("Omp Doacross clause"_en_US,
|
|
construct<OmpDoacrossClause>(Parser<OmpDoacross>{}))
|
|
|
|
TYPE_PARSER(construct<OmpFromClause>(
|
|
applyFunction<OmpFromClause>(makeMobClause<true>,
|
|
modifierList<OmpFromClause>(","_tok), Parser<OmpObjectList>{}) ||
|
|
applyFunction<OmpFromClause>(makeMobClause<false>,
|
|
modifierList<OmpFromClause>(maybe(","_tok)), Parser<OmpObjectList>{})))
|
|
|
|
TYPE_PARSER(construct<OmpToClause>(
|
|
applyFunction<OmpToClause>(makeMobClause<true>,
|
|
modifierList<OmpToClause>(","_tok), Parser<OmpObjectList>{}) ||
|
|
applyFunction<OmpToClause>(makeMobClause<false>,
|
|
modifierList<OmpToClause>(maybe(","_tok)), Parser<OmpObjectList>{})))
|
|
|
|
TYPE_CONTEXT_PARSER("Omp LINEAR clause"_en_US,
|
|
construct<OmpLinearClause>(
|
|
construct<OmpLinearClause>(construct<OmpLinearClause::WithModifier>(
|
|
Parser<OmpLinearModifier>{}, parenthesized(nonemptyList(name)),
|
|
maybe(":" >> scalarIntConstantExpr))) ||
|
|
construct<OmpLinearClause>(construct<OmpLinearClause::WithoutModifier>(
|
|
nonemptyList(name), maybe(":" >> scalarIntConstantExpr)))))
|
|
|
|
// OpenMPv5.2 12.5.2 detach-clause -> DETACH (event-handle)
|
|
TYPE_PARSER(construct<OmpDetachClause>(Parser<OmpObject>{}))
|
|
|
|
// 2.8.1 ALIGNED (list: alignment)
|
|
TYPE_PARSER(construct<OmpAlignedClause>(
|
|
Parser<OmpObjectList>{}, maybe(":" >> scalarIntConstantExpr)))
|
|
|
|
TYPE_PARSER(construct<OmpUpdateClause>(
|
|
construct<OmpUpdateClause>(Parser<OmpDependenceType>{}) ||
|
|
construct<OmpUpdateClause>(Parser<OmpTaskDependenceType>{})))
|
|
|
|
TYPE_PARSER(construct<OmpOrderClause>(
|
|
maybe(nonemptyList(Parser<OmpOrderClause::Modifier>{}) / ":"),
|
|
"CONCURRENT" >> pure(OmpOrderClause::Ordering::Concurrent)))
|
|
|
|
// OMP 5.2 12.6.1 grainsize([ prescriptiveness :] scalar-integer-expression)
|
|
TYPE_PARSER(construct<OmpGrainsizeClause>(
|
|
maybe("STRICT" >> pure(OmpGrainsizeClause::Prescriptiveness::Strict) / ":"),
|
|
scalarIntExpr))
|
|
|
|
// OMP 5.2 12.6.2 num_tasks([ prescriptiveness :] scalar-integer-expression)
|
|
TYPE_PARSER(construct<OmpNumTasksClause>(
|
|
maybe("STRICT" >> pure(OmpNumTasksClause::Prescriptiveness::Strict) / ":"),
|
|
scalarIntExpr))
|
|
|
|
TYPE_PARSER(
|
|
construct<OmpObject>(designator) || construct<OmpObject>("/" >> name / "/"))
|
|
|
|
// OMP 5.0 2.19.4.5 LASTPRIVATE ([lastprivate-modifier :] list)
|
|
TYPE_PARSER(construct<OmpLastprivateClause>(
|
|
maybe("CONDITIONAL" >>
|
|
pure(OmpLastprivateClause::LastprivateModifier::Conditional) / ":"),
|
|
Parser<OmpObjectList>{}))
|
|
|
|
// OMP 5.2 11.7.1 BIND ( PARALLEL | TEAMS | THREAD )
|
|
TYPE_PARSER(construct<OmpBindClause>(
|
|
"PARALLEL" >> pure(OmpBindClause::Type::Parallel) ||
|
|
"TEAMS" >> pure(OmpBindClause::Type::Teams) ||
|
|
"THREAD" >> pure(OmpBindClause::Type::Thread)))
|
|
|
|
TYPE_PARSER(
|
|
"ACQUIRE" >> construct<OmpClause>(construct<OmpClause::Acquire>()) ||
|
|
"ACQ_REL" >> construct<OmpClause>(construct<OmpClause::AcqRel>()) ||
|
|
"AFFINITY" >> construct<OmpClause>(construct<OmpClause::Affinity>(
|
|
parenthesized(Parser<OmpAffinityClause>{}))) ||
|
|
"ALIGNED" >> construct<OmpClause>(construct<OmpClause::Aligned>(
|
|
parenthesized(Parser<OmpAlignedClause>{}))) ||
|
|
"ALLOCATE" >> construct<OmpClause>(construct<OmpClause::Allocate>(
|
|
parenthesized(Parser<OmpAllocateClause>{}))) ||
|
|
"ALLOCATOR" >> construct<OmpClause>(construct<OmpClause::Allocator>(
|
|
parenthesized(scalarIntExpr))) ||
|
|
"ATOMIC_DEFAULT_MEM_ORDER" >>
|
|
construct<OmpClause>(construct<OmpClause::AtomicDefaultMemOrder>(
|
|
parenthesized(Parser<OmpAtomicDefaultMemOrderClause>{}))) ||
|
|
"BIND" >> construct<OmpClause>(construct<OmpClause::Bind>(
|
|
parenthesized(Parser<OmpBindClause>{}))) ||
|
|
"COLLAPSE" >> construct<OmpClause>(construct<OmpClause::Collapse>(
|
|
parenthesized(scalarIntConstantExpr))) ||
|
|
"COPYIN" >> construct<OmpClause>(construct<OmpClause::Copyin>(
|
|
parenthesized(Parser<OmpObjectList>{}))) ||
|
|
"COPYPRIVATE" >> construct<OmpClause>(construct<OmpClause::Copyprivate>(
|
|
(parenthesized(Parser<OmpObjectList>{})))) ||
|
|
"DEFAULT"_id >> construct<OmpClause>(construct<OmpClause::Default>(
|
|
parenthesized(Parser<OmpDefaultClause>{}))) ||
|
|
"DEFAULTMAP" >> construct<OmpClause>(construct<OmpClause::Defaultmap>(
|
|
parenthesized(Parser<OmpDefaultmapClause>{}))) ||
|
|
"DEPEND" >> construct<OmpClause>(construct<OmpClause::Depend>(
|
|
parenthesized(Parser<OmpDependClause>{}))) ||
|
|
"DESTROY" >>
|
|
construct<OmpClause>(construct<OmpClause::Destroy>(maybe(parenthesized(
|
|
construct<OmpDestroyClause>(Parser<OmpObject>{}))))) ||
|
|
"DEVICE" >> construct<OmpClause>(construct<OmpClause::Device>(
|
|
parenthesized(Parser<OmpDeviceClause>{}))) ||
|
|
"DEVICE_TYPE" >> construct<OmpClause>(construct<OmpClause::DeviceType>(
|
|
parenthesized(Parser<OmpDeviceTypeClause>{}))) ||
|
|
"DIST_SCHEDULE" >>
|
|
construct<OmpClause>(construct<OmpClause::DistSchedule>(
|
|
parenthesized("STATIC" >> maybe("," >> scalarIntExpr)))) ||
|
|
"DOACROSS" >>
|
|
construct<OmpClause>(parenthesized(Parser<OmpDoacrossClause>{})) ||
|
|
"DYNAMIC_ALLOCATORS" >>
|
|
construct<OmpClause>(construct<OmpClause::DynamicAllocators>()) ||
|
|
"ENTER" >> construct<OmpClause>(construct<OmpClause::Enter>(
|
|
parenthesized(Parser<OmpObjectList>{}))) ||
|
|
"EXCLUSIVE" >> construct<OmpClause>(construct<OmpClause::Exclusive>(
|
|
parenthesized(Parser<OmpObjectList>{}))) ||
|
|
"FILTER" >> construct<OmpClause>(construct<OmpClause::Filter>(
|
|
parenthesized(scalarIntExpr))) ||
|
|
"FINAL" >> construct<OmpClause>(construct<OmpClause::Final>(
|
|
parenthesized(scalarLogicalExpr))) ||
|
|
"FIRSTPRIVATE" >> construct<OmpClause>(construct<OmpClause::Firstprivate>(
|
|
parenthesized(Parser<OmpObjectList>{}))) ||
|
|
"FROM" >> construct<OmpClause>(construct<OmpClause::From>(
|
|
parenthesized(Parser<OmpFromClause>{}))) ||
|
|
"FULL" >> construct<OmpClause>(construct<OmpClause::Full>()) ||
|
|
"GRAINSIZE" >> construct<OmpClause>(construct<OmpClause::Grainsize>(
|
|
parenthesized(Parser<OmpGrainsizeClause>{}))) ||
|
|
"HAS_DEVICE_ADDR" >>
|
|
construct<OmpClause>(construct<OmpClause::HasDeviceAddr>(
|
|
parenthesized(Parser<OmpObjectList>{}))) ||
|
|
"HINT" >> construct<OmpClause>(
|
|
construct<OmpClause::Hint>(parenthesized(constantExpr))) ||
|
|
"IF" >> construct<OmpClause>(construct<OmpClause::If>(
|
|
parenthesized(Parser<OmpIfClause>{}))) ||
|
|
"INBRANCH" >> construct<OmpClause>(construct<OmpClause::Inbranch>()) ||
|
|
"INCLUSIVE" >> construct<OmpClause>(construct<OmpClause::Inclusive>(
|
|
parenthesized(Parser<OmpObjectList>{}))) ||
|
|
"IS_DEVICE_PTR" >> construct<OmpClause>(construct<OmpClause::IsDevicePtr>(
|
|
parenthesized(Parser<OmpObjectList>{}))) ||
|
|
"LASTPRIVATE" >> construct<OmpClause>(construct<OmpClause::Lastprivate>(
|
|
parenthesized(Parser<OmpLastprivateClause>{}))) ||
|
|
"LINEAR" >> construct<OmpClause>(construct<OmpClause::Linear>(
|
|
parenthesized(Parser<OmpLinearClause>{}))) ||
|
|
"LINK" >> construct<OmpClause>(construct<OmpClause::Link>(
|
|
parenthesized(Parser<OmpObjectList>{}))) ||
|
|
"MAP" >> construct<OmpClause>(construct<OmpClause::Map>(
|
|
parenthesized(Parser<OmpMapClause>{}))) ||
|
|
"MERGEABLE" >> construct<OmpClause>(construct<OmpClause::Mergeable>()) ||
|
|
"NOGROUP" >> construct<OmpClause>(construct<OmpClause::Nogroup>()) ||
|
|
"NONTEMPORAL" >> construct<OmpClause>(construct<OmpClause::Nontemporal>(
|
|
parenthesized(nonemptyList(name)))) ||
|
|
"NOTINBRANCH" >>
|
|
construct<OmpClause>(construct<OmpClause::Notinbranch>()) ||
|
|
"NOWAIT" >> construct<OmpClause>(construct<OmpClause::Nowait>()) ||
|
|
"NUM_TASKS" >> construct<OmpClause>(construct<OmpClause::NumTasks>(
|
|
parenthesized(Parser<OmpNumTasksClause>{}))) ||
|
|
"NUM_TEAMS" >> construct<OmpClause>(construct<OmpClause::NumTeams>(
|
|
parenthesized(scalarIntExpr))) ||
|
|
"NUM_THREADS" >> construct<OmpClause>(construct<OmpClause::NumThreads>(
|
|
parenthesized(scalarIntExpr))) ||
|
|
"ORDER" >> construct<OmpClause>(construct<OmpClause::Order>(
|
|
parenthesized(Parser<OmpOrderClause>{}))) ||
|
|
"ORDERED" >> construct<OmpClause>(construct<OmpClause::Ordered>(
|
|
maybe(parenthesized(scalarIntConstantExpr)))) ||
|
|
"PARTIAL" >> construct<OmpClause>(construct<OmpClause::Partial>(
|
|
maybe(parenthesized(scalarIntConstantExpr)))) ||
|
|
"PRIORITY" >> construct<OmpClause>(construct<OmpClause::Priority>(
|
|
parenthesized(scalarIntExpr))) ||
|
|
"PRIVATE" >> construct<OmpClause>(construct<OmpClause::Private>(
|
|
parenthesized(Parser<OmpObjectList>{}))) ||
|
|
"PROC_BIND" >> construct<OmpClause>(construct<OmpClause::ProcBind>(
|
|
parenthesized(Parser<OmpProcBindClause>{}))) ||
|
|
"REDUCTION" >> construct<OmpClause>(construct<OmpClause::Reduction>(
|
|
parenthesized(Parser<OmpReductionClause>{}))) ||
|
|
"IN_REDUCTION" >> construct<OmpClause>(construct<OmpClause::InReduction>(
|
|
parenthesized(Parser<OmpInReductionClause>{}))) ||
|
|
"DETACH" >> construct<OmpClause>(construct<OmpClause::Detach>(
|
|
parenthesized(Parser<OmpDetachClause>{}))) ||
|
|
"TASK_REDUCTION" >>
|
|
construct<OmpClause>(construct<OmpClause::TaskReduction>(
|
|
parenthesized(Parser<OmpReductionClause>{}))) ||
|
|
"RELAXED" >> construct<OmpClause>(construct<OmpClause::Relaxed>()) ||
|
|
"RELEASE" >> construct<OmpClause>(construct<OmpClause::Release>()) ||
|
|
"REVERSE_OFFLOAD" >>
|
|
construct<OmpClause>(construct<OmpClause::ReverseOffload>()) ||
|
|
"SAFELEN" >> construct<OmpClause>(construct<OmpClause::Safelen>(
|
|
parenthesized(scalarIntConstantExpr))) ||
|
|
"SCHEDULE" >> construct<OmpClause>(construct<OmpClause::Schedule>(
|
|
parenthesized(Parser<OmpScheduleClause>{}))) ||
|
|
"SEQ_CST" >> construct<OmpClause>(construct<OmpClause::SeqCst>()) ||
|
|
"SHARED" >> construct<OmpClause>(construct<OmpClause::Shared>(
|
|
parenthesized(Parser<OmpObjectList>{}))) ||
|
|
"SIMD"_id >> construct<OmpClause>(construct<OmpClause::Simd>()) ||
|
|
"SIMDLEN" >> construct<OmpClause>(construct<OmpClause::Simdlen>(
|
|
parenthesized(scalarIntConstantExpr))) ||
|
|
"SIZES" >> construct<OmpClause>(construct<OmpClause::Sizes>(
|
|
parenthesized(nonemptyList(scalarIntExpr)))) ||
|
|
"PERMUTATION" >> construct<OmpClause>(construct<OmpClause::Permutation>(
|
|
parenthesized(nonemptyList(scalarIntExpr)))) ||
|
|
"THREADS" >> construct<OmpClause>(construct<OmpClause::Threads>()) ||
|
|
"THREAD_LIMIT" >> construct<OmpClause>(construct<OmpClause::ThreadLimit>(
|
|
parenthesized(scalarIntExpr))) ||
|
|
"TO" >> construct<OmpClause>(construct<OmpClause::To>(
|
|
parenthesized(Parser<OmpToClause>{}))) ||
|
|
"USE_DEVICE_PTR" >> construct<OmpClause>(construct<OmpClause::UseDevicePtr>(
|
|
parenthesized(Parser<OmpObjectList>{}))) ||
|
|
"USE_DEVICE_ADDR" >>
|
|
construct<OmpClause>(construct<OmpClause::UseDeviceAddr>(
|
|
parenthesized(Parser<OmpObjectList>{}))) ||
|
|
"UNIFIED_ADDRESS" >>
|
|
construct<OmpClause>(construct<OmpClause::UnifiedAddress>()) ||
|
|
"UNIFIED_SHARED_MEMORY" >>
|
|
construct<OmpClause>(construct<OmpClause::UnifiedSharedMemory>()) ||
|
|
"UNIFORM" >> construct<OmpClause>(construct<OmpClause::Uniform>(
|
|
parenthesized(nonemptyList(name)))) ||
|
|
"UNTIED" >> construct<OmpClause>(construct<OmpClause::Untied>()) ||
|
|
"UPDATE" >> construct<OmpClause>(construct<OmpClause::Update>(
|
|
parenthesized(Parser<OmpUpdateClause>{}))))
|
|
|
|
// [Clause, [Clause], ...]
|
|
TYPE_PARSER(sourced(construct<OmpClauseList>(
|
|
many(maybe(","_tok) >> sourced(Parser<OmpClause>{})))))
|
|
|
|
// 2.1 (variable | /common-block | array-sections)
|
|
TYPE_PARSER(construct<OmpObjectList>(nonemptyList(Parser<OmpObject>{})))
|
|
|
|
// Omp directives enclosing do loop
|
|
TYPE_PARSER(sourced(construct<OmpLoopDirective>(first(
|
|
"DISTRIBUTE PARALLEL DO SIMD" >>
|
|
pure(llvm::omp::Directive::OMPD_distribute_parallel_do_simd),
|
|
"DISTRIBUTE PARALLEL DO" >>
|
|
pure(llvm::omp::Directive::OMPD_distribute_parallel_do),
|
|
"DISTRIBUTE SIMD" >> pure(llvm::omp::Directive::OMPD_distribute_simd),
|
|
"DISTRIBUTE" >> pure(llvm::omp::Directive::OMPD_distribute),
|
|
"DO SIMD" >> pure(llvm::omp::Directive::OMPD_do_simd),
|
|
"DO" >> pure(llvm::omp::Directive::OMPD_do),
|
|
"LOOP" >> pure(llvm::omp::Directive::OMPD_loop),
|
|
"MASKED TASKLOOP SIMD" >>
|
|
pure(llvm::omp::Directive::OMPD_masked_taskloop_simd),
|
|
"MASKED TASKLOOP" >> pure(llvm::omp::Directive::OMPD_masked_taskloop),
|
|
"MASTER TASKLOOP SIMD" >>
|
|
pure(llvm::omp::Directive::OMPD_master_taskloop_simd),
|
|
"MASTER TASKLOOP" >> pure(llvm::omp::Directive::OMPD_master_taskloop),
|
|
"PARALLEL DO SIMD" >> pure(llvm::omp::Directive::OMPD_parallel_do_simd),
|
|
"PARALLEL DO" >> pure(llvm::omp::Directive::OMPD_parallel_do),
|
|
"PARALLEL MASKED TASKLOOP SIMD" >>
|
|
pure(llvm::omp::Directive::OMPD_parallel_masked_taskloop_simd),
|
|
"PARALLEL MASKED TASKLOOP" >>
|
|
pure(llvm::omp::Directive::OMPD_parallel_masked_taskloop),
|
|
"PARALLEL MASTER TASKLOOP SIMD" >>
|
|
pure(llvm::omp::Directive::OMPD_parallel_master_taskloop_simd),
|
|
"PARALLEL MASTER TASKLOOP" >>
|
|
pure(llvm::omp::Directive::OMPD_parallel_master_taskloop),
|
|
"SIMD" >> pure(llvm::omp::Directive::OMPD_simd),
|
|
"TARGET LOOP" >> pure(llvm::omp::Directive::OMPD_target_loop),
|
|
"TARGET PARALLEL DO SIMD" >>
|
|
pure(llvm::omp::Directive::OMPD_target_parallel_do_simd),
|
|
"TARGET PARALLEL DO" >> pure(llvm::omp::Directive::OMPD_target_parallel_do),
|
|
"TARGET PARALLEL LOOP" >>
|
|
pure(llvm::omp::Directive::OMPD_target_parallel_loop),
|
|
"TARGET SIMD" >> pure(llvm::omp::Directive::OMPD_target_simd),
|
|
"TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD" >>
|
|
pure(llvm::omp::Directive::
|
|
OMPD_target_teams_distribute_parallel_do_simd),
|
|
"TARGET TEAMS DISTRIBUTE PARALLEL DO" >>
|
|
pure(llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do),
|
|
"TARGET TEAMS DISTRIBUTE SIMD" >>
|
|
pure(llvm::omp::Directive::OMPD_target_teams_distribute_simd),
|
|
"TARGET TEAMS DISTRIBUTE" >>
|
|
pure(llvm::omp::Directive::OMPD_target_teams_distribute),
|
|
"TARGET TEAMS LOOP" >> pure(llvm::omp::Directive::OMPD_target_teams_loop),
|
|
"TASKLOOP SIMD" >> pure(llvm::omp::Directive::OMPD_taskloop_simd),
|
|
"TASKLOOP" >> pure(llvm::omp::Directive::OMPD_taskloop),
|
|
"TEAMS DISTRIBUTE PARALLEL DO SIMD" >>
|
|
pure(llvm::omp::Directive::OMPD_teams_distribute_parallel_do_simd),
|
|
"TEAMS DISTRIBUTE PARALLEL DO" >>
|
|
pure(llvm::omp::Directive::OMPD_teams_distribute_parallel_do),
|
|
"TEAMS DISTRIBUTE SIMD" >>
|
|
pure(llvm::omp::Directive::OMPD_teams_distribute_simd),
|
|
"TEAMS DISTRIBUTE" >> pure(llvm::omp::Directive::OMPD_teams_distribute),
|
|
"TEAMS LOOP" >> pure(llvm::omp::Directive::OMPD_teams_loop),
|
|
"TILE" >> pure(llvm::omp::Directive::OMPD_tile),
|
|
"UNROLL" >> pure(llvm::omp::Directive::OMPD_unroll)))))
|
|
|
|
TYPE_PARSER(sourced(construct<OmpBeginLoopDirective>(
|
|
sourced(Parser<OmpLoopDirective>{}), Parser<OmpClauseList>{})))
|
|
|
|
// 2.14.1 construct-type-clause -> PARALLEL | SECTIONS | DO | TASKGROUP
|
|
TYPE_PARSER(sourced(construct<OmpCancelType>(
|
|
first("PARALLEL" >> pure(OmpCancelType::Type::Parallel),
|
|
"SECTIONS" >> pure(OmpCancelType::Type::Sections),
|
|
"DO" >> pure(OmpCancelType::Type::Do),
|
|
"TASKGROUP" >> pure(OmpCancelType::Type::Taskgroup)))))
|
|
|
|
// 2.14.2 Cancellation Point construct
|
|
TYPE_PARSER(sourced(construct<OpenMPCancellationPointConstruct>(
|
|
verbatim("CANCELLATION POINT"_tok), Parser<OmpCancelType>{})))
|
|
|
|
// 2.14.1 Cancel construct
|
|
TYPE_PARSER(sourced(construct<OpenMPCancelConstruct>(verbatim("CANCEL"_tok),
|
|
Parser<OmpCancelType>{}, maybe("IF" >> parenthesized(scalarLogicalExpr)))))
|
|
|
|
// 2.17.7 Atomic construct/2.17.8 Flush construct [OpenMP 5.0]
|
|
// memory-order-clause ->
|
|
// seq_cst
|
|
// acq_rel
|
|
// release
|
|
// acquire
|
|
// relaxed
|
|
TYPE_PARSER(sourced(construct<OmpMemoryOrderClause>(
|
|
sourced("SEQ_CST" >> construct<OmpClause>(construct<OmpClause::SeqCst>()) ||
|
|
"ACQ_REL" >> construct<OmpClause>(construct<OmpClause::AcqRel>()) ||
|
|
"RELEASE" >> construct<OmpClause>(construct<OmpClause::Release>()) ||
|
|
"ACQUIRE" >> construct<OmpClause>(construct<OmpClause::Acquire>()) ||
|
|
"RELAXED" >> construct<OmpClause>(construct<OmpClause::Relaxed>())))))
|
|
|
|
// 2.4 Requires construct [OpenMP 5.0]
|
|
// atomic-default-mem-order-clause ->
|
|
// seq_cst
|
|
// acq_rel
|
|
// relaxed
|
|
TYPE_PARSER(construct<OmpAtomicDefaultMemOrderClause>(
|
|
"SEQ_CST" >> pure(common::OmpAtomicDefaultMemOrderType::SeqCst) ||
|
|
"ACQ_REL" >> pure(common::OmpAtomicDefaultMemOrderType::AcqRel) ||
|
|
"RELAXED" >> pure(common::OmpAtomicDefaultMemOrderType::Relaxed)))
|
|
|
|
// 2.17.7 Atomic construct
|
|
// atomic-clause -> memory-order-clause | HINT(hint-expression)
|
|
TYPE_PARSER(sourced(construct<OmpAtomicClause>(
|
|
construct<OmpAtomicClause>(Parser<OmpMemoryOrderClause>{}) ||
|
|
construct<OmpAtomicClause>("HINT" >>
|
|
sourced(construct<OmpClause>(
|
|
construct<OmpClause::Hint>(parenthesized(constantExpr))))))))
|
|
|
|
// atomic-clause-list -> [atomic-clause, [atomic-clause], ...]
|
|
TYPE_PARSER(sourced(construct<OmpAtomicClauseList>(
|
|
many(maybe(","_tok) >> sourced(Parser<OmpAtomicClause>{})))))
|
|
|
|
TYPE_PARSER(sourced(construct<OpenMPDepobjConstruct>(verbatim("DEPOBJ"_tok),
|
|
parenthesized(Parser<OmpObject>{}), sourced(Parser<OmpClause>{}))))
|
|
|
|
TYPE_PARSER(sourced(construct<OpenMPFlushConstruct>(verbatim("FLUSH"_tok),
|
|
many(maybe(","_tok) >> sourced(Parser<OmpMemoryOrderClause>{})),
|
|
maybe(parenthesized(Parser<OmpObjectList>{})))))
|
|
|
|
// Simple Standalone Directives
|
|
TYPE_PARSER(sourced(construct<OmpSimpleStandaloneDirective>(first(
|
|
"BARRIER" >> pure(llvm::omp::Directive::OMPD_barrier),
|
|
"ORDERED" >> pure(llvm::omp::Directive::OMPD_ordered),
|
|
"SCAN" >> pure(llvm::omp::Directive::OMPD_scan),
|
|
"TARGET ENTER DATA" >> pure(llvm::omp::Directive::OMPD_target_enter_data),
|
|
"TARGET EXIT DATA" >> pure(llvm::omp::Directive::OMPD_target_exit_data),
|
|
"TARGET UPDATE" >> pure(llvm::omp::Directive::OMPD_target_update),
|
|
"TASKWAIT" >> pure(llvm::omp::Directive::OMPD_taskwait),
|
|
"TASKYIELD" >> pure(llvm::omp::Directive::OMPD_taskyield)))))
|
|
|
|
TYPE_PARSER(sourced(construct<OpenMPSimpleStandaloneConstruct>(
|
|
Parser<OmpSimpleStandaloneDirective>{}, Parser<OmpClauseList>{})))
|
|
|
|
// Standalone Constructs
|
|
TYPE_PARSER(
|
|
sourced(construct<OpenMPStandaloneConstruct>(
|
|
Parser<OpenMPSimpleStandaloneConstruct>{}) ||
|
|
construct<OpenMPStandaloneConstruct>(Parser<OpenMPFlushConstruct>{}) ||
|
|
construct<OpenMPStandaloneConstruct>(Parser<OpenMPCancelConstruct>{}) ||
|
|
construct<OpenMPStandaloneConstruct>(
|
|
Parser<OpenMPCancellationPointConstruct>{}) ||
|
|
construct<OpenMPStandaloneConstruct>(Parser<OpenMPDepobjConstruct>{})) /
|
|
endOfLine)
|
|
|
|
// Directives enclosing structured-block
|
|
TYPE_PARSER(construct<OmpBlockDirective>(first(
|
|
"MASKED" >> pure(llvm::omp::Directive::OMPD_masked),
|
|
"MASTER" >> pure(llvm::omp::Directive::OMPD_master),
|
|
"ORDERED" >> pure(llvm::omp::Directive::OMPD_ordered),
|
|
"PARALLEL MASKED" >> pure(llvm::omp::Directive::OMPD_parallel_masked),
|
|
"PARALLEL MASTER" >> pure(llvm::omp::Directive::OMPD_parallel_master),
|
|
"PARALLEL WORKSHARE" >> pure(llvm::omp::Directive::OMPD_parallel_workshare),
|
|
"PARALLEL" >> pure(llvm::omp::Directive::OMPD_parallel),
|
|
"SCOPE" >> pure(llvm::omp::Directive::OMPD_scope),
|
|
"SINGLE" >> pure(llvm::omp::Directive::OMPD_single),
|
|
"TARGET DATA" >> pure(llvm::omp::Directive::OMPD_target_data),
|
|
"TARGET PARALLEL" >> pure(llvm::omp::Directive::OMPD_target_parallel),
|
|
"TARGET TEAMS" >> pure(llvm::omp::Directive::OMPD_target_teams),
|
|
"TARGET" >> pure(llvm::omp::Directive::OMPD_target),
|
|
"TASK"_id >> pure(llvm::omp::Directive::OMPD_task),
|
|
"TASKGROUP" >> pure(llvm::omp::Directive::OMPD_taskgroup),
|
|
"TEAMS" >> pure(llvm::omp::Directive::OMPD_teams),
|
|
"WORKSHARE" >> pure(llvm::omp::Directive::OMPD_workshare))))
|
|
|
|
TYPE_PARSER(sourced(construct<OmpBeginBlockDirective>(
|
|
sourced(Parser<OmpBlockDirective>{}), Parser<OmpClauseList>{})))
|
|
|
|
TYPE_PARSER(construct<OmpReductionInitializerClause>(
|
|
"INITIALIZER" >> parenthesized("OMP_PRIV =" >> expr)))
|
|
|
|
// 2.16 Declare Reduction Construct
|
|
TYPE_PARSER(sourced(construct<OpenMPDeclareReductionConstruct>(
|
|
verbatim("DECLARE REDUCTION"_tok),
|
|
"(" >> Parser<OmpReductionIdentifier>{} / ":",
|
|
nonemptyList(Parser<DeclarationTypeSpec>{}) / ":",
|
|
Parser<OmpReductionCombiner>{} / ")",
|
|
maybe(Parser<OmpReductionInitializerClause>{}))))
|
|
|
|
// declare-target with list
|
|
TYPE_PARSER(sourced(construct<OmpDeclareTargetWithList>(
|
|
parenthesized(Parser<OmpObjectList>{}))))
|
|
|
|
// declare-target with clause
|
|
TYPE_PARSER(
|
|
sourced(construct<OmpDeclareTargetWithClause>(Parser<OmpClauseList>{})))
|
|
|
|
// declare-target-specifier
|
|
TYPE_PARSER(
|
|
construct<OmpDeclareTargetSpecifier>(Parser<OmpDeclareTargetWithList>{}) ||
|
|
construct<OmpDeclareTargetSpecifier>(Parser<OmpDeclareTargetWithClause>{}))
|
|
|
|
// 2.10.6 Declare Target Construct
|
|
TYPE_PARSER(sourced(construct<OpenMPDeclareTargetConstruct>(
|
|
verbatim("DECLARE TARGET"_tok), Parser<OmpDeclareTargetSpecifier>{})))
|
|
|
|
// declare-mapper-specifier
|
|
TYPE_PARSER(construct<OmpDeclareMapperSpecifier>(
|
|
maybe(name / ":" / !":"_tok), typeSpec / "::", name))
|
|
|
|
// OpenMP 5.2: 5.8.8 Declare Mapper Construct
|
|
TYPE_PARSER(sourced(construct<OpenMPDeclareMapperConstruct>(
|
|
verbatim("DECLARE MAPPER"_tok),
|
|
"(" >> Parser<OmpDeclareMapperSpecifier>{} / ")", Parser<OmpClauseList>{})))
|
|
|
|
TYPE_PARSER(construct<OmpReductionCombiner>(Parser<AssignmentStmt>{}) ||
|
|
construct<OmpReductionCombiner>(
|
|
construct<OmpReductionCombiner::FunctionCombiner>(
|
|
construct<Call>(Parser<ProcedureDesignator>{},
|
|
parenthesized(optionalList(actualArgSpec))))))
|
|
|
|
// 2.17.7 atomic -> ATOMIC [clause [,]] atomic-clause [[,] clause] |
|
|
// ATOMIC [clause]
|
|
// clause -> memory-order-clause | HINT(hint-expression)
|
|
// memory-order-clause -> SEQ_CST | ACQ_REL | RELEASE | ACQUIRE | RELAXED
|
|
// atomic-clause -> READ | WRITE | UPDATE | CAPTURE
|
|
|
|
// OMP END ATOMIC
|
|
TYPE_PARSER(construct<OmpEndAtomic>(startOmpLine >> "END ATOMIC"_tok))
|
|
|
|
// OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] READ [MEMORY-ORDER-CLAUSE-LIST]
|
|
TYPE_PARSER("ATOMIC" >>
|
|
sourced(construct<OmpAtomicRead>(
|
|
Parser<OmpAtomicClauseList>{} / maybe(","_tok), verbatim("READ"_tok),
|
|
Parser<OmpAtomicClauseList>{} / endOmpLine, statement(assignmentStmt),
|
|
maybe(Parser<OmpEndAtomic>{} / endOmpLine))))
|
|
|
|
// OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] CAPTURE [MEMORY-ORDER-CLAUSE-LIST]
|
|
TYPE_PARSER("ATOMIC" >>
|
|
sourced(construct<OmpAtomicCapture>(
|
|
Parser<OmpAtomicClauseList>{} / maybe(","_tok), verbatim("CAPTURE"_tok),
|
|
Parser<OmpAtomicClauseList>{} / endOmpLine, statement(assignmentStmt),
|
|
statement(assignmentStmt), Parser<OmpEndAtomic>{} / endOmpLine)))
|
|
|
|
// OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] UPDATE [MEMORY-ORDER-CLAUSE-LIST]
|
|
TYPE_PARSER("ATOMIC" >>
|
|
sourced(construct<OmpAtomicUpdate>(
|
|
Parser<OmpAtomicClauseList>{} / maybe(","_tok), verbatim("UPDATE"_tok),
|
|
Parser<OmpAtomicClauseList>{} / endOmpLine, statement(assignmentStmt),
|
|
maybe(Parser<OmpEndAtomic>{} / endOmpLine))))
|
|
|
|
// OMP ATOMIC [atomic-clause-list]
|
|
TYPE_PARSER(sourced(construct<OmpAtomic>(verbatim("ATOMIC"_tok),
|
|
Parser<OmpAtomicClauseList>{} / endOmpLine, statement(assignmentStmt),
|
|
maybe(Parser<OmpEndAtomic>{} / endOmpLine))))
|
|
|
|
// OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] WRITE [MEMORY-ORDER-CLAUSE-LIST]
|
|
TYPE_PARSER("ATOMIC" >>
|
|
sourced(construct<OmpAtomicWrite>(
|
|
Parser<OmpAtomicClauseList>{} / maybe(","_tok), verbatim("WRITE"_tok),
|
|
Parser<OmpAtomicClauseList>{} / endOmpLine, statement(assignmentStmt),
|
|
maybe(Parser<OmpEndAtomic>{} / endOmpLine))))
|
|
|
|
// Atomic Construct
|
|
TYPE_PARSER(construct<OpenMPAtomicConstruct>(Parser<OmpAtomicRead>{}) ||
|
|
construct<OpenMPAtomicConstruct>(Parser<OmpAtomicCapture>{}) ||
|
|
construct<OpenMPAtomicConstruct>(Parser<OmpAtomicWrite>{}) ||
|
|
construct<OpenMPAtomicConstruct>(Parser<OmpAtomicUpdate>{}) ||
|
|
construct<OpenMPAtomicConstruct>(Parser<OmpAtomic>{}))
|
|
|
|
// 2.13.2 OMP CRITICAL
|
|
TYPE_PARSER(startOmpLine >>
|
|
sourced(construct<OmpEndCriticalDirective>(
|
|
verbatim("END CRITICAL"_tok), maybe(parenthesized(name)))) /
|
|
endOmpLine)
|
|
TYPE_PARSER(sourced(construct<OmpCriticalDirective>(verbatim("CRITICAL"_tok),
|
|
maybe(parenthesized(name)), Parser<OmpClauseList>{})) /
|
|
endOmpLine)
|
|
|
|
TYPE_PARSER(construct<OpenMPCriticalConstruct>(
|
|
Parser<OmpCriticalDirective>{}, block, Parser<OmpEndCriticalDirective>{}))
|
|
|
|
// 2.11.3 Executable Allocate directive
|
|
TYPE_PARSER(
|
|
sourced(construct<OpenMPExecutableAllocate>(verbatim("ALLOCATE"_tok),
|
|
maybe(parenthesized(Parser<OmpObjectList>{})), Parser<OmpClauseList>{},
|
|
maybe(nonemptyList(Parser<OpenMPDeclarativeAllocate>{})) / endOmpLine,
|
|
statement(allocateStmt))))
|
|
|
|
// 6.7 Allocators construct [OpenMP 5.2]
|
|
// allocators-construct -> ALLOCATORS [allocate-clause [,]]
|
|
// allocate-stmt
|
|
// [omp-end-allocators-construct]
|
|
TYPE_PARSER(sourced(construct<OpenMPAllocatorsConstruct>(
|
|
verbatim("ALLOCATORS"_tok), Parser<OmpClauseList>{} / endOmpLine,
|
|
statement(allocateStmt), maybe(Parser<OmpEndAllocators>{} / endOmpLine))))
|
|
|
|
TYPE_PARSER(construct<OmpEndAllocators>(startOmpLine >> "END ALLOCATORS"_tok))
|
|
|
|
// 2.8.2 Declare Simd construct
|
|
TYPE_PARSER(
|
|
sourced(construct<OpenMPDeclareSimdConstruct>(verbatim("DECLARE SIMD"_tok),
|
|
maybe(parenthesized(name)), Parser<OmpClauseList>{})))
|
|
|
|
// 2.4 Requires construct
|
|
TYPE_PARSER(sourced(construct<OpenMPRequiresConstruct>(
|
|
verbatim("REQUIRES"_tok), Parser<OmpClauseList>{})))
|
|
|
|
// 2.15.2 Threadprivate directive
|
|
TYPE_PARSER(sourced(construct<OpenMPThreadprivate>(
|
|
verbatim("THREADPRIVATE"_tok), parenthesized(Parser<OmpObjectList>{}))))
|
|
|
|
// 2.11.3 Declarative Allocate directive
|
|
TYPE_PARSER(
|
|
sourced(construct<OpenMPDeclarativeAllocate>(verbatim("ALLOCATE"_tok),
|
|
parenthesized(Parser<OmpObjectList>{}), Parser<OmpClauseList>{})) /
|
|
lookAhead(endOmpLine / !statement(allocateStmt)))
|
|
|
|
// Declarative constructs
|
|
TYPE_PARSER(startOmpLine >>
|
|
withMessage("expected OpenMP construct"_err_en_US,
|
|
sourced(construct<OpenMPDeclarativeConstruct>(
|
|
Parser<OpenMPDeclareReductionConstruct>{}) ||
|
|
construct<OpenMPDeclarativeConstruct>(
|
|
Parser<OpenMPDeclareMapperConstruct>{}) ||
|
|
construct<OpenMPDeclarativeConstruct>(
|
|
Parser<OpenMPDeclareSimdConstruct>{}) ||
|
|
construct<OpenMPDeclarativeConstruct>(
|
|
Parser<OpenMPDeclareTargetConstruct>{}) ||
|
|
construct<OpenMPDeclarativeConstruct>(
|
|
Parser<OpenMPDeclarativeAllocate>{}) ||
|
|
construct<OpenMPDeclarativeConstruct>(
|
|
Parser<OpenMPRequiresConstruct>{}) ||
|
|
construct<OpenMPDeclarativeConstruct>(
|
|
Parser<OpenMPThreadprivate>{})) /
|
|
endOmpLine))
|
|
|
|
// Block Construct
|
|
TYPE_PARSER(construct<OpenMPBlockConstruct>(
|
|
Parser<OmpBeginBlockDirective>{} / endOmpLine, block,
|
|
Parser<OmpEndBlockDirective>{} / endOmpLine))
|
|
|
|
// OMP SECTIONS Directive
|
|
TYPE_PARSER(construct<OmpSectionsDirective>(first(
|
|
"SECTIONS" >> pure(llvm::omp::Directive::OMPD_sections),
|
|
"PARALLEL SECTIONS" >> pure(llvm::omp::Directive::OMPD_parallel_sections))))
|
|
|
|
// OMP BEGIN and END SECTIONS Directive
|
|
TYPE_PARSER(sourced(construct<OmpBeginSectionsDirective>(
|
|
sourced(Parser<OmpSectionsDirective>{}), Parser<OmpClauseList>{})))
|
|
TYPE_PARSER(
|
|
startOmpLine >> sourced(construct<OmpEndSectionsDirective>(
|
|
sourced("END"_tok >> Parser<OmpSectionsDirective>{}),
|
|
Parser<OmpClauseList>{})))
|
|
|
|
// OMP SECTION-BLOCK
|
|
|
|
TYPE_PARSER(construct<OpenMPSectionConstruct>(block))
|
|
|
|
TYPE_PARSER(maybe(startOmpLine >> "SECTION"_tok / endOmpLine) >>
|
|
construct<OmpSectionBlocks>(nonemptySeparated(
|
|
construct<OpenMPConstruct>(sourced(Parser<OpenMPSectionConstruct>{})),
|
|
startOmpLine >> "SECTION"_tok / endOmpLine)))
|
|
|
|
// OMP SECTIONS (OpenMP 5.0 - 2.8.1), PARALLEL SECTIONS (OpenMP 5.0 - 2.13.3)
|
|
TYPE_PARSER(construct<OpenMPSectionsConstruct>(
|
|
Parser<OmpBeginSectionsDirective>{} / endOmpLine,
|
|
Parser<OmpSectionBlocks>{}, Parser<OmpEndSectionsDirective>{} / endOmpLine))
|
|
|
|
TYPE_CONTEXT_PARSER("OpenMP construct"_en_US,
|
|
startOmpLine >>
|
|
withMessage("expected OpenMP construct"_err_en_US,
|
|
first(construct<OpenMPConstruct>(Parser<OpenMPSectionsConstruct>{}),
|
|
construct<OpenMPConstruct>(Parser<OpenMPLoopConstruct>{}),
|
|
construct<OpenMPConstruct>(Parser<OpenMPBlockConstruct>{}),
|
|
// OpenMPBlockConstruct is attempted before
|
|
// OpenMPStandaloneConstruct to resolve !$OMP ORDERED
|
|
construct<OpenMPConstruct>(Parser<OpenMPStandaloneConstruct>{}),
|
|
construct<OpenMPConstruct>(Parser<OpenMPAtomicConstruct>{}),
|
|
construct<OpenMPConstruct>(Parser<OpenMPExecutableAllocate>{}),
|
|
construct<OpenMPConstruct>(Parser<OpenMPAllocatorsConstruct>{}),
|
|
construct<OpenMPConstruct>(Parser<OpenMPDeclarativeAllocate>{}),
|
|
construct<OpenMPConstruct>(Parser<OpenMPCriticalConstruct>{}))))
|
|
|
|
// END OMP Block directives
|
|
TYPE_PARSER(
|
|
startOmpLine >> sourced(construct<OmpEndBlockDirective>(
|
|
sourced("END"_tok >> Parser<OmpBlockDirective>{}),
|
|
Parser<OmpClauseList>{})))
|
|
|
|
// END OMP Loop directives
|
|
TYPE_PARSER(
|
|
startOmpLine >> sourced(construct<OmpEndLoopDirective>(
|
|
sourced("END"_tok >> Parser<OmpLoopDirective>{}),
|
|
Parser<OmpClauseList>{})))
|
|
|
|
TYPE_PARSER(construct<OpenMPLoopConstruct>(
|
|
Parser<OmpBeginLoopDirective>{} / endOmpLine))
|
|
} // namespace Fortran::parser
|