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.1. 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" >> construct<AccClause>( 32 construct<AccClause::Bind>(Parser<AccBindClause>{})) || 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 "DEVICE_NUM" >> construct<AccClause>(construct<AccClause::DeviceNum>( 61 parenthesized(scalarIntExpr))) || 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>( 67 parenthesized(Parser<AccDeviceTypeExprList>{}))) || 68 "FINALIZE" >> construct<AccClause>(construct<AccClause::Finalize>()) || 69 "FIRSTPRIVATE" >> construct<AccClause>(construct<AccClause::Firstprivate>( 70 parenthesized(Parser<AccObjectList>{}))) || 71 "GANG" >> construct<AccClause>(construct<AccClause::Gang>( 72 maybe(parenthesized(Parser<AccGangArgument>{})))) || 73 "HOST" >> construct<AccClause>(construct<AccClause::Host>( 74 parenthesized(Parser<AccObjectList>{}))) || 75 "IF" >> construct<AccClause>( 76 construct<AccClause::If>(parenthesized(scalarLogicalExpr))) || 77 "IF_PRESENT" >> construct<AccClause>(construct<AccClause::IfPresent>()) || 78 "INDEPENDENT" >> 79 construct<AccClause>(construct<AccClause::Independent>()) || 80 "LINK" >> construct<AccClause>(construct<AccClause::Link>( 81 parenthesized(Parser<AccObjectList>{}))) || 82 "NO_CREATE" >> construct<AccClause>(construct<AccClause::NoCreate>( 83 parenthesized(Parser<AccObjectList>{}))) || 84 "NOHOST" >> construct<AccClause>(construct<AccClause::Nohost>()) || 85 "NUM_GANGS" >> construct<AccClause>(construct<AccClause::NumGangs>( 86 parenthesized(scalarIntExpr))) || 87 "NUM_WORKERS" >> construct<AccClause>(construct<AccClause::NumWorkers>( 88 parenthesized(scalarIntExpr))) || 89 "PRESENT" >> construct<AccClause>(construct<AccClause::Present>( 90 parenthesized(Parser<AccObjectList>{}))) || 91 "PRIVATE" >> construct<AccClause>(construct<AccClause::Private>( 92 parenthesized(Parser<AccObjectList>{}))) || 93 "READ" >> construct<AccClause>(construct<AccClause::Read>()) || 94 "REDUCTION" >> construct<AccClause>(construct<AccClause::Reduction>( 95 parenthesized(construct<AccObjectListWithReduction>( 96 Parser<AccReductionOperator>{} / ":", 97 Parser<AccObjectList>{})))) || 98 "SELF" >> construct<AccClause>(construct<AccClause::Self>( 99 maybe(parenthesized(Parser<AccSelfClause>{})))) || 100 "SEQ" >> construct<AccClause>(construct<AccClause::Seq>()) || 101 "TILE" >> construct<AccClause>(construct<AccClause::Tile>( 102 parenthesized(Parser<AccTileExprList>{}))) || 103 "USE_DEVICE" >> construct<AccClause>(construct<AccClause::UseDevice>( 104 parenthesized(Parser<AccObjectList>{}))) || 105 "VECTOR_LENGTH" >> construct<AccClause>(construct<AccClause::VectorLength>( 106 parenthesized(scalarIntExpr))) || 107 "VECTOR" >> 108 construct<AccClause>(construct<AccClause::Vector>(maybe( 109 parenthesized(("LENGTH:" >> scalarIntExpr || scalarIntExpr))))) || 110 "WAIT" >> construct<AccClause>(construct<AccClause::Wait>( 111 maybe(parenthesized(Parser<AccWaitArgument>{})))) || 112 "WORKER" >> 113 construct<AccClause>(construct<AccClause::Worker>(maybe( 114 parenthesized(("NUM:" >> scalarIntExpr || scalarIntExpr))))) || 115 "WRITE" >> construct<AccClause>(construct<AccClause::Auto>())) 116 117 TYPE_PARSER( 118 construct<AccObject>(designator) || construct<AccObject>("/" >> name / "/")) 119 120 TYPE_PARSER(construct<AccObjectList>(nonemptyList(Parser<AccObject>{}))) 121 122 TYPE_PARSER(construct<AccObjectListWithModifier>( 123 maybe(Parser<AccDataModifier>{}), Parser<AccObjectList>{})) 124 125 // 2.16.3 (2485) wait-argument is: 126 // [devnum : int-expr :] [queues :] int-expr-list 127 TYPE_PARSER(construct<AccWaitArgument>(maybe("DEVNUM:" >> scalarIntExpr / ":"), 128 "QUEUES:" >> nonemptyList(scalarIntExpr) || nonemptyList(scalarIntExpr))) 129 130 // 2.9 (1609) size-expr is one of: 131 // * (represented as an empty std::optional<ScalarIntExpr>) 132 // int-expr 133 TYPE_PARSER(construct<AccSizeExpr>(scalarIntExpr) || 134 construct<AccSizeExpr>("*" >> construct<std::optional<ScalarIntExpr>>())) 135 TYPE_PARSER(construct<AccSizeExprList>(nonemptyList(Parser<AccSizeExpr>{}))) 136 137 TYPE_PARSER(construct<AccDeviceTypeExpr>(scalarIntExpr) || 138 construct<AccDeviceTypeExpr>( 139 "*" >> construct<std::optional<ScalarIntExpr>>())) 140 TYPE_PARSER( 141 construct<AccDeviceTypeExprList>(nonemptyList(Parser<AccDeviceTypeExpr>{}))) 142 143 // tile size is one of: 144 // * (represented as an empty std::optional<ScalarIntExpr>) 145 // constant-int-expr 146 TYPE_PARSER(construct<AccTileExpr>(scalarIntConstantExpr) || 147 construct<AccTileExpr>( 148 "*" >> construct<std::optional<ScalarIntConstantExpr>>())) 149 TYPE_PARSER(construct<AccTileExprList>(nonemptyList(Parser<AccTileExpr>{}))) 150 151 // 2.9 (1607) gang-arg is: 152 // [[num:]int-expr][[,]static:size-expr] 153 TYPE_PARSER(construct<AccGangArgument>( 154 maybe(("NUM:"_tok >> scalarIntExpr || scalarIntExpr)), 155 maybe(", STATIC:" >> Parser<AccSizeExpr>{}))) 156 157 // 2.5.13 Reduction 158 // Operator for reduction 159 TYPE_PARSER(sourced(construct<AccReductionOperator>( 160 first("+" >> pure(AccReductionOperator::Operator::Plus), 161 "*" >> pure(AccReductionOperator::Operator::Multiply), 162 "MAX" >> pure(AccReductionOperator::Operator::Max), 163 "MIN" >> pure(AccReductionOperator::Operator::Min), 164 "IAND" >> pure(AccReductionOperator::Operator::Iand), 165 "IOR" >> pure(AccReductionOperator::Operator::Ior), 166 "IEOR" >> pure(AccReductionOperator::Operator::Ieor), 167 ".AND." >> pure(AccReductionOperator::Operator::And), 168 ".OR." >> pure(AccReductionOperator::Operator::Or), 169 ".EQV." >> pure(AccReductionOperator::Operator::Eqv), 170 ".NEQV." >> pure(AccReductionOperator::Operator::Neqv))))) 171 172 // 2.15.1 Bind clause 173 TYPE_PARSER(sourced(construct<AccBindClause>(parenthesized(name))) || 174 sourced(construct<AccBindClause>(parenthesized(scalarDefaultCharExpr)))) 175 176 // 2.5.14 Default clause 177 TYPE_PARSER(construct<AccDefaultClause>(parenthesized( 178 first("NONE" >> pure(llvm::acc::DefaultValue::ACC_Default_none), 179 "PRESENT" >> pure(llvm::acc::DefaultValue::ACC_Default_present))))) 180 181 // SELF clause is either a simple optional condition for compute construct 182 // or a synonym of the HOST clause for the update directive 2.14.4 holding 183 // an object list. 184 TYPE_PARSER(construct<AccSelfClause>(Parser<AccObjectList>{}) || 185 construct<AccSelfClause>(scalarLogicalExpr)) 186 187 // Modifier for copyin, copyout, cache and create 188 TYPE_PARSER(construct<AccDataModifier>( 189 first("ZERO:" >> pure(AccDataModifier::Modifier::Zero), 190 "READONLY:" >> pure(AccDataModifier::Modifier::ReadOnly)))) 191 192 // Combined directives 193 TYPE_PARSER(sourced(construct<AccCombinedDirective>( 194 first("KERNELS LOOP" >> pure(llvm::acc::Directive::ACCD_kernels_loop), 195 "PARALLEL LOOP" >> pure(llvm::acc::Directive::ACCD_parallel_loop), 196 "SERIAL LOOP" >> pure(llvm::acc::Directive::ACCD_serial_loop))))) 197 198 // Block directives 199 TYPE_PARSER(sourced(construct<AccBlockDirective>( 200 first("DATA" >> pure(llvm::acc::Directive::ACCD_data), 201 "HOST_DATA" >> pure(llvm::acc::Directive::ACCD_host_data), 202 "KERNELS" >> pure(llvm::acc::Directive::ACCD_kernels), 203 "PARALLEL" >> pure(llvm::acc::Directive::ACCD_parallel), 204 "SERIAL" >> pure(llvm::acc::Directive::ACCD_serial))))) 205 206 // Standalone directives 207 TYPE_PARSER(sourced(construct<AccStandaloneDirective>( 208 first("ENTER DATA" >> pure(llvm::acc::Directive::ACCD_enter_data), 209 "EXIT DATA" >> pure(llvm::acc::Directive::ACCD_exit_data), 210 "INIT" >> pure(llvm::acc::Directive::ACCD_init), 211 "SHUTDOWN" >> pure(llvm::acc::Directive::ACCD_shutdown), 212 "SET" >> pure(llvm::acc::Directive::ACCD_set), 213 "UPDATE" >> pure(llvm::acc::Directive::ACCD_update))))) 214 215 // Loop directives 216 TYPE_PARSER(sourced(construct<AccLoopDirective>( 217 first("LOOP" >> pure(llvm::acc::Directive::ACCD_loop))))) 218 219 TYPE_PARSER(construct<AccBeginLoopDirective>( 220 sourced(Parser<AccLoopDirective>{}), Parser<AccClauseList>{})) 221 222 TYPE_PARSER( 223 construct<OpenACCLoopConstruct>(sourced(Parser<AccBeginLoopDirective>{}))) 224 225 // 2.15.1 Routine directive 226 TYPE_PARSER(sourced(construct<OpenACCRoutineConstruct>(verbatim("ROUTINE"_tok), 227 maybe(parenthesized(name)), Parser<AccClauseList>{}))) 228 229 // 2.10 Cache directive 230 TYPE_PARSER(sourced( 231 construct<OpenACCCacheConstruct>(sourced(construct<Verbatim>("CACHE"_tok)), 232 parenthesized(Parser<AccObjectListWithModifier>{})))) 233 234 // 2.11 Combined constructs 235 TYPE_PARSER(construct<AccBeginCombinedDirective>( 236 sourced(Parser<AccCombinedDirective>{}), Parser<AccClauseList>{})) 237 238 // 2.12 Atomic constructs 239 TYPE_PARSER(construct<AccEndAtomic>(startAccLine >> "END ATOMIC"_tok)) 240 241 TYPE_PARSER("ATOMIC" >> 242 construct<AccAtomicRead>(verbatim("READ"_tok) / endAccLine, 243 statement(assignmentStmt), maybe(Parser<AccEndAtomic>{} / endAccLine))) 244 245 TYPE_PARSER("ATOMIC" >> 246 construct<AccAtomicWrite>(verbatim("WRITE"_tok) / endAccLine, 247 statement(assignmentStmt), maybe(Parser<AccEndAtomic>{} / endAccLine))) 248 249 TYPE_PARSER("ATOMIC" >> 250 construct<AccAtomicUpdate>(maybe(verbatim("UPDATE"_tok)) / endAccLine, 251 statement(assignmentStmt), maybe(Parser<AccEndAtomic>{} / endAccLine))) 252 253 TYPE_PARSER("ATOMIC" >> 254 construct<AccAtomicCapture>(verbatim("CAPTURE"_tok) / endAccLine, 255 statement(assignmentStmt), statement(assignmentStmt), 256 Parser<AccEndAtomic>{} / endAccLine)) 257 258 TYPE_PARSER( 259 sourced(construct<OpenACCAtomicConstruct>(Parser<AccAtomicRead>{})) || 260 sourced(construct<OpenACCAtomicConstruct>(Parser<AccAtomicCapture>{})) || 261 sourced(construct<OpenACCAtomicConstruct>(Parser<AccAtomicWrite>{})) || 262 sourced(construct<OpenACCAtomicConstruct>(Parser<AccAtomicUpdate>{}))) 263 264 // 2.13 Declare constructs 265 TYPE_PARSER(sourced(construct<AccDeclarativeDirective>( 266 first("DECLARE" >> pure(llvm::acc::Directive::ACCD_declare))))) 267 268 // [Clause, [Clause], ...] 269 TYPE_PARSER(sourced(construct<AccClauseList>( 270 many(maybe(","_tok) >> sourced(Parser<AccClause>{}))))) 271 272 // 2.16.3 Wait directive 273 TYPE_PARSER(sourced(construct<OpenACCWaitConstruct>( 274 sourced(construct<Verbatim>("WAIT"_tok)), 275 maybe(parenthesized(Parser<AccWaitArgument>{})), Parser<AccClauseList>{}))) 276 277 // Block Constructs 278 TYPE_PARSER(sourced(construct<AccBeginBlockDirective>( 279 sourced(Parser<AccBlockDirective>{}), Parser<AccClauseList>{}))) 280 281 TYPE_PARSER(startAccLine >> sourced(construct<AccEndBlockDirective>("END"_tok >> 282 sourced(Parser<AccBlockDirective>{})))) 283 284 TYPE_PARSER(construct<OpenACCBlockConstruct>( 285 Parser<AccBeginBlockDirective>{} / endAccLine, block, 286 Parser<AccEndBlockDirective>{} / endAccLine)) 287 288 // Standalone constructs 289 TYPE_PARSER(construct<OpenACCStandaloneConstruct>( 290 sourced(Parser<AccStandaloneDirective>{}), Parser<AccClauseList>{})) 291 292 // Standalone declarative constructs 293 TYPE_PARSER(construct<OpenACCStandaloneDeclarativeConstruct>( 294 sourced(Parser<AccDeclarativeDirective>{}), Parser<AccClauseList>{})) 295 296 TYPE_PARSER( 297 startAccLine >> first(sourced(construct<OpenACCDeclarativeConstruct>( 298 Parser<OpenACCStandaloneDeclarativeConstruct>{})), 299 sourced(construct<OpenACCDeclarativeConstruct>( 300 Parser<OpenACCRoutineConstruct>{})))) 301 302 // OpenACC constructs 303 TYPE_CONTEXT_PARSER("OpenACC construct"_en_US, 304 startAccLine >> 305 first(construct<OpenACCConstruct>(Parser<OpenACCBlockConstruct>{}), 306 construct<OpenACCConstruct>(Parser<OpenACCCombinedConstruct>{}), 307 construct<OpenACCConstruct>(Parser<OpenACCLoopConstruct>{}), 308 construct<OpenACCConstruct>(Parser<OpenACCStandaloneConstruct>{}), 309 construct<OpenACCConstruct>(Parser<OpenACCCacheConstruct>{}), 310 construct<OpenACCConstruct>(Parser<OpenACCWaitConstruct>{}), 311 construct<OpenACCConstruct>(Parser<OpenACCAtomicConstruct>{}))) 312 313 TYPE_PARSER(startAccLine >> sourced(construct<AccEndCombinedDirective>(sourced( 314 "END"_tok >> Parser<AccCombinedDirective>{})))) 315 316 TYPE_PARSER(construct<OpenACCCombinedConstruct>( 317 sourced(Parser<AccBeginCombinedDirective>{} / endAccLine))) 318 319 } // namespace Fortran::parser 320