diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Parse/ParseOpenMP.cpp | 137 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 75 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 20 |
3 files changed, 165 insertions, 67 deletions
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 6112c90cacd..b41a2a86f51 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -329,63 +329,6 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { IsCorrect); } -/// Parses clauses for 'declare simd' directive. -/// clause: -/// 'inbranch' | 'notinbranch' -/// 'simdlen' '(' <expr> ')' -/// { 'uniform' '(' <argument_list> ')' } -static bool parseDeclareSimdClauses(Parser &P, - OMPDeclareSimdDeclAttr::BranchStateTy &BS, - ExprResult &SimdLen, - SmallVectorImpl<Expr *> &Uniforms) { - SourceRange BSRange; - const Token &Tok = P.getCurToken(); - bool IsError = false; - while (Tok.isNot(tok::annot_pragma_openmp_end)) { - if (Tok.isNot(tok::identifier)) - break; - OMPDeclareSimdDeclAttr::BranchStateTy Out; - IdentifierInfo *II = Tok.getIdentifierInfo(); - StringRef ClauseName = II->getName(); - // Parse 'inranch|notinbranch' clauses. - if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) { - if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) { - P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch) - << ClauseName - << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange; - IsError = true; - } - BS = Out; - BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc()); - P.ConsumeToken(); - } else if (ClauseName.equals("simdlen")) { - if (SimdLen.isUsable()) { - P.Diag(Tok, diag::err_omp_more_one_clause) - << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0; - IsError = true; - } - P.ConsumeToken(); - SourceLocation RLoc; - SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc); - if (SimdLen.isInvalid()) - IsError = true; - } else if (ClauseName.equals("uniform")) { - Parser::OpenMPVarListDataTy Data; - - P.ConsumeToken(); - if (P.ParseOpenMPVarList(OMPD_declare_simd, - getOpenMPClauseKind(ClauseName), Uniforms, Data)) - IsError = true; - } else - // TODO: add parsing of other clauses. - break; - // Skip ',' if any. - if (Tok.is(tok::comma)) - P.ConsumeToken(); - } - return IsError; -} - namespace { /// RAII that recreates function context for correct parsing of clauses of /// 'declare simd' construct. @@ -442,6 +385,75 @@ public: }; } // namespace +/// Parses clauses for 'declare simd' directive. +/// clause: +/// 'inbranch' | 'notinbranch' +/// 'simdlen' '(' <expr> ')' +/// { 'uniform' '(' <argument_list> ')' } +/// { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' } +static bool parseDeclareSimdClauses(Parser &P, + OMPDeclareSimdDeclAttr::BranchStateTy &BS, + ExprResult &SimdLen, + SmallVectorImpl<Expr *> &Uniforms, + SmallVectorImpl<Expr *> &Aligneds, + SmallVectorImpl<Expr *> &Alignments) { + SourceRange BSRange; + const Token &Tok = P.getCurToken(); + bool IsError = false; + while (Tok.isNot(tok::annot_pragma_openmp_end)) { + if (Tok.isNot(tok::identifier)) + break; + OMPDeclareSimdDeclAttr::BranchStateTy Out; + IdentifierInfo *II = Tok.getIdentifierInfo(); + StringRef ClauseName = II->getName(); + // Parse 'inranch|notinbranch' clauses. + if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) { + if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) { + P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch) + << ClauseName + << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange; + IsError = true; + } + BS = Out; + BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc()); + P.ConsumeToken(); + } else if (ClauseName.equals("simdlen")) { + if (SimdLen.isUsable()) { + P.Diag(Tok, diag::err_omp_more_one_clause) + << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0; + IsError = true; + } + P.ConsumeToken(); + SourceLocation RLoc; + SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc); + if (SimdLen.isInvalid()) + IsError = true; + } else { + OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName); + if (CKind == OMPC_uniform || CKind == OMPC_aligned) { + Parser::OpenMPVarListDataTy Data; + auto *Vars = &Uniforms; + if (CKind == OMPC_aligned) { + Vars = &Aligneds; + } + + P.ConsumeToken(); + if (P.ParseOpenMPVarList(OMPD_declare_simd, + getOpenMPClauseKind(ClauseName), *Vars, Data)) + IsError = true; + if (CKind == OMPC_aligned) + Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr); + } else + // TODO: add parsing of other clauses. + break; + } + // Skip ',' if any. + if (Tok.is(tok::comma)) + P.ConsumeToken(); + } + return IsError; +} + /// Parse clauses for '#pragma omp declare simd'. Parser::DeclGroupPtrTy Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr, @@ -456,7 +468,10 @@ Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr, OMPDeclareSimdDeclAttr::BS_Undefined; ExprResult Simdlen; SmallVector<Expr *, 4> Uniforms; - bool IsError = parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms); + SmallVector<Expr *, 4> Aligneds; + SmallVector<Expr *, 4> Alignments; + bool IsError = parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds, + Alignments); // Need to check for extra tokens. if (Tok.isNot(tok::annot_pragma_openmp_end)) { Diag(Tok, diag::warn_omp_extra_tokens_at_eol) @@ -466,9 +481,11 @@ Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr, } // Skip the last annot_pragma_openmp_end. SourceLocation EndLoc = ConsumeToken(); - if (!IsError) + if (!IsError) { return Actions.ActOnOpenMPDeclareSimdDirective( - Ptr, BS, Simdlen.get(), Uniforms, SourceRange(Loc, EndLoc)); + Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, + SourceRange(Loc, EndLoc)); + } return Ptr; } diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 43a774eec66..287bb368184 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -3192,7 +3192,9 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective( DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen, - ArrayRef<Expr *> Uniforms, SourceRange SR) { + ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds, + ArrayRef<Expr *> Alignments, SourceRange SR) { + assert(Aligneds.size() == Alignments.size()); if (!DG || DG.get().isNull()) return DeclGroupPtrTy(); @@ -3235,9 +3237,76 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective( Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0); } + // OpenMP [2.8.2, declare simd construct, Description] + // The aligned clause declares that the object to which each list item points + // is aligned to the number of bytes expressed in the optional parameter of + // the aligned clause. + // The special this pointer can be used as if was one of the arguments to the + // function in any of the linear, aligned, or uniform clauses. + // The type of list items appearing in the aligned clause must be array, + // pointer, reference to array, or reference to pointer. + llvm::DenseMap<Decl *, Expr *> AlignedArgs; + Expr *AlignedThis = nullptr; + for (auto *E : Aligneds) { + E = E->IgnoreParenImpCasts(); + if (auto *DRE = dyn_cast<DeclRefExpr>(E)) + if (auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) { + auto *CanonPVD = PVD->getCanonicalDecl(); + if (FD->getNumParams() > PVD->getFunctionScopeIndex() && + FD->getParamDecl(PVD->getFunctionScopeIndex()) + ->getCanonicalDecl() == CanonPVD) { + // OpenMP [2.8.1, simd construct, Restrictions] + // A list-item cannot appear in more than one aligned clause. + if (AlignedArgs.count(CanonPVD) > 0) { + Diag(E->getExprLoc(), diag::err_omp_aligned_twice) + << 1 << E->getSourceRange(); + Diag(AlignedArgs[CanonPVD]->getExprLoc(), + diag::note_omp_explicit_dsa) + << getOpenMPClauseName(OMPC_aligned); + continue; + } + AlignedArgs[CanonPVD] = E; + QualType QTy = PVD->getType() + .getNonReferenceType() + .getUnqualifiedType() + .getCanonicalType(); + const Type *Ty = QTy.getTypePtrOrNull(); + if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) { + Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr) + << QTy << getLangOpts().CPlusPlus << E->getSourceRange(); + Diag(PVD->getLocation(), diag::note_previous_decl) << PVD; + } + continue; + } + } + if (isa<CXXThisExpr>(E)) { + if (AlignedThis) { + Diag(E->getExprLoc(), diag::err_omp_aligned_twice) + << 2 << E->getSourceRange(); + Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa) + << getOpenMPClauseName(OMPC_aligned); + } + AlignedThis = E; + continue; + } + Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) + << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0); + } + // The optional parameter of the aligned clause, alignment, must be a constant + // positive integer expression. If no optional parameter is specified, + // implementation-defined default alignments for SIMD instructions on the + // target platforms are assumed. + SmallVector<Expr *, 4> NewAligns; + for (auto *E : Alignments) { + ExprResult Align; + if (E) + Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned); + NewAligns.push_back(Align.get()); + } auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit( Context, BS, SL.get(), const_cast<Expr **>(Uniforms.data()), - Uniforms.size(), SR); + Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(), + const_cast<Expr **>(NewAligns.data()), NewAligns.size(), SR); ADecl->addAttr(NewAttr); return ConvertDeclToDeclGroup(ADecl); } @@ -8859,7 +8928,7 @@ OMPClause *Sema::ActOnOpenMPAlignedClause( // OpenMP [2.8.1, simd construct, Restrictions] // A list-item cannot appear in more than one aligned clause. if (Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) { - Diag(ELoc, diag::err_omp_aligned_twice) << ERange; + Diag(ELoc, diag::err_omp_aligned_twice) << 0 << ERange; Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa) << getOpenMPClauseName(OMPC_aligned); continue; diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 168bf6f451d..3a320e11d14 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -247,7 +247,7 @@ static void instantiateOMPDeclareSimdDeclAttr( New = FTD->getTemplatedDecl(); auto *FD = cast<FunctionDecl>(New); auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(FD->getDeclContext()); - SmallVector<Expr *, 4> Uniforms; + SmallVector<Expr *, 4> Uniforms, Aligneds, Alignments; auto &&Subst = [&](Expr *E) -> ExprResult { if (auto *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts())) @@ -273,9 +273,21 @@ static void instantiateOMPDeclareSimdDeclAttr( } } - (void)S.ActOnOpenMPDeclareSimdDirective(S.ConvertDeclToDeclGroup(New), - Attr.getBranchState(), Simdlen.get(), - Uniforms, Attr.getRange()); + auto AI = Attr.alignments_begin(); + for (auto *E : Attr.aligneds()) { + ExprResult Inst = Subst(E); + if (Inst.isInvalid()) + continue; + Aligneds.push_back(Inst.get()); + Inst = ExprEmpty(); + if (*AI) + Inst = S.SubstExpr(*AI, TemplateArgs); + Alignments.push_back(Inst.get()); + ++AI; + } + (void)S.ActOnOpenMPDeclareSimdDirective( + S.ConvertDeclToDeclGroup(New), Attr.getBranchState(), Simdlen.get(), + Uniforms, Aligneds, Alignments, Attr.getRange()); } void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, |

