301 lines · cpp
1//===-- lib/Parser/openacc-parsers.cpp ------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// Top-level grammar specification for OpenACC 3.3.10 11#include "basic-parsers.h"12#include "expr-parsers.h"13#include "misc-parsers.h"14#include "stmt-parser.h"15#include "token-parsers.h"16#include "type-parser-implementation.h"17#include "flang/Parser/parse-tree.h"18 19// OpenACC Directives and Clauses20namespace Fortran::parser {21 22// Only need to handle ! line comments because prescanning normalizes the23// other types of line comments from fixed form.24constexpr auto startAccLine{skipStuffBeforeStatement >>25 withMessage(26 "expected OpenACC directive sentinel: !$ACC, C$ACC, or *$ACC"_err_en_US,27 "!$ACC "_sptok)};28constexpr auto endAccLine{space >>29 recovery(30 withMessage("expected end of OpenACC directive"_err_en_US, endOfLine),31 SkipTo<'\n'>{} || ok)};32 33// Autogenerated clauses parser. Information is taken from ACC.td and the34// parser is generated by tablegen.35// Scalar value parsers are provided by Flang directly. Specific value parsers36// are provided below.37#define GEN_FLANG_CLAUSES_PARSER38#include "llvm/Frontend/OpenACC/ACC.inc"39 40TYPE_PARSER(41 construct<AccObject>(designator) || construct<AccObject>("/" >> name / "/"))42 43TYPE_PARSER(construct<AccObjectList>(nonemptyList(Parser<AccObject>{})))44 45TYPE_PARSER(construct<AccObjectListWithModifier>(46 maybe(Parser<AccDataModifier>{}), Parser<AccObjectList>{}))47 48TYPE_PARSER(construct<AccObjectListWithReduction>(49 Parser<ReductionOperator>{} / ":", Parser<AccObjectList>{}))50 51// 2.16 (3249) wait-argument is:52// [devnum : int-expr :] [queues :] int-expr-list53TYPE_PARSER(construct<AccWaitArgument>(maybe("DEVNUM:" >> scalarIntExpr / ":"),54 "QUEUES:" >> nonemptyList(scalarIntExpr) || nonemptyList(scalarIntExpr)))55 56// 2.9 (1984-1986) size-expr is one of:57// * (represented as an empty std::optional<ScalarIntExpr>)58// int-expr59TYPE_PARSER(construct<AccSizeExpr>(scalarIntExpr) ||60 construct<AccSizeExpr>("*" >> construct<std::optional<ScalarIntExpr>>()))61TYPE_PARSER(construct<AccSizeExprList>(nonemptyList(Parser<AccSizeExpr>{})))62 63TYPE_PARSER(sourced(construct<AccDeviceTypeExpr>(64 first("*" >> pure(Fortran::common::OpenACCDeviceType::Star),65 "DEFAULT" >> pure(Fortran::common::OpenACCDeviceType::Default),66 "NVIDIA" >> pure(Fortran::common::OpenACCDeviceType::Nvidia),67 "ACC_DEVICE_NVIDIA" >> pure(Fortran::common::OpenACCDeviceType::Nvidia),68 "RADEON" >> pure(Fortran::common::OpenACCDeviceType::Radeon),69 "HOST" >> pure(Fortran::common::OpenACCDeviceType::Host),70 "MULTICORE" >> pure(Fortran::common::OpenACCDeviceType::Multicore)))))71 72TYPE_PARSER(73 construct<AccDeviceTypeExprList>(nonemptyList(Parser<AccDeviceTypeExpr>{})))74 75// tile size is one of:76// * (represented as an empty std::optional<ScalarIntExpr>)77// constant-int-expr78TYPE_PARSER(sourced(construct<AccTileExpr>(scalarIntConstantExpr) ||79 construct<AccTileExpr>(80 "*" >> construct<std::optional<ScalarIntConstantExpr>>())))81TYPE_PARSER(construct<AccTileExprList>(nonemptyList(Parser<AccTileExpr>{})))82 83// 2.9 (1979-1982) gang-arg is one of :84// [num:]int-expr85// dim:int-expr86// static:size-expr87TYPE_PARSER(sourced(construct<AccGangArg>(construct<AccGangArg::Static>(88 "STATIC: " >> Parser<AccSizeExpr>{})) ||89 construct<AccGangArg>(90 construct<AccGangArg::Dim>("DIM: " >> scalarIntExpr)) ||91 construct<AccGangArg>(92 construct<AccGangArg::Num>(maybe("NUM: "_tok) >> scalarIntExpr))))93 94// 2.9 gang-arg-list95TYPE_PARSER(96 construct<AccGangArgList>(many(maybe(","_tok) >> Parser<AccGangArg>{})))97 98// 2.9.1 collapse99TYPE_PARSER(construct<AccCollapseArg>(100 "FORCE:"_tok >> pure(true) || pure(false), scalarIntConstantExpr))101 102// 2.5.15 Reduction, F'2023 R1131, and CUF reduction-op103// Operator for reduction104TYPE_PARSER(construct<ReductionOperator>(105 first("+" >> pure(ReductionOperator::Operator::Plus),106 "*" >> pure(ReductionOperator::Operator::Multiply),107 "MAX" >> pure(ReductionOperator::Operator::Max),108 "MIN" >> pure(ReductionOperator::Operator::Min),109 "IAND" >> pure(ReductionOperator::Operator::Iand),110 "IOR" >> pure(ReductionOperator::Operator::Ior),111 "IEOR" >> pure(ReductionOperator::Operator::Ieor),112 ".AND." >> pure(ReductionOperator::Operator::And),113 ".OR." >> pure(ReductionOperator::Operator::Or),114 ".EQV." >> pure(ReductionOperator::Operator::Eqv),115 ".NEQV." >> pure(ReductionOperator::Operator::Neqv))))116 117// 2.15.1 Bind clause118TYPE_PARSER(sourced(construct<AccBindClause>(name) ||119 construct<AccBindClause>(scalarDefaultCharExpr)))120 121// 2.5.16 Default clause122TYPE_PARSER(sourced(construct<AccDefaultClause>(123 first("NONE" >> pure(llvm::acc::DefaultValue::ACC_Default_none),124 "PRESENT" >> pure(llvm::acc::DefaultValue::ACC_Default_present)))))125 126// SELF clause is either a simple optional condition for compute construct127// or a synonym of the HOST clause for the update directive 2.14.4 holding128// an object list.129TYPE_PARSER(sourced(130 construct<AccSelfClause>(Parser<AccObjectList>{}) / lookAhead(")"_tok) ||131 construct<AccSelfClause>(scalarLogicalExpr) / lookAhead(")"_tok) ||132 construct<AccSelfClause>(133 recovery(fail<std::optional<ScalarLogicalExpr>>(134 "logical expression or object list expected"_err_en_US),135 SkipTo<')'>{} >> pure<std::optional<ScalarLogicalExpr>>()))))136 137// Modifier for copyin, copyout, cache and create138TYPE_PARSER(sourced(construct<AccDataModifier>(139 first("ZERO:" >> pure(AccDataModifier::Modifier::Zero),140 "READONLY:" >> pure(AccDataModifier::Modifier::ReadOnly)))))141 142// Combined directives143TYPE_PARSER(sourced(construct<AccCombinedDirective>(144 first("KERNELS LOOP" >> pure(llvm::acc::Directive::ACCD_kernels_loop),145 "PARALLEL LOOP" >> pure(llvm::acc::Directive::ACCD_parallel_loop),146 "SERIAL LOOP" >> pure(llvm::acc::Directive::ACCD_serial_loop)))))147 148// Block directives149TYPE_PARSER(sourced(construct<AccBlockDirective>(150 first("DATA" >> pure(llvm::acc::Directive::ACCD_data),151 "HOST_DATA" >> pure(llvm::acc::Directive::ACCD_host_data),152 "KERNELS" >> pure(llvm::acc::Directive::ACCD_kernels),153 "PARALLEL" >> pure(llvm::acc::Directive::ACCD_parallel),154 "SERIAL" >> pure(llvm::acc::Directive::ACCD_serial)))))155 156// Standalone directives157TYPE_PARSER(sourced(construct<AccStandaloneDirective>(158 first("ENTER DATA" >> pure(llvm::acc::Directive::ACCD_enter_data),159 "EXIT DATA" >> pure(llvm::acc::Directive::ACCD_exit_data),160 "INIT" >> pure(llvm::acc::Directive::ACCD_init),161 "SHUTDOWN" >> pure(llvm::acc::Directive::ACCD_shutdown),162 "SET" >> pure(llvm::acc::Directive::ACCD_set),163 "UPDATE" >> pure(llvm::acc::Directive::ACCD_update)))))164 165// Loop directives166TYPE_PARSER(sourced(construct<AccLoopDirective>(167 first("LOOP" >> pure(llvm::acc::Directive::ACCD_loop)))))168 169TYPE_PARSER(sourced(construct<AccBeginLoopDirective>(170 Parser<AccLoopDirective>{}, Parser<AccClauseList>{})))171 172TYPE_PARSER(construct<AccEndLoop>("END LOOP"_tok))173 174TYPE_PARSER(construct<OpenACCLoopConstruct>(175 Parser<AccBeginLoopDirective>{} / endAccLine, maybe(Parser<DoConstruct>{}),176 maybe(startAccLine >> Parser<AccEndLoop>{} / endAccLine)))177 178// 2.15.1 Routine directive179TYPE_PARSER(sourced(construct<OpenACCRoutineConstruct>(verbatim("ROUTINE"_tok),180 maybe(parenthesized(name)), Parser<AccClauseList>{})))181 182// 2.10 Cache directive183TYPE_PARSER(sourced(184 construct<OpenACCCacheConstruct>(sourced(construct<Verbatim>("CACHE"_tok)),185 parenthesized(Parser<AccObjectListWithModifier>{}))))186 187// 2.11 Combined constructs188TYPE_PARSER(sourced(construct<AccBeginCombinedDirective>(189 Parser<AccCombinedDirective>{}, Parser<AccClauseList>{})))190 191// 2.12 Atomic constructs192TYPE_PARSER(construct<AccEndAtomic>(startAccLine >> "END ATOMIC"_tok))193 194TYPE_PARSER("ATOMIC" >> construct<AccAtomicRead>(verbatim("READ"_tok),195 Parser<AccClauseList>{} / endAccLine,196 statement(assignmentStmt),197 maybe(Parser<AccEndAtomic>{} / endAccLine)))198 199TYPE_PARSER("ATOMIC" >> construct<AccAtomicWrite>(verbatim("WRITE"_tok),200 Parser<AccClauseList>{} / endAccLine,201 statement(assignmentStmt),202 maybe(Parser<AccEndAtomic>{} / endAccLine)))203 204TYPE_PARSER("ATOMIC" >>205 construct<AccAtomicUpdate>(maybe(verbatim("UPDATE"_tok)),206 Parser<AccClauseList>{} / endAccLine, statement(assignmentStmt),207 maybe(Parser<AccEndAtomic>{} / endAccLine)))208 209TYPE_PARSER("ATOMIC" >>210 construct<AccAtomicCapture>(verbatim("CAPTURE"_tok),211 Parser<AccClauseList>{} / endAccLine, statement(assignmentStmt),212 statement(assignmentStmt), Parser<AccEndAtomic>{} / endAccLine))213 214TYPE_PARSER(215 sourced(construct<OpenACCAtomicConstruct>(Parser<AccAtomicRead>{}) ||216 construct<OpenACCAtomicConstruct>(Parser<AccAtomicCapture>{}) ||217 construct<OpenACCAtomicConstruct>(Parser<AccAtomicWrite>{}) ||218 construct<OpenACCAtomicConstruct>(Parser<AccAtomicUpdate>{})))219 220// 2.13 Declare constructs221TYPE_PARSER(sourced(construct<AccDeclarativeDirective>(222 first("DECLARE" >> pure(llvm::acc::Directive::ACCD_declare)))))223 224// [Clause, [Clause], ...]225TYPE_PARSER(sourced(construct<AccClauseList>(226 many(maybe(","_tok) >> sourced(Parser<AccClause>{})))))227 228// 2.16.3 Wait directive229TYPE_PARSER(sourced(construct<OpenACCWaitConstruct>(230 sourced(construct<Verbatim>("WAIT"_tok)),231 maybe(parenthesized(Parser<AccWaitArgument>{})), Parser<AccClauseList>{})))232 233// Block Constructs234TYPE_PARSER(sourced(construct<AccBeginBlockDirective>(235 sourced(Parser<AccBlockDirective>{}), Parser<AccClauseList>{})))236 237TYPE_PARSER(startAccLine >> sourced(construct<AccEndBlockDirective>("END"_tok >>238 recovery(sourced(Parser<AccBlockDirective>{}),239 construct<AccBlockDirective>(pure(240 llvm::acc::Directive::ACCD_data))))))241 242TYPE_PARSER(construct<OpenACCBlockConstruct>(243 Parser<AccBeginBlockDirective>{} / endAccLine, block,244 // NB, This allows mismatched directives, but semantics checks that they245 // match.246 recovery(withMessage("expected OpenACC end block directive"_err_en_US,247 attempt(Parser<AccEndBlockDirective>{} / endAccLine)),248 construct<AccEndBlockDirective>(construct<AccBlockDirective>(249 pure(llvm::acc::Directive::ACCD_data))))))250 251// Standalone constructs252TYPE_PARSER(sourced(construct<OpenACCStandaloneConstruct>(253 Parser<AccStandaloneDirective>{}, Parser<AccClauseList>{})))254 255// Standalone declarative constructs256TYPE_PARSER(sourced(construct<OpenACCStandaloneDeclarativeConstruct>(257 Parser<AccDeclarativeDirective>{}, Parser<AccClauseList>{})))258 259TYPE_PARSER(startAccLine >>260 withMessage("expected OpenACC directive"_err_en_US,261 sourced(first(construct<OpenACCDeclarativeConstruct>(262 Parser<OpenACCStandaloneDeclarativeConstruct>{}),263 construct<OpenACCDeclarativeConstruct>(264 Parser<OpenACCRoutineConstruct>{})))))265 266TYPE_PARSER(sourced(construct<OpenACCEndConstruct>(267 "END"_tok >> "LOOP"_tok >> pure(llvm::acc::Directive::ACCD_loop))))268 269// OpenACC constructs270TYPE_CONTEXT_PARSER("OpenACC construct"_en_US,271 startAccLine >>272 withMessage("expected OpenACC directive"_err_en_US,273 // Combined constructs before block constructs so we try to match274 // the longest possible match first.275 first(276 construct<OpenACCConstruct>(Parser<OpenACCCombinedConstruct>{}),277 construct<OpenACCConstruct>(Parser<OpenACCBlockConstruct>{}),278 construct<OpenACCConstruct>(Parser<OpenACCLoopConstruct>{}),279 construct<OpenACCConstruct>(280 Parser<OpenACCStandaloneConstruct>{}),281 construct<OpenACCConstruct>(Parser<OpenACCCacheConstruct>{}),282 construct<OpenACCConstruct>(Parser<OpenACCWaitConstruct>{}),283 construct<OpenACCConstruct>(Parser<OpenACCAtomicConstruct>{}),284 construct<OpenACCConstruct>(Parser<OpenACCEndConstruct>{}))))285 286TYPE_PARSER(startAccLine >>287 sourced(construct<AccEndCombinedDirective>(sourced("END"_tok >>288 construct<AccCombinedDirective>("KERNELS"_tok >> maybe("LOOP"_tok) >>289 pure(llvm::acc::Directive::ACCD_kernels_loop) ||290 "PARALLEL"_tok >> maybe("LOOP"_tok) >>291 pure(llvm::acc::Directive::ACCD_parallel_loop) ||292 "SERIAL"_tok >> maybe("LOOP"_tok) >>293 pure(llvm::acc::Directive::ACCD_serial_loop))))))294 295TYPE_PARSER(sourced(construct<OpenACCCombinedConstruct>(296 Parser<AccBeginCombinedDirective>{} / endAccLine,297 maybe(Parser<DoConstruct>{}),298 maybe(Parser<AccEndCombinedDirective>{} / endAccLine))))299 300} // namespace Fortran::parser301