[clang] 70f4102 - [OpenACC] Implement compound construct parsing (#72692)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 20 11:46:12 PST 2023
Author: Erich Keane
Date: 2023-11-20T11:46:07-08:00
New Revision: 70f41022546ea8b2b41ad70702124acd4ed488dc
URL: https://github.com/llvm/llvm-project/commit/70f41022546ea8b2b41ad70702124acd4ed488dc
DIFF: https://github.com/llvm/llvm-project/commit/70f41022546ea8b2b41ad70702124acd4ed488dc.diff
LOG: [OpenACC] Implement compound construct parsing (#72692)
This patch implements the compound construct parsing, which allows
'parallel loop', 'serial loop', and 'kernel loop' to act as their own
constructs.
Added:
Modified:
clang/include/clang/Basic/OpenACCKinds.h
clang/lib/Parse/ParseOpenACC.cpp
clang/test/ParserOpenACC/parse-constructs.c
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/OpenACCKinds.h b/clang/include/clang/Basic/OpenACCKinds.h
index 8da02b93b2b974c..d53b7223b5334b3 100644
--- a/clang/include/clang/Basic/OpenACCKinds.h
+++ b/clang/include/clang/Basic/OpenACCKinds.h
@@ -33,7 +33,10 @@ enum class OpenACCDirectiveKind {
Loop,
// FIXME: 'cache'
- // FIXME: Combined Constructs.
+ // Combined Constructs.
+ ParallelLoop,
+ SerialLoop,
+ KernelsLoop,
// FIXME: atomic Construct variants.
diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp
index e0c8d4395564683..fdf0f24daf98548 100644
--- a/clang/lib/Parse/ParseOpenACC.cpp
+++ b/clang/lib/Parse/ParseOpenACC.cpp
@@ -22,8 +22,10 @@ using namespace llvm;
namespace {
-// Translate single-token string representations to the OpenACC Directive Kind.
-OpenACCDirectiveKind GetOpenACCDirectiveKind(StringRef Name) {
+/// This doesn't completely comprehend 'Compound Constructs' (as it just
+/// identifies the first token) just the first token of each. So
+/// this should only be used by `ParseOpenACCDirectiveKind`.
+OpenACCDirectiveKind getOpenACCDirectiveKind(StringRef Name) {
return llvm::StringSwitch<OpenACCDirectiveKind>(Name)
.Case("parallel", OpenACCDirectiveKind::Parallel)
.Case("serial", OpenACCDirectiveKind::Serial)
@@ -39,6 +41,42 @@ OpenACCDirectiveKind GetOpenACCDirectiveKind(StringRef Name) {
.Default(OpenACCDirectiveKind::Invalid);
}
+bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, StringRef Tok) {
+ switch (Kind) {
+ case OpenACCDirectiveKind::Parallel:
+ return Tok == "parallel";
+ case OpenACCDirectiveKind::Serial:
+ return Tok == "serial";
+ case OpenACCDirectiveKind::Kernels:
+ return Tok == "kernels";
+ case OpenACCDirectiveKind::Data:
+ return Tok == "data";
+ case OpenACCDirectiveKind::HostData:
+ return Tok == "host_data";
+ case OpenACCDirectiveKind::Loop:
+ return Tok == "loop";
+
+ case OpenACCDirectiveKind::ParallelLoop:
+ case OpenACCDirectiveKind::SerialLoop:
+ case OpenACCDirectiveKind::KernelsLoop:
+ return false;
+
+ case OpenACCDirectiveKind::Declare:
+ return Tok == "declare";
+ case OpenACCDirectiveKind::Init:
+ return Tok == "init";
+ case OpenACCDirectiveKind::Shutdown:
+ return Tok == "shutdown";
+ case OpenACCDirectiveKind::Set:
+ return Tok == "set";
+ case OpenACCDirectiveKind::Update:
+ return Tok == "update";
+ case OpenACCDirectiveKind::Invalid:
+ return false;
+ }
+ llvm_unreachable("Unknown 'Kind' Passed");
+}
+
// Parse and consume the tokens for OpenACC Directive/Construct kinds.
OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) {
Token FirstTok = P.getCurToken();
@@ -53,11 +91,35 @@ OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) {
P.ConsumeToken();
std::string FirstTokSpelling = P.getPreprocessor().getSpelling(FirstTok);
- OpenACCDirectiveKind DirKind = GetOpenACCDirectiveKind(FirstTokSpelling);
+ OpenACCDirectiveKind DirKind = getOpenACCDirectiveKind(FirstTokSpelling);
if (DirKind == OpenACCDirectiveKind::Invalid)
P.Diag(FirstTok, diag::err_acc_invalid_directive) << FirstTokSpelling;
+ // Combined Constructs allows parallel loop, serial loop, or kernels loop. Any
+ // other attempt at a combined construct will be diagnosed as an invalid
+ // clause.
+ Token SecondTok = P.getCurToken();
+ if (!SecondTok.isAnnotation() &&
+ isOpenACCDirectiveKind(OpenACCDirectiveKind::Loop,
+ P.getPreprocessor().getSpelling(SecondTok))) {
+ switch (DirKind) {
+ default:
+ // Nothing to do except in the below cases, as they should be diagnosed as
+ // a clause.
+ break;
+ case OpenACCDirectiveKind::Parallel:
+ P.ConsumeToken();
+ return OpenACCDirectiveKind::ParallelLoop;
+ case OpenACCDirectiveKind::Serial:
+ P.ConsumeToken();
+ return OpenACCDirectiveKind::SerialLoop;
+ case OpenACCDirectiveKind::Kernels:
+ P.ConsumeToken();
+ return OpenACCDirectiveKind::KernelsLoop;
+ }
+ }
+
return DirKind;
}
diff --git a/clang/test/ParserOpenACC/parse-constructs.c b/clang/test/ParserOpenACC/parse-constructs.c
index 8642833691ede7f..fcad4507e7c1da0 100644
--- a/clang/test/ParserOpenACC/parse-constructs.c
+++ b/clang/test/ParserOpenACC/parse-constructs.c
@@ -48,14 +48,24 @@ void func() {
// expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc parallel loop clause list
for(;;){}
+
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc parallel loop
+ for(;;){}
// expected-warning at +2{{OpenACC clause parsing not yet implemented}}
// expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial loop clause list
+ for(;;){}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial loop
for(;;){}
// expected-warning at +2{{OpenACC clause parsing not yet implemented}}
// expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc kernels loop clause list
for(;;){}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc kernels loop
+ for(;;){}
// expected-warning at +2{{OpenACC clause parsing not yet implemented}}
// expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
More information about the cfe-commits
mailing list