forked from OSchip/llvm-project
[OPENMP51]Initial support for the interop directive.
Added basic parsing/sema/serialization support for interop directive. Support for the 'init' clause. Differential Revision: https://reviews.llvm.org/D98558
This commit is contained in:
parent
fa9d8ace09
commit
410f09af09
|
@ -2576,7 +2576,11 @@ enum CXCursorKind {
|
||||||
*/
|
*/
|
||||||
CXCursor_OMPCanonicalLoop = 289,
|
CXCursor_OMPCanonicalLoop = 289,
|
||||||
|
|
||||||
CXCursor_LastStmt = CXCursor_OMPCanonicalLoop,
|
/** OpenMP interop directive.
|
||||||
|
*/
|
||||||
|
CXCursor_OMPInteropDirective = 290,
|
||||||
|
|
||||||
|
CXCursor_LastStmt = CXCursor_OMPInteropDirective,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cursor that represents the translation unit itself.
|
* Cursor that represents the translation unit itself.
|
||||||
|
|
|
@ -7366,6 +7366,129 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// This represents the 'init' clause in '#pragma omp ...' directives.
|
||||||
|
///
|
||||||
|
/// \code
|
||||||
|
/// #pragma omp interop init(target:obj)
|
||||||
|
/// \endcode
|
||||||
|
class OMPInitClause final
|
||||||
|
: public OMPVarListClause<OMPInitClause>,
|
||||||
|
private llvm::TrailingObjects<OMPInitClause, Expr *> {
|
||||||
|
friend class OMPClauseReader;
|
||||||
|
friend OMPVarListClause;
|
||||||
|
friend TrailingObjects;
|
||||||
|
|
||||||
|
/// Location of interop variable.
|
||||||
|
SourceLocation VarLoc;
|
||||||
|
|
||||||
|
bool IsTarget = false;
|
||||||
|
bool IsTargetSync = false;
|
||||||
|
|
||||||
|
void setInteropVar(Expr *E) { varlist_begin()[0] = E; }
|
||||||
|
|
||||||
|
void setIsTarget(bool V) { IsTarget = V; }
|
||||||
|
|
||||||
|
void setIsTargetSync(bool V) { IsTargetSync = V; }
|
||||||
|
|
||||||
|
/// Sets the location of the interop variable.
|
||||||
|
void setVarLoc(SourceLocation Loc) { VarLoc = Loc; }
|
||||||
|
|
||||||
|
/// Build 'init' clause.
|
||||||
|
///
|
||||||
|
/// \param IsTarget Uses the 'target' interop-type.
|
||||||
|
/// \param IsTargetSync Uses the 'targetsync' interop-type.
|
||||||
|
/// \param StartLoc Starting location of the clause.
|
||||||
|
/// \param LParenLoc Location of '('.
|
||||||
|
/// \param VarLoc Location of the interop variable.
|
||||||
|
/// \param EndLoc Ending location of the clause.
|
||||||
|
/// \param N Number of expressions.
|
||||||
|
OMPInitClause(bool IsTarget, bool IsTargetSync, SourceLocation StartLoc,
|
||||||
|
SourceLocation LParenLoc, SourceLocation VarLoc,
|
||||||
|
SourceLocation EndLoc, unsigned N)
|
||||||
|
: OMPVarListClause<OMPInitClause>(llvm::omp::OMPC_init, StartLoc,
|
||||||
|
LParenLoc, EndLoc, N),
|
||||||
|
VarLoc(VarLoc), IsTarget(IsTarget), IsTargetSync(IsTargetSync) {}
|
||||||
|
|
||||||
|
/// Build an empty clause.
|
||||||
|
OMPInitClause(unsigned N)
|
||||||
|
: OMPVarListClause<OMPInitClause>(llvm::omp::OMPC_init, SourceLocation(),
|
||||||
|
SourceLocation(), SourceLocation(), N) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Creates a fully specified clause.
|
||||||
|
///
|
||||||
|
/// \param C AST context.
|
||||||
|
/// \param InteropVar The interop variable.
|
||||||
|
/// \param PrefExprs The list of preference expressions.
|
||||||
|
/// \param IsTarget Uses the 'target' interop-type.
|
||||||
|
/// \param IsTargetSync Uses the 'targetsync' interop-type.
|
||||||
|
/// \param StartLoc Starting location of the clause.
|
||||||
|
/// \param LParenLoc Location of '('.
|
||||||
|
/// \param VarLoc Location of the interop variable.
|
||||||
|
/// \param EndLoc Ending location of the clause.
|
||||||
|
static OMPInitClause *Create(const ASTContext &C, Expr *InteropVar,
|
||||||
|
ArrayRef<Expr *> PrefExprs, bool IsTarget,
|
||||||
|
bool IsTargetSync, SourceLocation StartLoc,
|
||||||
|
SourceLocation LParenLoc, SourceLocation VarLoc,
|
||||||
|
SourceLocation EndLoc);
|
||||||
|
|
||||||
|
/// Creates an empty clause with \a N expressions.
|
||||||
|
///
|
||||||
|
/// \param C AST context.
|
||||||
|
/// \param N Number of expression items.
|
||||||
|
static OMPInitClause *CreateEmpty(const ASTContext &C, unsigned N);
|
||||||
|
|
||||||
|
/// Returns the location of the interop variable.
|
||||||
|
SourceLocation getVarLoc() const { return VarLoc; }
|
||||||
|
|
||||||
|
/// Returns the interop variable.
|
||||||
|
Expr *getInteropVar() { return varlist_begin()[0]; }
|
||||||
|
const Expr *getInteropVar() const { return varlist_begin()[0]; }
|
||||||
|
|
||||||
|
/// Returns true is interop-type 'target' is used.
|
||||||
|
bool getIsTarget() const { return IsTarget; }
|
||||||
|
|
||||||
|
/// Returns true is interop-type 'targetsync' is used.
|
||||||
|
bool getIsTargetSync() const { return IsTargetSync; }
|
||||||
|
|
||||||
|
child_range children() {
|
||||||
|
return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
|
||||||
|
reinterpret_cast<Stmt **>(varlist_end()));
|
||||||
|
}
|
||||||
|
|
||||||
|
const_child_range children() const {
|
||||||
|
auto Children = const_cast<OMPInitClause *>(this)->children();
|
||||||
|
return const_child_range(Children.begin(), Children.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
child_range used_children() {
|
||||||
|
return child_range(child_iterator(), child_iterator());
|
||||||
|
}
|
||||||
|
const_child_range used_children() const {
|
||||||
|
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||||
|
}
|
||||||
|
|
||||||
|
using prefs_iterator = MutableArrayRef<Expr *>::iterator;
|
||||||
|
using const_prefs_iterator = ArrayRef<const Expr *>::iterator;
|
||||||
|
using prefs_range = llvm::iterator_range<prefs_iterator>;
|
||||||
|
using const_prefs_range = llvm::iterator_range<const_prefs_iterator>;
|
||||||
|
|
||||||
|
prefs_range prefs() {
|
||||||
|
return prefs_range(reinterpret_cast<Expr **>(std::next(varlist_begin())),
|
||||||
|
reinterpret_cast<Expr **>(varlist_end()));
|
||||||
|
}
|
||||||
|
|
||||||
|
const_prefs_range prefs() const {
|
||||||
|
auto Prefs = const_cast<OMPInitClause *>(this)->prefs();
|
||||||
|
return const_prefs_range(Prefs.begin(), Prefs.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool classof(const OMPClause *T) {
|
||||||
|
return T->getClauseKind() == llvm::omp::OMPC_init;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/// This represents 'destroy' clause in the '#pragma omp depobj'
|
/// This represents 'destroy' clause in the '#pragma omp depobj'
|
||||||
/// directive.
|
/// directive.
|
||||||
///
|
///
|
||||||
|
|
|
@ -2968,6 +2968,9 @@ DEF_TRAVERSE_STMT(OMPTargetTeamsDistributeParallelForSimdDirective,
|
||||||
DEF_TRAVERSE_STMT(OMPTargetTeamsDistributeSimdDirective,
|
DEF_TRAVERSE_STMT(OMPTargetTeamsDistributeSimdDirective,
|
||||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||||
|
|
||||||
|
DEF_TRAVERSE_STMT(OMPInteropDirective,
|
||||||
|
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||||
|
|
||||||
// OpenMP clauses.
|
// OpenMP clauses.
|
||||||
template <typename Derived>
|
template <typename Derived>
|
||||||
bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
|
bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
|
||||||
|
@ -3194,6 +3197,12 @@ bool RecursiveASTVisitor<Derived>::VisitOMPNogroupClause(OMPNogroupClause *) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Derived>
|
||||||
|
bool RecursiveASTVisitor<Derived>::VisitOMPInitClause(OMPInitClause *C) {
|
||||||
|
TRY_TO(VisitOMPClauseList(C));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Derived>
|
template <typename Derived>
|
||||||
bool RecursiveASTVisitor<Derived>::VisitOMPDestroyClause(OMPDestroyClause *) {
|
bool RecursiveASTVisitor<Derived>::VisitOMPDestroyClause(OMPDestroyClause *) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -5086,6 +5086,59 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// This represents '#pragma omp interop' directive.
|
||||||
|
///
|
||||||
|
/// \code
|
||||||
|
/// #pragma omp interop init(target:obj) device(x) depend(inout:y) nowait
|
||||||
|
/// \endcode
|
||||||
|
/// In this example directive '#pragma omp interop' has
|
||||||
|
/// clauses 'init', 'device', 'depend' and 'nowait'.
|
||||||
|
///
|
||||||
|
class OMPInteropDirective final : public OMPExecutableDirective {
|
||||||
|
friend class ASTStmtReader;
|
||||||
|
friend class OMPExecutableDirective;
|
||||||
|
|
||||||
|
/// Build directive with the given start and end location.
|
||||||
|
///
|
||||||
|
/// \param StartLoc Starting location of the directive.
|
||||||
|
/// \param EndLoc Ending location of the directive.
|
||||||
|
///
|
||||||
|
OMPInteropDirective(SourceLocation StartLoc, SourceLocation EndLoc)
|
||||||
|
: OMPExecutableDirective(OMPInteropDirectiveClass,
|
||||||
|
llvm::omp::OMPD_interop, StartLoc, EndLoc) {}
|
||||||
|
|
||||||
|
/// Build an empty directive.
|
||||||
|
///
|
||||||
|
explicit OMPInteropDirective()
|
||||||
|
: OMPExecutableDirective(OMPInteropDirectiveClass,
|
||||||
|
llvm::omp::OMPD_interop, SourceLocation(),
|
||||||
|
SourceLocation()) {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Creates directive.
|
||||||
|
///
|
||||||
|
/// \param C AST context.
|
||||||
|
/// \param StartLoc Starting location of the directive.
|
||||||
|
/// \param EndLoc Ending Location of the directive.
|
||||||
|
/// \param Clauses The directive's clauses.
|
||||||
|
///
|
||||||
|
static OMPInteropDirective *Create(const ASTContext &C,
|
||||||
|
SourceLocation StartLoc,
|
||||||
|
SourceLocation EndLoc,
|
||||||
|
ArrayRef<OMPClause *> Clauses);
|
||||||
|
|
||||||
|
/// Creates an empty directive.
|
||||||
|
///
|
||||||
|
/// \param C AST context.
|
||||||
|
///
|
||||||
|
static OMPInteropDirective *CreateEmpty(const ASTContext &C,
|
||||||
|
unsigned NumClauses, EmptyShell);
|
||||||
|
|
||||||
|
static bool classof(const Stmt *T) {
|
||||||
|
return T->getStmtClass() == OMPInteropDirectiveClass;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // end namespace clang
|
} // end namespace clang
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1400,6 +1400,13 @@ def err_omp_variant_ctx_second_match_extension : Error<
|
||||||
"only a single match extension allowed per OpenMP context selector">;
|
"only a single match extension allowed per OpenMP context selector">;
|
||||||
def err_omp_invalid_dsa: Error<
|
def err_omp_invalid_dsa: Error<
|
||||||
"data-sharing attribute '%0' in '%1' clause requires OpenMP version %2 or above">;
|
"data-sharing attribute '%0' in '%1' clause requires OpenMP version %2 or above">;
|
||||||
|
def err_omp_expected_punc_after_interop_mod : Error<
|
||||||
|
"expected ',' after interop modifier">;
|
||||||
|
def err_omp_expected_interop_type : Error<
|
||||||
|
"expected interop type: 'target' and/or 'targetsync'">;
|
||||||
|
def warn_omp_more_one_interop_type
|
||||||
|
: Warning<"interop type '%0' cannot be specified more than once">,
|
||||||
|
InGroup<OpenMPClauses>;
|
||||||
|
|
||||||
// Pragma loop support.
|
// Pragma loop support.
|
||||||
def err_pragma_loop_missing_argument : Error<
|
def err_pragma_loop_missing_argument : Error<
|
||||||
|
|
|
@ -10587,6 +10587,17 @@ def note_omp_protected_structured_block
|
||||||
: Note<"jump bypasses OpenMP structured block">;
|
: Note<"jump bypasses OpenMP structured block">;
|
||||||
def note_omp_exits_structured_block
|
def note_omp_exits_structured_block
|
||||||
: Note<"jump exits scope of OpenMP structured block">;
|
: Note<"jump exits scope of OpenMP structured block">;
|
||||||
|
def err_omp_interop_variable_expected : Error<
|
||||||
|
"expected%select{| non-const}0 variable of type 'omp_interop_t'">;
|
||||||
|
def err_omp_interop_variable_wrong_type : Error<
|
||||||
|
"interop variable must be of type 'omp_interop_t'">;
|
||||||
|
def err_omp_interop_prefer_type : Error<
|
||||||
|
"prefer_list item must be a string literal or constant integral "
|
||||||
|
"expression">;
|
||||||
|
def err_omp_interop_bad_depend_clause : Error<
|
||||||
|
"'depend' clause requires the 'targetsync' interop type">;
|
||||||
|
def err_omp_interop_var_multiple_actions : Error<
|
||||||
|
"interop variable %0 used in multiple action clauses">;
|
||||||
} // end of OpenMP category
|
} // end of OpenMP category
|
||||||
|
|
||||||
let CategoryName = "Related Result Type Issue" in {
|
let CategoryName = "Related Result Type Issue" in {
|
||||||
|
|
|
@ -275,3 +275,4 @@ def OMPTargetTeamsDistributeDirective : StmtNode<OMPLoopDirective>;
|
||||||
def OMPTargetTeamsDistributeParallelForDirective : StmtNode<OMPLoopDirective>;
|
def OMPTargetTeamsDistributeParallelForDirective : StmtNode<OMPLoopDirective>;
|
||||||
def OMPTargetTeamsDistributeParallelForSimdDirective : StmtNode<OMPLoopDirective>;
|
def OMPTargetTeamsDistributeParallelForSimdDirective : StmtNode<OMPLoopDirective>;
|
||||||
def OMPTargetTeamsDistributeSimdDirective : StmtNode<OMPLoopDirective>;
|
def OMPTargetTeamsDistributeSimdDirective : StmtNode<OMPLoopDirective>;
|
||||||
|
def OMPInteropDirective : StmtNode<OMPExecutableDirective>;
|
||||||
|
|
|
@ -3292,6 +3292,14 @@ private:
|
||||||
/// '(' { <allocator> [ '(' <allocator_traits> ')' ] }+ ')'
|
/// '(' { <allocator> [ '(' <allocator_traits> ')' ] }+ ')'
|
||||||
OMPClause *ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind);
|
OMPClause *ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind);
|
||||||
|
|
||||||
|
/// Parses clause with an interop variable of kind \a Kind.
|
||||||
|
///
|
||||||
|
/// \param Kind Kind of current clause.
|
||||||
|
/// \param ParseOnly true to skip the clause's semantic actions and return
|
||||||
|
/// nullptr.
|
||||||
|
//
|
||||||
|
OMPClause *ParseOpenMPInteropClause(OpenMPClauseKind Kind, bool ParseOnly);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Parses simple expression in parens for single-expression clauses of OpenMP
|
/// Parses simple expression in parens for single-expression clauses of OpenMP
|
||||||
/// constructs.
|
/// constructs.
|
||||||
|
|
|
@ -10790,6 +10790,10 @@ public:
|
||||||
StmtResult ActOnOpenMPTargetTeamsDistributeSimdDirective(
|
StmtResult ActOnOpenMPTargetTeamsDistributeSimdDirective(
|
||||||
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
|
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
|
||||||
SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
|
SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
|
||||||
|
/// Called on well-formed '\#pragma omp interop'.
|
||||||
|
StmtResult ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses,
|
||||||
|
SourceLocation StartLoc,
|
||||||
|
SourceLocation EndLoc);
|
||||||
|
|
||||||
/// Checks correctness of linear modifiers.
|
/// Checks correctness of linear modifiers.
|
||||||
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
|
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
|
||||||
|
@ -10979,6 +10983,15 @@ public:
|
||||||
/// Called on well-formed 'relaxed' clause.
|
/// Called on well-formed 'relaxed' clause.
|
||||||
OMPClause *ActOnOpenMPRelaxedClause(SourceLocation StartLoc,
|
OMPClause *ActOnOpenMPRelaxedClause(SourceLocation StartLoc,
|
||||||
SourceLocation EndLoc);
|
SourceLocation EndLoc);
|
||||||
|
|
||||||
|
/// Called on well-formed 'init' clause.
|
||||||
|
OMPClause *ActOnOpenMPInitClause(Expr *InteropVar, ArrayRef<Expr *> PrefExprs,
|
||||||
|
bool IsTarget, bool IsTargetSync,
|
||||||
|
SourceLocation StartLoc,
|
||||||
|
SourceLocation LParenLoc,
|
||||||
|
SourceLocation VarLoc,
|
||||||
|
SourceLocation EndLoc);
|
||||||
|
|
||||||
/// Called on well-formed 'destroy' clause.
|
/// Called on well-formed 'destroy' clause.
|
||||||
OMPClause *ActOnOpenMPDestroyClause(SourceLocation StartLoc,
|
OMPClause *ActOnOpenMPDestroyClause(SourceLocation StartLoc,
|
||||||
SourceLocation EndLoc);
|
SourceLocation EndLoc);
|
||||||
|
|
|
@ -1940,6 +1940,7 @@ enum StmtCode {
|
||||||
STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE,
|
STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE,
|
||||||
STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE,
|
STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE,
|
||||||
STMT_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE,
|
STMT_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE,
|
||||||
|
STMT_OMP_INTEROP_DIRECTIVE,
|
||||||
EXPR_OMP_ARRAY_SECTION,
|
EXPR_OMP_ARRAY_SECTION,
|
||||||
EXPR_OMP_ARRAY_SHAPING,
|
EXPR_OMP_ARRAY_SHAPING,
|
||||||
EXPR_OMP_ITERATOR,
|
EXPR_OMP_ITERATOR,
|
||||||
|
|
|
@ -1513,6 +1513,27 @@ OMPAffinityClause *OMPAffinityClause::CreateEmpty(const ASTContext &C,
|
||||||
return new (Mem) OMPAffinityClause(N);
|
return new (Mem) OMPAffinityClause(N);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OMPInitClause *OMPInitClause::Create(const ASTContext &C, Expr *InteropVar,
|
||||||
|
ArrayRef<Expr *> PrefExprs, bool IsTarget,
|
||||||
|
bool IsTargetSync, SourceLocation StartLoc,
|
||||||
|
SourceLocation LParenLoc,
|
||||||
|
SourceLocation VarLoc,
|
||||||
|
SourceLocation EndLoc) {
|
||||||
|
|
||||||
|
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(PrefExprs.size() + 1));
|
||||||
|
auto *Clause =
|
||||||
|
new (Mem) OMPInitClause(IsTarget, IsTargetSync, StartLoc, LParenLoc,
|
||||||
|
VarLoc, EndLoc, PrefExprs.size() + 1);
|
||||||
|
Clause->setInteropVar(InteropVar);
|
||||||
|
llvm::copy(PrefExprs, Clause->getTrailingObjects<Expr *>() + 1);
|
||||||
|
return Clause;
|
||||||
|
}
|
||||||
|
|
||||||
|
OMPInitClause *OMPInitClause::CreateEmpty(const ASTContext &C, unsigned N) {
|
||||||
|
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N));
|
||||||
|
return new (Mem) OMPInitClause(N);
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// OpenMP clauses printing methods
|
// OpenMP clauses printing methods
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -1755,6 +1776,31 @@ void OMPClausePrinter::VisitOMPHintClause(OMPHintClause *Node) {
|
||||||
OS << ")";
|
OS << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OMPClausePrinter::VisitOMPInitClause(OMPInitClause *Node) {
|
||||||
|
OS << "init(";
|
||||||
|
bool First = true;
|
||||||
|
for (const Expr *E : Node->prefs()) {
|
||||||
|
if (First)
|
||||||
|
OS << "prefer_type(";
|
||||||
|
else
|
||||||
|
OS << ",";
|
||||||
|
E->printPretty(OS, nullptr, Policy);
|
||||||
|
First = false;
|
||||||
|
}
|
||||||
|
if (!First)
|
||||||
|
OS << "), ";
|
||||||
|
if (Node->getIsTarget())
|
||||||
|
OS << "target";
|
||||||
|
if (Node->getIsTargetSync()) {
|
||||||
|
if (Node->getIsTarget())
|
||||||
|
OS << ", ";
|
||||||
|
OS << "targetsync";
|
||||||
|
}
|
||||||
|
OS << " : ";
|
||||||
|
Node->getInteropVar()->printPretty(OS, nullptr, Policy);
|
||||||
|
OS << ")";
|
||||||
|
}
|
||||||
|
|
||||||
void OMPClausePrinter::VisitOMPDestroyClause(OMPDestroyClause *) {
|
void OMPClausePrinter::VisitOMPDestroyClause(OMPDestroyClause *) {
|
||||||
OS << "destroy";
|
OS << "destroy";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1944,3 +1944,18 @@ OMPTargetTeamsDistributeSimdDirective::CreateEmpty(const ASTContext &C,
|
||||||
numLoopChildren(CollapsedNum, OMPD_target_teams_distribute_simd),
|
numLoopChildren(CollapsedNum, OMPD_target_teams_distribute_simd),
|
||||||
CollapsedNum);
|
CollapsedNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OMPInteropDirective *
|
||||||
|
OMPInteropDirective::Create(const ASTContext &C, SourceLocation StartLoc,
|
||||||
|
SourceLocation EndLoc,
|
||||||
|
ArrayRef<OMPClause *> Clauses) {
|
||||||
|
return createDirective<OMPInteropDirective>(
|
||||||
|
C, Clauses, /*AssociatedStmt=*/nullptr, /*NumChildren=*/0, StartLoc,
|
||||||
|
EndLoc);
|
||||||
|
}
|
||||||
|
|
||||||
|
OMPInteropDirective *OMPInteropDirective::CreateEmpty(const ASTContext &C,
|
||||||
|
unsigned NumClauses,
|
||||||
|
EmptyShell) {
|
||||||
|
return createEmptyDirective<OMPInteropDirective>(C, NumClauses);
|
||||||
|
}
|
||||||
|
|
|
@ -962,6 +962,11 @@ void StmtPrinter::VisitOMPTargetTeamsDistributeSimdDirective(
|
||||||
PrintOMPExecutableDirective(Node);
|
PrintOMPExecutableDirective(Node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StmtPrinter::VisitOMPInteropDirective(OMPInteropDirective *Node) {
|
||||||
|
Indent() << "#pragma omp interop";
|
||||||
|
PrintOMPExecutableDirective(Node);
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Expr printing methods.
|
// Expr printing methods.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
@ -543,6 +543,10 @@ void OMPClauseProfiler::VisitOMPSIMDClause(const OMPSIMDClause *) {}
|
||||||
|
|
||||||
void OMPClauseProfiler::VisitOMPNogroupClause(const OMPNogroupClause *) {}
|
void OMPClauseProfiler::VisitOMPNogroupClause(const OMPNogroupClause *) {}
|
||||||
|
|
||||||
|
void OMPClauseProfiler::VisitOMPInitClause(const OMPInitClause *C) {
|
||||||
|
VisitOMPClauseList(C);
|
||||||
|
}
|
||||||
|
|
||||||
void OMPClauseProfiler::VisitOMPDestroyClause(const OMPDestroyClause *) {}
|
void OMPClauseProfiler::VisitOMPDestroyClause(const OMPDestroyClause *) {}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -1128,6 +1132,10 @@ void StmtProfiler::VisitOMPTargetTeamsDistributeSimdDirective(
|
||||||
VisitOMPLoopDirective(S);
|
VisitOMPLoopDirective(S);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StmtProfiler::VisitOMPInteropDirective(const OMPInteropDirective *S) {
|
||||||
|
VisitOMPExecutableDirective(S);
|
||||||
|
}
|
||||||
|
|
||||||
void StmtProfiler::VisitExpr(const Expr *S) {
|
void StmtProfiler::VisitExpr(const Expr *S) {
|
||||||
VisitStmt(S);
|
VisitStmt(S);
|
||||||
}
|
}
|
||||||
|
|
|
@ -375,6 +375,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
|
||||||
EmitOMPTargetTeamsDistributeSimdDirective(
|
EmitOMPTargetTeamsDistributeSimdDirective(
|
||||||
cast<OMPTargetTeamsDistributeSimdDirective>(*S));
|
cast<OMPTargetTeamsDistributeSimdDirective>(*S));
|
||||||
break;
|
break;
|
||||||
|
case Stmt::OMPInteropDirectiveClass:
|
||||||
|
llvm_unreachable("Interop directive not supported yet.");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2378,6 +2378,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
|
||||||
case OMPD_target_enter_data:
|
case OMPD_target_enter_data:
|
||||||
case OMPD_target_exit_data:
|
case OMPD_target_exit_data:
|
||||||
case OMPD_target_update:
|
case OMPD_target_update:
|
||||||
|
case OMPD_interop:
|
||||||
if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
|
if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
|
||||||
ParsedStmtContext()) {
|
ParsedStmtContext()) {
|
||||||
Diag(Tok, diag::err_omp_immediate_directive)
|
Diag(Tok, diag::err_omp_immediate_directive)
|
||||||
|
@ -2928,6 +2929,9 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
|
||||||
case OMPC_uses_allocators:
|
case OMPC_uses_allocators:
|
||||||
Clause = ParseOpenMPUsesAllocatorClause(DKind);
|
Clause = ParseOpenMPUsesAllocatorClause(DKind);
|
||||||
break;
|
break;
|
||||||
|
case OMPC_init:
|
||||||
|
Clause = ParseOpenMPInteropClause(CKind, WrongDirective);
|
||||||
|
break;
|
||||||
case OMPC_device_type:
|
case OMPC_device_type:
|
||||||
case OMPC_unknown:
|
case OMPC_unknown:
|
||||||
skipUntilPragmaOpenMPEnd(DKind);
|
skipUntilPragmaOpenMPEnd(DKind);
|
||||||
|
@ -3024,6 +3028,137 @@ OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
|
||||||
return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
|
return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parsing of OpenMP clauses that use an interop-var.
|
||||||
|
///
|
||||||
|
/// init-clause:
|
||||||
|
/// init([interop-modifier, ]interop-type[[, interop-type] ... ]:interop-var)
|
||||||
|
///
|
||||||
|
/// destroy-clause:
|
||||||
|
/// destroy(interop-var)
|
||||||
|
///
|
||||||
|
/// use-clause:
|
||||||
|
/// use(interop-var)
|
||||||
|
///
|
||||||
|
/// interop-modifier:
|
||||||
|
/// prefer_type(preference-list)
|
||||||
|
///
|
||||||
|
/// preference-list:
|
||||||
|
/// foreign-runtime-id [, foreign-runtime-id]...
|
||||||
|
///
|
||||||
|
/// foreign-runtime-id:
|
||||||
|
/// <string-literal> | <constant-integral-expression>
|
||||||
|
///
|
||||||
|
/// interop-type:
|
||||||
|
/// target | targetsync
|
||||||
|
///
|
||||||
|
OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind,
|
||||||
|
bool ParseOnly) {
|
||||||
|
SourceLocation Loc = ConsumeToken();
|
||||||
|
// Parse '('.
|
||||||
|
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
||||||
|
if (T.expectAndConsume(diag::err_expected_lparen_after,
|
||||||
|
getOpenMPClauseName(Kind).data()))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
bool IsTarget = false;
|
||||||
|
bool IsTargetSync = false;
|
||||||
|
SmallVector<Expr *, 4> Prefs;
|
||||||
|
|
||||||
|
if (Kind == OMPC_init) {
|
||||||
|
|
||||||
|
// Parse optional interop-modifier.
|
||||||
|
if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "prefer_type") {
|
||||||
|
ConsumeToken();
|
||||||
|
BalancedDelimiterTracker PT(*this, tok::l_paren,
|
||||||
|
tok::annot_pragma_openmp_end);
|
||||||
|
if (PT.expectAndConsume(diag::err_expected_lparen_after, "prefer_type"))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
while (Tok.isNot(tok::r_paren)) {
|
||||||
|
SourceLocation Loc = Tok.getLocation();
|
||||||
|
ExprResult LHS = ParseCastExpression(AnyCastExpr);
|
||||||
|
ExprResult PTExpr = Actions.CorrectDelayedTyposInExpr(
|
||||||
|
ParseRHSOfBinaryExpression(LHS, prec::Conditional));
|
||||||
|
PTExpr = Actions.ActOnFinishFullExpr(PTExpr.get(), Loc,
|
||||||
|
/*DiscardedValue=*/false);
|
||||||
|
if (PTExpr.isUsable())
|
||||||
|
Prefs.push_back(PTExpr.get());
|
||||||
|
else
|
||||||
|
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
|
||||||
|
StopBeforeMatch);
|
||||||
|
|
||||||
|
if (Tok.is(tok::comma))
|
||||||
|
ConsumeToken();
|
||||||
|
}
|
||||||
|
PT.consumeClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Prefs.empty()) {
|
||||||
|
if (Tok.is(tok::comma))
|
||||||
|
ConsumeToken();
|
||||||
|
else
|
||||||
|
Diag(Tok, diag::err_omp_expected_punc_after_interop_mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the interop-types.
|
||||||
|
bool HasError = false;
|
||||||
|
while (Tok.is(tok::identifier)) {
|
||||||
|
if (PP.getSpelling(Tok) == "target") {
|
||||||
|
// OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
|
||||||
|
// Each interop-type may be specified on an action-clause at most
|
||||||
|
// once.
|
||||||
|
if (IsTarget)
|
||||||
|
Diag(Tok, diag::warn_omp_more_one_interop_type) << "target";
|
||||||
|
IsTarget = true;
|
||||||
|
} else if (PP.getSpelling(Tok) == "targetsync") {
|
||||||
|
if (IsTargetSync)
|
||||||
|
Diag(Tok, diag::warn_omp_more_one_interop_type) << "targetsync";
|
||||||
|
IsTargetSync = true;
|
||||||
|
} else {
|
||||||
|
HasError = true;
|
||||||
|
Diag(Tok, diag::err_omp_expected_interop_type);
|
||||||
|
}
|
||||||
|
ConsumeToken();
|
||||||
|
|
||||||
|
if (!Tok.is(tok::comma))
|
||||||
|
break;
|
||||||
|
ConsumeToken();
|
||||||
|
}
|
||||||
|
if (!HasError && !IsTarget && !IsTargetSync)
|
||||||
|
Diag(Tok, diag::err_omp_expected_interop_type);
|
||||||
|
|
||||||
|
if (Tok.is(tok::colon))
|
||||||
|
ConsumeToken();
|
||||||
|
else if (IsTarget || IsTargetSync)
|
||||||
|
Diag(Tok, diag::warn_pragma_expected_colon) << "interop types";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the variable.
|
||||||
|
SourceLocation VarLoc = Tok.getLocation();
|
||||||
|
ExprResult InteropVarExpr =
|
||||||
|
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
|
||||||
|
if (!InteropVarExpr.isUsable()) {
|
||||||
|
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
|
||||||
|
StopBeforeMatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse ')'.
|
||||||
|
SourceLocation RLoc = Tok.getLocation();
|
||||||
|
if (!T.consumeClose())
|
||||||
|
RLoc = T.getCloseLocation();
|
||||||
|
|
||||||
|
if (ParseOnly || !InteropVarExpr.isUsable() ||
|
||||||
|
(Kind == OMPC_init && !IsTarget && !IsTargetSync))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (Kind == OMPC_init)
|
||||||
|
return Actions.ActOnOpenMPInitClause(InteropVarExpr.get(), Prefs, IsTarget,
|
||||||
|
IsTargetSync, Loc, T.getOpenLocation(),
|
||||||
|
VarLoc, RLoc);
|
||||||
|
|
||||||
|
llvm_unreachable("Unexpected interop variable clause.");
|
||||||
|
}
|
||||||
|
|
||||||
/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
|
/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
|
||||||
///
|
///
|
||||||
/// default-clause:
|
/// default-clause:
|
||||||
|
|
|
@ -1486,6 +1486,7 @@ CanThrowResult Sema::canThrow(const Stmt *S) {
|
||||||
case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
|
case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
|
||||||
case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
|
case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
|
||||||
case Stmt::OMPTeamsDistributeSimdDirectiveClass:
|
case Stmt::OMPTeamsDistributeSimdDirectiveClass:
|
||||||
|
case Stmt::OMPInteropDirectiveClass:
|
||||||
case Stmt::ReturnStmtClass:
|
case Stmt::ReturnStmtClass:
|
||||||
case Stmt::SEHExceptStmtClass:
|
case Stmt::SEHExceptStmtClass:
|
||||||
case Stmt::SEHFinallyStmtClass:
|
case Stmt::SEHFinallyStmtClass:
|
||||||
|
|
|
@ -6115,6 +6115,11 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
|
||||||
if (LangOpts.OpenMP >= 50)
|
if (LangOpts.OpenMP >= 50)
|
||||||
AllowedNameModifiers.push_back(OMPD_simd);
|
AllowedNameModifiers.push_back(OMPD_simd);
|
||||||
break;
|
break;
|
||||||
|
case OMPD_interop:
|
||||||
|
assert(AStmt == nullptr &&
|
||||||
|
"No associated statement allowed for 'omp interop' directive");
|
||||||
|
Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
|
||||||
|
break;
|
||||||
case OMPD_declare_target:
|
case OMPD_declare_target:
|
||||||
case OMPD_end_declare_target:
|
case OMPD_end_declare_target:
|
||||||
case OMPD_threadprivate:
|
case OMPD_threadprivate:
|
||||||
|
@ -13347,6 +13352,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
|
||||||
CaptureRegion = OMPD_task;
|
CaptureRegion = OMPD_task;
|
||||||
break;
|
break;
|
||||||
case OMPD_target_data:
|
case OMPD_target_data:
|
||||||
|
case OMPD_interop:
|
||||||
// Do not capture device-clause expressions.
|
// Do not capture device-clause expressions.
|
||||||
break;
|
break;
|
||||||
case OMPD_teams_distribute_parallel_for:
|
case OMPD_teams_distribute_parallel_for:
|
||||||
|
@ -14598,6 +14604,155 @@ OMPClause *Sema::ActOnOpenMPDestroyClause(SourceLocation StartLoc,
|
||||||
return new (Context) OMPDestroyClause(StartLoc, EndLoc);
|
return new (Context) OMPDestroyClause(StartLoc, EndLoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StmtResult Sema::ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses,
|
||||||
|
SourceLocation StartLoc,
|
||||||
|
SourceLocation EndLoc) {
|
||||||
|
|
||||||
|
// OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
|
||||||
|
// At least one action-clause must appear on a directive.
|
||||||
|
// TODO: also add 'use' and 'destroy' here.
|
||||||
|
if (!hasClauses(Clauses, OMPC_init, OMPC_nowait)) {
|
||||||
|
StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
|
||||||
|
Diag(StartLoc, diag::err_omp_no_clause_for_directive)
|
||||||
|
<< Expected << getOpenMPDirectiveName(OMPD_interop);
|
||||||
|
return StmtError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
|
||||||
|
// A depend clause can only appear on the directive if a targetsync
|
||||||
|
// interop-type is present or the interop-var was initialized with
|
||||||
|
// the targetsync interop-type.
|
||||||
|
|
||||||
|
// If there is any 'init' clause diagnose if there is no 'init' clause with
|
||||||
|
// interop-type of 'targetsync'. Cases involving other directives cannot be
|
||||||
|
// diagnosed.
|
||||||
|
const OMPDependClause *DependClause = nullptr;
|
||||||
|
bool IsTargetSync = false;
|
||||||
|
for (const OMPClause *C : Clauses) {
|
||||||
|
if (IsTargetSync)
|
||||||
|
break;
|
||||||
|
if (const auto *InitClause = dyn_cast<OMPInitClause>(C))
|
||||||
|
IsTargetSync = InitClause->getIsTargetSync();
|
||||||
|
else if (const auto *DC = dyn_cast<OMPDependClause>(C))
|
||||||
|
DependClause = DC;
|
||||||
|
}
|
||||||
|
if (DependClause && !IsTargetSync) {
|
||||||
|
Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
|
||||||
|
return StmtError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
|
||||||
|
// Each interop-var may be specified for at most one action-clause of each
|
||||||
|
// interop construct.
|
||||||
|
llvm::SmallPtrSet<const VarDecl *, 4> InteropVars;
|
||||||
|
for (const OMPClause *C : Clauses) {
|
||||||
|
OpenMPClauseKind ClauseKind = C->getClauseKind();
|
||||||
|
const DeclRefExpr *DRE = nullptr;
|
||||||
|
SourceLocation VarLoc;
|
||||||
|
|
||||||
|
if (ClauseKind == OMPC_init) {
|
||||||
|
const auto *IC = cast<OMPInitClause>(C);
|
||||||
|
VarLoc = IC->getVarLoc();
|
||||||
|
DRE = dyn_cast_or_null<DeclRefExpr>(IC->getInteropVar());
|
||||||
|
}
|
||||||
|
// TODO: 'use' and 'destroy' clauses to be added here.
|
||||||
|
|
||||||
|
if (!DRE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
|
||||||
|
if (!InteropVars.insert(VD->getCanonicalDecl()).second) {
|
||||||
|
Diag(VarLoc, diag::err_omp_interop_var_multiple_actions) << VD;
|
||||||
|
return StmtError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return OMPInteropDirective::Create(Context, StartLoc, EndLoc, Clauses);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
|
||||||
|
SourceLocation VarLoc,
|
||||||
|
OpenMPClauseKind Kind) {
|
||||||
|
if (InteropVarExpr->isValueDependent() || InteropVarExpr->isTypeDependent() ||
|
||||||
|
InteropVarExpr->isInstantiationDependent() ||
|
||||||
|
InteropVarExpr->containsUnexpandedParameterPack())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
const auto *DRE = dyn_cast<DeclRefExpr>(InteropVarExpr);
|
||||||
|
if (!DRE || !isa<VarDecl>(DRE->getDecl())) {
|
||||||
|
SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected) << 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interop variable should be of type omp_interop_t.
|
||||||
|
bool HasError = false;
|
||||||
|
QualType InteropType;
|
||||||
|
LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
|
||||||
|
VarLoc, Sema::LookupOrdinaryName);
|
||||||
|
if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
|
||||||
|
NamedDecl *ND = Result.getFoundDecl();
|
||||||
|
if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
|
||||||
|
InteropType = QualType(TD->getTypeForDecl(), 0);
|
||||||
|
} else {
|
||||||
|
HasError = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
HasError = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasError) {
|
||||||
|
SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
|
||||||
|
<< "omp_interop_t";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
|
||||||
|
if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
|
||||||
|
SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
|
||||||
|
// The interop-var passed to init or destroy must be non-const.
|
||||||
|
// TODO: 'destroy' clause too.
|
||||||
|
if (Kind == OMPC_init &&
|
||||||
|
isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
|
||||||
|
SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
|
||||||
|
<< /*non-const*/ 1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
OMPClause *
|
||||||
|
Sema::ActOnOpenMPInitClause(Expr *InteropVar, ArrayRef<Expr *> PrefExprs,
|
||||||
|
bool IsTarget, bool IsTargetSync,
|
||||||
|
SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||||
|
SourceLocation VarLoc, SourceLocation EndLoc) {
|
||||||
|
|
||||||
|
if (!isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_init))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// Check prefer_type values. These foreign-runtime-id values are either
|
||||||
|
// string literals or constant integral expressions.
|
||||||
|
for (const Expr *E : PrefExprs) {
|
||||||
|
if (E->isValueDependent() || E->isTypeDependent() ||
|
||||||
|
E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
|
||||||
|
continue;
|
||||||
|
if (E->isIntegerConstantExpr(Context))
|
||||||
|
continue;
|
||||||
|
if (isa<StringLiteral>(E))
|
||||||
|
continue;
|
||||||
|
Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OMPInitClause::Create(Context, InteropVar, PrefExprs, IsTarget,
|
||||||
|
IsTargetSync, StartLoc, LParenLoc, VarLoc,
|
||||||
|
EndLoc);
|
||||||
|
}
|
||||||
|
|
||||||
OMPClause *Sema::ActOnOpenMPVarListClause(
|
OMPClause *Sema::ActOnOpenMPVarListClause(
|
||||||
OpenMPClauseKind Kind, ArrayRef<Expr *> VarList, Expr *DepModOrTailExpr,
|
OpenMPClauseKind Kind, ArrayRef<Expr *> VarList, Expr *DepModOrTailExpr,
|
||||||
const OMPVarListLocTy &Locs, SourceLocation ColonLoc,
|
const OMPVarListLocTy &Locs, SourceLocation ColonLoc,
|
||||||
|
|
|
@ -2170,6 +2170,21 @@ public:
|
||||||
LParenLoc, EndLoc);
|
LParenLoc, EndLoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Build a new OpenMP 'init' clause.
|
||||||
|
///
|
||||||
|
/// By default, performs semantic analysis to build the new OpenMP clause.
|
||||||
|
/// Subclasses may override this routine to provide different behavior.
|
||||||
|
OMPClause *RebuildOMPInitClause(Expr *InteropVar, ArrayRef<Expr *> PrefExprs,
|
||||||
|
bool IsTarget, bool IsTargetSync,
|
||||||
|
SourceLocation StartLoc,
|
||||||
|
SourceLocation LParenLoc,
|
||||||
|
SourceLocation VarLoc,
|
||||||
|
SourceLocation EndLoc) {
|
||||||
|
return getSema().ActOnOpenMPInitClause(InteropVar, PrefExprs, IsTarget,
|
||||||
|
IsTargetSync, StartLoc, LParenLoc,
|
||||||
|
VarLoc, EndLoc);
|
||||||
|
}
|
||||||
|
|
||||||
/// Rebuild the operand to an Objective-C \@synchronized statement.
|
/// Rebuild the operand to an Objective-C \@synchronized statement.
|
||||||
///
|
///
|
||||||
/// By default, performs semantic analysis to build the new statement.
|
/// By default, performs semantic analysis to build the new statement.
|
||||||
|
@ -9020,6 +9035,16 @@ TreeTransform<Derived>::TransformOMPTargetTeamsDistributeSimdDirective(
|
||||||
return Res;
|
return Res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Derived>
|
||||||
|
StmtResult
|
||||||
|
TreeTransform<Derived>::TransformOMPInteropDirective(OMPInteropDirective *D) {
|
||||||
|
DeclarationNameInfo DirName;
|
||||||
|
getDerived().getSema().StartOpenMPDSABlock(OMPD_interop, DirName, nullptr,
|
||||||
|
D->getBeginLoc());
|
||||||
|
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
|
||||||
|
getDerived().getSema().EndOpenMPDSABlock(Res.get());
|
||||||
|
return Res;
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// OpenMP clause transformation
|
// OpenMP clause transformation
|
||||||
|
@ -9275,6 +9300,25 @@ TreeTransform<Derived>::TransformOMPNogroupClause(OMPNogroupClause *C) {
|
||||||
return C;
|
return C;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Derived>
|
||||||
|
OMPClause *TreeTransform<Derived>::TransformOMPInitClause(OMPInitClause *C) {
|
||||||
|
ExprResult IVR = getDerived().TransformExpr(C->getInteropVar());
|
||||||
|
if (IVR.isInvalid())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
llvm::SmallVector<Expr *, 8> PrefExprs;
|
||||||
|
PrefExprs.reserve(C->varlist_size() - 1);
|
||||||
|
for (Expr *E : llvm::drop_begin(C->varlists())) {
|
||||||
|
ExprResult ER = getDerived().TransformExpr(cast<Expr>(E));
|
||||||
|
if (ER.isInvalid())
|
||||||
|
return nullptr;
|
||||||
|
PrefExprs.push_back(ER.get());
|
||||||
|
}
|
||||||
|
return getDerived().RebuildOMPInitClause(
|
||||||
|
IVR.get(), PrefExprs, C->getIsTarget(), C->getIsTargetSync(),
|
||||||
|
C->getBeginLoc(), C->getLParenLoc(), C->getVarLoc(), C->getEndLoc());
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Derived>
|
template <typename Derived>
|
||||||
OMPClause *
|
OMPClause *
|
||||||
TreeTransform<Derived>::TransformOMPDestroyClause(OMPDestroyClause *C) {
|
TreeTransform<Derived>::TransformOMPDestroyClause(OMPDestroyClause *C) {
|
||||||
|
|
|
@ -11968,6 +11968,9 @@ OMPClause *OMPClauseReader::readClause() {
|
||||||
case llvm::omp::OMPC_order:
|
case llvm::omp::OMPC_order:
|
||||||
C = new (Context) OMPOrderClause();
|
C = new (Context) OMPOrderClause();
|
||||||
break;
|
break;
|
||||||
|
case llvm::omp::OMPC_init:
|
||||||
|
C = OMPInitClause::CreateEmpty(Context, Record.readInt());
|
||||||
|
break;
|
||||||
case llvm::omp::OMPC_destroy:
|
case llvm::omp::OMPC_destroy:
|
||||||
C = new (Context) OMPDestroyClause();
|
C = new (Context) OMPDestroyClause();
|
||||||
break;
|
break;
|
||||||
|
@ -12131,6 +12134,19 @@ void OMPClauseReader::VisitOMPSIMDClause(OMPSIMDClause *) {}
|
||||||
|
|
||||||
void OMPClauseReader::VisitOMPNogroupClause(OMPNogroupClause *) {}
|
void OMPClauseReader::VisitOMPNogroupClause(OMPNogroupClause *) {}
|
||||||
|
|
||||||
|
void OMPClauseReader::VisitOMPInitClause(OMPInitClause *C) {
|
||||||
|
unsigned NumVars = C->varlist_size();
|
||||||
|
SmallVector<Expr *, 16> Vars;
|
||||||
|
Vars.reserve(NumVars);
|
||||||
|
for (unsigned I = 0; I != NumVars; ++I)
|
||||||
|
Vars.push_back(Record.readSubExpr());
|
||||||
|
C->setVarRefs(Vars);
|
||||||
|
C->setIsTarget(Record.readBool());
|
||||||
|
C->setIsTargetSync(Record.readBool());
|
||||||
|
C->setLParenLoc(Record.readSourceLocation());
|
||||||
|
C->setVarLoc(Record.readSourceLocation());
|
||||||
|
}
|
||||||
|
|
||||||
void OMPClauseReader::VisitOMPDestroyClause(OMPDestroyClause *) {}
|
void OMPClauseReader::VisitOMPDestroyClause(OMPDestroyClause *) {}
|
||||||
|
|
||||||
void OMPClauseReader::VisitOMPUnifiedAddressClause(OMPUnifiedAddressClause *) {}
|
void OMPClauseReader::VisitOMPUnifiedAddressClause(OMPUnifiedAddressClause *) {}
|
||||||
|
|
|
@ -2588,6 +2588,11 @@ void ASTStmtReader::VisitOMPTargetTeamsDistributeSimdDirective(
|
||||||
VisitOMPLoopDirective(D);
|
VisitOMPLoopDirective(D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ASTStmtReader::VisitOMPInteropDirective(OMPInteropDirective *D) {
|
||||||
|
VisitStmt(D);
|
||||||
|
VisitOMPExecutableDirective(D);
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// ASTReader Implementation
|
// ASTReader Implementation
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -3503,6 +3508,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case STMT_OMP_INTEROP_DIRECTIVE:
|
||||||
|
S = OMPInteropDirective::CreateEmpty(
|
||||||
|
Context, Record[ASTStmtReader::NumStmtFields], Empty);
|
||||||
|
break;
|
||||||
|
|
||||||
case EXPR_CXX_OPERATOR_CALL:
|
case EXPR_CXX_OPERATOR_CALL:
|
||||||
S = CXXOperatorCallExpr::CreateEmpty(
|
S = CXXOperatorCallExpr::CreateEmpty(
|
||||||
Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields],
|
Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields],
|
||||||
|
|
|
@ -6215,6 +6215,16 @@ void OMPClauseWriter::VisitOMPSIMDClause(OMPSIMDClause *) {}
|
||||||
|
|
||||||
void OMPClauseWriter::VisitOMPNogroupClause(OMPNogroupClause *) {}
|
void OMPClauseWriter::VisitOMPNogroupClause(OMPNogroupClause *) {}
|
||||||
|
|
||||||
|
void OMPClauseWriter::VisitOMPInitClause(OMPInitClause *C) {
|
||||||
|
Record.push_back(C->varlist_size());
|
||||||
|
for (Expr *VE : C->varlists())
|
||||||
|
Record.AddStmt(VE);
|
||||||
|
Record.writeBool(C->getIsTarget());
|
||||||
|
Record.writeBool(C->getIsTargetSync());
|
||||||
|
Record.AddSourceLocation(C->getLParenLoc());
|
||||||
|
Record.AddSourceLocation(C->getVarLoc());
|
||||||
|
}
|
||||||
|
|
||||||
void OMPClauseWriter::VisitOMPDestroyClause(OMPDestroyClause *) {}
|
void OMPClauseWriter::VisitOMPDestroyClause(OMPDestroyClause *) {}
|
||||||
|
|
||||||
void OMPClauseWriter::VisitOMPPrivateClause(OMPPrivateClause *C) {
|
void OMPClauseWriter::VisitOMPPrivateClause(OMPPrivateClause *C) {
|
||||||
|
|
|
@ -2541,6 +2541,12 @@ void ASTStmtWriter::VisitOMPTargetTeamsDistributeSimdDirective(
|
||||||
Code = serialization::STMT_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE;
|
Code = serialization::STMT_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ASTStmtWriter::VisitOMPInteropDirective(OMPInteropDirective *D) {
|
||||||
|
VisitStmt(D);
|
||||||
|
VisitOMPExecutableDirective(D);
|
||||||
|
Code = serialization::STMT_OMP_INTEROP_DIRECTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// ASTWriter Implementation
|
// ASTWriter Implementation
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
@ -1294,6 +1294,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
|
||||||
case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
|
case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
|
||||||
case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
|
case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
|
||||||
case Stmt::OMPTileDirectiveClass:
|
case Stmt::OMPTileDirectiveClass:
|
||||||
|
case Stmt::OMPInteropDirectiveClass:
|
||||||
case Stmt::CapturedStmtClass: {
|
case Stmt::CapturedStmtClass: {
|
||||||
const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
|
const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
|
||||||
Engine.addAbortedBlock(node, currBldrCtx->getBlock());
|
Engine.addAbortedBlock(node, currBldrCtx->getBlock());
|
||||||
|
|
|
@ -0,0 +1,169 @@
|
||||||
|
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \
|
||||||
|
// RUN: -fsyntax-only -verify %s
|
||||||
|
|
||||||
|
// expected-no-diagnostics
|
||||||
|
|
||||||
|
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \
|
||||||
|
// RUN: -ast-print %s | FileCheck %s --check-prefix=PRINT
|
||||||
|
|
||||||
|
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \
|
||||||
|
// RUN: -ast-dump %s | FileCheck %s --check-prefix=DUMP
|
||||||
|
|
||||||
|
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \
|
||||||
|
// RUN: -emit-pch -o %t %s
|
||||||
|
|
||||||
|
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \
|
||||||
|
// RUN: -include-pch %t -ast-dump-all %s | FileCheck %s --check-prefix=DUMP
|
||||||
|
|
||||||
|
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \
|
||||||
|
// RUN: -include-pch %t -ast-print %s | FileCheck %s --check-prefix=PRINT
|
||||||
|
|
||||||
|
#ifndef HEADER
|
||||||
|
#define HEADER
|
||||||
|
|
||||||
|
typedef void *omp_interop_t;
|
||||||
|
|
||||||
|
//PRINT-LABEL: void foo1(
|
||||||
|
//DUMP-LABEL: FunctionDecl {{.*}} foo1
|
||||||
|
void foo1(int *ap, int dev) {
|
||||||
|
omp_interop_t I;
|
||||||
|
omp_interop_t &IRef = I;
|
||||||
|
|
||||||
|
//PRINT: #pragma omp interop init(target : I)
|
||||||
|
//DUMP: OMPInteropDirective
|
||||||
|
//DUMP: OMPInitClause
|
||||||
|
//DUMP: DeclRefExpr{{.*}}'omp_interop_t'{{.*}}Var{{.*}}'I'
|
||||||
|
#pragma omp interop init(target:I)
|
||||||
|
|
||||||
|
//PRINT: #pragma omp interop init(target : IRef)
|
||||||
|
//DUMP: OMPInteropDirective
|
||||||
|
//DUMP: OMPInitClause
|
||||||
|
//DUMP: DeclRefExpr{{.*}}'omp_interop_t'{{.*}}Var{{.*}}'IRef'
|
||||||
|
#pragma omp interop init(target:IRef)
|
||||||
|
|
||||||
|
//PRINT: #pragma omp interop device(dev) depend(inout : ap) init(targetsync : I)
|
||||||
|
//DUMP: OMPInteropDirective
|
||||||
|
//DUMP: OMPDeviceClause
|
||||||
|
//DUMP: DeclRefExpr{{.*}}'dev' 'int'
|
||||||
|
//DUMP: OMPDependClause
|
||||||
|
//DUMP: DeclRefExpr{{.*}}'ap' 'int *'
|
||||||
|
//DUMP: OMPInitClause
|
||||||
|
//DUMP: DeclRefExpr{{.*}}'omp_interop_t'{{.*}}Var{{.*}}'I'
|
||||||
|
#pragma omp interop device(dev) depend(inout:ap) init(targetsync:I)
|
||||||
|
|
||||||
|
//PRINT: #pragma omp interop init(prefer_type(1,2,3,4,5,6), targetsync : I)
|
||||||
|
//DUMP: OMPInteropDirective
|
||||||
|
//DUMP: OMPInitClause
|
||||||
|
//DUMP: DeclRefExpr{{.*}}'omp_interop_t'{{.*}}Var{{.*}}'I'
|
||||||
|
//DUMP: IntegerLiteral{{.*}}1
|
||||||
|
//DUMP: IntegerLiteral{{.*}}2
|
||||||
|
//DUMP: IntegerLiteral{{.*}}3
|
||||||
|
//DUMP: IntegerLiteral{{.*}}4
|
||||||
|
//DUMP: IntegerLiteral{{.*}}5
|
||||||
|
//DUMP: IntegerLiteral{{.*}}6
|
||||||
|
#pragma omp interop init(prefer_type(1,2,3,4,5,6),targetsync:I)
|
||||||
|
|
||||||
|
//PRINT: #pragma omp interop init(prefer_type(2,4,6,1), targetsync : I)
|
||||||
|
//DUMP: OMPInteropDirective
|
||||||
|
//DUMP: OMPInitClause
|
||||||
|
//DUMP: DeclRefExpr{{.*}}'omp_interop_t'{{.*}}Var{{.*}}'I'
|
||||||
|
//DUMP: IntegerLiteral{{.*}}2
|
||||||
|
//DUMP: IntegerLiteral{{.*}}4
|
||||||
|
//DUMP: IntegerLiteral{{.*}}6
|
||||||
|
//DUMP: IntegerLiteral{{.*}}1
|
||||||
|
#pragma omp interop init(prefer_type(2,4,6,1),targetsync:I)
|
||||||
|
|
||||||
|
//PRINT: #pragma omp interop init(prefer_type("cuda","cuda_driver","opencl","sycl","hip","level_zero"), targetsync : I)
|
||||||
|
//DUMP: OMPInteropDirective
|
||||||
|
//DUMP: OMPInitClause
|
||||||
|
//DUMP: DeclRefExpr{{.*}}'omp_interop_t'{{.*}}Var{{.*}}'I'
|
||||||
|
//DUMP: StringLiteral{{.*}}"cuda"
|
||||||
|
//DUMP: StringLiteral{{.*}}"cuda_driver"
|
||||||
|
//DUMP: StringLiteral{{.*}}"opencl"
|
||||||
|
//DUMP: StringLiteral{{.*}}"sycl"
|
||||||
|
//DUMP: StringLiteral{{.*}}"hip"
|
||||||
|
//DUMP: StringLiteral{{.*}}"level_zero"
|
||||||
|
#pragma omp interop init( \
|
||||||
|
prefer_type("cuda","cuda_driver","opencl","sycl","hip","level_zero"), \
|
||||||
|
targetsync:I)
|
||||||
|
|
||||||
|
//PRINT: #pragma omp interop init(prefer_type("level_zero",2,4), targetsync : I)
|
||||||
|
//DUMP: OMPInteropDirective
|
||||||
|
//DUMP: OMPInitClause
|
||||||
|
//DUMP: DeclRefExpr{{.*}}'omp_interop_t'{{.*}}Var{{.*}}'I'
|
||||||
|
//DUMP: StringLiteral{{.*}}"level_zero"
|
||||||
|
//DUMP: IntegerLiteral{{.*}}2
|
||||||
|
//DUMP: IntegerLiteral{{.*}}4
|
||||||
|
#pragma omp interop init(prefer_type("level_zero",2,4),targetsync:I)
|
||||||
|
|
||||||
|
omp_interop_t J;
|
||||||
|
|
||||||
|
//PRINT: #pragma omp interop init(target : I) init(targetsync : J)
|
||||||
|
//DUMP: OMPInteropDirective
|
||||||
|
//DUMP: OMPInitClause
|
||||||
|
//DUMP: DeclRefExpr{{.*}}'omp_interop_t'{{.*}}Var{{.*}}'I'
|
||||||
|
//DUMP: OMPInitClause
|
||||||
|
//DUMP: DeclRefExpr{{.*}}'omp_interop_t'{{.*}}Var{{.*}}'J'
|
||||||
|
#pragma omp interop init(target:I) init(targetsync:J)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//DUMP: FunctionTemplateDecl{{.*}}fooTemp
|
||||||
|
//DUMP-NEXT: NonTypeTemplateParmDecl{{.*}}'int{{.*}}I
|
||||||
|
template <int I>
|
||||||
|
void fooTemp() {
|
||||||
|
omp_interop_t interop_var;
|
||||||
|
//PRINT: #pragma omp interop init(prefer_type(I,4,"level_one"), target : interop_var)
|
||||||
|
//DUMP: FunctionDecl{{.*}}fooTemp
|
||||||
|
//DUMP: OMPInteropDirective
|
||||||
|
//DUMP: OMPInitClause
|
||||||
|
//DUMP: DeclRefExpr{{.*}}'omp_interop_t'{{.*}}'interop_var'
|
||||||
|
//DUMP: DeclRefExpr{{.*}}NonTypeTemplateParm{{.*}}'I' 'int'
|
||||||
|
//DUMP: IntegerLiteral{{.*}}'int' 4
|
||||||
|
//DUMP: StringLiteral{{.*}}"level_one"
|
||||||
|
|
||||||
|
//PRINT: #pragma omp interop init(prefer_type(3,4,"level_one"), target : interop_var)
|
||||||
|
//DUMP: FunctionDecl{{.*}}fooTemp
|
||||||
|
//DUMP: TemplateArgument integral 3
|
||||||
|
//DUMP: OMPInteropDirective
|
||||||
|
//DUMP: OMPInitClause
|
||||||
|
//DUMP: DeclRefExpr{{.*}}'omp_interop_t'{{.*}}'interop_var'
|
||||||
|
//DUMP: SubstNonTypeTemplateParmExpr{{.*}}'int'
|
||||||
|
//DUMP: NonTypeTemplateParmDecl{{.*}}'int'{{.*}}I
|
||||||
|
//DUMP: IntegerLiteral{{.*}}'int' 3
|
||||||
|
//DUMP: IntegerLiteral{{.*}}'int' 4
|
||||||
|
//DUMP: StringLiteral{{.*}}"level_one"
|
||||||
|
#pragma omp interop init(prefer_type(I,4,"level_one"), target: interop_var)
|
||||||
|
}
|
||||||
|
|
||||||
|
//DUMP: FunctionTemplateDecl{{.*}}barTemp
|
||||||
|
//DUMP-NEXT: TemplateTypeParmDecl{{.*}}typename{{.*}}T
|
||||||
|
template <typename T>
|
||||||
|
void barTemp(T t) {
|
||||||
|
//PRINT: #pragma omp interop init(prefer_type(4,"level_one"), target : t)
|
||||||
|
//DUMP: FunctionDecl{{.*}}barTemp 'void (T)'
|
||||||
|
//DUMP: ParmVarDecl{{.*}}t 'T'
|
||||||
|
//DUMP: OMPInteropDirective
|
||||||
|
//DUMP: OMPInitClause
|
||||||
|
//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'t' 'T'
|
||||||
|
//DUMP: IntegerLiteral{{.*}}'int' 4
|
||||||
|
//DUMP: StringLiteral{{.*}}"level_one"
|
||||||
|
#pragma omp interop init(prefer_type(4,"level_one"), target: t)
|
||||||
|
|
||||||
|
//DUMP: FunctionDecl{{.*}}barTemp 'void (void *)'
|
||||||
|
//DUMP: TemplateArgument type 'void *'
|
||||||
|
//DUMP: ParmVarDecl{{.*}}t 'void *'
|
||||||
|
//DUMP: OMPInteropDirective
|
||||||
|
//DUMP: OMPInitClause
|
||||||
|
//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'t' 'void *'
|
||||||
|
//PRINT: #pragma omp interop init(prefer_type(4,"level_one"), target : t)
|
||||||
|
}
|
||||||
|
|
||||||
|
void bar()
|
||||||
|
{
|
||||||
|
fooTemp<3>();
|
||||||
|
omp_interop_t Ivar;
|
||||||
|
barTemp(Ivar);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // HEADER
|
|
@ -0,0 +1,83 @@
|
||||||
|
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -o - -DWITHDEF %s
|
||||||
|
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -o - -DWITHOUTDEF %s
|
||||||
|
|
||||||
|
#ifdef WITHDEF
|
||||||
|
typedef void *omp_interop_t;
|
||||||
|
|
||||||
|
void foo(int *Ap) {
|
||||||
|
omp_interop_t InteropVar;
|
||||||
|
omp_interop_t Another;
|
||||||
|
|
||||||
|
//expected-error@+1 {{expected interop type: 'target' and/or 'targetsync'}}
|
||||||
|
#pragma omp interop init(target,foo:InteropVar) init(target:Another)
|
||||||
|
|
||||||
|
//expected-error@+1 {{use of undeclared identifier 'NoDeclVar'}}
|
||||||
|
#pragma omp interop init(target:NoDeclVar) init(target:Another)
|
||||||
|
|
||||||
|
//expected-error@+2 {{expected interop type: 'target' and/or 'targetsync'}}
|
||||||
|
//expected-error@+1 {{expected expression}}
|
||||||
|
#pragma omp interop init(InteropVar) init(target:Another)
|
||||||
|
|
||||||
|
//expected-warning@+1 {{missing ':' after interop types}}
|
||||||
|
#pragma omp interop init(target InteropVar)
|
||||||
|
|
||||||
|
//expected-error@+1 {{expected expression}}
|
||||||
|
#pragma omp interop init(prefer_type(1,+,3),target:InteropVar) \
|
||||||
|
init(target:Another)
|
||||||
|
|
||||||
|
int IntVar;
|
||||||
|
struct S { int I; } SVar;
|
||||||
|
|
||||||
|
//expected-error@+1 {{interop variable must be of type 'omp_interop_t'}}
|
||||||
|
#pragma omp interop init(prefer_type(1,"sycl",3),target:IntVar) \
|
||||||
|
init(target:Another)
|
||||||
|
|
||||||
|
//expected-error@+1 {{interop variable must be of type 'omp_interop_t'}}
|
||||||
|
#pragma omp interop init(prefer_type(1,"sycl",3),target:SVar) \
|
||||||
|
init(target:Another)
|
||||||
|
|
||||||
|
int a, b;
|
||||||
|
//expected-error@+1 {{expected variable of type 'omp_interop_t'}}
|
||||||
|
#pragma omp interop init(target:a+b) init(target:Another)
|
||||||
|
|
||||||
|
const omp_interop_t C = (omp_interop_t)5;
|
||||||
|
//expected-error@+1 {{expected non-const variable of type 'omp_interop_t'}}
|
||||||
|
#pragma omp interop init(target:C) init(target:Another)
|
||||||
|
|
||||||
|
//expected-error@+1 {{prefer_list item must be a string literal or constant integral expression}}
|
||||||
|
#pragma omp interop init(prefer_type(1.0),target:InteropVar) \
|
||||||
|
init(target:Another)
|
||||||
|
|
||||||
|
//expected-error@+1 {{prefer_list item must be a string literal or constant integral expression}}
|
||||||
|
#pragma omp interop init(prefer_type(a),target:InteropVar) \
|
||||||
|
init(target:Another)
|
||||||
|
|
||||||
|
//expected-error@+1 {{expected at least one 'init', 'use', 'destroy', or 'nowait' clause for '#pragma omp interop'}}
|
||||||
|
#pragma omp interop device(0)
|
||||||
|
|
||||||
|
//expected-warning@+1 {{interop type 'target' cannot be specified more than once}}
|
||||||
|
#pragma omp interop init(target,targetsync,target:InteropVar)
|
||||||
|
|
||||||
|
//expected-error@+1 {{'depend' clause requires the 'targetsync' interop type}}
|
||||||
|
#pragma omp interop init(target:InteropVar) depend(inout:Ap)
|
||||||
|
|
||||||
|
//expected-error@+1 {{interop variable 'InteropVar' used in multiple action clauses}}
|
||||||
|
#pragma omp interop init(target:InteropVar) init(target:InteropVar)
|
||||||
|
|
||||||
|
//expected-error@+1 {{directive '#pragma omp interop' cannot contain more than one 'device' clause}}
|
||||||
|
#pragma omp interop init(target:InteropVar) device(0) device(1)
|
||||||
|
|
||||||
|
//expected-error@+1 {{argument to 'device' clause must be a non-negative integer value}}
|
||||||
|
#pragma omp interop init(target:InteropVar) device(-4)
|
||||||
|
|
||||||
|
//expected-error@+1 {{directive '#pragma omp interop' cannot contain more than one 'nowait' clause}}
|
||||||
|
#pragma omp interop nowait init(target:InteropVar) nowait
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef WITHOUTDEF
|
||||||
|
void foo() {
|
||||||
|
int InteropVar;
|
||||||
|
//expected-error@+1 {{'omp_interop_t' type not found; include <omp.h>}}
|
||||||
|
#pragma omp interop init(prefer_type(1,"sycl",3),target:InteropVar) nowait
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -71,7 +71,7 @@ int foo() {
|
||||||
foo();
|
foo();
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma omp taskgroup init // expected-warning {{extra tokens at the end of '#pragma omp taskgroup' are ignored}}
|
#pragma omp taskgroup initi // expected-warning {{extra tokens at the end of '#pragma omp taskgroup' are ignored}}
|
||||||
;
|
;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2278,6 +2278,10 @@ void OMPClauseEnqueue::VisitOMPSIMDClause(const OMPSIMDClause *) {}
|
||||||
|
|
||||||
void OMPClauseEnqueue::VisitOMPNogroupClause(const OMPNogroupClause *) {}
|
void OMPClauseEnqueue::VisitOMPNogroupClause(const OMPNogroupClause *) {}
|
||||||
|
|
||||||
|
void OMPClauseEnqueue::VisitOMPInitClause(const OMPInitClause *C) {
|
||||||
|
VisitOMPClauseList(C);
|
||||||
|
}
|
||||||
|
|
||||||
void OMPClauseEnqueue::VisitOMPDestroyClause(const OMPDestroyClause *) {}
|
void OMPClauseEnqueue::VisitOMPDestroyClause(const OMPDestroyClause *) {}
|
||||||
|
|
||||||
void OMPClauseEnqueue::VisitOMPUnifiedAddressClause(
|
void OMPClauseEnqueue::VisitOMPUnifiedAddressClause(
|
||||||
|
@ -5655,6 +5659,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
|
||||||
"OMPTargetTeamsDistributeParallelForSimdDirective");
|
"OMPTargetTeamsDistributeParallelForSimdDirective");
|
||||||
case CXCursor_OMPTargetTeamsDistributeSimdDirective:
|
case CXCursor_OMPTargetTeamsDistributeSimdDirective:
|
||||||
return cxstring::createRef("OMPTargetTeamsDistributeSimdDirective");
|
return cxstring::createRef("OMPTargetTeamsDistributeSimdDirective");
|
||||||
|
case CXCursor_OMPInteropDirective:
|
||||||
|
return cxstring::createRef("OMPInteropDirective");
|
||||||
case CXCursor_OverloadCandidate:
|
case CXCursor_OverloadCandidate:
|
||||||
return cxstring::createRef("OverloadCandidate");
|
return cxstring::createRef("OverloadCandidate");
|
||||||
case CXCursor_TypeAliasTemplateDecl:
|
case CXCursor_TypeAliasTemplateDecl:
|
||||||
|
|
|
@ -807,6 +807,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
|
||||||
case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
|
case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
|
||||||
K = CXCursor_OMPTargetTeamsDistributeSimdDirective;
|
K = CXCursor_OMPTargetTeamsDistributeSimdDirective;
|
||||||
break;
|
break;
|
||||||
|
case Stmt::OMPInteropDirectiveClass:
|
||||||
|
K = CXCursor_OMPInteropDirective;
|
||||||
|
break;
|
||||||
case Stmt::BuiltinBitCastExprClass:
|
case Stmt::BuiltinBitCastExprClass:
|
||||||
K = CXCursor_BuiltinBitCastExpr;
|
K = CXCursor_BuiltinBitCastExpr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -717,6 +717,7 @@ CHECK_SIMPLE_CLAUSE(UsesAllocators, OMPC_uses_allocators)
|
||||||
CHECK_SIMPLE_CLAUSE(Update, OMPC_update)
|
CHECK_SIMPLE_CLAUSE(Update, OMPC_update)
|
||||||
CHECK_SIMPLE_CLAUSE(UseDeviceAddr, OMPC_use_device_addr)
|
CHECK_SIMPLE_CLAUSE(UseDeviceAddr, OMPC_use_device_addr)
|
||||||
CHECK_SIMPLE_CLAUSE(Write, OMPC_write)
|
CHECK_SIMPLE_CLAUSE(Write, OMPC_write)
|
||||||
|
CHECK_SIMPLE_CLAUSE(Init, OMPC_init)
|
||||||
|
|
||||||
CHECK_REQ_SCALAR_INT_CLAUSE(Allocator, OMPC_allocator)
|
CHECK_REQ_SCALAR_INT_CLAUSE(Allocator, OMPC_allocator)
|
||||||
CHECK_REQ_SCALAR_INT_CLAUSE(Grainsize, OMPC_grainsize)
|
CHECK_REQ_SCALAR_INT_CLAUSE(Grainsize, OMPC_grainsize)
|
||||||
|
|
|
@ -268,6 +268,9 @@ def OMPC_Order : Clause<"order"> {
|
||||||
OMP_ORDER_concurrent
|
OMP_ORDER_concurrent
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
def OMPC_Init : Clause<"init"> {
|
||||||
|
let clangClass = "OMPInitClause";
|
||||||
|
}
|
||||||
def OMPC_Destroy : Clause<"destroy"> {
|
def OMPC_Destroy : Clause<"destroy"> {
|
||||||
let clangClass = "OMPDestroyClause";
|
let clangClass = "OMPDestroyClause";
|
||||||
}
|
}
|
||||||
|
@ -1640,6 +1643,14 @@ def OMP_EndWorkshare : Directive<"end workshare"> {
|
||||||
VersionedClause<OMPC_NoWait>
|
VersionedClause<OMPC_NoWait>
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
def OMP_interop : Directive<"interop"> {
|
||||||
|
let allowedClauses = [
|
||||||
|
VersionedClause<OMPC_Device>,
|
||||||
|
VersionedClause<OMPC_Depend>,
|
||||||
|
VersionedClause<OMPC_Init>,
|
||||||
|
VersionedClause<OMPC_NoWait>,
|
||||||
|
];
|
||||||
|
}
|
||||||
def OMP_Unknown : Directive<"unknown"> {
|
def OMP_Unknown : Directive<"unknown"> {
|
||||||
let isDefault = true;
|
let isDefault = true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue