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.0.
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" >>
32         construct<AccClause>(construct<AccClause::Bind>(parenthesized(name))) ||
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     "DEVICENUM" >> construct<AccClause>(construct<AccClause::DeviceNum>(
61                        parenthesized(scalarIntConstantExpr))) ||
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>(parenthesized(
67             "*" >> construct<std::optional<std::list<Name>>>()))) ||
68     ("DEVICE_TYPE"_tok || "DTYPE"_tok) >>
69         construct<AccClause>(construct<AccClause::DeviceType>(
70             parenthesized(maybe(nonemptyList(name))))) ||
71     "FINALIZE" >> construct<AccClause>(construct<AccClause::Finalize>()) ||
72     "FIRSTPRIVATE" >> construct<AccClause>(construct<AccClause::Firstprivate>(
73                           parenthesized(Parser<AccObjectList>{}))) ||
74     "GANG" >> construct<AccClause>(construct<AccClause::Gang>(
75                   maybe(parenthesized(Parser<AccGangArgument>{})))) ||
76     "HOST" >> construct<AccClause>(construct<AccClause::Host>(
77                   parenthesized(Parser<AccObjectList>{}))) ||
78     "IF" >> construct<AccClause>(
79                 construct<AccClause::If>(parenthesized(scalarLogicalExpr))) ||
80     "IF_PRESENT" >> construct<AccClause>(construct<AccClause::IfPresent>()) ||
81     "INDEPENDENT" >>
82         construct<AccClause>(construct<AccClause::Independent>()) ||
83     "LINK" >> construct<AccClause>(construct<AccClause::Link>(
84                   parenthesized(Parser<AccObjectList>{}))) ||
85     "NO_CREATE" >> construct<AccClause>(construct<AccClause::NoCreate>(
86                        parenthesized(Parser<AccObjectList>{}))) ||
87     "NOHOST" >> construct<AccClause>(construct<AccClause::Nohost>()) ||
88     "NUM_GANGS" >> construct<AccClause>(construct<AccClause::NumGangs>(
89                        parenthesized(scalarIntExpr))) ||
90     "NUM_WORKERS" >> construct<AccClause>(construct<AccClause::NumWorkers>(
91                          parenthesized(scalarIntExpr))) ||
92     "PRESENT" >> construct<AccClause>(construct<AccClause::Present>(
93                      parenthesized(Parser<AccObjectList>{}))) ||
94     "PRIVATE" >> construct<AccClause>(construct<AccClause::Private>(
95                      parenthesized(Parser<AccObjectList>{}))) ||
96     "READ" >> construct<AccClause>(construct<AccClause::Read>()) ||
97     "REDUCTION" >> construct<AccClause>(construct<AccClause::Reduction>(
98                        parenthesized(construct<AccObjectListWithReduction>(
99                            Parser<AccReductionOperator>{} / ":",
100                            Parser<AccObjectList>{})))) ||
101     "SELF" >> construct<AccClause>(construct<AccClause::Self>(
102                   maybe(parenthesized(scalarLogicalExpr)))) ||
103     "SEQ" >> construct<AccClause>(construct<AccClause::Seq>()) ||
104     "TILE" >> construct<AccClause>(construct<AccClause::Tile>(
105                   parenthesized(Parser<AccSizeExprList>{}))) ||
106     "USE_DEVICE" >> construct<AccClause>(construct<AccClause::UseDevice>(
107                         parenthesized(Parser<AccObjectList>{}))) ||
108     "VECTOR_LENGTH" >> construct<AccClause>(construct<AccClause::VectorLength>(
109                            parenthesized(scalarIntExpr))) ||
110     "VECTOR" >>
111         construct<AccClause>(construct<AccClause::Vector>(maybe(
112             parenthesized(("LENGTH:" >> scalarIntExpr || scalarIntExpr))))) ||
113     "WAIT" >> construct<AccClause>(construct<AccClause::Wait>(
114                   maybe(parenthesized(Parser<AccWaitArgument>{})))) ||
115     "WORKER" >>
116         construct<AccClause>(construct<AccClause::Worker>(maybe(
117             parenthesized(("NUM:" >> scalarIntExpr || scalarIntExpr))))) ||
118     "WRITE" >> construct<AccClause>(construct<AccClause::Auto>()))
119 
120 TYPE_PARSER(
121     construct<AccObject>(designator) || construct<AccObject>("/" >> name / "/"))
122 
123 TYPE_PARSER(construct<AccObjectList>(nonemptyList(Parser<AccObject>{})))
124 
125 TYPE_PARSER(construct<AccObjectListWithModifier>(
126     maybe(Parser<AccDataModifier>{}), Parser<AccObjectList>{}))
127 
128 // 2.16.3 (2485) wait-argument is:
129 //   [devnum : int-expr :] [queues :] int-expr-list
130 TYPE_PARSER(construct<AccWaitArgument>(maybe("DEVNUM:" >> scalarIntExpr / ":"),
131     "QUEUES:" >> nonemptyList(scalarIntExpr) || nonemptyList(scalarIntExpr)))
132 
133 // 2.9 (1609) size-expr is one of:
134 //   int-expr
135 TYPE_PARSER(construct<AccSizeExpr>(scalarIntExpr) ||
136     construct<AccSizeExpr>("*" >> maybe(scalarIntExpr)))
137 TYPE_PARSER(construct<AccSizeExprList>(nonemptyList(Parser<AccSizeExpr>{})))
138 
139 // 2.9 (1607) gang-arg is one of:
140 //   [num:]int-expr
141 //   static:size-expr
142 TYPE_PARSER(construct<AccGangArgument>(maybe(scalarIntExpr),
143                 maybe(","_tok / "STATIC:" >> Parser<AccSizeExpr>{})) ||
144     construct<AccGangArgument>(maybe("NUM:" >> scalarIntExpr),
145         maybe(","_tok / "STATIC:" >> Parser<AccSizeExpr>{})))
146 
147 // 2.5.13 Reduction
148 TYPE_PARSER(construct<AccReductionOperator>(Parser<DefinedOperator>{}) ||
149     construct<AccReductionOperator>(Parser<ProcedureDesignator>{}))
150 
151 // 2.5.14 Default clause
152 TYPE_PARSER(construct<AccDefaultClause>(
153     parenthesized(first("NONE" >> pure(AccDefaultClause::Arg::None),
154         "PRESENT" >> pure(AccDefaultClause::Arg::Present)))))
155 
156 // Modifier for copyin, copyout, cache and create
157 TYPE_PARSER(construct<AccDataModifier>(
158     first("ZERO:" >> pure(AccDataModifier::Modifier::Zero),
159         "READONLY:" >> pure(AccDataModifier::Modifier::ReadOnly))))
160 
161 // Combined directives
162 TYPE_PARSER(sourced(construct<AccCombinedDirective>(
163     first("KERNELS LOOP" >> pure(llvm::acc::Directive::ACCD_kernels_loop),
164         "PARALLEL LOOP" >> pure(llvm::acc::Directive::ACCD_parallel_loop),
165         "SERIAL LOOP" >> pure(llvm::acc::Directive::ACCD_serial_loop)))))
166 
167 // Block directives
168 TYPE_PARSER(sourced(construct<AccBlockDirective>(
169     first("DATA" >> pure(llvm::acc::Directive::ACCD_data),
170         "HOST_DATA" >> pure(llvm::acc::Directive::ACCD_host_data),
171         "KERNELS" >> pure(llvm::acc::Directive::ACCD_kernels),
172         "PARALLEL" >> pure(llvm::acc::Directive::ACCD_parallel),
173         "SERIAL" >> pure(llvm::acc::Directive::ACCD_serial)))))
174 
175 // Standalone directives
176 TYPE_PARSER(sourced(construct<AccStandaloneDirective>(
177     first("ENTER DATA" >> pure(llvm::acc::Directive::ACCD_enter_data),
178         "EXIT DATA" >> pure(llvm::acc::Directive::ACCD_exit_data),
179         "INIT" >> pure(llvm::acc::Directive::ACCD_init),
180         "SHUTDOWN" >> pure(llvm::acc::Directive::ACCD_shutdown),
181         "SET" >> pure(llvm::acc::Directive::ACCD_set),
182         "UPDATE" >> pure(llvm::acc::Directive::ACCD_update)))))
183 
184 // Loop directives
185 TYPE_PARSER(sourced(construct<AccLoopDirective>(
186     first("LOOP" >> pure(llvm::acc::Directive::ACCD_loop)))))
187 
188 TYPE_PARSER(construct<AccBeginLoopDirective>(
189     sourced(Parser<AccLoopDirective>{}), Parser<AccClauseList>{}))
190 
191 TYPE_PARSER(
192     construct<OpenACCLoopConstruct>(sourced(Parser<AccBeginLoopDirective>{})))
193 
194 // 2.15.1 Routine directive
195 TYPE_PARSER(sourced(construct<OpenACCRoutineConstruct>(verbatim("ROUTINE"_tok),
196     maybe(parenthesized(name)), Parser<AccClauseList>{})))
197 
198 // 2.10 Cache directive
199 TYPE_PARSER(sourced(
200     construct<OpenACCCacheConstruct>(sourced(construct<Verbatim>("CACHE"_tok)),
201         parenthesized(Parser<AccObjectListWithModifier>{}))))
202 
203 // 2.11 Combined constructs
204 TYPE_PARSER(construct<AccBeginCombinedDirective>(
205     sourced(Parser<AccCombinedDirective>{}), Parser<AccClauseList>{}))
206 
207 // 2.12 Atomic constructs
208 TYPE_PARSER(construct<AccEndAtomic>(startAccLine >> "END ATOMIC"_tok))
209 
210 TYPE_PARSER("ATOMIC" >>
211     construct<AccAtomicRead>(verbatim("READ"_tok) / endAccLine,
212         statement(assignmentStmt), maybe(Parser<AccEndAtomic>{} / endAccLine)))
213 
214 TYPE_PARSER("ATOMIC" >>
215     construct<AccAtomicWrite>(verbatim("WRITE"_tok) / endAccLine,
216         statement(assignmentStmt), maybe(Parser<AccEndAtomic>{} / endAccLine)))
217 
218 TYPE_PARSER("ATOMIC" >>
219     construct<AccAtomicUpdate>(maybe(verbatim("UPDATE"_tok)) / endAccLine,
220         statement(assignmentStmt), maybe(Parser<AccEndAtomic>{} / endAccLine)))
221 
222 TYPE_PARSER("ATOMIC" >>
223     construct<AccAtomicCapture>(verbatim("CAPTURE"_tok) / endAccLine,
224         statement(assignmentStmt), statement(assignmentStmt),
225         Parser<AccEndAtomic>{} / endAccLine))
226 
227 TYPE_PARSER(construct<OpenACCAtomicConstruct>(Parser<AccAtomicRead>{}) ||
228     construct<OpenACCAtomicConstruct>(Parser<AccAtomicCapture>{}) ||
229     construct<OpenACCAtomicConstruct>(Parser<AccAtomicWrite>{}) ||
230     construct<OpenACCAtomicConstruct>(Parser<AccAtomicUpdate>{}))
231 
232 // 2.13 Declare constructs
233 TYPE_PARSER(sourced(construct<AccDeclarativeDirective>(
234     first("DECLARE" >> pure(llvm::acc::Directive::ACCD_declare)))))
235 
236 // [Clause, [Clause], ...]
237 TYPE_PARSER(sourced(construct<AccClauseList>(
238     many(maybe(","_tok) >> sourced(Parser<AccClause>{})))))
239 
240 // 2.16.3 Wait directive
241 TYPE_PARSER(sourced(construct<OpenACCWaitConstruct>(
242     sourced(construct<Verbatim>("WAIT"_tok)),
243     maybe(parenthesized(Parser<AccWaitArgument>{})), Parser<AccClauseList>{})))
244 
245 // Block Constructs
246 TYPE_PARSER(sourced(construct<AccBeginBlockDirective>(
247     sourced(Parser<AccBlockDirective>{}), Parser<AccClauseList>{})))
248 
249 TYPE_PARSER(startAccLine >> sourced(construct<AccEndBlockDirective>("END"_tok >>
250                                 sourced(Parser<AccBlockDirective>{}))))
251 
252 TYPE_PARSER(construct<OpenACCBlockConstruct>(
253     Parser<AccBeginBlockDirective>{} / endAccLine, block,
254     Parser<AccEndBlockDirective>{} / endAccLine))
255 
256 // Standalone constructs
257 TYPE_PARSER(construct<OpenACCStandaloneConstruct>(
258     sourced(Parser<AccStandaloneDirective>{}), Parser<AccClauseList>{}))
259 
260 // Standalone declarative constructs
261 TYPE_PARSER(construct<OpenACCStandaloneDeclarativeConstruct>(
262     sourced(Parser<AccDeclarativeDirective>{}), Parser<AccClauseList>{}))
263 
264 TYPE_PARSER(
265     startAccLine >> sourced(construct<OpenACCDeclarativeConstruct>(
266                         Parser<OpenACCStandaloneDeclarativeConstruct>{})))
267 
268 // OpenACC constructs
269 TYPE_CONTEXT_PARSER("OpenACC construct"_en_US,
270     startAccLine >>
271         first(construct<OpenACCConstruct>(Parser<OpenACCBlockConstruct>{}),
272             construct<OpenACCConstruct>(Parser<OpenACCCombinedConstruct>{}),
273             construct<OpenACCConstruct>(Parser<OpenACCLoopConstruct>{}),
274             construct<OpenACCConstruct>(Parser<OpenACCStandaloneConstruct>{}),
275             construct<OpenACCConstruct>(Parser<OpenACCRoutineConstruct>{}),
276             construct<OpenACCConstruct>(Parser<OpenACCCacheConstruct>{}),
277             construct<OpenACCConstruct>(Parser<OpenACCWaitConstruct>{}),
278             construct<OpenACCConstruct>(Parser<OpenACCAtomicConstruct>{})))
279 
280 TYPE_PARSER(startAccLine >> sourced(construct<AccEndCombinedDirective>(sourced(
281                                 "END"_tok >> Parser<AccCombinedDirective>{}))))
282 
283 TYPE_PARSER(construct<OpenACCCombinedConstruct>(
284     sourced(Parser<AccBeginCombinedDirective>{} / endAccLine)))
285 
286 } // namespace Fortran::parser
287