| //===-- 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.3. |
| |
| #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 || "C$ACC "_sptok || "*$ACC "_sptok)}; |
| constexpr auto endAccLine{space >> endOfLine}; |
| |
| // Autogenerated clauses parser. Information is taken from ACC.td and the |
| // parser is generated by tablegen. |
| // Scalar value parsers are provided by Flang directly. Specific value parsers |
| // are provided below. |
| #define GEN_FLANG_CLAUSES_PARSER |
| #include "llvm/Frontend/OpenACC/ACC.inc" |
| |
| TYPE_PARSER( |
| construct<AccObject>(designator) || construct<AccObject>("/" >> name / "/")) |
| |
| TYPE_PARSER(construct<AccObjectList>(nonemptyList(Parser<AccObject>{}))) |
| |
| TYPE_PARSER(construct<AccObjectListWithModifier>( |
| maybe(Parser<AccDataModifier>{}), Parser<AccObjectList>{})) |
| |
| TYPE_PARSER(construct<AccObjectListWithReduction>( |
| Parser<ReductionOperator>{} / ":", Parser<AccObjectList>{})) |
| |
| // 2.16 (3249) wait-argument is: |
| // [devnum : int-expr :] [queues :] int-expr-list |
| TYPE_PARSER(construct<AccWaitArgument>(maybe("DEVNUM:" >> scalarIntExpr / ":"), |
| "QUEUES:" >> nonemptyList(scalarIntExpr) || nonemptyList(scalarIntExpr))) |
| |
| // 2.9 (1984-1986) size-expr is one of: |
| // * (represented as an empty std::optional<ScalarIntExpr>) |
| // int-expr |
| TYPE_PARSER(construct<AccSizeExpr>(scalarIntExpr) || |
| construct<AccSizeExpr>("*" >> construct<std::optional<ScalarIntExpr>>())) |
| TYPE_PARSER(construct<AccSizeExprList>(nonemptyList(Parser<AccSizeExpr>{}))) |
| |
| TYPE_PARSER(sourced(construct<AccDeviceTypeExpr>( |
| first("*" >> pure(Fortran::common::OpenACCDeviceType::Star), |
| "DEFAULT" >> pure(Fortran::common::OpenACCDeviceType::Default), |
| "NVIDIA" >> pure(Fortran::common::OpenACCDeviceType::Nvidia), |
| "ACC_DEVICE_NVIDIA" >> pure(Fortran::common::OpenACCDeviceType::Nvidia), |
| "RADEON" >> pure(Fortran::common::OpenACCDeviceType::Radeon), |
| "HOST" >> pure(Fortran::common::OpenACCDeviceType::Host), |
| "MULTICORE" >> pure(Fortran::common::OpenACCDeviceType::Multicore))))) |
| |
| TYPE_PARSER( |
| construct<AccDeviceTypeExprList>(nonemptyList(Parser<AccDeviceTypeExpr>{}))) |
| |
| // tile size is one of: |
| // * (represented as an empty std::optional<ScalarIntExpr>) |
| // constant-int-expr |
| TYPE_PARSER(construct<AccTileExpr>(scalarIntConstantExpr) || |
| construct<AccTileExpr>( |
| "*" >> construct<std::optional<ScalarIntConstantExpr>>())) |
| TYPE_PARSER(construct<AccTileExprList>(nonemptyList(Parser<AccTileExpr>{}))) |
| |
| // 2.9 (1979-1982) gang-arg is one of : |
| // [num:]int-expr |
| // dim:int-expr |
| // static:size-expr |
| TYPE_PARSER(construct<AccGangArg>(construct<AccGangArg::Static>( |
| "STATIC: " >> Parser<AccSizeExpr>{})) || |
| construct<AccGangArg>( |
| construct<AccGangArg::Dim>("DIM: " >> scalarIntExpr)) || |
| construct<AccGangArg>( |
| construct<AccGangArg::Num>(maybe("NUM: "_tok) >> scalarIntExpr))) |
| |
| // 2.9 gang-arg-list |
| TYPE_PARSER( |
| construct<AccGangArgList>(many(maybe(","_tok) >> Parser<AccGangArg>{}))) |
| |
| // 2.9.1 collapse |
| TYPE_PARSER(construct<AccCollapseArg>( |
| "FORCE:"_tok >> pure(true) || pure(false), scalarIntConstantExpr)) |
| |
| // 2.5.15 Reduction, F'2023 R1131, and CUF reduction-op |
| // Operator for reduction |
| TYPE_PARSER(sourced(construct<ReductionOperator>( |
| first("+" >> pure(ReductionOperator::Operator::Plus), |
| "*" >> pure(ReductionOperator::Operator::Multiply), |
| "MAX" >> pure(ReductionOperator::Operator::Max), |
| "MIN" >> pure(ReductionOperator::Operator::Min), |
| "IAND" >> pure(ReductionOperator::Operator::Iand), |
| "IOR" >> pure(ReductionOperator::Operator::Ior), |
| "IEOR" >> pure(ReductionOperator::Operator::Ieor), |
| ".AND." >> pure(ReductionOperator::Operator::And), |
| ".OR." >> pure(ReductionOperator::Operator::Or), |
| ".EQV." >> pure(ReductionOperator::Operator::Eqv), |
| ".NEQV." >> pure(ReductionOperator::Operator::Neqv))))) |
| |
| // 2.15.1 Bind clause |
| TYPE_PARSER(sourced(construct<AccBindClause>(name)) || |
| sourced(construct<AccBindClause>(scalarDefaultCharExpr))) |
| |
| // 2.5.16 Default clause |
| TYPE_PARSER(construct<AccDefaultClause>( |
| first("NONE" >> pure(llvm::acc::DefaultValue::ACC_Default_none), |
| "PRESENT" >> pure(llvm::acc::DefaultValue::ACC_Default_present)))) |
| |
| // SELF clause is either a simple optional condition for compute construct |
| // or a synonym of the HOST clause for the update directive 2.14.4 holding |
| // an object list. |
| TYPE_PARSER(construct<AccSelfClause>(Parser<AccObjectList>{}) || |
| construct<AccSelfClause>(scalarLogicalExpr)) |
| |
| // 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<AccEndLoop>("END LOOP"_tok)) |
| |
| TYPE_PARSER(construct<OpenACCLoopConstruct>( |
| sourced(Parser<AccBeginLoopDirective>{} / endAccLine), |
| maybe(Parser<DoConstruct>{}), |
| maybe(startAccLine >> Parser<AccEndLoop>{} / endAccLine))) |
| |
| // 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( |
| sourced(construct<OpenACCAtomicConstruct>(Parser<AccAtomicRead>{})) || |
| sourced(construct<OpenACCAtomicConstruct>(Parser<AccAtomicCapture>{})) || |
| sourced(construct<OpenACCAtomicConstruct>(Parser<AccAtomicWrite>{})) || |
| sourced(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 >> |
| withMessage("expected OpenACC directive"_err_en_US, |
| first(sourced(construct<OpenACCDeclarativeConstruct>( |
| Parser<OpenACCStandaloneDeclarativeConstruct>{})), |
| sourced(construct<OpenACCDeclarativeConstruct>( |
| Parser<OpenACCRoutineConstruct>{}))))) |
| |
| TYPE_PARSER(sourced(construct<OpenACCEndConstruct>( |
| "END"_tok >> "LOOP"_tok >> pure(llvm::acc::Directive::ACCD_loop)))) |
| |
| // OpenACC constructs |
| TYPE_CONTEXT_PARSER("OpenACC construct"_en_US, |
| startAccLine >> |
| withMessage("expected OpenACC directive"_err_en_US, |
| first(construct<OpenACCConstruct>(Parser<OpenACCBlockConstruct>{}), |
| construct<OpenACCConstruct>(Parser<OpenACCCombinedConstruct>{}), |
| construct<OpenACCConstruct>(Parser<OpenACCLoopConstruct>{}), |
| construct<OpenACCConstruct>( |
| Parser<OpenACCStandaloneConstruct>{}), |
| construct<OpenACCConstruct>(Parser<OpenACCCacheConstruct>{}), |
| construct<OpenACCConstruct>(Parser<OpenACCWaitConstruct>{}), |
| construct<OpenACCConstruct>(Parser<OpenACCAtomicConstruct>{}), |
| construct<OpenACCConstruct>(Parser<OpenACCEndConstruct>{})))) |
| |
| TYPE_PARSER(startAccLine >> |
| sourced(construct<AccEndCombinedDirective>(sourced("END"_tok >> |
| construct<AccCombinedDirective>("KERNELS"_tok >> maybe("LOOP"_tok) >> |
| pure(llvm::acc::Directive::ACCD_kernels_loop) || |
| "PARALLEL"_tok >> maybe("LOOP"_tok) >> |
| pure(llvm::acc::Directive::ACCD_parallel_loop) || |
| "SERIAL"_tok >> maybe("LOOP"_tok) >> |
| pure(llvm::acc::Directive::ACCD_serial_loop)))))) |
| |
| TYPE_PARSER(construct<OpenACCCombinedConstruct>( |
| sourced(Parser<AccBeginCombinedDirective>{} / endAccLine), |
| maybe(Parser<DoConstruct>{}), |
| maybe(Parser<AccEndCombinedDirective>{} / endAccLine))) |
| |
| } // namespace Fortran::parser |