Skip to content

Commit f655778

Browse files
authored
[OpenACC] Implement AST for OpenACC Compute Constructs (#81188)
'serial', 'parallel', and 'kernel' constructs are all considered 'Compute' constructs. This patch creates the AST type, plus the required infrastructure for such a type, plus some base types that will be useful in the future for breaking this up. The only difference between the three is the 'kind'( plus some minor clause legalization rules, but those can be differentiated easily enough), so rather than representing them as separate AST nodes, it seems to make sense to make them the same. Additionally, no clause AST functionality is being implemented yet, as that fits better in a separate patch, and this is enough to get the 'naked' constructs implemented. This is otherwise an 'NFC' patch, as it doesn't alter execution at all, so there aren't any tests. I did this to break up the review workload and to get feedback on the layout.
1 parent bb60c06 commit f655778

24 files changed

+352
-6
lines changed

clang/include/clang-c/Index.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2145,7 +2145,11 @@ enum CXCursorKind {
21452145
*/
21462146
CXCursor_OMPScopeDirective = 306,
21472147

2148-
CXCursor_LastStmt = CXCursor_OMPScopeDirective,
2148+
/** OpenACC Compute Construct.
2149+
*/
2150+
CXCursor_OpenACCComputeConstruct = 320,
2151+
2152+
CXCursor_LastStmt = CXCursor_OpenACCComputeConstruct,
21492153

21502154
/**
21512155
* Cursor that represents the translation unit itself.

clang/include/clang/AST/RecursiveASTVisitor.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "clang/AST/Stmt.h"
3535
#include "clang/AST/StmtCXX.h"
3636
#include "clang/AST/StmtObjC.h"
37+
#include "clang/AST/StmtOpenACC.h"
3738
#include "clang/AST/StmtOpenMP.h"
3839
#include "clang/AST/TemplateBase.h"
3940
#include "clang/AST/TemplateName.h"
@@ -505,6 +506,9 @@ template <typename Derived> class RecursiveASTVisitor {
505506
bool VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *Node);
506507

507508
bool PostVisitStmt(Stmt *S);
509+
bool TraverseOpenACCConstructStmt(OpenACCConstructStmt *S);
510+
bool
511+
TraverseOpenACCAssociatedStmtConstruct(OpenACCAssociatedStmtConstruct *S);
508512
};
509513

510514
template <typename Derived>
@@ -3910,6 +3914,24 @@ bool RecursiveASTVisitor<Derived>::VisitOMPXBareClause(OMPXBareClause *C) {
39103914
return true;
39113915
}
39123916

3917+
template <typename Derived>
3918+
bool RecursiveASTVisitor<Derived>::TraverseOpenACCConstructStmt(
3919+
OpenACCConstructStmt *) {
3920+
// TODO OpenACC: When we implement clauses, ensure we traverse them here.
3921+
return true;
3922+
}
3923+
3924+
template <typename Derived>
3925+
bool RecursiveASTVisitor<Derived>::TraverseOpenACCAssociatedStmtConstruct(
3926+
OpenACCAssociatedStmtConstruct *S) {
3927+
TRY_TO(TraverseOpenACCConstructStmt(S));
3928+
TRY_TO(TraverseStmt(S->getAssociatedStmt()));
3929+
return true;
3930+
}
3931+
3932+
DEF_TRAVERSE_STMT(OpenACCComputeConstruct,
3933+
{ TRY_TO(TraverseOpenACCAssociatedStmtConstruct(S)); })
3934+
39133935
// FIXME: look at the following tricky-seeming exprs to see if we
39143936
// need to recurse on anything. These are ones that have methods
39153937
// returning decls or qualtypes or nestednamespecifier -- though I'm

clang/include/clang/AST/StmtOpenACC.h

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
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

clang/include/clang/AST/StmtVisitor.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@
1313
#ifndef LLVM_CLANG_AST_STMTVISITOR_H
1414
#define LLVM_CLANG_AST_STMTVISITOR_H
1515

16-
#include "clang/AST/ExprConcepts.h"
1716
#include "clang/AST/ExprCXX.h"
17+
#include "clang/AST/ExprConcepts.h"
1818
#include "clang/AST/ExprObjC.h"
1919
#include "clang/AST/ExprOpenMP.h"
2020
#include "clang/AST/Stmt.h"
2121
#include "clang/AST/StmtCXX.h"
2222
#include "clang/AST/StmtObjC.h"
23+
#include "clang/AST/StmtOpenACC.h"
2324
#include "clang/AST/StmtOpenMP.h"
2425
#include "clang/Basic/LLVM.h"
2526
#include "llvm/ADT/STLExtras.h"

clang/include/clang/AST/TextNodeDumper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,7 @@ class TextNodeDumper
401401
void
402402
VisitLifetimeExtendedTemporaryDecl(const LifetimeExtendedTemporaryDecl *D);
403403
void VisitHLSLBufferDecl(const HLSLBufferDecl *D);
404+
void VisitOpenACCConstructStmt(const OpenACCConstructStmt *S);
404405
};
405406

406407
} // namespace clang

clang/include/clang/Basic/OpenACCKinds.h

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "clang/Basic/Diagnostic.h"
1818
#include "llvm/Support/ErrorHandling.h"
19+
#include "llvm/Support/raw_ostream.h"
1920

2021
namespace clang {
2122
// Represents the Construct/Directive kind of a pragma directive. Note the
@@ -65,8 +66,9 @@ enum class OpenACCDirectiveKind {
6566
Invalid,
6667
};
6768

68-
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out,
69-
OpenACCDirectiveKind K) {
69+
template <typename StreamTy>
70+
inline StreamTy &PrintOpenACCDirectiveKind(StreamTy &Out,
71+
OpenACCDirectiveKind K) {
7072
switch (K) {
7173
case OpenACCDirectiveKind::Parallel:
7274
return Out << "parallel";
@@ -134,6 +136,16 @@ inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out,
134136
llvm_unreachable("Uncovered directive kind");
135137
}
136138

139+
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out,
140+
OpenACCDirectiveKind K) {
141+
return PrintOpenACCDirectiveKind(Out, K);
142+
}
143+
144+
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &Out,
145+
OpenACCDirectiveKind K) {
146+
return PrintOpenACCDirectiveKind(Out, K);
147+
}
148+
137149
enum class OpenACCAtomicKind {
138150
Read,
139151
Write,
@@ -253,8 +265,8 @@ enum class OpenACCClauseKind {
253265
Invalid,
254266
};
255267

256-
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out,
257-
OpenACCClauseKind K) {
268+
template <typename StreamTy>
269+
inline StreamTy &PrintOpenACCClauseKind(StreamTy &Out, OpenACCClauseKind K) {
258270
switch (K) {
259271
case OpenACCClauseKind::Finalize:
260272
return Out << "finalize";
@@ -387,6 +399,17 @@ inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out,
387399
}
388400
llvm_unreachable("Uncovered clause kind");
389401
}
402+
403+
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out,
404+
OpenACCClauseKind K) {
405+
return PrintOpenACCClauseKind(Out, K);
406+
}
407+
408+
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &Out,
409+
OpenACCClauseKind K) {
410+
return PrintOpenACCClauseKind(Out, K);
411+
}
412+
390413
enum class OpenACCDefaultClauseKind {
391414
/// 'none' option.
392415
None,

clang/include/clang/Basic/StmtNodes.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,3 +296,9 @@ def OMPTargetTeamsGenericLoopDirective : StmtNode<OMPLoopDirective>;
296296
def OMPParallelGenericLoopDirective : StmtNode<OMPLoopDirective>;
297297
def OMPTargetParallelGenericLoopDirective : StmtNode<OMPLoopDirective>;
298298
def OMPErrorDirective : StmtNode<OMPExecutableDirective>;
299+
300+
// OpenACC Constructs.
301+
def OpenACCConstructStmt : StmtNode<Stmt, /*abstract=*/1>;
302+
def OpenACCAssociatedStmtConstruct
303+
: StmtNode<OpenACCConstructStmt, /*abstract=*/1>;
304+
def OpenACCComputeConstruct : StmtNode<OpenACCAssociatedStmtConstruct>;

clang/include/clang/Serialization/ASTBitCodes.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2018,6 +2018,9 @@ enum StmtCode {
20182018

20192019
// SYCLUniqueStableNameExpr
20202020
EXPR_SYCL_UNIQUE_STABLE_NAME,
2021+
2022+
// OpenACC Constructs
2023+
STMT_OPENACC_COMPUTE_CONSTRUCT,
20212024
};
20222025

20232026
/// The kinds of designators that can occur in a

clang/lib/AST/ASTStructuralEquivalence.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
#include "clang/AST/ExprOpenMP.h"
7575
#include "clang/AST/NestedNameSpecifier.h"
7676
#include "clang/AST/StmtObjC.h"
77+
#include "clang/AST/StmtOpenACC.h"
7778
#include "clang/AST/StmtOpenMP.h"
7879
#include "clang/AST/TemplateBase.h"
7980
#include "clang/AST/TemplateName.h"

clang/lib/AST/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ add_clang_library(clangAST
112112
StmtCXX.cpp
113113
StmtIterator.cpp
114114
StmtObjC.cpp
115+
StmtOpenACC.cpp
115116
StmtOpenMP.cpp
116117
StmtPrinter.cpp
117118
StmtProfile.cpp

clang/lib/AST/Stmt.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "clang/AST/ExprOpenMP.h"
2424
#include "clang/AST/StmtCXX.h"
2525
#include "clang/AST/StmtObjC.h"
26+
#include "clang/AST/StmtOpenACC.h"
2627
#include "clang/AST/StmtOpenMP.h"
2728
#include "clang/AST/Type.h"
2829
#include "clang/Basic/CharInfo.h"

clang/lib/AST/StmtOpenACC.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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 subclesses of Stmt class declared in StmtOpenACC.h
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "clang/AST/StmtOpenACC.h"
14+
#include "clang/AST/ASTContext.h"
15+
using namespace clang;
16+
17+
OpenACCComputeConstruct *
18+
OpenACCComputeConstruct::CreateEmpty(const ASTContext &C, EmptyShell) {
19+
void *Mem = C.Allocate(sizeof(OpenACCComputeConstruct),
20+
alignof(OpenACCComputeConstruct));
21+
auto *Inst = new (Mem) OpenACCComputeConstruct;
22+
return Inst;
23+
}
24+
25+
OpenACCComputeConstruct *
26+
OpenACCComputeConstruct::Create(const ASTContext &C, OpenACCDirectiveKind K,
27+
SourceLocation BeginLoc,
28+
SourceLocation EndLoc) {
29+
void *Mem = C.Allocate(sizeof(OpenACCComputeConstruct),
30+
alignof(OpenACCComputeConstruct));
31+
auto *Inst = new (Mem) OpenACCComputeConstruct(K, BeginLoc, EndLoc);
32+
return Inst;
33+
}

clang/lib/AST/StmtPrinter.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,6 +1137,15 @@ void StmtPrinter::VisitOMPTargetParallelGenericLoopDirective(
11371137
PrintOMPExecutableDirective(Node);
11381138
}
11391139

1140+
//===----------------------------------------------------------------------===//
1141+
// OpenACC construct printing methods
1142+
//===----------------------------------------------------------------------===//
1143+
void StmtPrinter::VisitOpenACCComputeConstruct(OpenACCComputeConstruct *S) {
1144+
Indent() << "#pragma acc " << S->getDirectiveKind();
1145+
// TODO OpenACC: Print Clauses.
1146+
PrintStmt(S->getStructuredBlock());
1147+
}
1148+
11401149
//===----------------------------------------------------------------------===//
11411150
// Expr printing methods.
11421151
//===----------------------------------------------------------------------===//

clang/lib/AST/StmtProfile.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2441,6 +2441,13 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) {
24412441
}
24422442
}
24432443

2444+
void StmtProfiler::VisitOpenACCComputeConstruct(
2445+
const OpenACCComputeConstruct *S) {
2446+
// VisitStmt handles children, so the AssociatedStmt is handled.
2447+
VisitStmt(S);
2448+
// TODO OpenACC: Visit Clauses.
2449+
}
2450+
24442451
void Stmt::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
24452452
bool Canonical, bool ProfileLambdaExpr) const {
24462453
StmtProfilerWithPointers Profiler(ID, Context, Canonical, ProfileLambdaExpr);

0 commit comments

Comments
 (0)