Skip to content

Commit 99a9133

Browse files
committed
[OpenACC] Implement Sema/AST for 'atomic' construct
The atomic construct is a particularly complicated one. The directive itself is pretty simple, it has 5 options for the 'atomic-clause'. However, the associated statement is fairly complicated. 'read' accepts: v = x; 'write' accepts: x = expr; 'update' (or no clause) accepts: x++; x--; ++x; --x; x binop= expr; x = x binop expr; x = expr binop x; 'capture' accepts either a compound statement, or: v = x++; v = x--; v = ++x; v = --x; v = x binop= expr; v = x = x binop expr; v = x = expr binop x; IF 'capture' has a compound statement, it accepts: {v = x; x binop= expr; } {x binop= expr; v = x; } {v = x; x = x binop expr; } {v = x; x = expr binop x; } {x = x binop expr ;v = x; } {x = expr binop x; v = x; } {v = x; x = expr; } {v = x; x++; } {v = x; ++x; } {x++; v = x; } {++x; v = x; } {v = x; x--; } {v = x; --x; } {x--; v = x; } {--x; v = x; } While these are all quite complicated, there is a significant amount of similarity between the 'capture' and 'update' lists, so this patch reuses a lot of the same functions. This patch implements the entirety of 'atomic', creating a new Sema file for the sema for it, as it is fairly sizable.
1 parent cb2598d commit 99a9133

32 files changed

+3119
-39
lines changed

clang/include/clang-c/Index.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2206,7 +2206,11 @@ enum CXCursorKind {
22062206
*/
22072207
CXCursor_OpenACCUpdateConstruct = 331,
22082208

2209-
CXCursor_LastStmt = CXCursor_OpenACCUpdateConstruct,
2209+
/** OpenACC atomic Construct.
2210+
*/
2211+
CXCursor_OpenACCAtomicConstruct = 332,
2212+
2213+
CXCursor_LastStmt = CXCursor_OpenACCAtomicConstruct,
22102214

22112215
/**
22122216
* Cursor that represents the translation unit itself.

clang/include/clang/AST/RecursiveASTVisitor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4099,6 +4099,8 @@ DEF_TRAVERSE_STMT(OpenACCSetConstruct,
40994099
{ TRY_TO(VisitOpenACCClauseList(S->clauses())); })
41004100
DEF_TRAVERSE_STMT(OpenACCUpdateConstruct,
41014101
{ TRY_TO(VisitOpenACCClauseList(S->clauses())); })
4102+
DEF_TRAVERSE_STMT(OpenACCAtomicConstruct,
4103+
{ TRY_TO(TraverseOpenACCAssociatedStmtConstruct(S)); })
41024104

41034105
// Traverse HLSL: Out argument expression
41044106
DEF_TRAVERSE_STMT(HLSLOutArgExpr, {})

clang/include/clang/AST/StmtOpenACC.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -751,5 +751,50 @@ class OpenACCUpdateConstruct final
751751
Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
752752
SourceLocation End, ArrayRef<const OpenACCClause *> Clauses);
753753
};
754+
755+
// This class represents the 'atomic' construct, which has an associated
756+
// statement, but no clauses.
757+
class OpenACCAtomicConstruct final : public OpenACCAssociatedStmtConstruct {
758+
759+
friend class ASTStmtReader;
760+
OpenACCAtomicKind AtomicKind = OpenACCAtomicKind::None;
761+
762+
OpenACCAtomicConstruct(EmptyShell)
763+
: OpenACCAssociatedStmtConstruct(
764+
OpenACCAtomicConstructClass, OpenACCDirectiveKind::Atomic,
765+
SourceLocation{}, SourceLocation{}, SourceLocation{},
766+
/*AssociatedStmt=*/nullptr) {}
767+
768+
OpenACCAtomicConstruct(SourceLocation Start, SourceLocation DirectiveLoc,
769+
OpenACCAtomicKind AtKind, SourceLocation End,
770+
Stmt *AssociatedStmt)
771+
: OpenACCAssociatedStmtConstruct(OpenACCAtomicConstructClass,
772+
OpenACCDirectiveKind::Atomic, Start,
773+
DirectiveLoc, End, AssociatedStmt),
774+
AtomicKind(AtKind) {}
775+
776+
void setAssociatedStmt(Stmt *S) {
777+
OpenACCAssociatedStmtConstruct::setAssociatedStmt(S);
778+
}
779+
780+
public:
781+
static bool classof(const Stmt *T) {
782+
return T->getStmtClass() == OpenACCAtomicConstructClass;
783+
}
784+
785+
static OpenACCAtomicConstruct *CreateEmpty(const ASTContext &C);
786+
static OpenACCAtomicConstruct *
787+
Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
788+
OpenACCAtomicKind AtKind, SourceLocation End, Stmt *AssociatedStmt);
789+
790+
OpenACCAtomicKind getAtomicKind() const { return AtomicKind; }
791+
const Stmt *getAssociatedStmt() const {
792+
return OpenACCAssociatedStmtConstruct::getAssociatedStmt();
793+
}
794+
Stmt *getAssociatedStmt() {
795+
return OpenACCAssociatedStmtConstruct::getAssociatedStmt();
796+
}
797+
};
798+
754799
} // namespace clang
755800
#endif // LLVM_CLANG_AST_STMTOPENACC_H

clang/include/clang/AST/TextNodeDumper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,7 @@ class TextNodeDumper
420420
void VisitOpenACCSetConstruct(const OpenACCSetConstruct *S);
421421
void VisitOpenACCShutdownConstruct(const OpenACCShutdownConstruct *S);
422422
void VisitOpenACCUpdateConstruct(const OpenACCUpdateConstruct *S);
423+
void VisitOpenACCAtomicConstruct(const OpenACCAtomicConstruct *S);
423424
void VisitOpenACCAsteriskSizeExpr(const OpenACCAsteriskSizeExpr *S);
424425
void VisitEmbedExpr(const EmbedExpr *S);
425426
void VisitAtomicExpr(const AtomicExpr *AE);

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12903,6 +12903,48 @@ def err_acc_update_as_body
1290312903
: Error<"OpenACC 'update' construct may not appear in place of the "
1290412904
"statement following a%select{n if statement| while statement| do "
1290512905
"statement| switch statement| label statement}0">;
12906+
def err_acc_invalid_atomic
12907+
: Error<"statement associated with OpenACC 'atomic%select{| "
12908+
"%1}0' directive is invalid">;
12909+
def note_acc_atomic_expr_must_be
12910+
: Note<"expected "
12911+
"%enum_select<OACCAtomicExpr>{%Assign{assignment}|%UnaryCompAssign{"
12912+
"assignment, compound assignment, increment, or decrement}}0 "
12913+
"expression">;
12914+
def note_acc_atomic_unsupported_unary_operator
12915+
: Note<"unary operator not supported, only increment and decrement "
12916+
"operations permitted">;
12917+
def note_acc_atomic_unsupported_binary_operator
12918+
: Note<"binary operator not supported, only +, *, -, /, &, ^, |, <<, or >> "
12919+
"are permitted">;
12920+
def note_acc_atomic_unsupported_compound_binary_operator
12921+
: Note<"compound binary operator not supported, only +=, *=, -=, /=, &=, "
12922+
"^=, |=, <<=, or >>= are permitted">;
12923+
12924+
def note_acc_atomic_operand_lvalue_scalar
12925+
: Note<"%select{left |right |}0operand to "
12926+
"%enum_select<OACCAtomicOpKind>{%Assign{assignment}|%CompoundAssign{"
12927+
"compound assignment}|%Inc{increment}|"
12928+
"%Dec{decrement}}1 "
12929+
"expression must be "
12930+
"%enum_select<OACCLValScalar>{%LVal{an l-value}|%Scalar{of scalar "
12931+
"type (was %3)}}2">;
12932+
def note_acc_atomic_too_many_stmts
12933+
: Note<"'atomic capture' with a compound statement only supports two "
12934+
"statements">;
12935+
def note_acc_atomic_expected_binop : Note<"expected binary operation on right "
12936+
"hand side of assignment operator">;
12937+
def note_acc_atomic_mismatch_operand
12938+
: Note<"left hand side of assignment operation('%0') must match one side "
12939+
"of the sub-operation on the right hand side('%1' and '%2')">;
12940+
def note_acc_atomic_mismatch_compound_operand
12941+
: Note<"variable %select{|in unary expression|on right hand side of "
12942+
"assignment|on left hand side of assignment|on left hand side of "
12943+
"compound assignment|on left hand side of assignment}2('%3') must "
12944+
"match variable used %select{|in unary expression|on right hand "
12945+
"side of assignment|<not possible>|on left hand side of compound "
12946+
"assignment|on left hand side of assignment}0('%1') from the first "
12947+
"statement">;
1290612948

1290712949
// AMDGCN builtins diagnostics
1290812950
def err_amdgcn_global_load_lds_size_invalid_value : Error<"invalid size value">;

clang/include/clang/Basic/OpenACCKinds.h

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,33 @@ enum class OpenACCAtomicKind : uint8_t {
171171
Write,
172172
Update,
173173
Capture,
174-
Invalid,
174+
None,
175175
};
176176

177+
template <typename StreamTy>
178+
inline StreamTy &printOpenACCAtomicKind(StreamTy &Out, OpenACCAtomicKind AK) {
179+
switch (AK) {
180+
case OpenACCAtomicKind::Read:
181+
return Out << "read";
182+
case OpenACCAtomicKind::Write:
183+
return Out << "write";
184+
case OpenACCAtomicKind::Update:
185+
return Out << "update";
186+
case OpenACCAtomicKind::Capture:
187+
return Out << "capture";
188+
case OpenACCAtomicKind::None:
189+
return Out << "<none>";
190+
}
191+
}
192+
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out,
193+
OpenACCAtomicKind AK) {
194+
return printOpenACCAtomicKind(Out, AK);
195+
}
196+
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &Out,
197+
OpenACCAtomicKind AK) {
198+
return printOpenACCAtomicKind(Out, AK);
199+
}
200+
177201
/// Represents the kind of an OpenACC clause.
178202
enum class OpenACCClauseKind : uint8_t {
179203
/// 'finalize' clause, allowed on 'exit data' directive.

clang/include/clang/Basic/StmtNodes.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ def OpenACCInitConstruct : StmtNode<OpenACCConstructStmt>;
319319
def OpenACCShutdownConstruct : StmtNode<OpenACCConstructStmt>;
320320
def OpenACCSetConstruct : StmtNode<OpenACCConstructStmt>;
321321
def OpenACCUpdateConstruct : StmtNode<OpenACCConstructStmt>;
322+
def OpenACCAtomicConstruct : StmtNode<OpenACCAssociatedStmtConstruct>;
322323

323324
// OpenACC Additional Expressions.
324325
def OpenACCAsteriskSizeExpr : StmtNode<Expr>;

clang/include/clang/Parse/Parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3710,6 +3710,7 @@ class Parser : public CodeCompletionHandler {
37103710
SourceLocation RParenLoc;
37113711
SourceLocation EndLoc;
37123712
SourceLocation MiscLoc;
3713+
OpenACCAtomicKind AtomicKind;
37133714
SmallVector<Expr *> Exprs;
37143715
SmallVector<OpenACCClause *> Clauses;
37153716
// TODO OpenACC: As we implement support for the Atomic, Routine, and Cache

clang/include/clang/Sema/SemaOpenACC.h

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -695,24 +695,53 @@ class SemaOpenACC : public SemaBase {
695695
/// should check legality of the statement as it appertains to this Construct.
696696
StmtResult ActOnAssociatedStmt(SourceLocation DirectiveLoc,
697697
OpenACCDirectiveKind K,
698+
OpenACCAtomicKind AtKind,
698699
ArrayRef<const OpenACCClause *> Clauses,
699700
StmtResult AssocStmt);
700701

702+
StmtResult ActOnAssociatedStmt(SourceLocation DirectiveLoc,
703+
OpenACCDirectiveKind K,
704+
ArrayRef<const OpenACCClause *> Clauses,
705+
StmtResult AssocStmt) {
706+
return ActOnAssociatedStmt(DirectiveLoc, K, OpenACCAtomicKind::None,
707+
Clauses, AssocStmt);
708+
}
709+
/// Called to check the form of the `atomic` construct which has some fairly
710+
/// sizable restrictions.
711+
StmtResult CheckAtomicAssociatedStmt(SourceLocation AtomicDirLoc,
712+
OpenACCAtomicKind AtKind,
713+
StmtResult AssocStmt);
714+
701715
/// Called after the directive has been completely parsed, including the
702716
/// declaration group or associated statement.
717+
/// DirLoc: Location of the actual directive keyword.
703718
/// LParenLoc: Location of the left paren, if it exists (not on all
704719
/// constructs).
705720
/// MiscLoc: First misc location, if necessary (not all constructs).
706721
/// Exprs: List of expressions on the construct itself, if necessary (not all
707722
/// constructs).
723+
/// AK: The atomic kind of the directive, if necessary (atomic only)
708724
/// RParenLoc: Location of the right paren, if it exists (not on all
709725
/// constructs).
726+
/// EndLoc: The last source location of the driective.
727+
/// Clauses: The list of clauses for the directive, if present.
728+
/// AssocStmt: The associated statement for this construct, if necessary.
710729
StmtResult ActOnEndStmtDirective(
711730
OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc,
712731
SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef<Expr *> Exprs,
713-
SourceLocation RParenLoc, SourceLocation EndLoc,
732+
OpenACCAtomicKind AK, SourceLocation RParenLoc, SourceLocation EndLoc,
714733
ArrayRef<OpenACCClause *> Clauses, StmtResult AssocStmt);
715734

735+
StmtResult ActOnEndStmtDirective(
736+
OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc,
737+
SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef<Expr *> Exprs,
738+
SourceLocation RParenLoc, SourceLocation EndLoc,
739+
ArrayRef<OpenACCClause *> Clauses, StmtResult AssocStmt) {
740+
return ActOnEndStmtDirective(K, StartLoc, DirLoc, LParenLoc, MiscLoc, Exprs,
741+
OpenACCAtomicKind::None, RParenLoc, EndLoc,
742+
Clauses, AssocStmt);
743+
}
744+
716745
/// Called after the directive has been completely parsed, including the
717746
/// declaration group or associated statement.
718747
DeclGroupRef ActOnEndDeclDirective();

clang/include/clang/Serialization/ASTBitCodes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2045,6 +2045,7 @@ enum StmtCode {
20452045
STMT_OPENACC_SHUTDOWN_CONSTRUCT,
20462046
STMT_OPENACC_SET_CONSTRUCT,
20472047
STMT_OPENACC_UPDATE_CONSTRUCT,
2048+
STMT_OPENACC_ATOMIC_CONSTRUCT,
20482049

20492050
// HLSL Constructs
20502051
EXPR_HLSL_OUT_ARG,

clang/lib/AST/StmtOpenACC.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,3 +305,19 @@ OpenACCUpdateConstruct::Create(const ASTContext &C, SourceLocation Start,
305305
new (Mem) OpenACCUpdateConstruct(Start, DirectiveLoc, End, Clauses);
306306
return Inst;
307307
}
308+
309+
OpenACCAtomicConstruct *
310+
OpenACCAtomicConstruct::CreateEmpty(const ASTContext &C) {
311+
void *Mem = C.Allocate(sizeof(OpenACCAtomicConstruct));
312+
auto *Inst = new (Mem) OpenACCAtomicConstruct(EmptyShell{});
313+
return Inst;
314+
}
315+
316+
OpenACCAtomicConstruct *OpenACCAtomicConstruct::Create(
317+
const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
318+
OpenACCAtomicKind AtKind, SourceLocation End, Stmt *AssociatedStmt) {
319+
void *Mem = C.Allocate(sizeof(OpenACCAtomicConstruct));
320+
auto *Inst = new (Mem)
321+
OpenACCAtomicConstruct(Start, DirectiveLoc, AtKind, End, AssociatedStmt);
322+
return Inst;
323+
}

clang/lib/AST/StmtPrinter.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,6 +1242,16 @@ void StmtPrinter::VisitOpenACCWaitConstruct(OpenACCWaitConstruct *S) {
12421242
OS << '\n';
12431243
}
12441244

1245+
void StmtPrinter::VisitOpenACCAtomicConstruct(OpenACCAtomicConstruct *S) {
1246+
Indent() << "#pragma acc atomic";
1247+
1248+
if (S->getAtomicKind() != OpenACCAtomicKind::None)
1249+
OS << " " << S->getAtomicKind();
1250+
1251+
OS << '\n';
1252+
PrintStmt(S->getAssociatedStmt());
1253+
}
1254+
12451255
//===----------------------------------------------------------------------===//
12461256
// Expr printing methods.
12471257
//===----------------------------------------------------------------------===//

clang/lib/AST/StmtProfile.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2809,6 +2809,11 @@ void StmtProfiler::VisitOpenACCUpdateConstruct(
28092809
P.VisitOpenACCClauseList(S->clauses());
28102810
}
28112811

2812+
void StmtProfiler::VisitOpenACCAtomicConstruct(
2813+
const OpenACCAtomicConstruct *S) {
2814+
VisitStmt(S);
2815+
}
2816+
28122817
void StmtProfiler::VisitHLSLOutArgExpr(const HLSLOutArgExpr *S) {
28132818
VisitStmt(S);
28142819
}

clang/lib/AST/TextNodeDumper.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3041,6 +3041,12 @@ void TextNodeDumper::VisitOpenACCUpdateConstruct(
30413041
VisitOpenACCConstructStmt(S);
30423042
}
30433043

3044+
void TextNodeDumper::VisitOpenACCAtomicConstruct(
3045+
const OpenACCAtomicConstruct *S) {
3046+
VisitOpenACCConstructStmt(S);
3047+
OS << ' ' << S->getAtomicKind();
3048+
}
3049+
30443050
void TextNodeDumper::VisitEmbedExpr(const EmbedExpr *S) {
30453051
AddChild("begin", [=] { OS << S->getStartingElementPos(); });
30463052
AddChild("number of elements", [=] { OS << S->getDataElementCount(); });

clang/lib/CodeGen/CGStmt.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,8 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
489489
case Stmt::OpenACCUpdateConstructClass:
490490
EmitOpenACCUpdateConstruct(cast<OpenACCUpdateConstruct>(*S));
491491
break;
492+
case Stmt::OpenACCAtomicConstructClass:
493+
EmitOpenACCAtomicConstruct(cast<OpenACCAtomicConstruct>(*S));
492494
}
493495
}
494496

clang/lib/CodeGen/CodeGenFunction.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4167,6 +4167,13 @@ class CodeGenFunction : public CodeGenTypeCache {
41674167
// but in the future we will implement some sort of IR.
41684168
}
41694169

4170+
void EmitOpenACCAtomicConstruct(const OpenACCAtomicConstruct &S) {
4171+
// TODO OpenACC: Implement this. It is currently implemented as a 'no-op',
4172+
// simply emitting its associated stmt, but in the future we will implement
4173+
// some sort of IR.
4174+
EmitStmt(S.getAssociatedStmt());
4175+
}
4176+
41704177
//===--------------------------------------------------------------------===//
41714178
// LValue Expression Emission
41724179
//===--------------------------------------------------------------------===//

0 commit comments

Comments
 (0)