Skip to content

Commit 04e9b61

Browse files
authored
[OpenACC] Implement Atomic construct variants (#73015)
`atomic` is required to be followed by a special `atomic clause`, so this patch manages the parsing of that. We are representing each of the variants of the atomic construct as separate kinds, because they have distinct rules/application/etc, and this should make it easier to check rules in the future.
1 parent 730e0d0 commit 04e9b61

File tree

3 files changed

+81
-3
lines changed

3 files changed

+81
-3
lines changed

clang/include/clang/Basic/OpenACCKinds.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ enum class OpenACCDirectiveKind {
4141
SerialLoop,
4242
KernelsLoop,
4343

44-
// FIXME: atomic Construct variants.
44+
// Atomic Construct.
45+
Atomic,
4546

4647
// Declare Directive.
4748
Declare,
@@ -59,6 +60,14 @@ enum class OpenACCDirectiveKind {
5960
// Invalid.
6061
Invalid,
6162
};
63+
64+
enum class OpenACCAtomicKind {
65+
Read,
66+
Write,
67+
Update,
68+
Capture,
69+
Invalid,
70+
};
6271
} // namespace clang
6372

6473
#endif // LLVM_CLANG_BASIC_OPENACCKINDS_H

clang/lib/Parse/ParseOpenACC.cpp

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ enum class OpenACCDirectiveKindEx {
2929
// 'enter data' and 'exit data'
3030
Enter,
3131
Exit,
32-
// FIXME: Atomic Variants
3332
};
3433

3534
// Translate single-token string representations to the OpenACC Directive Kind.
@@ -46,6 +45,7 @@ OpenACCDirectiveKindEx getOpenACCDirectiveKind(StringRef Name) {
4645
.Case("data", OpenACCDirectiveKind::Data)
4746
.Case("host_data", OpenACCDirectiveKind::HostData)
4847
.Case("loop", OpenACCDirectiveKind::Loop)
48+
.Case("atomic", OpenACCDirectiveKind::Atomic)
4949
.Case("declare", OpenACCDirectiveKind::Declare)
5050
.Case("init", OpenACCDirectiveKind::Init)
5151
.Case("shutdown", OpenACCDirectiveKind::Shutdown)
@@ -62,6 +62,17 @@ OpenACCDirectiveKindEx getOpenACCDirectiveKind(StringRef Name) {
6262
.Default(OpenACCDirectiveKindEx::Invalid);
6363
}
6464

65+
// Since 'atomic' is effectively a compound directive, this will decode the
66+
// second part of the directive.
67+
OpenACCAtomicKind getOpenACCAtomicKind(StringRef Name) {
68+
return llvm::StringSwitch<OpenACCAtomicKind>(Name)
69+
.Case("read", OpenACCAtomicKind::Read)
70+
.Case("write", OpenACCAtomicKind::Write)
71+
.Case("update", OpenACCAtomicKind::Update)
72+
.Case("capture", OpenACCAtomicKind::Capture)
73+
.Default(OpenACCAtomicKind::Invalid);
74+
}
75+
6576
bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, StringRef Tok) {
6677
switch (Kind) {
6778
case OpenACCDirectiveKind::Parallel:
@@ -84,6 +95,8 @@ bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, StringRef Tok) {
8495
case OpenACCDirectiveKind::ExitData:
8596
return false;
8697

98+
case OpenACCDirectiveKind::Atomic:
99+
return Tok == "atomic";
87100
case OpenACCDirectiveKind::Declare:
88101
return Tok == "declare";
89102
case OpenACCDirectiveKind::Init:
@@ -126,6 +139,27 @@ ParseOpenACCEnterExitDataDirective(Parser &P, Token FirstTok,
126139
: OpenACCDirectiveKind::ExitData;
127140
}
128141

142+
OpenACCAtomicKind ParseOpenACCAtomicKind(Parser &P) {
143+
Token AtomicClauseToken = P.getCurToken();
144+
145+
// #pragma acc atomic is equivilent to update:
146+
if (AtomicClauseToken.isAnnotation())
147+
return OpenACCAtomicKind::Update;
148+
149+
std::string AtomicClauseSpelling =
150+
P.getPreprocessor().getSpelling(AtomicClauseToken);
151+
OpenACCAtomicKind AtomicKind = getOpenACCAtomicKind(AtomicClauseSpelling);
152+
153+
// If we don't know what this is, treat it as 'nothing', and treat the rest of
154+
// this as a clause list, which, despite being invalid, is likely what the
155+
// user was trying to do.
156+
if (AtomicKind == OpenACCAtomicKind::Invalid)
157+
return OpenACCAtomicKind::Update;
158+
159+
P.ConsumeToken();
160+
return AtomicKind;
161+
}
162+
129163
// Parse and consume the tokens for OpenACC Directive/Construct kinds.
130164
OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) {
131165
Token FirstTok = P.getCurToken();
@@ -199,7 +233,13 @@ void ParseOpenACCClauseList(Parser &P) {
199233
}
200234

201235
void ParseOpenACCDirective(Parser &P) {
202-
ParseOpenACCDirectiveKind(P);
236+
OpenACCDirectiveKind DirKind = ParseOpenACCDirectiveKind(P);
237+
238+
// Once we've parsed the construct/directive name, some have additional
239+
// specifiers that need to be taken care of. Atomic has an 'atomic-clause'
240+
// that needs to be parsed.
241+
if (DirKind == OpenACCDirectiveKind::Atomic)
242+
ParseOpenACCAtomicKind(P);
203243

204244
// Parses the list of clauses, if present.
205245
ParseOpenACCClauseList(P);

clang/test/ParserOpenACC/parse-constructs.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,35 @@ void func() {
9494
#pragma acc kernels loop
9595
for(;;){}
9696

97+
int i = 0, j = 0, k = 0;
98+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
99+
#pragma acc atomic
100+
i = j;
101+
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
102+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
103+
#pragma acc atomic garbage
104+
i = j;
105+
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
106+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
107+
#pragma acc atomic garbage clause list
108+
i = j;
109+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
110+
#pragma acc atomic read
111+
i = j;
112+
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
113+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
114+
#pragma acc atomic write clause list
115+
i = i + j;
116+
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
117+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
118+
#pragma acc atomic update clause list
119+
i++;
120+
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
121+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
122+
#pragma acc atomic capture clause list
123+
i = j++;
124+
125+
97126
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
98127
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
99128
#pragma acc declare clause list

0 commit comments

Comments
 (0)