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
20namespace Fortran::parser {
21
22constexpr auto startAccLine = skipStuffBeforeStatement >>
23 ("!$ACC "_sptok || "C$ACC "_sptok || "*$ACC "_sptok);
24constexpr 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
33TYPE_PARSER(
34 construct<AccObject>(designator) || construct<AccObject>("/" >> name / "/"))
35
36TYPE_PARSER(construct<AccObjectList>(nonemptyList(Parser<AccObject>{})))
37
38TYPE_PARSER(construct<AccObjectListWithModifier>(
39 maybe(Parser<AccDataModifier>{}), Parser<AccObjectList>{}))
40
41TYPE_PARSER(construct<AccObjectListWithReduction>(
42 Parser<AccReductionOperator>{} / ":", Parser<AccObjectList>{}))
43
44// 2.16 (3249) wait-argument is:
45// [devnum : int-expr :] [queues :] int-expr-list
46TYPE_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
52TYPE_PARSER(construct<AccSizeExpr>(scalarIntExpr) ||
53 construct<AccSizeExpr>("*" >> construct<std::optional<ScalarIntExpr>>()))
54TYPE_PARSER(construct<AccSizeExprList>(nonemptyList(Parser<AccSizeExpr>{})))
55
56TYPE_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
65TYPE_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
71TYPE_PARSER(construct<AccTileExpr>(scalarIntConstantExpr) ||
72 construct<AccTileExpr>(
73 "*" >> construct<std::optional<ScalarIntConstantExpr>>()))
74TYPE_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
80TYPE_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
88TYPE_PARSER(
89 construct<AccGangArgList>(many(maybe(","_tok) >> Parser<AccGangArg>{})))
90
91// 2.9.1 collapse
92TYPE_PARSER(construct<AccCollapseArg>(
93 "FORCE:"_tok >> pure(true) || pure(false), scalarIntConstantExpr))
94
95// 2.5.15 Reduction
96// Operator for reduction
97TYPE_PARSER(sourced(construct<AccReductionOperator>(
98 first("+" >> pure(AccReductionOperator::Operator::Plus),
99 "*" >> pure(AccReductionOperator::Operator::Multiply),
100 "MAX" >> pure(AccReductionOperator::Operator::Max),
101 "MIN" >> pure(AccReductionOperator::Operator::Min),
102 "IAND" >> pure(AccReductionOperator::Operator::Iand),
103 "IOR" >> pure(AccReductionOperator::Operator::Ior),
104 "IEOR" >> pure(AccReductionOperator::Operator::Ieor),
105 ".AND." >> pure(AccReductionOperator::Operator::And),
106 ".OR." >> pure(AccReductionOperator::Operator::Or),
107 ".EQV." >> pure(AccReductionOperator::Operator::Eqv),
108 ".NEQV." >> pure(AccReductionOperator::Operator::Neqv)))))
109
110// 2.15.1 Bind clause
111TYPE_PARSER(sourced(construct<AccBindClause>(name)) ||
112 sourced(construct<AccBindClause>(scalarDefaultCharExpr)))
113
114// 2.5.16 Default clause
115TYPE_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.
122TYPE_PARSER(construct<AccSelfClause>(Parser<AccObjectList>{}) ||
123 construct<AccSelfClause>(scalarLogicalExpr))
124
125// Modifier for copyin, copyout, cache and create
126TYPE_PARSER(construct<AccDataModifier>(
127 first("ZERO:" >> pure(AccDataModifier::Modifier::Zero),
128 "READONLY:" >> pure(AccDataModifier::Modifier::ReadOnly))))
129
130// Combined directives
131TYPE_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
137TYPE_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
145TYPE_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
154TYPE_PARSER(sourced(construct<AccLoopDirective>(
155 first("LOOP" >> pure(llvm::acc::Directive::ACCD_loop)))))
156
157TYPE_PARSER(construct<AccBeginLoopDirective>(
158 sourced(Parser<AccLoopDirective>{}), Parser<AccClauseList>{}))
159
160TYPE_PARSER(construct<AccEndLoop>("END LOOP"_tok))
161
162TYPE_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
168TYPE_PARSER(sourced(construct<OpenACCRoutineConstruct>(verbatim("ROUTINE"_tok),
169 maybe(parenthesized(name)), Parser<AccClauseList>{})))
170
171// 2.10 Cache directive
172TYPE_PARSER(sourced(
173 construct<OpenACCCacheConstruct>(sourced(construct<Verbatim>("CACHE"_tok)),
174 parenthesized(Parser<AccObjectListWithModifier>{}))))
175
176// 2.11 Combined constructs
177TYPE_PARSER(construct<AccBeginCombinedDirective>(
178 sourced(Parser<AccCombinedDirective>{}), Parser<AccClauseList>{}))
179
180// 2.12 Atomic constructs
181TYPE_PARSER(construct<AccEndAtomic>(startAccLine >> "END ATOMIC"_tok))
182
183TYPE_PARSER("ATOMIC" >>
184 construct<AccAtomicRead>(verbatim("READ"_tok) / endAccLine,
185 statement(assignmentStmt), maybe(Parser<AccEndAtomic>{} / endAccLine)))
186
187TYPE_PARSER("ATOMIC" >>
188 construct<AccAtomicWrite>(verbatim("WRITE"_tok) / endAccLine,
189 statement(assignmentStmt), maybe(Parser<AccEndAtomic>{} / endAccLine)))
190
191TYPE_PARSER("ATOMIC" >>
192 construct<AccAtomicUpdate>(maybe(verbatim("UPDATE"_tok)) / endAccLine,
193 statement(assignmentStmt), maybe(Parser<AccEndAtomic>{} / endAccLine)))
194
195TYPE_PARSER("ATOMIC" >>
196 construct<AccAtomicCapture>(verbatim("CAPTURE"_tok) / endAccLine,
197 statement(assignmentStmt), statement(assignmentStmt),
198 Parser<AccEndAtomic>{} / endAccLine))
199
200TYPE_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
207TYPE_PARSER(sourced(construct<AccDeclarativeDirective>(
208 first("DECLARE" >> pure(llvm::acc::Directive::ACCD_declare)))))
209
210// [Clause, [Clause], ...]
211TYPE_PARSER(sourced(construct<AccClauseList>(
212 many(maybe(","_tok) >> sourced(Parser<AccClause>{})))))
213
214// 2.16.3 Wait directive
215TYPE_PARSER(sourced(construct<OpenACCWaitConstruct>(
216 sourced(construct<Verbatim>("WAIT"_tok)),
217 maybe(parenthesized(Parser<AccWaitArgument>{})), Parser<AccClauseList>{})))
218
219// Block Constructs
220TYPE_PARSER(sourced(construct<AccBeginBlockDirective>(
221 sourced(Parser<AccBlockDirective>{}), Parser<AccClauseList>{})))
222
223TYPE_PARSER(startAccLine >> sourced(construct<AccEndBlockDirective>("END"_tok >>
224 sourced(Parser<AccBlockDirective>{}))))
225
226TYPE_PARSER(construct<OpenACCBlockConstruct>(
227 Parser<AccBeginBlockDirective>{} / endAccLine, block,
228 Parser<AccEndBlockDirective>{} / endAccLine))
229
230// Standalone constructs
231TYPE_PARSER(construct<OpenACCStandaloneConstruct>(
232 sourced(Parser<AccStandaloneDirective>{}), Parser<AccClauseList>{}))
233
234// Standalone declarative constructs
235TYPE_PARSER(construct<OpenACCStandaloneDeclarativeConstruct>(
236 sourced(Parser<AccDeclarativeDirective>{}), Parser<AccClauseList>{}))
237
238TYPE_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
245TYPE_PARSER(sourced(construct<OpenACCEndConstruct>(
246 "END"_tok >> "LOOP"_tok >> pure(llvm::acc::Directive::ACCD_loop))))
247
248// OpenACC constructs
249TYPE_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
262TYPE_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
271TYPE_PARSER(construct<OpenACCCombinedConstruct>(
272 sourced(Parser<AccBeginCombinedDirective>{} / endAccLine),
273 maybe(Parser<DoConstruct>{}),
274 maybe(Parser<AccEndCombinedDirective>{} / endAccLine)))
275
276} // namespace Fortran::parser
277

source code of flang/lib/Parser/openacc-parsers.cpp