Skip to content
This repository has been archived by the owner on Apr 23, 2020. It is now read-only.

Commit

Permalink
[OPENMP] Implemented 'copyin' clause
Browse files Browse the repository at this point in the history
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@205164 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
alexey-bataev committed Mar 31, 2014
1 parent 78afefd commit a100391
Show file tree
Hide file tree
Showing 18 changed files with 367 additions and 13 deletions.
6 changes: 6 additions & 0 deletions include/clang/AST/DataRecursiveASTVisitor.h
Expand Up @@ -2405,6 +2405,12 @@ bool DataRecursiveASTVisitor<Derived>::VisitOMPSharedClause(OMPSharedClause *C)
return true;
}

template<typename Derived>
bool DataRecursiveASTVisitor<Derived>::VisitOMPCopyinClause(OMPCopyinClause *C) {
VisitOMPClauseList(C);
return true;
}

// FIXME: look at the following tricky-seeming exprs to see if we
// need to recurse on anything. These are ones that have methods
// returning decls or qualtypes or nestednamespecifier -- though I'm
Expand Down
61 changes: 60 additions & 1 deletion include/clang/AST/OpenMPClause.h
Expand Up @@ -95,7 +95,7 @@ template <class T> class OMPVarListClause : public OMPClause {
llvm::RoundUpToAlignment(sizeof(T), llvm::alignOf<Expr *>())));
}

/// \brief Build clause with number of variables \a N.
/// \brief Build a clause with \a N variables
///
/// \param K Kind of the clause.
/// \param StartLoc Starting location of the clause (the clause keyword).
Expand Down Expand Up @@ -553,6 +553,65 @@ class OMPSharedClause : public OMPVarListClause<OMPSharedClause> {
}
};

/// \brief This represents clause 'copyin' in the '#pragma omp ...' directives.
///
/// \code
/// #pragma omp parallel copyin(a,b)
/// \endcode
/// In this example directive '#pragma omp parallel' has clause 'copyin'
/// with the variables 'a' and 'b'.
///
class OMPCopyinClause : public OMPVarListClause<OMPCopyinClause> {
/// \brief Build clause with number of variables \a N.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
/// \param N Number of the variables in the clause.
///
OMPCopyinClause(SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, unsigned N)
: OMPVarListClause<OMPCopyinClause>(OMPC_copyin, StartLoc, LParenLoc,
EndLoc, N) {}

/// \brief Build an empty clause.
///
/// \param N Number of variables.
///
explicit OMPCopyinClause(unsigned N)
: OMPVarListClause<OMPCopyinClause>(OMPC_copyin, SourceLocation(),
SourceLocation(), SourceLocation(),
N) {}

public:
/// \brief Creates clause with a list of variables \a VL.
///
/// \param C AST context.
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
/// \param VL List of references to the variables.
///
static OMPCopyinClause *Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc, ArrayRef<Expr *> VL);
/// \brief Creates an empty clause with \a N variables.
///
/// \param C AST context.
/// \param N The number of variables.
///
static OMPCopyinClause *CreateEmpty(const ASTContext &C, unsigned N);

StmtRange children() {
return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
reinterpret_cast<Stmt **>(varlist_end()));
}

static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_copyin;
}
};

} // end namespace clang

#endif
6 changes: 6 additions & 0 deletions include/clang/AST/RecursiveASTVisitor.h
Expand Up @@ -2442,6 +2442,12 @@ bool RecursiveASTVisitor<Derived>::VisitOMPSharedClause(OMPSharedClause *C) {
return true;
}

template<typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPCopyinClause(OMPCopyinClause *C) {
VisitOMPClauseList(C);
return true;
}

// FIXME: look at the following tricky-seeming exprs to see if we
// need to recurse on anything. These are ones that have methods
// returning decls or qualtypes or nestednamespecifier -- though I'm
Expand Down
2 changes: 2 additions & 0 deletions include/clang/Basic/DiagnosticSemaKinds.td
Expand Up @@ -6915,6 +6915,8 @@ def note_omp_conversion_here : Note<
def err_omp_ambiguous_conversion : Error<
"ambiguous conversion from type %0 to an integral or unscoped "
"enumeration type">;
def err_omp_required_access : Error<
"%0 variable must be %1">;
} // end of OpenMP category

let CategoryName = "Related Result Type Issue" in {
Expand Down
2 changes: 2 additions & 0 deletions include/clang/Basic/OpenMPKinds.def
Expand Up @@ -42,6 +42,7 @@ OPENMP_CLAUSE(default, OMPDefaultClause)
OPENMP_CLAUSE(private, OMPPrivateClause)
OPENMP_CLAUSE(firstprivate, OMPFirstprivateClause)
OPENMP_CLAUSE(shared, OMPSharedClause)
OPENMP_CLAUSE(copyin, OMPCopyinClause)

// Clauses allowed for OpenMP directive 'parallel'.
OPENMP_PARALLEL_CLAUSE(if)
Expand All @@ -50,6 +51,7 @@ OPENMP_PARALLEL_CLAUSE(default)
OPENMP_PARALLEL_CLAUSE(private)
OPENMP_PARALLEL_CLAUSE(firstprivate)
OPENMP_PARALLEL_CLAUSE(shared)
OPENMP_PARALLEL_CLAUSE(copyin)

// FIXME: more clauses allowed for directive 'omp simd'.
OPENMP_SIMD_CLAUSE(private)
Expand Down
5 changes: 5 additions & 0 deletions include/clang/Sema/Sema.h
Expand Up @@ -7210,6 +7210,11 @@ class Sema {
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
/// \brief Called on well-formed 'copyin' clause.
OMPClause *ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);

/// \brief The kind of conversion being performed.
enum CheckedConversionKind {
Expand Down
22 changes: 22 additions & 0 deletions lib/AST/Stmt.cpp
Expand Up @@ -1192,6 +1192,28 @@ OMPSharedClause *OMPSharedClause::CreateEmpty(const ASTContext &C,
return new (Mem) OMPSharedClause(N);
}

OMPCopyinClause *OMPCopyinClause::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc,
ArrayRef<Expr *> VL) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyinClause),
llvm::alignOf<Expr *>()) +
sizeof(Expr *) * VL.size());
OMPCopyinClause *Clause = new (Mem) OMPCopyinClause(StartLoc, LParenLoc,
EndLoc, VL.size());
Clause->setVarRefs(VL);
return Clause;
}

OMPCopyinClause *OMPCopyinClause::CreateEmpty(const ASTContext &C,
unsigned N) {
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyinClause),
llvm::alignOf<Expr *>()) +
sizeof(Expr *) * N);
return new (Mem) OMPCopyinClause(N);
}

void OMPExecutableDirective::setClauses(ArrayRef<OMPClause *> Clauses) {
assert(Clauses.size() == getNumClauses() &&
"Number of clauses is not the same as the preallocated buffer");
Expand Down
20 changes: 17 additions & 3 deletions lib/AST/StmtPrinter.cpp
Expand Up @@ -629,9 +629,15 @@ template<typename T>
void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) {
for (typename T::varlist_iterator I = Node->varlist_begin(),
E = Node->varlist_end();
I != E; ++I)
OS << (I == Node->varlist_begin() ? StartSym : ',')
<< *cast<NamedDecl>(cast<DeclRefExpr>(*I)->getDecl());
I != E; ++I) {
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(*I)) {
OS << (I == Node->varlist_begin() ? StartSym : ',');
cast<NamedDecl>(DRE->getDecl())->printQualifiedName(OS);
} else {
OS << (I == Node->varlist_begin() ? StartSym : ',');
(*I)->printPretty(OS, 0, Policy, 0);
}
}
}

void OMPClausePrinter::VisitOMPPrivateClause(OMPPrivateClause *Node) {
Expand All @@ -658,6 +664,14 @@ void OMPClausePrinter::VisitOMPSharedClause(OMPSharedClause *Node) {
}
}

void OMPClausePrinter::VisitOMPCopyinClause(OMPCopyinClause *Node) {
if (!Node->varlist_empty()) {
OS << "copyin";
VisitOMPClauseList(Node, '(');
OS << ")";
}
}

}

//===----------------------------------------------------------------------===//
Expand Down
3 changes: 3 additions & 0 deletions lib/AST/StmtProfile.cpp
Expand Up @@ -297,6 +297,9 @@ void OMPClauseProfiler::VisitOMPFirstprivateClause(
void OMPClauseProfiler::VisitOMPSharedClause(const OMPSharedClause *C) {
VisitOMPClauseList(C);
}
void OMPClauseProfiler::VisitOMPCopyinClause(const OMPCopyinClause *C) {
VisitOMPClauseList(C);
}
}

void
Expand Down
2 changes: 2 additions & 0 deletions lib/Basic/OpenMPKinds.cpp
Expand Up @@ -83,6 +83,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
case OMPC_private:
case OMPC_firstprivate:
case OMPC_shared:
case OMPC_copyin:
case NUM_OPENMP_CLAUSES:
break;
}
Expand All @@ -109,6 +110,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
case OMPC_private:
case OMPC_firstprivate:
case OMPC_shared:
case OMPC_copyin:
case NUM_OPENMP_CLAUSES:
break;
}
Expand Down
1 change: 1 addition & 0 deletions lib/Parse/ParseOpenMP.cpp
Expand Up @@ -301,6 +301,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_private:
case OMPC_firstprivate:
case OMPC_shared:
case OMPC_copyin:
Clause = ParseOpenMPVarListClause(CKind);
break;
case OMPC_unknown:
Expand Down
98 changes: 95 additions & 3 deletions lib/Sema/SemaOpenMP.cpp
Expand Up @@ -111,7 +111,6 @@ class DSAStackTy {
DSAVarData hasDSA(VarDecl *D, OpenMPClauseKind CKind,
OpenMPDirectiveKind DKind = OMPD_unknown);


/// \brief Returns currently analyzed directive.
OpenMPDirectiveKind getCurrentDirective() const {
return Stack.back().Directive;
Expand All @@ -126,6 +125,13 @@ class DSAStackTy {
return Stack.back().DefaultAttr;
}

/// \brief Checks if the spewcified variable is threadprivate.
bool isThreadPrivate(VarDecl *D) {
DSAVarData DVar = getTopDSA(D);
return (DVar.CKind == OMPC_threadprivate || DVar.CKind == OMPC_copyin);
}

Scope *getCurScope() const { return Stack.back().CurScope; }
Scope *getCurScope() { return Stack.back().CurScope; }
};
} // end anonymous namespace.
Expand Down Expand Up @@ -245,7 +251,8 @@ void DSAStackTy::addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A) {
}
}

bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
bool
DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
if (Stack.size() > 2) {
reverse_iterator I = Iter, E = Stack.rend() - 1;
Scope *TopScope = 0;
Expand Down Expand Up @@ -611,7 +618,7 @@ class DSAAttrChecker : public StmtVisitor<DSAAttrChecker, void> {
DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD);
if (DVar.CKind != OMPC_unknown) {
if (DKind == OMPD_task && DVar.CKind != OMPC_shared &&
DVar.CKind != OMPC_threadprivate && !DVar.RefExpr)
!Stack->isThreadPrivate(VD) && !DVar.RefExpr)
ImplicitFirstprivate.push_back(DVar.RefExpr);
return;
}
Expand Down Expand Up @@ -768,6 +775,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
case OMPC_private:
case OMPC_firstprivate:
case OMPC_shared:
case OMPC_copyin:
case OMPC_threadprivate:
case OMPC_unknown:
case NUM_OPENMP_CLAUSES:
Expand Down Expand Up @@ -922,6 +930,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
case OMPC_private:
case OMPC_firstprivate:
case OMPC_shared:
case OMPC_copyin:
case OMPC_threadprivate:
case OMPC_unknown:
case NUM_OPENMP_CLAUSES:
Expand Down Expand Up @@ -992,6 +1001,9 @@ OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
case OMPC_shared:
Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_copyin:
Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_if:
case OMPC_num_threads:
case OMPC_safelen:
Expand Down Expand Up @@ -1371,4 +1383,84 @@ OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
return OMPSharedClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
}

OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end();
I != E; ++I) {
assert(*I && "NULL expr in OpenMP copyin clause.");
if (isa<DependentScopeDeclRefExpr>(*I)) {
// It will be analyzed later.
Vars.push_back(*I);
continue;
}

SourceLocation ELoc = (*I)->getExprLoc();
// OpenMP [2.1, C/C++]
// A list item is a variable name.
// OpenMP [2.14.4.1, Restrictions, p.1]
// A list item that appears in a copyin clause must be threadprivate.
DeclRefExpr *DE = dyn_cast<DeclRefExpr>(*I);
if (!DE || !isa<VarDecl>(DE->getDecl())) {
Diag(ELoc, diag::err_omp_expected_var_name)
<< (*I)->getSourceRange();
continue;
}

Decl *D = DE->getDecl();
VarDecl *VD = cast<VarDecl>(D);

QualType Type = VD->getType();
if (Type->isDependentType() || Type->isInstantiationDependentType()) {
// It will be analyzed later.
Vars.push_back(DE);
continue;
}

// OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
// A list item that appears in a copyin clause must be threadprivate.
if (!DSAStack->isThreadPrivate(VD)) {
Diag(ELoc, diag::err_omp_required_access)
<< getOpenMPClauseName(OMPC_copyin)
<< getOpenMPDirectiveName(OMPD_threadprivate);
continue;
}

// OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
// A variable of class type (or array thereof) that appears in a
// copyin clause requires an accesible, unambiguous copy assignment
// operator for the class type.
Type = Context.getBaseElementType(Type);
CXXRecordDecl *RD = getLangOpts().CPlusPlus ?
Type->getAsCXXRecordDecl() : 0;
if (RD) {
CXXMethodDecl *MD = LookupCopyingAssignment(RD, 0, false, 0);
DeclAccessPair FoundDecl = DeclAccessPair::make(MD, MD->getAccess());
if (!MD ||
CheckMemberAccess(ELoc, RD, FoundDecl) == AR_inaccessible ||
MD->isDeleted()) {
Diag(ELoc, diag::err_omp_required_method)
<< getOpenMPClauseName(OMPC_copyin) << 2;
bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
VarDecl::DeclarationOnly;
Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
diag::note_defined_here) << VD;
Diag(RD->getLocation(), diag::note_previous_decl) << RD;
continue;
}
MarkFunctionReferenced(ELoc, MD);
DiagnoseUseOfDecl(MD, ELoc);
}

DSAStack->addDSA(VD, DE, OMPC_copyin);
Vars.push_back(DE);
}

if (Vars.empty()) return 0;

return OMPCopyinClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
}

#undef DSAStack

0 comments on commit a100391

Please sign in to comment.