diff options
Diffstat (limited to 'include/clang/AST/StmtOpenMP.h')
-rw-r--r-- | include/clang/AST/StmtOpenMP.h | 800 |
1 files changed, 760 insertions, 40 deletions
diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h index db02afe0..aed7691 100644 --- a/include/clang/AST/StmtOpenMP.h +++ b/include/clang/AST/StmtOpenMP.h @@ -128,6 +128,13 @@ public: operator bool() { return Current != End; } }; + /// \brief Gets a single clause of the specified kind \a K associated with the + /// current directive iff there is only one clause of this kind (and assertion + /// is fired if there is more than one clause is associated with the + /// directive). Returns nullptr if no clause of kind \a K is associated with + /// the directive. + const OMPClause *getSingleClause(OpenMPClauseKind K) const; + /// \brief Returns starting location of directive kind. SourceLocation getLocStart() const { return StartLoc; } /// \brief Returns ending location of directive. @@ -238,6 +245,353 @@ public: } }; +/// \brief This is a common base class for loop directives ('omp simd', 'omp +/// for', 'omp for simd' etc.). It is responsible for the loop code generation. +/// +class OMPLoopDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Number of collapsed loops as specified by 'collapse' clause. + unsigned CollapsedNum; + + /// \brief Offsets to the stored exprs. + /// This enumeration contains offsets to all the pointers to children + /// expressions stored in OMPLoopDirective. + /// The first 9 children are nesessary for all the loop directives, and + /// the next 7 are specific to the worksharing ones. + /// After the fixed children, three arrays of length CollapsedNum are + /// allocated: loop counters, their updates and final values. + /// + enum { + AssociatedStmtOffset = 0, + IterationVariableOffset = 1, + LastIterationOffset = 2, + CalcLastIterationOffset = 3, + PreConditionOffset = 4, + CondOffset = 5, + SeparatedCondOffset = 6, + InitOffset = 7, + IncOffset = 8, + // The '...End' enumerators do not correspond to child expressions - they + // specify the offset to the end (and start of the following counters/ + // updates/finals arrays). + DefaultEnd = 9, + // The following 7 exprs are used by worksharing loops only. + IsLastIterVariableOffset = 9, + LowerBoundVariableOffset = 10, + UpperBoundVariableOffset = 11, + StrideVariableOffset = 12, + EnsureUpperBoundOffset = 13, + NextLowerBoundOffset = 14, + NextUpperBoundOffset = 15, + // Offset to the end (and start of the following counters/updates/finals + // arrays) for worksharing loop directives. + WorksharingEnd = 16, + }; + + /// \brief Get the counters storage. + MutableArrayRef<Expr *> getCounters() { + Expr **Storage = reinterpret_cast<Expr **>( + &(*(std::next(child_begin(), getArraysOffset(getDirectiveKind()))))); + return MutableArrayRef<Expr *>(Storage, CollapsedNum); + } + + /// \brief Get the updates storage. + MutableArrayRef<Expr *> getUpdates() { + Expr **Storage = reinterpret_cast<Expr **>( + &*std::next(child_begin(), + getArraysOffset(getDirectiveKind()) + CollapsedNum)); + return MutableArrayRef<Expr *>(Storage, CollapsedNum); + } + + /// \brief Get the final counter updates storage. + MutableArrayRef<Expr *> getFinals() { + Expr **Storage = reinterpret_cast<Expr **>( + &*std::next(child_begin(), + getArraysOffset(getDirectiveKind()) + 2 * CollapsedNum)); + return MutableArrayRef<Expr *>(Storage, CollapsedNum); + } + +protected: + /// \brief Build instance of loop directive of class \a Kind. + /// + /// \param SC Statement class. + /// \param Kind Kind of OpenMP directive. + /// \param StartLoc Starting location of the directive (directive keyword). + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed loops from 'collapse' clause. + /// \param NumClauses Number of clauses. + /// \param NumSpecialChildren Number of additional directive-specific stmts. + /// + template <typename T> + OMPLoopDirective(const T *That, StmtClass SC, OpenMPDirectiveKind Kind, + SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, unsigned NumClauses, + unsigned NumSpecialChildren = 0) + : OMPExecutableDirective(That, SC, Kind, StartLoc, EndLoc, NumClauses, + numLoopChildren(CollapsedNum, Kind) + + NumSpecialChildren), + CollapsedNum(CollapsedNum) {} + + /// \brief Offset to the start of children expression arrays. + static unsigned getArraysOffset(OpenMPDirectiveKind Kind) { + return isOpenMPWorksharingDirective(Kind) ? WorksharingEnd + : DefaultEnd; + } + + /// \brief Children number. + static unsigned numLoopChildren(unsigned CollapsedNum, + OpenMPDirectiveKind Kind) { + return getArraysOffset(Kind) + + 3 * CollapsedNum; // Counters, Updates and Finals + } + + void setIterationVariable(Expr *IV) { + *std::next(child_begin(), IterationVariableOffset) = IV; + } + void setLastIteration(Expr *LI) { + *std::next(child_begin(), LastIterationOffset) = LI; + } + void setCalcLastIteration(Expr *CLI) { + *std::next(child_begin(), CalcLastIterationOffset) = CLI; + } + void setPreCond(Expr *PC) { + *std::next(child_begin(), PreConditionOffset) = PC; + } + void setCond(Expr *Cond, Expr *SeparatedCond) { + *std::next(child_begin(), CondOffset) = Cond; + *std::next(child_begin(), SeparatedCondOffset) = SeparatedCond; + } + void setInit(Expr *Init) { *std::next(child_begin(), InitOffset) = Init; } + void setInc(Expr *Inc) { *std::next(child_begin(), IncOffset) = Inc; } + void setIsLastIterVariable(Expr *IL) { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + *std::next(child_begin(), IsLastIterVariableOffset) = IL; + } + void setLowerBoundVariable(Expr *LB) { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + *std::next(child_begin(), LowerBoundVariableOffset) = LB; + } + void setUpperBoundVariable(Expr *UB) { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + *std::next(child_begin(), UpperBoundVariableOffset) = UB; + } + void setStrideVariable(Expr *ST) { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + *std::next(child_begin(), StrideVariableOffset) = ST; + } + void setEnsureUpperBound(Expr *EUB) { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + *std::next(child_begin(), EnsureUpperBoundOffset) = EUB; + } + void setNextLowerBound(Expr *NLB) { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + *std::next(child_begin(), NextLowerBoundOffset) = NLB; + } + void setNextUpperBound(Expr *NUB) { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + *std::next(child_begin(), NextUpperBoundOffset) = NUB; + } + void setCounters(ArrayRef<Expr *> A); + void setUpdates(ArrayRef<Expr *> A); + void setFinals(ArrayRef<Expr *> A); + +public: + /// \brief The expressions built for the OpenMP loop CodeGen for the + /// whole collapsed loop nest. + struct HelperExprs { + /// \brief Loop iteration variable. + Expr *IterationVarRef; + /// \brief Loop last iteration number. + Expr *LastIteration; + /// \brief Calculation of last iteration. + Expr *CalcLastIteration; + /// \brief Loop pre-condition. + Expr *PreCond; + /// \brief Loop condition. + Expr *Cond; + /// \brief A condition with 1 iteration separated. + Expr *SeparatedCond; + /// \brief Loop iteration variable init. + Expr *Init; + /// \brief Loop increment. + Expr *Inc; + /// \brief IsLastIteration - local flag variable passed to runtime. + Expr *IL; + /// \brief LowerBound - local variable passed to runtime. + Expr *LB; + /// \brief UpperBound - local variable passed to runtime. + Expr *UB; + /// \brief Stride - local variable passed to runtime. + Expr *ST; + /// \brief EnsureUpperBound -- expression LB = min(LB, NumIterations). + Expr *EUB; + /// \brief Update of LowerBound for statically sheduled 'omp for' loops. + Expr *NLB; + /// \brief Update of UpperBound for statically sheduled 'omp for' loops. + Expr *NUB; + /// \brief Counters Loop counters. + SmallVector<Expr *, 4> Counters; + /// \brief Expressions for loop counters update for CodeGen. + SmallVector<Expr *, 4> Updates; + /// \brief Final loop counter values for GodeGen. + SmallVector<Expr *, 4> Finals; + + /// \brief Check if all the expressions are built (does not check the + /// worksharing ones). + bool builtAll() { + return IterationVarRef != nullptr && LastIteration != nullptr && + PreCond != nullptr && Cond != nullptr && + SeparatedCond != nullptr && Init != nullptr && Inc != nullptr; + } + + /// \brief Initialize all the fields to null. + /// \param Size Number of elements in the counters/finals/updates arrays. + void clear(unsigned Size) { + IterationVarRef = nullptr; + LastIteration = nullptr; + CalcLastIteration = nullptr; + PreCond = nullptr; + Cond = nullptr; + SeparatedCond = nullptr; + Init = nullptr; + Inc = nullptr; + IL = nullptr; + LB = nullptr; + UB = nullptr; + ST = nullptr; + EUB = nullptr; + NLB = nullptr; + NUB = nullptr; + Counters.resize(Size); + Updates.resize(Size); + Finals.resize(Size); + for (unsigned i = 0; i < Size; ++i) { + Counters[i] = nullptr; + Updates[i] = nullptr; + Finals[i] = nullptr; + } + } + }; + + /// \brief Get number of collapsed loops. + unsigned getCollapsedNumber() const { return CollapsedNum; } + + Expr *getIterationVariable() const { + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), IterationVariableOffset))); + } + Expr *getLastIteration() const { + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), LastIterationOffset))); + } + Expr *getCalcLastIteration() const { + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), CalcLastIterationOffset))); + } + Expr *getPreCond() const { + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), PreConditionOffset))); + } + Expr *getCond(bool SeparateIter) const { + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), + (SeparateIter ? SeparatedCondOffset : CondOffset)))); + } + Expr *getInit() const { + return const_cast<Expr *>( + reinterpret_cast<const Expr *>(*std::next(child_begin(), InitOffset))); + } + Expr *getInc() const { + return const_cast<Expr *>( + reinterpret_cast<const Expr *>(*std::next(child_begin(), IncOffset))); + } + Expr *getIsLastIterVariable() const { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), IsLastIterVariableOffset))); + } + Expr *getLowerBoundVariable() const { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), LowerBoundVariableOffset))); + } + Expr *getUpperBoundVariable() const { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), UpperBoundVariableOffset))); + } + Expr *getStrideVariable() const { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), StrideVariableOffset))); + } + Expr *getEnsureUpperBound() const { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), EnsureUpperBoundOffset))); + } + Expr *getNextLowerBound() const { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), NextLowerBoundOffset))); + } + Expr *getNextUpperBound() const { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), NextUpperBoundOffset))); + } + const Stmt *getBody() const { + // This relies on the loop form is already checked by Sema. + Stmt *Body = getAssociatedStmt()->IgnoreContainers(true); + Body = cast<ForStmt>(Body)->getBody(); + for (unsigned Cnt = 1; Cnt < CollapsedNum; ++Cnt) { + Body = Body->IgnoreContainers(); + Body = cast<ForStmt>(Body)->getBody(); + } + return Body; + } + + ArrayRef<Expr *> counters() { return getCounters(); } + + ArrayRef<Expr *> counters() const { + return const_cast<OMPLoopDirective *>(this)->getCounters(); + } + + ArrayRef<Expr *> updates() { return getUpdates(); } + + ArrayRef<Expr *> updates() const { + return const_cast<OMPLoopDirective *>(this)->getUpdates(); + } + + ArrayRef<Expr *> finals() { return getFinals(); } + + ArrayRef<Expr *> finals() const { + return const_cast<OMPLoopDirective *>(this)->getFinals(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPSimdDirectiveClass || + T->getStmtClass() == OMPForDirectiveClass || + T->getStmtClass() == OMPForSimdDirectiveClass || + T->getStmtClass() == OMPParallelForDirectiveClass || + T->getStmtClass() == OMPParallelForSimdDirectiveClass; + } +}; + /// \brief This represents '#pragma omp simd' directive. /// /// \code @@ -247,10 +601,8 @@ public: /// with the variables 'a' and 'b', 'linear' with variables 'i', 'j' and /// linear step 's', 'reduction' with operator '+' and variables 'c' and 'd'. /// -class OMPSimdDirective : public OMPExecutableDirective { +class OMPSimdDirective : public OMPLoopDirective { friend class ASTStmtReader; - /// \brief Number of collapsed loops as specified by 'collapse' clause. - unsigned CollapsedNum; /// \brief Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. @@ -260,9 +612,8 @@ class OMPSimdDirective : public OMPExecutableDirective { /// OMPSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, unsigned NumClauses) - : OMPExecutableDirective(this, OMPSimdDirectiveClass, OMPD_simd, StartLoc, - EndLoc, NumClauses, 1), - CollapsedNum(CollapsedNum) {} + : OMPLoopDirective(this, OMPSimdDirectiveClass, OMPD_simd, StartLoc, + EndLoc, CollapsedNum, NumClauses) {} /// \brief Build an empty directive. /// @@ -270,10 +621,9 @@ class OMPSimdDirective : public OMPExecutableDirective { /// \param NumClauses Number of clauses. /// explicit OMPSimdDirective(unsigned CollapsedNum, unsigned NumClauses) - : OMPExecutableDirective(this, OMPSimdDirectiveClass, OMPD_simd, - SourceLocation(), SourceLocation(), NumClauses, - 1), - CollapsedNum(CollapsedNum) {} + : OMPLoopDirective(this, OMPSimdDirectiveClass, OMPD_simd, + SourceLocation(), SourceLocation(), CollapsedNum, + NumClauses) {} public: /// \brief Creates directive with a list of \a Clauses. @@ -284,11 +634,13 @@ public: /// \param CollapsedNum Number of collapsed loops. /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. /// static OMPSimdDirective *Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt); + Stmt *AssociatedStmt, + const HelperExprs &Exprs); /// \brief Creates an empty directive with the place /// for \a NumClauses clauses. @@ -300,8 +652,6 @@ public: static OMPSimdDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell); - unsigned getCollapsedNumber() const { return CollapsedNum; } - static bool classof(const Stmt *T) { return T->getStmtClass() == OMPSimdDirectiveClass; } @@ -316,10 +666,8 @@ public: /// variables 'a' and 'b' and 'reduction' with operator '+' and variables 'c' /// and 'd'. /// -class OMPForDirective : public OMPExecutableDirective { +class OMPForDirective : public OMPLoopDirective { friend class ASTStmtReader; - /// \brief Number of collapsed loops as specified by 'collapse' clause. - unsigned CollapsedNum; /// \brief Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. @@ -329,9 +677,8 @@ class OMPForDirective : public OMPExecutableDirective { /// OMPForDirective(SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, unsigned NumClauses) - : OMPExecutableDirective(this, OMPForDirectiveClass, OMPD_for, StartLoc, - EndLoc, NumClauses, 1), - CollapsedNum(CollapsedNum) {} + : OMPLoopDirective(this, OMPForDirectiveClass, OMPD_for, StartLoc, EndLoc, + CollapsedNum, NumClauses) {} /// \brief Build an empty directive. /// @@ -339,10 +686,8 @@ class OMPForDirective : public OMPExecutableDirective { /// \param NumClauses Number of clauses. /// explicit OMPForDirective(unsigned CollapsedNum, unsigned NumClauses) - : OMPExecutableDirective(this, OMPForDirectiveClass, OMPD_for, - SourceLocation(), SourceLocation(), NumClauses, - 1), - CollapsedNum(CollapsedNum) {} + : OMPLoopDirective(this, OMPForDirectiveClass, OMPD_for, SourceLocation(), + SourceLocation(), CollapsedNum, NumClauses) {} public: /// \brief Creates directive with a list of \a Clauses. @@ -353,11 +698,13 @@ public: /// \param CollapsedNum Number of collapsed loops. /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. /// static OMPForDirective *Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt); + Stmt *AssociatedStmt, + const HelperExprs &Exprs); /// \brief Creates an empty directive with the place /// for \a NumClauses clauses. @@ -369,13 +716,76 @@ public: static OMPForDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell); - unsigned getCollapsedNumber() const { return CollapsedNum; } - static bool classof(const Stmt *T) { return T->getStmtClass() == OMPForDirectiveClass; } }; +/// \brief This represents '#pragma omp for simd' directive. +/// +/// \code +/// #pragma omp for simd private(a,b) linear(i,j:s) reduction(+:c,d) +/// \endcode +/// In this example directive '#pragma omp for simd' has clauses 'private' +/// with the variables 'a' and 'b', 'linear' with variables 'i', 'j' and +/// linear step 's', 'reduction' with operator '+' and variables 'c' and 'd'. +/// +class OMPForSimdDirective : public OMPLoopDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + OMPForSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, unsigned NumClauses) + : OMPLoopDirective(this, OMPForSimdDirectiveClass, OMPD_for_simd, + StartLoc, EndLoc, CollapsedNum, NumClauses) {} + + /// \brief Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + explicit OMPForSimdDirective(unsigned CollapsedNum, unsigned NumClauses) + : OMPLoopDirective(this, OMPForSimdDirectiveClass, OMPD_for_simd, + SourceLocation(), SourceLocation(), CollapsedNum, + NumClauses) {} + +public: + /// \brief Creates directive with a list of \a Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. + /// + static OMPForSimdDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs); + + /// \brief Creates an empty directive with the place + /// for \a NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + static OMPForSimdDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPForSimdDirectiveClass; + } +}; + /// \brief This represents '#pragma omp sections' directive. /// /// \code @@ -657,10 +1067,8 @@ public: /// with the variables 'a' and 'b' and 'reduction' with operator '+' and /// variables 'c' and 'd'. /// -class OMPParallelForDirective : public OMPExecutableDirective { +class OMPParallelForDirective : public OMPLoopDirective { friend class ASTStmtReader; - /// \brief Number of collapsed loops as specified by 'collapse' clause. - unsigned CollapsedNum; /// \brief Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. @@ -670,10 +1078,8 @@ class OMPParallelForDirective : public OMPExecutableDirective { /// OMPParallelForDirective(SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, unsigned NumClauses) - : OMPExecutableDirective(this, OMPParallelForDirectiveClass, - OMPD_parallel_for, StartLoc, EndLoc, NumClauses, - 1), - CollapsedNum(CollapsedNum) {} + : OMPLoopDirective(this, OMPParallelForDirectiveClass, OMPD_parallel_for, + StartLoc, EndLoc, CollapsedNum, NumClauses) {} /// \brief Build an empty directive. /// @@ -681,10 +1087,9 @@ class OMPParallelForDirective : public OMPExecutableDirective { /// \param NumClauses Number of clauses. /// explicit OMPParallelForDirective(unsigned CollapsedNum, unsigned NumClauses) - : OMPExecutableDirective(this, OMPParallelForDirectiveClass, - OMPD_parallel_for, SourceLocation(), - SourceLocation(), NumClauses, 1), - CollapsedNum(CollapsedNum) {} + : OMPLoopDirective(this, OMPParallelForDirectiveClass, OMPD_parallel_for, + SourceLocation(), SourceLocation(), CollapsedNum, + NumClauses) {} public: /// \brief Creates directive with a list of \a Clauses. @@ -695,11 +1100,12 @@ public: /// \param CollapsedNum Number of collapsed loops. /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. /// static OMPParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt); + Stmt *AssociatedStmt, const HelperExprs &Exprs); /// \brief Creates an empty directive with the place /// for \a NumClauses clauses. @@ -713,13 +1119,80 @@ public: unsigned CollapsedNum, EmptyShell); - unsigned getCollapsedNumber() const { return CollapsedNum; } - static bool classof(const Stmt *T) { return T->getStmtClass() == OMPParallelForDirectiveClass; } }; +/// \brief This represents '#pragma omp parallel for simd' directive. +/// +/// \code +/// #pragma omp parallel for simd private(a,b) linear(i,j:s) reduction(+:c,d) +/// \endcode +/// In this example directive '#pragma omp parallel for simd' has clauses +/// 'private' with the variables 'a' and 'b', 'linear' with variables 'i', 'j' +/// and linear step 's', 'reduction' with operator '+' and variables 'c' and +/// 'd'. +/// +class OMPParallelForSimdDirective : public OMPLoopDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + OMPParallelForSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, unsigned NumClauses) + : OMPLoopDirective(this, OMPParallelForSimdDirectiveClass, + OMPD_parallel_for_simd, StartLoc, EndLoc, CollapsedNum, + NumClauses) {} + + /// \brief Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + explicit OMPParallelForSimdDirective(unsigned CollapsedNum, + unsigned NumClauses) + : OMPLoopDirective(this, OMPParallelForSimdDirectiveClass, + OMPD_parallel_for_simd, SourceLocation(), + SourceLocation(), CollapsedNum, NumClauses) {} + +public: + /// \brief Creates directive with a list of \a Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. + /// + static OMPParallelForSimdDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs); + + /// \brief Creates an empty directive with the place + /// for \a NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + static OMPParallelForSimdDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPParallelForSimdDirectiveClass; + } +}; + /// \brief This represents '#pragma omp parallel sections' directive. /// /// \code @@ -1028,6 +1501,253 @@ public: } }; +/// \brief This represents '#pragma omp ordered' directive. +/// +/// \code +/// #pragma omp ordered +/// \endcode +/// +class OMPOrderedDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// + OMPOrderedDirective(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPExecutableDirective(this, OMPOrderedDirectiveClass, OMPD_ordered, + StartLoc, EndLoc, 0, 1) {} + + /// \brief Build an empty directive. + /// + explicit OMPOrderedDirective() + : OMPExecutableDirective(this, OMPOrderedDirectiveClass, OMPD_ordered, + SourceLocation(), SourceLocation(), 0, 1) {} + +public: + /// \brief Creates directive. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param AssociatedStmt Statement, associated with the directive. + /// + static OMPOrderedDirective *Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + Stmt *AssociatedStmt); + + /// \brief Creates an empty directive. + /// + /// \param C AST context. + /// + static OMPOrderedDirective *CreateEmpty(const ASTContext &C, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPOrderedDirectiveClass; + } +}; + +/// \brief This represents '#pragma omp atomic' directive. +/// +/// \code +/// #pragma omp atomic capture +/// \endcode +/// In this example directive '#pragma omp atomic' has clause 'capture'. +/// +class OMPAtomicDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param NumClauses Number of clauses. + /// + OMPAtomicDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPAtomicDirectiveClass, OMPD_atomic, + StartLoc, EndLoc, NumClauses, 4) {} + + /// \brief Build an empty directive. + /// + /// \param NumClauses Number of clauses. + /// + explicit OMPAtomicDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPAtomicDirectiveClass, OMPD_atomic, + SourceLocation(), SourceLocation(), NumClauses, + 4) {} + + /// \brief Set 'x' part of the associated expression/statement. + void setX(Expr *X) { *std::next(child_begin()) = X; } + /// \brief Set 'v' part of the associated expression/statement. + void setV(Expr *V) { *std::next(child_begin(), 2) = V; } + /// \brief Set 'expr' part of the associated expression/statement. + void setExpr(Expr *E) { *std::next(child_begin(), 3) = E; } + +public: + /// \brief Creates directive with a list of \a Clauses and 'x', 'v' and 'expr' + /// parts of the atomic construct (see Section 2.12.6, atomic Construct, for + /// detailed description of 'x', 'v' and 'expr'). + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param X 'x' part of the associated expression/statement. + /// \param V 'v' part of the associated expression/statement. + /// \param E 'expr' part of the associated expression/statement. + /// + static OMPAtomicDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V, + Expr *E); + + /// \brief Creates an empty directive with the place for \a NumClauses + /// clauses. + /// + /// \param C AST context. + /// \param NumClauses Number of clauses. + /// + static OMPAtomicDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell); + + /// \brief Get 'x' part of the associated expression/statement. + Expr *getX() { return cast_or_null<Expr>(*std::next(child_begin())); } + const Expr *getX() const { + return cast_or_null<Expr>(*std::next(child_begin())); + } + /// \brief Get 'v' part of the associated expression/statement. + Expr *getV() { return cast_or_null<Expr>(*std::next(child_begin(), 2)); } + const Expr *getV() const { + return cast_or_null<Expr>(*std::next(child_begin(), 2)); + } + /// \brief Get 'expr' part of the associated expression/statement. + Expr *getExpr() { return cast_or_null<Expr>(*std::next(child_begin(), 3)); } + const Expr *getExpr() const { + return cast_or_null<Expr>(*std::next(child_begin(), 3)); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPAtomicDirectiveClass; + } +}; + +/// \brief This represents '#pragma omp target' directive. +/// +/// \code +/// #pragma omp target if(a) +/// \endcode +/// In this example directive '#pragma omp target' has clause 'if' with +/// condition 'a'. +/// +class OMPTargetDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param NumClauses Number of clauses. + /// + OMPTargetDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPTargetDirectiveClass, OMPD_target, + StartLoc, EndLoc, NumClauses, 1) {} + + /// \brief Build an empty directive. + /// + /// \param NumClauses Number of clauses. + /// + explicit OMPTargetDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPTargetDirectiveClass, OMPD_target, + SourceLocation(), SourceLocation(), NumClauses, + 1) {} + +public: + /// \brief Creates directive with a list of \a Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// + static OMPTargetDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); + + /// \brief Creates an empty directive with the place for \a NumClauses + /// clauses. + /// + /// \param C AST context. + /// \param NumClauses Number of clauses. + /// + static OMPTargetDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTargetDirectiveClass; + } +}; + +/// \brief This represents '#pragma omp teams' directive. +/// +/// \code +/// #pragma omp teams if(a) +/// \endcode +/// In this example directive '#pragma omp teams' has clause 'if' with +/// condition 'a'. +/// +class OMPTeamsDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param NumClauses Number of clauses. + /// + OMPTeamsDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPTeamsDirectiveClass, OMPD_teams, + StartLoc, EndLoc, NumClauses, 1) {} + + /// \brief Build an empty directive. + /// + /// \param NumClauses Number of clauses. + /// + explicit OMPTeamsDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPTeamsDirectiveClass, OMPD_teams, + SourceLocation(), SourceLocation(), NumClauses, + 1) {} + +public: + /// \brief Creates directive with a list of \a Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// + static OMPTeamsDirective *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt); + + /// \brief Creates an empty directive with the place for \a NumClauses + /// clauses. + /// + /// \param C AST context. + /// \param NumClauses Number of clauses. + /// + static OMPTeamsDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTeamsDirectiveClass; + } +}; + } // end namespace clang #endif |