1 | //===- OpenACCClause.h - Classes for OpenACC clauses ------------*- C++ -*-===// |
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 | // \file |
10 | // This file defines OpenACC AST classes for clauses. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_CLANG_AST_OPENACCCLAUSE_H |
15 | #define LLVM_CLANG_AST_OPENACCCLAUSE_H |
16 | #include "clang/AST/ASTContext.h" |
17 | #include "clang/AST/StmtIterator.h" |
18 | #include "clang/Basic/OpenACCKinds.h" |
19 | |
20 | namespace clang { |
21 | /// This is the base type for all OpenACC Clauses. |
22 | class OpenACCClause { |
23 | OpenACCClauseKind Kind; |
24 | SourceRange Location; |
25 | |
26 | protected: |
27 | OpenACCClause(OpenACCClauseKind K, SourceLocation BeginLoc, |
28 | SourceLocation EndLoc) |
29 | : Kind(K), Location(BeginLoc, EndLoc) {} |
30 | |
31 | public: |
32 | OpenACCClauseKind getClauseKind() const { return Kind; } |
33 | SourceLocation getBeginLoc() const { return Location.getBegin(); } |
34 | SourceLocation getEndLoc() const { return Location.getEnd(); } |
35 | |
36 | static bool classof(const OpenACCClause *) { return true; } |
37 | |
38 | using child_iterator = StmtIterator; |
39 | using const_child_iterator = ConstStmtIterator; |
40 | using child_range = llvm::iterator_range<child_iterator>; |
41 | using const_child_range = llvm::iterator_range<const_child_iterator>; |
42 | |
43 | child_range children(); |
44 | const_child_range children() const { |
45 | auto Children = const_cast<OpenACCClause *>(this)->children(); |
46 | return const_child_range(Children.begin(), Children.end()); |
47 | } |
48 | |
49 | virtual ~OpenACCClause() = default; |
50 | }; |
51 | |
52 | /// Represents a clause that has a list of parameters. |
53 | class OpenACCClauseWithParams : public OpenACCClause { |
54 | /// Location of the '('. |
55 | SourceLocation LParenLoc; |
56 | |
57 | protected: |
58 | OpenACCClauseWithParams(OpenACCClauseKind K, SourceLocation BeginLoc, |
59 | SourceLocation LParenLoc, SourceLocation EndLoc) |
60 | : OpenACCClause(K, BeginLoc, EndLoc), LParenLoc(LParenLoc) {} |
61 | |
62 | public: |
63 | SourceLocation getLParenLoc() const { return LParenLoc; } |
64 | |
65 | child_range children() { |
66 | return child_range(child_iterator(), child_iterator()); |
67 | } |
68 | const_child_range children() const { |
69 | return const_child_range(const_child_iterator(), const_child_iterator()); |
70 | } |
71 | }; |
72 | |
73 | /// A 'default' clause, has the optional 'none' or 'present' argument. |
74 | class OpenACCDefaultClause : public OpenACCClauseWithParams { |
75 | friend class ASTReaderStmt; |
76 | friend class ASTWriterStmt; |
77 | |
78 | OpenACCDefaultClauseKind DefaultClauseKind; |
79 | |
80 | protected: |
81 | OpenACCDefaultClause(OpenACCDefaultClauseKind K, SourceLocation BeginLoc, |
82 | SourceLocation LParenLoc, SourceLocation EndLoc) |
83 | : OpenACCClauseWithParams(OpenACCClauseKind::Default, BeginLoc, LParenLoc, |
84 | EndLoc), |
85 | DefaultClauseKind(K) { |
86 | assert((DefaultClauseKind == OpenACCDefaultClauseKind::None || |
87 | DefaultClauseKind == OpenACCDefaultClauseKind::Present) && |
88 | "Invalid Clause Kind" ); |
89 | } |
90 | |
91 | public: |
92 | OpenACCDefaultClauseKind getDefaultClauseKind() const { |
93 | return DefaultClauseKind; |
94 | } |
95 | |
96 | static OpenACCDefaultClause *Create(const ASTContext &C, |
97 | OpenACCDefaultClauseKind K, |
98 | SourceLocation BeginLoc, |
99 | SourceLocation LParenLoc, |
100 | SourceLocation EndLoc); |
101 | }; |
102 | |
103 | /// Represents one of the handful of classes that has an optional/required |
104 | /// 'condition' expression as an argument. |
105 | class OpenACCClauseWithCondition : public OpenACCClauseWithParams { |
106 | Expr *ConditionExpr = nullptr; |
107 | |
108 | protected: |
109 | OpenACCClauseWithCondition(OpenACCClauseKind K, SourceLocation BeginLoc, |
110 | SourceLocation LParenLoc, Expr *ConditionExpr, |
111 | SourceLocation EndLoc) |
112 | : OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc), |
113 | ConditionExpr(ConditionExpr) {} |
114 | |
115 | public: |
116 | bool hasConditionExpr() const { return ConditionExpr; } |
117 | const Expr *getConditionExpr() const { return ConditionExpr; } |
118 | Expr *getConditionExpr() { return ConditionExpr; } |
119 | |
120 | child_range children() { |
121 | if (ConditionExpr) |
122 | return child_range(reinterpret_cast<Stmt **>(&ConditionExpr), |
123 | reinterpret_cast<Stmt **>(&ConditionExpr + 1)); |
124 | return child_range(child_iterator(), child_iterator()); |
125 | } |
126 | |
127 | const_child_range children() const { |
128 | if (ConditionExpr) |
129 | return const_child_range( |
130 | reinterpret_cast<Stmt *const *>(&ConditionExpr), |
131 | reinterpret_cast<Stmt *const *>(&ConditionExpr + 1)); |
132 | return const_child_range(const_child_iterator(), const_child_iterator()); |
133 | } |
134 | }; |
135 | |
136 | /// An 'if' clause, which has a required condition expression. |
137 | class OpenACCIfClause : public OpenACCClauseWithCondition { |
138 | protected: |
139 | OpenACCIfClause(SourceLocation BeginLoc, SourceLocation LParenLoc, |
140 | Expr *ConditionExpr, SourceLocation EndLoc); |
141 | |
142 | public: |
143 | static OpenACCIfClause *Create(const ASTContext &C, SourceLocation BeginLoc, |
144 | SourceLocation LParenLoc, Expr *ConditionExpr, |
145 | SourceLocation EndLoc); |
146 | }; |
147 | |
148 | /// A 'self' clause, which has an optional condition expression. |
149 | class OpenACCSelfClause : public OpenACCClauseWithCondition { |
150 | OpenACCSelfClause(SourceLocation BeginLoc, SourceLocation LParenLoc, |
151 | Expr *ConditionExpr, SourceLocation EndLoc); |
152 | |
153 | public: |
154 | static OpenACCSelfClause *Create(const ASTContext &C, SourceLocation BeginLoc, |
155 | SourceLocation LParenLoc, |
156 | Expr *ConditionExpr, SourceLocation EndLoc); |
157 | }; |
158 | |
159 | /// Represents a clause that has one or more IntExprs. It does not own the |
160 | /// IntExprs, but provides 'children' and other accessors. |
161 | class OpenACCClauseWithIntExprs : public OpenACCClauseWithParams { |
162 | MutableArrayRef<Expr *> IntExprs; |
163 | |
164 | protected: |
165 | OpenACCClauseWithIntExprs(OpenACCClauseKind K, SourceLocation BeginLoc, |
166 | SourceLocation LParenLoc, SourceLocation EndLoc) |
167 | : OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc) {} |
168 | |
169 | /// Used only for initialization, the leaf class can initialize this to |
170 | /// trailing storage. |
171 | void setIntExprs(MutableArrayRef<Expr *> NewIntExprs) { |
172 | assert(IntExprs.empty() && "Cannot change IntExprs list" ); |
173 | IntExprs = NewIntExprs; |
174 | } |
175 | |
176 | /// Gets the entire list of integer expressions, but leave it to the |
177 | /// individual clauses to expose this how they'd like. |
178 | llvm::ArrayRef<Expr *> getIntExprs() const { return IntExprs; } |
179 | |
180 | public: |
181 | child_range children() { |
182 | return child_range(reinterpret_cast<Stmt **>(IntExprs.begin()), |
183 | reinterpret_cast<Stmt **>(IntExprs.end())); |
184 | } |
185 | |
186 | const_child_range children() const { |
187 | child_range Children = |
188 | const_cast<OpenACCClauseWithIntExprs *>(this)->children(); |
189 | return const_child_range(Children.begin(), Children.end()); |
190 | } |
191 | }; |
192 | |
193 | class OpenACCNumGangsClause final |
194 | : public OpenACCClauseWithIntExprs, |
195 | public llvm::TrailingObjects<OpenACCNumGangsClause, Expr *> { |
196 | |
197 | OpenACCNumGangsClause(SourceLocation BeginLoc, SourceLocation LParenLoc, |
198 | ArrayRef<Expr *> IntExprs, SourceLocation EndLoc) |
199 | : OpenACCClauseWithIntExprs(OpenACCClauseKind::NumGangs, BeginLoc, |
200 | LParenLoc, EndLoc) { |
201 | std::uninitialized_copy(first: IntExprs.begin(), last: IntExprs.end(), |
202 | result: getTrailingObjects<Expr *>()); |
203 | setIntExprs(MutableArrayRef(getTrailingObjects<Expr *>(), IntExprs.size())); |
204 | } |
205 | |
206 | public: |
207 | static OpenACCNumGangsClause * |
208 | Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, |
209 | ArrayRef<Expr *> IntExprs, SourceLocation EndLoc); |
210 | |
211 | llvm::ArrayRef<Expr *> getIntExprs() { |
212 | return OpenACCClauseWithIntExprs::getIntExprs(); |
213 | } |
214 | |
215 | llvm::ArrayRef<Expr *> getIntExprs() const { |
216 | return OpenACCClauseWithIntExprs::getIntExprs(); |
217 | } |
218 | }; |
219 | |
220 | /// Represents one of a handful of clauses that have a single integer |
221 | /// expression. |
222 | class OpenACCClauseWithSingleIntExpr : public OpenACCClauseWithIntExprs { |
223 | Expr *IntExpr; |
224 | |
225 | protected: |
226 | OpenACCClauseWithSingleIntExpr(OpenACCClauseKind K, SourceLocation BeginLoc, |
227 | SourceLocation LParenLoc, Expr *IntExpr, |
228 | SourceLocation EndLoc) |
229 | : OpenACCClauseWithIntExprs(K, BeginLoc, LParenLoc, EndLoc), |
230 | IntExpr(IntExpr) { |
231 | setIntExprs(MutableArrayRef<Expr *>{&this->IntExpr, 1}); |
232 | } |
233 | |
234 | public: |
235 | bool hasIntExpr() const { return !getIntExprs().empty(); } |
236 | const Expr *getIntExpr() const { |
237 | return hasIntExpr() ? getIntExprs()[0] : nullptr; |
238 | } |
239 | |
240 | Expr *getIntExpr() { return hasIntExpr() ? getIntExprs()[0] : nullptr; }; |
241 | }; |
242 | |
243 | class OpenACCNumWorkersClause : public OpenACCClauseWithSingleIntExpr { |
244 | OpenACCNumWorkersClause(SourceLocation BeginLoc, SourceLocation LParenLoc, |
245 | Expr *IntExpr, SourceLocation EndLoc); |
246 | |
247 | public: |
248 | static OpenACCNumWorkersClause *Create(const ASTContext &C, |
249 | SourceLocation BeginLoc, |
250 | SourceLocation LParenLoc, |
251 | Expr *IntExpr, SourceLocation EndLoc); |
252 | }; |
253 | |
254 | class OpenACCVectorLengthClause : public OpenACCClauseWithSingleIntExpr { |
255 | OpenACCVectorLengthClause(SourceLocation BeginLoc, SourceLocation LParenLoc, |
256 | Expr *IntExpr, SourceLocation EndLoc); |
257 | |
258 | public: |
259 | static OpenACCVectorLengthClause * |
260 | Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, |
261 | Expr *IntExpr, SourceLocation EndLoc); |
262 | }; |
263 | |
264 | template <class Impl> class OpenACCClauseVisitor { |
265 | Impl &getDerived() { return static_cast<Impl &>(*this); } |
266 | |
267 | public: |
268 | void VisitClauseList(ArrayRef<const OpenACCClause *> List) { |
269 | for (const OpenACCClause *Clause : List) |
270 | Visit(C: Clause); |
271 | } |
272 | |
273 | void Visit(const OpenACCClause *C) { |
274 | if (!C) |
275 | return; |
276 | |
277 | switch (C->getClauseKind()) { |
278 | #define VISIT_CLAUSE(CLAUSE_NAME) \ |
279 | case OpenACCClauseKind::CLAUSE_NAME: \ |
280 | Visit##CLAUSE_NAME##Clause(*cast<OpenACC##CLAUSE_NAME##Clause>(C)); \ |
281 | return; |
282 | #include "clang/Basic/OpenACCClauses.def" |
283 | |
284 | default: |
285 | llvm_unreachable("Clause visitor not yet implemented" ); |
286 | } |
287 | llvm_unreachable("Invalid Clause kind" ); |
288 | } |
289 | |
290 | #define VISIT_CLAUSE(CLAUSE_NAME) \ |
291 | void Visit##CLAUSE_NAME##Clause( \ |
292 | const OpenACC##CLAUSE_NAME##Clause &Clause) { \ |
293 | return getDerived().Visit##CLAUSE_NAME##Clause(Clause); \ |
294 | } |
295 | |
296 | #include "clang/Basic/OpenACCClauses.def" |
297 | }; |
298 | |
299 | class OpenACCClausePrinter final |
300 | : public OpenACCClauseVisitor<OpenACCClausePrinter> { |
301 | raw_ostream &OS; |
302 | |
303 | public: |
304 | void VisitClauseList(ArrayRef<const OpenACCClause *> List) { |
305 | for (const OpenACCClause *Clause : List) { |
306 | Visit(C: Clause); |
307 | |
308 | if (Clause != List.back()) |
309 | OS << ' '; |
310 | } |
311 | } |
312 | OpenACCClausePrinter(raw_ostream &OS) : OS(OS) {} |
313 | |
314 | #define VISIT_CLAUSE(CLAUSE_NAME) \ |
315 | void Visit##CLAUSE_NAME##Clause(const OpenACC##CLAUSE_NAME##Clause &Clause); |
316 | #include "clang/Basic/OpenACCClauses.def" |
317 | }; |
318 | |
319 | } // namespace clang |
320 | |
321 | #endif // LLVM_CLANG_AST_OPENACCCLAUSE_H |
322 | |