Skip to content

Commit

Permalink
[OpenACC] Implement compound construct parsing (#72692)
Browse files Browse the repository at this point in the history
This patch implements the compound construct parsing, which allows
'parallel loop', 'serial loop', and 'kernel loop' to act as their own
constructs.
  • Loading branch information
erichkeane committed Nov 20, 2023
1 parent b9951b3 commit 70f4102
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 4 deletions.
5 changes: 4 additions & 1 deletion clang/include/clang/Basic/OpenACCKinds.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ enum class OpenACCDirectiveKind {
Loop,
// FIXME: 'cache'

// FIXME: Combined Constructs.
// Combined Constructs.
ParallelLoop,
SerialLoop,
KernelsLoop,

// FIXME: atomic Construct variants.

Expand Down
68 changes: 65 additions & 3 deletions clang/lib/Parse/ParseOpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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();
Expand All @@ -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;
}

Expand Down
10 changes: 10 additions & 0 deletions clang/test/ParserOpenACC/parse-constructs.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,24 @@ void func() {
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc parallel loop clause list
for(;;){}

// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc parallel loop
for(;;){}
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial loop clause list
for(;;){}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial loop
for(;;){}
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc kernels loop clause list
for(;;){}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc kernels loop
for(;;){}

// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
Expand Down

0 comments on commit 70f4102

Please sign in to comment.