clang 20.0.0 (based on r547379) from build 12806354. Bug: http://b/379133546 Test: N/A Change-Id: I2eb8938af55d809de674be63cb30cf27e801862b Upstream-Commit: ad834e67b1105d15ef907f6255d4c96e8e733f57
257 lines
10 KiB
C++
257 lines
10 KiB
C++
//===- StmtOpenACC.h - Classes for OpenACC directives ----------*- 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 statement-level contructs.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#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
|
|
/// construct types are expected to inherit from this.
|
|
class OpenACCConstructStmt : public Stmt {
|
|
friend class ASTStmtWriter;
|
|
friend class ASTStmtReader;
|
|
/// The directive kind. Each implementation of this interface should handle
|
|
/// specific kinds.
|
|
OpenACCDirectiveKind Kind = OpenACCDirectiveKind::Invalid;
|
|
/// The location of the directive statement, from the '#' to the last token of
|
|
/// the directive.
|
|
SourceRange Range;
|
|
/// The location of the directive name.
|
|
SourceLocation DirectiveLoc;
|
|
|
|
/// 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;
|
|
|
|
protected:
|
|
OpenACCConstructStmt(StmtClass SC, OpenACCDirectiveKind K,
|
|
SourceLocation Start, SourceLocation DirectiveLoc,
|
|
SourceLocation End)
|
|
: Stmt(SC), Kind(K), Range(Start, End), DirectiveLoc(DirectiveLoc) {}
|
|
|
|
// Used only for initialization, the leaf class can initialize this to
|
|
// trailing storage.
|
|
void setClauseList(MutableArrayRef<const OpenACCClause *> NewClauses) {
|
|
assert(Clauses.empty() && "Cannot change clause list");
|
|
Clauses = NewClauses;
|
|
}
|
|
|
|
public:
|
|
OpenACCDirectiveKind getDirectiveKind() const { return Kind; }
|
|
|
|
static bool classof(const Stmt *S) {
|
|
return S->getStmtClass() >= firstOpenACCConstructStmtConstant &&
|
|
S->getStmtClass() <= lastOpenACCConstructStmtConstant;
|
|
}
|
|
|
|
SourceLocation getBeginLoc() const { return Range.getBegin(); }
|
|
SourceLocation getEndLoc() const { return Range.getEnd(); }
|
|
SourceLocation getDirectiveLoc() const { return DirectiveLoc; }
|
|
ArrayRef<const OpenACCClause *> clauses() const { return Clauses; }
|
|
|
|
child_range children() {
|
|
return child_range(child_iterator(), child_iterator());
|
|
}
|
|
|
|
const_child_range children() const {
|
|
return const_cast<OpenACCConstructStmt *>(this)->children();
|
|
}
|
|
};
|
|
|
|
/// This is a base class for any OpenACC statement-level constructs that have an
|
|
/// associated statement. This class is not intended to be instantiated, but is
|
|
/// a convenient place to hold the associated statement.
|
|
class OpenACCAssociatedStmtConstruct : public OpenACCConstructStmt {
|
|
friend class ASTStmtWriter;
|
|
friend class ASTStmtReader;
|
|
template <typename Derived> friend class RecursiveASTVisitor;
|
|
Stmt *AssociatedStmt = nullptr;
|
|
|
|
protected:
|
|
OpenACCAssociatedStmtConstruct(StmtClass SC, OpenACCDirectiveKind K,
|
|
SourceLocation Start,
|
|
SourceLocation DirectiveLoc,
|
|
SourceLocation End, Stmt *AssocStmt)
|
|
: OpenACCConstructStmt(SC, K, Start, DirectiveLoc, End),
|
|
AssociatedStmt(AssocStmt) {}
|
|
|
|
void setAssociatedStmt(Stmt *S) { AssociatedStmt = S; }
|
|
Stmt *getAssociatedStmt() { return AssociatedStmt; }
|
|
const Stmt *getAssociatedStmt() const {
|
|
return const_cast<OpenACCAssociatedStmtConstruct *>(this)
|
|
->getAssociatedStmt();
|
|
}
|
|
|
|
public:
|
|
static bool classof(const Stmt *T) {
|
|
return false;
|
|
}
|
|
|
|
child_range children() {
|
|
if (getAssociatedStmt())
|
|
return child_range(&AssociatedStmt, &AssociatedStmt + 1);
|
|
return child_range(child_iterator(), child_iterator());
|
|
}
|
|
|
|
const_child_range children() const {
|
|
return const_cast<OpenACCAssociatedStmtConstruct *>(this)->children();
|
|
}
|
|
};
|
|
|
|
class OpenACCLoopConstruct;
|
|
/// This class represents a compute construct, representing a 'Kind' of
|
|
/// `parallel', 'serial', or 'kernel'. These constructs are associated with a
|
|
/// 'structured block', defined as:
|
|
///
|
|
/// in C or C++, an executable statement, possibly compound, with a single
|
|
/// entry at the top and a single exit at the bottom
|
|
///
|
|
/// At the moment there is no real motivation to have a different AST node for
|
|
/// 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 final
|
|
: public OpenACCAssociatedStmtConstruct,
|
|
public llvm::TrailingObjects<OpenACCComputeConstruct,
|
|
const OpenACCClause *> {
|
|
friend class ASTStmtWriter;
|
|
friend class ASTStmtReader;
|
|
friend class ASTContext;
|
|
OpenACCComputeConstruct(unsigned NumClauses)
|
|
: OpenACCAssociatedStmtConstruct(
|
|
OpenACCComputeConstructClass, OpenACCDirectiveKind::Invalid,
|
|
SourceLocation{}, 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 DirectiveLoc, SourceLocation End,
|
|
ArrayRef<const OpenACCClause *> Clauses,
|
|
Stmt *StructuredBlock)
|
|
: OpenACCAssociatedStmtConstruct(OpenACCComputeConstructClass, K, Start,
|
|
DirectiveLoc, End, StructuredBlock) {
|
|
assert(isOpenACCComputeDirectiveKind(K) &&
|
|
"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); }
|
|
// Serialization helper function that searches the structured block for 'loop'
|
|
// constructs that should be associated with this, and sets their parent
|
|
// compute construct to this one. This isn't necessary normally, since we have
|
|
// the ability to record the state during parsing.
|
|
void findAndSetChildLoops();
|
|
|
|
public:
|
|
static bool classof(const Stmt *T) {
|
|
return T->getStmtClass() == OpenACCComputeConstructClass;
|
|
}
|
|
|
|
static OpenACCComputeConstruct *CreateEmpty(const ASTContext &C,
|
|
unsigned NumClauses);
|
|
static OpenACCComputeConstruct *
|
|
Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation BeginLoc,
|
|
SourceLocation DirectiveLoc, SourceLocation EndLoc,
|
|
ArrayRef<const OpenACCClause *> Clauses, Stmt *StructuredBlock,
|
|
ArrayRef<OpenACCLoopConstruct *> AssociatedLoopConstructs);
|
|
|
|
Stmt *getStructuredBlock() { return getAssociatedStmt(); }
|
|
const Stmt *getStructuredBlock() const {
|
|
return const_cast<OpenACCComputeConstruct *>(this)->getStructuredBlock();
|
|
}
|
|
};
|
|
/// This class represents a 'loop' construct. The 'loop' construct applies to a
|
|
/// 'for' loop (or range-for loop), and is optionally associated with a Compute
|
|
/// Construct.
|
|
class OpenACCLoopConstruct final
|
|
: public OpenACCAssociatedStmtConstruct,
|
|
public llvm::TrailingObjects<OpenACCLoopConstruct,
|
|
const OpenACCClause *> {
|
|
// The compute construct this loop is associated with, or nullptr if this is
|
|
// an orphaned loop construct, or if it hasn't been set yet. Because we
|
|
// construct the directives at the end of their statement, the 'parent'
|
|
// construct is not yet available at the time of construction, so this needs
|
|
// to be set 'later'.
|
|
const OpenACCComputeConstruct *ParentComputeConstruct = nullptr;
|
|
|
|
friend class ASTStmtWriter;
|
|
friend class ASTStmtReader;
|
|
friend class ASTContext;
|
|
friend class OpenACCComputeConstruct;
|
|
|
|
OpenACCLoopConstruct(unsigned NumClauses);
|
|
|
|
OpenACCLoopConstruct(SourceLocation Start, SourceLocation DirLoc,
|
|
SourceLocation End,
|
|
ArrayRef<const OpenACCClause *> Clauses, Stmt *Loop);
|
|
void setLoop(Stmt *Loop);
|
|
|
|
void setParentComputeConstruct(OpenACCComputeConstruct *CC) {
|
|
assert(!ParentComputeConstruct && "Parent already set?");
|
|
ParentComputeConstruct = CC;
|
|
}
|
|
|
|
public:
|
|
static bool classof(const Stmt *T) {
|
|
return T->getStmtClass() == OpenACCLoopConstructClass;
|
|
}
|
|
|
|
static OpenACCLoopConstruct *CreateEmpty(const ASTContext &C,
|
|
unsigned NumClauses);
|
|
|
|
static OpenACCLoopConstruct *
|
|
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation DirLoc,
|
|
SourceLocation EndLoc, ArrayRef<const OpenACCClause *> Clauses,
|
|
Stmt *Loop);
|
|
|
|
Stmt *getLoop() { return getAssociatedStmt(); }
|
|
const Stmt *getLoop() const {
|
|
return const_cast<OpenACCLoopConstruct *>(this)->getLoop();
|
|
}
|
|
|
|
/// OpenACC 3.3 2.9:
|
|
/// An orphaned loop construct is a loop construct that is not lexically
|
|
/// enclosed within a compute construct. The parent compute construct of a
|
|
/// loop construct is the nearest compute construct that lexically contains
|
|
/// the loop construct.
|
|
bool isOrphanedLoopConstruct() const {
|
|
return ParentComputeConstruct == nullptr;
|
|
}
|
|
const OpenACCComputeConstruct *getParentComputeConstruct() const {
|
|
return ParentComputeConstruct;
|
|
}
|
|
};
|
|
} // namespace clang
|
|
#endif // LLVM_CLANG_AST_STMTOPENACC_H
|