clang 20.0.0git
SemaOpenACC.h
Go to the documentation of this file.
1//===----- SemaOpenACC.h - Semantic Analysis 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/// \file
9/// This file declares semantic analysis for OpenACC constructs and
10/// clauses.
11///
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_SEMA_SEMAOPENACC_H
15#define LLVM_CLANG_SEMA_SEMAOPENACC_H
16
17#include "clang/AST/DeclGroup.h"
19#include "clang/Basic/LLVM.h"
23#include "clang/Sema/SemaBase.h"
24#include "llvm/ADT/SmallVector.h"
25#include "llvm/Support/Compiler.h"
26#include <cassert>
27#include <optional>
28#include <utility>
29#include <variant>
30
31namespace clang {
32class IdentifierInfo;
33class OpenACCClause;
34
35class SemaOpenACC : public SemaBase {
36private:
37 struct ComputeConstructInfo {
38 /// Which type of compute construct we are inside of, which we can use to
39 /// determine whether we should add loops to the above collection. We can
40 /// also use it to diagnose loop construct clauses.
42 // If we have an active compute construct, stores the list of clauses we've
43 // prepared for it, so that we can diagnose limitations on child constructs.
45 } ActiveComputeConstructInfo;
46
47 bool isInComputeConstruct() const {
48 return ActiveComputeConstructInfo.Kind != OpenACCDirectiveKind::Invalid;
49 }
50
51 /// Certain clauses care about the same things that aren't specific to the
52 /// individual clause, but can be shared by a few, so store them here. All
53 /// require a 'no intervening constructs' rule, so we know they are all from
54 /// the same 'place'.
55 struct LoopCheckingInfo {
56 /// Records whether we've seen the top level 'for'. We already diagnose
57 /// later that the 'top level' is a for loop, so we use this to suppress the
58 /// 'collapse inner loop not a 'for' loop' diagnostic.
59 LLVM_PREFERRED_TYPE(bool)
60 unsigned TopLevelLoopSeen : 1;
61
62 /// Records whether this 'tier' of the loop has already seen a 'for' loop,
63 /// used to diagnose if there are multiple 'for' loops at any one level.
64 LLVM_PREFERRED_TYPE(bool)
65 unsigned CurLevelHasLoopAlready : 1;
66
67 } LoopInfo{/*TopLevelLoopSeen=*/false, /*CurLevelHasLoopAlready=*/false};
68
69 /// The 'collapse' clause requires quite a bit of checking while
70 /// parsing/instantiating its body, so this structure/object keeps all of the
71 /// necessary information as we do checking. This should rarely be directly
72 /// modified, and typically should be controlled by the RAII objects.
73 ///
74 /// Collapse has an 'N' count that makes it apply to a number of loops 'below'
75 /// it.
76 struct CollapseCheckingInfo {
77 OpenACCCollapseClause *ActiveCollapse = nullptr;
78
79 /// This is a value that maintains the current value of the 'N' on the
80 /// current collapse, minus the depth that has already been traversed. When
81 /// there is not an active collapse, or a collapse whose depth we don't know
82 /// (for example, if it is a dependent value), this should be `nullopt`,
83 /// else it should be 'N' minus the current depth traversed.
84 std::optional<llvm::APSInt> CurCollapseCount;
85
86 /// Records whether we've hit a CurCollapseCount of '0' on the way down,
87 /// which allows us to diagnose if the value of 'N' is too large for the
88 /// current number of 'for' loops.
89 bool CollapseDepthSatisfied = true;
90
91 /// Records the kind of the directive that this clause is attached to, which
92 /// allows us to use it in diagnostics.
94 } CollapseInfo;
95
96 /// The 'tile' clause requires a bit of additional checking as well, so like
97 /// the `CollapseCheckingInfo`, ensure we maintain information here too.
98 struct TileCheckingInfo {
99 OpenACCTileClause *ActiveTile = nullptr;
100
101 /// This is the number of expressions on a 'tile' clause. This doesn't have
102 /// to be an APSInt because it isn't the result of a constexpr, just by our
103 /// own counting of elements.
104 std::optional<unsigned> CurTileCount;
105
106 /// Records whether we've hit a 'CurTileCount' of '0' on the wya down,
107 /// which allows us to diagnose if the number of arguments is too large for
108 /// the current number of 'for' loops.
109 bool TileDepthSatisfied = true;
110
111 /// Records the kind of the directive that this clause is attached to, which
112 /// allows us to use it in diagnostics.
114 } TileInfo;
115
116 /// A list of the active reduction clauses, which allows us to check that all
117 /// vars on nested constructs for the same reduction var have the same
118 /// reduction operator. Currently this is enforced against all constructs
119 /// despite the rule being in the 'loop' section. By current reading, this
120 /// should apply to all anyway, but we may need to make this more like the
121 /// 'loop' clause enforcement, where this is 'blocked' by a compute construct.
122 llvm::SmallVector<OpenACCReductionClause *> ActiveReductionClauses;
123
124 // Type to check the info about the 'for stmt'.
125 struct ForStmtBeginChecker {
126 SemaOpenACC &SemaRef;
127 SourceLocation ForLoc;
128 bool IsRangeFor = false;
129 std::optional<const CXXForRangeStmt *> RangeFor = nullptr;
130 const Stmt *Init = nullptr;
131 bool InitChanged = false;
132 std::optional<const Stmt *> Cond = nullptr;
133 std::optional<const Stmt *> Inc = nullptr;
134 // Prevent us from checking 2x, which can happen with collapse & tile.
135 bool AlreadyChecked = false;
136
137 ForStmtBeginChecker(SemaOpenACC &SemaRef, SourceLocation ForLoc,
138 std::optional<const CXXForRangeStmt *> S)
139 : SemaRef(SemaRef), ForLoc(ForLoc), IsRangeFor(true), RangeFor(S) {}
140
141 ForStmtBeginChecker(SemaOpenACC &SemaRef, SourceLocation ForLoc,
142 const Stmt *I, bool InitChanged,
143 std::optional<const Stmt *> C,
144 std::optional<const Stmt *> Inc)
145 : SemaRef(SemaRef), ForLoc(ForLoc), IsRangeFor(false), Init(I),
146 InitChanged(InitChanged), Cond(C), Inc(Inc) {}
147 // Do the checking for the For/Range-For. Currently this implements the 'not
148 // seq' restrictions only, and should be called either if we know we are a
149 // top-level 'for' (the one associated via associated-stmt), or extended via
150 // 'collapse'.
151 void check();
152
153 const ValueDecl *checkInit();
154 void checkCond();
155 void checkInc(const ValueDecl *Init);
156 };
157
158 /// Helper function for checking the 'for' and 'range for' stmts.
159 void ForStmtBeginHelper(SourceLocation ForLoc, ForStmtBeginChecker &C);
160
161public:
162 ComputeConstructInfo &getActiveComputeConstructInfo() {
163 return ActiveComputeConstructInfo;
164 }
165
166 /// If there is a current 'active' loop construct with a 'gang' clause on a
167 /// 'kernel' construct, this will have the source location for it, and the
168 /// 'kernel kind'. This permits us to implement the restriction of no further
169 /// 'gang' clauses.
174
175 /// If there is a current 'active' loop construct with a 'worker' clause on it
176 /// (on any sort of construct), this has the source location for it. This
177 /// permits us to implement the restriction of no further 'gang' or 'worker'
178 /// clauses.
180 /// If there is a current 'active' loop construct with a 'vector' clause on it
181 /// (on any sort of construct), this has the source location for it. This
182 /// permits us to implement the restriction of no further 'gang', 'vector', or
183 /// 'worker' clauses.
185 /// If there is a current 'active' loop construct that does NOT have a 'seq'
186 /// clause on it, this has that source location and loop Directive 'kind'.
187 /// This permits us to implement the 'loop' restrictions on the loop variable.
188 /// This can be extended via 'collapse', so we need to keep this around for a
189 /// while.
194
195 // Redeclaration of the version in OpenACCClause.h.
196 using DeviceTypeArgument = std::pair<IdentifierInfo *, SourceLocation>;
197
198 /// A type to represent all the data for an OpenACC Clause that has been
199 /// parsed, but not yet created/semantically analyzed. This is effectively a
200 /// discriminated union on the 'Clause Kind', with all of the individual
201 /// clause details stored in a std::variant.
203 OpenACCDirectiveKind DirKind;
204 OpenACCClauseKind ClauseKind;
205 SourceRange ClauseRange;
206 SourceLocation LParenLoc;
207
208 struct DefaultDetails {
209 OpenACCDefaultClauseKind DefaultClauseKind;
210 };
211
212 struct ConditionDetails {
213 Expr *ConditionExpr;
214 };
215
216 struct IntExprDetails {
217 SmallVector<Expr *> IntExprs;
218 };
219
220 struct VarListDetails {
221 SmallVector<Expr *> VarList;
222 bool IsReadOnly;
223 bool IsZero;
224 };
225
226 struct WaitDetails {
227 Expr *DevNumExpr;
228 SourceLocation QueuesLoc;
229 SmallVector<Expr *> QueueIdExprs;
230 };
231
232 struct DeviceTypeDetails {
234 };
235 struct ReductionDetails {
237 SmallVector<Expr *> VarList;
238 };
239
240 struct CollapseDetails {
241 bool IsForce;
242 Expr *LoopCount;
243 };
244
245 struct GangDetails {
247 SmallVector<Expr *> IntExprs;
248 };
249
250 std::variant<std::monostate, DefaultDetails, ConditionDetails,
251 IntExprDetails, VarListDetails, WaitDetails, DeviceTypeDetails,
252 ReductionDetails, CollapseDetails, GangDetails>
253 Details = std::monostate{};
254
255 public:
257 OpenACCClauseKind ClauseKind, SourceLocation BeginLoc)
258 : DirKind(DirKind), ClauseKind(ClauseKind), ClauseRange(BeginLoc, {}) {}
259
260 OpenACCDirectiveKind getDirectiveKind() const { return DirKind; }
261
262 OpenACCClauseKind getClauseKind() const { return ClauseKind; }
263
264 SourceLocation getBeginLoc() const { return ClauseRange.getBegin(); }
265
266 SourceLocation getLParenLoc() const { return LParenLoc; }
267
268 SourceLocation getEndLoc() const { return ClauseRange.getEnd(); }
269
271 assert(ClauseKind == OpenACCClauseKind::Default &&
272 "Parsed clause is not a default clause");
273 return std::get<DefaultDetails>(Details).DefaultClauseKind;
274 }
275
276 const Expr *getConditionExpr() const {
277 return const_cast<OpenACCParsedClause *>(this)->getConditionExpr();
278 }
279
281 assert((ClauseKind == OpenACCClauseKind::If ||
282 (ClauseKind == OpenACCClauseKind::Self &&
283 DirKind != OpenACCDirectiveKind::Update)) &&
284 "Parsed clause kind does not have a condition expr");
285
286 // 'self' has an optional ConditionExpr, so be tolerant of that. This will
287 // assert in variant otherwise.
288 if (ClauseKind == OpenACCClauseKind::Self &&
289 std::holds_alternative<std::monostate>(Details))
290 return nullptr;
291
292 return std::get<ConditionDetails>(Details).ConditionExpr;
293 }
294
295 unsigned getNumIntExprs() const {
296 assert((ClauseKind == OpenACCClauseKind::NumGangs ||
297 ClauseKind == OpenACCClauseKind::NumWorkers ||
298 ClauseKind == OpenACCClauseKind::Async ||
299 ClauseKind == OpenACCClauseKind::DeviceNum ||
300 ClauseKind == OpenACCClauseKind::Tile ||
301 ClauseKind == OpenACCClauseKind::Worker ||
302 ClauseKind == OpenACCClauseKind::Vector ||
303 ClauseKind == OpenACCClauseKind::VectorLength) &&
304 "Parsed clause kind does not have a int exprs");
305
306 // 'async', 'worker', 'vector', and 'wait' have an optional IntExpr, so be
307 // tolerant of that.
308 if ((ClauseKind == OpenACCClauseKind::Async ||
309 ClauseKind == OpenACCClauseKind::Worker ||
310 ClauseKind == OpenACCClauseKind::Vector ||
311 ClauseKind == OpenACCClauseKind::Wait) &&
312 std::holds_alternative<std::monostate>(Details))
313 return 0;
314 return std::get<IntExprDetails>(Details).IntExprs.size();
315 }
316
318 assert(ClauseKind == OpenACCClauseKind::Wait &&
319 "Parsed clause kind does not have a queues location");
320
321 if (std::holds_alternative<std::monostate>(Details))
322 return SourceLocation{};
323
324 return std::get<WaitDetails>(Details).QueuesLoc;
325 }
326
328 assert(ClauseKind == OpenACCClauseKind::Wait &&
329 "Parsed clause kind does not have a device number expr");
330
331 if (std::holds_alternative<std::monostate>(Details))
332 return nullptr;
333
334 return std::get<WaitDetails>(Details).DevNumExpr;
335 }
336
338 assert(ClauseKind == OpenACCClauseKind::Wait &&
339 "Parsed clause kind does not have a queue id expr list");
340
341 if (std::holds_alternative<std::monostate>(Details))
342 return ArrayRef<Expr *>();
343
344 return std::get<WaitDetails>(Details).QueueIdExprs;
345 }
346
348 assert((ClauseKind == OpenACCClauseKind::NumGangs ||
349 ClauseKind == OpenACCClauseKind::NumWorkers ||
350 ClauseKind == OpenACCClauseKind::Async ||
351 ClauseKind == OpenACCClauseKind::DeviceNum ||
352 ClauseKind == OpenACCClauseKind::Tile ||
353 ClauseKind == OpenACCClauseKind::Gang ||
354 ClauseKind == OpenACCClauseKind::Worker ||
355 ClauseKind == OpenACCClauseKind::Vector ||
356 ClauseKind == OpenACCClauseKind::VectorLength) &&
357 "Parsed clause kind does not have a int exprs");
358
359 if (ClauseKind == OpenACCClauseKind::Gang) {
360 // There might not be any gang int exprs, as this is an optional
361 // argument.
362 if (std::holds_alternative<std::monostate>(Details))
363 return {};
364 return std::get<GangDetails>(Details).IntExprs;
365 }
366
367 return std::get<IntExprDetails>(Details).IntExprs;
368 }
369
371 return const_cast<OpenACCParsedClause *>(this)->getIntExprs();
372 }
373
375 return std::get<ReductionDetails>(Details).Op;
376 }
377
379 assert(ClauseKind == OpenACCClauseKind::Gang &&
380 "Parsed clause kind does not have gang kind");
381 // The args on gang are optional, so this might not actually hold
382 // anything.
383 if (std::holds_alternative<std::monostate>(Details))
384 return {};
385 return std::get<GangDetails>(Details).GangKinds;
386 }
387
389 assert((ClauseKind == OpenACCClauseKind::Private ||
390 ClauseKind == OpenACCClauseKind::NoCreate ||
391 ClauseKind == OpenACCClauseKind::Present ||
392 ClauseKind == OpenACCClauseKind::Copy ||
393 ClauseKind == OpenACCClauseKind::PCopy ||
394 ClauseKind == OpenACCClauseKind::PresentOrCopy ||
395 ClauseKind == OpenACCClauseKind::CopyIn ||
396 ClauseKind == OpenACCClauseKind::PCopyIn ||
398 ClauseKind == OpenACCClauseKind::CopyOut ||
399 ClauseKind == OpenACCClauseKind::PCopyOut ||
401 ClauseKind == OpenACCClauseKind::Create ||
402 ClauseKind == OpenACCClauseKind::PCreate ||
404 ClauseKind == OpenACCClauseKind::Attach ||
405 ClauseKind == OpenACCClauseKind::Delete ||
406 ClauseKind == OpenACCClauseKind::UseDevice ||
407 ClauseKind == OpenACCClauseKind::Detach ||
408 ClauseKind == OpenACCClauseKind::DevicePtr ||
409 ClauseKind == OpenACCClauseKind::Reduction ||
410 ClauseKind == OpenACCClauseKind::FirstPrivate) &&
411 "Parsed clause kind does not have a var-list");
412
413 if (ClauseKind == OpenACCClauseKind::Reduction)
414 return std::get<ReductionDetails>(Details).VarList;
415
416 return std::get<VarListDetails>(Details).VarList;
417 }
418
420 return const_cast<OpenACCParsedClause *>(this)->getVarList();
421 }
422
423 bool isReadOnly() const {
424 assert((ClauseKind == OpenACCClauseKind::CopyIn ||
425 ClauseKind == OpenACCClauseKind::PCopyIn ||
426 ClauseKind == OpenACCClauseKind::PresentOrCopyIn) &&
427 "Only copyin accepts 'readonly:' tag");
428 return std::get<VarListDetails>(Details).IsReadOnly;
429 }
430
431 bool isZero() const {
432 assert((ClauseKind == OpenACCClauseKind::CopyOut ||
433 ClauseKind == OpenACCClauseKind::PCopyOut ||
435 ClauseKind == OpenACCClauseKind::Create ||
436 ClauseKind == OpenACCClauseKind::PCreate ||
437 ClauseKind == OpenACCClauseKind::PresentOrCreate) &&
438 "Only copyout/create accepts 'zero' tag");
439 return std::get<VarListDetails>(Details).IsZero;
440 }
441
442 bool isForce() const {
443 assert(ClauseKind == OpenACCClauseKind::Collapse &&
444 "Only 'collapse' has a force tag");
445 return std::get<CollapseDetails>(Details).IsForce;
446 }
447
449 assert(ClauseKind == OpenACCClauseKind::Collapse &&
450 "Only 'collapse' has a loop count");
451 return std::get<CollapseDetails>(Details).LoopCount;
452 }
453
455 assert((ClauseKind == OpenACCClauseKind::DeviceType ||
456 ClauseKind == OpenACCClauseKind::DType) &&
457 "Only 'device_type'/'dtype' has a device-type-arg list");
458 return std::get<DeviceTypeDetails>(Details).Archs;
459 }
460
461 void setLParenLoc(SourceLocation EndLoc) { LParenLoc = EndLoc; }
462 void setEndLoc(SourceLocation EndLoc) { ClauseRange.setEnd(EndLoc); }
463
465 assert(ClauseKind == OpenACCClauseKind::Default &&
466 "Parsed clause is not a default clause");
467 Details = DefaultDetails{DefKind};
468 }
469
470 void setConditionDetails(Expr *ConditionExpr) {
471 assert((ClauseKind == OpenACCClauseKind::If ||
472 (ClauseKind == OpenACCClauseKind::Self &&
473 DirKind != OpenACCDirectiveKind::Update)) &&
474 "Parsed clause kind does not have a condition expr");
475 // In C++ we can count on this being a 'bool', but in C this gets left as
476 // some sort of scalar that codegen will have to take care of converting.
477 assert((!ConditionExpr || ConditionExpr->isInstantiationDependent() ||
478 ConditionExpr->getType()->isScalarType()) &&
479 "Condition expression type not scalar/dependent");
480
481 Details = ConditionDetails{ConditionExpr};
482 }
483
485 assert((ClauseKind == OpenACCClauseKind::NumGangs ||
486 ClauseKind == OpenACCClauseKind::NumWorkers ||
487 ClauseKind == OpenACCClauseKind::Async ||
488 ClauseKind == OpenACCClauseKind::DeviceNum ||
489 ClauseKind == OpenACCClauseKind::Tile ||
490 ClauseKind == OpenACCClauseKind::Worker ||
491 ClauseKind == OpenACCClauseKind::Vector ||
492 ClauseKind == OpenACCClauseKind::VectorLength) &&
493 "Parsed clause kind does not have a int exprs");
494 Details = IntExprDetails{{IntExprs.begin(), IntExprs.end()}};
495 }
497 assert((ClauseKind == OpenACCClauseKind::NumGangs ||
498 ClauseKind == OpenACCClauseKind::NumWorkers ||
499 ClauseKind == OpenACCClauseKind::Async ||
500 ClauseKind == OpenACCClauseKind::DeviceNum ||
501 ClauseKind == OpenACCClauseKind::Tile ||
502 ClauseKind == OpenACCClauseKind::Worker ||
503 ClauseKind == OpenACCClauseKind::Vector ||
504 ClauseKind == OpenACCClauseKind::VectorLength) &&
505 "Parsed clause kind does not have a int exprs");
506 Details = IntExprDetails{std::move(IntExprs)};
507 }
508
510 ArrayRef<Expr *> IntExprs) {
511 assert(ClauseKind == OpenACCClauseKind::Gang &&
512 "Parsed Clause kind does not have gang details");
513 assert(GKs.size() == IntExprs.size() && "Mismatched kind/size?");
514
515 Details = GangDetails{{GKs.begin(), GKs.end()},
516 {IntExprs.begin(), IntExprs.end()}};
517 }
518
520 llvm::SmallVector<Expr *> &&IntExprs) {
521 assert(ClauseKind == OpenACCClauseKind::Gang &&
522 "Parsed Clause kind does not have gang details");
523 assert(GKs.size() == IntExprs.size() && "Mismatched kind/size?");
524
525 Details = GangDetails{std::move(GKs), std::move(IntExprs)};
526 }
527
528 void setVarListDetails(ArrayRef<Expr *> VarList, bool IsReadOnly,
529 bool IsZero) {
530 assert((ClauseKind == OpenACCClauseKind::Private ||
531 ClauseKind == OpenACCClauseKind::NoCreate ||
532 ClauseKind == OpenACCClauseKind::Present ||
533 ClauseKind == OpenACCClauseKind::Copy ||
534 ClauseKind == OpenACCClauseKind::PCopy ||
535 ClauseKind == OpenACCClauseKind::PresentOrCopy ||
536 ClauseKind == OpenACCClauseKind::CopyIn ||
537 ClauseKind == OpenACCClauseKind::PCopyIn ||
539 ClauseKind == OpenACCClauseKind::CopyOut ||
540 ClauseKind == OpenACCClauseKind::PCopyOut ||
542 ClauseKind == OpenACCClauseKind::Create ||
543 ClauseKind == OpenACCClauseKind::PCreate ||
545 ClauseKind == OpenACCClauseKind::Attach ||
546 ClauseKind == OpenACCClauseKind::Delete ||
547 ClauseKind == OpenACCClauseKind::UseDevice ||
548 ClauseKind == OpenACCClauseKind::Detach ||
549 ClauseKind == OpenACCClauseKind::DevicePtr ||
550 ClauseKind == OpenACCClauseKind::FirstPrivate) &&
551 "Parsed clause kind does not have a var-list");
552 assert((!IsReadOnly || ClauseKind == OpenACCClauseKind::CopyIn ||
553 ClauseKind == OpenACCClauseKind::PCopyIn ||
554 ClauseKind == OpenACCClauseKind::PresentOrCopyIn) &&
555 "readonly: tag only valid on copyin");
556 assert((!IsZero || ClauseKind == OpenACCClauseKind::CopyOut ||
557 ClauseKind == OpenACCClauseKind::PCopyOut ||
559 ClauseKind == OpenACCClauseKind::Create ||
560 ClauseKind == OpenACCClauseKind::PCreate ||
561 ClauseKind == OpenACCClauseKind::PresentOrCreate) &&
562 "zero: tag only valid on copyout/create");
563 Details =
564 VarListDetails{{VarList.begin(), VarList.end()}, IsReadOnly, IsZero};
565 }
566
567 void setVarListDetails(llvm::SmallVector<Expr *> &&VarList, bool IsReadOnly,
568 bool IsZero) {
569 assert((ClauseKind == OpenACCClauseKind::Private ||
570 ClauseKind == OpenACCClauseKind::NoCreate ||
571 ClauseKind == OpenACCClauseKind::Present ||
572 ClauseKind == OpenACCClauseKind::Copy ||
573 ClauseKind == OpenACCClauseKind::PCopy ||
574 ClauseKind == OpenACCClauseKind::PresentOrCopy ||
575 ClauseKind == OpenACCClauseKind::CopyIn ||
576 ClauseKind == OpenACCClauseKind::PCopyIn ||
578 ClauseKind == OpenACCClauseKind::CopyOut ||
579 ClauseKind == OpenACCClauseKind::PCopyOut ||
581 ClauseKind == OpenACCClauseKind::Create ||
582 ClauseKind == OpenACCClauseKind::PCreate ||
584 ClauseKind == OpenACCClauseKind::Attach ||
585 ClauseKind == OpenACCClauseKind::Delete ||
586 ClauseKind == OpenACCClauseKind::UseDevice ||
587 ClauseKind == OpenACCClauseKind::Detach ||
588 ClauseKind == OpenACCClauseKind::DevicePtr ||
589 ClauseKind == OpenACCClauseKind::FirstPrivate) &&
590 "Parsed clause kind does not have a var-list");
591 assert((!IsReadOnly || ClauseKind == OpenACCClauseKind::CopyIn ||
592 ClauseKind == OpenACCClauseKind::PCopyIn ||
593 ClauseKind == OpenACCClauseKind::PresentOrCopyIn) &&
594 "readonly: tag only valid on copyin");
595 assert((!IsZero || ClauseKind == OpenACCClauseKind::CopyOut ||
596 ClauseKind == OpenACCClauseKind::PCopyOut ||
598 ClauseKind == OpenACCClauseKind::Create ||
599 ClauseKind == OpenACCClauseKind::PCreate ||
600 ClauseKind == OpenACCClauseKind::PresentOrCreate) &&
601 "zero: tag only valid on copyout/create");
602 Details = VarListDetails{std::move(VarList), IsReadOnly, IsZero};
603 }
604
606 llvm::SmallVector<Expr *> &&VarList) {
607 assert(ClauseKind == OpenACCClauseKind::Reduction &&
608 "reduction details only valid on reduction");
609 Details = ReductionDetails{Op, std::move(VarList)};
610 }
611
612 void setWaitDetails(Expr *DevNum, SourceLocation QueuesLoc,
613 llvm::SmallVector<Expr *> &&IntExprs) {
614 assert(ClauseKind == OpenACCClauseKind::Wait &&
615 "Parsed clause kind does not have a wait-details");
616 Details = WaitDetails{DevNum, QueuesLoc, std::move(IntExprs)};
617 }
618
620 assert((ClauseKind == OpenACCClauseKind::DeviceType ||
621 ClauseKind == OpenACCClauseKind::DType) &&
622 "Only 'device_type'/'dtype' has a device-type-arg list");
623 Details = DeviceTypeDetails{std::move(Archs)};
624 }
625
626 void setCollapseDetails(bool IsForce, Expr *LoopCount) {
627 assert(ClauseKind == OpenACCClauseKind::Collapse &&
628 "Only 'collapse' has collapse details");
629 Details = CollapseDetails{IsForce, LoopCount};
630 }
631 };
632
633 SemaOpenACC(Sema &S);
634
635 // Called when we encounter a 'while' statement, before looking at its 'body'.
636 void ActOnWhileStmt(SourceLocation WhileLoc);
637 // Called when we encounter a 'do' statement, before looking at its 'body'.
638 void ActOnDoStmt(SourceLocation DoLoc);
639 // Called when we encounter a 'for' statement, before looking at its 'body',
640 // for the 'range-for'. 'ActOnForStmtEnd' is used after the body.
641 void ActOnRangeForStmtBegin(SourceLocation ForLoc, const Stmt *OldRangeFor,
642 const Stmt *RangeFor);
643 void ActOnRangeForStmtBegin(SourceLocation ForLoc, const Stmt *RangeFor);
644 // Called when we encounter a 'for' statement, before looking at its 'body'.
645 // 'ActOnForStmtEnd' is used after the body.
646 void ActOnForStmtBegin(SourceLocation ForLoc, const Stmt *First,
647 const Stmt *Second, const Stmt *Third);
648 void ActOnForStmtBegin(SourceLocation ForLoc, const Stmt *OldFirst,
649 const Stmt *First, const Stmt *OldSecond,
650 const Stmt *Second, const Stmt *OldThird,
651 const Stmt *Third);
652 // Called when we encounter a 'for' statement, after we've consumed/checked
653 // the body. This is necessary for a number of checks on the contents of the
654 // 'for' statement.
655 void ActOnForStmtEnd(SourceLocation ForLoc, StmtResult Body);
656
657 /// Called after parsing an OpenACC Clause so that it can be checked.
659 OpenACCParsedClause &Clause);
660
661 /// Called after the construct has been parsed, but clauses haven't been
662 /// parsed. This allows us to diagnose not-implemented, as well as set up any
663 /// state required for parsing the clauses.
665
666 /// Called after the directive, including its clauses, have been parsed and
667 /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES
668 /// happen before any associated declarations or statements have been parsed.
669 /// This function is only called when we are parsing a 'statement' context.
672
673 /// Called after the directive, including its clauses, have been parsed and
674 /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES
675 /// happen before any associated declarations or statements have been parsed.
676 /// This function is only called when we are parsing a 'Decl' context.
678 /// Called when we encounter an associated statement for our construct, this
679 /// should check legality of the statement as it appertains to this Construct.
683 StmtResult AssocStmt);
684
685 /// Called after the directive has been completely parsed, including the
686 /// declaration group or associated statement.
687 /// LParenLoc: Location of the left paren, if it exists (not on all
688 /// constructs).
689 /// MiscLoc: First misc location, if necessary (not all constructs).
690 /// Exprs: List of expressions on the construct itself, if necessary (not all
691 /// constructs).
692 /// RParenLoc: Location of the right paren, if it exists (not on all
693 /// constructs).
696 SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef<Expr *> Exprs,
697 SourceLocation RParenLoc, SourceLocation EndLoc,
698 ArrayRef<OpenACCClause *> Clauses, StmtResult AssocStmt);
699
700 /// Called after the directive has been completely parsed, including the
701 /// declaration group or associated statement.
703
704 /// Called when encountering an 'int-expr' for OpenACC, and manages
705 /// conversions and diagnostics to 'int'.
707 SourceLocation Loc, Expr *IntExpr);
708
709 /// Called when encountering a 'var' for OpenACC, ensures it is actually a
710 /// declaration reference to a variable of the correct type.
712
713 /// Called while semantically analyzing the reduction clause, ensuring the var
714 /// is the correct kind of reference.
716 OpenACCReductionOperator ReductionOp,
717 Expr *VarExpr);
718
719 /// Called to check the 'var' type is a variable of pointer type, necessary
720 /// for 'deviceptr' and 'attach' clauses. Returns true on success.
721 bool CheckVarIsPointerType(OpenACCClauseKind ClauseKind, Expr *VarExpr);
722
723 /// Checks and creates an Array Section used in an OpenACC construct/clause.
725 Expr *LowerBound,
726 SourceLocation ColonLocFirst, Expr *Length,
727 SourceLocation RBLoc);
728 /// Checks the loop depth value for a collapse clause.
730 /// Checks a single size expr for a tile clause.
732
733 // Check a single expression on a gang clause.
736 Expr *E);
737
738 // Does the checking for a 'gang' clause that needs to be done in dependent
739 // and not dependent cases.
742 ArrayRef<const OpenACCClause *> ExistingClauses,
743 SourceLocation BeginLoc, SourceLocation LParenLoc,
745 ArrayRef<Expr *> IntExprs, SourceLocation EndLoc);
746 // Does the checking for a 'reduction ' clause that needs to be done in
747 // dependent and not dependent cases.
750 OpenACCDirectiveKind DirectiveKind,
751 SourceLocation BeginLoc, SourceLocation LParenLoc,
752 OpenACCReductionOperator ReductionOp,
753 ArrayRef<Expr *> Vars, SourceLocation EndLoc);
754
757
758 /// Helper type to restore the state of various 'loop' constructs when we run
759 /// into a loop (for, etc) inside the construct.
761 SemaOpenACC &SemaRef;
762 LoopCheckingInfo OldLoopInfo;
763 CollapseCheckingInfo OldCollapseInfo;
764 TileCheckingInfo OldTileInfo;
765 bool PreserveDepth;
766
767 public:
768 LoopInConstructRAII(SemaOpenACC &SemaRef, bool PreserveDepth = true)
769 : SemaRef(SemaRef), OldLoopInfo(SemaRef.LoopInfo),
770 OldCollapseInfo(SemaRef.CollapseInfo), OldTileInfo(SemaRef.TileInfo),
771 PreserveDepth(PreserveDepth) {}
773 // The associated-statement level of this should NOT preserve this, as it
774 // is a new construct, but other loop uses need to preserve the depth so
775 // it makes it to the 'top level' for diagnostics.
776 bool CollapseDepthSatisified =
777 PreserveDepth ? SemaRef.CollapseInfo.CollapseDepthSatisfied
778 : OldCollapseInfo.CollapseDepthSatisfied;
779 bool TileDepthSatisfied = PreserveDepth
780 ? SemaRef.TileInfo.TileDepthSatisfied
781 : OldTileInfo.TileDepthSatisfied;
782 bool CurLevelHasLoopAlready =
783 PreserveDepth ? SemaRef.LoopInfo.CurLevelHasLoopAlready
784 : OldLoopInfo.CurLevelHasLoopAlready;
785
786 SemaRef.LoopInfo = OldLoopInfo;
787 SemaRef.CollapseInfo = OldCollapseInfo;
788 SemaRef.TileInfo = OldTileInfo;
789
790 SemaRef.CollapseInfo.CollapseDepthSatisfied = CollapseDepthSatisified;
791 SemaRef.TileInfo.TileDepthSatisfied = TileDepthSatisfied;
792 SemaRef.LoopInfo.CurLevelHasLoopAlready = CurLevelHasLoopAlready;
793 }
794 };
795
796 /// Helper type for the registration/assignment of constructs that need to
797 /// 'know' about their parent constructs and hold a reference to them, such as
798 /// Loop needing its parent construct.
800 SemaOpenACC &SemaRef;
801 ComputeConstructInfo OldActiveComputeConstructInfo;
802 OpenACCDirectiveKind DirKind;
803 LoopGangOnKernelTy OldLoopGangClauseOnKernel;
804 SourceLocation OldLoopWorkerClauseLoc;
805 SourceLocation OldLoopVectorClauseLoc;
806 LoopWithoutSeqCheckingInfo OldLoopWithoutSeqInfo;
807 llvm::SmallVector<OpenACCReductionClause *> ActiveReductionClauses;
808 LoopInConstructRAII LoopRAII;
809
810 public:
821 };
822};
823
824} // namespace clang
825
826#endif // LLVM_CLANG_SEMA_SEMAOPENACC_H
Expr * E
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines some OpenACC-specific enums and functions.
SourceLocation Loc
Definition: SemaObjC.cpp:759
Defines the clang::SourceLocation class and associated facilities.
This file defines OpenACC AST classes for statement-level contructs.
This represents one expression.
Definition: Expr.h:110
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition: Expr.h:221
QualType getType() const
Definition: Expr.h:142
This is the base type for all OpenACC Clauses.
Definition: OpenACCClause.h:24
Represents a 'collapse' clause on a 'loop' construct.
Helper type for the registration/assignment of constructs that need to 'know' about their parent cons...
Definition: SemaOpenACC.h:799
void SetTileInfoBeforeAssociatedStmt(ArrayRef< const OpenACCClause * > UnInstClauses, ArrayRef< OpenACCClause * > Clauses)
void SetCollapseInfoBeforeAssociatedStmt(ArrayRef< const OpenACCClause * > UnInstClauses, ArrayRef< OpenACCClause * > Clauses)
Helper type to restore the state of various 'loop' constructs when we run into a loop (for,...
Definition: SemaOpenACC.h:760
LoopInConstructRAII(SemaOpenACC &SemaRef, bool PreserveDepth=true)
Definition: SemaOpenACC.h:768
A type to represent all the data for an OpenACC Clause that has been parsed, but not yet created/sema...
Definition: SemaOpenACC.h:202
ArrayRef< Expr * > getQueueIdExprs() const
Definition: SemaOpenACC.h:337
OpenACCDirectiveKind getDirectiveKind() const
Definition: SemaOpenACC.h:260
ArrayRef< OpenACCGangKind > getGangKinds() const
Definition: SemaOpenACC.h:378
OpenACCParsedClause(OpenACCDirectiveKind DirKind, OpenACCClauseKind ClauseKind, SourceLocation BeginLoc)
Definition: SemaOpenACC.h:256
OpenACCReductionOperator getReductionOp() const
Definition: SemaOpenACC.h:374
void setLParenLoc(SourceLocation EndLoc)
Definition: SemaOpenACC.h:461
void setConditionDetails(Expr *ConditionExpr)
Definition: SemaOpenACC.h:470
void setCollapseDetails(bool IsForce, Expr *LoopCount)
Definition: SemaOpenACC.h:626
OpenACCClauseKind getClauseKind() const
Definition: SemaOpenACC.h:262
void setGangDetails(ArrayRef< OpenACCGangKind > GKs, ArrayRef< Expr * > IntExprs)
Definition: SemaOpenACC.h:509
SourceLocation getLParenLoc() const
Definition: SemaOpenACC.h:266
ArrayRef< DeviceTypeArgument > getDeviceTypeArchitectures() const
Definition: SemaOpenACC.h:454
void setIntExprDetails(llvm::SmallVector< Expr * > &&IntExprs)
Definition: SemaOpenACC.h:496
void setReductionDetails(OpenACCReductionOperator Op, llvm::SmallVector< Expr * > &&VarList)
Definition: SemaOpenACC.h:605
ArrayRef< Expr * > getVarList() const
Definition: SemaOpenACC.h:419
SourceLocation getBeginLoc() const
Definition: SemaOpenACC.h:264
void setDefaultDetails(OpenACCDefaultClauseKind DefKind)
Definition: SemaOpenACC.h:464
SourceLocation getQueuesLoc() const
Definition: SemaOpenACC.h:317
void setVarListDetails(llvm::SmallVector< Expr * > &&VarList, bool IsReadOnly, bool IsZero)
Definition: SemaOpenACC.h:567
void setVarListDetails(ArrayRef< Expr * > VarList, bool IsReadOnly, bool IsZero)
Definition: SemaOpenACC.h:528
void setWaitDetails(Expr *DevNum, SourceLocation QueuesLoc, llvm::SmallVector< Expr * > &&IntExprs)
Definition: SemaOpenACC.h:612
void setEndLoc(SourceLocation EndLoc)
Definition: SemaOpenACC.h:462
ArrayRef< Expr * > getIntExprs() const
Definition: SemaOpenACC.h:370
void setIntExprDetails(ArrayRef< Expr * > IntExprs)
Definition: SemaOpenACC.h:484
void setDeviceTypeDetails(llvm::SmallVector< DeviceTypeArgument > &&Archs)
Definition: SemaOpenACC.h:619
void setGangDetails(llvm::SmallVector< OpenACCGangKind > &&GKs, llvm::SmallVector< Expr * > &&IntExprs)
Definition: SemaOpenACC.h:519
OpenACCDefaultClauseKind getDefaultClauseKind() const
Definition: SemaOpenACC.h:270
ExprResult ActOnVar(OpenACCClauseKind CK, Expr *VarExpr)
Called when encountering a 'var' for OpenACC, ensures it is actually a declaration reference to a var...
ComputeConstructInfo & getActiveComputeConstructInfo()
Definition: SemaOpenACC.h:162
bool ActOnStartStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, ArrayRef< const OpenACCClause * > Clauses)
Called after the directive, including its clauses, have been parsed and parsing has consumed the 'ann...
ExprResult BuildOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc)
ExprResult ActOnIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK, SourceLocation Loc, Expr *IntExpr)
Called when encountering an 'int-expr' for OpenACC, and manages conversions and diagnostics to 'int'.
void ActOnWhileStmt(SourceLocation WhileLoc)
SourceLocation LoopWorkerClauseLoc
If there is a current 'active' loop construct with a 'worker' clause on it (on any sort of construct)...
Definition: SemaOpenACC.h:179
OpenACCClause * ActOnClause(ArrayRef< const OpenACCClause * > ExistingClauses, OpenACCParsedClause &Clause)
Called after parsing an OpenACC Clause so that it can be checked.
bool ActOnStartDeclDirective(OpenACCDirectiveKind K, SourceLocation StartLoc)
Called after the directive, including its clauses, have been parsed and parsing has consumed the 'ann...
bool CheckVarIsPointerType(OpenACCClauseKind ClauseKind, Expr *VarExpr)
Called to check the 'var' type is a variable of pointer type, necessary for 'deviceptr' and 'attach' ...
struct clang::SemaOpenACC::LoopGangOnKernelTy LoopGangClauseOnKernel
ExprResult CheckReductionVar(OpenACCDirectiveKind DirectiveKind, OpenACCReductionOperator ReductionOp, Expr *VarExpr)
Called while semantically analyzing the reduction clause, ensuring the var is the correct kind of ref...
ExprResult CheckCollapseLoopCount(Expr *LoopCount)
Checks the loop depth value for a collapse clause.
struct clang::SemaOpenACC::LoopWithoutSeqCheckingInfo LoopWithoutSeqInfo
StmtResult ActOnEndStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef< Expr * > Exprs, SourceLocation RParenLoc, SourceLocation EndLoc, ArrayRef< OpenACCClause * > Clauses, StmtResult AssocStmt)
Called after the directive has been completely parsed, including the declaration group or associated ...
DeclGroupRef ActOnEndDeclDirective()
Called after the directive has been completely parsed, including the declaration group or associated ...
OpenACCClause * CheckReductionClause(ArrayRef< const OpenACCClause * > ExistingClauses, OpenACCDirectiveKind DirectiveKind, SourceLocation BeginLoc, SourceLocation LParenLoc, OpenACCReductionOperator ReductionOp, ArrayRef< Expr * > Vars, SourceLocation EndLoc)
std::pair< IdentifierInfo *, SourceLocation > DeviceTypeArgument
Definition: SemaOpenACC.h:196
SourceLocation LoopVectorClauseLoc
If there is a current 'active' loop construct with a 'vector' clause on it (on any sort of construct)...
Definition: SemaOpenACC.h:184
void ActOnConstruct(OpenACCDirectiveKind K, SourceLocation DirLoc)
Called after the construct has been parsed, but clauses haven't been parsed.
ExprResult ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc)
ExprResult CheckGangExpr(ArrayRef< const OpenACCClause * > ExistingClauses, OpenACCDirectiveKind DK, OpenACCGangKind GK, Expr *E)
void ActOnDoStmt(SourceLocation DoLoc)
void ActOnRangeForStmtBegin(SourceLocation ForLoc, const Stmt *OldRangeFor, const Stmt *RangeFor)
void ActOnForStmtEnd(SourceLocation ForLoc, StmtResult Body)
OpenACCClause * CheckGangClause(OpenACCDirectiveKind DirKind, ArrayRef< const OpenACCClause * > ExistingClauses, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef< OpenACCGangKind > GangKinds, ArrayRef< Expr * > IntExprs, SourceLocation EndLoc)
StmtResult ActOnAssociatedStmt(SourceLocation DirectiveLoc, OpenACCDirectiveKind K, ArrayRef< const OpenACCClause * > Clauses, StmtResult AssocStmt)
Called when we encounter an associated statement for our construct, this should check legality of the...
void ActOnForStmtBegin(SourceLocation ForLoc, const Stmt *First, const Stmt *Second, const Stmt *Third)
ExprResult ActOnArraySectionExpr(Expr *Base, SourceLocation LBLoc, Expr *LowerBound, SourceLocation ColonLocFirst, Expr *Length, SourceLocation RBLoc)
Checks and creates an Array Section used in an OpenACC construct/clause.
ExprResult CheckTileSizeExpr(Expr *SizeExpr)
Checks a single size expr for a tile clause.
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:463
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
void setEnd(SourceLocation e)
Stmt - This represents one statement.
Definition: Stmt.h:84
bool isScalarType() const
Definition: Type.h:8609
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:671
The JSON file list parser is used to communicate input to InstallAPI.
OpenACCDirectiveKind
Definition: OpenACCKinds.h:25
OpenACCReductionOperator
Definition: OpenACCKinds.h:509
OpenACCClauseKind
Represents the kind of an OpenACC clause.
Definition: OpenACCKinds.h:178
@ Gang
'gang' clause, allowed on 'loop' and Combined constructs.
@ Wait
'wait' clause, allowed on Compute, Data, 'update', and Combined constructs.
@ DevicePtr
'deviceptr' clause, allowed on Compute and Combined Constructs, plus 'data' and 'declare'.
@ PCopyOut
'copyout' clause alias 'pcopyout'. Preserved for diagnostic purposes.
@ VectorLength
'vector_length' clause, allowed on 'parallel', 'kernels', 'parallel loop', and 'kernels loop' constru...
@ Async
'async' clause, allowed on Compute, Data, 'update', 'wait', and Combined constructs.
@ PresentOrCreate
'create' clause alias 'present_or_create'.
@ Collapse
'collapse' clause, allowed on 'loop' and Combined constructs.
@ PresentOrCopy
'copy' clause alias 'present_or_copy'. Preserved for diagnostic purposes.
@ DeviceNum
'device_num' clause, allowed on 'init', 'shutdown', and 'set' constructs.
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
@ Vector
'vector' clause, allowed on 'loop', Combined, and 'routine' directives.
@ Copy
'copy' clause, allowed on Compute and Combined Constructs, plus 'data' and 'declare'.
@ Worker
'worker' clause, allowed on 'loop', Combined, and 'routine' directives.
@ Create
'create' clause, allowed on Compute and Combined constructs, plus 'data', 'enter data',...
@ DeviceType
'device_type' clause, allowed on Compute, 'data', 'init', 'shutdown', 'set', update',...
@ Attach
'attach' clause, allowed on Compute and Combined constructs, plus 'data' and 'enter data'.
@ NumGangs
'num_gangs' clause, allowed on 'parallel', 'kernels', parallel loop', and 'kernels loop' constructs.
@ If
'if' clause, allowed on all the Compute Constructs, Data Constructs, Executable Constructs,...
@ Default
'default' clause, allowed on parallel, serial, kernel (and compound) constructs.
@ UseDevice
'use_device' clause, allowed on 'host_data' construct.
@ NoCreate
'no_create' clause, allowed on allowed on Compute and Combined constructs, plus 'data'.
@ PresentOrCopyOut
'copyout' clause alias 'present_or_copyout'.
@ Reduction
'reduction' clause, allowed on Parallel, Serial, Loop, and the combined constructs.
@ Self
'self' clause, allowed on Compute and Combined Constructs, plus 'update'.
@ CopyOut
'copyout' clause, allowed on Compute and Combined constructs, plus 'data', 'exit data',...
@ FirstPrivate
'firstprivate' clause, allowed on 'parallel', 'serial', 'parallel loop', and 'serial loop' constructs...
@ PCopy
'copy' clause alias 'pcopy'. Preserved for diagnostic purposes.
@ Tile
'tile' clause, allowed on 'loop' and Combined constructs.
@ PCopyIn
'copyin' clause alias 'pcopyin'. Preserved for diagnostic purposes.
@ PCreate
'create' clause alias 'pcreate'. Preserved for diagnostic purposes.
@ Present
'present' clause, allowed on Compute and Combined constructs, plus 'data' and 'declare'.
@ DType
'dtype' clause, an alias for 'device_type', stored separately for diagnostic purposes.
@ CopyIn
'copyin' clause, allowed on Compute and Combined constructs, plus 'data', 'enter data',...
@ NumWorkers
'num_workers' clause, allowed on 'parallel', 'kernels', parallel loop', and 'kernels loop' constructs...
@ Detach
'detach' clause, allowed on the 'exit data' construct.
@ Delete
'delete' clause, allowed on the 'exit data' construct.
@ PresentOrCopyIn
'copyin' clause alias 'present_or_copyin'.
OpenACCDefaultClauseKind
Definition: OpenACCKinds.h:476
OpenACCGangKind
Definition: OpenACCKinds.h:568
If there is a current 'active' loop construct with a 'gang' clause on a 'kernel' construct,...
Definition: SemaOpenACC.h:170
If there is a current 'active' loop construct that does NOT have a 'seq' clause on it,...
Definition: SemaOpenACC.h:190