1 | //===- StmtOpenACC.h - Classes for OpenACC directives ----------*- C++ -*-===// |
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 defines OpenACC AST classes for statement-level contructs. |
10 | /// |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLVM_CLANG_AST_STMTOPENACC_H |
14 | #define LLVM_CLANG_AST_STMTOPENACC_H |
15 | |
16 | #include "clang/AST/OpenACCClause.h" |
17 | #include "clang/AST/Stmt.h" |
18 | #include "clang/Basic/OpenACCKinds.h" |
19 | #include "clang/Basic/SourceLocation.h" |
20 | #include <memory> |
21 | |
22 | namespace clang { |
23 | /// This is the base class for an OpenACC statement-level construct, other |
24 | /// construct types are expected to inherit from this. |
25 | class OpenACCConstructStmt : public Stmt { |
26 | friend class ASTStmtWriter; |
27 | friend class ASTStmtReader; |
28 | /// The directive kind. Each implementation of this interface should handle |
29 | /// specific kinds. |
30 | OpenACCDirectiveKind Kind = OpenACCDirectiveKind::Invalid; |
31 | /// The location of the directive statement, from the '#' to the last token of |
32 | /// the directive. |
33 | SourceRange Range; |
34 | |
35 | /// The list of clauses. This is stored here as an ArrayRef, as this is the |
36 | /// most convienient place to access the list, however the list itself should |
37 | /// be stored in leaf nodes, likely in trailing-storage. |
38 | MutableArrayRef<const OpenACCClause *> Clauses; |
39 | |
40 | protected: |
41 | OpenACCConstructStmt(StmtClass SC, OpenACCDirectiveKind K, |
42 | SourceLocation Start, SourceLocation End) |
43 | : Stmt(SC), Kind(K), Range(Start, End) {} |
44 | |
45 | // Used only for initialization, the leaf class can initialize this to |
46 | // trailing storage. |
47 | void setClauseList(MutableArrayRef<const OpenACCClause *> NewClauses) { |
48 | assert(Clauses.empty() && "Cannot change clause list" ); |
49 | Clauses = NewClauses; |
50 | } |
51 | |
52 | public: |
53 | OpenACCDirectiveKind getDirectiveKind() const { return Kind; } |
54 | |
55 | static bool classof(const Stmt *S) { |
56 | return S->getStmtClass() >= firstOpenACCConstructStmtConstant && |
57 | S->getStmtClass() <= lastOpenACCConstructStmtConstant; |
58 | } |
59 | |
60 | SourceLocation getBeginLoc() const { return Range.getBegin(); } |
61 | SourceLocation getEndLoc() const { return Range.getEnd(); } |
62 | ArrayRef<const OpenACCClause *> clauses() const { return Clauses; } |
63 | |
64 | child_range children() { |
65 | return child_range(child_iterator(), child_iterator()); |
66 | } |
67 | |
68 | const_child_range children() const { |
69 | return const_cast<OpenACCConstructStmt *>(this)->children(); |
70 | } |
71 | }; |
72 | |
73 | /// This is a base class for any OpenACC statement-level constructs that have an |
74 | /// associated statement. This class is not intended to be instantiated, but is |
75 | /// a convenient place to hold the associated statement. |
76 | class OpenACCAssociatedStmtConstruct : public OpenACCConstructStmt { |
77 | friend class ASTStmtWriter; |
78 | friend class ASTStmtReader; |
79 | template <typename Derived> friend class RecursiveASTVisitor; |
80 | Stmt *AssociatedStmt = nullptr; |
81 | |
82 | protected: |
83 | OpenACCAssociatedStmtConstruct(StmtClass SC, OpenACCDirectiveKind K, |
84 | SourceLocation Start, SourceLocation End, |
85 | Stmt *AssocStmt) |
86 | : OpenACCConstructStmt(SC, K, Start, End), AssociatedStmt(AssocStmt) {} |
87 | |
88 | void setAssociatedStmt(Stmt *S) { AssociatedStmt = S; } |
89 | Stmt *getAssociatedStmt() { return AssociatedStmt; } |
90 | const Stmt *getAssociatedStmt() const { |
91 | return const_cast<OpenACCAssociatedStmtConstruct *>(this) |
92 | ->getAssociatedStmt(); |
93 | } |
94 | |
95 | public: |
96 | child_range children() { |
97 | if (getAssociatedStmt()) |
98 | return child_range(&AssociatedStmt, &AssociatedStmt + 1); |
99 | return child_range(child_iterator(), child_iterator()); |
100 | } |
101 | |
102 | const_child_range children() const { |
103 | return const_cast<OpenACCAssociatedStmtConstruct *>(this)->children(); |
104 | } |
105 | }; |
106 | /// This class represents a compute construct, representing a 'Kind' of |
107 | /// `parallel', 'serial', or 'kernel'. These constructs are associated with a |
108 | /// 'structured block', defined as: |
109 | /// |
110 | /// in C or C++, an executable statement, possibly compound, with a single |
111 | /// entry at the top and a single exit at the bottom |
112 | /// |
113 | /// At the moment there is no real motivation to have a different AST node for |
114 | /// those three, as they are semantically identical, and have only minor |
115 | /// differences in the permitted list of clauses, which can be differentiated by |
116 | /// the 'Kind'. |
117 | class OpenACCComputeConstruct final |
118 | : public OpenACCAssociatedStmtConstruct, |
119 | public llvm::TrailingObjects<OpenACCComputeConstruct, |
120 | const OpenACCClause *> { |
121 | friend class ASTStmtWriter; |
122 | friend class ASTStmtReader; |
123 | friend class ASTContext; |
124 | OpenACCComputeConstruct(unsigned NumClauses) |
125 | : OpenACCAssociatedStmtConstruct(OpenACCComputeConstructClass, |
126 | OpenACCDirectiveKind::Invalid, |
127 | SourceLocation{}, SourceLocation{}, |
128 | /*AssociatedStmt=*/nullptr) { |
129 | // We cannot send the TrailingObjects storage to the base class (which holds |
130 | // a reference to the data) until it is constructed, so we have to set it |
131 | // separately here. |
132 | std::uninitialized_value_construct( |
133 | first: getTrailingObjects<const OpenACCClause *>(), |
134 | last: getTrailingObjects<const OpenACCClause *>() + NumClauses); |
135 | setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), |
136 | NumClauses)); |
137 | } |
138 | |
139 | OpenACCComputeConstruct(OpenACCDirectiveKind K, SourceLocation Start, |
140 | SourceLocation End, |
141 | ArrayRef<const OpenACCClause *> Clauses, |
142 | Stmt *StructuredBlock) |
143 | : OpenACCAssociatedStmtConstruct(OpenACCComputeConstructClass, K, Start, |
144 | End, StructuredBlock) { |
145 | assert(isOpenACCComputeDirectiveKind(K) && |
146 | "Only parallel, serial, and kernels constructs should be " |
147 | "represented by this type" ); |
148 | |
149 | // Initialize the trailing storage. |
150 | std::uninitialized_copy(first: Clauses.begin(), last: Clauses.end(), |
151 | result: getTrailingObjects<const OpenACCClause *>()); |
152 | |
153 | setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), |
154 | Clauses.size())); |
155 | } |
156 | |
157 | void setStructuredBlock(Stmt *S) { setAssociatedStmt(S); } |
158 | |
159 | public: |
160 | static bool classof(const Stmt *T) { |
161 | return T->getStmtClass() == OpenACCComputeConstructClass; |
162 | } |
163 | |
164 | static OpenACCComputeConstruct *CreateEmpty(const ASTContext &C, |
165 | unsigned NumClauses); |
166 | static OpenACCComputeConstruct * |
167 | Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation BeginLoc, |
168 | SourceLocation EndLoc, ArrayRef<const OpenACCClause *> Clauses, |
169 | Stmt *StructuredBlock); |
170 | |
171 | Stmt *getStructuredBlock() { return getAssociatedStmt(); } |
172 | const Stmt *getStructuredBlock() const { |
173 | return const_cast<OpenACCComputeConstruct *>(this)->getStructuredBlock(); |
174 | } |
175 | }; |
176 | } // namespace clang |
177 | #endif // LLVM_CLANG_AST_STMTOPENACC_H |
178 | |