-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[clang] Factor out OpenACC part of Sema
#84184
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
23f4208
e5bdaf1
eab3895
aad4515
4910ff2
b239e9e
7ac2230
b3e2cc2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -183,6 +183,7 @@ class Preprocessor; | |
class PseudoDestructorTypeStorage; | ||
class PseudoObjectExpr; | ||
class QualType; | ||
class SemaOpenACC; | ||
class StandardConversionSequence; | ||
class Stmt; | ||
class StringLiteral; | ||
|
@@ -466,9 +467,8 @@ class Sema final { | |
// 37. Name Lookup for RISC-V Vector Intrinsic (SemaRISCVVectorLookup.cpp) | ||
// 38. CUDA (SemaCUDA.cpp) | ||
// 39. HLSL Constructs (SemaHLSL.cpp) | ||
// 40. OpenACC Constructs (SemaOpenACC.cpp) | ||
// 41. OpenMP Directives and Clauses (SemaOpenMP.cpp) | ||
// 42. SYCL Constructs (SemaSYCL.cpp) | ||
// 40. OpenMP Directives and Clauses (SemaOpenMP.cpp) | ||
// 41. SYCL Constructs (SemaSYCL.cpp) | ||
|
||
/// \name Semantic Analysis | ||
/// Implementations are in Sema.cpp | ||
|
@@ -1162,6 +1162,11 @@ class Sema final { | |
/// CurContext - This is the current declaration context of parsing. | ||
DeclContext *CurContext; | ||
|
||
SemaOpenACC &OpenACC() { | ||
assert(OpenACCPtr); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the current design, the assert does nothing useful. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO, there is value to having the assert. I can definitely see a world where the sub-types are allowed to get 'big enough' that restricting them to only be created 'sometimes' has value. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure. But that's not yet the case. I think we should add the asserts if and then, not everywhere. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't buy the 'noticeable impact on assertion build' here. The very next line is loading the same variable, so even the smallest amount of inliner action makes this at best a non-taken 'jne' type instruction. While this MIGHT have a slight impact, it is near-zero, and of the order of 'i used a pair of if/else instead of a switch'. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Given that moving a hot path getter to out-of-line definition doesn't regress compile-time performance even with LTO disabled, I'm skeptical additional assert on an effectively constant pointer would make a difference. I expect branch target predictors in CPUs to beat this easily. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the assert is reasonable for now; someday we may want to investigate adding nullability attributes in appropriate places and removing some asserts like these where sensible. |
||
return *OpenACCPtr; | ||
} | ||
|
||
protected: | ||
friend class Parser; | ||
friend class InitializationSequence; | ||
|
@@ -1192,6 +1197,8 @@ class Sema final { | |
|
||
mutable IdentifierInfo *Ident_super; | ||
|
||
std::unique_ptr<SemaOpenACC> OpenACCPtr; | ||
erichkeane marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
///@} | ||
|
||
// | ||
|
@@ -13309,56 +13316,6 @@ class Sema final { | |
// | ||
// | ||
|
||
/// \name OpenACC Constructs | ||
/// Implementations are in SemaOpenACC.cpp | ||
///@{ | ||
|
||
public: | ||
/// Called after parsing an OpenACC Clause so that it can be checked. | ||
bool ActOnOpenACCClause(OpenACCClauseKind ClauseKind, | ||
SourceLocation StartLoc); | ||
|
||
/// Called after the construct has been parsed, but clauses haven't been | ||
/// parsed. This allows us to diagnose not-implemented, as well as set up any | ||
/// state required for parsing the clauses. | ||
void ActOnOpenACCConstruct(OpenACCDirectiveKind K, SourceLocation StartLoc); | ||
|
||
/// Called after the directive, including its clauses, have been parsed and | ||
/// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES | ||
/// happen before any associated declarations or statements have been parsed. | ||
/// This function is only called when we are parsing a 'statement' context. | ||
bool ActOnStartOpenACCStmtDirective(OpenACCDirectiveKind K, | ||
SourceLocation StartLoc); | ||
|
||
/// Called after the directive, including its clauses, have been parsed and | ||
/// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES | ||
/// happen before any associated declarations or statements have been parsed. | ||
/// This function is only called when we are parsing a 'Decl' context. | ||
bool ActOnStartOpenACCDeclDirective(OpenACCDirectiveKind K, | ||
SourceLocation StartLoc); | ||
/// Called when we encounter an associated statement for our construct, this | ||
/// should check legality of the statement as it appertains to this Construct. | ||
StmtResult ActOnOpenACCAssociatedStmt(OpenACCDirectiveKind K, | ||
StmtResult AssocStmt); | ||
|
||
/// Called after the directive has been completely parsed, including the | ||
/// declaration group or associated statement. | ||
StmtResult ActOnEndOpenACCStmtDirective(OpenACCDirectiveKind K, | ||
SourceLocation StartLoc, | ||
SourceLocation EndLoc, | ||
StmtResult AssocStmt); | ||
/// Called after the directive has been completely parsed, including the | ||
/// declaration group or associated statement. | ||
DeclGroupRef ActOnEndOpenACCDeclDirective(); | ||
|
||
///@} | ||
|
||
// | ||
// | ||
// ------------------------------------------------------------------------- | ||
// | ||
// | ||
|
||
/// \name OpenMP Directives and Clauses | ||
/// Implementations are in SemaOpenMP.cpp | ||
///@{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
//===----- SemaOpenACC.h - Semantic Analysis for OpenACC constructs -------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
/// \file | ||
/// This file declares semantic analysis for OpenACC constructs and | ||
/// clauses. | ||
/// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_CLANG_SEMA_SEMAOPENACC_H | ||
#define LLVM_CLANG_SEMA_SEMAOPENACC_H | ||
|
||
#include "clang/AST/DeclGroup.h" | ||
#include "clang/Basic/OpenACCKinds.h" | ||
Endilll marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#include "clang/Basic/SourceLocation.h" | ||
#include "clang/Sema/Ownership.h" | ||
|
||
namespace clang { | ||
|
||
class Sema; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we expect that clients realistically use SemaOpenACC but not Sema::OpenACC()? Do we want to encourage clients to accept/store I think we should accept that at least for now, clients will and should still use In which case, I think we should Also, (Again, nitpicking because this is a precedent) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Your feedback is much appreciated! No worries about nitpicking, as we indeed establish a precedent here.
While it would be nice to have layering in Sema, and inline functions in
I wonder if @erichkeane can give us his insight here, as he has more code dealing with OpenACC down the line. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it is less of an OpenACC discussion and more of a general use case discussion FWIW. BUT I think we DO expect a lot of the 'child' Very much of the OpenMP implementation (and soon to be OpenACC implementation) calls into Constant evaluation functions, etc. BUT I think the hope here is that the calls will be '1 way', in that Sema won't call into the OpenACC implementation ever, but the OpenACC will call into Sema reasonably often (as it does for OMP). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I envision the eventual goal of layering to be similar to that of layering elsewhere in the compiler, where it's fine for things at a higher level (SemaOpenACC, SemaOpenMP, etc) to call into things in a lower level (Sema) but not vice versa. |
||
|
||
class SemaOpenACC { | ||
public: | ||
SemaOpenACC(Sema &S); | ||
|
||
Sema &SemaRef; | ||
|
||
/// Called after parsing an OpenACC Clause so that it can be checked. | ||
bool ActOnClause(OpenACCClauseKind ClauseKind, SourceLocation StartLoc); | ||
|
||
/// Called after the construct has been parsed, but clauses haven't been | ||
/// parsed. This allows us to diagnose not-implemented, as well as set up any | ||
/// state required for parsing the clauses. | ||
void ActOnConstruct(OpenACCDirectiveKind K, SourceLocation StartLoc); | ||
|
||
/// Called after the directive, including its clauses, have been parsed and | ||
/// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES | ||
/// happen before any associated declarations or statements have been parsed. | ||
/// This function is only called when we are parsing a 'statement' context. | ||
bool ActOnStartStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc); | ||
|
||
/// Called after the directive, including its clauses, have been parsed and | ||
/// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES | ||
/// happen before any associated declarations or statements have been parsed. | ||
/// This function is only called when we are parsing a 'Decl' context. | ||
bool ActOnStartDeclDirective(OpenACCDirectiveKind K, SourceLocation StartLoc); | ||
/// Called when we encounter an associated statement for our construct, this | ||
/// should check legality of the statement as it appertains to this Construct. | ||
StmtResult ActOnAssociatedStmt(OpenACCDirectiveKind K, StmtResult AssocStmt); | ||
|
||
/// Called after the directive has been completely parsed, including the | ||
/// declaration group or associated statement. | ||
StmtResult ActOnEndStmtDirective(OpenACCDirectiveKind K, | ||
SourceLocation StartLoc, | ||
SourceLocation EndLoc, StmtResult AssocStmt); | ||
/// Called after the directive has been completely parsed, including the | ||
/// declaration group or associated statement. | ||
DeclGroupRef ActOnEndDeclDirective(); | ||
}; | ||
|
||
} // namespace clang | ||
|
||
#endif // LLVM_CLANG_SEMA_SEMAOPENACC_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,14 +11,14 @@ | |
/// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "clang/Sema/SemaOpenACC.h" | ||
#include "clang/Basic/DiagnosticSema.h" | ||
#include "clang/Basic/OpenACCKinds.h" | ||
#include "clang/Sema/Sema.h" | ||
|
||
using namespace clang; | ||
|
||
namespace { | ||
bool diagnoseConstructAppertainment(Sema &S, OpenACCDirectiveKind K, | ||
bool diagnoseConstructAppertainment(SemaOpenACC &S, OpenACCDirectiveKind K, | ||
SourceLocation StartLoc, bool IsStmt) { | ||
switch (K) { | ||
default: | ||
|
@@ -30,24 +30,28 @@ bool diagnoseConstructAppertainment(Sema &S, OpenACCDirectiveKind K, | |
case OpenACCDirectiveKind::Serial: | ||
case OpenACCDirectiveKind::Kernels: | ||
if (!IsStmt) | ||
return S.Diag(StartLoc, diag::err_acc_construct_appertainment) << K; | ||
return S.SemaRef.Diag(StartLoc, diag::err_acc_construct_appertainment) | ||
<< K; | ||
break; | ||
} | ||
return false; | ||
} | ||
} // namespace | ||
|
||
bool Sema::ActOnOpenACCClause(OpenACCClauseKind ClauseKind, | ||
SemaOpenACC::SemaOpenACC(Sema &S) : SemaRef(S) {} | ||
|
||
bool SemaOpenACC::ActOnClause(OpenACCClauseKind ClauseKind, | ||
SourceLocation StartLoc) { | ||
if (ClauseKind == OpenACCClauseKind::Invalid) | ||
return false; | ||
// For now just diagnose that it is unsupported and leave the parsing to do | ||
// whatever it can do. This function will eventually need to start returning | ||
// some sort of Clause AST type, but for now just return true/false based on | ||
// success. | ||
return Diag(StartLoc, diag::warn_acc_clause_unimplemented) << ClauseKind; | ||
return SemaRef.Diag(StartLoc, diag::warn_acc_clause_unimplemented) | ||
<< ClauseKind; | ||
} | ||
void Sema::ActOnOpenACCConstruct(OpenACCDirectiveKind K, | ||
void SemaOpenACC::ActOnConstruct(OpenACCDirectiveKind K, | ||
SourceLocation StartLoc) { | ||
switch (K) { | ||
case OpenACCDirectiveKind::Invalid: | ||
|
@@ -63,17 +67,17 @@ void Sema::ActOnOpenACCConstruct(OpenACCDirectiveKind K, | |
// here as these constructs do not take any arguments. | ||
break; | ||
default: | ||
Diag(StartLoc, diag::warn_acc_construct_unimplemented) << K; | ||
SemaRef.Diag(StartLoc, diag::warn_acc_construct_unimplemented) << K; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think Diag and getASTContext should be accessible directly. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed. Is there a better way than this?
Accessing This requires some agreement on what common functionality is. On the other hand it forces some discussion/review of this definition which seems useful. It requires SemaOpenACC.h to depend on Sema.h (which personally I think is reasonable, based on what clients will do). It also requires a bunch of boilerplate, which is sad. |
||
break; | ||
} | ||
} | ||
|
||
bool Sema::ActOnStartOpenACCStmtDirective(OpenACCDirectiveKind K, | ||
bool SemaOpenACC::ActOnStartStmtDirective(OpenACCDirectiveKind K, | ||
SourceLocation StartLoc) { | ||
return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/true); | ||
} | ||
|
||
StmtResult Sema::ActOnEndOpenACCStmtDirective(OpenACCDirectiveKind K, | ||
StmtResult SemaOpenACC::ActOnEndStmtDirective(OpenACCDirectiveKind K, | ||
SourceLocation StartLoc, | ||
SourceLocation EndLoc, | ||
StmtResult AssocStmt) { | ||
|
@@ -86,13 +90,13 @@ StmtResult Sema::ActOnEndOpenACCStmtDirective(OpenACCDirectiveKind K, | |
case OpenACCDirectiveKind::Serial: | ||
case OpenACCDirectiveKind::Kernels: | ||
return OpenACCComputeConstruct::Create( | ||
getASTContext(), K, StartLoc, EndLoc, | ||
SemaRef.getASTContext(), K, StartLoc, EndLoc, | ||
AssocStmt.isUsable() ? AssocStmt.get() : nullptr); | ||
} | ||
llvm_unreachable("Unhandled case in directive handling?"); | ||
} | ||
|
||
StmtResult Sema::ActOnOpenACCAssociatedStmt(OpenACCDirectiveKind K, | ||
StmtResult SemaOpenACC::ActOnAssociatedStmt(OpenACCDirectiveKind K, | ||
StmtResult AssocStmt) { | ||
switch (K) { | ||
default: | ||
|
@@ -114,9 +118,9 @@ StmtResult Sema::ActOnOpenACCAssociatedStmt(OpenACCDirectiveKind K, | |
llvm_unreachable("Invalid associated statement application"); | ||
} | ||
|
||
bool Sema::ActOnStartOpenACCDeclDirective(OpenACCDirectiveKind K, | ||
bool SemaOpenACC::ActOnStartDeclDirective(OpenACCDirectiveKind K, | ||
SourceLocation StartLoc) { | ||
return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/false); | ||
} | ||
|
||
DeclGroupRef Sema::ActOnEndOpenACCDeclDirective() { return DeclGroupRef{}; } | ||
DeclGroupRef SemaOpenACC::ActOnEndDeclDirective() { return DeclGroupRef{}; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: per style guide, this should be
openACC()
(lowercase O), and it should begetOpenAcc()
(verb phrase).Personally, I think the verb-phrase rule when applied to getters is harmful enough to be worth ignoring (preferring name according to side-effects). So I'd be happiest with
openACC()
, but also fine withgetOpenACC()
.(Picking this nit because I suspect we're going to have a bunch of these, and they should be consistent.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not too keen to adhere to our style guide here, as this adds noise for users on top of already more lengthy notation: this PR made the following usage
getActions().ActOnOpenACCClause(Kind, ClauseLoc);
to look like this:getActions().OpenACC().ActOnClause(Kind, ClauseLoc);
. If we adhere to style guide, it's going to becomegetActions().getOpenACC().ActOnClause(Kind, ClauseLoc);
without any benefit for readers and writers of the code.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think @sam-mccall is reading the coding guidelines the same way I read them, and I agree with his conclusion that I also prefer
openACC()
overgetOpenACC()
. I don't findget
to add much value to readability in this case and I think deviating from the style guideline is appropriate.