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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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