saqut-compiler/llvm/include/clang/AST/OpenACCClause.h

1508 lines
56 KiB
C++

//===- 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/AST/StmtIterator.h"
#include "clang/Basic/OpenACCKinds.h"
#include "llvm/ADT/STLExtras.h"
#include <utility>
#include <variant>
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) {
assert(!BeginLoc.isInvalid() && !EndLoc.isInvalid() &&
"Begin and end location must be valid for OpenACCClause");
}
public:
OpenACCClauseKind getClauseKind() const { return Kind; }
SourceLocation getBeginLoc() const { return Location.getBegin(); }
SourceLocation getEndLoc() const { return Location.getEnd(); }
SourceRange getSourceRange() const { return Location; }
static bool classof(const OpenACCClause *) { return true; }
using child_iterator = StmtIterator;
using const_child_iterator = ConstStmtIterator;
using child_range = llvm::iterator_range<child_iterator>;
using const_child_range = llvm::iterator_range<const_child_iterator>;
child_range children();
const_child_range children() const {
return const_cast<OpenACCClause *>(this)->children();
}
virtual ~OpenACCClause() = default;
};
// Represents the 'auto' clause.
class OpenACCAutoClause : public OpenACCClause {
protected:
OpenACCAutoClause(SourceLocation BeginLoc, SourceLocation EndLoc)
: OpenACCClause(OpenACCClauseKind::Auto, BeginLoc, EndLoc) {}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Auto;
}
static OpenACCAutoClause *
Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
child_range children() {
return child_range(child_iterator(), child_iterator());
}
const_child_range children() const {
return const_child_range(const_child_iterator(), const_child_iterator());
}
};
// Represents the 'finalize' clause.
class OpenACCFinalizeClause : public OpenACCClause {
protected:
OpenACCFinalizeClause(SourceLocation BeginLoc, SourceLocation EndLoc)
: OpenACCClause(OpenACCClauseKind::Finalize, BeginLoc, EndLoc) {}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Finalize;
}
static OpenACCFinalizeClause *
Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
child_range children() {
return child_range(child_iterator(), child_iterator());
}
const_child_range children() const {
return const_child_range(const_child_iterator(), const_child_iterator());
}
};
// Represents the 'if_present' clause.
class OpenACCIfPresentClause : public OpenACCClause {
protected:
OpenACCIfPresentClause(SourceLocation BeginLoc, SourceLocation EndLoc)
: OpenACCClause(OpenACCClauseKind::IfPresent, BeginLoc, EndLoc) {}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::IfPresent;
}
static OpenACCIfPresentClause *
Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
child_range children() {
return child_range(child_iterator(), child_iterator());
}
const_child_range children() const {
return const_child_range(const_child_iterator(), const_child_iterator());
}
};
// Represents the 'independent' clause.
class OpenACCIndependentClause : public OpenACCClause {
protected:
OpenACCIndependentClause(SourceLocation BeginLoc, SourceLocation EndLoc)
: OpenACCClause(OpenACCClauseKind::Independent, BeginLoc, EndLoc) {}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Independent;
}
static OpenACCIndependentClause *
Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
child_range children() {
return child_range(child_iterator(), child_iterator());
}
const_child_range children() const {
return const_child_range(const_child_iterator(), const_child_iterator());
}
};
// Represents the 'seq' clause.
class OpenACCSeqClause : public OpenACCClause {
protected:
OpenACCSeqClause(SourceLocation BeginLoc, SourceLocation EndLoc)
: OpenACCClause(OpenACCClauseKind::Seq, BeginLoc, EndLoc) {}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Seq;
}
static OpenACCSeqClause *
Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
child_range children() {
return child_range(child_iterator(), child_iterator());
}
const_child_range children() const {
return const_child_range(const_child_iterator(), const_child_iterator());
}
};
// Represents the 'nohost' clause.
class OpenACCNoHostClause : public OpenACCClause {
protected:
OpenACCNoHostClause(SourceLocation BeginLoc, SourceLocation EndLoc)
: OpenACCClause(OpenACCClauseKind::NoHost, BeginLoc, EndLoc) {}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::NoHost;
}
static OpenACCNoHostClause *
Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
child_range children() {
return child_range(child_iterator(), child_iterator());
}
const_child_range children() const {
return const_child_range(const_child_iterator(), const_child_iterator());
}
};
/// 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:
static bool classof(const OpenACCClause *C);
SourceLocation getLParenLoc() const { return LParenLoc; }
child_range children() {
return child_range(child_iterator(), child_iterator());
}
const_child_range children() const {
return const_child_range(const_child_iterator(), const_child_iterator());
}
};
class OpenACCBindClause final : public OpenACCClauseWithParams {
std::variant<const StringLiteral *, const IdentifierInfo *> Argument;
OpenACCBindClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
const clang::StringLiteral *SL, SourceLocation EndLoc)
: OpenACCClauseWithParams(OpenACCClauseKind::Bind, BeginLoc, LParenLoc,
EndLoc),
Argument(SL) {}
OpenACCBindClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
const IdentifierInfo *ID, SourceLocation EndLoc)
: OpenACCClauseWithParams(OpenACCClauseKind::Bind, BeginLoc, LParenLoc,
EndLoc),
Argument(ID) {}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Bind;
}
static OpenACCBindClause *Create(const ASTContext &C, SourceLocation BeginLoc,
SourceLocation LParenLoc,
const IdentifierInfo *ID,
SourceLocation EndLoc);
static OpenACCBindClause *Create(const ASTContext &C, SourceLocation BeginLoc,
SourceLocation LParenLoc,
const StringLiteral *SL,
SourceLocation EndLoc);
bool isStringArgument() const {
return std::holds_alternative<const StringLiteral *>(Argument);
}
const StringLiteral *getStringArgument() const {
return std::get<const StringLiteral *>(Argument);
}
bool isIdentifierArgument() const {
return std::holds_alternative<const IdentifierInfo *>(Argument);
}
const IdentifierInfo *getIdentifierArgument() const {
return std::get<const IdentifierInfo *>(Argument);
}
};
bool operator==(const OpenACCBindClause &LHS, const OpenACCBindClause &RHS);
inline bool operator!=(const OpenACCBindClause &LHS,
const OpenACCBindClause &RHS) {
return !(LHS == RHS);
}
using DeviceTypeArgument = IdentifierLoc;
/// A 'device_type' or 'dtype' clause, takes a list of either an 'asterisk' or
/// an identifier. The 'asterisk' means 'the rest'.
class OpenACCDeviceTypeClause final
: public OpenACCClauseWithParams,
private llvm::TrailingObjects<OpenACCDeviceTypeClause,
DeviceTypeArgument> {
friend TrailingObjects;
// Data stored in trailing objects as IdentifierInfo* /SourceLocation pairs. A
// nullptr IdentifierInfo* represents an asterisk.
unsigned NumArchs;
OpenACCDeviceTypeClause(OpenACCClauseKind K, SourceLocation BeginLoc,
SourceLocation LParenLoc,
ArrayRef<DeviceTypeArgument> Archs,
SourceLocation EndLoc)
: OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc),
NumArchs(Archs.size()) {
assert(
(K == OpenACCClauseKind::DeviceType || K == OpenACCClauseKind::DType) &&
"Invalid clause kind for device-type");
assert(!llvm::any_of(Archs, [](const DeviceTypeArgument &Arg) {
return Arg.getLoc().isInvalid();
}) && "Invalid SourceLocation for an argument");
assert((Archs.size() == 1 ||
!llvm::any_of(Archs,
[](const DeviceTypeArgument &Arg) {
return Arg.getIdentifierInfo() == nullptr;
})) &&
"Only a single asterisk version is permitted, and must be the "
"only one");
llvm::uninitialized_copy(Archs, getTrailingObjects());
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::DType ||
C->getClauseKind() == OpenACCClauseKind::DeviceType;
}
bool hasAsterisk() const {
return getArchitectures().size() > 0 &&
getArchitectures()[0].getIdentifierInfo() == nullptr;
}
ArrayRef<DeviceTypeArgument> getArchitectures() const {
return getTrailingObjects(NumArchs);
}
static OpenACCDeviceTypeClause *
Create(const ASTContext &C, OpenACCClauseKind K, SourceLocation BeginLoc,
SourceLocation LParenLoc, ArrayRef<DeviceTypeArgument> Archs,
SourceLocation EndLoc);
};
/// A 'default' clause, has the optional 'none' or 'present' argument.
class OpenACCDefaultClause : public OpenACCClauseWithParams {
friend class ASTReaderStmt;
friend class ASTWriterStmt;
OpenACCDefaultClauseKind DefaultClauseKind;
protected:
OpenACCDefaultClause(OpenACCDefaultClauseKind K, SourceLocation BeginLoc,
SourceLocation LParenLoc, SourceLocation EndLoc)
: OpenACCClauseWithParams(OpenACCClauseKind::Default, BeginLoc, LParenLoc,
EndLoc),
DefaultClauseKind(K) {
assert((DefaultClauseKind == OpenACCDefaultClauseKind::None ||
DefaultClauseKind == OpenACCDefaultClauseKind::Present) &&
"Invalid Clause Kind");
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Default;
}
OpenACCDefaultClauseKind getDefaultClauseKind() const {
return DefaultClauseKind;
}
static OpenACCDefaultClause *Create(const ASTContext &C,
OpenACCDefaultClauseKind K,
SourceLocation BeginLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
};
/// Represents one of the handful of classes that has an optional/required
/// 'condition' expression as an argument.
class OpenACCClauseWithCondition : public OpenACCClauseWithParams {
Expr *ConditionExpr = nullptr;
protected:
OpenACCClauseWithCondition(OpenACCClauseKind K, SourceLocation BeginLoc,
SourceLocation LParenLoc, Expr *ConditionExpr,
SourceLocation EndLoc)
: OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc),
ConditionExpr(ConditionExpr) {}
public:
static bool classof(const OpenACCClause *C);
bool hasConditionExpr() const { return ConditionExpr; }
const Expr *getConditionExpr() const { return ConditionExpr; }
Expr *getConditionExpr() { return ConditionExpr; }
child_range children() {
if (ConditionExpr)
return child_range(reinterpret_cast<Stmt **>(&ConditionExpr),
reinterpret_cast<Stmt **>(&ConditionExpr + 1));
return child_range(child_iterator(), child_iterator());
}
const_child_range children() const {
if (ConditionExpr)
return const_child_range(
reinterpret_cast<Stmt *const *>(&ConditionExpr),
reinterpret_cast<Stmt *const *>(&ConditionExpr + 1));
return const_child_range(const_child_iterator(), const_child_iterator());
}
};
/// An 'if' clause, which has a required condition expression.
class OpenACCIfClause : public OpenACCClauseWithCondition {
protected:
OpenACCIfClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
Expr *ConditionExpr, SourceLocation EndLoc);
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::If;
}
static OpenACCIfClause *Create(const ASTContext &C, SourceLocation BeginLoc,
SourceLocation LParenLoc, Expr *ConditionExpr,
SourceLocation EndLoc);
};
/// A 'self' clause, which has an optional condition expression, or, in the
/// event of an 'update' directive, contains a 'VarList'.
class OpenACCSelfClause final
: public OpenACCClauseWithParams,
private llvm::TrailingObjects<OpenACCSelfClause, Expr *> {
friend TrailingObjects;
// Holds whether this HAS a condition expression. Lacks a value if this is NOT
// a condition-expr self clause.
std::optional<bool> HasConditionExpr;
// Holds the number of stored expressions. In the case of a condition-expr
// self clause, this is expected to be ONE (and there to be 1 trailing
// object), whether or not that is null.
unsigned NumExprs;
OpenACCSelfClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
Expr *ConditionExpr, SourceLocation EndLoc);
OpenACCSelfClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc);
// Intentionally internal, meant to be an implementation detail of everything
// else. All non-internal uses should go through getConditionExpr/getVarList.
ArrayRef<Expr *> getExprs() const { return getTrailingObjects(NumExprs); }
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Self;
}
bool isConditionExprClause() const { return HasConditionExpr.has_value(); }
bool isVarListClause() const { return !isConditionExprClause(); }
bool isEmptySelfClause() const {
return (isConditionExprClause() && !hasConditionExpr()) ||
(!isConditionExprClause() && getVarList().empty());
}
bool hasConditionExpr() const {
assert(HasConditionExpr.has_value() &&
"VarList Self Clause asked about condition expression");
return *HasConditionExpr;
}
const Expr *getConditionExpr() const {
assert(HasConditionExpr.has_value() &&
"VarList Self Clause asked about condition expression");
assert(getExprs().size() == 1 &&
"ConditionExpr Self Clause with too many Exprs");
return getExprs()[0];
}
Expr *getConditionExpr() {
assert(HasConditionExpr.has_value() &&
"VarList Self Clause asked about condition expression");
assert(getExprs().size() == 1 &&
"ConditionExpr Self Clause with too many Exprs");
return getExprs()[0];
}
ArrayRef<Expr *> getVarList() {
assert(!HasConditionExpr.has_value() &&
"Condition Expr self clause asked about var list");
return getExprs();
}
ArrayRef<Expr *> getVarList() const {
assert(!HasConditionExpr.has_value() &&
"Condition Expr self clause asked about var list");
return getExprs();
}
child_range children() {
return child_range(
reinterpret_cast<Stmt **>(getTrailingObjects()),
reinterpret_cast<Stmt **>(getTrailingObjects() + NumExprs));
}
const_child_range children() const {
return const_cast<OpenACCSelfClause *>(this)->children();
}
static OpenACCSelfClause *Create(const ASTContext &C, SourceLocation BeginLoc,
SourceLocation LParenLoc,
Expr *ConditionExpr, SourceLocation EndLoc);
static OpenACCSelfClause *Create(const ASTContext &C, SourceLocation BeginLoc,
SourceLocation LParenLoc,
ArrayRef<Expr *> ConditionExpr,
SourceLocation EndLoc);
};
/// Represents a clause that has one or more expressions associated with it.
class OpenACCClauseWithExprs : public OpenACCClauseWithParams {
MutableArrayRef<Expr *> Exprs;
protected:
OpenACCClauseWithExprs(OpenACCClauseKind K, SourceLocation BeginLoc,
SourceLocation LParenLoc, SourceLocation EndLoc)
: OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc) {}
/// Used only for initialization, the leaf class can initialize this to
/// trailing storage.
void setExprs(MutableArrayRef<Expr *> NewExprs) {
assert(Exprs.empty() && "Cannot change Exprs list");
Exprs = NewExprs;
}
/// Used only for initialization, the leaf class can initialize this to
/// trailing storage, and initialize the data in the trailing storage as well.
void setExprs(MutableArrayRef<Expr *> NewStorage, ArrayRef<Expr *> Exprs) {
assert(NewStorage.size() == Exprs.size());
llvm::uninitialized_copy(Exprs, NewStorage.begin());
setExprs(NewStorage);
}
/// Gets the entire list of expressions, but leave it to the
/// individual clauses to expose this how they'd like.
ArrayRef<Expr *> getExprs() const { return Exprs; }
public:
static bool classof(const OpenACCClause *C);
child_range children() {
return child_range(reinterpret_cast<Stmt **>(Exprs.begin()),
reinterpret_cast<Stmt **>(Exprs.end()));
}
const_child_range children() const {
return const_cast<OpenACCClauseWithExprs *>(this)->children();
}
};
// Represents the 'devnum' and expressions lists for the 'wait' clause.
class OpenACCWaitClause final
: public OpenACCClauseWithExprs,
private llvm::TrailingObjects<OpenACCWaitClause, Expr *> {
friend TrailingObjects;
SourceLocation QueuesLoc;
OpenACCWaitClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
Expr *DevNumExpr, SourceLocation QueuesLoc,
ArrayRef<Expr *> QueueIdExprs, SourceLocation EndLoc)
: OpenACCClauseWithExprs(OpenACCClauseKind::Wait, BeginLoc, LParenLoc,
EndLoc),
QueuesLoc(QueuesLoc) {
// The first element of the trailing storage is always the devnum expr,
// whether it is used or not.
auto *Exprs = getTrailingObjects();
llvm::uninitialized_copy(ArrayRef(DevNumExpr), Exprs);
llvm::uninitialized_copy(QueueIdExprs, Exprs + 1);
setExprs(getTrailingObjects(QueueIdExprs.size() + 1));
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Wait;
}
static OpenACCWaitClause *Create(const ASTContext &C, SourceLocation BeginLoc,
SourceLocation LParenLoc, Expr *DevNumExpr,
SourceLocation QueuesLoc,
ArrayRef<Expr *> QueueIdExprs,
SourceLocation EndLoc);
bool hasQueuesTag() const { return !QueuesLoc.isInvalid(); }
SourceLocation getQueuesLoc() const { return QueuesLoc; }
bool hasDevNumExpr() const { return getExprs()[0]; }
Expr *getDevNumExpr() const { return getExprs()[0]; }
ArrayRef<Expr *> getQueueIdExprs() {
return OpenACCClauseWithExprs::getExprs().drop_front();
}
ArrayRef<Expr *> getQueueIdExprs() const {
return OpenACCClauseWithExprs::getExprs().drop_front();
}
// If this is a plain `wait` (no parens) this returns 'false'. Else Sema/Parse
// ensures we have at least one QueueId expression.
bool hasExprs() const { return getLParenLoc().isValid(); }
};
class OpenACCNumGangsClause final
: public OpenACCClauseWithExprs,
private llvm::TrailingObjects<OpenACCNumGangsClause, Expr *> {
friend TrailingObjects;
OpenACCNumGangsClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> IntExprs, SourceLocation EndLoc)
: OpenACCClauseWithExprs(OpenACCClauseKind::NumGangs, BeginLoc, LParenLoc,
EndLoc) {
setExprs(getTrailingObjects(IntExprs.size()), IntExprs);
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::NumGangs;
}
static OpenACCNumGangsClause *
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> IntExprs, SourceLocation EndLoc);
ArrayRef<Expr *> getIntExprs() { return OpenACCClauseWithExprs::getExprs(); }
ArrayRef<Expr *> getIntExprs() const {
return OpenACCClauseWithExprs::getExprs();
}
};
class OpenACCTileClause final
: public OpenACCClauseWithExprs,
private llvm::TrailingObjects<OpenACCTileClause, Expr *> {
friend TrailingObjects;
OpenACCTileClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> SizeExprs, SourceLocation EndLoc)
: OpenACCClauseWithExprs(OpenACCClauseKind::Tile, BeginLoc, LParenLoc,
EndLoc) {
setExprs(getTrailingObjects(SizeExprs.size()), SizeExprs);
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Tile;
}
static OpenACCTileClause *Create(const ASTContext &C, SourceLocation BeginLoc,
SourceLocation LParenLoc,
ArrayRef<Expr *> SizeExprs,
SourceLocation EndLoc);
ArrayRef<Expr *> getSizeExprs() { return OpenACCClauseWithExprs::getExprs(); }
ArrayRef<Expr *> getSizeExprs() const {
return OpenACCClauseWithExprs::getExprs();
}
};
/// Represents one of a handful of clauses that have a single integer
/// expression.
class OpenACCClauseWithSingleIntExpr : public OpenACCClauseWithExprs {
Expr *IntExpr;
protected:
OpenACCClauseWithSingleIntExpr(OpenACCClauseKind K, SourceLocation BeginLoc,
SourceLocation LParenLoc, Expr *IntExpr,
SourceLocation EndLoc)
: OpenACCClauseWithExprs(K, BeginLoc, LParenLoc, EndLoc),
IntExpr(IntExpr) {
if (IntExpr)
setExprs(MutableArrayRef<Expr *>{&this->IntExpr, 1});
}
public:
static bool classof(const OpenACCClause *C);
bool hasIntExpr() const { return !getExprs().empty(); }
const Expr *getIntExpr() const {
return hasIntExpr() ? getExprs()[0] : nullptr;
}
Expr *getIntExpr() { return hasIntExpr() ? getExprs()[0] : nullptr; };
};
class OpenACCGangClause final
: public OpenACCClauseWithExprs,
private llvm::TrailingObjects<OpenACCGangClause, Expr *, OpenACCGangKind> {
friend TrailingObjects;
protected:
OpenACCGangClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<OpenACCGangKind> GangKinds,
ArrayRef<Expr *> IntExprs, SourceLocation EndLoc);
OpenACCGangKind getGangKind(unsigned I) const {
return getTrailingObjects<OpenACCGangKind>()[I];
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Gang;
}
size_t numTrailingObjects(OverloadToken<Expr *>) const {
return getNumExprs();
}
unsigned getNumExprs() const { return getExprs().size(); }
std::pair<OpenACCGangKind, const Expr *> getExpr(unsigned I) const {
return {getGangKind(I), getExprs()[I]};
}
bool hasExprOfKind(OpenACCGangKind GK) const {
for (unsigned I = 0; I < getNumExprs(); ++I) {
if (getGangKind(I) == GK)
return true;
}
return false;
}
static OpenACCGangClause *
Create(const ASTContext &Ctx, SourceLocation BeginLoc,
SourceLocation LParenLoc, ArrayRef<OpenACCGangKind> GangKinds,
ArrayRef<Expr *> IntExprs, SourceLocation EndLoc);
};
class OpenACCWorkerClause : public OpenACCClauseWithSingleIntExpr {
protected:
OpenACCWorkerClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
Expr *IntExpr, SourceLocation EndLoc);
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Worker;
}
static OpenACCWorkerClause *Create(const ASTContext &Ctx,
SourceLocation BeginLoc,
SourceLocation LParenLoc, Expr *IntExpr,
SourceLocation EndLoc);
};
class OpenACCVectorClause : public OpenACCClauseWithSingleIntExpr {
protected:
OpenACCVectorClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
Expr *IntExpr, SourceLocation EndLoc);
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Vector;
}
static OpenACCVectorClause *Create(const ASTContext &Ctx,
SourceLocation BeginLoc,
SourceLocation LParenLoc, Expr *IntExpr,
SourceLocation EndLoc);
};
class OpenACCNumWorkersClause : public OpenACCClauseWithSingleIntExpr {
OpenACCNumWorkersClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
Expr *IntExpr, SourceLocation EndLoc);
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::NumWorkers;
}
static OpenACCNumWorkersClause *Create(const ASTContext &C,
SourceLocation BeginLoc,
SourceLocation LParenLoc,
Expr *IntExpr, SourceLocation EndLoc);
};
class OpenACCVectorLengthClause : public OpenACCClauseWithSingleIntExpr {
OpenACCVectorLengthClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
Expr *IntExpr, SourceLocation EndLoc);
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::VectorLength;
}
static OpenACCVectorLengthClause *
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
Expr *IntExpr, SourceLocation EndLoc);
};
class OpenACCAsyncClause : public OpenACCClauseWithSingleIntExpr {
OpenACCAsyncClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
Expr *IntExpr, SourceLocation EndLoc);
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Async;
}
static OpenACCAsyncClause *Create(const ASTContext &C,
SourceLocation BeginLoc,
SourceLocation LParenLoc, Expr *IntExpr,
SourceLocation EndLoc);
};
class OpenACCDeviceNumClause : public OpenACCClauseWithSingleIntExpr {
OpenACCDeviceNumClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
Expr *IntExpr, SourceLocation EndLoc);
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::DeviceNum;
}
static OpenACCDeviceNumClause *Create(const ASTContext &C,
SourceLocation BeginLoc,
SourceLocation LParenLoc, Expr *IntExpr,
SourceLocation EndLoc);
};
class OpenACCDefaultAsyncClause : public OpenACCClauseWithSingleIntExpr {
OpenACCDefaultAsyncClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
Expr *IntExpr, SourceLocation EndLoc);
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::DefaultAsync;
}
static OpenACCDefaultAsyncClause *
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
Expr *IntExpr, SourceLocation EndLoc);
};
/// Represents a 'collapse' clause on a 'loop' construct. This clause takes an
/// integer constant expression 'N' that represents how deep to collapse the
/// construct. It also takes an optional 'force' tag that permits intervening
/// code in the loops.
class OpenACCCollapseClause : public OpenACCClauseWithSingleIntExpr {
bool HasForce = false;
OpenACCCollapseClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
bool HasForce, Expr *LoopCount, SourceLocation EndLoc);
public:
const Expr *getLoopCount() const { return getIntExpr(); }
Expr *getLoopCount() { return getIntExpr(); }
bool hasForce() const { return HasForce; }
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Collapse;
}
static OpenACCCollapseClause *Create(const ASTContext &C,
SourceLocation BeginLoc,
SourceLocation LParenLoc, bool HasForce,
Expr *LoopCount, SourceLocation EndLoc);
};
/// Represents a clause with one or more 'var' objects, represented as an expr,
/// as its arguments. Var-list is expected to be stored in trailing storage.
/// For now, we're just storing the original expression in its entirety, unlike
/// OMP which has to do a bunch of work to create a private.
class OpenACCClauseWithVarList : public OpenACCClauseWithExprs {
protected:
OpenACCClauseWithVarList(OpenACCClauseKind K, SourceLocation BeginLoc,
SourceLocation LParenLoc, SourceLocation EndLoc)
: OpenACCClauseWithExprs(K, BeginLoc, LParenLoc, EndLoc) {}
public:
static bool classof(const OpenACCClause *C);
ArrayRef<Expr *> getVarList() { return getExprs(); }
ArrayRef<Expr *> getVarList() const { return getExprs(); }
};
// Represents all the data needed for recipe generation. The declaration and
// init are stored separately, because in the case of subscripts, we do the
// alloca at the level of the base, and the init at the element level.
struct OpenACCPrivateRecipe {
VarDecl *AllocaDecl;
OpenACCPrivateRecipe(VarDecl *A) : AllocaDecl(A) {}
bool isSet() const { return AllocaDecl; }
static OpenACCPrivateRecipe Empty() {
return OpenACCPrivateRecipe(/*AllocaDecl=*/nullptr);
}
};
class OpenACCPrivateClause final
: public OpenACCClauseWithVarList,
private llvm::TrailingObjects<OpenACCPrivateClause, Expr *,
OpenACCPrivateRecipe> {
friend TrailingObjects;
OpenACCPrivateClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList,
ArrayRef<OpenACCPrivateRecipe> InitRecipes,
SourceLocation EndLoc)
: OpenACCClauseWithVarList(OpenACCClauseKind::Private, BeginLoc,
LParenLoc, EndLoc) {
assert(VarList.size() == InitRecipes.size());
setExprs(getTrailingObjects<Expr *>(VarList.size()), VarList);
llvm::uninitialized_copy(InitRecipes,
getTrailingObjects<OpenACCPrivateRecipe>());
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Private;
}
// Gets a list of 'made up' `VarDecl` objects that can be used by codegen to
// ensure that we properly initialize each of these variables.
ArrayRef<OpenACCPrivateRecipe> getInitRecipes() {
return ArrayRef<OpenACCPrivateRecipe>{
getTrailingObjects<OpenACCPrivateRecipe>(), getExprs().size()};
}
ArrayRef<OpenACCPrivateRecipe> getInitRecipes() const {
return ArrayRef<OpenACCPrivateRecipe>{
getTrailingObjects<OpenACCPrivateRecipe>(), getExprs().size()};
}
static OpenACCPrivateClause *
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, ArrayRef<OpenACCPrivateRecipe> InitRecipes,
SourceLocation EndLoc);
size_t numTrailingObjects(OverloadToken<Expr *>) const {
return getExprs().size();
}
};
// A 'pair' to stand in for the recipe. RecipeDecl is the main declaration, and
// InitFromTemporary is the 'temp' declaration we put in to be 'copied from'.
struct OpenACCFirstPrivateRecipe {
VarDecl *AllocaDecl;
VarDecl *InitFromTemporary;
OpenACCFirstPrivateRecipe(VarDecl *A, VarDecl *T)
: AllocaDecl(A), InitFromTemporary(T) {
assert(!InitFromTemporary || InitFromTemporary->getInit() == nullptr);
}
bool isSet() const { return AllocaDecl; }
static OpenACCFirstPrivateRecipe Empty() {
return OpenACCFirstPrivateRecipe(/*AllocaDecl=*/nullptr,
/*InitFromTemporary=*/nullptr);
}
};
class OpenACCFirstPrivateClause final
: public OpenACCClauseWithVarList,
private llvm::TrailingObjects<OpenACCFirstPrivateClause, Expr *,
OpenACCFirstPrivateRecipe> {
friend TrailingObjects;
OpenACCFirstPrivateClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList,
ArrayRef<OpenACCFirstPrivateRecipe> InitRecipes,
SourceLocation EndLoc)
: OpenACCClauseWithVarList(OpenACCClauseKind::FirstPrivate, BeginLoc,
LParenLoc, EndLoc) {
assert(VarList.size() == InitRecipes.size());
setExprs(getTrailingObjects<Expr *>(VarList.size()), VarList);
llvm::uninitialized_copy(InitRecipes,
getTrailingObjects<OpenACCFirstPrivateRecipe>());
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::FirstPrivate;
}
// Gets a list of 'made up' `VarDecl` objects that can be used by codegen to
// ensure that we properly initialize each of these variables.
ArrayRef<OpenACCFirstPrivateRecipe> getInitRecipes() {
return ArrayRef<OpenACCFirstPrivateRecipe>{
getTrailingObjects<OpenACCFirstPrivateRecipe>(), getExprs().size()};
}
ArrayRef<OpenACCFirstPrivateRecipe> getInitRecipes() const {
return ArrayRef<OpenACCFirstPrivateRecipe>{
getTrailingObjects<OpenACCFirstPrivateRecipe>(), getExprs().size()};
}
static OpenACCFirstPrivateClause *
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList,
ArrayRef<OpenACCFirstPrivateRecipe> InitRecipes,
SourceLocation EndLoc);
size_t numTrailingObjects(OverloadToken<Expr *>) const {
return getExprs().size();
}
};
class OpenACCDevicePtrClause final
: public OpenACCClauseWithVarList,
private llvm::TrailingObjects<OpenACCDevicePtrClause, Expr *> {
friend TrailingObjects;
OpenACCDevicePtrClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
: OpenACCClauseWithVarList(OpenACCClauseKind::DevicePtr, BeginLoc,
LParenLoc, EndLoc) {
setExprs(getTrailingObjects(VarList.size()), VarList);
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::DevicePtr;
}
static OpenACCDevicePtrClause *
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc);
};
class OpenACCAttachClause final
: public OpenACCClauseWithVarList,
private llvm::TrailingObjects<OpenACCAttachClause, Expr *> {
friend TrailingObjects;
OpenACCAttachClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
: OpenACCClauseWithVarList(OpenACCClauseKind::Attach, BeginLoc, LParenLoc,
EndLoc) {
setExprs(getTrailingObjects(VarList.size()), VarList);
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Attach;
}
static OpenACCAttachClause *
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc);
};
class OpenACCDetachClause final
: public OpenACCClauseWithVarList,
private llvm::TrailingObjects<OpenACCDetachClause, Expr *> {
friend TrailingObjects;
OpenACCDetachClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
: OpenACCClauseWithVarList(OpenACCClauseKind::Detach, BeginLoc, LParenLoc,
EndLoc) {
setExprs(getTrailingObjects(VarList.size()), VarList);
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Detach;
}
static OpenACCDetachClause *
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc);
};
class OpenACCDeleteClause final
: public OpenACCClauseWithVarList,
private llvm::TrailingObjects<OpenACCDeleteClause, Expr *> {
friend TrailingObjects;
OpenACCDeleteClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
: OpenACCClauseWithVarList(OpenACCClauseKind::Delete, BeginLoc, LParenLoc,
EndLoc) {
setExprs(getTrailingObjects(VarList.size()), VarList);
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Delete;
}
static OpenACCDeleteClause *
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc);
};
class OpenACCUseDeviceClause final
: public OpenACCClauseWithVarList,
private llvm::TrailingObjects<OpenACCUseDeviceClause, Expr *> {
friend TrailingObjects;
OpenACCUseDeviceClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
: OpenACCClauseWithVarList(OpenACCClauseKind::UseDevice, BeginLoc,
LParenLoc, EndLoc) {
setExprs(getTrailingObjects(VarList.size()), VarList);
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::UseDevice;
}
static OpenACCUseDeviceClause *
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc);
};
class OpenACCNoCreateClause final
: public OpenACCClauseWithVarList,
private llvm::TrailingObjects<OpenACCNoCreateClause, Expr *> {
friend TrailingObjects;
OpenACCNoCreateClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
: OpenACCClauseWithVarList(OpenACCClauseKind::NoCreate, BeginLoc,
LParenLoc, EndLoc) {
setExprs(getTrailingObjects(VarList.size()), VarList);
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::NoCreate;
}
static OpenACCNoCreateClause *
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc);
};
class OpenACCPresentClause final
: public OpenACCClauseWithVarList,
private llvm::TrailingObjects<OpenACCPresentClause, Expr *> {
friend TrailingObjects;
OpenACCPresentClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
: OpenACCClauseWithVarList(OpenACCClauseKind::Present, BeginLoc,
LParenLoc, EndLoc) {
setExprs(getTrailingObjects(VarList.size()), VarList);
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Present;
}
static OpenACCPresentClause *
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc);
};
class OpenACCHostClause final
: public OpenACCClauseWithVarList,
private llvm::TrailingObjects<OpenACCHostClause, Expr *> {
friend TrailingObjects;
OpenACCHostClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
: OpenACCClauseWithVarList(OpenACCClauseKind::Host, BeginLoc, LParenLoc,
EndLoc) {
setExprs(getTrailingObjects(VarList.size()), VarList);
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Host;
}
static OpenACCHostClause *Create(const ASTContext &C, SourceLocation BeginLoc,
SourceLocation LParenLoc,
ArrayRef<Expr *> VarList,
SourceLocation EndLoc);
};
class OpenACCDeviceClause final
: public OpenACCClauseWithVarList,
private llvm::TrailingObjects<OpenACCDeviceClause, Expr *> {
friend TrailingObjects;
OpenACCDeviceClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
: OpenACCClauseWithVarList(OpenACCClauseKind::Device, BeginLoc, LParenLoc,
EndLoc) {
setExprs(getTrailingObjects(VarList.size()), VarList);
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Device;
}
static OpenACCDeviceClause *
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc);
};
class OpenACCCopyClause final
: public OpenACCClauseWithVarList,
private llvm::TrailingObjects<OpenACCCopyClause, Expr *> {
friend TrailingObjects;
OpenACCModifierKind Modifiers;
OpenACCCopyClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc,
SourceLocation LParenLoc, OpenACCModifierKind Mods,
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
: OpenACCClauseWithVarList(Spelling, BeginLoc, LParenLoc, EndLoc),
Modifiers(Mods) {
assert((Spelling == OpenACCClauseKind::Copy ||
Spelling == OpenACCClauseKind::PCopy ||
Spelling == OpenACCClauseKind::PresentOrCopy) &&
"Invalid clause kind for copy-clause");
setExprs(getTrailingObjects(VarList.size()), VarList);
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Copy ||
C->getClauseKind() == OpenACCClauseKind::PCopy ||
C->getClauseKind() == OpenACCClauseKind::PresentOrCopy;
}
static OpenACCCopyClause *
Create(const ASTContext &C, OpenACCClauseKind Spelling,
SourceLocation BeginLoc, SourceLocation LParenLoc,
OpenACCModifierKind Mods, ArrayRef<Expr *> VarList,
SourceLocation EndLoc);
OpenACCModifierKind getModifierList() const { return Modifiers; }
};
class OpenACCCopyInClause final
: public OpenACCClauseWithVarList,
private llvm::TrailingObjects<OpenACCCopyInClause, Expr *> {
friend TrailingObjects;
OpenACCModifierKind Modifiers;
OpenACCCopyInClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc,
SourceLocation LParenLoc, OpenACCModifierKind Mods,
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
: OpenACCClauseWithVarList(Spelling, BeginLoc, LParenLoc, EndLoc),
Modifiers(Mods) {
assert((Spelling == OpenACCClauseKind::CopyIn ||
Spelling == OpenACCClauseKind::PCopyIn ||
Spelling == OpenACCClauseKind::PresentOrCopyIn) &&
"Invalid clause kind for copyin-clause");
setExprs(getTrailingObjects(VarList.size()), VarList);
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::CopyIn ||
C->getClauseKind() == OpenACCClauseKind::PCopyIn ||
C->getClauseKind() == OpenACCClauseKind::PresentOrCopyIn;
}
OpenACCModifierKind getModifierList() const { return Modifiers; }
static OpenACCCopyInClause *
Create(const ASTContext &C, OpenACCClauseKind Spelling,
SourceLocation BeginLoc, SourceLocation LParenLoc,
OpenACCModifierKind Mods, ArrayRef<Expr *> VarList,
SourceLocation EndLoc);
};
class OpenACCCopyOutClause final
: public OpenACCClauseWithVarList,
private llvm::TrailingObjects<OpenACCCopyOutClause, Expr *> {
friend TrailingObjects;
OpenACCModifierKind Modifiers;
OpenACCCopyOutClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc,
SourceLocation LParenLoc, OpenACCModifierKind Mods,
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
: OpenACCClauseWithVarList(Spelling, BeginLoc, LParenLoc, EndLoc),
Modifiers(Mods) {
assert((Spelling == OpenACCClauseKind::CopyOut ||
Spelling == OpenACCClauseKind::PCopyOut ||
Spelling == OpenACCClauseKind::PresentOrCopyOut) &&
"Invalid clause kind for copyout-clause");
setExprs(getTrailingObjects(VarList.size()), VarList);
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::CopyOut ||
C->getClauseKind() == OpenACCClauseKind::PCopyOut ||
C->getClauseKind() == OpenACCClauseKind::PresentOrCopyOut;
}
OpenACCModifierKind getModifierList() const { return Modifiers; }
static OpenACCCopyOutClause *
Create(const ASTContext &C, OpenACCClauseKind Spelling,
SourceLocation BeginLoc, SourceLocation LParenLoc,
OpenACCModifierKind Mods, ArrayRef<Expr *> VarList,
SourceLocation EndLoc);
};
class OpenACCCreateClause final
: public OpenACCClauseWithVarList,
private llvm::TrailingObjects<OpenACCCreateClause, Expr *> {
friend TrailingObjects;
OpenACCModifierKind Modifiers;
OpenACCCreateClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc,
SourceLocation LParenLoc, OpenACCModifierKind Mods,
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
: OpenACCClauseWithVarList(Spelling, BeginLoc, LParenLoc, EndLoc),
Modifiers(Mods) {
assert((Spelling == OpenACCClauseKind::Create ||
Spelling == OpenACCClauseKind::PCreate ||
Spelling == OpenACCClauseKind::PresentOrCreate) &&
"Invalid clause kind for create-clause");
setExprs(getTrailingObjects(VarList.size()), VarList);
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Create ||
C->getClauseKind() == OpenACCClauseKind::PCreate ||
C->getClauseKind() == OpenACCClauseKind::PresentOrCreate;
}
OpenACCModifierKind getModifierList() const { return Modifiers; }
static OpenACCCreateClause *
Create(const ASTContext &C, OpenACCClauseKind Spelling,
SourceLocation BeginLoc, SourceLocation LParenLoc,
OpenACCModifierKind Mods, ArrayRef<Expr *> VarList,
SourceLocation EndLoc);
};
// A structure to stand in for the recipe on a reduction. RecipeDecl is the
// 'main' declaration used for initializaiton, which is fixed.
struct OpenACCReductionRecipe {
VarDecl *AllocaDecl;
// A combiner recipe is represented by an operation expression. However, in
// order to generate these properly, we have to make up a LHS and a RHS
// expression for the purposes of generation.
struct CombinerRecipe {
VarDecl *LHS;
VarDecl *RHS;
Expr *Op;
};
// Contains a collection of the recipe elements we need for the combiner:
// -For Scalars, there will be 1 element, just the combiner for that scalar.
// -For a struct with a valid operator, this will be 1 element, just that
// call.
// -For a struct without the operator, this will be 1 element per field, which
// should be the combiner for that element.
// -For an array of any of the above, it will be the above for the element.
// Note: These are necessarily stored in either Trailing Storage (when in the
// AST), or in a separate collection when being semantically analyzed.
llvm::ArrayRef<CombinerRecipe> CombinerRecipes;
bool isSet() const { return AllocaDecl; }
private:
friend class OpenACCReductionClause;
OpenACCReductionRecipe(VarDecl *A, llvm::ArrayRef<CombinerRecipe> Combiners)
: AllocaDecl(A), CombinerRecipes(Combiners) {}
};
// A version of the above that is used for semantic analysis, at a time before
// the OpenACCReductionClause node has been created. This one has storage for
// the CombinerRecipe, since Trailing storage for it doesn't exist yet.
struct OpenACCReductionRecipeWithStorage {
VarDecl *AllocaDecl;
llvm::SmallVector<OpenACCReductionRecipe::CombinerRecipe, 1> CombinerRecipes;
OpenACCReductionRecipeWithStorage(
VarDecl *A,
llvm::ArrayRef<OpenACCReductionRecipe::CombinerRecipe> Combiners)
: AllocaDecl(A), CombinerRecipes(Combiners) {}
static OpenACCReductionRecipeWithStorage Empty() {
return OpenACCReductionRecipeWithStorage(/*AllocaDecl=*/nullptr, {});
}
};
class OpenACCReductionClause final
: public OpenACCClauseWithVarList,
private llvm::TrailingObjects<OpenACCReductionClause, Expr *,
OpenACCReductionRecipe,
OpenACCReductionRecipe::CombinerRecipe> {
friend TrailingObjects;
OpenACCReductionOperator Op;
OpenACCReductionClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
OpenACCReductionOperator Operator,
ArrayRef<Expr *> VarList,
ArrayRef<OpenACCReductionRecipeWithStorage> Recipes,
SourceLocation EndLoc)
: OpenACCClauseWithVarList(OpenACCClauseKind::Reduction, BeginLoc,
LParenLoc, EndLoc),
Op(Operator) {
assert(VarList.size() == Recipes.size());
setExprs(getTrailingObjects<Expr *>(VarList.size()), VarList);
// Since we're using trailing storage on this node to store the 'combiner'
// recipes of the Reduction Recipes (which have a 1:M relationship), we need
// to ensure we get the ArrayRef of each of our combiner 'correct'.
OpenACCReductionRecipe::CombinerRecipe *CurCombinerLoc =
getTrailingObjects<OpenACCReductionRecipe::CombinerRecipe>();
for (const auto &[Idx, R] : llvm::enumerate(Recipes)) {
// ArrayRef to the 'correct' data location in trailing storage.
llvm::MutableArrayRef<OpenACCReductionRecipe::CombinerRecipe>
NewCombiners{CurCombinerLoc, R.CombinerRecipes.size()};
CurCombinerLoc += R.CombinerRecipes.size();
llvm::uninitialized_copy(R.CombinerRecipes, NewCombiners.begin());
// Placement new into the correct location in trailng storage.
new (&getTrailingObjects<OpenACCReductionRecipe>()[Idx])
OpenACCReductionRecipe(R.AllocaDecl, NewCombiners);
}
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Reduction;
}
ArrayRef<OpenACCReductionRecipe> getRecipes() {
return ArrayRef<OpenACCReductionRecipe>{
getTrailingObjects<OpenACCReductionRecipe>(), getExprs().size()};
}
ArrayRef<OpenACCReductionRecipe> getRecipes() const {
return ArrayRef<OpenACCReductionRecipe>{
getTrailingObjects<OpenACCReductionRecipe>(), getExprs().size()};
}
static OpenACCReductionClause *
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
OpenACCReductionOperator Operator, ArrayRef<Expr *> VarList,
ArrayRef<OpenACCReductionRecipeWithStorage> Recipes,
SourceLocation EndLoc);
OpenACCReductionOperator getReductionOp() const { return Op; }
size_t numTrailingObjects(OverloadToken<Expr *>) const {
return getExprs().size();
}
size_t numTrailingObjects(OverloadToken<OpenACCReductionRecipe>) const {
return getExprs().size();
}
};
class OpenACCLinkClause final
: public OpenACCClauseWithVarList,
private llvm::TrailingObjects<OpenACCLinkClause, Expr *> {
friend TrailingObjects;
OpenACCLinkClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
: OpenACCClauseWithVarList(OpenACCClauseKind::Link, BeginLoc, LParenLoc,
EndLoc) {
setExprs(getTrailingObjects(VarList.size()), VarList);
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Link;
}
static OpenACCLinkClause *Create(const ASTContext &C, SourceLocation BeginLoc,
SourceLocation LParenLoc,
ArrayRef<Expr *> VarList,
SourceLocation EndLoc);
};
class OpenACCDeviceResidentClause final
: public OpenACCClauseWithVarList,
private llvm::TrailingObjects<OpenACCDeviceResidentClause, Expr *> {
friend TrailingObjects;
OpenACCDeviceResidentClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
: OpenACCClauseWithVarList(OpenACCClauseKind::DeviceResident, BeginLoc,
LParenLoc, EndLoc) {
setExprs(getTrailingObjects(VarList.size()), VarList);
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::DeviceResident;
}
static OpenACCDeviceResidentClause *
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> VarList, SourceLocation EndLoc);
};
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()) {
#define VISIT_CLAUSE(CLAUSE_NAME) \
case OpenACCClauseKind::CLAUSE_NAME: \
getDerived().Visit##CLAUSE_NAME##Clause( \
*cast<OpenACC##CLAUSE_NAME##Clause>(C)); \
return;
#define CLAUSE_ALIAS(ALIAS_NAME, CLAUSE_NAME, DEPRECATED) \
case OpenACCClauseKind::ALIAS_NAME: \
getDerived().Visit##CLAUSE_NAME##Clause( \
*cast<OpenACC##CLAUSE_NAME##Clause>(C)); \
return;
#include "clang/Basic/OpenACCClauses.def"
default:
llvm_unreachable("Clause visitor not yet implemented");
}
llvm_unreachable("Invalid Clause kind");
}
#define VISIT_CLAUSE(CLAUSE_NAME) \
void Visit##CLAUSE_NAME##Clause( \
const OpenACC##CLAUSE_NAME##Clause &Clause) { \
return getDerived().VisitClause(Clause); \
}
#include "clang/Basic/OpenACCClauses.def"
};
class OpenACCClausePrinter final
: public OpenACCClauseVisitor<OpenACCClausePrinter> {
raw_ostream &OS;
const PrintingPolicy &Policy;
void printExpr(const Expr *E);
public:
void VisitClauseList(ArrayRef<const OpenACCClause *> List) {
for (const OpenACCClause *Clause : List) {
Visit(Clause);
if (Clause != List.back())
OS << ' ';
}
}
OpenACCClausePrinter(raw_ostream &OS, const PrintingPolicy &Policy)
: OS(OS), Policy(Policy) {}
#define VISIT_CLAUSE(CLAUSE_NAME) \
void Visit##CLAUSE_NAME##Clause(const OpenACC##CLAUSE_NAME##Clause &Clause);
#include "clang/Basic/OpenACCClauses.def"
};
} // namespace clang
#endif // LLVM_CLANG_AST_OPENACCCLAUSE_H