diff --git a/flang/lib/parser/grammar.h b/flang/lib/parser/grammar.h index 36f682b32720..dbfd22f5a8b5 100644 --- a/flang/lib/parser/grammar.h +++ b/flang/lib/parser/grammar.h @@ -49,7 +49,7 @@ namespace Fortran::parser { // R507 declaration-construct -> // specification-construct | data-stmt | format-stmt | // entry-stmt | stmt-function-stmt -constexpr auto execPartLookAhead{first(actionStmt >> ok, "ASSOCIATE ("_tok, +constexpr auto execPartLookAhead{first(actionStmt >> ok, openmpEndLoopDirective >> ok, openmpConstruct >> ok, "ASSOCIATE ("_tok, "BLOCK"_tok, "SELECT"_tok, "CHANGE TEAM"_sptok, "CRITICAL"_tok, "DO"_tok, "IF ("_tok, "WHERE ("_tok, "FORALL ("_tok)}; constexpr auto declErrorRecovery{ @@ -96,7 +96,7 @@ TYPE_CONTEXT_PARSER("specification construct"_en_US, construct( statement(indirect(typeDeclarationStmt))), construct(indirect(Parser{})), - construct(indirect(openmpConstruct)), + construct(indirect(openmpDeclarativeConstruct)), construct(indirect(compilerDirective)))) // R513 other-specification-stmt -> @@ -263,7 +263,7 @@ TYPE_PARSER(construct(indirect(functionSubprogram)) || // [use-stmt]... [import-stmt]... [implicit-part] // [declaration-construct]... TYPE_CONTEXT_PARSER("specification part"_en_US, - construct( + construct(many(openmpDeclarativeConstruct), many(unambiguousStatement(indirect(Parser{}))), many(unambiguousStatement(indirect(Parser{}))), implicitPart, many(declarationConstruct))) @@ -274,7 +274,7 @@ TYPE_CONTEXT_PARSER("specification part"_en_US, // specialized error recovery in the event of a spurious executable // statement. constexpr auto limitedSpecificationPart{inContext("specification part"_en_US, - construct( + construct(many(openmpDeclarativeConstruct), many(unambiguousStatement(indirect(Parser{}))), many(unambiguousStatement(indirect(Parser{}))), implicitPart, many(limitedDeclarationConstruct)))}; @@ -391,6 +391,7 @@ constexpr auto executableConstruct{ construct(indirect(Parser{})), construct(indirect(whereConstruct)), construct(indirect(forallConstruct)), + construct(indirect(openmpEndLoopDirective)), construct(indirect(openmpConstruct)), construct(indirect(compilerDirective)))}; diff --git a/flang/lib/parser/openmp-grammar.h b/flang/lib/parser/openmp-grammar.h index 5ca0e2c7998e..d668f59238f4 100644 --- a/flang/lib/parser/openmp-grammar.h +++ b/flang/lib/parser/openmp-grammar.h @@ -39,10 +39,9 @@ // OpenMP Directives and Clauses namespace Fortran::parser { -constexpr auto beginOmpDirective{skipStuffBeforeStatement >> "!$OMP "_sptok}; +constexpr auto endOmpLine = space >> endOfLine; // OpenMP Clauses - // DEFAULT (PRIVATE | FIRSTPRIVATE | SHARED | NONE ) TYPE_PARSER(construct( "PRIVATE" >> pure(OmpDefaultClause::Type::Private) || @@ -59,15 +58,17 @@ TYPE_PARSER(construct( // MAP ([ [map-type-modifier[,]] map-type : ] list) // map-type-modifier -> ALWAYS // map-type -> TO | FROM | TOFROM | ALLOC | RELEASE | DELETE +TYPE_PARSER(construct( + maybe("ALWAYS" >> construct() / maybe(","_tok)), + "TO" >> pure(OmpMapType::Type::To) / ":"_tok || + "FROM" >> pure(OmpMapType::Type::From) / ":"_tok || + "TOFROM" >> pure(OmpMapType::Type::Tofrom) / ":"_tok || + "ALLOC" >> pure(OmpMapType::Type::Alloc) / ":"_tok || + "RELEASE" >> pure(OmpMapType::Type::Release) / ":"_tok || + "DELETE" >> pure(OmpMapType::Type::Delete) / ":"_tok)) + TYPE_PARSER(construct( - maybe(maybe("ALWAYS" >> maybe(","_tok)) >> - ("TO" >> pure(OmpMapClause::Type::To) / ":"_tok || - "FROM" >> pure(OmpMapClause::Type::From) / ":"_tok || - "TOFROM" >> pure(OmpMapClause::Type::Tofrom) / ":"_tok || - "ALLOC" >> pure(OmpMapClause::Type::Alloc) / ":"_tok || - "RELEASE" >> pure(OmpMapClause::Type::Release) / ":"_tok || - "DELETE" >> pure(OmpMapClause::Type::Delete) / ":"_tok)), - nonemptyList(name))) + maybe(Parser{}), Parser{})) // SCHEDULE ([modifier [, modifier]:]kind[, chunk_size]) // Modifier -> MONITONIC | NONMONOTONIC | SIMD @@ -87,45 +88,29 @@ TYPE_PARSER(construct(maybe(Parser{}), "GUIDED" >> pure(OmpScheduleClause::ScheduleType::Guided) || "AUTO" >> pure(OmpScheduleClause::ScheduleType::Auto) || "RUNTIME" >> pure(OmpScheduleClause::ScheduleType::Runtime), - maybe(","_tok) >> scalarIntExpr)) + maybe(","_tok >> scalarIntExpr))) // IF(directive-name-modifier: scalar-logical-expr) TYPE_PARSER(construct( maybe( - "PARALLEL"_tok >> pure(OmpIfClause::DirectiveNameModifier::Parallel) || - "TARGET ENTER DATA"_tok >> - pure(OmpIfClause::DirectiveNameModifier::TargetEnterData) || - "TARGET EXIT DATA"_tok >> - pure(OmpIfClause::DirectiveNameModifier::TargetExitData) || - "TARGET DATA"_tok >> - pure(OmpIfClause::DirectiveNameModifier::TargetData) || - "TARGET UPDATE"_tok >> - pure(OmpIfClause::DirectiveNameModifier::TargetUpdate) || - "TARGET"_tok >> pure(OmpIfClause::DirectiveNameModifier::Target) || - "TASKLOOP"_tok >> pure(OmpIfClause::DirectiveNameModifier::Taskloop) || - "TASK"_tok >> pure(OmpIfClause::DirectiveNameModifier::Task)) / - maybe(":"_tok), + ("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) || + "TASKLOOP" >> pure(OmpIfClause::DirectiveNameModifier::Taskloop) || + "TASK" >> pure(OmpIfClause::DirectiveNameModifier::Task)) / + ":"_tok), scalarLogicalExpr)) -// REDUCTION(reduction-identifier: list) -constexpr auto reductionBinaryOperator{ - "+" >> pure(OmpReductionOperator::BinaryOperator::Add) || - "-" >> pure(OmpReductionOperator::BinaryOperator::Subtract) || - "*" >> pure(OmpReductionOperator::BinaryOperator::Multiply) || - ".AND." >> pure(OmpReductionOperator::BinaryOperator::AND) || - ".OR." >> pure(OmpReductionOperator::BinaryOperator::OR) || - ".EQV." >> pure(OmpReductionOperator::BinaryOperator::EQV) || - ".NEQV." >> pure(OmpReductionOperator::BinaryOperator::NEQV)}; - -constexpr auto reductionProcedureOperator{ - "MIN" >> pure(OmpReductionOperator::ProcedureOperator::MIN) || - "MAX" >> pure(OmpReductionOperator::ProcedureOperator::MAX) || - "IAND" >> pure(OmpReductionOperator::ProcedureOperator::IAND) || - "IOR" >> pure(OmpReductionOperator::ProcedureOperator::IOR) || - "IEOR" >> pure(OmpReductionOperator::ProcedureOperator::IEOR)}; - -TYPE_PARSER(construct(reductionBinaryOperator) || - construct(reductionProcedureOperator)) +TYPE_PARSER( + construct(indirect(Parser{})) || + construct(Parser{})) TYPE_PARSER(construct( Parser{} / ":"_tok, nonemptyList(designator))) @@ -138,9 +123,9 @@ TYPE_PARSER( construct(name, maybe(Parser{}))) TYPE_PARSER(construct( - "IN"_tok >> pure(OmpDependenceType::Type::In) || - "OUT"_tok >> pure(OmpDependenceType::Type::Out) || - "INOUT"_tok >> pure(OmpDependenceType::Type::Inout))) + "INOUT" >> pure(OmpDependenceType::Type::Inout) || + "IN" >> pure(OmpDependenceType::Type::In) || + "OUT" >> pure(OmpDependenceType::Type::Out))) TYPE_CONTEXT_PARSER("Omp Depend clause"_en_US, construct(construct( @@ -150,12 +135,13 @@ TYPE_CONTEXT_PARSER("Omp Depend clause"_en_US, construct(construct( Parser{}, ":"_tok >> nonemptyList(designator)))) -// LINEAR(list: linear-step) -TYPE_PARSER(construct( - "REF"_tok >> pure(OmpLinearModifier::Type::Ref) || - "VAL"_tok >> pure(OmpLinearModifier::Type::Val) || - "UVAL"_tok >> pure(OmpLinearModifier::Type::Uval))) +// linear-modifier +TYPE_PARSER( + construct("REF" >> pure(OmpLinearModifier::Type::Ref) || + "VAL" >> pure(OmpLinearModifier::Type::Val) || + "UVAL" >> pure(OmpLinearModifier::Type::Uval))) +// LINEAR(list: linear-step) TYPE_CONTEXT_PARSER("Omp LINEAR clause"_en_US, construct( construct(construct( @@ -168,187 +154,437 @@ TYPE_CONTEXT_PARSER("Omp LINEAR clause"_en_US, TYPE_PARSER(construct( nonemptyList(name), maybe(":"_tok) >> scalarIntConstantExpr)) -TYPE_PARSER(construct(pure(OmpNameList::Kind::Object), name) || - construct("/" >> pure(OmpNameList::Kind::Common), name / "/")) +TYPE_PARSER(construct(pure(OmpObject::Kind::Object), designator) || + construct( + "/" >> pure(OmpObject::Kind::Common), designator / "/")) -TYPE_PARSER( - construct(construct("DEFAULTMAP"_tok >> - parenthesized("TOFROM"_tok >> ":"_tok >> "SCALAR"_tok))) || - construct(construct("INBRANCH"_tok)) || - construct(construct("MERGEABLE"_tok)) || - construct(construct("NOGROUP"_tok)) || - construct( - construct("NOTINBRANCH"_tok)) || - construct(construct("NOWAIT"_tok)) || - construct(construct("UNTIED"_tok)) || - construct(construct( - "COLLAPSE"_tok >> parenthesized(scalarIntConstantExpr))) || - construct(construct( - "COPYIN"_tok >> parenthesized(nonemptyList(Parser{})))) || - construct(construct("COPYPRIVATE"_tok >> - parenthesized(nonemptyList(Parser{})))) || - construct(construct( - "DEVICE"_tok >> parenthesized(scalarIntExpr))) || - construct( - construct("DIST_SCHEDULE"_tok >> +TYPE_PARSER("DEFAULTMAP" >> + construct(construct( + parenthesized("TOFROM"_tok >> ":"_tok >> "SCALAR"_tok))) || + "INBRANCH" >> construct(construct()) || + "MERGEABLE" >> construct(construct()) || + "NOGROUP" >> construct(construct()) || + "NOTINBRANCH" >> + construct(construct()) || + "NOWAIT" >> construct(construct()) || + "UNTIED" >> construct(construct()) || + "COLLAPSE" >> construct(construct( + parenthesized(scalarIntConstantExpr))) || + "COPYIN" >> construct(construct( + parenthesized(Parser{}))) || + "COPYPRIVATE" >> construct(construct( + (parenthesized(Parser{})))) || + "DEVICE" >> construct(construct( + parenthesized(scalarIntExpr))) || + "DIST_SCHEDULE" >> + construct(construct( parenthesized("STATIC"_tok >> ","_tok >> scalarIntExpr))) || - construct(construct( - "FINAL"_tok >> parenthesized(scalarIntExpr))) || - construct( - construct("FIRSTPRIVATE"_tok >> - parenthesized(nonemptyList(Parser{})))) || - construct(construct( - "FROM"_tok >> parenthesized(nonemptyList(designator)))) || - construct(construct( - "GRAINSIZE"_tok >> parenthesized(scalarIntExpr))) || - construct(construct("LASTPRIVATE"_tok >> - parenthesized(nonemptyList(Parser{})))) || - construct(construct( - "LINK"_tok >> parenthesized(nonemptyList(name)))) || - construct(construct( - "NUM_TASKS"_tok >> parenthesized(scalarIntExpr))) || - construct(construct( - "NUM_TEAMS"_tok >> parenthesized(scalarIntExpr))) || - construct(construct( - "NUM_THREADS"_tok >> parenthesized(scalarIntExpr))) || - construct(construct( - "ORDERED"_tok >> maybe(parenthesized(scalarIntConstantExpr)))) || - construct(construct( - "PRIORITY"_tok >> parenthesized(scalarIntExpr))) || - construct(construct( - "PRIVATE"_tok >> parenthesized(nonemptyList(Parser{})))) || - construct(construct( - "SAFELEN"_tok >> parenthesized(scalarIntConstantExpr))) || - construct(construct( - "SHARED"_tok >> parenthesized(nonemptyList(Parser{})))) || - construct(construct( - "SIMDLEN"_tok >> parenthesized(scalarIntConstantExpr))) || - construct(construct( - "THREAD_LIMIT"_tok >> parenthesized(scalarIntExpr))) || - construct(construct( - "TO"_tok >> parenthesized(nonemptyList(designator)))) || - construct(construct( - "UNIFORM"_tok >> parenthesized(nonemptyList(name)))) || - construct(construct( - "USE_DEVICE_PTR"_tok >> parenthesized(nonemptyList(name)))) || - construct( - "ALIGNED"_tok >> parenthesized(Parser{})) || - construct( - "DEFAULT"_tok >> parenthesized(Parser{})) || - construct( - "DEPEND"_tok >> parenthesized(Parser{})) || - construct("IF"_tok >> parenthesized(Parser{})) || - construct( - "LINEAR"_tok >> parenthesized(Parser{})) || - construct("MAP"_tok >> parenthesized(Parser{})) || - construct( - "PROC_BIND"_tok >> parenthesized(Parser{})) || - construct( - "REDUCTION"_tok >> parenthesized(Parser{})) || - construct( - "SCHEDULE"_tok >> parenthesized(Parser{}))) + "FINAL" >> construct( + construct(parenthesized(scalarIntExpr))) || + "FIRSTPRIVATE" >> construct(construct( + parenthesized(Parser{}))) || + "FROM" >> construct(construct( + parenthesized(nonemptyList(designator)))) || + "GRAINSIZE" >> construct(construct( + parenthesized(scalarIntExpr))) || + "LASTPRIVATE" >> construct(construct( + parenthesized(Parser{}))) || + "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{}))) || + "SAFELEN" >> construct(construct( + parenthesized(scalarIntConstantExpr))) || + "SHARED" >> construct(construct( + parenthesized(Parser{}))) || + "SIMDLEN" >> construct(construct( + parenthesized(scalarIntConstantExpr))) || + "THREAD_LIMIT" >> construct(construct( + parenthesized(scalarIntExpr))) || + "TO" >> construct(construct( + parenthesized(nonemptyList(designator)))) || + "UNIFORM" >> construct(construct( + parenthesized(nonemptyList(name)))) || + "USE_DEVICE_PTR" >> construct(construct( + parenthesized(nonemptyList(name)))) || + "ALIGNED" >> + construct(parenthesized(Parser{})) || + "DEFAULT" >> + construct(parenthesized(Parser{})) || + "DEPEND" >> + construct(parenthesized(Parser{})) || + "IF" >> construct(parenthesized(Parser{})) || + "LINEAR" >> + construct(parenthesized(Parser{})) || + "MAP" >> construct(parenthesized(Parser{})) || + "PROC_BIND" >> + construct(parenthesized(Parser{})) || + "REDUCTION" >> + construct(parenthesized(Parser{})) || + "SCHEDULE" >> + construct(parenthesized(Parser{}))) -TYPE_PARSER(skipStuffBeforeStatement >> "!$OMP END"_sptok >> - (construct(Parser{}))) +// [Clause, [Clause], ...] +TYPE_PARSER( + construct(many(maybe(","_tok) >> Parser{}))) + +// (variable | /common-block | array-sections) +TYPE_PARSER(construct(nonemptyList(Parser{}))) // Omp directives enclosing do loop -TYPE_PARSER( - construct( - construct( - "DISTRIBUTE PARALLEL DO SIMD"_tok >> many(Parser{}))) || - construct( - construct( - "DISTRIBUTE PARALLEL DO"_tok >> many(Parser{}))) || - construct(construct( - "DISTRIBUTE SIMD"_tok >> many(Parser{}))) || - construct(construct( - "DISTRIBUTE"_tok >> many(Parser{}))) || - construct(construct( - "DO SIMD"_tok >> many(Parser{}))) || - construct(construct( - "DO"_tok >> many(Parser{}))) || - construct(construct( - "PARALLEL DO SIMD"_tok >> many(Parser{}))) || - construct(construct( - "PARALLEL DO"_tok >> many(Parser{}))) || - construct(construct( - "SIMD"_tok >> many(Parser{}))) || - construct( - construct( - "TARGET PARALLEL DO SIMD"_tok >> many(Parser{}))) || - construct(construct( - "TARGET PARALLEL DO"_tok >> many(Parser{}))) || - construct(construct( - "TARGET SIMD"_tok >> many(Parser{}))) || - construct( - construct( - "TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD"_tok >> - many(Parser{}))) || - construct( - construct( - "TARGET TEAMS DISTRIBUTE PARALLEL DO"_tok >> - many(Parser{}))) || - construct( - construct( - "TARGET TEAMS DISTRIBUTE SIMD"_tok >> many(Parser{}))) || - construct( - construct( - "TARGET TEAMS DISTRIBUTE"_tok >> many(Parser{}))) || - construct(construct( - "TASKLOOP SIMD" >> many(Parser{}))) || - construct(construct( - "TASKLOOP" >> many(Parser{}))) || - construct( - construct( - "TEAMS DISTRIBUTE PARALLEL DO SIMD"_tok >> - many(Parser{}))) || - construct( - construct( - "TEAMS DISTRIBUTE PARALLEL DO"_tok >> many(Parser{}))) || - construct( - construct( - "TEAMS DISTRIBUTE SIMD"_tok >> many(Parser{}))) || - construct(construct( - "TEAMS DISTRIBUTE"_tok >> many(Parser{})))) +TYPE_PARSER("DISTRIBUTE PARALLEL DO SIMD" >> + construct( + construct()) || + "DISTRIBUTE PARALLEL DO" >> + construct( + construct()) || + "DISTRIBUTE SIMD" >> construct( + construct()) || + "DISTRIBUTE" >> construct( + construct()) || + "PARALLEL DO SIMD" >> construct( + construct()) || + "PARALLEL DO" >> construct( + construct()) || + "SIMD" >> + construct(construct()) || + "DO SIMD" >> + construct(construct()) || + "DO" >> construct(construct()) || + "TARGET PARALLEL DO SIMD" >> + construct( + construct()) || + "TARGET PARALLEL DO" >> + construct( + construct()) || + "TARGET SIMD" >> construct( + construct()) || + "TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD" >> + construct(construct< + OmpLoopDirective::TargetTeamsDistributeParallelDoSimd>()) || + "TARGET TEAMS DISTRIBUTE PARALLEL DO" >> + construct( + construct()) || + "TARGET TEAMS DISTRIBUTE SIMD" >> + construct( + construct()) || + "TARGET TEAMS DISTRIBUTE" >> + construct( + construct()) || + "TASKLOOP SIMD" >> construct( + construct()) || + "TASKLOOP" >> + construct(construct()) || + "TEAMS DISTRIBUTE PARALLEL DO SIMD" >> + construct( + construct()) || + "TEAMS DISTRIBUTE PARALLEL DO" >> + construct( + construct()) || + "TEAMS DISTRIBUTE SIMD" >> + construct( + construct()) || + "TEAMS DISTRIBUTE" >> construct( + construct())) -TYPE_PARSER(construct( - construct( - "BARRIER"_tok >> many(Parser{}))) || - construct( - construct( - "CANCELLATION POINT"_tok >> many(Parser{}))) || - construct(construct( - "CANCEL"_tok >> many(Parser{}))) || - construct(construct( - "FLUSH"_tok >> many(Parser{}))) || - construct( - construct( - "TARGET ENTER DATA"_tok >> many(Parser{}))) || - construct( - construct( - "TARGET EXIT DATA"_tok >> many(Parser{}))) || - construct( - construct( - "TARGET UPDATE"_tok >> many(Parser{}))) || - construct( - construct( - "TASKWAIT"_tok >> many(Parser{}))) || - construct( - construct( - "TASKYIELD"_tok >> many(Parser{})))) +// Cancellation Point construct +TYPE_PARSER("CANCELLATION POINT" >> + construct( + "PARALLEL" >> pure(OmpCancelType::Type::Parallel) || + "SECTIONS" >> pure(OmpCancelType::Type::Sections) || + "DO" >> pure(OmpCancelType::Type::Do) || + "TASKGROUP" >> pure(OmpCancelType::Type::Taskgroup))) +// Cancel construct TYPE_PARSER( - construct(statement(Parser{}), - Parser{}, maybe(Parser{}))) + "CANCEL" >> construct( + ("PARALLEL" >> pure(OmpCancelType::Type::Parallel) || + "SECTIONS" >> pure(OmpCancelType::Type::Sections) || + "DO" >> pure(OmpCancelType::Type::Do) || + "TASKGROUP" >> pure(OmpCancelType::Type::Taskgroup)), + maybe("IF" >> parenthesized(scalarLogicalExpr)))) + +// Flush construct +TYPE_PARSER("FLUSH" >> construct( + maybe(parenthesized(Parser{})))) + +// Standalone directives +TYPE_PARSER("TARGET ENTER DATA" >> + construct( + construct()) || + "TARGET EXIT DATA" >> + construct( + construct()) || + "TARGET UPDATE" >> construct( + construct())) + +// Directives enclosing structured-block +TYPE_PARSER("MASTER" >> + construct(construct()) || + "ORDERED" >> + construct(construct()) || + "PARALLEL WORKSHARE" >> + construct( + construct()) || + "PARALLEL" >> construct( + construct()) || + "TARGET DATA" >> construct( + construct()) || + "TARGET PARALLEL" >> construct( + construct()) || + "TARGET TEAMS" >> construct( + construct()) || + "TARGET" >> + construct(construct()) || + "TASKGROUP" >> construct( + construct()) || + "TASK" >> + construct(construct()) || + "TEAMS" >> + construct(construct())) + +TYPE_PARSER(construct("INITIALIZER"_tok >> + parenthesized("OMP_PRIV"_tok >> "="_tok >> indirect(expr)))) + +// Declare Reduction Construct +TYPE_PARSER(construct( + "("_tok >> Parser{} / ":"_tok, + nonemptyList(Parser{}) / ":"_tok, + Parser{} / ")"_tok, + maybe(Parser{}))) + +// declare-target-map-type +TYPE_PARSER(construct( + "LINK" >> pure(OmpDeclareTargetMapType::Type::Link) || + "TO" >> pure(OmpDeclareTargetMapType::Type::To))) + +// Declarative directives +TYPE_PARSER(construct( + construct( + construct( + Parser{}, + parenthesized(Parser{}))) || + lookAhead(endOfLine) >> + construct( + construct()) || + construct( + parenthesized(construct( + Parser{}))))) + +TYPE_PARSER(construct(Parser{}) || + construct( + construct( + construct(Parser{}, + parenthesized(optionalList(actualArgSpec)))))) + +// OMP END ATOMIC +TYPE_PARSER(construct("!$OMP "_sptok >> "END ATOMIC"_tok)) + +// OMP [SEQ_CST] ATOMIC READ [SEQ_CST] +TYPE_PARSER(construct( + maybe( + "SEQ_CST"_tok >> construct() / maybe(","_tok)), + "READ" >> maybe(","_tok) >> + maybe("SEQ_CST"_tok >> construct()) / + endOmpLine, + statement(assignmentStmt), maybe(Parser{} / endOmpLine))) + +// OMP ATOMIC [SEQ_CST] CAPTURE [SEQ_CST] +TYPE_PARSER(construct( + maybe("SEQ_CST"_tok >> + construct() / maybe(","_tok)), + "CAPTURE" >> maybe(","_tok) >> + maybe("SEQ_CST"_tok >> construct()) / + endOmpLine, + statement(assignmentStmt), statement(assignmentStmt), + Parser{} / endOmpLine)) + +// OMP ATOMIC [SEQ_CST] UPDATE [SEQ_CST] +TYPE_PARSER(construct( + maybe("SEQ_CST"_tok >> + construct() / maybe(","_tok)), + "UPDATE" >> maybe(","_tok) >> + maybe("SEQ_CST"_tok >> construct()) / + endOmpLine, + statement(assignmentStmt), maybe(Parser{} / endOmpLine))) + +// OMP ATOMIC [SEQ_CST] +TYPE_PARSER(construct( + maybe("SEQ_CST"_tok >> construct()) / endOmpLine, + statement(assignmentStmt), maybe(Parser{} / endOmpLine))) + +// ATOMIC [SEQ_CST] WRITE [SEQ_CST] +TYPE_PARSER(construct( + maybe( + "SEQ_CST"_tok >> construct() / maybe(","_tok)), + "WRITE" >> maybe(","_tok) >> + maybe("SEQ_CST"_tok >> construct()) / + endOmpLine, + statement(assignmentStmt), maybe(Parser{} / endOmpLine))) + +// Atomic Construct +TYPE_PARSER("ATOMIC" >> + (construct(Parser{}) || + construct(Parser{}) || + construct(Parser{}) || + construct(Parser{}) || + construct(Parser{}))) + +// OMP CRITICAL +TYPE_PARSER("!$OMP "_sptok >> "END"_tok >> "CRITICAL"_tok >> + construct(maybe(parenthesized(name)))) + +TYPE_PARSER("CRITICAL" >> + construct(maybe(parenthesized(name)), + maybe("HINT"_tok >> construct( + parenthesized(constantExpr))) / + endOmpLine, + block, Parser{} / endOmpLine)) + +// Declare Simd construct +TYPE_PARSER(construct( + maybe(parenthesized(name)), Parser{})) + +// Declarative construct & Threadprivate directive +TYPE_PARSER(lookAhead(!"!$OMP END"_tok) >> "!$OMP "_tok >> + ("DECLARE REDUCTION" >> + construct( + construct( + Parser{})) / + endOmpLine || + "DECLARE SIMD" >> construct( + Parser{}) / + endOmpLine || + "DECLARE TARGET" >> construct( + construct( + Parser{})) / + endOmpLine || + "THREADPRIVATE" >> + construct( + construct( + parenthesized(Parser{})) / + endOmpLine))) + +// Block Construct +TYPE_PARSER(construct(Parser{}, + Parser{} / endOmpLine, block, + Parser{} / endOmpLine)) TYPE_PARSER(construct( - statement(Parser{}))) + Parser{}, Parser{} / endOmpLine)) + +// OMP BARRIER +TYPE_PARSER("BARRIER" >> construct() / endOmpLine) + +// OMP TASKWAIT +TYPE_PARSER("TASKWAIT" >> construct() / endOmpLine) + +// OMP TASKYIELD +TYPE_PARSER("TASKYIELD" >> construct() / endOmpLine) + +// OMP SINGLE +TYPE_PARSER(skipStuffBeforeStatement >> "!$OMP "_sptok >> "END"_tok >> + construct("SINGLE"_tok >> Parser{})) + +TYPE_PARSER("SINGLE" >> + construct(Parser{} / endOmpLine, + block, Parser{} / endOmpLine)) + +TYPE_PARSER(skipStuffBeforeStatement >> "!$OMP "_sptok >> "END"_tok >> + construct("WORKSHARE"_tok)) + +// OMP WORKSHARE +TYPE_PARSER("WORKSHARE" >> + construct(endOmpLine >> block, + Parser{} >> + maybe(construct("NOWAIT"_tok)) / endOmpLine)) + +// OMP END DO SIMD [NOWAIT] +TYPE_PARSER(construct(maybe(construct("NOWAIT"_tok)))) + +// OMP END DO [NOWAIT] +TYPE_PARSER(construct(maybe(construct("NOWAIT"_tok)))) + +// OMP END SECTIONS [NOWAIT] +TYPE_PARSER(skipStuffBeforeStatement >> "!$OMP "_sptok >> "END"_tok >> + "SECTIONS"_tok >> + construct( + maybe("NOWAIT"_tok >> construct()) / endOmpLine)) + +// OMP SECTIONS +TYPE_PARSER("SECTIONS" >> + construct( + Parser{} / endOmpLine, block, Parser{})) + +// OMP END PARALLEL SECTIONS [NOWAIT] +TYPE_PARSER(skipStuffBeforeStatement >> "!$OMP "_sptok >> "END"_tok >> + "PARALLEL SECTIONS"_tok >> + construct( + maybe("NOWAIT"_tok >> construct()) / endOmpLine)) + +// OMP PARALLEL SECTIONS +TYPE_PARSER("PARALLEL SECTIONS" >> construct( + Parser{} / endOmpLine, + block, Parser{})) TYPE_CONTEXT_PARSER("OpenMP construct"_en_US, - beginOmpDirective >> (construct( - indirect(Parser{})) || - construct( - indirect(Parser{})))) + skipStuffBeforeStatement >> "!$OMP "_sptok >> lookAhead(!"END"_tok) >> + (construct( + indirect(Parser{})) || + construct( + indirect(Parser{})) || + construct( + indirect(Parser{})) || + construct( + indirect(Parser{})) || + construct( + indirect(Parser{})) || + construct( + indirect(Parser{})) || + construct( + indirect(Parser{})) || + construct( + indirect(Parser{})) || + construct( + indirect(Parser{})) || + construct( + indirect(Parser{})) || + construct( + indirect(Parser{})) || + construct( + indirect(Parser{})) || + construct( + indirect(Parser{})) || + construct( + indirect(Parser{})) || + construct( + indirect(Parser{})) || + "SECTION"_tok >> endOmpLine >> + construct(construct()))) + +// END OMP Block directives +TYPE_PARSER(skipStuffBeforeStatement >> "!$OMP "_sptok >> "END"_tok >> + construct(indirect(Parser{}))) + +// END OMP Loop directives +TYPE_PARSER(skipStuffBeforeStatement >> "!$OMP "_sptok >> "END"_tok >> + (construct( + "DO SIMD" >> indirect(Parser{}) / endOmpLine) || + construct( + "DO" >> indirect(Parser{}) / endOmpLine) || + construct( + indirect(Parser{}) / endOmpLine))) + +TYPE_PARSER(construct( + Parser{}, Parser{} / endOmpLine)) } // namespace Fortran::parser #endif // FORTRAN_PARSER_OPENMP_GRAMMAR_H_ diff --git a/flang/lib/parser/parse-tree-visitor.h b/flang/lib/parser/parse-tree-visitor.h index c481379d5dc6..cb3e7c54452e 100644 --- a/flang/lib/parser/parse-tree-visitor.h +++ b/flang/lib/parser/parse-tree-visitor.h @@ -672,7 +672,6 @@ void Walk(format::IntrinsicTypeDataEditDesc &x, M &mutator) { mutator.Post(x); } } - template void Walk(const OmpLinearClause::WithModifier &x, V &visitor) { if (visitor.Pre(x)) { @@ -706,6 +705,35 @@ void Walk(OmpLinearClause::WithoutModifier &x, M &mutator) { mutator.Post(x); } } +template +void Walk(const OpenMPDeclareTargetConstruct::WithClause &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.maptype, visitor); + Walk(x.names, visitor); + visitor.Post(x); + } +} +template void Walk(OpenMPDeclareTargetConstruct::WithClause &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.maptype, mutator); + Walk(x.names, mutator); + mutator.Post(x); + } +} +template +void Walk(const OpenMPDeclareTargetConstruct::WithExtendedList &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.names, visitor); + visitor.Post(x); + } +} +template +void Walk(OpenMPDeclareTargetConstruct::WithExtendedList &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.names, mutator); + mutator.Post(x); + } +} } // namespace Fortran::parser #endif // FORTRAN_PARSER_PARSE_TREE_VISITOR_H_ diff --git a/flang/lib/parser/parse-tree.h b/flang/lib/parser/parse-tree.h index d1eb62ea675e..4596d1235d68 100644 --- a/flang/lib/parser/parse-tree.h +++ b/flang/lib/parser/parse-tree.h @@ -249,10 +249,9 @@ struct AssignStmt; struct AssignedGotoStmt; struct PauseStmt; struct OpenMPConstruct; -struct OmpClause; -struct OmpStandaloneDirective; -struct OmpLoopDirective; -struct OmpEndDirective; +struct OpenMPDeclarativeConstruct; +struct OmpBlockDirective; +struct OpenMPEndLoopDirective; // Cooked character stream locations using Location = const char *; @@ -260,7 +259,7 @@ using Location = const char *; // Implicit definitions of the Standard // R403 scalar-xyz -> xyz -// These class template wrappers correspond to the Standard's modifiers +// These template class wrappers correspond to the Standard's modifiers // scalar-xyz, constant-xzy, int-xzy, default-char-xyz, & logical-xyz. // TODO: Implement as wrappers instead, or maybe remove. template struct Scalar { @@ -365,7 +364,8 @@ struct SpecificationConstruct { Statement>, Statement, Statement>, - common::Indirection, common::Indirection, + common::Indirection, + common::Indirection, common::Indirection> u; }; @@ -403,7 +403,8 @@ struct DeclarationConstruct { // from the implicit part to the declaration constructs struct SpecificationPart { TUPLE_CLASS_BOILERPLATE(SpecificationPart); - std::tuple>>, + std::tuple, + std::list>>, std::list>>, ImplicitPart, std::list> t; @@ -487,7 +488,8 @@ struct ExecutableConstruct { common::Indirection, common::Indirection, common::Indirection, common::Indirection, - common::Indirection> + common::Indirection, + common::Indirection> u; }; @@ -829,7 +831,7 @@ struct LiteralConstant { }; // R604 constant -> literal-constant | named-constant -// Renamed to dodge a clash with Constant<> class template. +// Renamed to dodge a clash with Constant<> template class. struct ConstantValue { UNION_CLASS_BOILERPLATE(ConstantValue); std::variant u; @@ -3236,18 +3238,27 @@ struct OmpDefaultClause { WRAPPER_CLASS_BOILERPLATE(OmpDefaultClause, Type); }; -// List -> variable-name | / common-block / -struct OmpNameList { - TUPLE_CLASS_BOILERPLATE(OmpNameList); +// variable-name | / common-block / | array-sections +struct OmpObject { + TUPLE_CLASS_BOILERPLATE(OmpObject); ENUM_CLASS(Kind, Object, Common) - std::tuple t; + std::tuple t; }; -// MAP((TO | FROM | TOFROM | ALLOC | RELEASE | DELETE) : list) +WRAPPER_CLASS(OmpObjectList, std::list); + +// map-type ->(TO | FROM | TOFROM | ALLOC | RELEASE | DELETE) +struct OmpMapType { + TUPLE_CLASS_BOILERPLATE(OmpMapType); + EMPTY_CLASS(Always); + ENUM_CLASS(Type, To, From, Tofrom, Alloc, Release, Delete) + std::tuple, Type> t; +}; + +// MAP ( map-type : list) struct OmpMapClause { TUPLE_CLASS_BOILERPLATE(OmpMapClause); - ENUM_CLASS(Type, To, From, Tofrom, Alloc, Release, Delete) - std::tuple, std::list> t; + std::tuple, OmpObjectList> t; }; // schedule-modifier-type -> MONOTONIC | NONMONOTONIC | SIMD @@ -3293,7 +3304,7 @@ struct OmpLinearModifier { WRAPPER_CLASS_BOILERPLATE(OmpLinearModifier, Type); }; -// LINEAR((modifier(list) | (list)) [: linear-step]) +// LINEAR((linear-modifier(list) | (list)) [: linear-step]) struct OmpLinearClause { UNION_CLASS_BOILERPLATE(OmpLinearClause); struct WithModifier { @@ -3316,13 +3327,11 @@ struct OmpLinearClause { std::variant u; }; -// reduction-identifier -> "+", "-", "*", .AND., .OR., .EQV., .NEQV., -// MIN, MAX, IAND, IOR, IEOR +// reduction-identifier -> Add, Subtract, Multiply, .and., .or., .eqv., .neqv., +// min, max, iand, ior, ieor struct OmpReductionOperator { UNION_CLASS_BOILERPLATE(OmpReductionOperator); - ENUM_CLASS(ProcedureOperator, MIN, MAX, IAND, IOR, IEOR) - ENUM_CLASS(BinaryOperator, Add, Subtract, Multiply, AND, OR, EQV, NEQV) - std::variant u; + std::variant, ProcedureDesignator> u; }; // REDUCTION(reduction-identifier: list) @@ -3331,16 +3340,13 @@ struct OmpReductionClause { std::tuple> t; }; -// DEPEND(SOURCE | SINK: vec | DEPEND((IN | OUT | INOUT) : list) -// vec -> iterator_variable [ +/- d1], x2 [ +/- d2], ... -// d1 -> non-negative-constant -// list -> names | array-sections - +// depend-vec-length -> +/- non-negative-constant struct OmpDependSinkVecLength { TUPLE_CLASS_BOILERPLATE(OmpDependSinkVecLength); std::tuple, ScalarIntConstantExpr> t; }; +// depend-vec -> iterator_variable [+/- depend-vec-length] struct OmpDependSinkVec { TUPLE_CLASS_BOILERPLATE(OmpDependSinkVec); std::tuple> t; @@ -3351,6 +3357,7 @@ struct OmpDependenceType { WRAPPER_CLASS_BOILERPLATE(OmpDependenceType, Type); }; +// DEPEND(SOURCE | SINK: vec | DEPEND((IN | OUT | INOUT) : list) struct OmpDependClause { UNION_CLASS_BOILERPLATE(OmpDependClause); EMPTY_CLASS(Source); @@ -3362,6 +3369,9 @@ struct OmpDependClause { std::variant u; }; +// NOWAIT +EMPTY_CLASS(OmpNowait); + // OpenMP Clauses struct OmpClause { UNION_CLASS_BOILERPLATE(OmpClause); @@ -3370,35 +3380,33 @@ struct OmpClause { EMPTY_CLASS(Mergeable); EMPTY_CLASS(Nogroup); EMPTY_CLASS(Notinbranch); - EMPTY_CLASS(Nowait); EMPTY_CLASS(Untied); WRAPPER_CLASS(Collapse, ScalarIntConstantExpr); - WRAPPER_CLASS(Copyin, std::list); - WRAPPER_CLASS(Copyprivate, std::list); + WRAPPER_CLASS(Copyin, OmpObjectList); + WRAPPER_CLASS(Copyprivate, OmpObjectList); WRAPPER_CLASS(Device, ScalarIntExpr); WRAPPER_CLASS(DistSchedule, ScalarIntExpr); WRAPPER_CLASS(Final, ScalarIntExpr); - WRAPPER_CLASS(Firstprivate, std::list); + WRAPPER_CLASS(Firstprivate, OmpObjectList); WRAPPER_CLASS(From, std::list); WRAPPER_CLASS(Grainsize, ScalarIntExpr); - WRAPPER_CLASS(Lastprivate, std::list); - WRAPPER_CLASS(Link, std::list); + WRAPPER_CLASS(Lastprivate, OmpObjectList); WRAPPER_CLASS(NumTasks, ScalarIntExpr); WRAPPER_CLASS(NumTeams, ScalarIntExpr); WRAPPER_CLASS(NumThreads, ScalarIntExpr); WRAPPER_CLASS(Ordered, std::optional); WRAPPER_CLASS(Priority, ScalarIntExpr); - WRAPPER_CLASS(Private, std::list); + WRAPPER_CLASS(Private, OmpObjectList); WRAPPER_CLASS(Safelen, ScalarIntConstantExpr); - WRAPPER_CLASS(Shared, std::list); + WRAPPER_CLASS(Shared, OmpObjectList); WRAPPER_CLASS(Simdlen, ScalarIntConstantExpr); WRAPPER_CLASS(ThreadLimit, ScalarIntExpr); WRAPPER_CLASS(To, std::list); WRAPPER_CLASS(Uniform, std::list); WRAPPER_CLASS(UseDevicePtr, std::list); - std::variant); + +// SECTIONS, PARALLEL SECTIONS +WRAPPER_CLASS(OmpEndSections, std::optional); +WRAPPER_CLASS(OmpEndParallelSections, std::optional); +EMPTY_CLASS(OmpSection); + +struct OpenMPSectionsConstruct { + TUPLE_CLASS_BOILERPLATE(OpenMPSectionsConstruct); + std::tuple t; +}; + +struct OpenMPParallelSectionsConstruct { + TUPLE_CLASS_BOILERPLATE(OpenMPParallelSectionsConstruct); + std::tuple t; +}; + +// WORKSHARE +EMPTY_CLASS(OmpEndWorkshare); +struct OpenMPWorkshareConstruct { + TUPLE_CLASS_BOILERPLATE(OpenMPWorkshareConstruct); + std::tuple> t; +}; + +// SINGLE +WRAPPER_CLASS(OmpEndSingle, OmpClauseList); +struct OpenMPSingleConstruct { + TUPLE_CLASS_BOILERPLATE(OpenMPSingleConstruct); + std::tuple t; +}; + +// OpenMP directive enclosing block +struct OmpBlockDirective { + UNION_CLASS_BOILERPLATE(OmpBlockDirective); + EMPTY_CLASS(Master); + EMPTY_CLASS(Ordered); + EMPTY_CLASS(ParallelWorkshare); + EMPTY_CLASS(Parallel); + EMPTY_CLASS(TargetData); + EMPTY_CLASS(TargetParallel); + EMPTY_CLASS(TargetTeams); + EMPTY_CLASS(Target); + EMPTY_CLASS(Taskgroup); + EMPTY_CLASS(Task); + EMPTY_CLASS(Teams); + std::variant + u; +}; + +struct OmpDeclareTargetMapType { + ENUM_CLASS(Type, Link, To) + WRAPPER_CLASS_BOILERPLATE(OmpDeclareTargetMapType, Type); +}; + +struct OpenMPDeclareTargetConstruct { + UNION_CLASS_BOILERPLATE(OpenMPDeclareTargetConstruct); + struct WithClause { + BOILERPLATE(WithClause); + WithClause(OmpDeclareTargetMapType &&m, OmpObjectList &&n) + : maptype(std::move(m)), names(std::move(n)) {} + OmpDeclareTargetMapType maptype; + OmpObjectList names; + }; + struct WithExtendedList { + BOILERPLATE(WithExtendedList); + WithExtendedList(OmpObjectList &&n) : names(std::move(n)) {} + OmpObjectList names; + }; + EMPTY_CLASS(Implicit); + std::variant u; +}; + +struct OmpReductionCombiner { + UNION_CLASS_BOILERPLATE(OmpReductionCombiner); + WRAPPER_CLASS(FunctionCombiner, Call); + std::variant u; +}; + +WRAPPER_CLASS(OmpReductionInitializerClause, common::Indirection); + +struct OpenMPDeclareReductionConstruct { + TUPLE_CLASS_BOILERPLATE(OpenMPDeclareReductionConstruct); + std::tuple, + OmpReductionCombiner, std::optional> + t; +}; + +struct OpenMPDeclareSimdConstruct { + TUPLE_CLASS_BOILERPLATE(OpenMPDeclareSimdConstruct); + std::tuple, OmpClauseList> t; +}; + +struct OpenMPDeclarativeConstruct { + UNION_CLASS_BOILERPLATE(OpenMPDeclarativeConstruct); + WRAPPER_CLASS(Threadprivate, OmpObjectList); + std::variant + u; +}; + +// CRITICAL [Name] END CRITICAL [Name] +WRAPPER_CLASS(OmpEndCritical, std::optional); +struct OpenMPCriticalConstruct { + TUPLE_CLASS_BOILERPLATE(OpenMPCriticalConstruct); + WRAPPER_CLASS(Hint, ConstantExpr); + std::tuple, std::optional, Block, OmpEndCritical> t; +}; + +// END ATOMIC +EMPTY_CLASS(OmpEndAtomic); + +// ATOMIC READ +struct OmpAtomicRead { + TUPLE_CLASS_BOILERPLATE(OmpAtomicRead); + EMPTY_CLASS(SeqCst1); + EMPTY_CLASS(SeqCst2); + std::tuple, std::optional, + Statement, std::optional> + t; +}; + +// ATOMIC WRITE +struct OmpAtomicWrite { + TUPLE_CLASS_BOILERPLATE(OmpAtomicWrite); + EMPTY_CLASS(SeqCst1); + EMPTY_CLASS(SeqCst2); + std::tuple, std::optional, + Statement, std::optional> + t; +}; + +// ATOMIC UPDATE +struct OmpAtomicUpdate { + TUPLE_CLASS_BOILERPLATE(OmpAtomicUpdate); + EMPTY_CLASS(SeqCst1); + EMPTY_CLASS(SeqCst2); + std::tuple, std::optional, + Statement, std::optional> + t; +}; + +// ATOMIC CAPTURE +struct OmpAtomicCapture { + TUPLE_CLASS_BOILERPLATE(OmpAtomicCapture); + EMPTY_CLASS(SeqCst1); + EMPTY_CLASS(SeqCst2); + WRAPPER_CLASS(Stmt1, Statement); + WRAPPER_CLASS(Stmt2, Statement); + std::tuple, std::optional, Stmt1, Stmt2, + OmpEndAtomic> + t; +}; + +// ATOMIC +struct OmpAtomic { + TUPLE_CLASS_BOILERPLATE(OmpAtomic); + EMPTY_CLASS(SeqCst); + std::tuple, Statement, + std::optional> + t; +}; + +struct OpenMPAtomicConstruct { + UNION_CLASS_BOILERPLATE(OpenMPAtomicConstruct); + std::variant + u; +}; + struct OmpLoopDirective { UNION_CLASS_BOILERPLATE(OmpLoopDirective); - WRAPPER_CLASS(DistributeParallelDoSimd, std::list); - WRAPPER_CLASS(DistributeParallelDo, std::list); - WRAPPER_CLASS(DistributeSimd, std::list); - WRAPPER_CLASS(Distribute, std::list); - WRAPPER_CLASS(DoSimd, std::list); - WRAPPER_CLASS(Do, std::list); - WRAPPER_CLASS(ParallelDoSimd, std::list); - WRAPPER_CLASS(ParallelDo, std::list); - WRAPPER_CLASS(Simd, std::list); - WRAPPER_CLASS(TargetParallelDoSimd, std::list); - WRAPPER_CLASS(TargetParallelDo, std::list); - WRAPPER_CLASS(TargetTeamsDistributeParallelDoSimd, std::list); - WRAPPER_CLASS(TargetTeamsDistributeParallelDo, std::list); - WRAPPER_CLASS(TargetTeamsDistributeSimd, std::list); - WRAPPER_CLASS(TargetTeamsDistribute, std::list); - WRAPPER_CLASS(TargetSimd, std::list); - WRAPPER_CLASS(TaskloopSimd, std::list); - WRAPPER_CLASS(Taskloop, std::list); - WRAPPER_CLASS(TeamsDistributeParallelDoSimd, std::list); - WRAPPER_CLASS(TeamsDistributeParallelDo, std::list); - WRAPPER_CLASS(TeamsDistributeSimd, std::list); - WRAPPER_CLASS(TeamsDistribute, std::list); + EMPTY_CLASS(DistributeParallelDoSimd); + EMPTY_CLASS(DistributeParallelDo); + EMPTY_CLASS(DistributeSimd); + EMPTY_CLASS(Distribute); + EMPTY_CLASS(ParallelDoSimd); + EMPTY_CLASS(ParallelDo); + EMPTY_CLASS(Do); + EMPTY_CLASS(DoSimd); + EMPTY_CLASS(Simd); + EMPTY_CLASS(TargetParallelDoSimd); + EMPTY_CLASS(TargetParallelDo); + EMPTY_CLASS(TargetTeamsDistributeParallelDoSimd); + EMPTY_CLASS(TargetTeamsDistributeParallelDo); + EMPTY_CLASS(TargetTeamsDistributeSimd); + EMPTY_CLASS(TargetTeamsDistribute); + EMPTY_CLASS(TargetSimd); + EMPTY_CLASS(TaskloopSimd); + EMPTY_CLASS(Taskloop); + EMPTY_CLASS(TeamsDistributeParallelDoSimd); + EMPTY_CLASS(TeamsDistributeParallelDo); + EMPTY_CLASS(TeamsDistributeSimd); + EMPTY_CLASS(TeamsDistribute); std::variant> t; +}; + +// FLUSH +WRAPPER_CLASS(OpenMPFlushConstruct, std::optional); + +// Standalone constructs struct OmpStandaloneDirective { UNION_CLASS_BOILERPLATE(OmpStandaloneDirective); - WRAPPER_CLASS(Barrier, std::list); - WRAPPER_CLASS(CancellationPoint, std::list); - WRAPPER_CLASS(Cancel, std::list); - WRAPPER_CLASS(Flush, std::list); - WRAPPER_CLASS(TargetEnterData, std::list); - WRAPPER_CLASS(TargetExitData, std::list); - WRAPPER_CLASS(TargetUpdate, std::list); - WRAPPER_CLASS(Taskwait, std::list); - WRAPPER_CLASS(Taskyield, std::list); - std::variant + EMPTY_CLASS(TargetEnterData); + EMPTY_CLASS(TargetExitData); + EMPTY_CLASS(TargetUpdate); + std::variant u; +}; + +EMPTY_CLASS(OpenMPTaskyieldConstruct); +EMPTY_CLASS(OpenMPTaskwaitConstruct); +EMPTY_CLASS(OpenMPBarrierConstruct); +WRAPPER_CLASS(OmpEndBlockDirective, common::Indirection); + +// DO / DO SIMD +WRAPPER_CLASS(OmpEndDoSimd, std::optional); +WRAPPER_CLASS(OmpEndDo, std::optional); +struct OpenMPEndLoopDirective { + UNION_CLASS_BOILERPLATE(OpenMPEndLoopDirective); + std::variant, common::Indirection, + common::Indirection> u; }; -struct OmpEndDirective { - UNION_CLASS_BOILERPLATE(OmpEndDirective); - std::variant u; +struct OpenMPBlockConstruct { + TUPLE_CLASS_BOILERPLATE(OpenMPBlockConstruct); + std::tuple t; }; struct OpenMPLoopConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPLoopConstruct); - std::tuple, DoConstruct, - std::optional> - t; + std::tuple t; }; -WRAPPER_CLASS(OpenMPStandaloneConstruct, Statement); +struct OpenMPStandaloneConstruct { + TUPLE_CLASS_BOILERPLATE(OpenMPStandaloneConstruct); + std::tuple t; +}; struct OpenMPConstruct { UNION_CLASS_BOILERPLATE(OpenMPConstruct); std::variant, - common::Indirection> + common::Indirection, + common::Indirection, + common::Indirection, + common::Indirection, + common::Indirection, + common::Indirection, + common::Indirection, + common::Indirection, + common::Indirection, + common::Indirection, + common::Indirection, + common::Indirection, + common::Indirection, + common::Indirection, OmpSection> u; }; diff --git a/flang/lib/parser/stmt-parser.h b/flang/lib/parser/stmt-parser.h index 8b07373043a2..d65602ef1c02 100644 --- a/flang/lib/parser/stmt-parser.h +++ b/flang/lib/parser/stmt-parser.h @@ -77,7 +77,8 @@ constexpr auto stmtErrorRecoveryStart{ignoredStatementPrefix}; constexpr auto skipBadLine{SkipPast<'\n'>{} >> construct()}; constexpr auto executionPartErrorRecovery{stmtErrorRecoveryStart >> !"END"_tok >> !"CONTAINS"_tok >> !"ELSE"_tok >> !"CASE"_tok >> - !"TYPE IS"_tok >> !"CLASS"_tok >> !"RANK"_tok >> skipBadLine}; + !"TYPE IS"_tok >> !"CLASS"_tok >> !"RANK"_tok >> + !("!$OMP "_sptok >> "END"_tok) >> skipBadLine}; } // namespace Fortran::parser #endif // FORTRAN_PARSER_STMT_PARSER_H_ diff --git a/flang/lib/parser/type-parsers.h b/flang/lib/parser/type-parsers.h index fd3cae1daf77..85a42cf8bef9 100644 --- a/flang/lib/parser/type-parsers.h +++ b/flang/lib/parser/type-parsers.h @@ -143,6 +143,8 @@ constexpr Parser entryStmt; // R1541 constexpr Parser containsStmt; // R1543 constexpr Parser compilerDirective; constexpr Parser openmpConstruct; +constexpr Parser openmpDeclarativeConstruct; +constexpr Parser openmpEndLoopDirective; } // namespace Fortran::parser #endif // FORTRAN_PARSER_TYPE_PARSERS_H_ diff --git a/flang/lib/parser/unparse.cc b/flang/lib/parser/unparse.cc index 6bc5a64346b1..c94c8e8210b7 100644 --- a/flang/lib/parser/unparse.cc +++ b/flang/lib/parser/unparse.cc @@ -1673,15 +1673,16 @@ public: Walk(std::get(x.t)); } // OpenMP Clauses & Directives - void Unparse(const OmpNameList &x) { - bool isCommon{ - std::get(x.t) == OmpNameList::Kind::Common}; + void Unparse(const OmpObject &x) { + bool isCommon{std::get(x.t) == OmpObject::Kind::Common}; const char *slash{isCommon ? "/" : ""}; - Put(slash), Walk(std::get(x.t)), Put(slash); + Put(slash), Walk(std::get(x.t)), Put(slash); } + void Unparse(const OmpMapType::Always &x) { Word("ALWAYS,"); } void Unparse(const OmpMapClause &x) { - Word(" MAP("), Walk(std::get>(x.t), ":"); - Walk(std::get>(x.t), ", "); + Word("MAP("); + Walk(std::get>(x.t), ":"); + Walk(std::get(x.t)); Put(") "); } void Unparse(const OmpScheduleModifier &x) { @@ -1689,48 +1690,36 @@ public: Walk(",", std::get>(x.t)); } void Unparse(const OmpScheduleClause &x) { - Word(" SCHEDULE("); + Word("SCHEDULE("); Walk(std::get>(x.t)); Walk(std::get(x.t)); Walk(",", std::get>(x.t)); Put(")"); } void Unparse(const OmpAlignedClause &x) { - Word(" ALIGNED("), Walk(std::get>(x.t), ","); + Word("ALIGNED("), Walk(std::get>(x.t), ","); Walk(std::get>(x.t)); Put(") "); } void Unparse(const OmpIfClause &x) { - Word(" IF("), + Word("IF("), Walk(std::get>(x.t), ":"); Walk(std::get(x.t)); Put(") "); } void Unparse(const OmpLinearClause::WithoutModifier &x) { - Word(" LINEAR("), Walk(x.names, ", "); + Word("LINEAR("), Walk(x.names, ", "); Walk(":", x.step); Put(")"); } void Unparse(const OmpLinearClause::WithModifier &x) { - Word(" LINEAR("), Walk(x.modifier), Put("("), Walk(x.names, ","), Put(")"); + Word("LINEAR("), Walk(x.modifier), Put("("), Walk(x.names, ","), Put(")"); Walk(":", x.step); Put(")"); } - void Unparse(const OmpReductionOperator::BinaryOperator &x) { - switch (x) { - case OmpReductionOperator::BinaryOperator::Add: Put("+"); break; - case OmpReductionOperator::BinaryOperator::Subtract: Put("-"); break; - case OmpReductionOperator::BinaryOperator::Multiply: Put("*"); break; - case OmpReductionOperator::BinaryOperator::AND: Word(".AND."); break; - case OmpReductionOperator::BinaryOperator::OR: Word(".OR."); break; - case OmpReductionOperator::BinaryOperator::EQV: Word(".EQV."); break; - case OmpReductionOperator::BinaryOperator::NEQV: Word(".NEQV."); break; - default: break; - } - } void Unparse(const OmpReductionClause &x) { - Word(" REDUCTION("); + Word("REDUCTION("); Walk(std::get(x.t)); Put(":"); Walk(std::get>(x.t), ","); @@ -1745,35 +1734,48 @@ public: Walk(std::get>(x.t)); } void Unparse(const OmpDependClause::InOut &x) { + Put("("); Walk(std::get(x.t)); Put(":"); Walk(std::get>(x.t), ","); + Put(")"); } - void Unparse(const OmpDependClause &x) { - std::visit(common::visitors{[&](const OmpDependClause::Source &y) { - Word("DEPEND(SOURCE)"); - }, - [&](const OmpDependClause::Sink &y) { - Word("DEPEND(SINK:"); - Walk(y.v); - Put(")"); - }, - [&](const OmpDependClause::InOut &y) { - Word("DEPEND("); - Walk(y.t); - Put(")"); - }}, + bool Pre(const OmpDependClause &x) { + return std::visit(common::visitors{[&](const OmpDependClause::Source &y) { + Word("DEPEND(SOURCE)"); + return false; + }, + [&](const OmpDependClause::Sink &y) { + Word("DEPEND(SINK:"); + Walk(y.v); + Put(")"); + return false; + }, + [&](const OmpDependClause::InOut &y) { + Word("DEPEND"); + return true; + }}, x.u); } + bool Pre(const OmpDefaultClause &x) { + Word("DEFAULT("); + return true; + } + void Post(const OmpDefaultClause &x) { Put(")"); } + bool Pre(const OmpProcBindClause &x) { + Word("PROC_BIND("); + return true; + } + void Post(const OmpProcBindClause &x) { Put(")"); } void Before(const OmpClause::Defaultmap &x) { - Word(" DEFAULTMAP(TOFROM:SCALAR)"); + Word("DEFAULTMAP(TOFROM:SCALAR)"); } void Before(const OmpClause::Inbranch &x) { Word("INBRANCH"); } void Before(const OmpClause::Mergeable &x) { Word("MERGEABLE"); } void Before(const OmpClause::Nogroup &x) { Word("NOGROUP"); } void Before(const OmpClause::Notinbranch &x) { Word("NOTINBRANCH"); } - void Before(const OmpClause::Nowait &x) { Word("NOWAIT"); } void Before(const OmpClause::Untied &x) { Word("UNTIED"); } + void Unparse(const OmpNowait &) { Word("NOWAIT"); } void Unparse(const OmpClause::Collapse &x) { Word("COLLAPSE("); Walk(x.v); @@ -1781,12 +1783,12 @@ public: } void Unparse(const OmpClause::Copyin &x) { Word("COPYIN("); - Walk(x.v, ","); + Walk(x.v); Put(")"); } void Unparse(const OmpClause::Copyprivate &x) { Word("COPYPRIVATE("); - Walk(x.v, ","); + Walk(x.v); Put(")"); } void Unparse(const OmpClause::Device &x) { @@ -1806,7 +1808,7 @@ public: } void Unparse(const OmpClause::Firstprivate &x) { Word("FIRSTPRIVATE("); - Walk(x.v, ","); + Walk(x.v); Put(")"); } void Unparse(const OmpClause::From &x) { @@ -1821,12 +1823,7 @@ public: } void Unparse(const OmpClause::Lastprivate &x) { Word("LASTPRIVATE("); - Walk(x.v, ","); - Put(")"); - } - void Unparse(const OmpClause::Link &x) { - Word("LINK("); - Walk(x.v, ","); + Walk(x.v); Put(")"); } void Unparse(const OmpClause::NumTasks &x) { @@ -1855,7 +1852,7 @@ public: } void Unparse(const OmpClause::Private &x) { Word("PRIVATE("); - Walk(x.v, ","); + Walk(x.v); Put(")"); } void Unparse(const OmpClause::Safelen &x) { @@ -1875,7 +1872,7 @@ public: } void Unparse(const OmpClause::Shared &x) { Word("SHARED("); - Walk(x.v, ","); + Walk(x.v); Put(")"); } void Unparse(const OmpClause::To &x) { @@ -1896,159 +1893,401 @@ public: void Unparse(const OmpLoopDirective &x) { std::visit( common::visitors{ - [&](const OmpLoopDirective::DistributeParallelDoSimd &y) { + [&](const OmpLoopDirective::DistributeParallelDoSimd &) { Word("DISTRIBUTE PARALLEL DO SIMD "); - Walk(y.v, " "); }, - [&](const OmpLoopDirective::DistributeParallelDo &y) { + [&](const OmpLoopDirective::DistributeParallelDo &) { Word("DISTRIBUTE PARALLEL DO "); - Walk(y.v, " "); }, - [&](const OmpLoopDirective::DistributeSimd &y) { + [&](const OmpLoopDirective::DistributeSimd &) { Word("DISTRIBUTE SIMD "); - Walk(y.v, " "); }, - [&](const OmpLoopDirective::Distribute &y) { - Word("DISTRIBUTE "); - Walk(y.v, " "); - }, - [&](const OmpLoopDirective::DoSimd &y) { - Word("DO SIMD "); - Walk(y.v, " "); - }, - [&](const OmpLoopDirective::Do &y) { - Word("DO "); - Walk(y.v, " "); - }, - [&](const OmpLoopDirective::ParallelDoSimd &y) { + [&](const OmpLoopDirective::Distribute &) { Word("DISTRIBUTE "); }, + [&](const OmpLoopDirective::ParallelDoSimd &) { Word("PARALLEL DO SIMD "); - Walk(y.v, " "); }, - [&](const OmpLoopDirective::ParallelDo &y) { - Word("PARALLEL DO "); - Walk(y.v, " "); - }, - [&](const OmpLoopDirective::Simd &y) { - Word("SIMD "); - Walk(y.v, " "); - }, - [&](const OmpLoopDirective::TargetParallelDoSimd &y) { + [&](const OmpLoopDirective::ParallelDo &) { Word("PARALLEL DO "); }, + [&](const OmpLoopDirective::Do &) { Word("DO "); }, + [&](const OmpLoopDirective::DoSimd &) { Word("Do SIMD "); }, + [&](const OmpLoopDirective::Simd &) { Word("SIMD "); }, + [&](const OmpLoopDirective::TargetParallelDoSimd &) { Word("TARGET PARALLEL DO SIMD "); - Walk(y.v, " "); }, - [&](const OmpLoopDirective::TargetParallelDo &y) { + [&](const OmpLoopDirective::TargetParallelDo &) { Word("TARGET PARALLEL DO "); - Walk(y.v, " "); }, - [&](const OmpLoopDirective::TargetTeamsDistributeParallelDoSimd - &y) { + [&](const OmpLoopDirective::TargetTeamsDistributeParallelDoSimd &) { Word("TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD "); - Walk(y.v, " "); }, - [&](const OmpLoopDirective::TargetTeamsDistributeParallelDo &y) { + [&](const OmpLoopDirective::TargetTeamsDistributeParallelDo &) { Word("TARGET TEAMS DISTRIBUTE PARALLEL DO "); - Walk(y.v, " "); }, - [&](const OmpLoopDirective::TargetTeamsDistributeSimd &y) { + [&](const OmpLoopDirective::TargetTeamsDistributeSimd &) { Word("TARGET TEAMS DISTRIBUTE SIMD "); - Walk(y.v, " "); }, - [&](const OmpLoopDirective::TargetTeamsDistribute &y) { + [&](const OmpLoopDirective::TargetTeamsDistribute &) { Word("TARGET TEAMS DISTRIBUTE "); - Walk(y.v, " "); }, - [&](const OmpLoopDirective::TargetSimd &y) { - Word("TARGET SIMD "); - Walk(y.v, " "); - }, - [&](const OmpLoopDirective::TaskloopSimd &y) { + [&](const OmpLoopDirective::TargetSimd &) { Word("TARGET SIMD "); }, + [&](const OmpLoopDirective::TaskloopSimd &) { Word("TASKLOOP SIMD "); - Walk(y.v, " "); }, - [&](const OmpLoopDirective::Taskloop &y) { - Word("TASKLOOP "); - Walk(y.v, " "); - }, - [&](const OmpLoopDirective::TeamsDistributeParallelDoSimd &y) { + [&](const OmpLoopDirective::Taskloop &) { Word("TASKLOOP "); }, + [&](const OmpLoopDirective::TeamsDistributeParallelDoSimd &) { Word("TEAMS DISTRIBUTE PARALLEL DO SIMD "); - Walk(y.v, " "); }, - [&](const OmpLoopDirective::TeamsDistributeParallelDo &y) { + [&](const OmpLoopDirective::TeamsDistributeParallelDo &) { Word("TEAMS DISTRIBUTE PARALLEL DO "); - Walk(y.v, " "); }, - [&](const OmpLoopDirective::TeamsDistributeSimd &y) { + [&](const OmpLoopDirective::TeamsDistributeSimd &) { Word("TEAMS DISTRIBUTE SIMD "); - Walk(y.v, " "); }, - [&](const OmpLoopDirective::TeamsDistribute &y) { + [&](const OmpLoopDirective::TeamsDistribute &) { Word("TEAMS DISTRIBUTE "); - Walk(y.v, " "); }}, x.u); - Put("\n"); - Indent(); } + void Unparse(const OmpObjectList &x) { Walk(x.v, ","); } void Unparse(const OmpStandaloneDirective &x) { - std::visit(common::visitors{[&](const OmpStandaloneDirective::Barrier &y) { - Word("BARRIER "); - Walk(y.v, " "); - }, - [&](const OmpStandaloneDirective::CancellationPoint &y) { - Word("CANCELLATION POINT "); - Walk(y.v, " "); - }, - [&](const OmpStandaloneDirective::Cancel &y) { - Word("CANCEL "); - Walk(y.v, " "); - }, - [&](const OmpStandaloneDirective::Flush &y) { - Word("FLUSH "); - Walk(y.v, " "); - }, - [&](const OmpStandaloneDirective::TargetEnterData &y) { - Word("TARGET ENTER DATA "); - Walk(y.v, " "); - }, - [&](const OmpStandaloneDirective::TargetExitData &y) { - Word("TARGET EXIT DATA "); - Walk(y.v, " "); - }, - [&](const OmpStandaloneDirective::TargetUpdate &y) { - Word("TARGET UPDATE "); - Walk(y.v, " "); - }, - [&](const OmpStandaloneDirective::Taskwait &y) { - Word("TASKWAIT "); - Walk(y.v, " "); - }, - [&](const OmpStandaloneDirective::Taskyield &y) { - Word("TASKYIELD "); - Walk(y.v, " "); - }}, + std::visit( + common::visitors{[&](const OmpStandaloneDirective::TargetEnterData &) { + Word("TARGET ENTER DATA "); + }, + [&](const OmpStandaloneDirective::TargetExitData &) { + Word("TARGET EXIT DATA "); + }, + [&](const OmpStandaloneDirective::TargetUpdate &) { + Word("TARGET UPDATE "); + }}, x.u); + } + void Unparse(const OmpBlockDirective &x) { + std::visit( + common::visitors{ + [&](const OmpBlockDirective::Master &y) { Word("MASTER"); }, + [&](const OmpBlockDirective::Ordered &) { Word("ORDERED "); }, + [&](const OmpBlockDirective::ParallelWorkshare &) { + Word("PARALLEL WORKSHARE "); + }, + [&](const OmpBlockDirective::Parallel &) { Word("PARALLEL "); }, + [&](const OmpBlockDirective::TargetData &) { + Word("TARGET DATA "); + }, + [&](const OmpBlockDirective::TargetParallel &) { + Word("TARGET PARALLEL "); + }, + [&](const OmpBlockDirective::TargetTeams &) { + Word("TARGET TEAMS "); + }, + [&](const OmpBlockDirective::Target &) { Word("TARGET "); }, + [&](const OmpBlockDirective::Taskgroup &) { Word("TASKGROUP "); }, + [&](const OmpBlockDirective::Task &) { Word("TASK "); }, + [&](const OmpBlockDirective::Teams &) { Word("TEAMS "); }}, + x.u); + } + void Unparse(const OmpAtomic &x) { + BeginOpenMP(); + Word("!$OMP ATOMIC"); + Walk(std::get>(x.t), " SEQ_CST"); Put("\n"); - Indent(); + EndOpenMP(); + Walk(std::get>(x.t)); + BeginOpenMP(); + Walk(std::get>(x.t), "!$OMP END ATOMIC\n"); + EndOpenMP(); } - void Unparse(const OmpEndDirective &x) { - Outdent(); - std::visit(common::visitors{[&](const OmpLoopDirective &y) { - Word("!$OMP END "); - Walk(y); - }}, + void Unparse(const OmpAtomicCapture &x) { + BeginOpenMP(); + Word("!$OMP ATOMIC"); + Walk(std::get>(x.t), " SEQ_CST,"); + Word(" CAPTURE"); + Walk(std::get>(x.t), " ,SEQ_CST"); + Put("\n"); + EndOpenMP(); + Walk(std::get(x.t)); + Put("\n"); + Walk(std::get(x.t)); + BeginOpenMP(); + Word("!$OMP END ATOMIC\n"); + EndOpenMP(); + } + void Unparse(const OmpAtomicRead &x) { + BeginOpenMP(); + Word("!$OMP ATOMIC"); + Walk(std::get>(x.t), " SEQ_CST,"); + Word(" READ"); + Walk(std::get>(x.t), " ,SEQ_CST"); + Put("\n"); + EndOpenMP(); + Walk(std::get>(x.t)); + BeginOpenMP(); + Walk(std::get>(x.t), "!$OMP END ATOMIC\n"); + EndOpenMP(); + } + void Unparse(const OmpAtomicUpdate &x) { + BeginOpenMP(); + Word("!$OMP ATOMIC"); + Walk(std::get>(x.t), " SEQ_CST,"); + Word(" UPDATE"); + Walk(std::get>(x.t), " ,SEQ_CST"); + Put("\n"); + EndOpenMP(); + Walk(std::get>(x.t)); + BeginOpenMP(); + Walk(std::get>(x.t), "!$OMP END ATOMIC\n"); + EndOpenMP(); + } + void Unparse(const OmpAtomicWrite &x) { + BeginOpenMP(); + Word("!$OMP ATOMIC"); + Walk(std::get>(x.t), " SEQ_CST,"); + Word(" WRITE"); + Walk(std::get>(x.t), " ,SEQ_CST"); + Put("\n"); + EndOpenMP(); + Walk(std::get>(x.t)); + BeginOpenMP(); + Walk(std::get>(x.t), "!$OMP END ATOMIC\n"); + EndOpenMP(); + } + void Unparse(const OmpEndCritical &x) { + Walk(" (", x.v, ")"); + EndOpenMP(); + } + void Unparse(const OpenMPCriticalConstruct &x) { + BeginOpenMP(); + Word("!$OMP CRITICAL"); + Walk(" (", std::get>(x.t), ")"); + Walk(" HINT(", std::get>(x.t), + ")"); + Put("\n"); + EndOpenMP(); + Walk(std::get(x.t), ""); + BeginOpenMP(); + Word("!$OMP END CRITICAL"); + Walk(std::get(x.t)); + Put("\n"); + EndOpenMP(); + } + void Unparse(const OpenMPDeclareTargetConstruct::WithClause &x) { + Walk(x.maptype), Put("("), Walk(x.names), Put(")"); + } + void Unparse(const OpenMPDeclareTargetConstruct::WithExtendedList &x) { + Put("("), Walk(x.names), Put(")"); + } + void Unparse(const OmpReductionInitializerClause &x) { + Word(" INITIALIZER(OMP_PRIV = "); + Walk(x.v); + Put(")"); + } + void Unparse(const OmpReductionCombiner::FunctionCombiner &x) { + const auto &pd = std::get(x.v.t); + const auto &args = std::get>(x.v.t); + Walk(pd); + if (args.empty()) { + if (std::holds_alternative(pd.u)) { + Put("()"); + } + } else { + Walk("(", args, ", ", ")"); + } + } + void Unparse(const OpenMPDeclareReductionConstruct &x) { + Put("("); + Walk(std::get(x.t)), Put(" : "); + Walk(std::get>(x.t), ","), Put(" : "); + Walk(std::get(x.t)); + Put(")"); + Walk(std::get>(x.t)); + } + bool Pre(const OpenMPDeclarativeConstruct &x) { + BeginOpenMP(); + Word("!$OMP "); + return std::visit( + common::visitors{[&](const OpenMPDeclareReductionConstruct &y) { + Word("DECLARE REDUCTION "); + return true; + }, + [&](const OpenMPDeclareSimdConstruct &y) { + Word("DECLARE SIMD "); + Walk("(", std::get>(y.t), ")"); + Walk(std::get(y.t)); + Put("\n"); + EndOpenMP(); + return false; + }, + [&](const OpenMPDeclareTargetConstruct &y) { + Word("DECLARE TARGET "); + return true; + }, + [&](const OpenMPDeclarativeConstruct::Threadprivate &y) { + Word("THREADPRIVATE ("); + return true; + }}, x.u); } - void Unparse(const OpenMPStandaloneConstruct &x) { - Outdent(); - Word("!$OMP "); - Walk(x.v); + void Post(const OpenMPDeclarativeConstruct &x) { + Put("\n"); + EndOpenMP(); } - bool Pre(const OpenMPLoopConstruct &x) { - Outdent(); - Word("!$OMP "); + void Post(const OpenMPDeclarativeConstruct::Threadprivate &x) { + Put(")\n"); + EndOpenMP(); + } + void Unparse(const OmpEndDoSimd &x) { + BeginOpenMP(); + Word("DO SIMD "); + Walk(x.v); + EndOpenMP(); + } + void Unparse(const OmpEndDo &x) { + BeginOpenMP(); + Word("DO "); + Walk(x.v); + EndOpenMP(); + } + bool Pre(const OpenMPBarrierConstruct &x) { + BeginOpenMP(); + Word("!$OMP BARRIER"); + Put("\n"); + EndOpenMP(); + return false; + } + void Unparse(const OpenMPSingleConstruct &x) { + BeginOpenMP(); + Word("!$OMP SINGLE"); + Walk(std::get(x.t)); + EndOpenMP(); + Put("\n"); + Walk(std::get(x.t), ""); + BeginOpenMP(); + Word("!$OMP END SINGLE "); + Walk(std::get(x.t)); + Put("\n"); + EndOpenMP(); + } + void Unparse(const OmpSection &x) { + BeginOpenMP(); + Word("!$OMP SECTION"); + Put("\n"); + EndOpenMP(); + } + void Unparse(const OpenMPSectionsConstruct &x) { + BeginOpenMP(); + Word("!$OMP SECTIONS"); + Walk(std::get(x.t)); + Put("\n"); + EndOpenMP(); + Walk(std::get(x.t), ""); + BeginOpenMP(); + Word("!$OMP END SECTIONS"); + Put("\n"); + EndOpenMP(); + } + void Unparse(const OpenMPParallelSectionsConstruct &x) { + BeginOpenMP(); + Word("!$OMP PARALLEL SECTIONS"); + Walk(std::get(x.t)); + Put("\n"); + EndOpenMP(); + Walk(std::get(x.t), ""); + BeginOpenMP(); + Word("!$OMP END PARALLEL SECTIONS"); + Put("\n"); + EndOpenMP(); + } + void Unparse(const OpenMPWorkshareConstruct &x) { + BeginOpenMP(); + Word("!$OMP WORKSHARE"); + Put("\n"); + EndOpenMP(); + Walk(std::get(x.t), ""); + BeginOpenMP(); + Word("!$OMP END WORKSHARE "); + Walk(std::get>(x.t)); + Put("\n"); + EndOpenMP(); + } + bool Pre(const OpenMPTaskyieldConstruct &x) { + BeginOpenMP(); + Word("!$OMP TASKYIELD"); + Put("\n"); + EndOpenMP(); + return false; + } + bool Pre(const OpenMPTaskwaitConstruct &x) { + BeginOpenMP(); + Word("!$OMP TASKWAIT"); + Put("\n"); + EndOpenMP(); + return false; + } + void Unparse(const OpenMPCancellationPointConstruct &x) { + BeginOpenMP(); + Word("!$OMP CANCELLATION POINT "); + Walk(x.v); + Put("\n"); + EndOpenMP(); + } + void Unparse(const OpenMPCancelConstruct &x) { + BeginOpenMP(); + Word("!$OMP CANCEL "); + Walk(std::get(x.t)); + Walk(std::get>(x.t)); + Put("\n"); + EndOpenMP(); + } + void Unparse(const OpenMPFlushConstruct &x) { + BeginOpenMP(); + Word("!$OMP FLUSH"); + if ((x.v).has_value()) { + Put("("); + Walk(x.v); + Put(")"); + } + Put("\n"); + EndOpenMP(); + } + bool Pre(const OpenMPEndLoopDirective &x) { + BeginOpenMP(); + Word("!$OMP END "); return true; } - + void Post(const OpenMPEndLoopDirective &x) { + Put("\n"); + EndOpenMP(); + } + void Unparse(const OmpClauseList &x) { Walk(" ", x.v, " "); } + void Unparse(const OpenMPStandaloneConstruct &x) { + BeginOpenMP(); + Word("!$OMP "); + Walk(std::get(x.t)); + Walk(std::get(x.t)); + Put("\n"); + EndOpenMP(); + } + void Unparse(const OpenMPBlockConstruct &x) { + BeginOpenMP(); + Word("!$OMP "); + Walk(std::get(x.t)); + Walk(std::get(x.t)); + Put("\n"); + EndOpenMP(); + Walk(std::get(x.t), ""); + BeginOpenMP(); + Word("!$OMP END "); + Walk(std::get(x.t)); + Put("\n"); + EndOpenMP(); + } + void Unparse(const OpenMPLoopConstruct &x) { + BeginOpenMP(); + Word("!$OMP "); + Walk(std::get(x.t)); + Walk(std::get(x.t)); + Put("\n"); + EndOpenMP(); + } void Unparse(const BasedPointerStmt &x) { Word("POINTER ("), Walk(std::get<0>(x.t)), Put(", "); Walk(std::get<1>(x.t)); @@ -2116,13 +2355,13 @@ public: WALK_NESTED_ENUM(OmpDefaultClause, Type) // OMP DEFAULT WALK_NESTED_ENUM(OmpScheduleModifierType, ModType) // OMP schedule-modifier WALK_NESTED_ENUM(OmpLinearModifier, Type) // OMP linear-modifier - WALK_NESTED_ENUM( - OmpReductionOperator, ProcedureOperator) // OMP reduction-identifier WALK_NESTED_ENUM(OmpDependenceType, Type) // OMP dependence-type - WALK_NESTED_ENUM(OmpMapClause, Type) // OMP map-type + WALK_NESTED_ENUM(OmpMapType, Type) // OMP map-type WALK_NESTED_ENUM(OmpScheduleClause, ScheduleType) // OMP schedule-type WALK_NESTED_ENUM( OmpIfClause, DirectiveNameModifier) // OMP directive-modifier + WALK_NESTED_ENUM(OmpDeclareTargetMapType, Type) // OMP DeclareTarget map-type + WALK_NESTED_ENUM(OmpCancelType, Type) // OMP cancel-type #undef WALK_NESTED_ENUM void Done() const { CHECK(indent_ == 0); } @@ -2139,6 +2378,8 @@ private: CHECK(indent_ >= indentationAmount_); indent_ -= indentationAmount_; } + void BeginOpenMP() { openmpDirective_ = true; } + void EndOpenMP() { openmpDirective_ = false; } // Call back to the traversal framework. template void Walk(const T &x) { @@ -2208,11 +2449,16 @@ private: std::set structureComponents_; Encoding encoding_{Encoding::UTF8}; bool capitalizeKeywords_{true}; + bool openmpDirective_{false}; bool backslashEscapes_{false}; preStatementType *preStatement_{nullptr}; }; void UnparseVisitor::Put(char ch) { + int sav = indent_; + if (openmpDirective_) { + indent_ = 0; + } if (column_ <= 1) { if (ch == '\n') { return; @@ -2228,10 +2474,18 @@ void UnparseVisitor::Put(char ch) { for (int j{0}; j < indent_; ++j) { out_ << ' '; } - out_ << '&'; - column_ = indent_ + 3; + if (openmpDirective_) { + out_ << "!$OMP&"; + column_ = 8; + } else { + out_ << '&'; + column_ = indent_ + 3; + } } out_ << ch; + if (openmpDirective_) { + indent_ = sav; + } } void UnparseVisitor::Put(const char *str) { diff --git a/flang/lib/semantics/dump-parse-tree.h b/flang/lib/semantics/dump-parse-tree.h index 00c95e201ff0..e0014e3b0f88 100644 --- a/flang/lib/semantics/dump-parse-tree.h +++ b/flang/lib/semantics/dump-parse-tree.h @@ -394,7 +394,46 @@ public: NODE(parser, ObjectDecl) NODE(parser, OldParameterStmt) NODE(parser, OmpAlignedClause) + NODE(parser, OpenMPAtomicConstruct) + NODE(parser, OmpEndAtomic) + NODE(parser, OpenMPCriticalConstruct) + NODE(parser::OpenMPCriticalConstruct, Hint) + NODE(parser, OmpEndCritical) + NODE(parser, OmpAtomic) + NODE(parser::OmpAtomic, SeqCst) + NODE(parser, OmpAtomicCapture) + NODE(parser::OmpAtomicCapture, SeqCst1) + NODE(parser::OmpAtomicCapture, SeqCst2) + NODE(parser::OmpAtomicCapture, Stmt1) + NODE(parser::OmpAtomicCapture, Stmt2) + NODE(parser, OmpAtomicRead) + NODE(parser::OmpAtomicRead, SeqCst1) + NODE(parser::OmpAtomicRead, SeqCst2) + NODE(parser, OmpAtomicUpdate) + NODE(parser::OmpAtomicUpdate, SeqCst1) + NODE(parser::OmpAtomicUpdate, SeqCst2) + NODE(parser, OmpAtomicWrite) + NODE(parser::OmpAtomicWrite, SeqCst1) + NODE(parser::OmpAtomicWrite, SeqCst2) + NODE(parser, OmpBlockDirective) + NODE(parser::OmpBlockDirective, Master) + NODE(parser::OmpBlockDirective, Ordered) + NODE(parser::OmpBlockDirective, Parallel) + NODE(parser::OmpBlockDirective, ParallelWorkshare) + NODE(parser, OpenMPSingleConstruct) + NODE(parser, OmpEndSingle) + NODE(parser, OpenMPWorkshareConstruct) + NODE(parser, OmpEndDo) + NODE(parser, OmpEndDoSimd) + NODE(parser::OmpBlockDirective, Target) + NODE(parser::OmpBlockDirective, TargetData) + NODE(parser::OmpBlockDirective, TargetParallel) + NODE(parser::OmpBlockDirective, TargetTeams) + NODE(parser::OmpBlockDirective, Task) + NODE(parser::OmpBlockDirective, Taskgroup) + NODE(parser::OmpBlockDirective, Teams) NODE(parser, OmpClause) + NODE(parser, OmpClauseList) NODE(parser::OmpClause, Collapse) NODE(parser::OmpClause, Copyin) NODE(parser::OmpClause, Copyprivate) @@ -407,11 +446,9 @@ public: NODE(parser::OmpClause, Grainsize) NODE(parser::OmpClause, Inbranch) NODE(parser::OmpClause, Lastprivate) - NODE(parser::OmpClause, Link) NODE(parser::OmpClause, Mergeable) NODE(parser::OmpClause, Nogroup) NODE(parser::OmpClause, Notinbranch) - NODE(parser::OmpClause, Nowait) NODE(parser::OmpClause, NumTasks) NODE(parser::OmpClause, NumTeams) NODE(parser::OmpClause, NumThreads) @@ -436,21 +473,37 @@ public: NODE(parser::OmpDependenceType, Type) NODE(parser, OmpDependSinkVec) NODE(parser, OmpDependSinkVecLength) - NODE(parser, OmpEndDirective) + NODE(parser, OmpEndBlockDirective) + NODE(parser, OmpIfClause) + NODE(parser::OmpIfClause, DirectiveNameModifier) NODE(parser, OmpLinearClause) NODE(parser::OmpLinearClause, WithModifier) NODE(parser::OmpLinearClause, WithoutModifier) NODE(parser, OmpLinearModifier) NODE(parser::OmpLinearModifier, Type) + NODE(parser, OpenMPDeclareReductionConstruct) + NODE(parser, OmpReductionInitializerClause) + NODE(parser, OmpReductionCombiner) + NODE(parser::OmpReductionCombiner, FunctionCombiner) + NODE(parser, OpenMPDeclareSimdConstruct) + NODE(parser, OmpDeclareTargetMapType) + NODE(parser::OmpDeclareTargetMapType, Type) + NODE(parser, OpenMPEndLoopDirective) + NODE(parser, OpenMPDeclareTargetConstruct) + NODE(parser::OpenMPDeclareTargetConstruct, Implicit) + NODE(parser::OpenMPDeclareTargetConstruct, WithClause) + NODE(parser::OpenMPDeclareTargetConstruct, WithExtendedList) + NODE(parser::OpenMPDeclarativeConstruct, Threadprivate) + NODE(parser, OpenMPLoopConstruct) NODE(parser, OmpLoopDirective) NODE(parser::OmpLoopDirective, Distribute) NODE(parser::OmpLoopDirective, DistributeParallelDo) NODE(parser::OmpLoopDirective, DistributeParallelDoSimd) NODE(parser::OmpLoopDirective, DistributeSimd) - NODE(parser::OmpLoopDirective, Do) - NODE(parser::OmpLoopDirective, DoSimd) NODE(parser::OmpLoopDirective, ParallelDo) NODE(parser::OmpLoopDirective, ParallelDoSimd) + NODE(parser::OmpLoopDirective, DoSimd) + NODE(parser::OmpLoopDirective, Do) NODE(parser::OmpLoopDirective, Simd) NODE(parser::OmpLoopDirective, TargetParallelDo) NODE(parser::OmpLoopDirective, TargetParallelDoSimd) @@ -465,8 +518,7 @@ public: NODE(parser::OmpLoopDirective, TeamsDistributeParallelDo) NODE(parser::OmpLoopDirective, TeamsDistributeParallelDoSimd) NODE(parser::OmpLoopDirective, TeamsDistributeSimd) - NODE(parser, OmpIfClause) - NODE(parser::OmpIfClause, DirectiveNameModifier) + NODE(parser, OmpNowait) NODE(parser, OmpScheduleClause) NODE(parser::OmpScheduleClause, ScheduleType) NODE(parser, OmpScheduleModifier) @@ -475,28 +527,38 @@ public: NODE(parser, OmpScheduleModifierType) NODE(parser::OmpScheduleModifierType, ModType) NODE(parser, OmpMapClause) - NODE(parser::OmpMapClause, Type) - NODE(parser, OmpNameList) - NODE(parser::OmpNameList, Kind) + NODE(parser, OmpMapType) + NODE(parser::OmpMapType, Always) + NODE(parser::OmpMapType, Type) + NODE(parser, OmpObject) + NODE(parser::OmpObject, Kind) + NODE(parser, OmpObjectList) NODE(parser, OmpProcBindClause) NODE(parser::OmpProcBindClause, Type) NODE(parser, OmpReductionOperator) - NODE(parser::OmpReductionOperator, ProcedureOperator) - NODE(parser::OmpReductionOperator, BinaryOperator) + NODE(parser, OmpSection) NODE(parser, OmpStandaloneDirective) - NODE(parser::OmpStandaloneDirective, Barrier) - NODE(parser::OmpStandaloneDirective, Cancel) - NODE(parser::OmpStandaloneDirective, CancellationPoint) - NODE(parser::OmpStandaloneDirective, Flush) + NODE(parser, OpenMPCancellationPointConstruct) + NODE(parser, OpenMPCancelConstruct) + NODE(parser::OpenMPCancelConstruct, If) + NODE(parser, OmpCancelType) + NODE(parser::OmpCancelType, Type) + NODE(parser, OpenMPFlushConstruct) NODE(parser::OmpStandaloneDirective, TargetEnterData) NODE(parser::OmpStandaloneDirective, TargetExitData) NODE(parser::OmpStandaloneDirective, TargetUpdate) - NODE(parser::OmpStandaloneDirective, Taskwait) - NODE(parser::OmpStandaloneDirective, Taskyield) + NODE(parser, OpenMPBarrierConstruct) + NODE(parser, OpenMPTaskwaitConstruct) + NODE(parser, OpenMPTaskyieldConstruct) NODE(parser, OpenMPConstruct) - NODE(parser, OpenMPLoopConstruct) + NODE(parser, OpenMPBlockConstruct) + NODE(parser, OpenMPDeclarativeConstruct) NODE(parser, OpenMPStandaloneConstruct) NODE(parser, OmpReductionClause) + NODE(parser, OpenMPSectionsConstruct) + NODE(parser, OpenMPParallelSectionsConstruct) + NODE(parser, OmpEndSections) + NODE(parser, OmpEndParallelSections) NODE(parser, Only) NODE(parser, OpenStmt) NODE(parser, Optional)