Skip to content

Commit 30f6eaf

Browse files
authored
[OpenACC][NFC] Add OpenACC Clause AST Nodes/infrastructure (#87675)
As a first step in adding clause support for OpenACC to Semantic Analysis, this patch adds the 'base' AST nodes required for clauses. This patch has no functional effect at the moment, but followup patches will add the semantic analysis of clauses (plus individual clauses).
1 parent b7593b2 commit 30f6eaf

20 files changed

+439
-27
lines changed

clang/include/clang/AST/ASTNodeTraverser.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ struct {
5353
void Visit(TypeLoc);
5454
void Visit(const Decl *D);
5555
void Visit(const CXXCtorInitializer *Init);
56+
void Visit(const OpenACCClause *C);
5657
void Visit(const OMPClause *C);
5758
void Visit(const BlockDecl::Capture &C);
5859
void Visit(const GenericSelectionExpr::ConstAssociation &A);
@@ -239,6 +240,13 @@ class ASTNodeTraverser
239240
});
240241
}
241242

243+
void Visit(const OpenACCClause *C) {
244+
getNodeDelegate().AddChild([=] {
245+
getNodeDelegate().Visit(C);
246+
// TODO OpenACC: Switch on clauses that have children, and add them.
247+
});
248+
}
249+
242250
void Visit(const OMPClause *C) {
243251
getNodeDelegate().AddChild([=] {
244252
getNodeDelegate().Visit(C);
@@ -799,6 +807,11 @@ class ASTNodeTraverser
799807
Visit(C);
800808
}
801809

810+
void VisitOpenACCConstructStmt(const OpenACCConstructStmt *Node) {
811+
for (const auto *C : Node->clauses())
812+
Visit(C);
813+
}
814+
802815
void VisitInitListExpr(const InitListExpr *ILE) {
803816
if (auto *Filler = ILE->getArrayFiller()) {
804817
Visit(Filler, "array_filler");

clang/include/clang/AST/JSONNodeDumper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ class JSONNodeDumper
203203
void Visit(const TemplateArgument &TA, SourceRange R = {},
204204
const Decl *From = nullptr, StringRef Label = {});
205205
void Visit(const CXXCtorInitializer *Init);
206+
void Visit(const OpenACCClause *C);
206207
void Visit(const OMPClause *C);
207208
void Visit(const BlockDecl::Capture &C);
208209
void Visit(const GenericSelectionExpr::ConstAssociation &A);
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
//===- OpenACCClause.h - Classes for OpenACC clauses ------------*- 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+
//
9+
// \file
10+
// This file defines OpenACC AST classes for clauses.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef LLVM_CLANG_AST_OPENACCCLAUSE_H
15+
#define LLVM_CLANG_AST_OPENACCCLAUSE_H
16+
#include "clang/AST/ASTContext.h"
17+
#include "clang/Basic/OpenACCKinds.h"
18+
19+
namespace clang {
20+
/// This is the base type for all OpenACC Clauses.
21+
class OpenACCClause {
22+
OpenACCClauseKind Kind;
23+
SourceRange Location;
24+
25+
protected:
26+
OpenACCClause(OpenACCClauseKind K, SourceLocation BeginLoc,
27+
SourceLocation EndLoc)
28+
: Kind(K), Location(BeginLoc, EndLoc) {}
29+
30+
public:
31+
OpenACCClauseKind getClauseKind() const { return Kind; }
32+
SourceLocation getBeginLoc() const { return Location.getBegin(); }
33+
SourceLocation getEndLoc() const { return Location.getEnd(); }
34+
35+
static bool classof(const OpenACCClause *) { return true; }
36+
37+
virtual ~OpenACCClause() = default;
38+
};
39+
40+
/// Represents a clause that has a list of parameters.
41+
class OpenACCClauseWithParams : public OpenACCClause {
42+
/// Location of the '('.
43+
SourceLocation LParenLoc;
44+
45+
protected:
46+
OpenACCClauseWithParams(OpenACCClauseKind K, SourceLocation BeginLoc,
47+
SourceLocation LParenLoc, SourceLocation EndLoc)
48+
: OpenACCClause(K, BeginLoc, EndLoc), LParenLoc(LParenLoc) {}
49+
50+
public:
51+
SourceLocation getLParenLoc() const { return LParenLoc; }
52+
};
53+
54+
template <class Impl> class OpenACCClauseVisitor {
55+
Impl &getDerived() { return static_cast<Impl &>(*this); }
56+
57+
public:
58+
void VisitClauseList(ArrayRef<const OpenACCClause *> List) {
59+
for (const OpenACCClause *Clause : List)
60+
Visit(Clause);
61+
}
62+
63+
void Visit(const OpenACCClause *C) {
64+
if (!C)
65+
return;
66+
67+
switch (C->getClauseKind()) {
68+
case OpenACCClauseKind::Default:
69+
case OpenACCClauseKind::Finalize:
70+
case OpenACCClauseKind::IfPresent:
71+
case OpenACCClauseKind::Seq:
72+
case OpenACCClauseKind::Independent:
73+
case OpenACCClauseKind::Auto:
74+
case OpenACCClauseKind::Worker:
75+
case OpenACCClauseKind::Vector:
76+
case OpenACCClauseKind::NoHost:
77+
case OpenACCClauseKind::If:
78+
case OpenACCClauseKind::Self:
79+
case OpenACCClauseKind::Copy:
80+
case OpenACCClauseKind::UseDevice:
81+
case OpenACCClauseKind::Attach:
82+
case OpenACCClauseKind::Delete:
83+
case OpenACCClauseKind::Detach:
84+
case OpenACCClauseKind::Device:
85+
case OpenACCClauseKind::DevicePtr:
86+
case OpenACCClauseKind::DeviceResident:
87+
case OpenACCClauseKind::FirstPrivate:
88+
case OpenACCClauseKind::Host:
89+
case OpenACCClauseKind::Link:
90+
case OpenACCClauseKind::NoCreate:
91+
case OpenACCClauseKind::Present:
92+
case OpenACCClauseKind::Private:
93+
case OpenACCClauseKind::CopyOut:
94+
case OpenACCClauseKind::CopyIn:
95+
case OpenACCClauseKind::Create:
96+
case OpenACCClauseKind::Reduction:
97+
case OpenACCClauseKind::Collapse:
98+
case OpenACCClauseKind::Bind:
99+
case OpenACCClauseKind::VectorLength:
100+
case OpenACCClauseKind::NumGangs:
101+
case OpenACCClauseKind::NumWorkers:
102+
case OpenACCClauseKind::DeviceNum:
103+
case OpenACCClauseKind::DefaultAsync:
104+
case OpenACCClauseKind::DeviceType:
105+
case OpenACCClauseKind::DType:
106+
case OpenACCClauseKind::Async:
107+
case OpenACCClauseKind::Tile:
108+
case OpenACCClauseKind::Gang:
109+
case OpenACCClauseKind::Wait:
110+
case OpenACCClauseKind::Invalid:
111+
llvm_unreachable("Clause visitor not yet implemented");
112+
}
113+
llvm_unreachable("Invalid Clause kind");
114+
}
115+
};
116+
117+
class OpenACCClausePrinter final
118+
: public OpenACCClauseVisitor<OpenACCClausePrinter> {
119+
raw_ostream &OS;
120+
121+
public:
122+
void VisitClauseList(ArrayRef<const OpenACCClause *> List) {
123+
for (const OpenACCClause *Clause : List) {
124+
Visit(Clause);
125+
126+
if (Clause != List.back())
127+
OS << ' ';
128+
}
129+
}
130+
OpenACCClausePrinter(raw_ostream &OS) : OS(OS) {}
131+
};
132+
133+
} // namespace clang
134+
135+
#endif // LLVM_CLANG_AST_OPENACCCLAUSE_H

clang/include/clang/AST/RecursiveASTVisitor.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,7 @@ template <typename Derived> class RecursiveASTVisitor {
509509
bool TraverseOpenACCConstructStmt(OpenACCConstructStmt *S);
510510
bool
511511
TraverseOpenACCAssociatedStmtConstruct(OpenACCAssociatedStmtConstruct *S);
512+
bool VisitOpenACCClauseList(ArrayRef<const OpenACCClause *>);
512513
};
513514

514515
template <typename Derived>
@@ -3936,8 +3937,8 @@ bool RecursiveASTVisitor<Derived>::VisitOMPXBareClause(OMPXBareClause *C) {
39363937

39373938
template <typename Derived>
39383939
bool RecursiveASTVisitor<Derived>::TraverseOpenACCConstructStmt(
3939-
OpenACCConstructStmt *) {
3940-
// TODO OpenACC: When we implement clauses, ensure we traverse them here.
3940+
OpenACCConstructStmt *C) {
3941+
TRY_TO(VisitOpenACCClauseList(C->clauses()));
39413942
return true;
39423943
}
39433944

@@ -3949,6 +3950,14 @@ bool RecursiveASTVisitor<Derived>::TraverseOpenACCAssociatedStmtConstruct(
39493950
return true;
39503951
}
39513952

3953+
template <typename Derived>
3954+
bool RecursiveASTVisitor<Derived>::VisitOpenACCClauseList(
3955+
ArrayRef<const OpenACCClause *>) {
3956+
// TODO OpenACC: When we have Clauses with expressions, we should visit them
3957+
// here.
3958+
return true;
3959+
}
3960+
39523961
DEF_TRAVERSE_STMT(OpenACCComputeConstruct,
39533962
{ TRY_TO(TraverseOpenACCAssociatedStmtConstruct(S)); })
39543963

clang/include/clang/AST/StmtOpenACC.h

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@
1313
#ifndef LLVM_CLANG_AST_STMTOPENACC_H
1414
#define LLVM_CLANG_AST_STMTOPENACC_H
1515

16+
#include "clang/AST/OpenACCClause.h"
1617
#include "clang/AST/Stmt.h"
1718
#include "clang/Basic/OpenACCKinds.h"
1819
#include "clang/Basic/SourceLocation.h"
20+
#include <memory>
1921

2022
namespace clang {
2123
/// This is the base class for an OpenACC statement-level construct, other
@@ -30,13 +32,23 @@ class OpenACCConstructStmt : public Stmt {
3032
/// the directive.
3133
SourceRange Range;
3234

33-
// TODO OPENACC: Clauses should probably be collected in this class.
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;
3439

3540
protected:
3641
OpenACCConstructStmt(StmtClass SC, OpenACCDirectiveKind K,
3742
SourceLocation Start, SourceLocation End)
3843
: Stmt(SC), Kind(K), Range(Start, End) {}
3944

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+
4052
public:
4153
OpenACCDirectiveKind getDirectiveKind() const { return Kind; }
4254

@@ -47,6 +59,7 @@ class OpenACCConstructStmt : public Stmt {
4759

4860
SourceLocation getBeginLoc() const { return Range.getBegin(); }
4961
SourceLocation getEndLoc() const { return Range.getEnd(); }
62+
ArrayRef<const OpenACCClause *> clauses() const { return Clauses; }
5063

5164
child_range children() {
5265
return child_range(child_iterator(), child_iterator());
@@ -101,24 +114,46 @@ class OpenACCAssociatedStmtConstruct : public OpenACCConstructStmt {
101114
/// those three, as they are semantically identical, and have only minor
102115
/// differences in the permitted list of clauses, which can be differentiated by
103116
/// the 'Kind'.
104-
class OpenACCComputeConstruct : public OpenACCAssociatedStmtConstruct {
117+
class OpenACCComputeConstruct final
118+
: public OpenACCAssociatedStmtConstruct,
119+
public llvm::TrailingObjects<OpenACCComputeConstruct,
120+
const OpenACCClause *> {
105121
friend class ASTStmtWriter;
106122
friend class ASTStmtReader;
107123
friend class ASTContext;
108-
OpenACCComputeConstruct()
109-
: OpenACCAssociatedStmtConstruct(
110-
OpenACCComputeConstructClass, OpenACCDirectiveKind::Invalid,
111-
SourceLocation{}, SourceLocation{}, /*AssociatedStmt=*/nullptr) {}
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+
getTrailingObjects<const OpenACCClause *>(),
134+
getTrailingObjects<const OpenACCClause *>() + NumClauses);
135+
setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
136+
NumClauses));
137+
}
112138

113139
OpenACCComputeConstruct(OpenACCDirectiveKind K, SourceLocation Start,
114-
SourceLocation End, Stmt *StructuredBlock)
140+
SourceLocation End,
141+
ArrayRef<const OpenACCClause *> Clauses,
142+
Stmt *StructuredBlock)
115143
: OpenACCAssociatedStmtConstruct(OpenACCComputeConstructClass, K, Start,
116144
End, StructuredBlock) {
117145
assert((K == OpenACCDirectiveKind::Parallel ||
118146
K == OpenACCDirectiveKind::Serial ||
119147
K == OpenACCDirectiveKind::Kernels) &&
120148
"Only parallel, serial, and kernels constructs should be "
121149
"represented by this type");
150+
151+
// Initialize the trailing storage.
152+
std::uninitialized_copy(Clauses.begin(), Clauses.end(),
153+
getTrailingObjects<const OpenACCClause *>());
154+
155+
setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
156+
Clauses.size()));
122157
}
123158

124159
void setStructuredBlock(Stmt *S) { setAssociatedStmt(S); }
@@ -128,10 +163,12 @@ class OpenACCComputeConstruct : public OpenACCAssociatedStmtConstruct {
128163
return T->getStmtClass() == OpenACCComputeConstructClass;
129164
}
130165

131-
static OpenACCComputeConstruct *CreateEmpty(const ASTContext &C, EmptyShell);
166+
static OpenACCComputeConstruct *CreateEmpty(const ASTContext &C,
167+
unsigned NumClauses);
132168
static OpenACCComputeConstruct *
133169
Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation BeginLoc,
134-
SourceLocation EndLoc, Stmt *StructuredBlock);
170+
SourceLocation EndLoc, ArrayRef<const OpenACCClause *> Clauses,
171+
Stmt *StructuredBlock);
135172

136173
Stmt *getStructuredBlock() { return getAssociatedStmt(); }
137174
const Stmt *getStructuredBlock() const {

clang/include/clang/AST/TextNodeDumper.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ class TextNodeDumper
189189

190190
void Visit(const OMPClause *C);
191191

192+
void Visit(const OpenACCClause *C);
193+
192194
void Visit(const BlockDecl::Capture &C);
193195

194196
void Visit(const GenericSelectionExpr::ConstAssociation &A);

clang/include/clang/Serialization/ASTRecordReader.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "llvm/ADT/APSInt.h"
2525

2626
namespace clang {
27+
class OpenACCClause;
2728
class OMPTraitInfo;
2829
class OMPChildren;
2930

@@ -278,6 +279,12 @@ class ASTRecordReader
278279
/// Read an OpenMP children, advancing Idx.
279280
void readOMPChildren(OMPChildren *Data);
280281

282+
/// Read an OpenACC clause, advancing Idx.
283+
OpenACCClause *readOpenACCClause();
284+
285+
/// Read a list of OpenACC clauses into the passed SmallVector.
286+
void readOpenACCClauseList(MutableArrayRef<const OpenACCClause *> Clauses);
287+
281288
/// Read a source location, advancing Idx.
282289
SourceLocation readSourceLocation(LocSeq *Seq = nullptr) {
283290
return Reader->ReadSourceLocation(*F, Record, Idx, Seq);

clang/include/clang/Serialization/ASTRecordWriter.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
namespace clang {
2323

24+
class OpenACCClause;
2425
class TypeLoc;
2526

2627
/// An object for streaming information to a record.
@@ -292,6 +293,12 @@ class ASTRecordWriter
292293
/// Writes data related to the OpenMP directives.
293294
void writeOMPChildren(OMPChildren *Data);
294295

296+
/// Writes out a single OpenACC Clause.
297+
void writeOpenACCClause(const OpenACCClause *C);
298+
299+
/// Writes out a list of OpenACC clauses.
300+
void writeOpenACCClauseList(ArrayRef<const OpenACCClause *> Clauses);
301+
295302
/// Emit a string.
296303
void AddString(StringRef Str) {
297304
return Writer->AddString(Str, *Record);

clang/lib/AST/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ add_clang_library(clangAST
9898
NSAPI.cpp
9999
ODRDiagsEmitter.cpp
100100
ODRHash.cpp
101+
OpenACCClause.cpp
101102
OpenMPClause.cpp
102103
OSLog.cpp
103104
ParentMap.cpp

clang/lib/AST/JSONNodeDumper.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,8 @@ void JSONNodeDumper::Visit(const CXXCtorInitializer *Init) {
187187
llvm_unreachable("Unknown initializer type");
188188
}
189189

190+
void JSONNodeDumper::Visit(const OpenACCClause *C) {}
191+
190192
void JSONNodeDumper::Visit(const OMPClause *C) {}
191193

192194
void JSONNodeDumper::Visit(const BlockDecl::Capture &C) {

0 commit comments

Comments
 (0)