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