Skip to content

Commit 8ef2011

Browse files
committed
Reapply "[OpenACC] device_type clause Sema for Compute constructs"
device_type, also spelled as dtype, specifies the applicability of the clauses following it, and takes a series of identifiers representing the architectures it applies to. As we don't have a source for the valid architectures yet, this patch just accepts all. Semantically, this also limits the list of clauses that can be applied after the device_type, so this implements that as well. This reverts commit 06f04b2. This reapplies commit c4a9a37. The build failures were caused by the patch depending on the order of evaluation of arguments to a function. This reapplication separates out the capture of one of the values.
1 parent b8f802f commit 8ef2011

19 files changed

+624
-35
lines changed

clang/include/clang/AST/OpenACCClause.h

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#include "clang/AST/StmtIterator.h"
1818
#include "clang/Basic/OpenACCKinds.h"
1919

20+
#include <utility>
21+
2022
namespace clang {
2123
/// This is the base type for all OpenACC Clauses.
2224
class OpenACCClause {
@@ -75,6 +77,63 @@ class OpenACCClauseWithParams : public OpenACCClause {
7577
}
7678
};
7779

80+
using DeviceTypeArgument = std::pair<IdentifierInfo *, SourceLocation>;
81+
/// A 'device_type' or 'dtype' clause, takes a list of either an 'asterisk' or
82+
/// an identifier. The 'asterisk' means 'the rest'.
83+
class OpenACCDeviceTypeClause final
84+
: public OpenACCClauseWithParams,
85+
public llvm::TrailingObjects<OpenACCDeviceTypeClause,
86+
DeviceTypeArgument> {
87+
// Data stored in trailing objects as IdentifierInfo* /SourceLocation pairs. A
88+
// nullptr IdentifierInfo* represents an asterisk.
89+
unsigned NumArchs;
90+
OpenACCDeviceTypeClause(OpenACCClauseKind K, SourceLocation BeginLoc,
91+
SourceLocation LParenLoc,
92+
ArrayRef<DeviceTypeArgument> Archs,
93+
SourceLocation EndLoc)
94+
: OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc),
95+
NumArchs(Archs.size()) {
96+
assert(
97+
(K == OpenACCClauseKind::DeviceType || K == OpenACCClauseKind::DType) &&
98+
"Invalid clause kind for device-type");
99+
100+
assert(!llvm::any_of(Archs, [](const DeviceTypeArgument &Arg) {
101+
return Arg.second.isInvalid();
102+
}) && "Invalid SourceLocation for an argument");
103+
104+
assert(
105+
(Archs.size() == 1 || !llvm::any_of(Archs,
106+
[](const DeviceTypeArgument &Arg) {
107+
return Arg.first == nullptr;
108+
})) &&
109+
"Only a single asterisk version is permitted, and must be the "
110+
"only one");
111+
112+
std::uninitialized_copy(Archs.begin(), Archs.end(),
113+
getTrailingObjects<DeviceTypeArgument>());
114+
}
115+
116+
public:
117+
static bool classof(const OpenACCClause *C) {
118+
return C->getClauseKind() == OpenACCClauseKind::DType ||
119+
C->getClauseKind() == OpenACCClauseKind::DeviceType;
120+
}
121+
bool hasAsterisk() const {
122+
return getArchitectures().size() > 0 &&
123+
getArchitectures()[0].first == nullptr;
124+
}
125+
126+
ArrayRef<DeviceTypeArgument> getArchitectures() const {
127+
return ArrayRef<DeviceTypeArgument>(
128+
getTrailingObjects<DeviceTypeArgument>(), NumArchs);
129+
}
130+
131+
static OpenACCDeviceTypeClause *
132+
Create(const ASTContext &C, OpenACCClauseKind K, SourceLocation BeginLoc,
133+
SourceLocation LParenLoc, ArrayRef<DeviceTypeArgument> Archs,
134+
SourceLocation EndLoc);
135+
};
136+
78137
/// A 'default' clause, has the optional 'none' or 'present' argument.
79138
class OpenACCDefaultClause : public OpenACCClauseWithParams {
80139
friend class ASTReaderStmt;

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12344,4 +12344,8 @@ def warn_acc_deprecated_alias_name
1234412344
def err_acc_var_not_pointer_type
1234512345
: Error<"expected pointer in '%0' clause, type is %1">;
1234612346
def note_acc_expected_pointer_var : Note<"expected variable of pointer type">;
12347+
def err_acc_clause_after_device_type
12348+
: Error<"OpenACC clause '%0' may not follow a '%1' clause in a "
12349+
"compute construct">;
12350+
1234712351
} // end of sema component.

clang/include/clang/Basic/OpenACCClauses.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ CLAUSE_ALIAS(PCreate, Create)
3737
CLAUSE_ALIAS(PresentOrCreate, Create)
3838
VISIT_CLAUSE(Default)
3939
VISIT_CLAUSE(DevicePtr)
40+
VISIT_CLAUSE(DeviceType)
41+
CLAUSE_ALIAS(DType, DeviceType)
4042
VISIT_CLAUSE(FirstPrivate)
4143
VISIT_CLAUSE(If)
4244
VISIT_CLAUSE(NoCreate)

clang/include/clang/Parse/Parser.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3720,7 +3720,8 @@ class Parser : public CodeCompletionHandler {
37203720
SourceLocation Loc,
37213721
llvm::SmallVectorImpl<Expr *> &IntExprs);
37223722
/// Parses the 'device-type-list', which is a list of identifiers.
3723-
bool ParseOpenACCDeviceTypeList();
3723+
bool ParseOpenACCDeviceTypeList(
3724+
llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>> &Archs);
37243725
/// Parses the 'async-argument', which is an integral value with two
37253726
/// 'special' values that are likely negative (but come from Macros).
37263727
OpenACCIntExprParseResult ParseOpenACCAsyncArgument(OpenACCDirectiveKind DK,

clang/include/clang/Sema/SemaOpenACC.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ class OpenACCClause;
2626

2727
class SemaOpenACC : public SemaBase {
2828
public:
29+
// Redeclaration of the version in OpenACCClause.h.
30+
using DeviceTypeArgument = std::pair<IdentifierInfo *, SourceLocation>;
31+
2932
/// A type to represent all the data for an OpenACC Clause that has been
3033
/// parsed, but not yet created/semantically analyzed. This is effectively a
3134
/// discriminated union on the 'Clause Kind', with all of the individual
@@ -60,8 +63,12 @@ class SemaOpenACC : public SemaBase {
6063
SmallVector<Expr *> QueueIdExprs;
6164
};
6265

66+
struct DeviceTypeDetails {
67+
SmallVector<DeviceTypeArgument> Archs;
68+
};
69+
6370
std::variant<std::monostate, DefaultDetails, ConditionDetails,
64-
IntExprDetails, VarListDetails, WaitDetails>
71+
IntExprDetails, VarListDetails, WaitDetails, DeviceTypeDetails>
6572
Details = std::monostate{};
6673

6774
public:
@@ -209,6 +216,13 @@ class SemaOpenACC : public SemaBase {
209216
return std::get<VarListDetails>(Details).IsZero;
210217
}
211218

219+
ArrayRef<DeviceTypeArgument> getDeviceTypeArchitectures() const {
220+
assert((ClauseKind == OpenACCClauseKind::DeviceType ||
221+
ClauseKind == OpenACCClauseKind::DType) &&
222+
"Only 'device_type'/'dtype' has a device-type-arg list");
223+
return std::get<DeviceTypeDetails>(Details).Archs;
224+
}
225+
212226
void setLParenLoc(SourceLocation EndLoc) { LParenLoc = EndLoc; }
213227
void setEndLoc(SourceLocation EndLoc) { ClauseRange.setEnd(EndLoc); }
214228

@@ -326,6 +340,13 @@ class SemaOpenACC : public SemaBase {
326340
"Parsed clause kind does not have a wait-details");
327341
Details = WaitDetails{DevNum, QueuesLoc, std::move(IntExprs)};
328342
}
343+
344+
void setDeviceTypeDetails(llvm::SmallVector<DeviceTypeArgument> &&Archs) {
345+
assert((ClauseKind == OpenACCClauseKind::DeviceType ||
346+
ClauseKind == OpenACCClauseKind::DType) &&
347+
"Only 'device_type'/'dtype' has a device-type-arg list");
348+
Details = DeviceTypeDetails{std::move(Archs)};
349+
}
329350
};
330351

331352
SemaOpenACC(Sema &S);

clang/lib/AST/OpenACCClause.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
using namespace clang;
1919

2020
bool OpenACCClauseWithParams::classof(const OpenACCClause *C) {
21-
return OpenACCClauseWithCondition::classof(C) ||
21+
return OpenACCDeviceTypeClause::classof(C) ||
22+
OpenACCClauseWithCondition::classof(C) ||
2223
OpenACCClauseWithExprs::classof(C);
2324
}
2425
bool OpenACCClauseWithExprs::classof(const OpenACCClause *C) {
@@ -298,6 +299,17 @@ OpenACCCreateClause::Create(const ASTContext &C, OpenACCClauseKind Spelling,
298299
VarList, EndLoc);
299300
}
300301

302+
OpenACCDeviceTypeClause *OpenACCDeviceTypeClause::Create(
303+
const ASTContext &C, OpenACCClauseKind K, SourceLocation BeginLoc,
304+
SourceLocation LParenLoc, ArrayRef<DeviceTypeArgument> Archs,
305+
SourceLocation EndLoc) {
306+
void *Mem =
307+
C.Allocate(OpenACCDeviceTypeClause::totalSizeToAlloc<DeviceTypeArgument>(
308+
Archs.size()));
309+
return new (Mem)
310+
OpenACCDeviceTypeClause(K, BeginLoc, LParenLoc, Archs, EndLoc);
311+
}
312+
301313
//===----------------------------------------------------------------------===//
302314
// OpenACC clauses printing methods
303315
//===----------------------------------------------------------------------===//
@@ -451,3 +463,17 @@ void OpenACCClausePrinter::VisitWaitClause(const OpenACCWaitClause &C) {
451463
OS << ")";
452464
}
453465
}
466+
467+
void OpenACCClausePrinter::VisitDeviceTypeClause(
468+
const OpenACCDeviceTypeClause &C) {
469+
OS << C.getClauseKind();
470+
OS << "(";
471+
llvm::interleaveComma(C.getArchitectures(), OS,
472+
[&](const DeviceTypeArgument &Arch) {
473+
if (Arch.first == nullptr)
474+
OS << "*";
475+
else
476+
OS << Arch.first;
477+
});
478+
OS << ")";
479+
}

clang/lib/AST/StmtProfile.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2585,6 +2585,9 @@ void OpenACCClauseProfiler::VisitWaitClause(const OpenACCWaitClause &Clause) {
25852585
for (auto *E : Clause.getQueueIdExprs())
25862586
Profiler.VisitStmt(E);
25872587
}
2588+
/// Nothing to do here, there are no sub-statements.
2589+
void OpenACCClauseProfiler::VisitDeviceTypeClause(
2590+
const OpenACCDeviceTypeClause &Clause) {}
25882591
} // namespace
25892592

25902593
void StmtProfiler::VisitOpenACCComputeConstruct(

clang/lib/AST/TextNodeDumper.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,19 @@ void TextNodeDumper::Visit(const OpenACCClause *C) {
444444
if (cast<OpenACCWaitClause>(C)->hasQueuesTag())
445445
OS << " has queues tag";
446446
break;
447+
case OpenACCClauseKind::DeviceType:
448+
case OpenACCClauseKind::DType:
449+
OS << "(";
450+
llvm::interleaveComma(
451+
cast<OpenACCDeviceTypeClause>(C)->getArchitectures(), OS,
452+
[&](const DeviceTypeArgument &Arch) {
453+
if (Arch.first == nullptr)
454+
OS << "*";
455+
else
456+
OS << Arch.first->getName();
457+
});
458+
OS << ")";
459+
break;
447460
default:
448461
// Nothing to do here.
449462
break;

clang/lib/Parse/ParseOpenACC.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -711,24 +711,27 @@ bool Parser::ParseOpenACCIntExprList(OpenACCDirectiveKind DK,
711711
/// device_type( device-type-list )
712712
///
713713
/// The device_type clause may be abbreviated to dtype.
714-
bool Parser::ParseOpenACCDeviceTypeList() {
714+
bool Parser::ParseOpenACCDeviceTypeList(
715+
llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>> &Archs) {
715716

716717
if (expectIdentifierOrKeyword(*this)) {
717718
SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
718719
Parser::StopBeforeMatch);
719-
return false;
720+
return true;
720721
}
721-
ConsumeToken();
722+
IdentifierInfo *Ident = getCurToken().getIdentifierInfo();
723+
Archs.emplace_back(Ident, ConsumeToken());
722724

723725
while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
724726
ExpectAndConsume(tok::comma);
725727

726728
if (expectIdentifierOrKeyword(*this)) {
727729
SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
728730
Parser::StopBeforeMatch);
729-
return false;
731+
return true;
730732
}
731-
ConsumeToken();
733+
Ident = getCurToken().getIdentifierInfo();
734+
Archs.emplace_back(Ident, ConsumeToken());
732735
}
733736
return false;
734737
}
@@ -1021,16 +1024,20 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams(
10211024
break;
10221025
}
10231026
case OpenACCClauseKind::DType:
1024-
case OpenACCClauseKind::DeviceType:
1027+
case OpenACCClauseKind::DeviceType: {
1028+
llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>> Archs;
10251029
if (getCurToken().is(tok::star)) {
10261030
// FIXME: We want to mark that this is an 'everything else' type of
10271031
// device_type in Sema.
1028-
ConsumeToken();
1029-
} else if (ParseOpenACCDeviceTypeList()) {
1032+
ParsedClause.setDeviceTypeDetails({{nullptr, ConsumeToken()}});
1033+
} else if (!ParseOpenACCDeviceTypeList(Archs)) {
1034+
ParsedClause.setDeviceTypeDetails(std::move(Archs));
1035+
} else {
10301036
Parens.skipToEnd();
10311037
return OpenACCCanContinue();
10321038
}
10331039
break;
1040+
}
10341041
case OpenACCClauseKind::Tile:
10351042
if (ParseOpenACCSizeExprList()) {
10361043
Parens.skipToEnd();

clang/lib/Sema/SemaOpenACC.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,33 @@ bool checkAlreadyHasClauseOfKind(
255255
return false;
256256
}
257257

258+
/// Implement check from OpenACC3.3: section 2.5.4:
259+
/// Only the async, wait, num_gangs, num_workers, and vector_length clauses may
260+
/// follow a device_type clause.
261+
bool checkValidAfterDeviceType(
262+
SemaOpenACC &S, const OpenACCDeviceTypeClause &DeviceTypeClause,
263+
const SemaOpenACC::OpenACCParsedClause &NewClause) {
264+
// This is only a requirement on compute constructs so far, so this is fine
265+
// otherwise.
266+
if (!isOpenACCComputeDirectiveKind(NewClause.getDirectiveKind()))
267+
return false;
268+
switch (NewClause.getClauseKind()) {
269+
case OpenACCClauseKind::Async:
270+
case OpenACCClauseKind::Wait:
271+
case OpenACCClauseKind::NumGangs:
272+
case OpenACCClauseKind::NumWorkers:
273+
case OpenACCClauseKind::VectorLength:
274+
case OpenACCClauseKind::DType:
275+
case OpenACCClauseKind::DeviceType:
276+
return false;
277+
default:
278+
S.Diag(NewClause.getBeginLoc(), diag::err_acc_clause_after_device_type)
279+
<< NewClause.getClauseKind() << DeviceTypeClause.getClauseKind();
280+
S.Diag(DeviceTypeClause.getBeginLoc(), diag::note_acc_previous_clause_here);
281+
return true;
282+
}
283+
}
284+
258285
} // namespace
259286

260287
SemaOpenACC::SemaOpenACC(Sema &S) : SemaBase(S) {}
@@ -273,6 +300,17 @@ SemaOpenACC::ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses,
273300
return nullptr;
274301
}
275302

303+
if (const auto *DevTypeClause =
304+
llvm::find_if(ExistingClauses,
305+
[&](const OpenACCClause *C) {
306+
return isa<OpenACCDeviceTypeClause>(C);
307+
});
308+
DevTypeClause != ExistingClauses.end()) {
309+
if (checkValidAfterDeviceType(
310+
*this, *cast<OpenACCDeviceTypeClause>(*DevTypeClause), Clause))
311+
return nullptr;
312+
}
313+
276314
switch (Clause.getClauseKind()) {
277315
case OpenACCClauseKind::Default: {
278316
// Restrictions only properly implemented on 'compute' constructs, and
@@ -651,6 +689,23 @@ SemaOpenACC::ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses,
651689
Clause.getDevNumExpr(), Clause.getQueuesLoc(), Clause.getQueueIdExprs(),
652690
Clause.getEndLoc());
653691
}
692+
case OpenACCClauseKind::DType:
693+
case OpenACCClauseKind::DeviceType: {
694+
// Restrictions only properly implemented on 'compute' constructs, and
695+
// 'compute' constructs are the only construct that can do anything with
696+
// this yet, so skip/treat as unimplemented in this case.
697+
if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
698+
break;
699+
700+
// TODO OpenACC: Once we get enough of the CodeGen implemented that we have
701+
// a source for the list of valid architectures, we need to warn on unknown
702+
// identifiers here.
703+
704+
return OpenACCDeviceTypeClause::Create(
705+
getASTContext(), Clause.getClauseKind(), Clause.getBeginLoc(),
706+
Clause.getLParenLoc(), Clause.getDeviceTypeArchitectures(),
707+
Clause.getEndLoc());
708+
}
654709
default:
655710
break;
656711
}

clang/lib/Sema/TreeTransform.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11480,6 +11480,16 @@ void OpenACCClauseTransform<Derived>::VisitWaitClause(
1148011480
ParsedClause.getQueuesLoc(), ParsedClause.getQueueIdExprs(),
1148111481
ParsedClause.getEndLoc());
1148211482
}
11483+
11484+
template <typename Derived>
11485+
void OpenACCClauseTransform<Derived>::VisitDeviceTypeClause(
11486+
const OpenACCDeviceTypeClause &C) {
11487+
// Nothing to transform here, just create a new version of 'C'.
11488+
NewClause = OpenACCDeviceTypeClause::Create(
11489+
Self.getSema().getASTContext(), C.getClauseKind(),
11490+
ParsedClause.getBeginLoc(), ParsedClause.getLParenLoc(),
11491+
C.getArchitectures(), ParsedClause.getEndLoc());
11492+
}
1148311493
} // namespace
1148411494
template <typename Derived>
1148511495
OpenACCClause *TreeTransform<Derived>::TransformOpenACCClause(

0 commit comments

Comments
 (0)