[clang] [OpenACC] Implement 'wait' construct parsing (PR #74752)
Erich Keane via cfe-commits
cfe-commits at lists.llvm.org
Thu Dec 7 13:30:36 PST 2023
https://github.com/erichkeane updated https://github.com/llvm/llvm-project/pull/74752
>From 8b7d70d55395d9a75968deeac8a13d88aae62a00 Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Thu, 7 Dec 2023 08:55:46 -0800
Subject: [PATCH 1/2] [OpenACC] Implement 'wait' construct parsing
The 'wait' construct comes in two forms: one with no parens, the second
with a 'wait-argument'. This implements both forms for constructs.
Additionally, the 'wait-argument' parsing is split into its own function
because the 'wait clause' can also take the same 'wait-argument'.
---
clang/include/clang/Basic/OpenACCKinds.h | 2 +-
clang/include/clang/Parse/Parser.h | 1 +
clang/lib/Parse/ParseOpenACC.cpp | 71 ++++++++
.../test/ParserOpenACC/parse-wait-construct.c | 157 ++++++++++++++++++
4 files changed, 230 insertions(+), 1 deletion(-)
create mode 100644 clang/test/ParserOpenACC/parse-wait-construct.c
diff --git a/clang/include/clang/Basic/OpenACCKinds.h b/clang/include/clang/Basic/OpenACCKinds.h
index 449a75638b43f..62c0a4c1a9dea 100644
--- a/clang/include/clang/Basic/OpenACCKinds.h
+++ b/clang/include/clang/Basic/OpenACCKinds.h
@@ -53,7 +53,7 @@ enum class OpenACCDirectiveKind {
Shutdown,
Set,
Update,
- // FIXME: wait construct.
+ Wait,
// Procedure Calls in Compute Regions.
Routine,
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 32d0b76c35b0d..0663498235164 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -3544,6 +3544,7 @@ class Parser : public CodeCompletionHandler {
void ParseOpenACCCacheVarList();
/// Parses a single variable in a variable list for the 'cache' construct.
bool ParseOpenACCCacheVar();
+ bool ParseOpenACCWaitArgument();
private:
//===--------------------------------------------------------------------===//
diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp
index 71cb665a56327..0bdf8da26bb01 100644
--- a/clang/lib/Parse/ParseOpenACC.cpp
+++ b/clang/lib/Parse/ParseOpenACC.cpp
@@ -56,6 +56,7 @@ OpenACCDirectiveKindEx getOpenACCDirectiveKind(Token Tok) {
.Case("shutdown", OpenACCDirectiveKind::Shutdown)
.Case("set", OpenACCDirectiveKind::Shutdown)
.Case("update", OpenACCDirectiveKind::Update)
+ .Case("wait", OpenACCDirectiveKind::Wait)
.Default(OpenACCDirectiveKind::Invalid);
if (DirKind != OpenACCDirectiveKind::Invalid)
@@ -123,6 +124,8 @@ bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, Token Tok) {
return Tok.getIdentifierInfo()->isStr("set");
case OpenACCDirectiveKind::Update:
return Tok.getIdentifierInfo()->isStr("update");
+ case OpenACCDirectiveKind::Wait:
+ return Tok.getIdentifierInfo()->isStr("wait");
case OpenACCDirectiveKind::Invalid:
return false;
}
@@ -251,6 +254,67 @@ void ParseOpenACCClauseList(Parser &P) {
} // namespace
+/// OpenACC 3.3, section 2.16:
+/// In this section and throughout the specification, the term wait-argument
+/// means:
+/// [ devnum : int-expr : ] [ queues : ] async-argument-list
+bool Parser::ParseOpenACCWaitArgument() {
+ // [devnum : int-expr : ]
+ if (Tok.is(tok::identifier) && NextToken().is(tok::colon) &&
+ Tok.getIdentifierInfo()->isStr("devnum")) {
+ // Consume devnum.
+ ConsumeToken();
+ // Consume colon.
+ ConsumeToken();
+
+ ExprResult IntExpr =
+ getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression());
+ if (IntExpr.isInvalid())
+ return true;
+
+ if (ExpectAndConsume(tok::colon))
+ return true;
+ }
+
+ // [ queues : ]
+ if (Tok.is(tok::identifier) && NextToken().is(tok::colon) &&
+ Tok.getIdentifierInfo()->isStr("queues")) {
+ // Consume queues.
+ ConsumeToken();
+ // Consume colon.
+ ConsumeToken();
+ }
+
+ // OpenACC 3.3, section 2.16:
+ // the term 'async-argument' means a nonnegative scalar integer expression, or
+ // one of the special values 'acc_async_noval' or 'acc_async_sync', as defined
+ // in the C header file and the Fortran opacc module.
+ //
+ // We are parsing this simply as list of assignment expressions (to avoid
+ // comma being troublesome), and will ensure it is an integral type. The
+ // 'special' types are defined as macros, so we can't really check those
+ // (other than perhaps as values at one point?), but the standard does say it
+ // is implementation-defined to use any other negative value.
+ //
+ //
+ bool FirstArg = true;
+ while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
+ if (!FirstArg) {
+ if (ExpectAndConsume(tok::comma))
+ return true;
+ }
+ FirstArg = false;
+
+ ExprResult CurArg =
+ getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression());
+
+ if (CurArg.isInvalid())
+ return true;
+ }
+
+ return false;
+}
+
ExprResult Parser::ParseOpenACCIDExpression() {
ExprResult Res;
if (getLangOpts().CPlusPlus) {
@@ -399,6 +463,13 @@ void Parser::ParseOpenACCDirective() {
// so we can always consume the close.
T.consumeClose();
break;
+ case OpenACCDirectiveKind::Wait:
+ // OpenACC has an optional paren-wrapped 'wait-argument'.
+ if (ParseOpenACCWaitArgument())
+ T.skipToEnd();
+ else
+ T.consumeClose();
+ break;
}
} else if (DirKind == OpenACCDirectiveKind::Cache) {
// Cache's paren var-list is required, so error here if it isn't provided.
diff --git a/clang/test/ParserOpenACC/parse-wait-construct.c b/clang/test/ParserOpenACC/parse-wait-construct.c
new file mode 100644
index 0000000000000..9b210bc709421
--- /dev/null
+++ b/clang/test/ParserOpenACC/parse-wait-construct.c
@@ -0,0 +1,157 @@
+// RUN: %clang_cc1 %s -verify -fopenacc
+
+void func() {
+ int i, j;
+
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait
+
+ // expected-warning at +2{{OpenACC clause parsing not yet implemented}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait clause-list
+
+ // expected-error at +3{{expected ')'}}
+ // expected-note at +2{{to match this '('}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (
+
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait ()
+
+ // expected-warning at +2{{OpenACC clause parsing not yet implemented}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait () clause-list
+
+ // expected-error at +4{{expected expression}}
+ // expected-error at +3{{expected ')'}}
+ // expected-note at +2{{to match this '('}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (devnum:
+
+ // expected-error at +2{{expected expression}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (devnum:)
+
+ // expected-error at +3{{expected expression}}
+ // expected-warning at +2{{OpenACC clause parsing not yet implemented}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (devnum:) clause-list
+
+ // expected-error at +4{{expected ':'}}
+ // expected-error at +3{{expected ')'}}
+ // expected-note at +2{{to match this '('}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (devnum: i + j
+
+ // expected-error at +2{{expected ':'}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (devnum: i + j)
+
+ // expected-error at +3{{expected ':'}}
+ // expected-warning at +2{{OpenACC clause parsing not yet implemented}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (devnum: i + j) clause-list
+
+ // expected-error at +3{{expected ')'}}
+ // expected-note at +2{{to match this '('}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (queues:
+
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (queues:)
+
+ // expected-warning at +2{{OpenACC clause parsing not yet implemented}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (queues:) clause-list
+
+ // expected-error at +3{{expected ')'}}
+ // expected-note at +2{{to match this '('}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (devnum: i + j:queues:
+
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (devnum: i + j:queues:)
+
+ // expected-warning at +2{{OpenACC clause parsing not yet implemented}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (devnum: i + j:queues:) clause-list
+
+ // expected-error at +4{{use of undeclared identifier 'devnum'}}
+ // expected-error at +3{{expected ')'}}
+ // expected-note at +2{{to match this '('}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (queues:devnum: i + j
+
+ // expected-error at +2{{use of undeclared identifier 'devnum'}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (queues:devnum: i + j)
+
+ // expected-error at +3{{use of undeclared identifier 'devnum'}}
+ // expected-warning at +2{{OpenACC clause parsing not yet implemented}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (queues:devnum: i + j) clause-list
+
+ // expected-error at +3{{expected ')'}}
+ // expected-note at +2{{to match this '('}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(i, j, 1+1, 3.3
+
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(i, j, 1+1, 3.3)
+ // expected-warning at +2{{OpenACC clause parsing not yet implemented}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(i, j, 1+1, 3.3) clause-list
+
+ // expected-error at +4{{expected expression}}
+ // expected-error at +3{{expected ')'}}
+ // expected-note at +2{{to match this '('}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(,
+
+ // expected-error at +2{{expected expression}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(,)
+
+ // expected-error at +3{{expected expression}}
+ // expected-warning at +2{{OpenACC clause parsing not yet implemented}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(,) clause-list
+
+ // expected-error at +3{{expected ')'}}
+ // expected-note at +2{{to match this '('}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(queues:i, j, 1+1, 3.3
+
+ // expected-error at +4{{expected expression}}
+ // expected-error at +3{{expected ')'}}
+ // expected-note at +2{{to match this '('}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(queues:i, j, 1+1, 3.3,
+
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(queues:i, j, 1+1, 3.3)
+
+ // expected-warning at +2{{OpenACC clause parsing not yet implemented}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(queues:i, j, 1+1, 3.3) clause-list
+
+ // expected-error at +3{{expected ')'}}
+ // expected-note at +2{{to match this '('}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(devnum:3:i, j, 1+1, 3.3
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(devnum:3:i, j, 1+1, 3.3)
+ // expected-warning at +2{{OpenACC clause parsing not yet implemented}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(devnum:3:i, j, 1+1, 3.3) clause-list
+
+ // expected-error at +3{{expected ')'}}
+ // expected-note at +2{{to match this '('}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(devnum:3:queues:i, j, 1+1, 3.3
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(devnum:3:queues:i, j, 1+1, 3.3)
+ // expected-warning at +2{{OpenACC clause parsing not yet implemented}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(devnum:3:queues:i, j, 1+1, 3.3) clause-list
+}
>From 9fbfe112f4420777a0c0ff8837ce929a31457a17 Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Thu, 7 Dec 2023 13:30:13 -0800
Subject: [PATCH 2/2] Add isSpecialTokenKind
---
clang/lib/Parse/ParseOpenACC.cpp | 26 ++++++++++++++++++++++----
1 file changed, 22 insertions(+), 4 deletions(-)
diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp
index 0bdf8da26bb01..40b53dd180c79 100644
--- a/clang/lib/Parse/ParseOpenACC.cpp
+++ b/clang/lib/Parse/ParseOpenACC.cpp
@@ -83,6 +83,24 @@ OpenACCAtomicKind getOpenACCAtomicKind(Token Tok) {
.Default(OpenACCAtomicKind::Invalid);
}
+enum class OpenACCSpecialTokenKind {
+ DevNum,
+ Queues,
+};
+
+bool isOpenACCSpecialToken(OpenACCSpecialTokenKind Kind, Token Tok) {
+ if (!Tok.is(tok::identifier))
+ return false;
+
+ switch (Kind) {
+ case OpenACCSpecialTokenKind::DevNum:
+ return Tok.getIdentifierInfo()->isStr("devnum");
+ case OpenACCSpecialTokenKind::Queues:
+ return Tok.getIdentifierInfo()->isStr("queues");
+ }
+ llvm_unreachable("Unknown 'Kind' Passed");
+}
+
bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, Token Tok) {
if (!Tok.is(tok::identifier))
return false;
@@ -260,8 +278,8 @@ void ParseOpenACCClauseList(Parser &P) {
/// [ devnum : int-expr : ] [ queues : ] async-argument-list
bool Parser::ParseOpenACCWaitArgument() {
// [devnum : int-expr : ]
- if (Tok.is(tok::identifier) && NextToken().is(tok::colon) &&
- Tok.getIdentifierInfo()->isStr("devnum")) {
+ if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::DevNum, Tok) &&
+ NextToken().is(tok::colon)) {
// Consume devnum.
ConsumeToken();
// Consume colon.
@@ -277,8 +295,8 @@ bool Parser::ParseOpenACCWaitArgument() {
}
// [ queues : ]
- if (Tok.is(tok::identifier) && NextToken().is(tok::colon) &&
- Tok.getIdentifierInfo()->isStr("queues")) {
+ if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Queues, Tok) &&
+ NextToken().is(tok::colon)) {
// Consume queues.
ConsumeToken();
// Consume colon.
More information about the cfe-commits
mailing list