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<AccReductionOperator>{} / ":" , 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 |
96 | // Operator for reduction |
97 | TYPE_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 |
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 | |