llvm-project/flang/lib/Parser/openacc-parsers.cpp

298 lines
14 KiB
C++

//===-- lib/Parser/openacc-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 OpenACC 3.0.
#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"
// OpenACC Directives and Clauses
namespace Fortran::parser {
constexpr auto startAccLine = skipStuffBeforeStatement >> "!$ACC "_sptok;
constexpr auto endAccLine = space >> endOfLine;
// Basic clauses
TYPE_PARSER("AUTO" >> construct<AccClause>(construct<AccClause::Auto>()) ||
"ASYNC" >> construct<AccClause>(construct<AccClause::Async>(
maybe(parenthesized(scalarIntExpr)))) ||
"ATTACH" >> construct<AccClause>(construct<AccClause::Attach>(
parenthesized(Parser<AccObjectList>{}))) ||
"BIND" >>
construct<AccClause>(construct<AccClause::Bind>(parenthesized(name))) ||
"CAPTURE" >> construct<AccClause>(construct<AccClause::Capture>()) ||
"COLLAPSE" >> construct<AccClause>(construct<AccClause::Collapse>(
parenthesized(scalarIntConstantExpr))) ||
("COPY"_tok || "PRESENT_OR_COPY"_tok || "PCOPY"_tok) >>
construct<AccClause>(construct<AccClause::Copy>(
parenthesized(Parser<AccObjectList>{}))) ||
("COPYIN"_tok || "PRESENT_OR_COPYIN"_tok || "PCOPYIN"_tok) >>
construct<AccClause>(construct<AccClause::Copyin>(
parenthesized(Parser<AccObjectListWithModifier>{}))) ||
("COPYOUT"_tok || "PRESENT_OR_COPYOUT"_tok || "PCOPYOUT"_tok) >>
construct<AccClause>(construct<AccClause::Copyout>(
parenthesized(Parser<AccObjectListWithModifier>{}))) ||
("CREATE"_tok || "PRESENT_OR_CREATE"_tok || "PCREATE"_tok) >>
construct<AccClause>(construct<AccClause::Create>(
parenthesized(Parser<AccObjectListWithModifier>{}))) ||
"DEFAULT" >> construct<AccClause>(construct<AccClause::Default>(
Parser<AccDefaultClause>{})) ||
"DEFAULT_ASYNC" >> construct<AccClause>(construct<AccClause::DefaultAsync>(
parenthesized(scalarIntExpr))) ||
"DELETE" >> construct<AccClause>(construct<AccClause::Delete>(
parenthesized(Parser<AccObjectList>{}))) ||
"DETACH" >> construct<AccClause>(construct<AccClause::Detach>(
parenthesized(Parser<AccObjectList>{}))) ||
"DEVICE" >> construct<AccClause>(construct<AccClause::Device>(
parenthesized(Parser<AccObjectList>{}))) ||
"DEVICEPTR" >> construct<AccClause>(construct<AccClause::Deviceptr>(
parenthesized(Parser<AccObjectList>{}))) ||
"DEVICENUM" >> construct<AccClause>(construct<AccClause::DeviceNum>(
parenthesized(scalarIntConstantExpr))) ||
"DEVICE_RESIDENT" >>
construct<AccClause>(construct<AccClause::DeviceResident>(
parenthesized(Parser<AccObjectList>{}))) ||
("DEVICE_TYPE"_tok || "DTYPE"_tok) >>
construct<AccClause>(construct<AccClause::DeviceType>(parenthesized(
"*" >> construct<std::optional<std::list<Name>>>()))) ||
("DEVICE_TYPE"_tok || "DTYPE"_tok) >>
construct<AccClause>(construct<AccClause::DeviceType>(
parenthesized(maybe(nonemptyList(name))))) ||
"FINALIZE" >> construct<AccClause>(construct<AccClause::Finalize>()) ||
"FIRSTPRIVATE" >> construct<AccClause>(construct<AccClause::Firstprivate>(
parenthesized(Parser<AccObjectList>{}))) ||
"GANG" >> construct<AccClause>(construct<AccClause::Gang>(
maybe(parenthesized(Parser<AccGangArgument>{})))) ||
"HOST" >> construct<AccClause>(construct<AccClause::Host>(
parenthesized(Parser<AccObjectList>{}))) ||
"IF" >> construct<AccClause>(
construct<AccClause::If>(parenthesized(scalarLogicalExpr))) ||
"IF_PRESENT" >> construct<AccClause>(construct<AccClause::IfPresent>()) ||
"INDEPENDENT" >>
construct<AccClause>(construct<AccClause::Independent>()) ||
"LINK" >> construct<AccClause>(construct<AccClause::Link>(
parenthesized(Parser<AccObjectList>{}))) ||
"NO_CREATE" >> construct<AccClause>(construct<AccClause::NoCreate>(
parenthesized(Parser<AccObjectList>{}))) ||
"NOHOST" >> construct<AccClause>(construct<AccClause::Nohost>()) ||
"NUM_GANGS" >> construct<AccClause>(construct<AccClause::NumGangs>(
parenthesized(scalarIntExpr))) ||
"NUM_WORKERS" >> construct<AccClause>(construct<AccClause::NumWorkers>(
parenthesized(scalarIntExpr))) ||
"PRESENT" >> construct<AccClause>(construct<AccClause::Present>(
parenthesized(Parser<AccObjectList>{}))) ||
"PRIVATE" >> construct<AccClause>(construct<AccClause::Private>(
parenthesized(Parser<AccObjectList>{}))) ||
"READ" >> construct<AccClause>(construct<AccClause::Read>()) ||
"REDUCTION" >> construct<AccClause>(construct<AccClause::Reduction>(
parenthesized(construct<AccObjectListWithReduction>(
Parser<AccReductionOperator>{} / ":",
Parser<AccObjectList>{})))) ||
"SELF" >> construct<AccClause>(construct<AccClause::Self>(
maybe(parenthesized(scalarLogicalExpr)))) ||
"SEQ" >> construct<AccClause>(construct<AccClause::Seq>()) ||
"TILE" >> construct<AccClause>(construct<AccClause::Tile>(
parenthesized(Parser<AccSizeExprList>{}))) ||
"USE_DEVICE" >> construct<AccClause>(construct<AccClause::UseDevice>(
parenthesized(Parser<AccObjectList>{}))) ||
"VECTOR_LENGTH" >> construct<AccClause>(construct<AccClause::VectorLength>(
parenthesized(scalarIntExpr))) ||
"VECTOR" >>
construct<AccClause>(construct<AccClause::Vector>(maybe(
parenthesized(("LENGTH:" >> scalarIntExpr || scalarIntExpr))))) ||
"WAIT" >> construct<AccClause>(construct<AccClause::Wait>(
maybe(parenthesized(Parser<AccWaitArgument>{})))) ||
"WORKER" >>
construct<AccClause>(construct<AccClause::Worker>(maybe(
parenthesized(("NUM:" >> scalarIntExpr || scalarIntExpr))))) ||
"WRITE" >> construct<AccClause>(construct<AccClause::Auto>()))
TYPE_PARSER(
construct<AccObject>(designator) || construct<AccObject>("/" >> name / "/"))
TYPE_PARSER(construct<AccObjectList>(nonemptyList(Parser<AccObject>{})))
TYPE_PARSER(construct<AccObjectListWithModifier>(
maybe(Parser<AccDataModifier>{}), Parser<AccObjectList>{}))
// 2.16.3 (2485) wait-argument is:
// [devnum : int-expr :] [queues :] int-expr-list
TYPE_PARSER(construct<AccWaitArgument>(maybe("DEVNUM:" >> scalarIntExpr / ":"),
"QUEUES:" >> nonemptyList(scalarIntExpr) || nonemptyList(scalarIntExpr)))
// 2.9 (1609) size-expr is one of:
// int-expr
TYPE_PARSER(construct<AccSizeExpr>(scalarIntExpr) ||
construct<AccSizeExpr>("*" >> maybe(scalarIntExpr)))
TYPE_PARSER(construct<AccSizeExprList>(nonemptyList(Parser<AccSizeExpr>{})))
// 2.9 (1607) gang-arg is one of:
// [num:]int-expr
// static:size-expr
TYPE_PARSER(construct<AccGangArgument>(maybe(scalarIntExpr),
maybe(","_tok / "STATIC:" >> Parser<AccSizeExpr>{})) ||
construct<AccGangArgument>(maybe("NUM:" >> scalarIntExpr),
maybe(","_tok / "STATIC:" >> Parser<AccSizeExpr>{})))
// 2.5.13 Reduction
// Operator for reduction
TYPE_PARSER(sourced(construct<AccReductionOperator>(
first("+" >> pure(AccReductionOperator::Operator::Plus),
"*" >> pure(AccReductionOperator::Operator::Multiply),
"MAX" >> pure(AccReductionOperator::Operator::Max),
"MIN" >> pure(AccReductionOperator::Operator::Min),
"IAND" >> pure(AccReductionOperator::Operator::Iand),
"IOR" >> pure(AccReductionOperator::Operator::Ior),
"IEOR" >> pure(AccReductionOperator::Operator::Ieor),
".AND." >> pure(AccReductionOperator::Operator::And),
".OR." >> pure(AccReductionOperator::Operator::Or),
".EQV." >> pure(AccReductionOperator::Operator::Eqv),
".NEQV." >> pure(AccReductionOperator::Operator::Neqv)))))
// 2.5.14 Default clause
TYPE_PARSER(construct<AccDefaultClause>(
parenthesized(first("NONE" >> pure(AccDefaultClause::Arg::None),
"PRESENT" >> pure(AccDefaultClause::Arg::Present)))))
// Modifier for copyin, copyout, cache and create
TYPE_PARSER(construct<AccDataModifier>(
first("ZERO:" >> pure(AccDataModifier::Modifier::Zero),
"READONLY:" >> pure(AccDataModifier::Modifier::ReadOnly))))
// Combined directives
TYPE_PARSER(sourced(construct<AccCombinedDirective>(
first("KERNELS LOOP" >> pure(llvm::acc::Directive::ACCD_kernels_loop),
"PARALLEL LOOP" >> pure(llvm::acc::Directive::ACCD_parallel_loop),
"SERIAL LOOP" >> pure(llvm::acc::Directive::ACCD_serial_loop)))))
// Block directives
TYPE_PARSER(sourced(construct<AccBlockDirective>(
first("DATA" >> pure(llvm::acc::Directive::ACCD_data),
"HOST_DATA" >> pure(llvm::acc::Directive::ACCD_host_data),
"KERNELS" >> pure(llvm::acc::Directive::ACCD_kernels),
"PARALLEL" >> pure(llvm::acc::Directive::ACCD_parallel),
"SERIAL" >> pure(llvm::acc::Directive::ACCD_serial)))))
// Standalone directives
TYPE_PARSER(sourced(construct<AccStandaloneDirective>(
first("ENTER DATA" >> pure(llvm::acc::Directive::ACCD_enter_data),
"EXIT DATA" >> pure(llvm::acc::Directive::ACCD_exit_data),
"INIT" >> pure(llvm::acc::Directive::ACCD_init),
"SHUTDOWN" >> pure(llvm::acc::Directive::ACCD_shutdown),
"SET" >> pure(llvm::acc::Directive::ACCD_set),
"UPDATE" >> pure(llvm::acc::Directive::ACCD_update)))))
// Loop directives
TYPE_PARSER(sourced(construct<AccLoopDirective>(
first("LOOP" >> pure(llvm::acc::Directive::ACCD_loop)))))
TYPE_PARSER(construct<AccBeginLoopDirective>(
sourced(Parser<AccLoopDirective>{}), Parser<AccClauseList>{}))
TYPE_PARSER(
construct<OpenACCLoopConstruct>(sourced(Parser<AccBeginLoopDirective>{})))
// 2.15.1 Routine directive
TYPE_PARSER(sourced(construct<OpenACCRoutineConstruct>(verbatim("ROUTINE"_tok),
maybe(parenthesized(name)), Parser<AccClauseList>{})))
// 2.10 Cache directive
TYPE_PARSER(sourced(
construct<OpenACCCacheConstruct>(sourced(construct<Verbatim>("CACHE"_tok)),
parenthesized(Parser<AccObjectListWithModifier>{}))))
// 2.11 Combined constructs
TYPE_PARSER(construct<AccBeginCombinedDirective>(
sourced(Parser<AccCombinedDirective>{}), Parser<AccClauseList>{}))
// 2.12 Atomic constructs
TYPE_PARSER(construct<AccEndAtomic>(startAccLine >> "END ATOMIC"_tok))
TYPE_PARSER("ATOMIC" >>
construct<AccAtomicRead>(verbatim("READ"_tok) / endAccLine,
statement(assignmentStmt), maybe(Parser<AccEndAtomic>{} / endAccLine)))
TYPE_PARSER("ATOMIC" >>
construct<AccAtomicWrite>(verbatim("WRITE"_tok) / endAccLine,
statement(assignmentStmt), maybe(Parser<AccEndAtomic>{} / endAccLine)))
TYPE_PARSER("ATOMIC" >>
construct<AccAtomicUpdate>(maybe(verbatim("UPDATE"_tok)) / endAccLine,
statement(assignmentStmt), maybe(Parser<AccEndAtomic>{} / endAccLine)))
TYPE_PARSER("ATOMIC" >>
construct<AccAtomicCapture>(verbatim("CAPTURE"_tok) / endAccLine,
statement(assignmentStmt), statement(assignmentStmt),
Parser<AccEndAtomic>{} / endAccLine))
TYPE_PARSER(construct<OpenACCAtomicConstruct>(Parser<AccAtomicRead>{}) ||
construct<OpenACCAtomicConstruct>(Parser<AccAtomicCapture>{}) ||
construct<OpenACCAtomicConstruct>(Parser<AccAtomicWrite>{}) ||
construct<OpenACCAtomicConstruct>(Parser<AccAtomicUpdate>{}))
// 2.13 Declare constructs
TYPE_PARSER(sourced(construct<AccDeclarativeDirective>(
first("DECLARE" >> pure(llvm::acc::Directive::ACCD_declare)))))
// [Clause, [Clause], ...]
TYPE_PARSER(sourced(construct<AccClauseList>(
many(maybe(","_tok) >> sourced(Parser<AccClause>{})))))
// 2.16.3 Wait directive
TYPE_PARSER(sourced(construct<OpenACCWaitConstruct>(
sourced(construct<Verbatim>("WAIT"_tok)),
maybe(parenthesized(Parser<AccWaitArgument>{})), Parser<AccClauseList>{})))
// Block Constructs
TYPE_PARSER(sourced(construct<AccBeginBlockDirective>(
sourced(Parser<AccBlockDirective>{}), Parser<AccClauseList>{})))
TYPE_PARSER(startAccLine >> sourced(construct<AccEndBlockDirective>("END"_tok >>
sourced(Parser<AccBlockDirective>{}))))
TYPE_PARSER(construct<OpenACCBlockConstruct>(
Parser<AccBeginBlockDirective>{} / endAccLine, block,
Parser<AccEndBlockDirective>{} / endAccLine))
// Standalone constructs
TYPE_PARSER(construct<OpenACCStandaloneConstruct>(
sourced(Parser<AccStandaloneDirective>{}), Parser<AccClauseList>{}))
// Standalone declarative constructs
TYPE_PARSER(construct<OpenACCStandaloneDeclarativeConstruct>(
sourced(Parser<AccDeclarativeDirective>{}), Parser<AccClauseList>{}))
TYPE_PARSER(
startAccLine >> sourced(construct<OpenACCDeclarativeConstruct>(
Parser<OpenACCStandaloneDeclarativeConstruct>{})))
// OpenACC constructs
TYPE_CONTEXT_PARSER("OpenACC construct"_en_US,
startAccLine >>
first(construct<OpenACCConstruct>(Parser<OpenACCBlockConstruct>{}),
construct<OpenACCConstruct>(Parser<OpenACCCombinedConstruct>{}),
construct<OpenACCConstruct>(Parser<OpenACCLoopConstruct>{}),
construct<OpenACCConstruct>(Parser<OpenACCStandaloneConstruct>{}),
construct<OpenACCConstruct>(Parser<OpenACCRoutineConstruct>{}),
construct<OpenACCConstruct>(Parser<OpenACCCacheConstruct>{}),
construct<OpenACCConstruct>(Parser<OpenACCWaitConstruct>{}),
construct<OpenACCConstruct>(Parser<OpenACCAtomicConstruct>{})))
TYPE_PARSER(startAccLine >> sourced(construct<AccEndCombinedDirective>(sourced(
"END"_tok >> Parser<AccCombinedDirective>{}))))
TYPE_PARSER(construct<OpenACCCombinedConstruct>(
sourced(Parser<AccBeginCombinedDirective>{} / endAccLine)))
} // namespace Fortran::parser