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