1*0fca6ea1SDimitry Andric //===--- StmtOpenACC.cpp - Classes for OpenACC Constructs -----------------===// 2*0fca6ea1SDimitry Andric // 3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0fca6ea1SDimitry Andric // 7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8*0fca6ea1SDimitry Andric // 9*0fca6ea1SDimitry Andric // This file implements the subclasses of Stmt class declared in StmtOpenACC.h 10*0fca6ea1SDimitry Andric // 11*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 12*0fca6ea1SDimitry Andric 13*0fca6ea1SDimitry Andric #include "clang/AST/StmtOpenACC.h" 14*0fca6ea1SDimitry Andric #include "clang/AST/ASTContext.h" 15*0fca6ea1SDimitry Andric #include "clang/AST/RecursiveASTVisitor.h" 16*0fca6ea1SDimitry Andric #include "clang/AST/StmtCXX.h" 17*0fca6ea1SDimitry Andric using namespace clang; 18*0fca6ea1SDimitry Andric 19*0fca6ea1SDimitry Andric OpenACCComputeConstruct * 20*0fca6ea1SDimitry Andric OpenACCComputeConstruct::CreateEmpty(const ASTContext &C, unsigned NumClauses) { 21*0fca6ea1SDimitry Andric void *Mem = C.Allocate( 22*0fca6ea1SDimitry Andric OpenACCComputeConstruct::totalSizeToAlloc<const OpenACCClause *>( 23*0fca6ea1SDimitry Andric NumClauses)); 24*0fca6ea1SDimitry Andric auto *Inst = new (Mem) OpenACCComputeConstruct(NumClauses); 25*0fca6ea1SDimitry Andric return Inst; 26*0fca6ea1SDimitry Andric } 27*0fca6ea1SDimitry Andric 28*0fca6ea1SDimitry Andric OpenACCComputeConstruct *OpenACCComputeConstruct::Create( 29*0fca6ea1SDimitry Andric const ASTContext &C, OpenACCDirectiveKind K, SourceLocation BeginLoc, 30*0fca6ea1SDimitry Andric SourceLocation DirLoc, SourceLocation EndLoc, 31*0fca6ea1SDimitry Andric ArrayRef<const OpenACCClause *> Clauses, Stmt *StructuredBlock, 32*0fca6ea1SDimitry Andric ArrayRef<OpenACCLoopConstruct *> AssociatedLoopConstructs) { 33*0fca6ea1SDimitry Andric void *Mem = C.Allocate( 34*0fca6ea1SDimitry Andric OpenACCComputeConstruct::totalSizeToAlloc<const OpenACCClause *>( 35*0fca6ea1SDimitry Andric Clauses.size())); 36*0fca6ea1SDimitry Andric auto *Inst = new (Mem) OpenACCComputeConstruct(K, BeginLoc, DirLoc, EndLoc, 37*0fca6ea1SDimitry Andric Clauses, StructuredBlock); 38*0fca6ea1SDimitry Andric 39*0fca6ea1SDimitry Andric llvm::for_each(AssociatedLoopConstructs, [&](OpenACCLoopConstruct *C) { 40*0fca6ea1SDimitry Andric C->setParentComputeConstruct(Inst); 41*0fca6ea1SDimitry Andric }); 42*0fca6ea1SDimitry Andric 43*0fca6ea1SDimitry Andric return Inst; 44*0fca6ea1SDimitry Andric } 45*0fca6ea1SDimitry Andric 46*0fca6ea1SDimitry Andric void OpenACCComputeConstruct::findAndSetChildLoops() { 47*0fca6ea1SDimitry Andric struct LoopConstructFinder : RecursiveASTVisitor<LoopConstructFinder> { 48*0fca6ea1SDimitry Andric OpenACCComputeConstruct *Construct = nullptr; 49*0fca6ea1SDimitry Andric 50*0fca6ea1SDimitry Andric LoopConstructFinder(OpenACCComputeConstruct *Construct) 51*0fca6ea1SDimitry Andric : Construct(Construct) {} 52*0fca6ea1SDimitry Andric 53*0fca6ea1SDimitry Andric bool TraverseOpenACCComputeConstruct(OpenACCComputeConstruct *C) { 54*0fca6ea1SDimitry Andric // Stop searching if we find a compute construct. 55*0fca6ea1SDimitry Andric return true; 56*0fca6ea1SDimitry Andric } 57*0fca6ea1SDimitry Andric bool TraverseOpenACCLoopConstruct(OpenACCLoopConstruct *C) { 58*0fca6ea1SDimitry Andric // Stop searching if we find a loop construct, after taking ownership of 59*0fca6ea1SDimitry Andric // it. 60*0fca6ea1SDimitry Andric C->setParentComputeConstruct(Construct); 61*0fca6ea1SDimitry Andric return true; 62*0fca6ea1SDimitry Andric } 63*0fca6ea1SDimitry Andric }; 64*0fca6ea1SDimitry Andric 65*0fca6ea1SDimitry Andric LoopConstructFinder f(this); 66*0fca6ea1SDimitry Andric f.TraverseStmt(getAssociatedStmt()); 67*0fca6ea1SDimitry Andric } 68*0fca6ea1SDimitry Andric 69*0fca6ea1SDimitry Andric OpenACCLoopConstruct::OpenACCLoopConstruct(unsigned NumClauses) 70*0fca6ea1SDimitry Andric : OpenACCAssociatedStmtConstruct( 71*0fca6ea1SDimitry Andric OpenACCLoopConstructClass, OpenACCDirectiveKind::Loop, 72*0fca6ea1SDimitry Andric SourceLocation{}, SourceLocation{}, SourceLocation{}, 73*0fca6ea1SDimitry Andric /*AssociatedStmt=*/nullptr) { 74*0fca6ea1SDimitry Andric std::uninitialized_value_construct( 75*0fca6ea1SDimitry Andric getTrailingObjects<const OpenACCClause *>(), 76*0fca6ea1SDimitry Andric getTrailingObjects<const OpenACCClause *>() + NumClauses); 77*0fca6ea1SDimitry Andric setClauseList( 78*0fca6ea1SDimitry Andric MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), NumClauses)); 79*0fca6ea1SDimitry Andric } 80*0fca6ea1SDimitry Andric 81*0fca6ea1SDimitry Andric OpenACCLoopConstruct::OpenACCLoopConstruct( 82*0fca6ea1SDimitry Andric SourceLocation Start, SourceLocation DirLoc, SourceLocation End, 83*0fca6ea1SDimitry Andric ArrayRef<const OpenACCClause *> Clauses, Stmt *Loop) 84*0fca6ea1SDimitry Andric : OpenACCAssociatedStmtConstruct(OpenACCLoopConstructClass, 85*0fca6ea1SDimitry Andric OpenACCDirectiveKind::Loop, Start, DirLoc, 86*0fca6ea1SDimitry Andric End, Loop) { 87*0fca6ea1SDimitry Andric // accept 'nullptr' for the loop. This is diagnosed somewhere, but this gives 88*0fca6ea1SDimitry Andric // us some level of AST fidelity in the error case. 89*0fca6ea1SDimitry Andric assert((Loop == nullptr || isa<ForStmt, CXXForRangeStmt>(Loop)) && 90*0fca6ea1SDimitry Andric "Associated Loop not a for loop?"); 91*0fca6ea1SDimitry Andric // Initialize the trailing storage. 92*0fca6ea1SDimitry Andric std::uninitialized_copy(Clauses.begin(), Clauses.end(), 93*0fca6ea1SDimitry Andric getTrailingObjects<const OpenACCClause *>()); 94*0fca6ea1SDimitry Andric 95*0fca6ea1SDimitry Andric setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), 96*0fca6ea1SDimitry Andric Clauses.size())); 97*0fca6ea1SDimitry Andric } 98*0fca6ea1SDimitry Andric 99*0fca6ea1SDimitry Andric void OpenACCLoopConstruct::setLoop(Stmt *Loop) { 100*0fca6ea1SDimitry Andric assert((isa<ForStmt, CXXForRangeStmt>(Loop)) && 101*0fca6ea1SDimitry Andric "Associated Loop not a for loop?"); 102*0fca6ea1SDimitry Andric setAssociatedStmt(Loop); 103*0fca6ea1SDimitry Andric } 104*0fca6ea1SDimitry Andric 105*0fca6ea1SDimitry Andric OpenACCLoopConstruct *OpenACCLoopConstruct::CreateEmpty(const ASTContext &C, 106*0fca6ea1SDimitry Andric unsigned NumClauses) { 107*0fca6ea1SDimitry Andric void *Mem = 108*0fca6ea1SDimitry Andric C.Allocate(OpenACCLoopConstruct::totalSizeToAlloc<const OpenACCClause *>( 109*0fca6ea1SDimitry Andric NumClauses)); 110*0fca6ea1SDimitry Andric auto *Inst = new (Mem) OpenACCLoopConstruct(NumClauses); 111*0fca6ea1SDimitry Andric return Inst; 112*0fca6ea1SDimitry Andric } 113*0fca6ea1SDimitry Andric 114*0fca6ea1SDimitry Andric OpenACCLoopConstruct * 115*0fca6ea1SDimitry Andric OpenACCLoopConstruct::Create(const ASTContext &C, SourceLocation BeginLoc, 116*0fca6ea1SDimitry Andric SourceLocation DirLoc, SourceLocation EndLoc, 117*0fca6ea1SDimitry Andric ArrayRef<const OpenACCClause *> Clauses, 118*0fca6ea1SDimitry Andric Stmt *Loop) { 119*0fca6ea1SDimitry Andric void *Mem = 120*0fca6ea1SDimitry Andric C.Allocate(OpenACCLoopConstruct::totalSizeToAlloc<const OpenACCClause *>( 121*0fca6ea1SDimitry Andric Clauses.size())); 122*0fca6ea1SDimitry Andric auto *Inst = 123*0fca6ea1SDimitry Andric new (Mem) OpenACCLoopConstruct(BeginLoc, DirLoc, EndLoc, Clauses, Loop); 124*0fca6ea1SDimitry Andric return Inst; 125*0fca6ea1SDimitry Andric } 126