[OPENMP] 'proc_bind' clause support - Parsing and sema analysis for OpenMP clause 'proc_bind'

llvm-svn: 208060
This commit is contained in:
Alexey Bataev 2014-05-06 06:04:14 +00:00
parent 4cf4e664c2
commit bcbadb65ab
17 changed files with 249 additions and 14 deletions

View File

@ -2379,6 +2379,12 @@ bool DataRecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *C
return true;
}
template<typename Derived>
bool
DataRecursiveASTVisitor<Derived>::VisitOMPProcBindClause(OMPProcBindClause *C) {
return true;
}
template<typename Derived>
template<typename T>
void DataRecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {

View File

@ -375,6 +375,76 @@ public:
StmtRange children() { return StmtRange(); }
};
/// \brief This represents 'proc_bind' clause in the '#pragma omp ...' directive.
///
/// \code
/// #pragma omp parallel proc_bind(master)
/// \endcode
/// In this example directive '#pragma omp parallel' has simple 'proc_bind'
/// clause with kind 'master'.
///
class OMPProcBindClause : public OMPClause {
friend class OMPClauseReader;
/// \brief Location of '('.
SourceLocation LParenLoc;
/// \brief A kind of the 'proc_bind' clause.
OpenMPProcBindClauseKind Kind;
/// \brief Start location of the kind in source code.
SourceLocation KindKwLoc;
/// \brief Set kind of the clause.
///
/// \param K Kind of clause.
///
void setProcBindKind(OpenMPProcBindClauseKind K) { Kind = K; }
/// \brief Set clause kind location.
///
/// \param KLoc Kind location.
///
void setProcBindKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; }
public:
/// \brief Build 'proc_bind' clause with argument \a A ('master', 'close' or
/// 'spread').
///
/// \param A Argument of the clause ('master', 'close' or 'spread').
/// \param ALoc Starting location of the argument.
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
///
OMPProcBindClause(OpenMPProcBindClauseKind A, SourceLocation ALoc,
SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc)
: OMPClause(OMPC_proc_bind, StartLoc, EndLoc), LParenLoc(LParenLoc),
Kind(A), KindKwLoc(ALoc) {}
/// \brief Build an empty clause.
///
OMPProcBindClause()
: OMPClause(OMPC_proc_bind, SourceLocation(), SourceLocation()),
LParenLoc(SourceLocation()), Kind(OMPC_PROC_BIND_unknown),
KindKwLoc(SourceLocation()) {}
/// \brief Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
/// \brief Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
/// \brief Returns kind of the clause.
OpenMPProcBindClauseKind getProcBindKind() const { return Kind; }
/// \brief Returns location of clause kind.
SourceLocation getProcBindKindKwLoc() const { return KindKwLoc; }
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_proc_bind;
}
StmtRange children() { return StmtRange(); }
};
/// \brief This represents clause 'private' in the '#pragma omp ...' directives.
///
/// \code

View File

@ -2416,6 +2416,11 @@ bool RecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *C) {
return true;
}
template<typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPProcBindClause(OMPProcBindClause *C) {
return true;
}
template<typename Derived>
template<typename T>
void RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {

View File

@ -27,6 +27,9 @@
#ifndef OPENMP_DEFAULT_KIND
# define OPENMP_DEFAULT_KIND(Name)
#endif
#ifndef OPENMP_PROC_BIND_KIND
# define OPENMP_PROC_BIND_KIND(Name)
#endif
// OpenMP directives.
OPENMP_DIRECTIVE(threadprivate)
@ -44,11 +47,13 @@ OPENMP_CLAUSE(firstprivate, OMPFirstprivateClause)
OPENMP_CLAUSE(shared, OMPSharedClause)
OPENMP_CLAUSE(linear, OMPLinearClause)
OPENMP_CLAUSE(copyin, OMPCopyinClause)
OPENMP_CLAUSE(proc_bind, OMPProcBindClause)
// Clauses allowed for OpenMP directive 'parallel'.
OPENMP_PARALLEL_CLAUSE(if)
OPENMP_PARALLEL_CLAUSE(num_threads)
OPENMP_PARALLEL_CLAUSE(default)
OPENMP_PARALLEL_CLAUSE(proc_bind)
OPENMP_PARALLEL_CLAUSE(private)
OPENMP_PARALLEL_CLAUSE(firstprivate)
OPENMP_PARALLEL_CLAUSE(shared)
@ -63,6 +68,12 @@ OPENMP_SIMD_CLAUSE(safelen)
OPENMP_DEFAULT_KIND(none)
OPENMP_DEFAULT_KIND(shared)
// Static attributes for 'proc_bind' clause.
OPENMP_PROC_BIND_KIND(master)
OPENMP_PROC_BIND_KIND(close)
OPENMP_PROC_BIND_KIND(spread)
#undef OPENMP_PROC_BIND_KIND
#undef OPENMP_DEFAULT_KIND
#undef OPENMP_DIRECTIVE
#undef OPENMP_CLAUSE

View File

@ -47,6 +47,14 @@ enum OpenMPDefaultClauseKind {
NUM_OPENMP_DEFAULT_KINDS
};
/// \brief OpenMP attributes for 'proc_bind' clause.
enum OpenMPProcBindClauseKind {
#define OPENMP_PROC_BIND_KIND(Name) \
OMPC_PROC_BIND_##Name,
#include "clang/Basic/OpenMPKinds.def"
OMPC_PROC_BIND_unknown
};
OpenMPDirectiveKind getOpenMPDirectiveKind(llvm::StringRef Str);
const char *getOpenMPDirectiveName(OpenMPDirectiveKind Kind);

View File

@ -7301,6 +7301,12 @@ public:
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
/// \brief Called on well-formed 'proc_bind' clause.
OMPClause *ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind Kind,
SourceLocation KindLoc,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
OMPClause *ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
ArrayRef<Expr *> Vars,

View File

@ -625,6 +625,12 @@ void OMPClausePrinter::VisitOMPDefaultClause(OMPDefaultClause *Node) {
<< ")";
}
void OMPClausePrinter::VisitOMPProcBindClause(OMPProcBindClause *Node) {
OS << "proc_bind("
<< getOpenMPSimpleClauseTypeName(OMPC_proc_bind, Node->getProcBindKind())
<< ")";
}
template<typename T>
void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) {
for (typename T::varlist_iterator I = Node->varlist_begin(),

View File

@ -281,6 +281,8 @@ void OMPClauseProfiler::VisitOMPSafelenClause(const OMPSafelenClause *C) {
void OMPClauseProfiler::VisitOMPDefaultClause(const OMPDefaultClause *C) { }
void OMPClauseProfiler::VisitOMPProcBindClause(const OMPProcBindClause *C) { }
template<typename T>
void OMPClauseProfiler::VisitOMPClauseList(T *Node) {
for (auto *I : Node->varlists())

View File

@ -75,6 +75,12 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
.Case(#Name, OMPC_DEFAULT_##Name)
#include "clang/Basic/OpenMPKinds.def"
.Default(OMPC_DEFAULT_unknown);
case OMPC_proc_bind:
return llvm::StringSwitch<OpenMPProcBindClauseKind>(Str)
#define OPENMP_PROC_BIND_KIND(Name) \
.Case(#Name, OMPC_PROC_BIND_##Name)
#include "clang/Basic/OpenMPKinds.def"
.Default(OMPC_PROC_BIND_unknown);
case OMPC_unknown:
case OMPC_threadprivate:
case OMPC_if:
@ -103,6 +109,15 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
#include "clang/Basic/OpenMPKinds.def"
}
llvm_unreachable("Invalid OpenMP 'default' clause type");
case OMPC_proc_bind:
switch (Type) {
case OMPC_PROC_BIND_unknown:
return "unknown";
#define OPENMP_PROC_BIND_KIND(Name) \
case OMPC_PROC_BIND_##Name : return #Name;
#include "clang/Basic/OpenMPKinds.def"
}
llvm_unreachable("Invalid OpenMP 'proc_bind' clause type");
case OMPC_unknown:
case OMPC_threadprivate:
case OMPC_if:

View File

@ -288,9 +288,12 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
Clause = ParseOpenMPSingleExprClause(CKind);
break;
case OMPC_default:
case OMPC_proc_bind:
// OpenMP [2.14.3.1, Restrictions]
// Only a single default clause may be specified on a parallel, task or
// teams directive.
// OpenMP [2.5, parallel Construct, Restrictions]
// At most one proc_bind clause can appear on the directive.
if (!FirstClause) {
Diag(Tok, diag::err_omp_more_one_clause)
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind);
@ -355,11 +358,14 @@ OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
T.getCloseLocation());
}
/// \brief Parsing of simple OpenMP clauses like 'default'.
/// \brief Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
///
/// default-clause:
/// 'default' '(' 'none' | 'shared' ')
///
/// proc_bind-clause:
/// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
///
OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
SourceLocation Loc = Tok.getLocation();
SourceLocation LOpen = ConsumeToken();
@ -369,9 +375,9 @@ OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
getOpenMPClauseName(Kind)))
return 0;
unsigned Type = Tok.isAnnotation() ?
unsigned(OMPC_DEFAULT_unknown) :
getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok));
unsigned Type =
getOpenMPSimpleClauseType(Kind,
Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
SourceLocation TypeLoc = Tok.getLocation();
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
Tok.isNot(tok::annot_pragma_openmp_end))

View File

@ -771,6 +771,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_default:
case OMPC_proc_bind:
case OMPC_private:
case OMPC_firstprivate:
case OMPC_shared:
@ -924,6 +925,11 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
ActOnOpenMPDefaultClause(static_cast<OpenMPDefaultClauseKind>(Argument),
ArgumentLoc, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_proc_bind:
Res =
ActOnOpenMPProcBindClause(static_cast<OpenMPProcBindClauseKind>(Argument),
ArgumentLoc, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_if:
case OMPC_num_threads:
case OMPC_safelen:
@ -986,6 +992,37 @@ OMPClause *Sema::ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind,
EndLoc);
}
OMPClause *Sema::ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind Kind,
SourceLocation KindKwLoc,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
if (Kind == OMPC_PROC_BIND_unknown) {
std::string Values;
std::string Sep(", ");
for (unsigned i = 0; i < OMPC_PROC_BIND_unknown; ++i) {
Values += "'";
Values += getOpenMPSimpleClauseTypeName(OMPC_proc_bind, i);
Values += "'";
switch (i) {
case OMPC_PROC_BIND_unknown - 2:
Values += " or ";
break;
case OMPC_PROC_BIND_unknown - 1:
break;
default:
Values += Sep;
break;
}
}
Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
<< Values << getOpenMPClauseName(OMPC_proc_bind);
return 0;
}
return new (Context) OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc,
EndLoc);
}
OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
ArrayRef<Expr *> VarList,
Expr *TailExpr,
@ -1015,6 +1052,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_default:
case OMPC_proc_bind:
case OMPC_threadprivate:
case OMPC_unknown:
case NUM_OPENMP_CLAUSES:

View File

@ -1345,6 +1345,19 @@ public:
StartLoc, LParenLoc, EndLoc);
}
/// \brief Build a new OpenMP 'proc_bind' clause.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
OMPClause *RebuildOMPProcBindClause(OpenMPProcBindClauseKind Kind,
SourceLocation KindKwLoc,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
return getSema().ActOnOpenMPProcBindClause(Kind, KindKwLoc,
StartLoc, LParenLoc, EndLoc);
}
/// \brief Build a new OpenMP 'private' clause.
///
/// By default, performs semantic analysis to build the new statement.
@ -6394,6 +6407,16 @@ TreeTransform<Derived>::TransformOMPDefaultClause(OMPDefaultClause *C) {
C->getLocEnd());
}
template<typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPProcBindClause(OMPProcBindClause *C) {
return getDerived().RebuildOMPProcBindClause(C->getProcBindKind(),
C->getProcBindKindKwLoc(),
C->getLocStart(),
C->getLParenLoc(),
C->getLocEnd());
}
template<typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPPrivateClause(OMPPrivateClause *C) {

View File

@ -1685,6 +1685,9 @@ OMPClause *OMPClauseReader::readClause() {
case OMPC_default:
C = new (Context) OMPDefaultClause();
break;
case OMPC_proc_bind:
C = new (Context) OMPProcBindClause();
break;
case OMPC_private:
C = OMPPrivateClause::CreateEmpty(Context, Record[Idx++]);
break;
@ -1730,6 +1733,13 @@ void OMPClauseReader::VisitOMPDefaultClause(OMPDefaultClause *C) {
C->setDefaultKindKwLoc(Reader->ReadSourceLocation(Record, Idx));
}
void OMPClauseReader::VisitOMPProcBindClause(OMPProcBindClause *C) {
C->setProcBindKind(
static_cast<OpenMPProcBindClauseKind>(Record[Idx++]));
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
C->setProcBindKindKwLoc(Reader->ReadSourceLocation(Record, Idx));
}
void OMPClauseReader::VisitOMPPrivateClause(OMPPrivateClause *C) {
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
unsigned NumVars = C->varlist_size();

View File

@ -1696,6 +1696,12 @@ void OMPClauseWriter::VisitOMPDefaultClause(OMPDefaultClause *C) {
Writer->Writer.AddSourceLocation(C->getDefaultKindKwLoc(), Record);
}
void OMPClauseWriter::VisitOMPProcBindClause(OMPProcBindClause *C) {
Record.push_back(C->getProcBindKind());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
Writer->Writer.AddSourceLocation(C->getProcBindKindKwLoc(), Record);
}
void OMPClauseWriter::VisitOMPPrivateClause(OMPPrivateClause *C) {
Record.push_back(C->varlist_size());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);

View File

@ -35,9 +35,9 @@ T tmain(T argc, T *argv) {
S<T> s;
#pragma omp parallel
a=2;
#pragma omp parallel default(none), private(argc,b) firstprivate(argv) shared (d) if (argc > 0) num_threads(C) copyin(S<T>::TS)
#pragma omp parallel default(none), private(argc,b) firstprivate(argv) shared (d) if (argc > 0) num_threads(C) copyin(S<T>::TS) proc_bind(master)
foo();
#pragma omp parallel if (C) num_threads(s)
#pragma omp parallel if (C) num_threads(s) proc_bind(close)
foo();
return 0;
}
@ -48,9 +48,9 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: S<int> s;
// CHECK-NEXT: #pragma omp parallel
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(5) copyin(S<int>::TS)
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(5) copyin(S<int>::TS) proc_bind(master)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp parallel if(5) num_threads(s)
// CHECK-NEXT: #pragma omp parallel if(5) num_threads(s) proc_bind(close)
// CHECK-NEXT: foo()
// CHECK: template <typename T = long, int C = 1> long tmain(long argc, long *argv) {
// CHECK-NEXT: long b = argc, c, d, e, f, g;
@ -58,9 +58,9 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: S<long> s;
// CHECK-NEXT: #pragma omp parallel
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(1) copyin(S<long>::TS)
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(1) copyin(S<long>::TS) proc_bind(master)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp parallel if(1) num_threads(s)
// CHECK-NEXT: #pragma omp parallel if(1) num_threads(s) proc_bind(close)
// CHECK-NEXT: foo()
// CHECK: template <typename T, int C> T tmain(T argc, T *argv) {
// CHECK-NEXT: T b = argc, c, d, e, f, g;
@ -68,9 +68,9 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: S<T> s;
// CHECK-NEXT: #pragma omp parallel
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(C) copyin(S<T>::TS)
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(C) copyin(S<T>::TS) proc_bind(master)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp parallel if(C) num_threads(s)
// CHECK-NEXT: #pragma omp parallel if(C) num_threads(s) proc_bind(close)
// CHECK-NEXT: foo()
enum Enum { };
@ -86,8 +86,8 @@ int main (int argc, char **argv) {
// CHECK-NEXT: #pragma omp parallel
a=2;
// CHECK-NEXT: a = 2;
#pragma omp parallel default(none), private(argc,b) firstprivate(argv) if (argc > 0) num_threads(ee) copyin(a)
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) if(argc > 0) num_threads(ee) copyin(a)
#pragma omp parallel default(none), private(argc,b) firstprivate(argv) if (argc > 0) num_threads(ee) copyin(a) proc_bind(spread)
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) if(argc > 0) num_threads(ee) copyin(a) proc_bind(spread)
foo();
// CHECK-NEXT: foo();
return tmain<int, 5>(b, &b) + tmain<long, 1>(x, &x);

View File

@ -0,0 +1,21 @@
// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ferror-limit 100 -o - %s
void foo();
int main(int argc, char **argv) {
#pragma omp parallel proc_bind // expected-error {{expected '(' after 'proc_bind'}}
#pragma omp parallel proc_bind ( // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel proc_bind () // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}}
#pragma omp parallel proc_bind (master // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel proc_bind (close), proc_bind(spread) // expected-error {{directive '#pragma omp parallel' cannot contain more than one 'proc_bind' clause}}
#pragma omp parallel proc_bind (x) // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}}
foo();
#pragma omp parallel proc_bind(master)
++argc;
#pragma omp parallel proc_bind(close)
#pragma omp parallel proc_bind(spread)
++argc;
return 0;
}

View File

@ -1937,6 +1937,8 @@ void OMPClauseEnqueue::VisitOMPSafelenClause(const OMPSafelenClause *C) {
void OMPClauseEnqueue::VisitOMPDefaultClause(const OMPDefaultClause *C) { }
void OMPClauseEnqueue::VisitOMPProcBindClause(const OMPProcBindClause *C) { }
template<typename T>
void OMPClauseEnqueue::VisitOMPClauseList(T *Node) {
for (const auto *I : Node->varlists())