Skip to content

Commit

Permalink
[OpenMP 5.0] Parsing/sema support for "omp declare mapper" directive.
Browse files Browse the repository at this point in the history
This patch implements parsing and sema for "omp declare mapper"
directive. User defined mapper, i.e., declare mapper directive, is a new
feature in OpenMP 5.0. It is introduced to extend existing map clauses
for the purpose of simplifying the copy of complex data structures
between host and device (i.e., deep copy). An example is shown below:

    struct S {  int len;  int *d; };
    #pragma omp declare mapper(struct S s) map(s, s.d[0:s.len]) // Memory region that d points to is also mapped using this mapper.

Contributed-by: Lingda Li <lildmh@gmail.com>

Differential Revision: https://reviews.llvm.org/D56326

llvm-svn: 352906
  • Loading branch information
Meinersbur committed Feb 1, 2019
1 parent 6b653fc commit 251e148
Show file tree
Hide file tree
Showing 39 changed files with 1,035 additions and 13 deletions.
8 changes: 6 additions & 2 deletions clang/include/clang/AST/DeclBase.h
Expand Up @@ -175,7 +175,10 @@ class alignas(8) Decl {
IDNS_LocalExtern = 0x0800,

/// This declaration is an OpenMP user defined reduction construction.
IDNS_OMPReduction = 0x1000
IDNS_OMPReduction = 0x1000,

/// This declaration is an OpenMP user defined mapper.
IDNS_OMPMapper = 0x2000,
};

/// ObjCDeclQualifier - 'Qualifiers' written next to the return and
Expand Down Expand Up @@ -323,7 +326,7 @@ class alignas(8) Decl {
unsigned FromASTFile : 1;

/// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
unsigned IdentifierNamespace : 13;
unsigned IdentifierNamespace : 14;

/// If 0, we have not computed the linkage of this declaration.
/// Otherwise, it is the linkage + 1.
Expand Down Expand Up @@ -1251,6 +1254,7 @@ class DeclContextLookupResult {
/// NamespaceDecl
/// TagDecl
/// OMPDeclareReductionDecl
/// OMPDeclareMapperDecl
/// FunctionDecl
/// ObjCMethodDecl
/// ObjCContainerDecl
Expand Down
8 changes: 8 additions & 0 deletions clang/include/clang/AST/DeclCXX.h
Expand Up @@ -1827,6 +1827,14 @@ class CXXRecordDecl : public RecordDecl {
static bool FindOMPReductionMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path, DeclarationName Name);

/// Base-class lookup callback that determines whether there exists
/// an OpenMP declare mapper member with the given name.
///
/// This callback can be used with \c lookupInBases() to find members
/// of the given name within a C++ class hierarchy.
static bool FindOMPMapperMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path, DeclarationName Name);

/// Base-class lookup callback that determines whether there exists
/// a member with the given name that can be used in a nested-name-specifier.
///
Expand Down
102 changes: 102 additions & 0 deletions clang/include/clang/AST/DeclOpenMP.h
Expand Up @@ -206,6 +206,108 @@ class OMPDeclareReductionDecl final : public ValueDecl, public DeclContext {
}
};

/// This represents '#pragma omp declare mapper ...' directive. Map clauses are
/// allowed to use with this directive. The following example declares a user
/// defined mapper for the type 'struct vec'. This example instructs the fields
/// 'len' and 'data' should be mapped when mapping instances of 'struct vec'.
///
/// \code
/// #pragma omp declare mapper(mid: struct vec v) map(v.len, v.data[0:N])
/// \endcode
class OMPDeclareMapperDecl final : public ValueDecl, public DeclContext {
friend class ASTDeclReader;

/// Clauses assoicated with this mapper declaration
MutableArrayRef<OMPClause *> Clauses;

/// Mapper variable, which is 'v' in the example above
Expr *MapperVarRef = nullptr;

/// Name of the mapper variable
DeclarationName VarName;

LazyDeclPtr PrevDeclInScope;

virtual void anchor();

OMPDeclareMapperDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName Name, QualType Ty,
DeclarationName VarName,
OMPDeclareMapperDecl *PrevDeclInScope)
: ValueDecl(DK, DC, L, Name, Ty), DeclContext(DK), VarName(VarName),
PrevDeclInScope(PrevDeclInScope) {}

void setPrevDeclInScope(OMPDeclareMapperDecl *Prev) {
PrevDeclInScope = Prev;
}

/// Sets an array of clauses to this mapper declaration
void setClauses(ArrayRef<OMPClause *> CL);

public:
/// Creates declare mapper node.
static OMPDeclareMapperDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, DeclarationName Name,
QualType T, DeclarationName VarName,
OMPDeclareMapperDecl *PrevDeclInScope);
/// Creates deserialized declare mapper node.
static OMPDeclareMapperDecl *CreateDeserialized(ASTContext &C, unsigned ID,
unsigned N);

/// Creates an array of clauses to this mapper declaration and intializes
/// them.
void CreateClauses(ASTContext &C, ArrayRef<OMPClause *> CL);

using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator;
using clauselist_const_iterator = ArrayRef<const OMPClause *>::iterator;
using clauselist_range = llvm::iterator_range<clauselist_iterator>;
using clauselist_const_range =
llvm::iterator_range<clauselist_const_iterator>;

unsigned clauselist_size() const { return Clauses.size(); }
bool clauselist_empty() const { return Clauses.empty(); }

clauselist_range clauselists() {
return clauselist_range(clauselist_begin(), clauselist_end());
}
clauselist_const_range clauselists() const {
return clauselist_const_range(clauselist_begin(), clauselist_end());
}
clauselist_iterator clauselist_begin() { return Clauses.begin(); }
clauselist_iterator clauselist_end() { return Clauses.end(); }
clauselist_const_iterator clauselist_begin() const { return Clauses.begin(); }
clauselist_const_iterator clauselist_end() const { return Clauses.end(); }

/// Get the variable declared in the mapper
Expr *getMapperVarRef() { return MapperVarRef; }
const Expr *getMapperVarRef() const { return MapperVarRef; }
/// Set the variable declared in the mapper
void setMapperVarRef(Expr *MapperVarRefE) { MapperVarRef = MapperVarRefE; }

/// Get the name of the variable declared in the mapper
DeclarationName getVarName() { return VarName; }

/// Get reference to previous declare mapper construct in the same
/// scope with the same name.
OMPDeclareMapperDecl *getPrevDeclInScope() {
return cast_or_null<OMPDeclareMapperDecl>(
PrevDeclInScope.get(getASTContext().getExternalSource()));
}
const OMPDeclareMapperDecl *getPrevDeclInScope() const {
return cast_or_null<OMPDeclareMapperDecl>(
PrevDeclInScope.get(getASTContext().getExternalSource()));
}

static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == OMPDeclareMapper; }
static DeclContext *castToDeclContext(const OMPDeclareMapperDecl *D) {
return static_cast<DeclContext *>(const_cast<OMPDeclareMapperDecl *>(D));
}
static OMPDeclareMapperDecl *castFromDeclContext(const DeclContext *DC) {
return static_cast<OMPDeclareMapperDecl *>(const_cast<DeclContext *>(DC));
}
};

/// Pseudo declaration for capturing expressions. Also is used for capturing of
/// non-static data members in non-static member functions.
///
Expand Down
9 changes: 8 additions & 1 deletion clang/include/clang/AST/RecursiveASTVisitor.h
Expand Up @@ -1590,7 +1590,7 @@ DEF_TRAVERSE_DECL(OMPThreadPrivateDecl, {
TRY_TO(TraverseStmt(I));
}
})

DEF_TRAVERSE_DECL(OMPRequiresDecl, {
for (auto *C : D->clauselists()) {
TRY_TO(TraverseOMPClause(C));
Expand All @@ -1605,6 +1605,13 @@ DEF_TRAVERSE_DECL(OMPDeclareReductionDecl, {
return true;
})

DEF_TRAVERSE_DECL(OMPDeclareMapperDecl, {
for (auto *C : D->clauselists())
TRY_TO(TraverseOMPClause(C));
TRY_TO(TraverseType(D->getType()));
return true;
})

DEF_TRAVERSE_DECL(OMPCapturedExprDecl, { TRY_TO(TraverseVarHelper(D)); })

// A helper method for TemplateDecl's children.
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/DeclNodes.td
Expand Up @@ -41,6 +41,7 @@ def Named : Decl<"named declarations", 1>;
def IndirectField : DDecl<Value>;
def Binding : DDecl<Value>;
def OMPDeclareReduction : DDecl<Value>, DeclContext;
def OMPDeclareMapper : DDecl<Value>, DeclContext;
def Declarator : DDecl<Value, "declarators", 1>;
def Field : DDecl<Declarator, "non-static data members">;
def ObjCIvar : DDecl<Field>;
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/DiagnosticParseKinds.td
Expand Up @@ -1176,6 +1176,10 @@ def err_omp_declare_target_unexpected_clause: Error<
"unexpected '%0' clause, only 'to' or 'link' clauses expected">;
def err_omp_expected_clause: Error<
"expected at least one clause on '#pragma omp %0' directive">;
def err_omp_mapper_illegal_identifier : Error<
"illegal identifier on 'omp declare mapper' directive">;
def err_omp_mapper_expected_declarator : Error<
"expected declarator on 'omp declare mapper' directive">;

// Pragma loop support.
def err_pragma_loop_missing_argument : Error<
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Expand Up @@ -8977,6 +8977,12 @@ def err_omp_parent_cancel_region_ordered : Error<
def err_omp_reduction_wrong_type : Error<"reduction type cannot be %select{qualified with 'const', 'volatile' or 'restrict'|a function|a reference|an array}0 type">;
def err_omp_wrong_var_in_declare_reduction : Error<"only %select{'omp_priv' or 'omp_orig'|'omp_in' or 'omp_out'}0 variables are allowed in %select{initializer|combiner}0 expression">;
def err_omp_declare_reduction_redefinition : Error<"redefinition of user-defined reduction for type %0">;
def err_omp_mapper_wrong_type : Error<
"mapper type must be of struct, union or class type">;
def err_omp_declare_mapper_wrong_var : Error<
"only variable %0 is allowed in map clauses of this 'omp declare mapper' directive">;
def err_omp_declare_mapper_redefinition : Error<
"redefinition of user-defined mapper for type %0 with name %1">;
def err_omp_array_section_use : Error<"OpenMP array section is not allowed here">;
def err_omp_typecheck_section_value : Error<
"subscripted value is not an array or pointer">;
Expand Down
8 changes: 8 additions & 0 deletions clang/include/clang/Basic/OpenMPKinds.def
Expand Up @@ -179,6 +179,9 @@
#ifndef OPENMP_TASKGROUP_CLAUSE
#define OPENMP_TASKGROUP_CLAUSE(Name)
#endif
#ifndef OPENMP_DECLARE_MAPPER_CLAUSE
#define OPENMP_DECLARE_MAPPER_CLAUSE(Name)
#endif

// OpenMP directives.
OPENMP_DIRECTIVE(threadprivate)
Expand Down Expand Up @@ -214,6 +217,7 @@ OPENMP_DIRECTIVE_EXT(parallel_sections, "parallel sections")
OPENMP_DIRECTIVE_EXT(for_simd, "for simd")
OPENMP_DIRECTIVE_EXT(cancellation_point, "cancellation point")
OPENMP_DIRECTIVE_EXT(declare_reduction, "declare reduction")
OPENMP_DIRECTIVE_EXT(declare_mapper, "declare mapper")
OPENMP_DIRECTIVE_EXT(declare_simd, "declare simd")
OPENMP_DIRECTIVE(taskloop)
OPENMP_DIRECTIVE_EXT(taskloop_simd, "taskloop simd")
Expand Down Expand Up @@ -887,6 +891,10 @@ OPENMP_TARGET_TEAMS_DISTRIBUTE_SIMD_CLAUSE(simdlen)
// Clauses allowed for OpenMP directive 'taskgroup'.
OPENMP_TASKGROUP_CLAUSE(task_reduction)

// Clauses allowed for OpenMP directive 'declare mapper'.
OPENMP_DECLARE_MAPPER_CLAUSE(map)

#undef OPENMP_DECLARE_MAPPER_CLAUSE
#undef OPENMP_TASKGROUP_CLAUSE
#undef OPENMP_TASKLOOP_SIMD_CLAUSE
#undef OPENMP_TASKLOOP_CLAUSE
Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/Parse/Parser.h
Expand Up @@ -2803,6 +2803,13 @@ class Parser : public CodeCompletionHandler {
/// initializer.
void ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm);

/// Parses 'omp declare mapper' directive.
DeclGroupPtrTy ParseOpenMPDeclareMapperDirective(AccessSpecifier AS);
/// Parses variable declaration in 'omp declare mapper' directive.
TypeResult parseOpenMPDeclareMapperVarDecl(SourceRange &Range,
DeclarationName &Name,
AccessSpecifier AS = AS_none);

/// Parses simple list of variables.
///
/// \param Kind Kind of the directive.
Expand Down
23 changes: 23 additions & 0 deletions clang/include/clang/Sema/Sema.h
Expand Up @@ -3155,6 +3155,8 @@ class Sema {
LookupObjCImplicitSelfParam,
/// Look up the name of an OpenMP user-defined reduction operation.
LookupOMPReductionName,
/// Look up the name of an OpenMP user-defined mapper.
LookupOMPMapperName,
/// Look up any declaration with any name.
LookupAnyName
};
Expand Down Expand Up @@ -8870,6 +8872,27 @@ class Sema {
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd(
Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid);

/// Check variable declaration in 'omp declare mapper' construct.
TypeResult ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D);
/// Check if the specified type is allowed to be used in 'omp declare
/// mapper' construct.
QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc,
TypeResult ParsedType);
/// Called on start of '#pragma omp declare mapper'.
OMPDeclareMapperDecl *ActOnOpenMPDeclareMapperDirectiveStart(
Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS,
Decl *PrevDeclInScope = nullptr);
/// Build the mapper variable of '#pragma omp declare mapper'.
void ActOnOpenMPDeclareMapperDirectiveVarDecl(OMPDeclareMapperDecl *DMD,
Scope *S, QualType MapperType,
SourceLocation StartLoc,
DeclarationName VN);
/// Called at the end of '#pragma omp declare mapper'.
DeclGroupPtrTy
ActOnOpenMPDeclareMapperDirectiveEnd(OMPDeclareMapperDecl *D, Scope *S,
ArrayRef<OMPClause *> ClauseList);

/// Called on the start of target region i.e. '#pragma omp declare target'.
bool ActOnStartOpenMPDeclareTargetDirective(SourceLocation Loc);
/// Called at the end of target region i.e. '#pragme omp end declare target'.
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Serialization/ASTBitCodes.h
Expand Up @@ -1537,6 +1537,9 @@ namespace serialization {
/// A PragmaDetectMismatchDecl record.
DECL_PRAGMA_DETECT_MISMATCH,

/// An OMPDeclareMapperDecl record.
DECL_OMP_DECLARE_MAPPER,

/// An OMPDeclareReductionDecl record.
DECL_OMP_DECLARE_REDUCTION,

Expand Down
5 changes: 5 additions & 0 deletions clang/lib/AST/ASTDumper.cpp
Expand Up @@ -381,6 +381,11 @@ namespace {
Visit(Initializer);
}

void VisitOMPDeclareMapperDecl(const OMPDeclareMapperDecl *D) {
for (const auto *C : D->clauselists())
Visit(C);
}

void VisitOMPCapturedExprDecl(const OMPCapturedExprDecl *D) {
Visit(D->getInit());
}
Expand Down
15 changes: 15 additions & 0 deletions clang/lib/AST/CXXInheritance.cpp
Expand Up @@ -486,6 +486,21 @@ bool CXXRecordDecl::FindOMPReductionMember(const CXXBaseSpecifier *Specifier,
return false;
}

bool CXXRecordDecl::FindOMPMapperMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
DeclarationName Name) {
RecordDecl *BaseRecord =
Specifier->getType()->castAs<RecordType>()->getDecl();

for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty();
Path.Decls = Path.Decls.slice(1)) {
if (Path.Decls.front()->isInIdentifierNamespace(IDNS_OMPMapper))
return true;
}

return false;
}

bool CXXRecordDecl::
FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/AST/DeclBase.cpp
Expand Up @@ -780,6 +780,9 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case OMPDeclareReduction:
return IDNS_OMPReduction;

case OMPDeclareMapper:
return IDNS_OMPMapper;

// Never have names.
case Friend:
case FriendTemplate:
Expand Down Expand Up @@ -1163,6 +1166,7 @@ DeclContext *DeclContext::getPrimaryContext() {
case Decl::Block:
case Decl::Captured:
case Decl::OMPDeclareReduction:
case Decl::OMPDeclareMapper:
// There is only one DeclContext for these entities.
return this;

Expand Down

0 comments on commit 251e148

Please sign in to comment.