//===-- 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; // OpenMP Clauses // 2.15.3.1 DEFAULT (PRIVATE | FIRSTPRIVATE | SHARED | NONE) TYPE_PARSER(construct( "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 | SPREAD) TYPE_PARSER(construct( "CLOSE" >> pure(OmpProcBindClause::Type::Close) || "MASTER" >> pure(OmpProcBindClause::Type::Master) || "SPREAD" >> pure(OmpProcBindClause::Type::Spread))) // 2.15.5.1 MAP ([ [ALWAYS[,]] map-type : ] variable-name-list) // map-type -> TO | FROM | TOFROM | ALLOC | RELEASE | DELETE TYPE_PARSER(construct( maybe("ALWAYS" >> construct() / maybe(","_tok)), ("TO"_id >> pure(OmpMapType::Type::To) || "FROM" >> pure(OmpMapType::Type::From) || "TOFROM" >> pure(OmpMapType::Type::Tofrom) || "ALLOC" >> pure(OmpMapType::Type::Alloc) || "RELEASE" >> pure(OmpMapType::Type::Release) || "DELETE" >> pure(OmpMapType::Type::Delete)) / ":")) TYPE_PARSER(construct( maybe(Parser{}), Parser{})) // 2.15.5.2 defaultmap -> DEFAULTMAP (TOFROM:SCALAR) TYPE_PARSER(construct( construct( "TOFROM" >> pure(OmpDefaultmapClause::ImplicitBehavior::Tofrom)), maybe(":" >> construct("SCALAR" >> pure(OmpDefaultmapClause::VariableCategory::Scalar))))) // 2.7.1 SCHEDULE ([modifier1 [, modifier2]:]kind[, chunk_size]) // Modifier -> MONITONIC | NONMONOTONIC | SIMD // kind -> STATIC | DYNAMIC | GUIDED | AUTO | RUNTIME // chunk_size -> ScalarIntExpr TYPE_PARSER(construct( "MONOTONIC" >> pure(OmpScheduleModifierType::ModType::Monotonic) || "NONMONOTONIC" >> pure(OmpScheduleModifierType::ModType::Nonmonotonic) || "SIMD" >> pure(OmpScheduleModifierType::ModType::Simd))) TYPE_PARSER(construct(Parser{}, maybe("," >> Parser{}) / ":")) TYPE_PARSER(construct(maybe(Parser{}), "STATIC" >> pure(OmpScheduleClause::ScheduleType::Static) || "DYNAMIC" >> pure(OmpScheduleClause::ScheduleType::Dynamic) || "GUIDED" >> pure(OmpScheduleClause::ScheduleType::Guided) || "AUTO" >> pure(OmpScheduleClause::ScheduleType::Auto) || "RUNTIME" >> pure(OmpScheduleClause::ScheduleType::Runtime), maybe("," >> scalarIntExpr))) // 2.12 IF (directive-name-modifier: scalar-logical-expr) TYPE_PARSER(construct( maybe( ("PARALLEL" >> pure(OmpIfClause::DirectiveNameModifier::Parallel) || "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)) / ":"), scalarLogicalExpr)) // 2.15.3.6 REDUCTION (reduction-identifier: variable-name-list) TYPE_PARSER(construct(Parser{}) || construct(Parser{})) TYPE_PARSER(construct( Parser{} / ":", nonemptyList(designator))) // OMP 5.0 2.11.4 ALLOCATE ([allocator:] variable-name-list) TYPE_PARSER(construct( maybe(construct(scalarIntExpr) / ":"), Parser{})) // 2.13.9 DEPEND (SOURCE | SINK : vec | (IN | OUT | INOUT) : list TYPE_PARSER(construct( Parser{}, scalarIntConstantExpr)) TYPE_PARSER( construct(name, maybe(Parser{}))) TYPE_PARSER( construct("IN"_id >> pure(OmpDependenceType::Type::In) || "INOUT" >> pure(OmpDependenceType::Type::Inout) || "OUT" >> pure(OmpDependenceType::Type::Out))) TYPE_CONTEXT_PARSER("Omp Depend clause"_en_US, construct(construct( "SINK :" >> nonemptyList(Parser{}))) || construct( construct("SOURCE"_tok)) || construct(construct( Parser{}, ":" >> nonemptyList(designator)))) // 2.15.3.7 LINEAR (linear-list: linear-step) // linear-list -> list | modifier(list) // linear-modifier -> REF | VAL | UVAL TYPE_PARSER( construct("REF" >> pure(OmpLinearModifier::Type::Ref) || "VAL" >> pure(OmpLinearModifier::Type::Val) || "UVAL" >> pure(OmpLinearModifier::Type::Uval))) TYPE_CONTEXT_PARSER("Omp LINEAR clause"_en_US, construct( construct(construct( Parser{}, parenthesized(nonemptyList(name)), maybe(":" >> scalarIntConstantExpr))) || construct(construct( nonemptyList(name), maybe(":" >> scalarIntConstantExpr))))) // 2.8.1 ALIGNED (list: alignment) TYPE_PARSER(construct( nonemptyList(name), maybe(":" >> scalarIntConstantExpr))) TYPE_PARSER( construct(designator) || construct("/" >> name / "/")) TYPE_PARSER( "ACQUIRE" >> construct(construct()) || "ACQ_REL" >> construct(construct()) || "ALIGNED" >> construct(parenthesized(Parser{})) || "ALLOCATE" >> construct(parenthesized(Parser{})) || "COLLAPSE" >> construct(construct( parenthesized(scalarIntConstantExpr))) || "COPYIN" >> construct(construct( parenthesized(Parser{}))) || "COPYPRIVATE" >> construct(construct( (parenthesized(Parser{})))) || "DEFAULT"_id >> construct(parenthesized(Parser{})) || "DEFAULTMAP" >> construct(parenthesized(Parser{})) || "DEPEND" >> construct(parenthesized(Parser{})) || "DEVICE" >> construct(construct( parenthesized(scalarIntExpr))) || "DIST_SCHEDULE" >> construct(construct( parenthesized("STATIC" >> maybe("," >> scalarIntExpr)))) || "FINAL" >> construct(construct( parenthesized(scalarLogicalExpr))) || "FIRSTPRIVATE" >> construct(construct( parenthesized(Parser{}))) || "FROM" >> construct(construct( parenthesized(Parser{}))) || "GRAINSIZE" >> construct(construct( parenthesized(scalarIntExpr))) || "HINT" >> construct( construct(parenthesized(constantExpr))) || "IF" >> construct(parenthesized(Parser{})) || "INBRANCH" >> construct(construct()) || "IS_DEVICE_PTR" >> construct(construct( parenthesized(nonemptyList(name)))) || "LASTPRIVATE" >> construct(construct( parenthesized(Parser{}))) || "LINEAR" >> construct(parenthesized(Parser{})) || "LINK" >> construct(construct( parenthesized(Parser{}))) || "MAP" >> construct(parenthesized(Parser{})) || "MERGEABLE" >> construct(construct()) || "NOGROUP" >> construct(construct()) || "NOTINBRANCH" >> construct(construct()) || "NOWAIT" >> construct(construct()) || "NUM_TASKS" >> construct(construct( parenthesized(scalarIntExpr))) || "NUM_TEAMS" >> construct(construct( parenthesized(scalarIntExpr))) || "NUM_THREADS" >> construct(construct( parenthesized(scalarIntExpr))) || "ORDERED" >> construct(construct( maybe(parenthesized(scalarIntConstantExpr)))) || "PRIORITY" >> construct(construct( parenthesized(scalarIntExpr))) || "PRIVATE" >> construct(construct( parenthesized(Parser{}))) || "PROC_BIND" >> construct(parenthesized(Parser{})) || "REDUCTION" >> construct(parenthesized(Parser{})) || "RELAXED" >> construct(construct()) || "RELEASE" >> construct(construct()) || "SAFELEN" >> construct(construct( parenthesized(scalarIntConstantExpr))) || "SCHEDULE" >> construct(parenthesized(Parser{})) || "SEQ_CST" >> construct(construct()) || "SHARED" >> construct(construct( parenthesized(Parser{}))) || "SIMD"_id >> construct(construct()) || "SIMDLEN" >> construct(construct( parenthesized(scalarIntConstantExpr))) || "THREADS" >> construct(construct()) || "THREAD_LIMIT" >> construct(construct( parenthesized(scalarIntExpr))) || "TO" >> construct(construct( parenthesized(Parser{}))) || "USE_DEVICE_PTR" >> construct(construct( parenthesized(nonemptyList(name)))) || "UNIFORM" >> construct(construct( parenthesized(nonemptyList(name)))) || "UNTIED" >> construct(construct())) // [Clause, [Clause], ...] TYPE_PARSER(sourced(construct( many(maybe(","_tok) >> sourced(Parser{}))))) // 2.1 (variable | /common-block | array-sections) TYPE_PARSER(construct(nonemptyList(Parser{}))) // Omp directives enclosing do loop TYPE_PARSER(sourced(construct(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), "PARALLEL DO SIMD" >> pure(llvm::omp::Directive::OMPD_parallel_do_simd), "PARALLEL DO" >> pure(llvm::omp::Directive::OMPD_parallel_do), "SIMD" >> pure(llvm::omp::Directive::OMPD_simd), "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 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), "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))))) TYPE_PARSER(sourced(construct( sourced(Parser{}), Parser{}))) // 2.14.1 construct-type-clause -> PARALLEL | SECTIONS | DO | TASKGROUP TYPE_PARSER(sourced(construct( 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( verbatim("CANCELLATION POINT"_tok), Parser{}))) // 2.14.1 Cancel construct TYPE_PARSER(sourced(construct(verbatim("CANCEL"_tok), Parser{}, 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( sourced("SEQ_CST" >> construct(construct()) || "ACQ_REL" >> construct(construct()) || "RELEASE" >> construct(construct()) || "ACQUIRE" >> construct(construct()) || "RELAXED" >> construct(construct()))))) TYPE_PARSER(sourced(construct(verbatim("FLUSH"_tok), maybe(Parser{}), maybe(parenthesized(Parser{}))))) // Simple Standalone Directives TYPE_PARSER(sourced(construct(first( "BARRIER" >> pure(llvm::omp::Directive::OMPD_barrier), "ORDERED" >> pure(llvm::omp::Directive::OMPD_ordered), "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( Parser{}, Parser{}))) // Standalone Constructs TYPE_PARSER( sourced(construct( Parser{}) || construct(Parser{}) || construct(Parser{}) || construct( Parser{})) / endOfLine) // Directives enclosing structured-block TYPE_PARSER(construct(first( "MASTER" >> pure(llvm::omp::Directive::OMPD_master), "ORDERED" >> pure(llvm::omp::Directive::OMPD_ordered), "PARALLEL WORKSHARE" >> pure(llvm::omp::Directive::OMPD_parallel_workshare), "PARALLEL" >> pure(llvm::omp::Directive::OMPD_parallel), "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( sourced(Parser{}), Parser{}))) TYPE_PARSER(construct( "INITIALIZER" >> parenthesized("OMP_PRIV =" >> expr))) // 2.16 Declare Reduction Construct TYPE_PARSER(sourced(construct( verbatim("DECLARE REDUCTION"_tok), "(" >> Parser{} / ":", nonemptyList(Parser{}) / ":", Parser{} / ")", maybe(Parser{})))) // declare-target with list TYPE_PARSER(sourced(construct( parenthesized(Parser{})))) // declare-target with clause TYPE_PARSER( sourced(construct(Parser{}))) // declare-target-specifier TYPE_PARSER( construct(Parser{}) || construct(Parser{})) // 2.10.6 Declare Target Construct TYPE_PARSER(sourced(construct( verbatim("DECLARE TARGET"_tok), Parser{}))) TYPE_PARSER(construct(Parser{}) || construct( construct( construct(Parser{}, 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(startOmpLine >> "END ATOMIC"_tok)) // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] READ [MEMORY-ORDER-CLAUSE-LIST] TYPE_PARSER("ATOMIC" >> construct(Parser{} / maybe(","_tok), verbatim("READ"_tok), Parser{} / endOmpLine, statement(assignmentStmt), maybe(Parser{} / endOmpLine))) // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] CAPTURE [MEMORY-ORDER-CLAUSE-LIST] TYPE_PARSER("ATOMIC" >> construct(Parser{} / maybe(","_tok), verbatim("CAPTURE"_tok), Parser{} / endOmpLine, statement(assignmentStmt), statement(assignmentStmt), Parser{} / endOmpLine)) // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] UPDATE [MEMORY-ORDER-CLAUSE-LIST] TYPE_PARSER("ATOMIC" >> construct(Parser{} / maybe(","_tok), verbatim("UPDATE"_tok), Parser{} / endOmpLine, statement(assignmentStmt), maybe(Parser{} / endOmpLine))) // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] TYPE_PARSER(construct(verbatim("ATOMIC"_tok), Parser{} / endOmpLine, statement(assignmentStmt), maybe(Parser{} / endOmpLine))) // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] WRITE [MEMORY-ORDER-CLAUSE-LIST] TYPE_PARSER("ATOMIC" >> construct(Parser{} / maybe(","_tok), verbatim("WRITE"_tok), Parser{} / endOmpLine, statement(assignmentStmt), maybe(Parser{} / endOmpLine))) // Atomic Construct TYPE_PARSER(construct(Parser{}) || construct(Parser{}) || construct(Parser{}) || construct(Parser{}) || construct(Parser{})) // 2.13.2 OMP CRITICAL TYPE_PARSER(startOmpLine >> sourced(construct( verbatim("END CRITICAL"_tok), maybe(parenthesized(name)))) / endOmpLine) TYPE_PARSER(sourced(construct(verbatim("CRITICAL"_tok), maybe(parenthesized(name)), maybe(Parser{}))) / endOmpLine) TYPE_PARSER(construct( Parser{}, block, Parser{})) // 2.8.2 Declare Simd construct TYPE_PARSER( sourced(construct(verbatim("DECLARE SIMD"_tok), maybe(parenthesized(name)), Parser{}))) // 2.15.2 Threadprivate directive TYPE_PARSER(sourced(construct( verbatim("THREADPRIVATE"_tok), parenthesized(Parser{})))) // Declarative constructs TYPE_PARSER(startOmpLine >> sourced(construct( Parser{}) || construct( Parser{}) || construct( Parser{}) || construct(Parser{})) / endOmpLine) // Block Construct TYPE_PARSER(construct( Parser{} / endOmpLine, block, Parser{} / endOmpLine)) // OMP SECTIONS Directive TYPE_PARSER(construct(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( sourced(Parser{}), Parser{}))) TYPE_PARSER( startOmpLine >> sourced(construct( sourced("END"_tok >> Parser{}), Parser{}))) // OMP SECTION-BLOCK TYPE_PARSER(maybe(startOmpLine >> "SECTION"_tok / endOmpLine) >> construct( nonemptySeparated(block, startOmpLine >> "SECTION"_tok / endOmpLine))) // OMP SECTIONS (2.7.2), PARALLEL SECTIONS (2.11.2) TYPE_PARSER(construct( Parser{} / endOmpLine, Parser{}, Parser{} / endOmpLine)) TYPE_CONTEXT_PARSER("OpenMP construct"_en_US, startOmpLine >> first(construct(Parser{}), construct(Parser{}), construct(Parser{}), // OpenMPBlockConstruct is attempted before // OpenMPStandaloneConstruct to resolve !$OMP ORDERED construct(Parser{}), construct(Parser{}), construct(Parser{}))) // END OMP Block directives TYPE_PARSER( startOmpLine >> sourced(construct( sourced("END"_tok >> Parser{}), Parser{}))) // END OMP Loop directives TYPE_PARSER( startOmpLine >> sourced(construct( sourced("END"_tok >> Parser{}), Parser{}))) TYPE_PARSER(construct( Parser{} / endOmpLine)) } // namespace Fortran::parser