| //===--- StmtOpenACC.cpp - Classes for OpenACC Constructs -----------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file implements the subclasses of Stmt class declared in StmtOpenACC.h |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "clang/AST/StmtOpenACC.h" |
| #include "clang/AST/ASTContext.h" |
| #include "clang/AST/RecursiveASTVisitor.h" |
| #include "clang/AST/StmtCXX.h" |
| using namespace clang; |
| |
| OpenACCComputeConstruct * |
| OpenACCComputeConstruct::CreateEmpty(const ASTContext &C, unsigned NumClauses) { |
| void *Mem = C.Allocate( |
| OpenACCComputeConstruct::totalSizeToAlloc<const OpenACCClause *>( |
| NumClauses)); |
| auto *Inst = new (Mem) OpenACCComputeConstruct(NumClauses); |
| return Inst; |
| } |
| |
| OpenACCComputeConstruct *OpenACCComputeConstruct::Create( |
| const ASTContext &C, OpenACCDirectiveKind K, SourceLocation BeginLoc, |
| SourceLocation DirLoc, SourceLocation EndLoc, |
| ArrayRef<const OpenACCClause *> Clauses, Stmt *StructuredBlock, |
| ArrayRef<OpenACCLoopConstruct *> AssociatedLoopConstructs) { |
| void *Mem = C.Allocate( |
| OpenACCComputeConstruct::totalSizeToAlloc<const OpenACCClause *>( |
| Clauses.size())); |
| auto *Inst = new (Mem) OpenACCComputeConstruct(K, BeginLoc, DirLoc, EndLoc, |
| Clauses, StructuredBlock); |
| |
| llvm::for_each(AssociatedLoopConstructs, [&](OpenACCLoopConstruct *C) { |
| C->setParentComputeConstruct(Inst); |
| }); |
| |
| return Inst; |
| } |
| |
| void OpenACCComputeConstruct::findAndSetChildLoops() { |
| struct LoopConstructFinder : RecursiveASTVisitor<LoopConstructFinder> { |
| OpenACCComputeConstruct *Construct = nullptr; |
| |
| LoopConstructFinder(OpenACCComputeConstruct *Construct) |
| : Construct(Construct) {} |
| |
| bool TraverseOpenACCComputeConstruct(OpenACCComputeConstruct *C) { |
| // Stop searching if we find a compute construct. |
| return true; |
| } |
| bool TraverseOpenACCLoopConstruct(OpenACCLoopConstruct *C) { |
| // Stop searching if we find a loop construct, after taking ownership of |
| // it. |
| C->setParentComputeConstruct(Construct); |
| return true; |
| } |
| }; |
| |
| LoopConstructFinder f(this); |
| f.TraverseStmt(getAssociatedStmt()); |
| } |
| |
| OpenACCLoopConstruct::OpenACCLoopConstruct(unsigned NumClauses) |
| : OpenACCAssociatedStmtConstruct( |
| OpenACCLoopConstructClass, OpenACCDirectiveKind::Loop, |
| SourceLocation{}, SourceLocation{}, SourceLocation{}, |
| /*AssociatedStmt=*/nullptr) { |
| std::uninitialized_value_construct( |
| getTrailingObjects<const OpenACCClause *>(), |
| getTrailingObjects<const OpenACCClause *>() + NumClauses); |
| setClauseList( |
| MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), NumClauses)); |
| } |
| |
| OpenACCLoopConstruct::OpenACCLoopConstruct( |
| SourceLocation Start, SourceLocation DirLoc, SourceLocation End, |
| ArrayRef<const OpenACCClause *> Clauses, Stmt *Loop) |
| : OpenACCAssociatedStmtConstruct(OpenACCLoopConstructClass, |
| OpenACCDirectiveKind::Loop, Start, DirLoc, |
| End, Loop) { |
| // accept 'nullptr' for the loop. This is diagnosed somewhere, but this gives |
| // us some level of AST fidelity in the error case. |
| assert((Loop == nullptr || isa<ForStmt, CXXForRangeStmt>(Loop)) && |
| "Associated Loop not a for loop?"); |
| // Initialize the trailing storage. |
| std::uninitialized_copy(Clauses.begin(), Clauses.end(), |
| getTrailingObjects<const OpenACCClause *>()); |
| |
| setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), |
| Clauses.size())); |
| } |
| |
| void OpenACCLoopConstruct::setLoop(Stmt *Loop) { |
| assert((isa<ForStmt, CXXForRangeStmt>(Loop)) && |
| "Associated Loop not a for loop?"); |
| setAssociatedStmt(Loop); |
| } |
| |
| OpenACCLoopConstruct *OpenACCLoopConstruct::CreateEmpty(const ASTContext &C, |
| unsigned NumClauses) { |
| void *Mem = |
| C.Allocate(OpenACCLoopConstruct::totalSizeToAlloc<const OpenACCClause *>( |
| NumClauses)); |
| auto *Inst = new (Mem) OpenACCLoopConstruct(NumClauses); |
| return Inst; |
| } |
| |
| OpenACCLoopConstruct * |
| OpenACCLoopConstruct::Create(const ASTContext &C, SourceLocation BeginLoc, |
| SourceLocation DirLoc, SourceLocation EndLoc, |
| ArrayRef<const OpenACCClause *> Clauses, |
| Stmt *Loop) { |
| void *Mem = |
| C.Allocate(OpenACCLoopConstruct::totalSizeToAlloc<const OpenACCClause *>( |
| Clauses.size())); |
| auto *Inst = |
| new (Mem) OpenACCLoopConstruct(BeginLoc, DirLoc, EndLoc, Clauses, Loop); |
| return Inst; |
| } |