Skip to content

Commit 8a8f135

Browse files
committed
[OpenACC] Implement 'bind' ast/sema for 'routine' directive
The 'bind' clause allows the renaming of a function during code generation. There are a few rules about when this can/cannot happen, and it takes either a string or identifier (previously mis-implemetned as ID-expression) argument. Note there are additional rules to this in the implicit-function routine case, but that isn't implemented in this patch, as implicit-function routine is not yet implemented either.
1 parent 967ab7e commit 8a8f135

27 files changed

+297
-117
lines changed

clang/include/clang/AST/OpenACCClause.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "clang/Basic/OpenACCKinds.h"
1919

2020
#include <utility>
21+
#include <variant>
2122

2223
namespace clang {
2324
/// This is the base type for all OpenACC Clauses.
@@ -206,6 +207,50 @@ class OpenACCClauseWithParams : public OpenACCClause {
206207
}
207208
};
208209

210+
class OpenACCBindClause final : public OpenACCClauseWithParams {
211+
std::variant<const StringLiteral *, const IdentifierInfo *> Argument;
212+
213+
OpenACCBindClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
214+
const clang::StringLiteral *SL, SourceLocation EndLoc)
215+
: OpenACCClauseWithParams(OpenACCClauseKind::Bind, BeginLoc, LParenLoc,
216+
EndLoc),
217+
Argument(SL) {}
218+
OpenACCBindClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
219+
const IdentifierInfo *ID, SourceLocation EndLoc)
220+
: OpenACCClauseWithParams(OpenACCClauseKind::Bind, BeginLoc, LParenLoc,
221+
EndLoc),
222+
Argument(ID) {}
223+
224+
public:
225+
static bool classof(const OpenACCClause *C) {
226+
return C->getClauseKind() == OpenACCClauseKind::Bind;
227+
}
228+
static OpenACCBindClause *Create(const ASTContext &C, SourceLocation BeginLoc,
229+
SourceLocation LParenLoc,
230+
const IdentifierInfo *ID,
231+
SourceLocation EndLoc);
232+
static OpenACCBindClause *Create(const ASTContext &C, SourceLocation BeginLoc,
233+
SourceLocation LParenLoc,
234+
const StringLiteral *SL,
235+
SourceLocation EndLoc);
236+
237+
bool isStringArgument() const {
238+
return std::holds_alternative<const StringLiteral *>(Argument);
239+
}
240+
241+
const StringLiteral *getStringArgument() const {
242+
return std::get<const StringLiteral *>(Argument);
243+
}
244+
245+
bool isIdentifierArgument() const {
246+
return std::holds_alternative<const IdentifierInfo *>(Argument);
247+
}
248+
249+
const IdentifierInfo *getIdentifierArgument() const {
250+
return std::get<const IdentifierInfo *>(Argument);
251+
}
252+
};
253+
209254
using DeviceTypeArgument = std::pair<IdentifierInfo *, SourceLocation>;
210255
/// A 'device_type' or 'dtype' clause, takes a list of either an 'asterisk' or
211256
/// an identifier. The 'asterisk' means 'the rest'.

clang/include/clang/Basic/Attr.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5026,4 +5026,7 @@ def OpenACCRoutineAnnot : InheritableAttr {
50265026
let Spellings = [];
50275027
let Subjects = SubjectList<[Function]>;
50285028
let Documentation = [InternalOnly];
5029+
let AdditionalMembers = [{
5030+
SourceLocation BindClause;
5031+
}];
50295032
}

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12844,9 +12844,6 @@ def warn_acc_routine_unimplemented
1284412844
: Warning<"OpenACC construct 'routine' with implicit function not yet "
1284512845
"implemented, pragma ignored">,
1284612846
InGroup<SourceUsesOpenACC>;
12847-
def warn_acc_clause_unimplemented
12848-
: Warning<"OpenACC clause '%0' not yet implemented, clause ignored">,
12849-
InGroup<SourceUsesOpenACC>;
1285012847
def err_acc_construct_appertainment
1285112848
: Error<"OpenACC construct '%0' cannot be used here; it can only "
1285212849
"be used in a statement context">;
@@ -13087,6 +13084,9 @@ def err_acc_routine_overload_set
1308713084
def err_acc_magic_static_in_routine
1308813085
: Error<"function static variables are not permitted in functions to which "
1308913086
"an OpenACC 'routine' directive applies">;
13087+
def err_acc_duplicate_bind
13088+
: Error<"multiple 'routine' directives with 'bind' clauses are not "
13089+
"permitted to refer to the same function">;
1309013090

1309113091
// AMDGCN builtins diagnostics
1309213092
def err_amdgcn_global_load_lds_size_invalid_value : Error<"invalid size value">;

clang/include/clang/Basic/OpenACCClauses.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
VISIT_CLAUSE(Auto)
2525
VISIT_CLAUSE(Async)
2626
VISIT_CLAUSE(Attach)
27+
VISIT_CLAUSE(Bind)
2728
VISIT_CLAUSE(Collapse)
2829
VISIT_CLAUSE(Copy)
2930
CLAUSE_ALIAS(PCopy, Copy, true)

clang/include/clang/Parse/Parser.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3783,8 +3783,9 @@ class Parser : public CodeCompletionHandler {
37833783
OpenACCWaitParseInfo ParseOpenACCWaitArgument(SourceLocation Loc,
37843784
bool IsDirective);
37853785
/// Parses the clause of the 'bind' argument, which can be a string literal or
3786-
/// an ID expression.
3787-
ExprResult ParseOpenACCBindClauseArgument();
3786+
/// an identifier.
3787+
std::variant<std::monostate, StringLiteral *, IdentifierInfo *>
3788+
ParseOpenACCBindClauseArgument();
37883789

37893790
/// A type to represent the state of parsing after an attempt to parse an
37903791
/// OpenACC int-expr. This is useful to determine whether an int-expr list can

clang/include/clang/Sema/SemaOpenACC.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,10 +261,14 @@ class SemaOpenACC : public SemaBase {
261261
SmallVector<OpenACCGangKind> GangKinds;
262262
SmallVector<Expr *> IntExprs;
263263
};
264+
struct BindDetails {
265+
std::variant<std::monostate, clang::StringLiteral *, IdentifierInfo *>
266+
Argument;
267+
};
264268

265269
std::variant<std::monostate, DefaultDetails, ConditionDetails,
266270
IntExprDetails, VarListDetails, WaitDetails, DeviceTypeDetails,
267-
ReductionDetails, CollapseDetails, GangDetails>
271+
ReductionDetails, CollapseDetails, GangDetails, BindDetails>
268272
Details = std::monostate{};
269273

270274
public:
@@ -468,6 +472,13 @@ class SemaOpenACC : public SemaBase {
468472
return std::get<DeviceTypeDetails>(Details).Archs;
469473
}
470474

475+
std::variant<std::monostate, clang::StringLiteral *, IdentifierInfo *>
476+
getBindDetails() const {
477+
assert(ClauseKind == OpenACCClauseKind::Bind &&
478+
"Only 'bind' has bind details");
479+
return std::get<BindDetails>(Details).Argument;
480+
}
481+
471482
void setLParenLoc(SourceLocation EndLoc) { LParenLoc = EndLoc; }
472483
void setEndLoc(SourceLocation EndLoc) { ClauseRange.setEnd(EndLoc); }
473484

@@ -652,6 +663,14 @@ class SemaOpenACC : public SemaBase {
652663
"Only 'collapse' has collapse details");
653664
Details = CollapseDetails{IsForce, LoopCount};
654665
}
666+
667+
void setBindDetails(
668+
std::variant<std::monostate, clang::StringLiteral *, IdentifierInfo *>
669+
Arg) {
670+
assert(ClauseKind == OpenACCClauseKind::Bind &&
671+
"Only 'bind' has bind details");
672+
Details = BindDetails{Arg};
673+
}
655674
};
656675

657676
SemaOpenACC(Sema &S);

clang/lib/AST/OpenACCClause.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ using namespace clang;
2020
bool OpenACCClauseWithParams::classof(const OpenACCClause *C) {
2121
return OpenACCDeviceTypeClause::classof(C) ||
2222
OpenACCClauseWithCondition::classof(C) ||
23-
OpenACCClauseWithExprs::classof(C) || OpenACCSelfClause::classof(C);
23+
OpenACCBindClause::classof(C) || OpenACCClauseWithExprs::classof(C) ||
24+
OpenACCSelfClause::classof(C);
2425
}
2526
bool OpenACCClauseWithExprs::classof(const OpenACCClause *C) {
2627
return OpenACCWaitClause::classof(C) || OpenACCNumGangsClause::classof(C) ||
@@ -609,6 +610,24 @@ OpenACCIfPresentClause *OpenACCIfPresentClause::Create(const ASTContext &C,
609610
return new (Mem) OpenACCIfPresentClause(BeginLoc, EndLoc);
610611
}
611612

613+
OpenACCBindClause *OpenACCBindClause::Create(const ASTContext &C,
614+
SourceLocation BeginLoc,
615+
SourceLocation LParenLoc,
616+
const StringLiteral *SL,
617+
SourceLocation EndLoc) {
618+
void *Mem = C.Allocate(sizeof(OpenACCBindClause), alignof(OpenACCBindClause));
619+
return new (Mem) OpenACCBindClause(BeginLoc, LParenLoc, SL, EndLoc);
620+
}
621+
622+
OpenACCBindClause *OpenACCBindClause::Create(const ASTContext &C,
623+
SourceLocation BeginLoc,
624+
SourceLocation LParenLoc,
625+
const IdentifierInfo *ID,
626+
SourceLocation EndLoc) {
627+
void *Mem = C.Allocate(sizeof(OpenACCBindClause), alignof(OpenACCBindClause));
628+
return new (Mem) OpenACCBindClause(BeginLoc, LParenLoc, ID, EndLoc);
629+
}
630+
612631
//===----------------------------------------------------------------------===//
613632
// OpenACC clauses printing methods
614633
//===----------------------------------------------------------------------===//
@@ -936,3 +955,12 @@ void OpenACCClausePrinter::VisitIfPresentClause(
936955
const OpenACCIfPresentClause &C) {
937956
OS << "if_present";
938957
}
958+
959+
void OpenACCClausePrinter::VisitBindClause(const OpenACCBindClause &C) {
960+
OS << "bind(";
961+
if (C.isStringArgument())
962+
OS << '"' << C.getStringArgument()->getString() << '"';
963+
else
964+
OS << C.getIdentifierArgument()->getName();
965+
OS << ")";
966+
}

clang/lib/AST/StmtProfile.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2732,6 +2732,10 @@ void OpenACCClauseProfiler::VisitReductionClause(
27322732
const OpenACCReductionClause &Clause) {
27332733
VisitClauseWithVarList(Clause);
27342734
}
2735+
2736+
void OpenACCClauseProfiler::VisitBindClause(const OpenACCBindClause &Clause) {
2737+
assert(false && "not implemented... what can we do about our expr?");
2738+
}
27352739
} // namespace
27362740

27372741
void StmtProfiler::VisitOpenACCComputeConstruct(

clang/lib/AST/TextNodeDumper.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,7 @@ void TextNodeDumper::Visit(const OpenACCClause *C) {
435435
case OpenACCClauseKind::UseDevice:
436436
case OpenACCClauseKind::Vector:
437437
case OpenACCClauseKind::VectorLength:
438+
case OpenACCClauseKind::Invalid:
438439
// The condition expression will be printed as a part of the 'children',
439440
// but print 'clause' here so it is clear what is happening from the dump.
440441
OS << " clause";
@@ -501,9 +502,15 @@ void TextNodeDumper::Visit(const OpenACCClause *C) {
501502
OS << " clause Operator: "
502503
<< cast<OpenACCReductionClause>(C)->getReductionOp();
503504
break;
504-
default:
505-
// Nothing to do here.
506-
break;
505+
case OpenACCClauseKind::Bind:
506+
OS << " clause";
507+
if (cast<OpenACCBindClause>(C)->isIdentifierArgument())
508+
OS << " identifier '"
509+
<< cast<OpenACCBindClause>(C)->getIdentifierArgument()->getName()
510+
<< "'";
511+
else
512+
AddChild(
513+
[=] { Visit(cast<OpenACCBindClause>(C)->getStringArgument()); });
507514
}
508515
}
509516
dumpPointer(C);

clang/lib/Parse/ParseOpenACC.cpp

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,8 +1059,11 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams(
10591059
break;
10601060
}
10611061
case OpenACCClauseKind::Bind: {
1062-
ExprResult BindArg = ParseOpenACCBindClauseArgument();
1063-
if (BindArg.isInvalid()) {
1062+
ParsedClause.setBindDetails(ParseOpenACCBindClauseArgument());
1063+
1064+
// We can create an 'empty' bind clause in the event of an error
1065+
if (std::holds_alternative<std::monostate>(
1066+
ParsedClause.getBindDetails())) {
10641067
Parens.skipToEnd();
10651068
return OpenACCCanContinue();
10661069
}
@@ -1334,7 +1337,8 @@ ExprResult Parser::ParseOpenACCIDExpression() {
13341337
return getActions().CorrectDelayedTyposInExpr(Res);
13351338
}
13361339

1337-
ExprResult Parser::ParseOpenACCBindClauseArgument() {
1340+
std::variant<std::monostate, clang::StringLiteral *, IdentifierInfo *>
1341+
Parser::ParseOpenACCBindClauseArgument() {
13381342
// OpenACC 3.3 section 2.15:
13391343
// The bind clause specifies the name to use when calling the procedure on a
13401344
// device other than the host. If the name is specified as an identifier, it
@@ -1343,14 +1347,21 @@ ExprResult Parser::ParseOpenACCBindClauseArgument() {
13431347
// name unmodified.
13441348
if (getCurToken().is(tok::r_paren)) {
13451349
Diag(getCurToken(), diag::err_acc_incorrect_bind_arg);
1346-
return ExprError();
1350+
return std::monostate{};
13471351
}
13481352

1349-
if (tok::isStringLiteral(getCurToken().getKind()))
1350-
return getActions().CorrectDelayedTyposInExpr(ParseStringLiteralExpression(
1351-
/*AllowUserDefinedLiteral=*/false, /*Unevaluated=*/true));
1353+
if (getCurToken().is(tok::identifier)) {
1354+
IdentifierInfo *II = getCurToken().getIdentifierInfo();
1355+
ConsumeToken();
1356+
return II;
1357+
}
13521358

1353-
return ParseOpenACCIDExpression();
1359+
ExprResult Res =
1360+
getActions().CorrectDelayedTyposInExpr(ParseStringLiteralExpression(
1361+
/*AllowUserDefinedLiteral=*/false, /*Unevaluated=*/true));
1362+
if (!Res.isUsable())
1363+
return std::monostate{};
1364+
return cast<StringLiteral>(Res.get());
13541365
}
13551366

13561367
/// OpenACC 3.3, section 1.6:

clang/lib/Sema/SemaOpenACC.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1904,7 +1904,31 @@ DeclGroupRef SemaOpenACC::ActOnEndDeclDirective(
19041904
Diag(DirLoc, diag::note_acc_construct_here)
19051905
<< OpenACCDirectiveKind::Routine;
19061906
}
1907-
FD->addAttr(OpenACCRoutineAnnotAttr::Create(getASTContext(), DirLoc));
1907+
1908+
// OpenACC 3.3 2.15:
1909+
// A bind clause may not bind to a routine name that has a visible bind
1910+
// clause.
1911+
// TODO OpenACC: There is an exception to this rule that if these are the
1912+
// implicit function style (that is, without a name), they may have
1913+
// duplicates as long as they have the same name.
1914+
auto BindItr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCBindClause>);
1915+
if (auto *A = FD->getAttr<OpenACCRoutineAnnotAttr>()) {
1916+
if (BindItr != Clauses.end()) {
1917+
if (A->BindClause.isInvalid()) {
1918+
// If we have a bind clause, and the function doesn't have one
1919+
// annotated yet, set it.
1920+
A->BindClause = (*BindItr)->getBeginLoc();
1921+
} else {
1922+
Diag((*BindItr)->getBeginLoc(), diag::err_acc_duplicate_bind);
1923+
Diag(A->BindClause, diag::note_acc_previous_clause_here);
1924+
}
1925+
}
1926+
} else {
1927+
auto *RAA = OpenACCRoutineAnnotAttr::Create(getASTContext(), DirLoc);
1928+
FD->addAttr(RAA);
1929+
if (BindItr != Clauses.end())
1930+
RAA->BindClause = (*BindItr)->getBeginLoc();
1931+
}
19081932
}
19091933

19101934
return DeclGroupRef{RoutineDecl};

clang/lib/Sema/SemaOpenACCClause.cpp

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,14 @@ bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind,
483483
return false;
484484
}
485485
}
486+
case OpenACCClauseKind::Bind: {
487+
switch (DirectiveKind) {
488+
case OpenACCDirectiveKind::Routine:
489+
return true;
490+
default:
491+
return false;
492+
}
493+
}
486494
}
487495

488496
default:
@@ -677,10 +685,6 @@ class SemaOpenACCClauseVisitor {
677685
SemaOpenACCClauseVisitor(SemaOpenACC &S,
678686
ArrayRef<const OpenACCClause *> ExistingClauses)
679687
: SemaRef(S), Ctx(S.getASTContext()), ExistingClauses(ExistingClauses) {}
680-
// Once we've implemented everything, we shouldn't need this infrastructure.
681-
// But in the meantime, we use this to help decide whether the clause was
682-
// handled for this directive.
683-
bool diagNotImplemented() { return NotImplemented; }
684688

685689
OpenACCClause *Visit(SemaOpenACC::OpenACCParsedClause &Clause) {
686690
switch (Clause.getClauseKind()) {
@@ -1985,6 +1989,17 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitCollapseClause(
19851989
LoopCount.get(), Clause.getEndLoc());
19861990
}
19871991

1992+
OpenACCClause *SemaOpenACCClauseVisitor::VisitBindClause(
1993+
SemaOpenACC::OpenACCParsedClause &Clause) {
1994+
if (std::holds_alternative<StringLiteral *>(Clause.getBindDetails()))
1995+
return OpenACCBindClause::Create(
1996+
Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(),
1997+
std::get<StringLiteral *>(Clause.getBindDetails()), Clause.getEndLoc());
1998+
return OpenACCBindClause::Create(
1999+
Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(),
2000+
std::get<IdentifierInfo *>(Clause.getBindDetails()), Clause.getEndLoc());
2001+
}
2002+
19882003
// Return true if the two vars refer to the same variable, for the purposes of
19892004
// equality checking.
19902005
bool areVarsEqual(Expr *VarExpr1, Expr *VarExpr2) {
@@ -2073,12 +2088,7 @@ SemaOpenACC::ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses,
20732088
assert((!Result || Result->getClauseKind() == Clause.getClauseKind()) &&
20742089
"Created wrong clause?");
20752090

2076-
if (Visitor.diagNotImplemented())
2077-
Diag(Clause.getBeginLoc(), diag::warn_acc_clause_unimplemented)
2078-
<< Clause.getClauseKind();
2079-
20802091
return Result;
2081-
20822092
}
20832093

20842094
/// OpenACC 3.3 section 2.5.15:

0 commit comments

Comments
 (0)