@@ -29,7 +29,6 @@ enum class OpenACCDirectiveKindEx {
29
29
// 'enter data' and 'exit data'
30
30
Enter,
31
31
Exit,
32
- // FIXME: Atomic Variants
33
32
};
34
33
35
34
// Translate single-token string representations to the OpenACC Directive Kind.
@@ -46,6 +45,7 @@ OpenACCDirectiveKindEx getOpenACCDirectiveKind(StringRef Name) {
46
45
.Case (" data" , OpenACCDirectiveKind::Data)
47
46
.Case (" host_data" , OpenACCDirectiveKind::HostData)
48
47
.Case (" loop" , OpenACCDirectiveKind::Loop)
48
+ .Case (" atomic" , OpenACCDirectiveKind::Atomic)
49
49
.Case (" declare" , OpenACCDirectiveKind::Declare)
50
50
.Case (" init" , OpenACCDirectiveKind::Init)
51
51
.Case (" shutdown" , OpenACCDirectiveKind::Shutdown)
@@ -62,6 +62,17 @@ OpenACCDirectiveKindEx getOpenACCDirectiveKind(StringRef Name) {
62
62
.Default (OpenACCDirectiveKindEx::Invalid);
63
63
}
64
64
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
+
65
76
bool isOpenACCDirectiveKind (OpenACCDirectiveKind Kind, StringRef Tok) {
66
77
switch (Kind) {
67
78
case OpenACCDirectiveKind::Parallel:
@@ -84,6 +95,8 @@ bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, StringRef Tok) {
84
95
case OpenACCDirectiveKind::ExitData:
85
96
return false ;
86
97
98
+ case OpenACCDirectiveKind::Atomic:
99
+ return Tok == " atomic" ;
87
100
case OpenACCDirectiveKind::Declare:
88
101
return Tok == " declare" ;
89
102
case OpenACCDirectiveKind::Init:
@@ -126,6 +139,27 @@ ParseOpenACCEnterExitDataDirective(Parser &P, Token FirstTok,
126
139
: OpenACCDirectiveKind::ExitData;
127
140
}
128
141
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
+
129
163
// Parse and consume the tokens for OpenACC Directive/Construct kinds.
130
164
OpenACCDirectiveKind ParseOpenACCDirectiveKind (Parser &P) {
131
165
Token FirstTok = P.getCurToken ();
@@ -199,7 +233,13 @@ void ParseOpenACCClauseList(Parser &P) {
199
233
}
200
234
201
235
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);
203
243
204
244
// Parses the list of clauses, if present.
205
245
ParseOpenACCClauseList (P);
0 commit comments