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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // Top-level grammar specification for OpenACC 3.0. 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 Clauses 20 namespace Fortran::parser { 21 22 constexpr auto startAccLine = skipStuffBeforeStatement >> "!$ACC "_sptok; 23 constexpr auto endAccLine = space >> endOfLine; 24 25 // Basic clauses 26 TYPE_PARSER("AUTO" >> construct<AccClause>(construct<AccClause::Auto>()) || 27 "ASYNC" >> construct<AccClause>(construct<AccClause::Async>( 28 maybe(parenthesized(scalarIntExpr)))) || 29 "ATTACH" >> construct<AccClause>(construct<AccClause::Attach>( 30 parenthesized(Parser<AccObjectList>{}))) || 31 "BIND" >> 32 construct<AccClause>(construct<AccClause::Bind>(parenthesized(name))) || 33 "CAPTURE" >> construct<AccClause>(construct<AccClause::Capture>()) || 34 "COLLAPSE" >> construct<AccClause>(construct<AccClause::Collapse>( 35 parenthesized(scalarIntConstantExpr))) || 36 ("COPY"_tok || "PRESENT_OR_COPY"_tok || "PCOPY"_tok) >> 37 construct<AccClause>(construct<AccClause::Copy>( 38 parenthesized(Parser<AccObjectList>{}))) || 39 ("COPYIN"_tok || "PRESENT_OR_COPYIN"_tok || "PCOPYIN"_tok) >> 40 construct<AccClause>(construct<AccClause::Copyin>( 41 parenthesized(Parser<AccObjectListWithModifier>{}))) || 42 ("COPYOUT"_tok || "PRESENT_OR_COPYOUT"_tok || "PCOPYOUT"_tok) >> 43 construct<AccClause>(construct<AccClause::Copyout>( 44 parenthesized(Parser<AccObjectListWithModifier>{}))) || 45 ("CREATE"_tok || "PRESENT_OR_CREATE"_tok || "PCREATE"_tok) >> 46 construct<AccClause>(construct<AccClause::Create>( 47 parenthesized(Parser<AccObjectListWithModifier>{}))) || 48 "DEFAULT" >> construct<AccClause>(construct<AccClause::Default>( 49 Parser<AccDefaultClause>{})) || 50 "DEFAULT_ASYNC" >> construct<AccClause>(construct<AccClause::DefaultAsync>( 51 parenthesized(scalarIntExpr))) || 52 "DELETE" >> construct<AccClause>(construct<AccClause::Delete>( 53 parenthesized(Parser<AccObjectList>{}))) || 54 "DETACH" >> construct<AccClause>(construct<AccClause::Detach>( 55 parenthesized(Parser<AccObjectList>{}))) || 56 "DEVICE" >> construct<AccClause>(construct<AccClause::Device>( 57 parenthesized(Parser<AccObjectList>{}))) || 58 "DEVICEPTR" >> construct<AccClause>(construct<AccClause::Deviceptr>( 59 parenthesized(Parser<AccObjectList>{}))) || 60 "DEVICENUM" >> construct<AccClause>(construct<AccClause::DeviceNum>( 61 parenthesized(scalarIntConstantExpr))) || 62 "DEVICE_RESIDENT" >> 63 construct<AccClause>(construct<AccClause::DeviceResident>( 64 parenthesized(Parser<AccObjectList>{}))) || 65 ("DEVICE_TYPE"_tok || "DTYPE"_tok) >> 66 construct<AccClause>(construct<AccClause::DeviceType>(parenthesized( 67 "*" >> construct<std::optional<std::list<Name>>>()))) || 68 ("DEVICE_TYPE"_tok || "DTYPE"_tok) >> 69 construct<AccClause>(construct<AccClause::DeviceType>( 70 parenthesized(maybe(nonemptyList(name))))) || 71 "FINALIZE" >> construct<AccClause>(construct<AccClause::Finalize>()) || 72 "FIRSTPRIVATE" >> construct<AccClause>(construct<AccClause::Firstprivate>( 73 parenthesized(Parser<AccObjectList>{}))) || 74 "GANG" >> construct<AccClause>(construct<AccClause::Gang>( 75 maybe(parenthesized(Parser<AccGangArgument>{})))) || 76 "HOST" >> construct<AccClause>(construct<AccClause::Host>( 77 parenthesized(Parser<AccObjectList>{}))) || 78 "IF" >> construct<AccClause>( 79 construct<AccClause::If>(parenthesized(scalarLogicalExpr))) || 80 "IF_PRESENT" >> construct<AccClause>(construct<AccClause::IfPresent>()) || 81 "INDEPENDENT" >> 82 construct<AccClause>(construct<AccClause::Independent>()) || 83 "LINK" >> construct<AccClause>(construct<AccClause::Link>( 84 parenthesized(Parser<AccObjectList>{}))) || 85 "NO_CREATE" >> construct<AccClause>(construct<AccClause::NoCreate>( 86 parenthesized(Parser<AccObjectList>{}))) || 87 "NOHOST" >> construct<AccClause>(construct<AccClause::Nohost>()) || 88 "NUM_GANGS" >> construct<AccClause>(construct<AccClause::NumGangs>( 89 parenthesized(scalarIntExpr))) || 90 "NUM_WORKERS" >> construct<AccClause>(construct<AccClause::NumWorkers>( 91 parenthesized(scalarIntExpr))) || 92 "PRESENT" >> construct<AccClause>(construct<AccClause::Present>( 93 parenthesized(Parser<AccObjectList>{}))) || 94 "PRIVATE" >> construct<AccClause>(construct<AccClause::Private>( 95 parenthesized(Parser<AccObjectList>{}))) || 96 "READ" >> construct<AccClause>(construct<AccClause::Read>()) || 97 "REDUCTION" >> construct<AccClause>(construct<AccClause::Reduction>( 98 parenthesized(construct<AccObjectListWithReduction>( 99 Parser<AccReductionOperator>{} / ":", 100 Parser<AccObjectList>{})))) || 101 "SELF" >> construct<AccClause>(construct<AccClause::Self>( 102 maybe(parenthesized(scalarLogicalExpr)))) || 103 "SEQ" >> construct<AccClause>(construct<AccClause::Seq>()) || 104 "TILE" >> construct<AccClause>(construct<AccClause::Tile>( 105 parenthesized(Parser<AccSizeExprList>{}))) || 106 "USE_DEVICE" >> construct<AccClause>(construct<AccClause::UseDevice>( 107 parenthesized(Parser<AccObjectList>{}))) || 108 "VECTOR_LENGTH" >> construct<AccClause>(construct<AccClause::VectorLength>( 109 parenthesized(scalarIntExpr))) || 110 "VECTOR" >> 111 construct<AccClause>(construct<AccClause::Vector>(maybe( 112 parenthesized(("LENGTH:" >> scalarIntExpr || scalarIntExpr))))) || 113 "WAIT" >> construct<AccClause>(construct<AccClause::Wait>( 114 maybe(parenthesized(Parser<AccWaitArgument>{})))) || 115 "WORKER" >> 116 construct<AccClause>(construct<AccClause::Worker>(maybe( 117 parenthesized(("NUM:" >> scalarIntExpr || scalarIntExpr))))) || 118 "WRITE" >> construct<AccClause>(construct<AccClause::Auto>())) 119 120 TYPE_PARSER( 121 construct<AccObject>(designator) || construct<AccObject>("/" >> name / "/")) 122 123 TYPE_PARSER(construct<AccObjectList>(nonemptyList(Parser<AccObject>{}))) 124 125 TYPE_PARSER(construct<AccObjectListWithModifier>( 126 maybe(Parser<AccDataModifier>{}), Parser<AccObjectList>{})) 127 128 // 2.16.3 (2485) wait-argument is: 129 // [devnum : int-expr :] [queues :] int-expr-list 130 TYPE_PARSER(construct<AccWaitArgument>(maybe("DEVNUM:" >> scalarIntExpr / ":"), 131 "QUEUES:" >> nonemptyList(scalarIntExpr) || nonemptyList(scalarIntExpr))) 132 133 // 2.9 (1609) size-expr is one of: 134 // int-expr 135 TYPE_PARSER(construct<AccSizeExpr>(scalarIntExpr) || 136 construct<AccSizeExpr>("*" >> maybe(scalarIntExpr))) 137 TYPE_PARSER(construct<AccSizeExprList>(nonemptyList(Parser<AccSizeExpr>{}))) 138 139 // 2.9 (1607) gang-arg is one of: 140 // [num:]int-expr 141 // static:size-expr 142 TYPE_PARSER(construct<AccGangArgument>(maybe(scalarIntExpr), 143 maybe(","_tok / "STATIC:" >> Parser<AccSizeExpr>{})) || 144 construct<AccGangArgument>(maybe("NUM:" >> scalarIntExpr), 145 maybe(","_tok / "STATIC:" >> Parser<AccSizeExpr>{}))) 146 147 // 2.5.13 Reduction 148 TYPE_PARSER(construct<AccReductionOperator>(Parser<DefinedOperator>{}) || 149 construct<AccReductionOperator>(Parser<ProcedureDesignator>{})) 150 151 // 2.5.14 Default clause 152 TYPE_PARSER(construct<AccDefaultClause>( 153 parenthesized(first("NONE" >> pure(AccDefaultClause::Arg::None), 154 "PRESENT" >> pure(AccDefaultClause::Arg::Present))))) 155 156 // Modifier for copyin, copyout, cache and create 157 TYPE_PARSER(construct<AccDataModifier>( 158 first("ZERO:" >> pure(AccDataModifier::Modifier::Zero), 159 "READONLY:" >> pure(AccDataModifier::Modifier::ReadOnly)))) 160 161 // Combined directives 162 TYPE_PARSER(sourced(construct<AccCombinedDirective>( 163 first("KERNELS LOOP" >> pure(llvm::acc::Directive::ACCD_kernels_loop), 164 "PARALLEL LOOP" >> pure(llvm::acc::Directive::ACCD_parallel_loop), 165 "SERIAL LOOP" >> pure(llvm::acc::Directive::ACCD_serial_loop))))) 166 167 // Block directives 168 TYPE_PARSER(sourced(construct<AccBlockDirective>( 169 first("DATA" >> pure(llvm::acc::Directive::ACCD_data), 170 "HOST_DATA" >> pure(llvm::acc::Directive::ACCD_host_data), 171 "KERNELS" >> pure(llvm::acc::Directive::ACCD_kernels), 172 "PARALLEL" >> pure(llvm::acc::Directive::ACCD_parallel), 173 "SERIAL" >> pure(llvm::acc::Directive::ACCD_serial))))) 174 175 // Standalone directives 176 TYPE_PARSER(sourced(construct<AccStandaloneDirective>( 177 first("ENTER DATA" >> pure(llvm::acc::Directive::ACCD_enter_data), 178 "EXIT DATA" >> pure(llvm::acc::Directive::ACCD_exit_data), 179 "INIT" >> pure(llvm::acc::Directive::ACCD_init), 180 "SHUTDOWN" >> pure(llvm::acc::Directive::ACCD_shutdown), 181 "SET" >> pure(llvm::acc::Directive::ACCD_set), 182 "UPDATE" >> pure(llvm::acc::Directive::ACCD_update))))) 183 184 // Loop directives 185 TYPE_PARSER(sourced(construct<AccLoopDirective>( 186 first("LOOP" >> pure(llvm::acc::Directive::ACCD_loop))))) 187 188 TYPE_PARSER(construct<AccBeginLoopDirective>( 189 sourced(Parser<AccLoopDirective>{}), Parser<AccClauseList>{})) 190 191 TYPE_PARSER( 192 construct<OpenACCLoopConstruct>(sourced(Parser<AccBeginLoopDirective>{}))) 193 194 // 2.15.1 Routine directive 195 TYPE_PARSER(sourced(construct<OpenACCRoutineConstruct>(verbatim("ROUTINE"_tok), 196 maybe(parenthesized(name)), Parser<AccClauseList>{}))) 197 198 // 2.10 Cache directive 199 TYPE_PARSER(sourced( 200 construct<OpenACCCacheConstruct>(sourced(construct<Verbatim>("CACHE"_tok)), 201 parenthesized(Parser<AccObjectListWithModifier>{})))) 202 203 // 2.11 Combined constructs 204 TYPE_PARSER(construct<AccBeginCombinedDirective>( 205 sourced(Parser<AccCombinedDirective>{}), Parser<AccClauseList>{})) 206 207 // 2.12 Atomic constructs 208 TYPE_PARSER(construct<AccEndAtomic>(startAccLine >> "END ATOMIC"_tok)) 209 210 TYPE_PARSER("ATOMIC" >> 211 construct<AccAtomicRead>(verbatim("READ"_tok) / endAccLine, 212 statement(assignmentStmt), maybe(Parser<AccEndAtomic>{} / endAccLine))) 213 214 TYPE_PARSER("ATOMIC" >> 215 construct<AccAtomicWrite>(verbatim("WRITE"_tok) / endAccLine, 216 statement(assignmentStmt), maybe(Parser<AccEndAtomic>{} / endAccLine))) 217 218 TYPE_PARSER("ATOMIC" >> 219 construct<AccAtomicUpdate>(maybe(verbatim("UPDATE"_tok)) / endAccLine, 220 statement(assignmentStmt), maybe(Parser<AccEndAtomic>{} / endAccLine))) 221 222 TYPE_PARSER("ATOMIC" >> 223 construct<AccAtomicCapture>(verbatim("CAPTURE"_tok) / endAccLine, 224 statement(assignmentStmt), statement(assignmentStmt), 225 Parser<AccEndAtomic>{} / endAccLine)) 226 227 TYPE_PARSER(construct<OpenACCAtomicConstruct>(Parser<AccAtomicRead>{}) || 228 construct<OpenACCAtomicConstruct>(Parser<AccAtomicCapture>{}) || 229 construct<OpenACCAtomicConstruct>(Parser<AccAtomicWrite>{}) || 230 construct<OpenACCAtomicConstruct>(Parser<AccAtomicUpdate>{})) 231 232 // 2.13 Declare constructs 233 TYPE_PARSER(sourced(construct<AccDeclarativeDirective>( 234 first("DECLARE" >> pure(llvm::acc::Directive::ACCD_declare))))) 235 236 // [Clause, [Clause], ...] 237 TYPE_PARSER(sourced(construct<AccClauseList>( 238 many(maybe(","_tok) >> sourced(Parser<AccClause>{}))))) 239 240 // 2.16.3 Wait directive 241 TYPE_PARSER(sourced(construct<OpenACCWaitConstruct>( 242 sourced(construct<Verbatim>("WAIT"_tok)), 243 maybe(parenthesized(Parser<AccWaitArgument>{})), Parser<AccClauseList>{}))) 244 245 // Block Constructs 246 TYPE_PARSER(sourced(construct<AccBeginBlockDirective>( 247 sourced(Parser<AccBlockDirective>{}), Parser<AccClauseList>{}))) 248 249 TYPE_PARSER(startAccLine >> sourced(construct<AccEndBlockDirective>("END"_tok >> 250 sourced(Parser<AccBlockDirective>{})))) 251 252 TYPE_PARSER(construct<OpenACCBlockConstruct>( 253 Parser<AccBeginBlockDirective>{} / endAccLine, block, 254 Parser<AccEndBlockDirective>{} / endAccLine)) 255 256 // Standalone constructs 257 TYPE_PARSER(construct<OpenACCStandaloneConstruct>( 258 sourced(Parser<AccStandaloneDirective>{}), Parser<AccClauseList>{})) 259 260 // Standalone declarative constructs 261 TYPE_PARSER(construct<OpenACCStandaloneDeclarativeConstruct>( 262 sourced(Parser<AccDeclarativeDirective>{}), Parser<AccClauseList>{})) 263 264 TYPE_PARSER( 265 startAccLine >> sourced(construct<OpenACCDeclarativeConstruct>( 266 Parser<OpenACCStandaloneDeclarativeConstruct>{}))) 267 268 // OpenACC constructs 269 TYPE_CONTEXT_PARSER("OpenACC construct"_en_US, 270 startAccLine >> 271 first(construct<OpenACCConstruct>(Parser<OpenACCBlockConstruct>{}), 272 construct<OpenACCConstruct>(Parser<OpenACCCombinedConstruct>{}), 273 construct<OpenACCConstruct>(Parser<OpenACCLoopConstruct>{}), 274 construct<OpenACCConstruct>(Parser<OpenACCStandaloneConstruct>{}), 275 construct<OpenACCConstruct>(Parser<OpenACCRoutineConstruct>{}), 276 construct<OpenACCConstruct>(Parser<OpenACCCacheConstruct>{}), 277 construct<OpenACCConstruct>(Parser<OpenACCWaitConstruct>{}), 278 construct<OpenACCConstruct>(Parser<OpenACCAtomicConstruct>{}))) 279 280 TYPE_PARSER(startAccLine >> sourced(construct<AccEndCombinedDirective>(sourced( 281 "END"_tok >> Parser<AccCombinedDirective>{})))) 282 283 TYPE_PARSER(construct<OpenACCCombinedConstruct>( 284 sourced(Parser<AccBeginCombinedDirective>{} / endAccLine))) 285 286 } // namespace Fortran::parser 287