1 | //===--- ExprOpenMP.h - Classes for representing expressions ----*- 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 | // This file defines the Expr interface and subclasses. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLVM_CLANG_AST_EXPROPENMP_H |
14 | #define LLVM_CLANG_AST_EXPROPENMP_H |
15 | |
16 | #include "clang/AST/ComputeDependence.h" |
17 | #include "clang/AST/Expr.h" |
18 | |
19 | namespace clang { |
20 | /// An explicit cast in C or a C-style cast in C++, which uses the syntax |
21 | /// ([s1][s2]...[sn])expr. For example: @c ([3][3])f. |
22 | class OMPArrayShapingExpr final |
23 | : public Expr, |
24 | private llvm::TrailingObjects<OMPArrayShapingExpr, Expr *, SourceRange> { |
25 | friend TrailingObjects; |
26 | friend class ASTStmtReader; |
27 | friend class ASTStmtWriter; |
28 | /// Base node. |
29 | SourceLocation LPLoc; /// The location of the left paren |
30 | SourceLocation RPLoc; /// The location of the right paren |
31 | unsigned NumDims = 0; /// Number of dimensions in the shaping expression. |
32 | |
33 | /// Construct full expression. |
34 | OMPArrayShapingExpr(QualType ExprTy, Expr *Op, SourceLocation L, |
35 | SourceLocation R, ArrayRef<Expr *> Dims); |
36 | |
37 | /// Construct an empty expression. |
38 | explicit OMPArrayShapingExpr(EmptyShell Shell, unsigned NumDims) |
39 | : Expr(OMPArrayShapingExprClass, Shell), NumDims(NumDims) {} |
40 | |
41 | /// Sets the dimensions for the array shaping. |
42 | void setDimensions(ArrayRef<Expr *> Dims); |
43 | |
44 | /// Sets the base expression for array shaping operation. |
45 | void setBase(Expr *Op) { getTrailingObjects<Expr *>()[NumDims] = Op; } |
46 | |
47 | /// Sets source ranges for the brackets in the array shaping operation. |
48 | void setBracketsRanges(ArrayRef<SourceRange> BR); |
49 | |
50 | unsigned numTrailingObjects(OverloadToken<Expr *>) const { |
51 | // Add an extra one for the base expression. |
52 | return NumDims + 1; |
53 | } |
54 | |
55 | unsigned numTrailingObjects(OverloadToken<SourceRange>) const { |
56 | return NumDims; |
57 | } |
58 | |
59 | public: |
60 | static OMPArrayShapingExpr *Create(const ASTContext &Context, QualType T, |
61 | Expr *Op, SourceLocation L, |
62 | SourceLocation R, ArrayRef<Expr *> Dims, |
63 | ArrayRef<SourceRange> BracketRanges); |
64 | |
65 | static OMPArrayShapingExpr *CreateEmpty(const ASTContext &Context, |
66 | unsigned NumDims); |
67 | |
68 | SourceLocation getLParenLoc() const { return LPLoc; } |
69 | void setLParenLoc(SourceLocation L) { LPLoc = L; } |
70 | |
71 | SourceLocation getRParenLoc() const { return RPLoc; } |
72 | void setRParenLoc(SourceLocation L) { RPLoc = L; } |
73 | |
74 | SourceLocation getBeginLoc() const LLVM_READONLY { return LPLoc; } |
75 | SourceLocation getEndLoc() const LLVM_READONLY { |
76 | return getBase()->getEndLoc(); |
77 | } |
78 | |
79 | /// Fetches the dimensions for array shaping expression. |
80 | ArrayRef<Expr *> getDimensions() const { |
81 | return llvm::ArrayRef(getTrailingObjects<Expr *>(), NumDims); |
82 | } |
83 | |
84 | /// Fetches source ranges for the brackets os the array shaping expression. |
85 | ArrayRef<SourceRange> getBracketsRanges() const { |
86 | return llvm::ArrayRef(getTrailingObjects<SourceRange>(), NumDims); |
87 | } |
88 | |
89 | /// Fetches base expression of array shaping expression. |
90 | Expr *getBase() { return getTrailingObjects<Expr *>()[NumDims]; } |
91 | const Expr *getBase() const { return getTrailingObjects<Expr *>()[NumDims]; } |
92 | |
93 | static bool classof(const Stmt *T) { |
94 | return T->getStmtClass() == OMPArrayShapingExprClass; |
95 | } |
96 | |
97 | // Iterators |
98 | child_range children() { |
99 | Stmt **Begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>()); |
100 | return child_range(Begin, Begin + NumDims + 1); |
101 | } |
102 | const_child_range children() const { |
103 | Stmt *const *Begin = |
104 | reinterpret_cast<Stmt *const *>(getTrailingObjects<Expr *>()); |
105 | return const_child_range(Begin, Begin + NumDims + 1); |
106 | } |
107 | }; |
108 | |
109 | /// Helper expressions and declaration for OMPIteratorExpr class for each |
110 | /// iteration space. |
111 | struct OMPIteratorHelperData { |
112 | /// Internal normalized counter. |
113 | VarDecl *CounterVD = nullptr; |
114 | /// Normalized upper bound. Normalized loop iterates from 0 to Upper with |
115 | /// step 1. |
116 | Expr *Upper = nullptr; |
117 | /// Update expression for the originally specified iteration variable, |
118 | /// calculated as VD = Begin + CounterVD * Step; |
119 | Expr *Update = nullptr; |
120 | /// Updater for the internal counter: ++CounterVD; |
121 | Expr *CounterUpdate = nullptr; |
122 | }; |
123 | |
124 | /// OpenMP 5.0 [2.1.6 Iterators] |
125 | /// Iterators are identifiers that expand to multiple values in the clause on |
126 | /// which they appear. |
127 | /// The syntax of the iterator modifier is as follows: |
128 | /// \code |
129 | /// iterator(iterators-definition) |
130 | /// \endcode |
131 | /// where iterators-definition is one of the following: |
132 | /// \code |
133 | /// iterator-specifier [, iterators-definition ] |
134 | /// \endcode |
135 | /// where iterator-specifier is one of the following: |
136 | /// \code |
137 | /// [ iterator-type ] identifier = range-specification |
138 | /// \endcode |
139 | /// where identifier is a base language identifier. |
140 | /// iterator-type is a type name. |
141 | /// range-specification is of the form begin:end[:step], where begin and end are |
142 | /// expressions for which their types can be converted to iterator-type and step |
143 | /// is an integral expression. |
144 | /// In an iterator-specifier, if the iterator-type is not specified then the |
145 | /// type of that iterator is of int type. |
146 | /// The iterator-type must be an integral or pointer type. |
147 | /// The iterator-type must not be const qualified. |
148 | class OMPIteratorExpr final |
149 | : public Expr, |
150 | private llvm::TrailingObjects<OMPIteratorExpr, Decl *, Expr *, |
151 | SourceLocation, OMPIteratorHelperData> { |
152 | public: |
153 | /// Iterator range representation begin:end[:step]. |
154 | struct IteratorRange { |
155 | Expr *Begin = nullptr; |
156 | Expr *End = nullptr; |
157 | Expr *Step = nullptr; |
158 | }; |
159 | /// Iterator definition representation. |
160 | struct IteratorDefinition { |
161 | Decl *IteratorDecl = nullptr; |
162 | IteratorRange Range; |
163 | SourceLocation AssignmentLoc; |
164 | SourceLocation ColonLoc, SecondColonLoc; |
165 | }; |
166 | |
167 | private: |
168 | friend TrailingObjects; |
169 | friend class ASTStmtReader; |
170 | friend class ASTStmtWriter; |
171 | |
172 | /// Offset in the list of expressions for subelements of the ranges. |
173 | enum class RangeExprOffset { |
174 | Begin = 0, |
175 | End = 1, |
176 | Step = 2, |
177 | Total = 3, |
178 | }; |
179 | /// Offset in the list of locations for subelements of colon symbols |
180 | /// locations. |
181 | enum class RangeLocOffset { |
182 | AssignLoc = 0, |
183 | FirstColonLoc = 1, |
184 | SecondColonLoc = 2, |
185 | Total = 3, |
186 | }; |
187 | /// Location of 'iterator' keyword. |
188 | SourceLocation IteratorKwLoc; |
189 | /// Location of '('. |
190 | SourceLocation LPLoc; |
191 | /// Location of ')'. |
192 | SourceLocation RPLoc; |
193 | /// Number of iterator definitions. |
194 | unsigned NumIterators = 0; |
195 | |
196 | OMPIteratorExpr(QualType ExprTy, SourceLocation IteratorKwLoc, |
197 | SourceLocation L, SourceLocation R, |
198 | ArrayRef<IteratorDefinition> Data, |
199 | ArrayRef<OMPIteratorHelperData> Helpers); |
200 | |
201 | /// Construct an empty expression. |
202 | explicit OMPIteratorExpr(EmptyShell Shell, unsigned NumIterators) |
203 | : Expr(OMPIteratorExprClass, Shell), NumIterators(NumIterators) {} |
204 | |
205 | /// Sets basic declaration for the specified iterator definition. |
206 | void setIteratorDeclaration(unsigned I, Decl *D); |
207 | |
208 | /// Sets the location of the assignment symbol for the specified iterator |
209 | /// definition. |
210 | void setAssignmentLoc(unsigned I, SourceLocation Loc); |
211 | |
212 | /// Sets begin, end and optional step expressions for specified iterator |
213 | /// definition. |
214 | void setIteratorRange(unsigned I, Expr *Begin, SourceLocation ColonLoc, |
215 | Expr *End, SourceLocation SecondColonLoc, Expr *Step); |
216 | |
217 | /// Sets helpers for the specified iteration space. |
218 | void setHelper(unsigned I, const OMPIteratorHelperData &D); |
219 | |
220 | unsigned numTrailingObjects(OverloadToken<Decl *>) const { |
221 | return NumIterators; |
222 | } |
223 | |
224 | unsigned numTrailingObjects(OverloadToken<Expr *>) const { |
225 | return NumIterators * static_cast<int>(RangeExprOffset::Total); |
226 | } |
227 | |
228 | unsigned numTrailingObjects(OverloadToken<SourceLocation>) const { |
229 | return NumIterators * static_cast<int>(RangeLocOffset::Total); |
230 | } |
231 | |
232 | public: |
233 | static OMPIteratorExpr *Create(const ASTContext &Context, QualType T, |
234 | SourceLocation IteratorKwLoc, SourceLocation L, |
235 | SourceLocation R, |
236 | ArrayRef<IteratorDefinition> Data, |
237 | ArrayRef<OMPIteratorHelperData> Helpers); |
238 | |
239 | static OMPIteratorExpr *CreateEmpty(const ASTContext &Context, |
240 | unsigned NumIterators); |
241 | |
242 | SourceLocation getLParenLoc() const { return LPLoc; } |
243 | void setLParenLoc(SourceLocation L) { LPLoc = L; } |
244 | |
245 | SourceLocation getRParenLoc() const { return RPLoc; } |
246 | void setRParenLoc(SourceLocation L) { RPLoc = L; } |
247 | |
248 | SourceLocation getIteratorKwLoc() const { return IteratorKwLoc; } |
249 | void setIteratorKwLoc(SourceLocation L) { IteratorKwLoc = L; } |
250 | SourceLocation getBeginLoc() const LLVM_READONLY { return IteratorKwLoc; } |
251 | SourceLocation getEndLoc() const LLVM_READONLY { return RPLoc; } |
252 | |
253 | /// Gets the iterator declaration for the given iterator. |
254 | Decl *getIteratorDecl(unsigned I); |
255 | const Decl *getIteratorDecl(unsigned I) const { |
256 | return const_cast<OMPIteratorExpr *>(this)->getIteratorDecl(I); |
257 | } |
258 | |
259 | /// Gets the iterator range for the given iterator. |
260 | IteratorRange getIteratorRange(unsigned I); |
261 | const IteratorRange getIteratorRange(unsigned I) const { |
262 | return const_cast<OMPIteratorExpr *>(this)->getIteratorRange(I); |
263 | } |
264 | |
265 | /// Gets the location of '=' for the given iterator definition. |
266 | SourceLocation getAssignLoc(unsigned I) const; |
267 | /// Gets the location of the first ':' in the range for the given iterator |
268 | /// definition. |
269 | SourceLocation getColonLoc(unsigned I) const; |
270 | /// Gets the location of the second ':' (if any) in the range for the given |
271 | /// iteratori definition. |
272 | SourceLocation getSecondColonLoc(unsigned I) const; |
273 | |
274 | /// Returns number of iterator definitions. |
275 | unsigned numOfIterators() const { return NumIterators; } |
276 | |
277 | /// Fetches helper data for the specified iteration space. |
278 | OMPIteratorHelperData &getHelper(unsigned I); |
279 | const OMPIteratorHelperData &getHelper(unsigned I) const; |
280 | |
281 | static bool classof(const Stmt *T) { |
282 | return T->getStmtClass() == OMPIteratorExprClass; |
283 | } |
284 | |
285 | // Iterators |
286 | child_range children() { |
287 | Stmt **Begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>()); |
288 | return child_range( |
289 | Begin, Begin + NumIterators * static_cast<int>(RangeExprOffset::Total)); |
290 | } |
291 | const_child_range children() const { |
292 | Stmt *const *Begin = |
293 | reinterpret_cast<Stmt *const *>(getTrailingObjects<Expr *>()); |
294 | return const_child_range( |
295 | Begin, Begin + NumIterators * static_cast<int>(RangeExprOffset::Total)); |
296 | } |
297 | }; |
298 | |
299 | } // end namespace clang |
300 | |
301 | #endif |
302 | |