-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[OpenACC][NFC] Add OpenACC Clause AST Nodes/infrastructure #87675
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
//===- OpenACCClause.h - Classes for OpenACC clauses ------------*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// \file | ||
// This file defines OpenACC AST classes for clauses. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_CLANG_AST_OPENACCCLAUSE_H | ||
#define LLVM_CLANG_AST_OPENACCCLAUSE_H | ||
#include "clang/AST/ASTContext.h" | ||
#include "clang/Basic/OpenACCKinds.h" | ||
|
||
namespace clang { | ||
/// This is the base type for all OpenACC Clauses. | ||
class OpenACCClause { | ||
OpenACCClauseKind Kind; | ||
SourceRange Location; | ||
|
||
protected: | ||
OpenACCClause(OpenACCClauseKind K, SourceLocation BeginLoc, | ||
SourceLocation EndLoc) | ||
: Kind(K), Location(BeginLoc, EndLoc) {} | ||
|
||
public: | ||
OpenACCClauseKind getClauseKind() const { return Kind; } | ||
SourceLocation getBeginLoc() const { return Location.getBegin(); } | ||
SourceLocation getEndLoc() const { return Location.getEnd(); } | ||
|
||
static bool classof(const OpenACCClause *) { return true; } | ||
|
||
virtual ~OpenACCClause() = default; | ||
}; | ||
|
||
/// Represents a clause that has a list of parameters. | ||
class OpenACCClauseWithParams : public OpenACCClause { | ||
/// Location of the '('. | ||
SourceLocation LParenLoc; | ||
|
||
protected: | ||
OpenACCClauseWithParams(OpenACCClauseKind K, SourceLocation BeginLoc, | ||
SourceLocation LParenLoc, SourceLocation EndLoc) | ||
: OpenACCClause(K, BeginLoc, EndLoc), LParenLoc(LParenLoc) {} | ||
|
||
public: | ||
SourceLocation getLParenLoc() const { return LParenLoc; } | ||
}; | ||
|
||
template <class Impl> class OpenACCClauseVisitor { | ||
Impl &getDerived() { return static_cast<Impl &>(*this); } | ||
|
||
public: | ||
void VisitClauseList(ArrayRef<const OpenACCClause *> List) { | ||
for (const OpenACCClause *Clause : List) | ||
Visit(Clause); | ||
} | ||
|
||
void Visit(const OpenACCClause *C) { | ||
if (!C) | ||
return; | ||
|
||
switch (C->getClauseKind()) { | ||
case OpenACCClauseKind::Default: | ||
case OpenACCClauseKind::Finalize: | ||
case OpenACCClauseKind::IfPresent: | ||
case OpenACCClauseKind::Seq: | ||
case OpenACCClauseKind::Independent: | ||
case OpenACCClauseKind::Auto: | ||
case OpenACCClauseKind::Worker: | ||
case OpenACCClauseKind::Vector: | ||
case OpenACCClauseKind::NoHost: | ||
case OpenACCClauseKind::If: | ||
case OpenACCClauseKind::Self: | ||
case OpenACCClauseKind::Copy: | ||
case OpenACCClauseKind::UseDevice: | ||
case OpenACCClauseKind::Attach: | ||
case OpenACCClauseKind::Delete: | ||
case OpenACCClauseKind::Detach: | ||
case OpenACCClauseKind::Device: | ||
case OpenACCClauseKind::DevicePtr: | ||
case OpenACCClauseKind::DeviceResident: | ||
case OpenACCClauseKind::FirstPrivate: | ||
case OpenACCClauseKind::Host: | ||
case OpenACCClauseKind::Link: | ||
case OpenACCClauseKind::NoCreate: | ||
case OpenACCClauseKind::Present: | ||
case OpenACCClauseKind::Private: | ||
case OpenACCClauseKind::CopyOut: | ||
case OpenACCClauseKind::CopyIn: | ||
case OpenACCClauseKind::Create: | ||
case OpenACCClauseKind::Reduction: | ||
case OpenACCClauseKind::Collapse: | ||
case OpenACCClauseKind::Bind: | ||
case OpenACCClauseKind::VectorLength: | ||
case OpenACCClauseKind::NumGangs: | ||
case OpenACCClauseKind::NumWorkers: | ||
case OpenACCClauseKind::DeviceNum: | ||
case OpenACCClauseKind::DefaultAsync: | ||
case OpenACCClauseKind::DeviceType: | ||
case OpenACCClauseKind::DType: | ||
case OpenACCClauseKind::Async: | ||
case OpenACCClauseKind::Tile: | ||
case OpenACCClauseKind::Gang: | ||
case OpenACCClauseKind::Wait: | ||
case OpenACCClauseKind::Invalid: | ||
llvm_unreachable("Clause visitor not yet implemented"); | ||
} | ||
llvm_unreachable("Invalid Clause kind"); | ||
} | ||
}; | ||
|
||
class OpenACCClausePrinter final | ||
: public OpenACCClauseVisitor<OpenACCClausePrinter> { | ||
raw_ostream &OS; | ||
|
||
public: | ||
void VisitClauseList(ArrayRef<const OpenACCClause *> List) { | ||
for (const OpenACCClause *Clause : List) { | ||
Visit(Clause); | ||
|
||
if (Clause != List.back()) | ||
OS << ' '; | ||
} | ||
} | ||
OpenACCClausePrinter(raw_ostream &OS) : OS(OS) {} | ||
}; | ||
|
||
} // namespace clang | ||
|
||
#endif // LLVM_CLANG_AST_OPENACCCLAUSE_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,9 +13,11 @@ | |
#ifndef LLVM_CLANG_AST_STMTOPENACC_H | ||
#define LLVM_CLANG_AST_STMTOPENACC_H | ||
|
||
#include "clang/AST/OpenACCClause.h" | ||
#include "clang/AST/Stmt.h" | ||
#include "clang/Basic/OpenACCKinds.h" | ||
#include "clang/Basic/SourceLocation.h" | ||
#include <memory> | ||
|
||
namespace clang { | ||
/// This is the base class for an OpenACC statement-level construct, other | ||
|
@@ -30,13 +32,23 @@ class OpenACCConstructStmt : public Stmt { | |
/// the directive. | ||
SourceRange Range; | ||
|
||
// TODO OPENACC: Clauses should probably be collected in this class. | ||
/// The list of clauses. This is stored here as an ArrayRef, as this is the | ||
/// most convienient place to access the list, however the list itself should | ||
/// be stored in leaf nodes, likely in trailing-storage. | ||
MutableArrayRef<const OpenACCClause *> Clauses; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why need to keep as MutbleArrayRef, not just ArrayRef? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unfortunately de-Serialization means we have to be able to modify the elements. See ASTReaderStmt.cpp:2790 here. |
||
|
||
protected: | ||
OpenACCConstructStmt(StmtClass SC, OpenACCDirectiveKind K, | ||
SourceLocation Start, SourceLocation End) | ||
: Stmt(SC), Kind(K), Range(Start, End) {} | ||
|
||
// Used only for initialization, the leaf class can initialize this to | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This ends up being necessary because the trailing storage isn't initialized when we do construction, so the derived classes need to set this after this class is constructed (and their trailing storage base is legal to do stuff with). |
||
// trailing storage. | ||
void setClauseList(MutableArrayRef<const OpenACCClause *> NewClauses) { | ||
assert(Clauses.empty() && "Cannot change clause list"); | ||
Clauses = NewClauses; | ||
} | ||
|
||
public: | ||
OpenACCDirectiveKind getDirectiveKind() const { return Kind; } | ||
|
||
|
@@ -47,6 +59,7 @@ class OpenACCConstructStmt : public Stmt { | |
|
||
SourceLocation getBeginLoc() const { return Range.getBegin(); } | ||
SourceLocation getEndLoc() const { return Range.getEnd(); } | ||
ArrayRef<const OpenACCClause *> clauses() const { return Clauses; } | ||
|
||
child_range children() { | ||
return child_range(child_iterator(), child_iterator()); | ||
|
@@ -101,24 +114,46 @@ class OpenACCAssociatedStmtConstruct : public OpenACCConstructStmt { | |
/// those three, as they are semantically identical, and have only minor | ||
/// differences in the permitted list of clauses, which can be differentiated by | ||
/// the 'Kind'. | ||
class OpenACCComputeConstruct : public OpenACCAssociatedStmtConstruct { | ||
class OpenACCComputeConstruct final | ||
: public OpenACCAssociatedStmtConstruct, | ||
public llvm::TrailingObjects<OpenACCComputeConstruct, | ||
const OpenACCClause *> { | ||
friend class ASTStmtWriter; | ||
friend class ASTStmtReader; | ||
friend class ASTContext; | ||
OpenACCComputeConstruct() | ||
: OpenACCAssociatedStmtConstruct( | ||
OpenACCComputeConstructClass, OpenACCDirectiveKind::Invalid, | ||
SourceLocation{}, SourceLocation{}, /*AssociatedStmt=*/nullptr) {} | ||
OpenACCComputeConstruct(unsigned NumClauses) | ||
: OpenACCAssociatedStmtConstruct(OpenACCComputeConstructClass, | ||
OpenACCDirectiveKind::Invalid, | ||
SourceLocation{}, SourceLocation{}, | ||
/*AssociatedStmt=*/nullptr) { | ||
// We cannot send the TrailingObjects storage to the base class (which holds | ||
// a reference to the data) until it is constructed, so we have to set it | ||
// separately here. | ||
std::uninitialized_value_construct( | ||
getTrailingObjects<const OpenACCClause *>(), | ||
getTrailingObjects<const OpenACCClause *>() + NumClauses); | ||
setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), | ||
NumClauses)); | ||
} | ||
|
||
OpenACCComputeConstruct(OpenACCDirectiveKind K, SourceLocation Start, | ||
SourceLocation End, Stmt *StructuredBlock) | ||
SourceLocation End, | ||
ArrayRef<const OpenACCClause *> Clauses, | ||
Stmt *StructuredBlock) | ||
: OpenACCAssociatedStmtConstruct(OpenACCComputeConstructClass, K, Start, | ||
End, StructuredBlock) { | ||
assert((K == OpenACCDirectiveKind::Parallel || | ||
K == OpenACCDirectiveKind::Serial || | ||
K == OpenACCDirectiveKind::Kernels) && | ||
"Only parallel, serial, and kernels constructs should be " | ||
"represented by this type"); | ||
|
||
// Initialize the trailing storage. | ||
std::uninitialized_copy(Clauses.begin(), Clauses.end(), | ||
getTrailingObjects<const OpenACCClause *>()); | ||
|
||
setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), | ||
Clauses.size())); | ||
} | ||
|
||
void setStructuredBlock(Stmt *S) { setAssociatedStmt(S); } | ||
|
@@ -128,10 +163,12 @@ class OpenACCComputeConstruct : public OpenACCAssociatedStmtConstruct { | |
return T->getStmtClass() == OpenACCComputeConstructClass; | ||
} | ||
|
||
static OpenACCComputeConstruct *CreateEmpty(const ASTContext &C, EmptyShell); | ||
static OpenACCComputeConstruct *CreateEmpty(const ASTContext &C, | ||
unsigned NumClauses); | ||
static OpenACCComputeConstruct * | ||
Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation BeginLoc, | ||
SourceLocation EndLoc, Stmt *StructuredBlock); | ||
SourceLocation EndLoc, ArrayRef<const OpenACCClause *> Clauses, | ||
Stmt *StructuredBlock); | ||
|
||
Stmt *getStructuredBlock() { return getAssociatedStmt(); } | ||
const Stmt *getStructuredBlock() const { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of this patch is just boilerplate, but THIS decision I think is the important one. I could EITHER have the base clause store an
llvm::SmallVector
of clause pointers, OR do the trailing storage trick I'm doing here. The trailing-storage seemed closest to being what OMP does, but is a bit extra rigamarole to make work.