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 // Autogenerated clauses parser. Information is taken from ACC.td and the
26 // parser is generated by tablegen.
27 // Scalar value parsers are provided by Flang directly. Specific value parsers
28 // are provided below.
29 #define GEN_FLANG_CLAUSES_PARSER
30 #include "llvm/Frontend/OpenACC/ACC.inc"
31 
32 TYPE_PARSER(
33     construct<AccObject>(designator) || construct<AccObject>("/" >> name / "/"))
34 
35 TYPE_PARSER(construct<AccObjectList>(nonemptyList(Parser<AccObject>{})))
36 
37 TYPE_PARSER(construct<AccObjectListWithModifier>(
38     maybe(Parser<AccDataModifier>{}), Parser<AccObjectList>{}))
39 
40 TYPE_PARSER(construct<AccObjectListWithReduction>(
41     Parser<AccReductionOperator>{} / ":", Parser<AccObjectList>{}))
42 
43 // 2.16.3 (2485) wait-argument is:
44 //   [devnum : int-expr :] [queues :] int-expr-list
45 TYPE_PARSER(construct<AccWaitArgument>(maybe("DEVNUM:" >> scalarIntExpr / ":"),
46     "QUEUES:" >> nonemptyList(scalarIntExpr) || nonemptyList(scalarIntExpr)))
47 
48 // 2.9 (1609) size-expr is one of:
49 //   * (represented as an empty std::optional<ScalarIntExpr>)
50 //   int-expr
51 TYPE_PARSER(construct<AccSizeExpr>(scalarIntExpr) ||
52     construct<AccSizeExpr>("*" >> construct<std::optional<ScalarIntExpr>>()))
53 TYPE_PARSER(construct<AccSizeExprList>(nonemptyList(Parser<AccSizeExpr>{})))
54 
55 TYPE_PARSER(construct<AccDeviceTypeExpr>(scalarIntExpr) ||
56     construct<AccDeviceTypeExpr>(
57         "*" >> construct<std::optional<ScalarIntExpr>>()))
58 TYPE_PARSER(
59     construct<AccDeviceTypeExprList>(nonemptyList(Parser<AccDeviceTypeExpr>{})))
60 
61 // tile size is one of:
62 //   * (represented as an empty std::optional<ScalarIntExpr>)
63 //   constant-int-expr
64 TYPE_PARSER(construct<AccTileExpr>(scalarIntConstantExpr) ||
65     construct<AccTileExpr>(
66         "*" >> construct<std::optional<ScalarIntConstantExpr>>()))
67 TYPE_PARSER(construct<AccTileExprList>(nonemptyList(Parser<AccTileExpr>{})))
68 
69 // 2.9 (1607) gang-arg is:
70 //   [[num:]int-expr][[,]static:size-expr]
71 TYPE_PARSER(construct<AccGangArgument>(
72     maybe(("NUM:"_tok >> scalarIntExpr || scalarIntExpr)),
73     maybe(", STATIC:" >> Parser<AccSizeExpr>{})))
74 
75 // 2.5.13 Reduction
76 // Operator for reduction
77 TYPE_PARSER(sourced(construct<AccReductionOperator>(
78     first("+" >> pure(AccReductionOperator::Operator::Plus),
79         "*" >> pure(AccReductionOperator::Operator::Multiply),
80         "MAX" >> pure(AccReductionOperator::Operator::Max),
81         "MIN" >> pure(AccReductionOperator::Operator::Min),
82         "IAND" >> pure(AccReductionOperator::Operator::Iand),
83         "IOR" >> pure(AccReductionOperator::Operator::Ior),
84         "IEOR" >> pure(AccReductionOperator::Operator::Ieor),
85         ".AND." >> pure(AccReductionOperator::Operator::And),
86         ".OR." >> pure(AccReductionOperator::Operator::Or),
87         ".EQV." >> pure(AccReductionOperator::Operator::Eqv),
88         ".NEQV." >> pure(AccReductionOperator::Operator::Neqv)))))
89 
90 // 2.15.1 Bind clause
91 TYPE_PARSER(sourced(construct<AccBindClause>(name)) ||
92     sourced(construct<AccBindClause>(scalarDefaultCharExpr)))
93 
94 // 2.5.14 Default clause
95 TYPE_PARSER(construct<AccDefaultClause>(
96     first("NONE" >> pure(llvm::acc::DefaultValue::ACC_Default_none),
97         "PRESENT" >> pure(llvm::acc::DefaultValue::ACC_Default_present))))
98 
99 // SELF clause is either a simple optional condition for compute construct
100 // or a synonym of the HOST clause for the update directive 2.14.4 holding
101 // an object list.
102 TYPE_PARSER(construct<AccSelfClause>(Parser<AccObjectList>{}) ||
103     construct<AccSelfClause>(scalarLogicalExpr))
104 
105 // Modifier for copyin, copyout, cache and create
106 TYPE_PARSER(construct<AccDataModifier>(
107     first("ZERO:" >> pure(AccDataModifier::Modifier::Zero),
108         "READONLY:" >> pure(AccDataModifier::Modifier::ReadOnly))))
109 
110 // Combined directives
111 TYPE_PARSER(sourced(construct<AccCombinedDirective>(
112     first("KERNELS LOOP" >> pure(llvm::acc::Directive::ACCD_kernels_loop),
113         "PARALLEL LOOP" >> pure(llvm::acc::Directive::ACCD_parallel_loop),
114         "SERIAL LOOP" >> pure(llvm::acc::Directive::ACCD_serial_loop)))))
115 
116 // Block directives
117 TYPE_PARSER(sourced(construct<AccBlockDirective>(
118     first("DATA" >> pure(llvm::acc::Directive::ACCD_data),
119         "HOST_DATA" >> pure(llvm::acc::Directive::ACCD_host_data),
120         "KERNELS" >> pure(llvm::acc::Directive::ACCD_kernels),
121         "PARALLEL" >> pure(llvm::acc::Directive::ACCD_parallel),
122         "SERIAL" >> pure(llvm::acc::Directive::ACCD_serial)))))
123 
124 // Standalone directives
125 TYPE_PARSER(sourced(construct<AccStandaloneDirective>(
126     first("ENTER DATA" >> pure(llvm::acc::Directive::ACCD_enter_data),
127         "EXIT DATA" >> pure(llvm::acc::Directive::ACCD_exit_data),
128         "INIT" >> pure(llvm::acc::Directive::ACCD_init),
129         "SHUTDOWN" >> pure(llvm::acc::Directive::ACCD_shutdown),
130         "SET" >> pure(llvm::acc::Directive::ACCD_set),
131         "UPDATE" >> pure(llvm::acc::Directive::ACCD_update)))))
132 
133 // Loop directives
134 TYPE_PARSER(sourced(construct<AccLoopDirective>(
135     first("LOOP" >> pure(llvm::acc::Directive::ACCD_loop)))))
136 
137 TYPE_PARSER(construct<AccBeginLoopDirective>(
138     sourced(Parser<AccLoopDirective>{}), Parser<AccClauseList>{}))
139 
140 TYPE_PARSER(
141     construct<OpenACCLoopConstruct>(sourced(Parser<AccBeginLoopDirective>{})))
142 
143 // 2.15.1 Routine directive
144 TYPE_PARSER(sourced(construct<OpenACCRoutineConstruct>(verbatim("ROUTINE"_tok),
145     maybe(parenthesized(name)), Parser<AccClauseList>{})))
146 
147 // 2.10 Cache directive
148 TYPE_PARSER(sourced(
149     construct<OpenACCCacheConstruct>(sourced(construct<Verbatim>("CACHE"_tok)),
150         parenthesized(Parser<AccObjectListWithModifier>{}))))
151 
152 // 2.11 Combined constructs
153 TYPE_PARSER(construct<AccBeginCombinedDirective>(
154     sourced(Parser<AccCombinedDirective>{}), Parser<AccClauseList>{}))
155 
156 // 2.12 Atomic constructs
157 TYPE_PARSER(construct<AccEndAtomic>(startAccLine >> "END ATOMIC"_tok))
158 
159 TYPE_PARSER("ATOMIC" >>
160     construct<AccAtomicRead>(verbatim("READ"_tok) / endAccLine,
161         statement(assignmentStmt), maybe(Parser<AccEndAtomic>{} / endAccLine)))
162 
163 TYPE_PARSER("ATOMIC" >>
164     construct<AccAtomicWrite>(verbatim("WRITE"_tok) / endAccLine,
165         statement(assignmentStmt), maybe(Parser<AccEndAtomic>{} / endAccLine)))
166 
167 TYPE_PARSER("ATOMIC" >>
168     construct<AccAtomicUpdate>(maybe(verbatim("UPDATE"_tok)) / endAccLine,
169         statement(assignmentStmt), maybe(Parser<AccEndAtomic>{} / endAccLine)))
170 
171 TYPE_PARSER("ATOMIC" >>
172     construct<AccAtomicCapture>(verbatim("CAPTURE"_tok) / endAccLine,
173         statement(assignmentStmt), statement(assignmentStmt),
174         Parser<AccEndAtomic>{} / endAccLine))
175 
176 TYPE_PARSER(
177     sourced(construct<OpenACCAtomicConstruct>(Parser<AccAtomicRead>{})) ||
178     sourced(construct<OpenACCAtomicConstruct>(Parser<AccAtomicCapture>{})) ||
179     sourced(construct<OpenACCAtomicConstruct>(Parser<AccAtomicWrite>{})) ||
180     sourced(construct<OpenACCAtomicConstruct>(Parser<AccAtomicUpdate>{})))
181 
182 // 2.13 Declare constructs
183 TYPE_PARSER(sourced(construct<AccDeclarativeDirective>(
184     first("DECLARE" >> pure(llvm::acc::Directive::ACCD_declare)))))
185 
186 // [Clause, [Clause], ...]
187 TYPE_PARSER(sourced(construct<AccClauseList>(
188     many(maybe(","_tok) >> sourced(Parser<AccClause>{})))))
189 
190 // 2.16.3 Wait directive
191 TYPE_PARSER(sourced(construct<OpenACCWaitConstruct>(
192     sourced(construct<Verbatim>("WAIT"_tok)),
193     maybe(parenthesized(Parser<AccWaitArgument>{})), Parser<AccClauseList>{})))
194 
195 // Block Constructs
196 TYPE_PARSER(sourced(construct<AccBeginBlockDirective>(
197     sourced(Parser<AccBlockDirective>{}), Parser<AccClauseList>{})))
198 
199 TYPE_PARSER(startAccLine >> sourced(construct<AccEndBlockDirective>("END"_tok >>
200                                 sourced(Parser<AccBlockDirective>{}))))
201 
202 TYPE_PARSER(construct<OpenACCBlockConstruct>(
203     Parser<AccBeginBlockDirective>{} / endAccLine, block,
204     Parser<AccEndBlockDirective>{} / endAccLine))
205 
206 // Standalone constructs
207 TYPE_PARSER(construct<OpenACCStandaloneConstruct>(
208     sourced(Parser<AccStandaloneDirective>{}), Parser<AccClauseList>{}))
209 
210 // Standalone declarative constructs
211 TYPE_PARSER(construct<OpenACCStandaloneDeclarativeConstruct>(
212     sourced(Parser<AccDeclarativeDirective>{}), Parser<AccClauseList>{}))
213 
214 TYPE_PARSER(
215     startAccLine >> first(sourced(construct<OpenACCDeclarativeConstruct>(
216                               Parser<OpenACCStandaloneDeclarativeConstruct>{})),
217                         sourced(construct<OpenACCDeclarativeConstruct>(
218                             Parser<OpenACCRoutineConstruct>{}))))
219 
220 // OpenACC constructs
221 TYPE_CONTEXT_PARSER("OpenACC construct"_en_US,
222     startAccLine >>
223         first(construct<OpenACCConstruct>(Parser<OpenACCBlockConstruct>{}),
224             construct<OpenACCConstruct>(Parser<OpenACCCombinedConstruct>{}),
225             construct<OpenACCConstruct>(Parser<OpenACCLoopConstruct>{}),
226             construct<OpenACCConstruct>(Parser<OpenACCStandaloneConstruct>{}),
227             construct<OpenACCConstruct>(Parser<OpenACCCacheConstruct>{}),
228             construct<OpenACCConstruct>(Parser<OpenACCWaitConstruct>{}),
229             construct<OpenACCConstruct>(Parser<OpenACCAtomicConstruct>{})))
230 
231 TYPE_PARSER(startAccLine >> sourced(construct<AccEndCombinedDirective>(sourced(
232                                 "END"_tok >> Parser<AccCombinedDirective>{}))))
233 
234 TYPE_PARSER(construct<OpenACCCombinedConstruct>(
235     sourced(Parser<AccBeginCombinedDirective>{} / endAccLine)))
236 
237 } // namespace Fortran::parser
238