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/Stmt.h" |
17 | #include "clang/Basic/OpenACCKinds.h" |
18 | #include "clang/Basic/SourceLocation.h" |
19 | |
20 | namespace clang { |
21 | /// This is the base class for an OpenACC statement-level construct, other |
22 | /// construct types are expected to inherit from this. |
23 | class OpenACCConstructStmt : public Stmt { |
24 | friend class ASTStmtWriter; |
25 | friend class ASTStmtReader; |
26 | /// The directive kind. Each implementation of this interface should handle |
27 | /// specific kinds. |
28 | OpenACCDirectiveKind Kind = OpenACCDirectiveKind::Invalid; |
29 | /// The location of the directive statement, from the '#' to the last token of |
30 | /// the directive. |
31 | SourceRange Range; |
32 | |
33 | // TODO OPENACC: Clauses should probably be collected in this class. |
34 | |
35 | protected: |
36 | OpenACCConstructStmt(StmtClass SC, OpenACCDirectiveKind K, |
37 | SourceLocation Start, SourceLocation End) |
38 | : Stmt(SC), Kind(K), Range(Start, End) {} |
39 | |
40 | public: |
41 | OpenACCDirectiveKind getDirectiveKind() const { return Kind; } |
42 | |
43 | static bool classof(const Stmt *S) { |
44 | return S->getStmtClass() >= firstOpenACCConstructStmtConstant && |
45 | S->getStmtClass() <= lastOpenACCConstructStmtConstant; |
46 | } |
47 | |
48 | SourceLocation getBeginLoc() const { return Range.getBegin(); } |
49 | SourceLocation getEndLoc() const { return Range.getEnd(); } |
50 | |
51 | child_range children() { |
52 | return child_range(child_iterator(), child_iterator()); |
53 | } |
54 | |
55 | const_child_range children() const { |
56 | return const_cast<OpenACCConstructStmt *>(this)->children(); |
57 | } |
58 | }; |
59 | |
60 | /// This is a base class for any OpenACC statement-level constructs that have an |
61 | /// associated statement. This class is not intended to be instantiated, but is |
62 | /// a convenient place to hold the associated statement. |
63 | class OpenACCAssociatedStmtConstruct : public OpenACCConstructStmt { |
64 | friend class ASTStmtWriter; |
65 | friend class ASTStmtReader; |
66 | template <typename Derived> friend class RecursiveASTVisitor; |
67 | Stmt *AssociatedStmt = nullptr; |
68 | |
69 | protected: |
70 | OpenACCAssociatedStmtConstruct(StmtClass SC, OpenACCDirectiveKind K, |
71 | SourceLocation Start, SourceLocation End) |
72 | : OpenACCConstructStmt(SC, K, Start, End) {} |
73 | |
74 | void setAssociatedStmt(Stmt *S) { AssociatedStmt = S; } |
75 | Stmt *getAssociatedStmt() { return AssociatedStmt; } |
76 | const Stmt *getAssociatedStmt() const { |
77 | return const_cast<OpenACCAssociatedStmtConstruct *>(this) |
78 | ->getAssociatedStmt(); |
79 | } |
80 | |
81 | public: |
82 | child_range children() { |
83 | if (getAssociatedStmt()) |
84 | return child_range(&AssociatedStmt, &AssociatedStmt + 1); |
85 | return child_range(child_iterator(), child_iterator()); |
86 | } |
87 | |
88 | const_child_range children() const { |
89 | return const_cast<OpenACCAssociatedStmtConstruct *>(this)->children(); |
90 | } |
91 | }; |
92 | /// This class represents a compute construct, representing a 'Kind' of |
93 | /// `parallel', 'serial', or 'kernel'. These constructs are associated with a |
94 | /// 'structured block', defined as: |
95 | /// |
96 | /// in C or C++, an executable statement, possibly compound, with a single |
97 | /// entry at the top and a single exit at the bottom |
98 | /// |
99 | /// At the moment there is no real motivation to have a different AST node for |
100 | /// those three, as they are semantically identical, and have only minor |
101 | /// differences in the permitted list of clauses, which can be differentiated by |
102 | /// the 'Kind'. |
103 | class OpenACCComputeConstruct : public OpenACCAssociatedStmtConstruct { |
104 | friend class ASTStmtWriter; |
105 | friend class ASTStmtReader; |
106 | friend class ASTContext; |
107 | OpenACCComputeConstruct() |
108 | : OpenACCAssociatedStmtConstruct(OpenACCComputeConstructClass, |
109 | OpenACCDirectiveKind::Invalid, |
110 | SourceLocation{}, SourceLocation{}) {} |
111 | |
112 | OpenACCComputeConstruct(OpenACCDirectiveKind K, SourceLocation Start, |
113 | SourceLocation End) |
114 | : OpenACCAssociatedStmtConstruct(OpenACCComputeConstructClass, K, Start, |
115 | End) { |
116 | assert((K == OpenACCDirectiveKind::Parallel || |
117 | K == OpenACCDirectiveKind::Serial || |
118 | K == OpenACCDirectiveKind::Kernels) && |
119 | "Only parallel, serial, and kernels constructs should be " |
120 | "represented by this type" ); |
121 | } |
122 | |
123 | void setStructuredBlock(Stmt *S) { setAssociatedStmt(S); } |
124 | |
125 | public: |
126 | static bool classof(const Stmt *T) { |
127 | return T->getStmtClass() == OpenACCComputeConstructClass; |
128 | } |
129 | |
130 | static OpenACCComputeConstruct *CreateEmpty(const ASTContext &C, EmptyShell); |
131 | static OpenACCComputeConstruct *Create(const ASTContext &C, |
132 | OpenACCDirectiveKind K, |
133 | SourceLocation BeginLoc, |
134 | SourceLocation EndLoc); |
135 | |
136 | Stmt *getStructuredBlock() { return getAssociatedStmt(); } |
137 | const Stmt *getStructuredBlock() const { |
138 | return const_cast<OpenACCComputeConstruct *>(this)->getStructuredBlock(); |
139 | } |
140 | }; |
141 | } // namespace clang |
142 | #endif // LLVM_CLANG_AST_STMTOPENACC_H |
143 | |