Skip to content

Commit 70f4102

Browse files
authored
[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.
1 parent b9951b3 commit 70f4102

File tree

3 files changed

+79
-4
lines changed

3 files changed

+79
-4
lines changed

clang/include/clang/Basic/OpenACCKinds.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ enum class OpenACCDirectiveKind {
3333
Loop,
3434
// FIXME: 'cache'
3535

36-
// FIXME: Combined Constructs.
36+
// Combined Constructs.
37+
ParallelLoop,
38+
SerialLoop,
39+
KernelsLoop,
3740

3841
// FIXME: atomic Construct variants.
3942

clang/lib/Parse/ParseOpenACC.cpp

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ using namespace llvm;
2222

2323
namespace {
2424

25-
// Translate single-token string representations to the OpenACC Directive Kind.
26-
OpenACCDirectiveKind GetOpenACCDirectiveKind(StringRef Name) {
25+
/// This doesn't completely comprehend 'Compound Constructs' (as it just
26+
/// identifies the first token) just the first token of each. So
27+
/// this should only be used by `ParseOpenACCDirectiveKind`.
28+
OpenACCDirectiveKind getOpenACCDirectiveKind(StringRef Name) {
2729
return llvm::StringSwitch<OpenACCDirectiveKind>(Name)
2830
.Case("parallel", OpenACCDirectiveKind::Parallel)
2931
.Case("serial", OpenACCDirectiveKind::Serial)
@@ -39,6 +41,42 @@ OpenACCDirectiveKind GetOpenACCDirectiveKind(StringRef Name) {
3941
.Default(OpenACCDirectiveKind::Invalid);
4042
}
4143

44+
bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, StringRef Tok) {
45+
switch (Kind) {
46+
case OpenACCDirectiveKind::Parallel:
47+
return Tok == "parallel";
48+
case OpenACCDirectiveKind::Serial:
49+
return Tok == "serial";
50+
case OpenACCDirectiveKind::Kernels:
51+
return Tok == "kernels";
52+
case OpenACCDirectiveKind::Data:
53+
return Tok == "data";
54+
case OpenACCDirectiveKind::HostData:
55+
return Tok == "host_data";
56+
case OpenACCDirectiveKind::Loop:
57+
return Tok == "loop";
58+
59+
case OpenACCDirectiveKind::ParallelLoop:
60+
case OpenACCDirectiveKind::SerialLoop:
61+
case OpenACCDirectiveKind::KernelsLoop:
62+
return false;
63+
64+
case OpenACCDirectiveKind::Declare:
65+
return Tok == "declare";
66+
case OpenACCDirectiveKind::Init:
67+
return Tok == "init";
68+
case OpenACCDirectiveKind::Shutdown:
69+
return Tok == "shutdown";
70+
case OpenACCDirectiveKind::Set:
71+
return Tok == "set";
72+
case OpenACCDirectiveKind::Update:
73+
return Tok == "update";
74+
case OpenACCDirectiveKind::Invalid:
75+
return false;
76+
}
77+
llvm_unreachable("Unknown 'Kind' Passed");
78+
}
79+
4280
// Parse and consume the tokens for OpenACC Directive/Construct kinds.
4381
OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) {
4482
Token FirstTok = P.getCurToken();
@@ -53,11 +91,35 @@ OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) {
5391
P.ConsumeToken();
5492
std::string FirstTokSpelling = P.getPreprocessor().getSpelling(FirstTok);
5593

56-
OpenACCDirectiveKind DirKind = GetOpenACCDirectiveKind(FirstTokSpelling);
94+
OpenACCDirectiveKind DirKind = getOpenACCDirectiveKind(FirstTokSpelling);
5795

5896
if (DirKind == OpenACCDirectiveKind::Invalid)
5997
P.Diag(FirstTok, diag::err_acc_invalid_directive) << FirstTokSpelling;
6098

99+
// Combined Constructs allows parallel loop, serial loop, or kernels loop. Any
100+
// other attempt at a combined construct will be diagnosed as an invalid
101+
// clause.
102+
Token SecondTok = P.getCurToken();
103+
if (!SecondTok.isAnnotation() &&
104+
isOpenACCDirectiveKind(OpenACCDirectiveKind::Loop,
105+
P.getPreprocessor().getSpelling(SecondTok))) {
106+
switch (DirKind) {
107+
default:
108+
// Nothing to do except in the below cases, as they should be diagnosed as
109+
// a clause.
110+
break;
111+
case OpenACCDirectiveKind::Parallel:
112+
P.ConsumeToken();
113+
return OpenACCDirectiveKind::ParallelLoop;
114+
case OpenACCDirectiveKind::Serial:
115+
P.ConsumeToken();
116+
return OpenACCDirectiveKind::SerialLoop;
117+
case OpenACCDirectiveKind::Kernels:
118+
P.ConsumeToken();
119+
return OpenACCDirectiveKind::KernelsLoop;
120+
}
121+
}
122+
61123
return DirKind;
62124
}
63125

clang/test/ParserOpenACC/parse-constructs.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,24 @@ void func() {
4848
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
4949
#pragma acc parallel loop clause list
5050
for(;;){}
51+
52+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
53+
#pragma acc parallel loop
54+
for(;;){}
5155
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
5256
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
5357
#pragma acc serial loop clause list
58+
for(;;){}
59+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
60+
#pragma acc serial loop
5461
for(;;){}
5562
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
5663
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
5764
#pragma acc kernels loop clause list
5865
for(;;){}
66+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
67+
#pragma acc kernels loop
68+
for(;;){}
5969

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

0 commit comments

Comments
 (0)