https://github.com/erichkeane updated https://github.com/llvm/llvm-project/pull/74752
>From 8b7d70d55395d9a75968deeac8a13d88aae62a00 Mon Sep 17 00:00:00 2001 From: erichkeane <eke...@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@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait + + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait clause-list + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait ( + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait () + + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait () clause-list + + // expected-error@+4{{expected expression}} + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (devnum: + + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (devnum:) + + // expected-error@+3{{expected expression}} + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (devnum:) clause-list + + // expected-error@+4{{expected ':'}} + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (devnum: i + j + + // expected-error@+2{{expected ':'}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (devnum: i + j) + + // expected-error@+3{{expected ':'}} + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (devnum: i + j) clause-list + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (queues: + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (queues:) + + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (queues:) clause-list + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (devnum: i + j:queues: + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (devnum: i + j:queues:) + + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (devnum: i + j:queues:) clause-list + + // expected-error@+4{{use of undeclared identifier 'devnum'}} + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (queues:devnum: i + j + + // expected-error@+2{{use of undeclared identifier 'devnum'}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (queues:devnum: i + j) + + // expected-error@+3{{use of undeclared identifier 'devnum'}} + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (queues:devnum: i + j) clause-list + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(i, j, 1+1, 3.3 + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(i, j, 1+1, 3.3) + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(i, j, 1+1, 3.3) clause-list + + // expected-error@+4{{expected expression}} + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(, + + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(,) + + // expected-error@+3{{expected expression}} + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(,) clause-list + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(queues:i, j, 1+1, 3.3 + + // expected-error@+4{{expected expression}} + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(queues:i, j, 1+1, 3.3, + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(queues:i, j, 1+1, 3.3) + + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(queues:i, j, 1+1, 3.3) clause-list + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(devnum:3:i, j, 1+1, 3.3 + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(devnum:3:i, j, 1+1, 3.3) + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(devnum:3:i, j, 1+1, 3.3) clause-list + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(devnum:3:queues:i, j, 1+1, 3.3 + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(devnum:3:queues:i, j, 1+1, 3.3) + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+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 <eke...@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. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits