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.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 Clauses 20 namespace Fortran::parser { 21 22 constexpr auto startAccLine{skipStuffBeforeStatement >> 23 ("!$ACC "_sptok || "C$ACC "_sptok || "*$ACC "_sptok)}; 24 constexpr auto endAccLine{space >> endOfLine}; 25 26 // Autogenerated clauses parser. Information is taken from ACC.td and the 27 // parser is generated by tablegen. 28 // Scalar value parsers are provided by Flang directly. Specific value parsers 29 // are provided below. 30 #define GEN_FLANG_CLAUSES_PARSER 31 #include "llvm/Frontend/OpenACC/ACC.inc" 32 33 TYPE_PARSER( 34 construct<AccObject>(designator) || construct<AccObject>("/" >> name / "/")) 35 36 TYPE_PARSER(construct<AccObjectList>(nonemptyList(Parser<AccObject>{}))) 37 38 TYPE_PARSER(construct<AccObjectListWithModifier>( 39 maybe(Parser<AccDataModifier>{}), Parser<AccObjectList>{})) 40 41 TYPE_PARSER(construct<AccObjectListWithReduction>( 42 Parser<ReductionOperator>{} / ":", Parser<AccObjectList>{})) 43 44 // 2.16 (3249) wait-argument is: 45 // [devnum : int-expr :] [queues :] int-expr-list 46 TYPE_PARSER(construct<AccWaitArgument>(maybe("DEVNUM:" >> scalarIntExpr / ":"), 47 "QUEUES:" >> nonemptyList(scalarIntExpr) || nonemptyList(scalarIntExpr))) 48 49 // 2.9 (1984-1986) size-expr is one of: 50 // * (represented as an empty std::optional<ScalarIntExpr>) 51 // int-expr 52 TYPE_PARSER(construct<AccSizeExpr>(scalarIntExpr) || 53 construct<AccSizeExpr>("*" >> construct<std::optional<ScalarIntExpr>>())) 54 TYPE_PARSER(construct<AccSizeExprList>(nonemptyList(Parser<AccSizeExpr>{}))) 55 56 TYPE_PARSER(sourced(construct<AccDeviceTypeExpr>( 57 first("*" >> pure(Fortran::common::OpenACCDeviceType::Star), 58 "DEFAULT" >> pure(Fortran::common::OpenACCDeviceType::Default), 59 "NVIDIA" >> pure(Fortran::common::OpenACCDeviceType::Nvidia), 60 "ACC_DEVICE_NVIDIA" >> pure(Fortran::common::OpenACCDeviceType::Nvidia), 61 "RADEON" >> pure(Fortran::common::OpenACCDeviceType::Radeon), 62 "HOST" >> pure(Fortran::common::OpenACCDeviceType::Host), 63 "MULTICORE" >> pure(Fortran::common::OpenACCDeviceType::Multicore))))) 64 65 TYPE_PARSER( 66 construct<AccDeviceTypeExprList>(nonemptyList(Parser<AccDeviceTypeExpr>{}))) 67 68 // tile size is one of: 69 // * (represented as an empty std::optional<ScalarIntExpr>) 70 // constant-int-expr 71 TYPE_PARSER(construct<AccTileExpr>(scalarIntConstantExpr) || 72 construct<AccTileExpr>( 73 "*" >> construct<std::optional<ScalarIntConstantExpr>>())) 74 TYPE_PARSER(construct<AccTileExprList>(nonemptyList(Parser<AccTileExpr>{}))) 75 76 // 2.9 (1979-1982) gang-arg is one of : 77 // [num:]int-expr 78 // dim:int-expr 79 // static:size-expr 80 TYPE_PARSER(construct<AccGangArg>(construct<AccGangArg::Static>( 81 "STATIC: " >> Parser<AccSizeExpr>{})) || 82 construct<AccGangArg>( 83 construct<AccGangArg::Dim>("DIM: " >> scalarIntExpr)) || 84 construct<AccGangArg>( 85 construct<AccGangArg::Num>(maybe("NUM: "_tok) >> scalarIntExpr))) 86 87 // 2.9 gang-arg-list 88 TYPE_PARSER( 89 construct<AccGangArgList>(many(maybe(","_tok) >> Parser<AccGangArg>{}))) 90 91 // 2.9.1 collapse 92 TYPE_PARSER(construct<AccCollapseArg>( 93 "FORCE:"_tok >> pure(true) || pure(false), scalarIntConstantExpr)) 94 95 // 2.5.15 Reduction, F'2023 R1131, and CUF reduction-op 96 // Operator for reduction 97 TYPE_PARSER(sourced(construct<ReductionOperator>( 98 first("+" >> pure(ReductionOperator::Operator::Plus), 99 "*" >> pure(ReductionOperator::Operator::Multiply), 100 "MAX" >> pure(ReductionOperator::Operator::Max), 101 "MIN" >> pure(ReductionOperator::Operator::Min), 102 "IAND" >> pure(ReductionOperator::Operator::Iand), 103 "IOR" >> pure(ReductionOperator::Operator::Ior), 104 "IEOR" >> pure(ReductionOperator::Operator::Ieor), 105 ".AND." >> pure(ReductionOperator::Operator::And), 106 ".OR." >> pure(ReductionOperator::Operator::Or), 107 ".EQV." >> pure(ReductionOperator::Operator::Eqv), 108 ".NEQV." >> pure(ReductionOperator::Operator::Neqv))))) 109 110 // 2.15.1 Bind clause 111 TYPE_PARSER(sourced(construct<AccBindClause>(name)) || 112 sourced(construct<AccBindClause>(scalarDefaultCharExpr))) 113 114 // 2.5.16 Default clause 115 TYPE_PARSER(construct<AccDefaultClause>( 116 first("NONE" >> pure(llvm::acc::DefaultValue::ACC_Default_none), 117 "PRESENT" >> pure(llvm::acc::DefaultValue::ACC_Default_present)))) 118 119 // SELF clause is either a simple optional condition for compute construct 120 // or a synonym of the HOST clause for the update directive 2.14.4 holding 121 // an object list. 122 TYPE_PARSER(construct<AccSelfClause>(Parser<AccObjectList>{}) || 123 construct<AccSelfClause>(scalarLogicalExpr)) 124 125 // Modifier for copyin, copyout, cache and create 126 TYPE_PARSER(construct<AccDataModifier>( 127 first("ZERO:" >> pure(AccDataModifier::Modifier::Zero), 128 "READONLY:" >> pure(AccDataModifier::Modifier::ReadOnly)))) 129 130 // Combined directives 131 TYPE_PARSER(sourced(construct<AccCombinedDirective>( 132 first("KERNELS LOOP" >> pure(llvm::acc::Directive::ACCD_kernels_loop), 133 "PARALLEL LOOP" >> pure(llvm::acc::Directive::ACCD_parallel_loop), 134 "SERIAL LOOP" >> pure(llvm::acc::Directive::ACCD_serial_loop))))) 135 136 // Block directives 137 TYPE_PARSER(sourced(construct<AccBlockDirective>( 138 first("DATA" >> pure(llvm::acc::Directive::ACCD_data), 139 "HOST_DATA" >> pure(llvm::acc::Directive::ACCD_host_data), 140 "KERNELS" >> pure(llvm::acc::Directive::ACCD_kernels), 141 "PARALLEL" >> pure(llvm::acc::Directive::ACCD_parallel), 142 "SERIAL" >> pure(llvm::acc::Directive::ACCD_serial))))) 143 144 // Standalone directives 145 TYPE_PARSER(sourced(construct<AccStandaloneDirective>( 146 first("ENTER DATA" >> pure(llvm::acc::Directive::ACCD_enter_data), 147 "EXIT DATA" >> pure(llvm::acc::Directive::ACCD_exit_data), 148 "INIT" >> pure(llvm::acc::Directive::ACCD_init), 149 "SHUTDOWN" >> pure(llvm::acc::Directive::ACCD_shutdown), 150 "SET" >> pure(llvm::acc::Directive::ACCD_set), 151 "UPDATE" >> pure(llvm::acc::Directive::ACCD_update))))) 152 153 // Loop directives 154 TYPE_PARSER(sourced(construct<AccLoopDirective>( 155 first("LOOP" >> pure(llvm::acc::Directive::ACCD_loop))))) 156 157 TYPE_PARSER(construct<AccBeginLoopDirective>( 158 sourced(Parser<AccLoopDirective>{}), Parser<AccClauseList>{})) 159 160 TYPE_PARSER(construct<AccEndLoop>("END LOOP"_tok)) 161 162 TYPE_PARSER(construct<OpenACCLoopConstruct>( 163 sourced(Parser<AccBeginLoopDirective>{} / endAccLine), 164 maybe(Parser<DoConstruct>{}), 165 maybe(startAccLine >> Parser<AccEndLoop>{} / endAccLine))) 166 167 // 2.15.1 Routine directive 168 TYPE_PARSER(sourced(construct<OpenACCRoutineConstruct>(verbatim("ROUTINE"_tok), 169 maybe(parenthesized(name)), Parser<AccClauseList>{}))) 170 171 // 2.10 Cache directive 172 TYPE_PARSER(sourced( 173 construct<OpenACCCacheConstruct>(sourced(construct<Verbatim>("CACHE"_tok)), 174 parenthesized(Parser<AccObjectListWithModifier>{})))) 175 176 // 2.11 Combined constructs 177 TYPE_PARSER(construct<AccBeginCombinedDirective>( 178 sourced(Parser<AccCombinedDirective>{}), Parser<AccClauseList>{})) 179 180 // 2.12 Atomic constructs 181 TYPE_PARSER(construct<AccEndAtomic>(startAccLine >> "END ATOMIC"_tok)) 182 183 TYPE_PARSER("ATOMIC" >> 184 construct<AccAtomicRead>(verbatim("READ"_tok) / endAccLine, 185 statement(assignmentStmt), maybe(Parser<AccEndAtomic>{} / endAccLine))) 186 187 TYPE_PARSER("ATOMIC" >> 188 construct<AccAtomicWrite>(verbatim("WRITE"_tok) / endAccLine, 189 statement(assignmentStmt), maybe(Parser<AccEndAtomic>{} / endAccLine))) 190 191 TYPE_PARSER("ATOMIC" >> 192 construct<AccAtomicUpdate>(maybe(verbatim("UPDATE"_tok)) / endAccLine, 193 statement(assignmentStmt), maybe(Parser<AccEndAtomic>{} / endAccLine))) 194 195 TYPE_PARSER("ATOMIC" >> 196 construct<AccAtomicCapture>(verbatim("CAPTURE"_tok) / endAccLine, 197 statement(assignmentStmt), statement(assignmentStmt), 198 Parser<AccEndAtomic>{} / endAccLine)) 199 200 TYPE_PARSER( 201 sourced(construct<OpenACCAtomicConstruct>(Parser<AccAtomicRead>{})) || 202 sourced(construct<OpenACCAtomicConstruct>(Parser<AccAtomicCapture>{})) || 203 sourced(construct<OpenACCAtomicConstruct>(Parser<AccAtomicWrite>{})) || 204 sourced(construct<OpenACCAtomicConstruct>(Parser<AccAtomicUpdate>{}))) 205 206 // 2.13 Declare constructs 207 TYPE_PARSER(sourced(construct<AccDeclarativeDirective>( 208 first("DECLARE" >> pure(llvm::acc::Directive::ACCD_declare))))) 209 210 // [Clause, [Clause], ...] 211 TYPE_PARSER(sourced(construct<AccClauseList>( 212 many(maybe(","_tok) >> sourced(Parser<AccClause>{}))))) 213 214 // 2.16.3 Wait directive 215 TYPE_PARSER(sourced(construct<OpenACCWaitConstruct>( 216 sourced(construct<Verbatim>("WAIT"_tok)), 217 maybe(parenthesized(Parser<AccWaitArgument>{})), Parser<AccClauseList>{}))) 218 219 // Block Constructs 220 TYPE_PARSER(sourced(construct<AccBeginBlockDirective>( 221 sourced(Parser<AccBlockDirective>{}), Parser<AccClauseList>{}))) 222 223 TYPE_PARSER(startAccLine >> sourced(construct<AccEndBlockDirective>("END"_tok >> 224 sourced(Parser<AccBlockDirective>{})))) 225 226 TYPE_PARSER(construct<OpenACCBlockConstruct>( 227 Parser<AccBeginBlockDirective>{} / endAccLine, block, 228 Parser<AccEndBlockDirective>{} / endAccLine)) 229 230 // Standalone constructs 231 TYPE_PARSER(construct<OpenACCStandaloneConstruct>( 232 sourced(Parser<AccStandaloneDirective>{}), Parser<AccClauseList>{})) 233 234 // Standalone declarative constructs 235 TYPE_PARSER(construct<OpenACCStandaloneDeclarativeConstruct>( 236 sourced(Parser<AccDeclarativeDirective>{}), Parser<AccClauseList>{})) 237 238 TYPE_PARSER(startAccLine >> 239 withMessage("expected OpenACC directive"_err_en_US, 240 first(sourced(construct<OpenACCDeclarativeConstruct>( 241 Parser<OpenACCStandaloneDeclarativeConstruct>{})), 242 sourced(construct<OpenACCDeclarativeConstruct>( 243 Parser<OpenACCRoutineConstruct>{}))))) 244 245 TYPE_PARSER(sourced(construct<OpenACCEndConstruct>( 246 "END"_tok >> "LOOP"_tok >> pure(llvm::acc::Directive::ACCD_loop)))) 247 248 // OpenACC constructs 249 TYPE_CONTEXT_PARSER("OpenACC construct"_en_US, 250 startAccLine >> 251 withMessage("expected OpenACC directive"_err_en_US, 252 first(construct<OpenACCConstruct>(Parser<OpenACCBlockConstruct>{}), 253 construct<OpenACCConstruct>(Parser<OpenACCCombinedConstruct>{}), 254 construct<OpenACCConstruct>(Parser<OpenACCLoopConstruct>{}), 255 construct<OpenACCConstruct>( 256 Parser<OpenACCStandaloneConstruct>{}), 257 construct<OpenACCConstruct>(Parser<OpenACCCacheConstruct>{}), 258 construct<OpenACCConstruct>(Parser<OpenACCWaitConstruct>{}), 259 construct<OpenACCConstruct>(Parser<OpenACCAtomicConstruct>{}), 260 construct<OpenACCConstruct>(Parser<OpenACCEndConstruct>{})))) 261 262 TYPE_PARSER(startAccLine >> 263 sourced(construct<AccEndCombinedDirective>(sourced("END"_tok >> 264 construct<AccCombinedDirective>("KERNELS"_tok >> maybe("LOOP"_tok) >> 265 pure(llvm::acc::Directive::ACCD_kernels_loop) || 266 "PARALLEL"_tok >> maybe("LOOP"_tok) >> 267 pure(llvm::acc::Directive::ACCD_parallel_loop) || 268 "SERIAL"_tok >> maybe("LOOP"_tok) >> 269 pure(llvm::acc::Directive::ACCD_serial_loop)))))) 270 271 TYPE_PARSER(construct<OpenACCCombinedConstruct>( 272 sourced(Parser<AccBeginCombinedDirective>{} / endAccLine), 273 maybe(Parser<DoConstruct>{}), 274 maybe(Parser<AccEndCombinedDirective>{} / endAccLine))) 275 276 } // namespace Fortran::parser 277