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" 18 #include "clang/AST/StmtOpenACC.h" 19 #include "clang/Basic/LLVM.h" 20 #include "clang/Basic/OpenACCKinds.h" 21 #include "clang/Basic/SourceLocation.h" 22 #include "clang/Sema/Ownership.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 31 namespace clang { 32 class IdentifierInfo; 33 class OpenACCClause; 34 35 class SemaOpenACC : public SemaBase { 36 private: 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. 41 OpenACCDirectiveKind Kind = OpenACCDirectiveKind::Invalid; 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. 44 ArrayRef<OpenACCClause *> Clauses; 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. 93 OpenACCDirectiveKind DirectiveKind = OpenACCDirectiveKind::Invalid; 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. 113 OpenACCDirectiveKind DirectiveKind = OpenACCDirectiveKind::Invalid; 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 161 public: 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. 170 struct LoopGangOnKernelTy { 171 SourceLocation Loc; 172 OpenACCDirectiveKind DirKind = OpenACCDirectiveKind::Invalid; 173 } LoopGangClauseOnKernel; 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. 179 SourceLocation LoopWorkerClauseLoc; 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. 184 SourceLocation LoopVectorClauseLoc; 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. 190 struct LoopWithoutSeqCheckingInfo { 191 OpenACCDirectiveKind Kind = OpenACCDirectiveKind::Invalid; 192 SourceLocation Loc; 193 } LoopWithoutSeqInfo; 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. 202 class OpenACCParsedClause { 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 { 233 SmallVector<DeviceTypeArgument> Archs; 234 }; 235 struct ReductionDetails { 236 OpenACCReductionOperator Op; 237 SmallVector<Expr *> VarList; 238 }; 239 240 struct CollapseDetails { 241 bool IsForce; 242 Expr *LoopCount; 243 }; 244 245 struct GangDetails { 246 SmallVector<OpenACCGangKind> GangKinds; 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: 256 OpenACCParsedClause(OpenACCDirectiveKind DirKind, 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 270 OpenACCDefaultClauseKind getDefaultClauseKind() const { 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 280 Expr *getConditionExpr() { 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::DefaultAsync || 301 ClauseKind == OpenACCClauseKind::Tile || 302 ClauseKind == OpenACCClauseKind::Worker || 303 ClauseKind == OpenACCClauseKind::Vector || 304 ClauseKind == OpenACCClauseKind::VectorLength) && 305 "Parsed clause kind does not have a int exprs"); 306 307 // 'async', 'worker', 'vector', and 'wait' have an optional IntExpr, so be 308 // tolerant of that. 309 if ((ClauseKind == OpenACCClauseKind::Async || 310 ClauseKind == OpenACCClauseKind::Worker || 311 ClauseKind == OpenACCClauseKind::Vector || 312 ClauseKind == OpenACCClauseKind::Wait) && 313 std::holds_alternative<std::monostate>(Details)) 314 return 0; 315 return std::get<IntExprDetails>(Details).IntExprs.size(); 316 } 317 318 SourceLocation getQueuesLoc() const { 319 assert(ClauseKind == OpenACCClauseKind::Wait && 320 "Parsed clause kind does not have a queues location"); 321 322 if (std::holds_alternative<std::monostate>(Details)) 323 return SourceLocation{}; 324 325 return std::get<WaitDetails>(Details).QueuesLoc; 326 } 327 328 Expr *getDevNumExpr() const { 329 assert(ClauseKind == OpenACCClauseKind::Wait && 330 "Parsed clause kind does not have a device number expr"); 331 332 if (std::holds_alternative<std::monostate>(Details)) 333 return nullptr; 334 335 return std::get<WaitDetails>(Details).DevNumExpr; 336 } 337 338 ArrayRef<Expr *> getQueueIdExprs() const { 339 assert(ClauseKind == OpenACCClauseKind::Wait && 340 "Parsed clause kind does not have a queue id expr list"); 341 342 if (std::holds_alternative<std::monostate>(Details)) 343 return ArrayRef<Expr *>(); 344 345 return std::get<WaitDetails>(Details).QueueIdExprs; 346 } 347 348 ArrayRef<Expr *> getIntExprs() { 349 assert((ClauseKind == OpenACCClauseKind::NumGangs || 350 ClauseKind == OpenACCClauseKind::NumWorkers || 351 ClauseKind == OpenACCClauseKind::Async || 352 ClauseKind == OpenACCClauseKind::DeviceNum || 353 ClauseKind == OpenACCClauseKind::DefaultAsync || 354 ClauseKind == OpenACCClauseKind::Tile || 355 ClauseKind == OpenACCClauseKind::Gang || 356 ClauseKind == OpenACCClauseKind::Worker || 357 ClauseKind == OpenACCClauseKind::Vector || 358 ClauseKind == OpenACCClauseKind::VectorLength) && 359 "Parsed clause kind does not have a int exprs"); 360 361 if (ClauseKind == OpenACCClauseKind::Gang) { 362 // There might not be any gang int exprs, as this is an optional 363 // argument. 364 if (std::holds_alternative<std::monostate>(Details)) 365 return {}; 366 return std::get<GangDetails>(Details).IntExprs; 367 } 368 369 return std::get<IntExprDetails>(Details).IntExprs; 370 } 371 372 ArrayRef<Expr *> getIntExprs() const { 373 return const_cast<OpenACCParsedClause *>(this)->getIntExprs(); 374 } 375 376 OpenACCReductionOperator getReductionOp() const { 377 return std::get<ReductionDetails>(Details).Op; 378 } 379 380 ArrayRef<OpenACCGangKind> getGangKinds() const { 381 assert(ClauseKind == OpenACCClauseKind::Gang && 382 "Parsed clause kind does not have gang kind"); 383 // The args on gang are optional, so this might not actually hold 384 // anything. 385 if (std::holds_alternative<std::monostate>(Details)) 386 return {}; 387 return std::get<GangDetails>(Details).GangKinds; 388 } 389 390 ArrayRef<Expr *> getVarList() { 391 assert((ClauseKind == OpenACCClauseKind::Private || 392 ClauseKind == OpenACCClauseKind::NoCreate || 393 ClauseKind == OpenACCClauseKind::Present || 394 ClauseKind == OpenACCClauseKind::Copy || 395 ClauseKind == OpenACCClauseKind::PCopy || 396 ClauseKind == OpenACCClauseKind::PresentOrCopy || 397 ClauseKind == OpenACCClauseKind::CopyIn || 398 ClauseKind == OpenACCClauseKind::PCopyIn || 399 ClauseKind == OpenACCClauseKind::PresentOrCopyIn || 400 ClauseKind == OpenACCClauseKind::CopyOut || 401 ClauseKind == OpenACCClauseKind::PCopyOut || 402 ClauseKind == OpenACCClauseKind::PresentOrCopyOut || 403 ClauseKind == OpenACCClauseKind::Create || 404 ClauseKind == OpenACCClauseKind::PCreate || 405 ClauseKind == OpenACCClauseKind::PresentOrCreate || 406 ClauseKind == OpenACCClauseKind::Attach || 407 ClauseKind == OpenACCClauseKind::Delete || 408 ClauseKind == OpenACCClauseKind::UseDevice || 409 ClauseKind == OpenACCClauseKind::Detach || 410 ClauseKind == OpenACCClauseKind::DevicePtr || 411 ClauseKind == OpenACCClauseKind::Reduction || 412 ClauseKind == OpenACCClauseKind::Host || 413 ClauseKind == OpenACCClauseKind::Device || 414 (ClauseKind == OpenACCClauseKind::Self && 415 DirKind == OpenACCDirectiveKind::Update) || 416 ClauseKind == OpenACCClauseKind::FirstPrivate) && 417 "Parsed clause kind does not have a var-list"); 418 419 if (ClauseKind == OpenACCClauseKind::Reduction) 420 return std::get<ReductionDetails>(Details).VarList; 421 422 return std::get<VarListDetails>(Details).VarList; 423 } 424 425 ArrayRef<Expr *> getVarList() const { 426 return const_cast<OpenACCParsedClause *>(this)->getVarList(); 427 } 428 429 bool isReadOnly() const { 430 assert((ClauseKind == OpenACCClauseKind::CopyIn || 431 ClauseKind == OpenACCClauseKind::PCopyIn || 432 ClauseKind == OpenACCClauseKind::PresentOrCopyIn) && 433 "Only copyin accepts 'readonly:' tag"); 434 return std::get<VarListDetails>(Details).IsReadOnly; 435 } 436 437 bool isZero() const { 438 assert((ClauseKind == OpenACCClauseKind::CopyOut || 439 ClauseKind == OpenACCClauseKind::PCopyOut || 440 ClauseKind == OpenACCClauseKind::PresentOrCopyOut || 441 ClauseKind == OpenACCClauseKind::Create || 442 ClauseKind == OpenACCClauseKind::PCreate || 443 ClauseKind == OpenACCClauseKind::PresentOrCreate) && 444 "Only copyout/create accepts 'zero' tag"); 445 return std::get<VarListDetails>(Details).IsZero; 446 } 447 448 bool isForce() const { 449 assert(ClauseKind == OpenACCClauseKind::Collapse && 450 "Only 'collapse' has a force tag"); 451 return std::get<CollapseDetails>(Details).IsForce; 452 } 453 454 Expr *getLoopCount() const { 455 assert(ClauseKind == OpenACCClauseKind::Collapse && 456 "Only 'collapse' has a loop count"); 457 return std::get<CollapseDetails>(Details).LoopCount; 458 } 459 460 ArrayRef<DeviceTypeArgument> getDeviceTypeArchitectures() const { 461 assert((ClauseKind == OpenACCClauseKind::DeviceType || 462 ClauseKind == OpenACCClauseKind::DType) && 463 "Only 'device_type'/'dtype' has a device-type-arg list"); 464 return std::get<DeviceTypeDetails>(Details).Archs; 465 } 466 467 void setLParenLoc(SourceLocation EndLoc) { LParenLoc = EndLoc; } 468 void setEndLoc(SourceLocation EndLoc) { ClauseRange.setEnd(EndLoc); } 469 470 void setDefaultDetails(OpenACCDefaultClauseKind DefKind) { 471 assert(ClauseKind == OpenACCClauseKind::Default && 472 "Parsed clause is not a default clause"); 473 Details = DefaultDetails{DefKind}; 474 } 475 476 void setConditionDetails(Expr *ConditionExpr) { 477 assert((ClauseKind == OpenACCClauseKind::If || 478 (ClauseKind == OpenACCClauseKind::Self && 479 DirKind != OpenACCDirectiveKind::Update)) && 480 "Parsed clause kind does not have a condition expr"); 481 // In C++ we can count on this being a 'bool', but in C this gets left as 482 // some sort of scalar that codegen will have to take care of converting. 483 assert((!ConditionExpr || ConditionExpr->isInstantiationDependent() || 484 ConditionExpr->getType()->isScalarType()) && 485 "Condition expression type not scalar/dependent"); 486 487 Details = ConditionDetails{ConditionExpr}; 488 } 489 490 void setIntExprDetails(ArrayRef<Expr *> IntExprs) { 491 assert((ClauseKind == OpenACCClauseKind::NumGangs || 492 ClauseKind == OpenACCClauseKind::NumWorkers || 493 ClauseKind == OpenACCClauseKind::Async || 494 ClauseKind == OpenACCClauseKind::DeviceNum || 495 ClauseKind == OpenACCClauseKind::DefaultAsync || 496 ClauseKind == OpenACCClauseKind::Tile || 497 ClauseKind == OpenACCClauseKind::Worker || 498 ClauseKind == OpenACCClauseKind::Vector || 499 ClauseKind == OpenACCClauseKind::VectorLength) && 500 "Parsed clause kind does not have a int exprs"); 501 Details = IntExprDetails{{IntExprs.begin(), IntExprs.end()}}; 502 } 503 void setIntExprDetails(llvm::SmallVector<Expr *> &&IntExprs) { 504 assert((ClauseKind == OpenACCClauseKind::NumGangs || 505 ClauseKind == OpenACCClauseKind::NumWorkers || 506 ClauseKind == OpenACCClauseKind::Async || 507 ClauseKind == OpenACCClauseKind::DeviceNum || 508 ClauseKind == OpenACCClauseKind::DefaultAsync || 509 ClauseKind == OpenACCClauseKind::Tile || 510 ClauseKind == OpenACCClauseKind::Worker || 511 ClauseKind == OpenACCClauseKind::Vector || 512 ClauseKind == OpenACCClauseKind::VectorLength) && 513 "Parsed clause kind does not have a int exprs"); 514 Details = IntExprDetails{std::move(IntExprs)}; 515 } 516 517 void setGangDetails(ArrayRef<OpenACCGangKind> GKs, 518 ArrayRef<Expr *> IntExprs) { 519 assert(ClauseKind == OpenACCClauseKind::Gang && 520 "Parsed Clause kind does not have gang details"); 521 assert(GKs.size() == IntExprs.size() && "Mismatched kind/size?"); 522 523 Details = GangDetails{{GKs.begin(), GKs.end()}, 524 {IntExprs.begin(), IntExprs.end()}}; 525 } 526 527 void setGangDetails(llvm::SmallVector<OpenACCGangKind> &&GKs, 528 llvm::SmallVector<Expr *> &&IntExprs) { 529 assert(ClauseKind == OpenACCClauseKind::Gang && 530 "Parsed Clause kind does not have gang details"); 531 assert(GKs.size() == IntExprs.size() && "Mismatched kind/size?"); 532 533 Details = GangDetails{std::move(GKs), std::move(IntExprs)}; 534 } 535 536 void setVarListDetails(ArrayRef<Expr *> VarList, bool IsReadOnly, 537 bool IsZero) { 538 assert((ClauseKind == OpenACCClauseKind::Private || 539 ClauseKind == OpenACCClauseKind::NoCreate || 540 ClauseKind == OpenACCClauseKind::Present || 541 ClauseKind == OpenACCClauseKind::Copy || 542 ClauseKind == OpenACCClauseKind::PCopy || 543 ClauseKind == OpenACCClauseKind::PresentOrCopy || 544 ClauseKind == OpenACCClauseKind::CopyIn || 545 ClauseKind == OpenACCClauseKind::PCopyIn || 546 ClauseKind == OpenACCClauseKind::PresentOrCopyIn || 547 ClauseKind == OpenACCClauseKind::CopyOut || 548 ClauseKind == OpenACCClauseKind::PCopyOut || 549 ClauseKind == OpenACCClauseKind::PresentOrCopyOut || 550 ClauseKind == OpenACCClauseKind::Create || 551 ClauseKind == OpenACCClauseKind::PCreate || 552 ClauseKind == OpenACCClauseKind::PresentOrCreate || 553 ClauseKind == OpenACCClauseKind::Attach || 554 ClauseKind == OpenACCClauseKind::Delete || 555 ClauseKind == OpenACCClauseKind::UseDevice || 556 ClauseKind == OpenACCClauseKind::Detach || 557 ClauseKind == OpenACCClauseKind::DevicePtr || 558 ClauseKind == OpenACCClauseKind::Host || 559 ClauseKind == OpenACCClauseKind::Device || 560 (ClauseKind == OpenACCClauseKind::Self && 561 DirKind == OpenACCDirectiveKind::Update) || 562 ClauseKind == OpenACCClauseKind::FirstPrivate) && 563 "Parsed clause kind does not have a var-list"); 564 assert((!IsReadOnly || ClauseKind == OpenACCClauseKind::CopyIn || 565 ClauseKind == OpenACCClauseKind::PCopyIn || 566 ClauseKind == OpenACCClauseKind::PresentOrCopyIn) && 567 "readonly: tag only valid on copyin"); 568 assert((!IsZero || ClauseKind == OpenACCClauseKind::CopyOut || 569 ClauseKind == OpenACCClauseKind::PCopyOut || 570 ClauseKind == OpenACCClauseKind::PresentOrCopyOut || 571 ClauseKind == OpenACCClauseKind::Create || 572 ClauseKind == OpenACCClauseKind::PCreate || 573 ClauseKind == OpenACCClauseKind::PresentOrCreate) && 574 "zero: tag only valid on copyout/create"); 575 Details = 576 VarListDetails{{VarList.begin(), VarList.end()}, IsReadOnly, IsZero}; 577 } 578 579 void setVarListDetails(llvm::SmallVector<Expr *> &&VarList, bool IsReadOnly, 580 bool IsZero) { 581 assert((ClauseKind == OpenACCClauseKind::Private || 582 ClauseKind == OpenACCClauseKind::NoCreate || 583 ClauseKind == OpenACCClauseKind::Present || 584 ClauseKind == OpenACCClauseKind::Copy || 585 ClauseKind == OpenACCClauseKind::PCopy || 586 ClauseKind == OpenACCClauseKind::PresentOrCopy || 587 ClauseKind == OpenACCClauseKind::CopyIn || 588 ClauseKind == OpenACCClauseKind::PCopyIn || 589 ClauseKind == OpenACCClauseKind::PresentOrCopyIn || 590 ClauseKind == OpenACCClauseKind::CopyOut || 591 ClauseKind == OpenACCClauseKind::PCopyOut || 592 ClauseKind == OpenACCClauseKind::PresentOrCopyOut || 593 ClauseKind == OpenACCClauseKind::Create || 594 ClauseKind == OpenACCClauseKind::PCreate || 595 ClauseKind == OpenACCClauseKind::PresentOrCreate || 596 ClauseKind == OpenACCClauseKind::Attach || 597 ClauseKind == OpenACCClauseKind::Delete || 598 ClauseKind == OpenACCClauseKind::UseDevice || 599 ClauseKind == OpenACCClauseKind::Detach || 600 ClauseKind == OpenACCClauseKind::DevicePtr || 601 ClauseKind == OpenACCClauseKind::Host || 602 ClauseKind == OpenACCClauseKind::Device || 603 (ClauseKind == OpenACCClauseKind::Self && 604 DirKind == OpenACCDirectiveKind::Update) || 605 ClauseKind == OpenACCClauseKind::FirstPrivate) && 606 "Parsed clause kind does not have a var-list"); 607 assert((!IsReadOnly || ClauseKind == OpenACCClauseKind::CopyIn || 608 ClauseKind == OpenACCClauseKind::PCopyIn || 609 ClauseKind == OpenACCClauseKind::PresentOrCopyIn) && 610 "readonly: tag only valid on copyin"); 611 assert((!IsZero || ClauseKind == OpenACCClauseKind::CopyOut || 612 ClauseKind == OpenACCClauseKind::PCopyOut || 613 ClauseKind == OpenACCClauseKind::PresentOrCopyOut || 614 ClauseKind == OpenACCClauseKind::Create || 615 ClauseKind == OpenACCClauseKind::PCreate || 616 ClauseKind == OpenACCClauseKind::PresentOrCreate) && 617 "zero: tag only valid on copyout/create"); 618 Details = VarListDetails{std::move(VarList), IsReadOnly, IsZero}; 619 } 620 621 void setReductionDetails(OpenACCReductionOperator Op, 622 llvm::SmallVector<Expr *> &&VarList) { 623 assert(ClauseKind == OpenACCClauseKind::Reduction && 624 "reduction details only valid on reduction"); 625 Details = ReductionDetails{Op, std::move(VarList)}; 626 } 627 628 void setWaitDetails(Expr *DevNum, SourceLocation QueuesLoc, 629 llvm::SmallVector<Expr *> &&IntExprs) { 630 assert(ClauseKind == OpenACCClauseKind::Wait && 631 "Parsed clause kind does not have a wait-details"); 632 Details = WaitDetails{DevNum, QueuesLoc, std::move(IntExprs)}; 633 } 634 635 void setDeviceTypeDetails(llvm::SmallVector<DeviceTypeArgument> &&Archs) { 636 assert((ClauseKind == OpenACCClauseKind::DeviceType || 637 ClauseKind == OpenACCClauseKind::DType) && 638 "Only 'device_type'/'dtype' has a device-type-arg list"); 639 Details = DeviceTypeDetails{std::move(Archs)}; 640 } 641 642 void setCollapseDetails(bool IsForce, Expr *LoopCount) { 643 assert(ClauseKind == OpenACCClauseKind::Collapse && 644 "Only 'collapse' has collapse details"); 645 Details = CollapseDetails{IsForce, LoopCount}; 646 } 647 }; 648 649 SemaOpenACC(Sema &S); 650 651 // Called when we encounter a 'while' statement, before looking at its 'body'. 652 void ActOnWhileStmt(SourceLocation WhileLoc); 653 // Called when we encounter a 'do' statement, before looking at its 'body'. 654 void ActOnDoStmt(SourceLocation DoLoc); 655 // Called when we encounter a 'for' statement, before looking at its 'body', 656 // for the 'range-for'. 'ActOnForStmtEnd' is used after the body. 657 void ActOnRangeForStmtBegin(SourceLocation ForLoc, const Stmt *OldRangeFor, 658 const Stmt *RangeFor); 659 void ActOnRangeForStmtBegin(SourceLocation ForLoc, const Stmt *RangeFor); 660 // Called when we encounter a 'for' statement, before looking at its 'body'. 661 // 'ActOnForStmtEnd' is used after the body. 662 void ActOnForStmtBegin(SourceLocation ForLoc, const Stmt *First, 663 const Stmt *Second, const Stmt *Third); 664 void ActOnForStmtBegin(SourceLocation ForLoc, const Stmt *OldFirst, 665 const Stmt *First, const Stmt *OldSecond, 666 const Stmt *Second, const Stmt *OldThird, 667 const Stmt *Third); 668 // Called when we encounter a 'for' statement, after we've consumed/checked 669 // the body. This is necessary for a number of checks on the contents of the 670 // 'for' statement. 671 void ActOnForStmtEnd(SourceLocation ForLoc, StmtResult Body); 672 673 /// Called after parsing an OpenACC Clause so that it can be checked. 674 OpenACCClause *ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses, 675 OpenACCParsedClause &Clause); 676 677 /// Called after the construct has been parsed, but clauses haven't been 678 /// parsed. This allows us to diagnose not-implemented, as well as set up any 679 /// state required for parsing the clauses. 680 void ActOnConstruct(OpenACCDirectiveKind K, SourceLocation DirLoc); 681 682 /// Called after the directive, including its clauses, have been parsed and 683 /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES 684 /// happen before any associated declarations or statements have been parsed. 685 /// This function is only called when we are parsing a 'statement' context. 686 bool ActOnStartStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, 687 ArrayRef<const OpenACCClause *> Clauses); 688 689 /// Called after the directive, including its clauses, have been parsed and 690 /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES 691 /// happen before any associated declarations or statements have been parsed. 692 /// This function is only called when we are parsing a 'Decl' context. 693 bool ActOnStartDeclDirective(OpenACCDirectiveKind K, SourceLocation StartLoc); 694 /// Called when we encounter an associated statement for our construct, this 695 /// should check legality of the statement as it appertains to this Construct. 696 StmtResult ActOnAssociatedStmt(SourceLocation DirectiveLoc, 697 OpenACCDirectiveKind K, 698 ArrayRef<const OpenACCClause *> Clauses, 699 StmtResult AssocStmt); 700 701 /// Called after the directive has been completely parsed, including the 702 /// declaration group or associated statement. 703 /// LParenLoc: Location of the left paren, if it exists (not on all 704 /// constructs). 705 /// MiscLoc: First misc location, if necessary (not all constructs). 706 /// Exprs: List of expressions on the construct itself, if necessary (not all 707 /// constructs). 708 /// RParenLoc: Location of the right paren, if it exists (not on all 709 /// constructs). 710 StmtResult ActOnEndStmtDirective( 711 OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc, 712 SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef<Expr *> Exprs, 713 SourceLocation RParenLoc, SourceLocation EndLoc, 714 ArrayRef<OpenACCClause *> Clauses, StmtResult AssocStmt); 715 716 /// Called after the directive has been completely parsed, including the 717 /// declaration group or associated statement. 718 DeclGroupRef ActOnEndDeclDirective(); 719 720 /// Called when encountering an 'int-expr' for OpenACC, and manages 721 /// conversions and diagnostics to 'int'. 722 ExprResult ActOnIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK, 723 SourceLocation Loc, Expr *IntExpr); 724 725 /// Called when encountering a 'var' for OpenACC, ensures it is actually a 726 /// declaration reference to a variable of the correct type. 727 ExprResult ActOnVar(OpenACCClauseKind CK, Expr *VarExpr); 728 729 /// Called while semantically analyzing the reduction clause, ensuring the var 730 /// is the correct kind of reference. 731 ExprResult CheckReductionVar(OpenACCDirectiveKind DirectiveKind, 732 OpenACCReductionOperator ReductionOp, 733 Expr *VarExpr); 734 735 /// Called to check the 'var' type is a variable of pointer type, necessary 736 /// for 'deviceptr' and 'attach' clauses. Returns true on success. 737 bool CheckVarIsPointerType(OpenACCClauseKind ClauseKind, Expr *VarExpr); 738 739 /// Checks and creates an Array Section used in an OpenACC construct/clause. 740 ExprResult ActOnArraySectionExpr(Expr *Base, SourceLocation LBLoc, 741 Expr *LowerBound, 742 SourceLocation ColonLocFirst, Expr *Length, 743 SourceLocation RBLoc); 744 /// Checks the loop depth value for a collapse clause. 745 ExprResult CheckCollapseLoopCount(Expr *LoopCount); 746 /// Checks a single size expr for a tile clause. 747 ExprResult CheckTileSizeExpr(Expr *SizeExpr); 748 749 // Check a single expression on a gang clause. 750 ExprResult CheckGangExpr(ArrayRef<const OpenACCClause *> ExistingClauses, 751 OpenACCDirectiveKind DK, OpenACCGangKind GK, 752 Expr *E); 753 754 // Does the checking for a 'gang' clause that needs to be done in dependent 755 // and not dependent cases. 756 OpenACCClause * 757 CheckGangClause(OpenACCDirectiveKind DirKind, 758 ArrayRef<const OpenACCClause *> ExistingClauses, 759 SourceLocation BeginLoc, SourceLocation LParenLoc, 760 ArrayRef<OpenACCGangKind> GangKinds, 761 ArrayRef<Expr *> IntExprs, SourceLocation EndLoc); 762 // Does the checking for a 'reduction ' clause that needs to be done in 763 // dependent and not dependent cases. 764 OpenACCClause * 765 CheckReductionClause(ArrayRef<const OpenACCClause *> ExistingClauses, 766 OpenACCDirectiveKind DirectiveKind, 767 SourceLocation BeginLoc, SourceLocation LParenLoc, 768 OpenACCReductionOperator ReductionOp, 769 ArrayRef<Expr *> Vars, SourceLocation EndLoc); 770 771 ExprResult BuildOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc); 772 ExprResult ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc); 773 774 /// Helper type to restore the state of various 'loop' constructs when we run 775 /// into a loop (for, etc) inside the construct. 776 class LoopInConstructRAII { 777 SemaOpenACC &SemaRef; 778 LoopCheckingInfo OldLoopInfo; 779 CollapseCheckingInfo OldCollapseInfo; 780 TileCheckingInfo OldTileInfo; 781 bool PreserveDepth; 782 783 public: 784 LoopInConstructRAII(SemaOpenACC &SemaRef, bool PreserveDepth = true) 785 : SemaRef(SemaRef), OldLoopInfo(SemaRef.LoopInfo), 786 OldCollapseInfo(SemaRef.CollapseInfo), OldTileInfo(SemaRef.TileInfo), 787 PreserveDepth(PreserveDepth) {} 788 ~LoopInConstructRAII() { 789 // The associated-statement level of this should NOT preserve this, as it 790 // is a new construct, but other loop uses need to preserve the depth so 791 // it makes it to the 'top level' for diagnostics. 792 bool CollapseDepthSatisified = 793 PreserveDepth ? SemaRef.CollapseInfo.CollapseDepthSatisfied 794 : OldCollapseInfo.CollapseDepthSatisfied; 795 bool TileDepthSatisfied = PreserveDepth 796 ? SemaRef.TileInfo.TileDepthSatisfied 797 : OldTileInfo.TileDepthSatisfied; 798 bool CurLevelHasLoopAlready = 799 PreserveDepth ? SemaRef.LoopInfo.CurLevelHasLoopAlready 800 : OldLoopInfo.CurLevelHasLoopAlready; 801 802 SemaRef.LoopInfo = OldLoopInfo; 803 SemaRef.CollapseInfo = OldCollapseInfo; 804 SemaRef.TileInfo = OldTileInfo; 805 806 SemaRef.CollapseInfo.CollapseDepthSatisfied = CollapseDepthSatisified; 807 SemaRef.TileInfo.TileDepthSatisfied = TileDepthSatisfied; 808 SemaRef.LoopInfo.CurLevelHasLoopAlready = CurLevelHasLoopAlready; 809 } 810 }; 811 812 /// Helper type for the registration/assignment of constructs that need to 813 /// 'know' about their parent constructs and hold a reference to them, such as 814 /// Loop needing its parent construct. 815 class AssociatedStmtRAII { 816 SemaOpenACC &SemaRef; 817 ComputeConstructInfo OldActiveComputeConstructInfo; 818 OpenACCDirectiveKind DirKind; 819 LoopGangOnKernelTy OldLoopGangClauseOnKernel; 820 SourceLocation OldLoopWorkerClauseLoc; 821 SourceLocation OldLoopVectorClauseLoc; 822 LoopWithoutSeqCheckingInfo OldLoopWithoutSeqInfo; 823 llvm::SmallVector<OpenACCReductionClause *> ActiveReductionClauses; 824 LoopInConstructRAII LoopRAII; 825 826 public: 827 AssociatedStmtRAII(SemaOpenACC &, OpenACCDirectiveKind, SourceLocation, 828 ArrayRef<const OpenACCClause *>, 829 ArrayRef<OpenACCClause *>); 830 void SetCollapseInfoBeforeAssociatedStmt( 831 ArrayRef<const OpenACCClause *> UnInstClauses, 832 ArrayRef<OpenACCClause *> Clauses); 833 void SetTileInfoBeforeAssociatedStmt( 834 ArrayRef<const OpenACCClause *> UnInstClauses, 835 ArrayRef<OpenACCClause *> Clauses); 836 ~AssociatedStmtRAII(); 837 }; 838 }; 839 840 } // namespace clang 841 842 #endif // LLVM_CLANG_SEMA_SEMAOPENACC_H 843