1 //===-- lib/Parser/openacc-parsers.cpp ------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // Top-level grammar specification for OpenACC 3.3.
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"
19 // OpenACC Directives and Clauses
20 namespace Fortran::parser
{
22 constexpr auto startAccLine
{skipStuffBeforeStatement
>>
23 ("!$ACC "_sptok
|| "C$ACC "_sptok
|| "*$ACC "_sptok
)};
24 constexpr auto endAccLine
{space
>> endOfLine
};
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"
34 construct
<AccObject
>(designator
) || construct
<AccObject
>("/" >> name
/ "/"))
36 TYPE_PARSER(construct
<AccObjectList
>(nonemptyList(Parser
<AccObject
>{})))
38 TYPE_PARSER(construct
<AccObjectListWithModifier
>(
39 maybe(Parser
<AccDataModifier
>{}), Parser
<AccObjectList
>{}))
41 TYPE_PARSER(construct
<AccObjectListWithReduction
>(
42 Parser
<ReductionOperator
>{} / ":", Parser
<AccObjectList
>{}))
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
)))
49 // 2.9 (1984-1986) size-expr is one of:
50 // * (represented as an empty std::optional<ScalarIntExpr>)
52 TYPE_PARSER(construct
<AccSizeExpr
>(scalarIntExpr
) ||
53 construct
<AccSizeExpr
>("*" >> construct
<std::optional
<ScalarIntExpr
>>()))
54 TYPE_PARSER(construct
<AccSizeExprList
>(nonemptyList(Parser
<AccSizeExpr
>{})))
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
)))))
66 construct
<AccDeviceTypeExprList
>(nonemptyList(Parser
<AccDeviceTypeExpr
>{})))
68 // tile size is one of:
69 // * (represented as an empty std::optional<ScalarIntExpr>)
71 TYPE_PARSER(construct
<AccTileExpr
>(scalarIntConstantExpr
) ||
72 construct
<AccTileExpr
>(
73 "*" >> construct
<std::optional
<ScalarIntConstantExpr
>>()))
74 TYPE_PARSER(construct
<AccTileExprList
>(nonemptyList(Parser
<AccTileExpr
>{})))
76 // 2.9 (1979-1982) gang-arg is one of :
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
)))
89 construct
<AccGangArgList
>(many(maybe(","_tok
) >> Parser
<AccGangArg
>{})))
92 TYPE_PARSER(construct
<AccCollapseArg
>(
93 "FORCE:"_tok
>> pure(true) || pure(false), scalarIntConstantExpr
))
95 // 2.5.15 Reduction, F'2023 R1131, and CUF reduction-op
96 // Operator for reduction
97 TYPE_PARSER(sourced(construct
<ReductionOperator
>(
98 first("+" >> pure(ReductionOperator::Operator::Plus
),
99 "*" >> pure(ReductionOperator::Operator::Multiply
),
100 "MAX" >> pure(ReductionOperator::Operator::Max
),
101 "MIN" >> pure(ReductionOperator::Operator::Min
),
102 "IAND" >> pure(ReductionOperator::Operator::Iand
),
103 "IOR" >> pure(ReductionOperator::Operator::Ior
),
104 "IEOR" >> pure(ReductionOperator::Operator::Ieor
),
105 ".AND." >> pure(ReductionOperator::Operator::And
),
106 ".OR." >> pure(ReductionOperator::Operator::Or
),
107 ".EQV." >> pure(ReductionOperator::Operator::Eqv
),
108 ".NEQV." >> pure(ReductionOperator::Operator::Neqv
)))))
110 // 2.15.1 Bind clause
111 TYPE_PARSER(sourced(construct
<AccBindClause
>(name
)) ||
112 sourced(construct
<AccBindClause
>(scalarDefaultCharExpr
)))
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
))))
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
122 TYPE_PARSER(construct
<AccSelfClause
>(Parser
<AccObjectList
>{}) ||
123 construct
<AccSelfClause
>(scalarLogicalExpr
))
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
))))
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
)))))
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
)))))
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
)))))
154 TYPE_PARSER(sourced(construct
<AccLoopDirective
>(
155 first("LOOP" >> pure(llvm::acc::Directive::ACCD_loop
)))))
157 TYPE_PARSER(construct
<AccBeginLoopDirective
>(
158 sourced(Parser
<AccLoopDirective
>{}), Parser
<AccClauseList
>{}))
160 TYPE_PARSER(construct
<AccEndLoop
>("END LOOP"_tok
))
162 TYPE_PARSER(construct
<OpenACCLoopConstruct
>(
163 sourced(Parser
<AccBeginLoopDirective
>{} / endAccLine
),
164 maybe(Parser
<DoConstruct
>{}),
165 maybe(startAccLine
>> Parser
<AccEndLoop
>{} / endAccLine
)))
167 // 2.15.1 Routine directive
168 TYPE_PARSER(sourced(construct
<OpenACCRoutineConstruct
>(verbatim("ROUTINE"_tok
),
169 maybe(parenthesized(name
)), Parser
<AccClauseList
>{})))
171 // 2.10 Cache directive
173 construct
<OpenACCCacheConstruct
>(sourced(construct
<Verbatim
>("CACHE"_tok
)),
174 parenthesized(Parser
<AccObjectListWithModifier
>{}))))
176 // 2.11 Combined constructs
177 TYPE_PARSER(construct
<AccBeginCombinedDirective
>(
178 sourced(Parser
<AccCombinedDirective
>{}), Parser
<AccClauseList
>{}))
180 // 2.12 Atomic constructs
181 TYPE_PARSER(construct
<AccEndAtomic
>(startAccLine
>> "END ATOMIC"_tok
))
183 TYPE_PARSER("ATOMIC" >>
184 construct
<AccAtomicRead
>(verbatim("READ"_tok
) / endAccLine
,
185 statement(assignmentStmt
), maybe(Parser
<AccEndAtomic
>{} / endAccLine
)))
187 TYPE_PARSER("ATOMIC" >>
188 construct
<AccAtomicWrite
>(verbatim("WRITE"_tok
) / endAccLine
,
189 statement(assignmentStmt
), maybe(Parser
<AccEndAtomic
>{} / endAccLine
)))
191 TYPE_PARSER("ATOMIC" >>
192 construct
<AccAtomicUpdate
>(maybe(verbatim("UPDATE"_tok
)) / endAccLine
,
193 statement(assignmentStmt
), maybe(Parser
<AccEndAtomic
>{} / endAccLine
)))
195 TYPE_PARSER("ATOMIC" >>
196 construct
<AccAtomicCapture
>(verbatim("CAPTURE"_tok
) / endAccLine
,
197 statement(assignmentStmt
), statement(assignmentStmt
),
198 Parser
<AccEndAtomic
>{} / endAccLine
))
201 sourced(construct
<OpenACCAtomicConstruct
>(Parser
<AccAtomicRead
>{})) ||
202 sourced(construct
<OpenACCAtomicConstruct
>(Parser
<AccAtomicCapture
>{})) ||
203 sourced(construct
<OpenACCAtomicConstruct
>(Parser
<AccAtomicWrite
>{})) ||
204 sourced(construct
<OpenACCAtomicConstruct
>(Parser
<AccAtomicUpdate
>{})))
206 // 2.13 Declare constructs
207 TYPE_PARSER(sourced(construct
<AccDeclarativeDirective
>(
208 first("DECLARE" >> pure(llvm::acc::Directive::ACCD_declare
)))))
210 // [Clause, [Clause], ...]
211 TYPE_PARSER(sourced(construct
<AccClauseList
>(
212 many(maybe(","_tok
) >> sourced(Parser
<AccClause
>{})))))
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
>{})))
220 TYPE_PARSER(sourced(construct
<AccBeginBlockDirective
>(
221 sourced(Parser
<AccBlockDirective
>{}), Parser
<AccClauseList
>{})))
223 TYPE_PARSER(startAccLine
>> sourced(construct
<AccEndBlockDirective
>("END"_tok
>>
224 sourced(Parser
<AccBlockDirective
>{}))))
226 TYPE_PARSER(construct
<OpenACCBlockConstruct
>(
227 Parser
<AccBeginBlockDirective
>{} / endAccLine
, block
,
228 Parser
<AccEndBlockDirective
>{} / endAccLine
))
230 // Standalone constructs
231 TYPE_PARSER(construct
<OpenACCStandaloneConstruct
>(
232 sourced(Parser
<AccStandaloneDirective
>{}), Parser
<AccClauseList
>{}))
234 // Standalone declarative constructs
235 TYPE_PARSER(construct
<OpenACCStandaloneDeclarativeConstruct
>(
236 sourced(Parser
<AccDeclarativeDirective
>{}), Parser
<AccClauseList
>{}))
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
>{})))))
245 TYPE_PARSER(sourced(construct
<OpenACCEndConstruct
>(
246 "END"_tok
>> "LOOP"_tok
>> pure(llvm::acc::Directive::ACCD_loop
))))
248 // OpenACC constructs
249 TYPE_CONTEXT_PARSER("OpenACC construct"_en_US
,
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
>{}))))
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
))))))
271 TYPE_PARSER(construct
<OpenACCCombinedConstruct
>(
272 sourced(Parser
<AccBeginCombinedDirective
>{} / endAccLine
),
273 maybe(Parser
<DoConstruct
>{}),
274 maybe(Parser
<AccEndCombinedDirective
>{} / endAccLine
)))
276 } // namespace Fortran::parser