clang 22.0.0git
StmtOpenACC.cpp
Go to the documentation of this file.
1//===--- StmtOpenACC.cpp - Classes for OpenACC Constructs -----------------===//
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 implements the subclasses of Stmt class declared in StmtOpenACC.h
10//
11//===----------------------------------------------------------------------===//
12
15#include "clang/AST/ExprCXX.h"
16#include "clang/AST/StmtCXX.h"
17
18using namespace clang;
19
21OpenACCComputeConstruct::CreateEmpty(const ASTContext &C, unsigned NumClauses) {
22 void *Mem = C.Allocate(
23 OpenACCComputeConstruct::totalSizeToAlloc<const OpenACCClause *>(
24 NumClauses));
25 auto *Inst = new (Mem) OpenACCComputeConstruct(NumClauses);
26 return Inst;
27}
28
29OpenACCComputeConstruct *OpenACCComputeConstruct::Create(
31 SourceLocation DirLoc, SourceLocation EndLoc,
32 ArrayRef<const OpenACCClause *> Clauses, Stmt *StructuredBlock) {
33 void *Mem = C.Allocate(
34 OpenACCComputeConstruct::totalSizeToAlloc<const OpenACCClause *>(
35 Clauses.size()));
36 auto *Inst = new (Mem) OpenACCComputeConstruct(K, BeginLoc, DirLoc, EndLoc,
37 Clauses, StructuredBlock);
38 return Inst;
39}
40
41OpenACCLoopConstruct::OpenACCLoopConstruct(unsigned NumClauses)
43 OpenACCLoopConstructClass, OpenACCDirectiveKind::Loop,
45 /*AssociatedStmt=*/nullptr) {
46 std::uninitialized_value_construct_n(getTrailingObjects(), NumClauses);
47 setClauseList(getTrailingObjects(NumClauses));
48}
49
50OpenACCLoopConstruct::OpenACCLoopConstruct(
51 OpenACCDirectiveKind ParentKind, SourceLocation Start,
54 : OpenACCAssociatedStmtConstruct(OpenACCLoopConstructClass,
55 OpenACCDirectiveKind::Loop, Start, DirLoc,
56 End, Loop),
57 ParentComputeConstructKind(ParentKind) {
58 // accept 'nullptr' for the loop. This is diagnosed somewhere, but this gives
59 // us some level of AST fidelity in the error case.
60 assert((Loop == nullptr || isa<ForStmt, CXXForRangeStmt>(Loop)) &&
61 "Associated Loop not a for loop?");
62 // Initialize the trailing storage.
63 llvm::uninitialized_copy(Clauses, getTrailingObjects());
64
65 setClauseList(getTrailingObjects(Clauses.size()));
66}
67
68OpenACCLoopConstruct *OpenACCLoopConstruct::CreateEmpty(const ASTContext &C,
69 unsigned NumClauses) {
70 void *Mem =
71 C.Allocate(OpenACCLoopConstruct::totalSizeToAlloc<const OpenACCClause *>(
72 NumClauses));
73 auto *Inst = new (Mem) OpenACCLoopConstruct(NumClauses);
74 return Inst;
75}
76
77OpenACCLoopConstruct *OpenACCLoopConstruct::Create(
78 const ASTContext &C, OpenACCDirectiveKind ParentKind,
79 SourceLocation BeginLoc, SourceLocation DirLoc, SourceLocation EndLoc,
81 void *Mem =
82 C.Allocate(OpenACCLoopConstruct::totalSizeToAlloc<const OpenACCClause *>(
83 Clauses.size()));
84 auto *Inst = new (Mem)
85 OpenACCLoopConstruct(ParentKind, BeginLoc, DirLoc, EndLoc, Clauses, Loop);
86 return Inst;
87}
88
91 unsigned NumClauses) {
92 void *Mem = C.Allocate(
93 OpenACCCombinedConstruct::totalSizeToAlloc<const OpenACCClause *>(
94 NumClauses));
95 auto *Inst = new (Mem) OpenACCCombinedConstruct(NumClauses);
96 return Inst;
97}
98
99OpenACCCombinedConstruct *OpenACCCombinedConstruct::Create(
100 const ASTContext &C, OpenACCDirectiveKind DK, SourceLocation BeginLoc,
101 SourceLocation DirLoc, SourceLocation EndLoc,
103 void *Mem = C.Allocate(
104 OpenACCCombinedConstruct::totalSizeToAlloc<const OpenACCClause *>(
105 Clauses.size()));
106 auto *Inst = new (Mem)
107 OpenACCCombinedConstruct(DK, BeginLoc, DirLoc, EndLoc, Clauses, Loop);
108 return Inst;
109}
110
111OpenACCDataConstruct *OpenACCDataConstruct::CreateEmpty(const ASTContext &C,
112 unsigned NumClauses) {
113 void *Mem =
114 C.Allocate(OpenACCDataConstruct::totalSizeToAlloc<const OpenACCClause *>(
115 NumClauses));
116 auto *Inst = new (Mem) OpenACCDataConstruct(NumClauses);
117 return Inst;
118}
119
122 SourceLocation DirectiveLoc, SourceLocation End,
124 Stmt *StructuredBlock) {
125 void *Mem =
126 C.Allocate(OpenACCDataConstruct::totalSizeToAlloc<const OpenACCClause *>(
127 Clauses.size()));
128 auto *Inst = new (Mem)
129 OpenACCDataConstruct(Start, DirectiveLoc, End, Clauses, StructuredBlock);
130 return Inst;
131}
132
135 unsigned NumClauses) {
136 void *Mem = C.Allocate(
137 OpenACCEnterDataConstruct::totalSizeToAlloc<const OpenACCClause *>(
138 NumClauses));
139 auto *Inst = new (Mem) OpenACCEnterDataConstruct(NumClauses);
140 return Inst;
141}
142
143OpenACCEnterDataConstruct *OpenACCEnterDataConstruct::Create(
144 const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
146 void *Mem = C.Allocate(
147 OpenACCEnterDataConstruct::totalSizeToAlloc<const OpenACCClause *>(
148 Clauses.size()));
149 auto *Inst =
150 new (Mem) OpenACCEnterDataConstruct(Start, DirectiveLoc, End, Clauses);
151 return Inst;
152}
153
156 unsigned NumClauses) {
157 void *Mem = C.Allocate(
158 OpenACCExitDataConstruct::totalSizeToAlloc<const OpenACCClause *>(
159 NumClauses));
160 auto *Inst = new (Mem) OpenACCExitDataConstruct(NumClauses);
161 return Inst;
162}
163
164OpenACCExitDataConstruct *OpenACCExitDataConstruct::Create(
165 const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
167 void *Mem = C.Allocate(
168 OpenACCExitDataConstruct::totalSizeToAlloc<const OpenACCClause *>(
169 Clauses.size()));
170 auto *Inst =
171 new (Mem) OpenACCExitDataConstruct(Start, DirectiveLoc, End, Clauses);
172 return Inst;
173}
174
177 unsigned NumClauses) {
178 void *Mem = C.Allocate(
179 OpenACCHostDataConstruct::totalSizeToAlloc<const OpenACCClause *>(
180 NumClauses));
181 auto *Inst = new (Mem) OpenACCHostDataConstruct(NumClauses);
182 return Inst;
183}
184
185OpenACCHostDataConstruct *OpenACCHostDataConstruct::Create(
186 const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
188 Stmt *StructuredBlock) {
189 void *Mem = C.Allocate(
190 OpenACCHostDataConstruct::totalSizeToAlloc<const OpenACCClause *>(
191 Clauses.size()));
192 auto *Inst = new (Mem) OpenACCHostDataConstruct(Start, DirectiveLoc, End,
193 Clauses, StructuredBlock);
194 return Inst;
195}
196
197OpenACCWaitConstruct *OpenACCWaitConstruct::CreateEmpty(const ASTContext &C,
198 unsigned NumExprs,
199 unsigned NumClauses) {
200 void *Mem = C.Allocate(
201 OpenACCWaitConstruct::totalSizeToAlloc<Expr *, OpenACCClause *>(
202 NumExprs, NumClauses));
203
204 auto *Inst = new (Mem) OpenACCWaitConstruct(NumExprs, NumClauses);
205 return Inst;
206}
207
208OpenACCWaitConstruct *OpenACCWaitConstruct::Create(
209 const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
210 SourceLocation LParenLoc, Expr *DevNumExpr, SourceLocation QueuesLoc,
211 ArrayRef<Expr *> QueueIdExprs, SourceLocation RParenLoc, SourceLocation End,
213
214 assert(!llvm::is_contained(QueueIdExprs, nullptr));
215
216 void *Mem = C.Allocate(
217 OpenACCWaitConstruct::totalSizeToAlloc<Expr *, OpenACCClause *>(
218 QueueIdExprs.size() + 1, Clauses.size()));
219
220 auto *Inst = new (Mem)
221 OpenACCWaitConstruct(Start, DirectiveLoc, LParenLoc, DevNumExpr,
222 QueuesLoc, QueueIdExprs, RParenLoc, End, Clauses);
223 return Inst;
224}
225OpenACCInitConstruct *OpenACCInitConstruct::CreateEmpty(const ASTContext &C,
226 unsigned NumClauses) {
227 void *Mem =
228 C.Allocate(OpenACCInitConstruct::totalSizeToAlloc<const OpenACCClause *>(
229 NumClauses));
230 auto *Inst = new (Mem) OpenACCInitConstruct(NumClauses);
231 return Inst;
232}
233
236 SourceLocation DirectiveLoc, SourceLocation End,
238 void *Mem =
239 C.Allocate(OpenACCInitConstruct::totalSizeToAlloc<const OpenACCClause *>(
240 Clauses.size()));
241 auto *Inst =
242 new (Mem) OpenACCInitConstruct(Start, DirectiveLoc, End, Clauses);
243 return Inst;
244}
247 unsigned NumClauses) {
248 void *Mem = C.Allocate(
249 OpenACCShutdownConstruct::totalSizeToAlloc<const OpenACCClause *>(
250 NumClauses));
251 auto *Inst = new (Mem) OpenACCShutdownConstruct(NumClauses);
252 return Inst;
253}
254
255OpenACCShutdownConstruct *OpenACCShutdownConstruct::Create(
256 const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
258 void *Mem = C.Allocate(
259 OpenACCShutdownConstruct::totalSizeToAlloc<const OpenACCClause *>(
260 Clauses.size()));
261 auto *Inst =
262 new (Mem) OpenACCShutdownConstruct(Start, DirectiveLoc, End, Clauses);
263 return Inst;
264}
265
267 unsigned NumClauses) {
268 void *Mem = C.Allocate(
269 OpenACCSetConstruct::totalSizeToAlloc<const OpenACCClause *>(NumClauses));
270 auto *Inst = new (Mem) OpenACCSetConstruct(NumClauses);
271 return Inst;
272}
273
276 SourceLocation DirectiveLoc, SourceLocation End,
278 void *Mem =
279 C.Allocate(OpenACCSetConstruct::totalSizeToAlloc<const OpenACCClause *>(
280 Clauses.size()));
281 auto *Inst = new (Mem) OpenACCSetConstruct(Start, DirectiveLoc, End, Clauses);
282 return Inst;
283}
284
287 void *Mem = C.Allocate(
288 OpenACCUpdateConstruct::totalSizeToAlloc<const OpenACCClause *>(
289 NumClauses));
290 auto *Inst = new (Mem) OpenACCUpdateConstruct(NumClauses);
291 return Inst;
292}
293
296 SourceLocation DirectiveLoc, SourceLocation End,
298 void *Mem = C.Allocate(
299 OpenACCUpdateConstruct::totalSizeToAlloc<const OpenACCClause *>(
300 Clauses.size()));
301 auto *Inst =
302 new (Mem) OpenACCUpdateConstruct(Start, DirectiveLoc, End, Clauses);
303 return Inst;
304}
305
308 void *Mem = C.Allocate(
309 OpenACCAtomicConstruct::totalSizeToAlloc<const OpenACCClause *>(
310 NumClauses));
311 auto *Inst = new (Mem) OpenACCAtomicConstruct(NumClauses);
312 return Inst;
313}
314
315OpenACCAtomicConstruct *OpenACCAtomicConstruct::Create(
316 const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
318 ArrayRef<const OpenACCClause *> Clauses, Stmt *AssociatedStmt) {
319 void *Mem = C.Allocate(
320 OpenACCAtomicConstruct::totalSizeToAlloc<const OpenACCClause *>(
321 Clauses.size()));
322 auto *Inst = new (Mem) OpenACCAtomicConstruct(Start, DirectiveLoc, AtKind,
323 End, Clauses, AssociatedStmt);
324 return Inst;
325}
326
327static std::pair<const Expr *, const Expr *> getBinaryOpArgs(const Expr *Op) {
328 if (const auto *BO = dyn_cast<BinaryOperator>(Op)) {
329 assert(BO->isAssignmentOp());
330 return {BO->getLHS(), BO->getRHS()};
331 }
332
333 const auto *OO = cast<CXXOperatorCallExpr>(Op);
334 assert(OO->isAssignmentOp());
335 return {OO->getArg(0), OO->getArg(1)};
336}
337
338static std::pair<bool, const Expr *> getUnaryOpArgs(const Expr *Op) {
339 if (const auto *UO = dyn_cast<UnaryOperator>(Op))
340 return {true, UO->getSubExpr()};
341
342 if (const auto *OpCall = dyn_cast<CXXOperatorCallExpr>(Op)) {
343 // Post-inc/dec have a second unused argument to differentiate it, so we
344 // accept -- or ++ as unary, or any operator call with only 1 arg.
345 if (OpCall->getNumArgs() == 1 || OpCall->getOperator() != OO_PlusPlus ||
346 OpCall->getOperator() != OO_MinusMinus)
347 return {true, OpCall->getArg(0)};
348 }
349
350 return {false, nullptr};
351}
352
355 // This ends up being a vastly simplified version of SemaOpenACCAtomic, since
356 // it doesn't have to worry about erroring out, but we should do a lot of
357 // asserts to ensure we don't get off into the weeds.
358 assert(getAssociatedStmt() && "invalid associated stmt?");
359
360 const Expr *AssocStmt = cast<const Expr>(getAssociatedStmt());
361 switch (AtomicKind) {
363 assert(false && "Only 'read'/'write'/'update' have been implemented here");
364 return {};
366 // Read only supports the format 'v = x'; where both sides are a scalar
367 // expression. This can come in 2 forms; BinaryOperator or
368 // CXXOperatorCallExpr (rarely).
369 std::pair<const Expr *, const Expr *> BinaryArgs =
370 getBinaryOpArgs(AssocStmt);
371 // We want the L-value for each side, so we ignore implicit casts.
372 return {BinaryArgs.first->IgnoreImpCasts(),
373 BinaryArgs.second->IgnoreImpCasts(), /*expr=*/nullptr};
374 }
376 // Write supports only the format 'x = expr', where the expression is scalar
377 // type, and 'x' is a scalar l value. As above, this can come in 2 forms;
378 // Binary Operator or CXXOperatorCallExpr.
379 std::pair<const Expr *, const Expr *> BinaryArgs =
380 getBinaryOpArgs(AssocStmt);
381 // We want the L-value for ONLY the X side, so we ignore implicit casts. For
382 // the right side (the expr), we emit it as an r-value so we need to
383 // maintain implicit casts.
384 return {/*v=*/nullptr, BinaryArgs.first->IgnoreImpCasts(),
385 BinaryArgs.second};
386 }
389 std::pair<bool, const Expr *> UnaryArgs = getUnaryOpArgs(AssocStmt);
390 if (UnaryArgs.first)
391 return {/*v=*/nullptr, UnaryArgs.second->IgnoreImpCasts(),
392 /*expr=*/nullptr};
393
394 std::pair<const Expr *, const Expr *> BinaryArgs =
395 getBinaryOpArgs(AssocStmt);
396 // For binary args, we just store the RHS as an expression (in the
397 // expression slot), since the codegen just wants the whole thing for a
398 // recipe.
399 return {/*v=*/nullptr, BinaryArgs.first->IgnoreImpCasts(),
400 BinaryArgs.second};
401 }
402 }
403
404 llvm_unreachable("unknown OpenACC atomic kind");
405}
406
407OpenACCCacheConstruct *OpenACCCacheConstruct::CreateEmpty(const ASTContext &C,
408 unsigned NumVars) {
409 void *Mem =
410 C.Allocate(OpenACCCacheConstruct::totalSizeToAlloc<Expr *>(NumVars));
411 auto *Inst = new (Mem) OpenACCCacheConstruct(NumVars);
412 return Inst;
413}
414
415OpenACCCacheConstruct *OpenACCCacheConstruct::Create(
416 const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
417 SourceLocation LParenLoc, SourceLocation ReadOnlyLoc,
418 ArrayRef<Expr *> VarList, SourceLocation RParenLoc, SourceLocation End) {
419 void *Mem = C.Allocate(
420 OpenACCCacheConstruct::totalSizeToAlloc<Expr *>(VarList.size()));
421 auto *Inst = new (Mem) OpenACCCacheConstruct(
422 Start, DirectiveLoc, LParenLoc, ReadOnlyLoc, VarList, RParenLoc, End);
423 return Inst;
424}
Defines the clang::ASTContext interface.
Defines the clang::Expr interface and subclasses for C++ expressions.
static std::pair< const Expr *, const Expr * > getBinaryOpArgs(const Expr *Op)
static std::pair< bool, const Expr * > getUnaryOpArgs(const Expr *Op)
This file defines OpenACC AST classes for statement-level contructs.
const Stmt * getAssociatedStmt() const
static OpenACCAtomicConstruct * CreateEmpty(const ASTContext &C, unsigned NumClauses)
const StmtInfo getAssociatedStmtInfo() const
static OpenACCAtomicConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, OpenACCAtomicKind AtKind, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses, Stmt *AssociatedStmt)
static OpenACCCacheConstruct * CreateEmpty(const ASTContext &C, unsigned NumVars)
static OpenACCCacheConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation LParenLoc, SourceLocation ReadOnlyLoc, ArrayRef< Expr * > VarList, SourceLocation RParenLoc, SourceLocation End)
static OpenACCCombinedConstruct * CreateEmpty(const ASTContext &C, unsigned NumClauses)
static OpenACCCombinedConstruct * Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses, Stmt *StructuredBlock)
static OpenACCDataConstruct * CreateEmpty(const ASTContext &C, unsigned NumClauses)
static OpenACCDataConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses, Stmt *StructuredBlock)
static OpenACCEnterDataConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
static OpenACCEnterDataConstruct * CreateEmpty(const ASTContext &C, unsigned NumClauses)
static OpenACCExitDataConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
static OpenACCExitDataConstruct * CreateEmpty(const ASTContext &C, unsigned NumClauses)
static OpenACCHostDataConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses, Stmt *StructuredBlock)
static OpenACCHostDataConstruct * CreateEmpty(const ASTContext &C, unsigned NumClauses)
static OpenACCInitConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
static OpenACCInitConstruct * CreateEmpty(const ASTContext &C, unsigned NumClauses)
static OpenACCLoopConstruct * CreateEmpty(const ASTContext &C, unsigned NumClauses)
static OpenACCLoopConstruct * Create(const ASTContext &C, OpenACCDirectiveKind ParentKind, SourceLocation BeginLoc, SourceLocation DirLoc, SourceLocation EndLoc, ArrayRef< const OpenACCClause * > Clauses, Stmt *Loop)
friend class ASTContext
static OpenACCSetConstruct * CreateEmpty(const ASTContext &C, unsigned NumClauses)
static OpenACCSetConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
static OpenACCShutdownConstruct * CreateEmpty(const ASTContext &C, unsigned NumClauses)
static OpenACCShutdownConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
static OpenACCUpdateConstruct * CreateEmpty(const ASTContext &C, unsigned NumClauses)
static OpenACCUpdateConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
static OpenACCWaitConstruct * CreateEmpty(const ASTContext &C, unsigned NumExprs, unsigned NumClauses)
static OpenACCWaitConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation LParenLoc, Expr *DevNumExpr, SourceLocation QueuesLoc, ArrayRef< Expr * > QueueIdExprs, SourceLocation RParenLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:220
This represents one expression.
Definition Expr.h:112
This is a base class for any OpenACC statement-level constructs that have an associated statement.
Definition StmtOpenACC.h:81
Encodes a location in the source.
Stmt - This represents one statement.
Definition Stmt.h:85
The JSON file list parser is used to communicate input to InstallAPI.
OpenACCDirectiveKind
bool isa(CodeGen::Address addr)
Definition Address.h:330
OpenACCAtomicKind
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
OpenACCComputeConstruct(OpenACCDirectiveKind K, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses, Stmt *StructuredBlock)
setClauseList(getTrailingObjects(NumClauses))
U cast(CodeGen::Address addr)
Definition Address.h:327