xref: /llvm-project/flang/lib/Parser/openacc-parsers.cpp (revision 3af717d661e9fe8d562181b933a373ca58e41b27)
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