//===- OpenMPClause.cpp - Classes for OpenMP clauses ----------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file implements the subclesses of Stmt class declared in OpenMPClause.h // //===----------------------------------------------------------------------===// #include "clang/AST/OpenMPClause.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclOpenMP.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include #include #include using namespace clang; using namespace llvm; using namespace omp; OMPClause::child_range OMPClause::children() { switch (getClauseKind()) { default: break; #define GEN_CLANG_CLAUSE_CLASS #define CLAUSE_CLASS(Enum, Str, Class) \ case Enum: \ return static_cast(this)->children(); #include "llvm/Frontend/OpenMP/OMP.inc" } llvm_unreachable("unknown OMPClause"); } OMPClause::child_range OMPClause::used_children() { switch (getClauseKind()) { #define GEN_CLANG_CLAUSE_CLASS #define CLAUSE_CLASS(Enum, Str, Class) \ case Enum: \ return static_cast(this)->used_children(); #define CLAUSE_NO_CLASS(Enum, Str) \ case Enum: \ break; #include "llvm/Frontend/OpenMP/OMP.inc" } llvm_unreachable("unknown OMPClause"); } OMPClauseWithPreInit *OMPClauseWithPreInit::get(OMPClause *C) { auto *Res = OMPClauseWithPreInit::get(const_cast(C)); return Res ? const_cast(Res) : nullptr; } const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) { switch (C->getClauseKind()) { case OMPC_schedule: return static_cast(C); case OMPC_dist_schedule: return static_cast(C); case OMPC_firstprivate: return static_cast(C); case OMPC_lastprivate: return static_cast(C); case OMPC_reduction: return static_cast(C); case OMPC_task_reduction: return static_cast(C); case OMPC_in_reduction: return static_cast(C); case OMPC_linear: return static_cast(C); case OMPC_if: return static_cast(C); case OMPC_num_threads: return static_cast(C); case OMPC_num_teams: return static_cast(C); case OMPC_thread_limit: return static_cast(C); case OMPC_device: return static_cast(C); case OMPC_grainsize: return static_cast(C); case OMPC_num_tasks: return static_cast(C); case OMPC_final: return static_cast(C); case OMPC_priority: return static_cast(C); case OMPC_novariants: return static_cast(C); case OMPC_nocontext: return static_cast(C); case OMPC_filter: return static_cast(C); case OMPC_ompx_dyn_cgroup_mem: return static_cast(C); case OMPC_default: case OMPC_proc_bind: case OMPC_safelen: case OMPC_simdlen: case OMPC_sizes: case OMPC_allocator: case OMPC_allocate: case OMPC_collapse: case OMPC_private: case OMPC_shared: case OMPC_aligned: case OMPC_copyin: case OMPC_copyprivate: case OMPC_ordered: case OMPC_nowait: case OMPC_untied: case OMPC_mergeable: case OMPC_threadprivate: case OMPC_flush: case OMPC_depobj: case OMPC_read: case OMPC_write: case OMPC_update: case OMPC_capture: case OMPC_compare: case OMPC_fail: case OMPC_seq_cst: case OMPC_acq_rel: case OMPC_acquire: case OMPC_release: case OMPC_relaxed: case OMPC_depend: case OMPC_threads: case OMPC_simd: case OMPC_map: case OMPC_nogroup: case OMPC_hint: case OMPC_defaultmap: case OMPC_unknown: case OMPC_uniform: case OMPC_to: case OMPC_from: case OMPC_use_device_ptr: case OMPC_use_device_addr: case OMPC_is_device_ptr: case OMPC_has_device_addr: case OMPC_unified_address: case OMPC_unified_shared_memory: case OMPC_reverse_offload: case OMPC_dynamic_allocators: case OMPC_atomic_default_mem_order: case OMPC_at: case OMPC_severity: case OMPC_message: case OMPC_device_type: case OMPC_match: case OMPC_nontemporal: case OMPC_order: case OMPC_destroy: case OMPC_detach: case OMPC_inclusive: case OMPC_exclusive: case OMPC_uses_allocators: case OMPC_affinity: case OMPC_when: case OMPC_bind: case OMPC_ompx_bare: break; default: break; } return nullptr; } OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(OMPClause *C) { auto *Res = OMPClauseWithPostUpdate::get(const_cast(C)); return Res ? const_cast(Res) : nullptr; } const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C) { switch (C->getClauseKind()) { case OMPC_lastprivate: return static_cast(C); case OMPC_reduction: return static_cast(C); case OMPC_task_reduction: return static_cast(C); case OMPC_in_reduction: return static_cast(C); case OMPC_linear: return static_cast(C); case OMPC_schedule: case OMPC_dist_schedule: case OMPC_firstprivate: case OMPC_default: case OMPC_proc_bind: case OMPC_if: case OMPC_final: case OMPC_num_threads: case OMPC_safelen: case OMPC_simdlen: case OMPC_sizes: case OMPC_allocator: case OMPC_allocate: case OMPC_collapse: case OMPC_private: case OMPC_shared: case OMPC_aligned: case OMPC_copyin: case OMPC_copyprivate: case OMPC_ordered: case OMPC_nowait: case OMPC_untied: case OMPC_mergeable: case OMPC_threadprivate: case OMPC_flush: case OMPC_depobj: case OMPC_read: case OMPC_write: case OMPC_update: case OMPC_capture: case OMPC_compare: case OMPC_fail: case OMPC_seq_cst: case OMPC_acq_rel: case OMPC_acquire: case OMPC_release: case OMPC_relaxed: case OMPC_depend: case OMPC_device: case OMPC_threads: case OMPC_simd: case OMPC_map: case OMPC_num_teams: case OMPC_thread_limit: case OMPC_priority: case OMPC_grainsize: case OMPC_nogroup: case OMPC_num_tasks: case OMPC_hint: case OMPC_defaultmap: case OMPC_unknown: case OMPC_uniform: case OMPC_to: case OMPC_from: case OMPC_use_device_ptr: case OMPC_use_device_addr: case OMPC_is_device_ptr: case OMPC_has_device_addr: case OMPC_unified_address: case OMPC_unified_shared_memory: case OMPC_reverse_offload: case OMPC_dynamic_allocators: case OMPC_atomic_default_mem_order: case OMPC_at: case OMPC_severity: case OMPC_message: case OMPC_device_type: case OMPC_match: case OMPC_nontemporal: case OMPC_order: case OMPC_destroy: case OMPC_novariants: case OMPC_nocontext: case OMPC_detach: case OMPC_inclusive: case OMPC_exclusive: case OMPC_uses_allocators: case OMPC_affinity: case OMPC_when: case OMPC_bind: break; default: break; } return nullptr; } /// Gets the address of the original, non-captured, expression used in the /// clause as the preinitializer. static Stmt **getAddrOfExprAsWritten(Stmt *S) { if (!S) return nullptr; if (auto *DS = dyn_cast(S)) { assert(DS->isSingleDecl() && "Only single expression must be captured."); if (auto *OED = dyn_cast(DS->getSingleDecl())) return OED->getInitAddress(); } return nullptr; } OMPClause::child_range OMPIfClause::used_children() { if (Stmt **C = getAddrOfExprAsWritten(getPreInitStmt())) return child_range(C, C + 1); return child_range(&Condition, &Condition + 1); } OMPClause::child_range OMPGrainsizeClause::used_children() { if (Stmt **C = getAddrOfExprAsWritten(getPreInitStmt())) return child_range(C, C + 1); return child_range(&Grainsize, &Grainsize + 1); } OMPClause::child_range OMPNumTasksClause::used_children() { if (Stmt **C = getAddrOfExprAsWritten(getPreInitStmt())) return child_range(C, C + 1); return child_range(&NumTasks, &NumTasks + 1); } OMPClause::child_range OMPFinalClause::used_children() { if (Stmt **C = getAddrOfExprAsWritten(getPreInitStmt())) return child_range(C, C + 1); return children(); } OMPClause::child_range OMPPriorityClause::used_children() { if (Stmt **C = getAddrOfExprAsWritten(getPreInitStmt())) return child_range(C, C + 1); return child_range(&Priority, &Priority + 1); } OMPClause::child_range OMPNovariantsClause::used_children() { if (Stmt **C = getAddrOfExprAsWritten(getPreInitStmt())) return child_range(C, C + 1); return children(); } OMPClause::child_range OMPNocontextClause::used_children() { if (Stmt **C = getAddrOfExprAsWritten(getPreInitStmt())) return child_range(C, C + 1); return children(); } OMPOrderedClause *OMPOrderedClause::Create(const ASTContext &C, Expr *Num, unsigned NumLoops, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { void *Mem = C.Allocate(totalSizeToAlloc(2 * NumLoops)); auto *Clause = new (Mem) OMPOrderedClause(Num, NumLoops, StartLoc, LParenLoc, EndLoc); for (unsigned I = 0; I < NumLoops; ++I) { Clause->setLoopNumIterations(I, nullptr); Clause->setLoopCounter(I, nullptr); } return Clause; } OMPOrderedClause *OMPOrderedClause::CreateEmpty(const ASTContext &C, unsigned NumLoops) { void *Mem = C.Allocate(totalSizeToAlloc(2 * NumLoops)); auto *Clause = new (Mem) OMPOrderedClause(NumLoops); for (unsigned I = 0; I < NumLoops; ++I) { Clause->setLoopNumIterations(I, nullptr); Clause->setLoopCounter(I, nullptr); } return Clause; } void OMPOrderedClause::setLoopNumIterations(unsigned NumLoop, Expr *NumIterations) { assert(NumLoop < NumberOfLoops && "out of loops number."); getTrailingObjects()[NumLoop] = NumIterations; } ArrayRef OMPOrderedClause::getLoopNumIterations() const { return llvm::ArrayRef(getTrailingObjects(), NumberOfLoops); } void OMPOrderedClause::setLoopCounter(unsigned NumLoop, Expr *Counter) { assert(NumLoop < NumberOfLoops && "out of loops number."); getTrailingObjects()[NumberOfLoops + NumLoop] = Counter; } Expr *OMPOrderedClause::getLoopCounter(unsigned NumLoop) { assert(NumLoop < NumberOfLoops && "out of loops number."); return getTrailingObjects()[NumberOfLoops + NumLoop]; } const Expr *OMPOrderedClause::getLoopCounter(unsigned NumLoop) const { assert(NumLoop < NumberOfLoops && "out of loops number."); return getTrailingObjects()[NumberOfLoops + NumLoop]; } OMPUpdateClause *OMPUpdateClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc) { return new (C) OMPUpdateClause(StartLoc, EndLoc, /*IsExtended=*/false); } OMPUpdateClause * OMPUpdateClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ArgumentLoc, OpenMPDependClauseKind DK, SourceLocation EndLoc) { void *Mem = C.Allocate(totalSizeToAlloc(2, 1), alignof(OMPUpdateClause)); auto *Clause = new (Mem) OMPUpdateClause(StartLoc, EndLoc, /*IsExtended=*/true); Clause->setLParenLoc(LParenLoc); Clause->setArgumentLoc(ArgumentLoc); Clause->setDependencyKind(DK); return Clause; } OMPUpdateClause *OMPUpdateClause::CreateEmpty(const ASTContext &C, bool IsExtended) { if (!IsExtended) return new (C) OMPUpdateClause(/*IsExtended=*/false); void *Mem = C.Allocate(totalSizeToAlloc(2, 1), alignof(OMPUpdateClause)); auto *Clause = new (Mem) OMPUpdateClause(/*IsExtended=*/true); Clause->IsExtended = true; return Clause; } void OMPPrivateClause::setPrivateCopies(ArrayRef VL) { assert(VL.size() == varlist_size() && "Number of private copies is not the same as the preallocated buffer"); std::copy(VL.begin(), VL.end(), varlist_end()); } OMPPrivateClause * OMPPrivateClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef VL, ArrayRef PrivateVL) { // Allocate space for private variables and initializer expressions. void *Mem = C.Allocate(totalSizeToAlloc(2 * VL.size())); OMPPrivateClause *Clause = new (Mem) OMPPrivateClause(StartLoc, LParenLoc, EndLoc, VL.size()); Clause->setVarRefs(VL); Clause->setPrivateCopies(PrivateVL); return Clause; } OMPPrivateClause *OMPPrivateClause::CreateEmpty(const ASTContext &C, unsigned N) { void *Mem = C.Allocate(totalSizeToAlloc(2 * N)); return new (Mem) OMPPrivateClause(N); } void OMPFirstprivateClause::setPrivateCopies(ArrayRef VL) { assert(VL.size() == varlist_size() && "Number of private copies is not the same as the preallocated buffer"); std::copy(VL.begin(), VL.end(), varlist_end()); } void OMPFirstprivateClause::setInits(ArrayRef VL) { assert(VL.size() == varlist_size() && "Number of inits is not the same as the preallocated buffer"); std::copy(VL.begin(), VL.end(), getPrivateCopies().end()); } OMPFirstprivateClause * OMPFirstprivateClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef VL, ArrayRef PrivateVL, ArrayRef InitVL, Stmt *PreInit) { void *Mem = C.Allocate(totalSizeToAlloc(3 * VL.size())); OMPFirstprivateClause *Clause = new (Mem) OMPFirstprivateClause(StartLoc, LParenLoc, EndLoc, VL.size()); Clause->setVarRefs(VL); Clause->setPrivateCopies(PrivateVL); Clause->setInits(InitVL); Clause->setPreInitStmt(PreInit); return Clause; } OMPFirstprivateClause *OMPFirstprivateClause::CreateEmpty(const ASTContext &C, unsigned N) { void *Mem = C.Allocate(totalSizeToAlloc(3 * N)); return new (Mem) OMPFirstprivateClause(N); } void OMPLastprivateClause::setPrivateCopies(ArrayRef PrivateCopies) { assert(PrivateCopies.size() == varlist_size() && "Number of private copies is not the same as the preallocated buffer"); std::copy(PrivateCopies.begin(), PrivateCopies.end(), varlist_end()); } void OMPLastprivateClause::setSourceExprs(ArrayRef SrcExprs) { assert(SrcExprs.size() == varlist_size() && "Number of source expressions is " "not the same as the " "preallocated buffer"); std::copy(SrcExprs.begin(), SrcExprs.end(), getPrivateCopies().end()); } void OMPLastprivateClause::setDestinationExprs(ArrayRef DstExprs) { assert(DstExprs.size() == varlist_size() && "Number of destination " "expressions is not the same as " "the preallocated buffer"); std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end()); } void OMPLastprivateClause::setAssignmentOps(ArrayRef AssignmentOps) { assert(AssignmentOps.size() == varlist_size() && "Number of assignment expressions is not the same as the preallocated " "buffer"); std::copy(AssignmentOps.begin(), AssignmentOps.end(), getDestinationExprs().end()); } OMPLastprivateClause *OMPLastprivateClause::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef VL, ArrayRef SrcExprs, ArrayRef DstExprs, ArrayRef AssignmentOps, OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, SourceLocation ColonLoc, Stmt *PreInit, Expr *PostUpdate) { void *Mem = C.Allocate(totalSizeToAlloc(5 * VL.size())); OMPLastprivateClause *Clause = new (Mem) OMPLastprivateClause( StartLoc, LParenLoc, EndLoc, LPKind, LPKindLoc, ColonLoc, VL.size()); Clause->setVarRefs(VL); Clause->setSourceExprs(SrcExprs); Clause->setDestinationExprs(DstExprs); Clause->setAssignmentOps(AssignmentOps); Clause->setPreInitStmt(PreInit); Clause->setPostUpdateExpr(PostUpdate); return Clause; } OMPLastprivateClause *OMPLastprivateClause::CreateEmpty(const ASTContext &C, unsigned N) { void *Mem = C.Allocate(totalSizeToAlloc(5 * N)); return new (Mem) OMPLastprivateClause(N); } OMPSharedClause *OMPSharedClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef VL) { void *Mem = C.Allocate(totalSizeToAlloc(VL.size())); OMPSharedClause *Clause = new (Mem) OMPSharedClause(StartLoc, LParenLoc, EndLoc, VL.size()); Clause->setVarRefs(VL); return Clause; } OMPSharedClause *OMPSharedClause::CreateEmpty(const ASTContext &C, unsigned N) { void *Mem = C.Allocate(totalSizeToAlloc(N)); return new (Mem) OMPSharedClause(N); } void OMPLinearClause::setPrivates(ArrayRef PL) { assert(PL.size() == varlist_size() && "Number of privates is not the same as the preallocated buffer"); std::copy(PL.begin(), PL.end(), varlist_end()); } void OMPLinearClause::setInits(ArrayRef IL) { assert(IL.size() == varlist_size() && "Number of inits is not the same as the preallocated buffer"); std::copy(IL.begin(), IL.end(), getPrivates().end()); } void OMPLinearClause::setUpdates(ArrayRef UL) { assert(UL.size() == varlist_size() && "Number of updates is not the same as the preallocated buffer"); std::copy(UL.begin(), UL.end(), getInits().end()); } void OMPLinearClause::setFinals(ArrayRef FL) { assert(FL.size() == varlist_size() && "Number of final updates is not the same as the preallocated buffer"); std::copy(FL.begin(), FL.end(), getUpdates().end()); } void OMPLinearClause::setUsedExprs(ArrayRef UE) { assert( UE.size() == varlist_size() + 1 && "Number of used expressions is not the same as the preallocated buffer"); std::copy(UE.begin(), UE.end(), getFinals().end() + 2); } OMPLinearClause *OMPLinearClause::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation StepModifierLoc, SourceLocation EndLoc, ArrayRef VL, ArrayRef PL, ArrayRef IL, Expr *Step, Expr *CalcStep, Stmt *PreInit, Expr *PostUpdate) { // Allocate space for 5 lists (Vars, Inits, Updates, Finals), 2 expressions // (Step and CalcStep), list of used expression + step. void *Mem = C.Allocate(totalSizeToAlloc(5 * VL.size() + 2 + VL.size() + 1)); OMPLinearClause *Clause = new (Mem) OMPLinearClause(StartLoc, LParenLoc, Modifier, ModifierLoc, ColonLoc, StepModifierLoc, EndLoc, VL.size()); Clause->setVarRefs(VL); Clause->setPrivates(PL); Clause->setInits(IL); // Fill update and final expressions with zeroes, they are provided later, // after the directive construction. std::fill(Clause->getInits().end(), Clause->getInits().end() + VL.size(), nullptr); std::fill(Clause->getUpdates().end(), Clause->getUpdates().end() + VL.size(), nullptr); std::fill(Clause->getUsedExprs().begin(), Clause->getUsedExprs().end(), nullptr); Clause->setStep(Step); Clause->setCalcStep(CalcStep); Clause->setPreInitStmt(PreInit); Clause->setPostUpdateExpr(PostUpdate); return Clause; } OMPLinearClause *OMPLinearClause::CreateEmpty(const ASTContext &C, unsigned NumVars) { // Allocate space for 5 lists (Vars, Inits, Updates, Finals), 2 expressions // (Step and CalcStep), list of used expression + step. void *Mem = C.Allocate(totalSizeToAlloc(5 * NumVars + 2 + NumVars +1)); return new (Mem) OMPLinearClause(NumVars); } OMPClause::child_range OMPLinearClause::used_children() { // Range includes only non-nullptr elements. return child_range( reinterpret_cast(getUsedExprs().begin()), reinterpret_cast(llvm::find(getUsedExprs(), nullptr))); } OMPAlignedClause * OMPAlignedClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef VL, Expr *A) { void *Mem = C.Allocate(totalSizeToAlloc(VL.size() + 1)); OMPAlignedClause *Clause = new (Mem) OMPAlignedClause(StartLoc, LParenLoc, ColonLoc, EndLoc, VL.size()); Clause->setVarRefs(VL); Clause->setAlignment(A); return Clause; } OMPAlignedClause *OMPAlignedClause::CreateEmpty(const ASTContext &C, unsigned NumVars) { void *Mem = C.Allocate(totalSizeToAlloc(NumVars + 1)); return new (Mem) OMPAlignedClause(NumVars); } OMPAlignClause *OMPAlignClause::Create(const ASTContext &C, Expr *A, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { return new (C) OMPAlignClause(A, StartLoc, LParenLoc, EndLoc); } void OMPCopyinClause::setSourceExprs(ArrayRef SrcExprs) { assert(SrcExprs.size() == varlist_size() && "Number of source expressions is " "not the same as the " "preallocated buffer"); std::copy(SrcExprs.begin(), SrcExprs.end(), varlist_end()); } void OMPCopyinClause::setDestinationExprs(ArrayRef DstExprs) { assert(DstExprs.size() == varlist_size() && "Number of destination " "expressions is not the same as " "the preallocated buffer"); std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end()); } void OMPCopyinClause::setAssignmentOps(ArrayRef AssignmentOps) { assert(AssignmentOps.size() == varlist_size() && "Number of assignment expressions is not the same as the preallocated " "buffer"); std::copy(AssignmentOps.begin(), AssignmentOps.end(), getDestinationExprs().end()); } OMPCopyinClause *OMPCopyinClause::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef VL, ArrayRef SrcExprs, ArrayRef DstExprs, ArrayRef AssignmentOps) { void *Mem = C.Allocate(totalSizeToAlloc(4 * VL.size())); OMPCopyinClause *Clause = new (Mem) OMPCopyinClause(StartLoc, LParenLoc, EndLoc, VL.size()); Clause->setVarRefs(VL); Clause->setSourceExprs(SrcExprs); Clause->setDestinationExprs(DstExprs); Clause->setAssignmentOps(AssignmentOps); return Clause; } OMPCopyinClause *OMPCopyinClause::CreateEmpty(const ASTContext &C, unsigned N) { void *Mem = C.Allocate(totalSizeToAlloc(4 * N)); return new (Mem) OMPCopyinClause(N); } void OMPCopyprivateClause::setSourceExprs(ArrayRef SrcExprs) { assert(SrcExprs.size() == varlist_size() && "Number of source expressions is " "not the same as the " "preallocated buffer"); std::copy(SrcExprs.begin(), SrcExprs.end(), varlist_end()); } void OMPCopyprivateClause::setDestinationExprs(ArrayRef DstExprs) { assert(DstExprs.size() == varlist_size() && "Number of destination " "expressions is not the same as " "the preallocated buffer"); std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end()); } void OMPCopyprivateClause::setAssignmentOps(ArrayRef AssignmentOps) { assert(AssignmentOps.size() == varlist_size() && "Number of assignment expressions is not the same as the preallocated " "buffer"); std::copy(AssignmentOps.begin(), AssignmentOps.end(), getDestinationExprs().end()); } OMPCopyprivateClause *OMPCopyprivateClause::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef VL, ArrayRef SrcExprs, ArrayRef DstExprs, ArrayRef AssignmentOps) { void *Mem = C.Allocate(totalSizeToAlloc(4 * VL.size())); OMPCopyprivateClause *Clause = new (Mem) OMPCopyprivateClause(StartLoc, LParenLoc, EndLoc, VL.size()); Clause->setVarRefs(VL); Clause->setSourceExprs(SrcExprs); Clause->setDestinationExprs(DstExprs); Clause->setAssignmentOps(AssignmentOps); return Clause; } OMPCopyprivateClause *OMPCopyprivateClause::CreateEmpty(const ASTContext &C, unsigned N) { void *Mem = C.Allocate(totalSizeToAlloc(4 * N)); return new (Mem) OMPCopyprivateClause(N); } void OMPReductionClause::setPrivates(ArrayRef Privates) { assert(Privates.size() == varlist_size() && "Number of private copies is not the same as the preallocated buffer"); std::copy(Privates.begin(), Privates.end(), varlist_end()); } void OMPReductionClause::setLHSExprs(ArrayRef LHSExprs) { assert( LHSExprs.size() == varlist_size() && "Number of LHS expressions is not the same as the preallocated buffer"); std::copy(LHSExprs.begin(), LHSExprs.end(), getPrivates().end()); } void OMPReductionClause::setRHSExprs(ArrayRef RHSExprs) { assert( RHSExprs.size() == varlist_size() && "Number of RHS expressions is not the same as the preallocated buffer"); std::copy(RHSExprs.begin(), RHSExprs.end(), getLHSExprs().end()); } void OMPReductionClause::setReductionOps(ArrayRef ReductionOps) { assert(ReductionOps.size() == varlist_size() && "Number of reduction " "expressions is not the same " "as the preallocated buffer"); std::copy(ReductionOps.begin(), ReductionOps.end(), getRHSExprs().end()); } void OMPReductionClause::setInscanCopyOps(ArrayRef Ops) { assert(Modifier == OMPC_REDUCTION_inscan && "Expected inscan reduction."); assert(Ops.size() == varlist_size() && "Number of copy " "expressions is not the same " "as the preallocated buffer"); llvm::copy(Ops, getReductionOps().end()); } void OMPReductionClause::setInscanCopyArrayTemps( ArrayRef CopyArrayTemps) { assert(Modifier == OMPC_REDUCTION_inscan && "Expected inscan reduction."); assert(CopyArrayTemps.size() == varlist_size() && "Number of copy temp expressions is not the same as the preallocated " "buffer"); llvm::copy(CopyArrayTemps, getInscanCopyOps().end()); } void OMPReductionClause::setInscanCopyArrayElems( ArrayRef CopyArrayElems) { assert(Modifier == OMPC_REDUCTION_inscan && "Expected inscan reduction."); assert(CopyArrayElems.size() == varlist_size() && "Number of copy temp expressions is not the same as the preallocated " "buffer"); llvm::copy(CopyArrayElems, getInscanCopyArrayTemps().end()); } OMPReductionClause *OMPReductionClause::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc, SourceLocation ColonLoc, OpenMPReductionClauseModifier Modifier, ArrayRef VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef Privates, ArrayRef LHSExprs, ArrayRef RHSExprs, ArrayRef ReductionOps, ArrayRef CopyOps, ArrayRef CopyArrayTemps, ArrayRef CopyArrayElems, Stmt *PreInit, Expr *PostUpdate) { void *Mem = C.Allocate(totalSizeToAlloc( (Modifier == OMPC_REDUCTION_inscan ? 8 : 5) * VL.size())); auto *Clause = new (Mem) OMPReductionClause(StartLoc, LParenLoc, ModifierLoc, EndLoc, ColonLoc, Modifier, VL.size(), QualifierLoc, NameInfo); Clause->setVarRefs(VL); Clause->setPrivates(Privates); Clause->setLHSExprs(LHSExprs); Clause->setRHSExprs(RHSExprs); Clause->setReductionOps(ReductionOps); Clause->setPreInitStmt(PreInit); Clause->setPostUpdateExpr(PostUpdate); if (Modifier == OMPC_REDUCTION_inscan) { Clause->setInscanCopyOps(CopyOps); Clause->setInscanCopyArrayTemps(CopyArrayTemps); Clause->setInscanCopyArrayElems(CopyArrayElems); } else { assert(CopyOps.empty() && "copy operations are expected in inscan reductions only."); assert(CopyArrayTemps.empty() && "copy array temps are expected in inscan reductions only."); assert(CopyArrayElems.empty() && "copy array temps are expected in inscan reductions only."); } return Clause; } OMPReductionClause * OMPReductionClause::CreateEmpty(const ASTContext &C, unsigned N, OpenMPReductionClauseModifier Modifier) { void *Mem = C.Allocate(totalSizeToAlloc( (Modifier == OMPC_REDUCTION_inscan ? 8 : 5) * N)); auto *Clause = new (Mem) OMPReductionClause(N); Clause->setModifier(Modifier); return Clause; } void OMPTaskReductionClause::setPrivates(ArrayRef Privates) { assert(Privates.size() == varlist_size() && "Number of private copies is not the same as the preallocated buffer"); std::copy(Privates.begin(), Privates.end(), varlist_end()); } void OMPTaskReductionClause::setLHSExprs(ArrayRef LHSExprs) { assert( LHSExprs.size() == varlist_size() && "Number of LHS expressions is not the same as the preallocated buffer"); std::copy(LHSExprs.begin(), LHSExprs.end(), getPrivates().end()); } void OMPTaskReductionClause::setRHSExprs(ArrayRef RHSExprs) { assert( RHSExprs.size() == varlist_size() && "Number of RHS expressions is not the same as the preallocated buffer"); std::copy(RHSExprs.begin(), RHSExprs.end(), getLHSExprs().end()); } void OMPTaskReductionClause::setReductionOps(ArrayRef ReductionOps) { assert(ReductionOps.size() == varlist_size() && "Number of task reduction " "expressions is not the same " "as the preallocated buffer"); std::copy(ReductionOps.begin(), ReductionOps.end(), getRHSExprs().end()); } OMPTaskReductionClause *OMPTaskReductionClause::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef Privates, ArrayRef LHSExprs, ArrayRef RHSExprs, ArrayRef ReductionOps, Stmt *PreInit, Expr *PostUpdate) { void *Mem = C.Allocate(totalSizeToAlloc(5 * VL.size())); OMPTaskReductionClause *Clause = new (Mem) OMPTaskReductionClause( StartLoc, LParenLoc, EndLoc, ColonLoc, VL.size(), QualifierLoc, NameInfo); Clause->setVarRefs(VL); Clause->setPrivates(Privates); Clause->setLHSExprs(LHSExprs); Clause->setRHSExprs(RHSExprs); Clause->setReductionOps(ReductionOps); Clause->setPreInitStmt(PreInit); Clause->setPostUpdateExpr(PostUpdate); return Clause; } OMPTaskReductionClause *OMPTaskReductionClause::CreateEmpty(const ASTContext &C, unsigned N) { void *Mem = C.Allocate(totalSizeToAlloc(5 * N)); return new (Mem) OMPTaskReductionClause(N); } void OMPInReductionClause::setPrivates(ArrayRef Privates) { assert(Privates.size() == varlist_size() && "Number of private copies is not the same as the preallocated buffer"); std::copy(Privates.begin(), Privates.end(), varlist_end()); } void OMPInReductionClause::setLHSExprs(ArrayRef LHSExprs) { assert( LHSExprs.size() == varlist_size() && "Number of LHS expressions is not the same as the preallocated buffer"); std::copy(LHSExprs.begin(), LHSExprs.end(), getPrivates().end()); } void OMPInReductionClause::setRHSExprs(ArrayRef RHSExprs) { assert( RHSExprs.size() == varlist_size() && "Number of RHS expressions is not the same as the preallocated buffer"); std::copy(RHSExprs.begin(), RHSExprs.end(), getLHSExprs().end()); } void OMPInReductionClause::setReductionOps(ArrayRef ReductionOps) { assert(ReductionOps.size() == varlist_size() && "Number of in reduction " "expressions is not the same " "as the preallocated buffer"); std::copy(ReductionOps.begin(), ReductionOps.end(), getRHSExprs().end()); } void OMPInReductionClause::setTaskgroupDescriptors( ArrayRef TaskgroupDescriptors) { assert(TaskgroupDescriptors.size() == varlist_size() && "Number of in reduction descriptors is not the same as the " "preallocated buffer"); std::copy(TaskgroupDescriptors.begin(), TaskgroupDescriptors.end(), getReductionOps().end()); } OMPInReductionClause *OMPInReductionClause::Create( const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef Privates, ArrayRef LHSExprs, ArrayRef RHSExprs, ArrayRef ReductionOps, ArrayRef TaskgroupDescriptors, Stmt *PreInit, Expr *PostUpdate) { void *Mem = C.Allocate(totalSizeToAlloc(6 * VL.size())); OMPInReductionClause *Clause = new (Mem) OMPInReductionClause( StartLoc, LParenLoc, EndLoc, ColonLoc, VL.size(), QualifierLoc, NameInfo); Clause->setVarRefs(VL); Clause->setPrivates(Privates); Clause->setLHSExprs(LHSExprs); Clause->setRHSExprs(RHSExprs); Clause->setReductionOps(ReductionOps); Clause->setTaskgroupDescriptors(TaskgroupDescriptors); Clause->setPreInitStmt(PreInit); Clause->setPostUpdateExpr(PostUpdate); return Clause; } OMPInReductionClause *OMPInReductionClause::CreateEmpty(const ASTContext &C, unsigned N) { void *Mem = C.Allocate(totalSizeToAlloc(6 * N)); return new (Mem) OMPInReductionClause(N); } OMPSizesClause *OMPSizesClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef Sizes) { OMPSizesClause *Clause = CreateEmpty(C, Sizes.size()); Clause->setLocStart(StartLoc); Clause->setLParenLoc(LParenLoc); Clause->setLocEnd(EndLoc); Clause->setSizesRefs(Sizes); return Clause; } OMPSizesClause *OMPSizesClause::CreateEmpty(const ASTContext &C, unsigned NumSizes) { void *Mem = C.Allocate(totalSizeToAlloc(NumSizes)); return new (Mem) OMPSizesClause(NumSizes); } OMPFullClause *OMPFullClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc) { OMPFullClause *Clause = CreateEmpty(C); Clause->setLocStart(StartLoc); Clause->setLocEnd(EndLoc); return Clause; } OMPFullClause *OMPFullClause::CreateEmpty(const ASTContext &C) { return new (C) OMPFullClause(); } OMPPartialClause *OMPPartialClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, Expr *Factor) { OMPPartialClause *Clause = CreateEmpty(C); Clause->setLocStart(StartLoc); Clause->setLParenLoc(LParenLoc); Clause->setLocEnd(EndLoc); Clause->setFactor(Factor); return Clause; } OMPPartialClause *OMPPartialClause::CreateEmpty(const ASTContext &C) { return new (C) OMPPartialClause(); } OMPAllocateClause * OMPAllocateClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, Expr *Allocator, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef VL) { // Allocate space for private variables and initializer expressions. void *Mem = C.Allocate(totalSizeToAlloc(VL.size())); auto *Clause = new (Mem) OMPAllocateClause(StartLoc, LParenLoc, Allocator, ColonLoc, EndLoc, VL.size()); Clause->setVarRefs(VL); return Clause; } OMPAllocateClause *OMPAllocateClause::CreateEmpty(const ASTContext &C, unsigned N) { void *Mem = C.Allocate(totalSizeToAlloc(N)); return new (Mem) OMPAllocateClause(N); } OMPFlushClause *OMPFlushClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef VL) { void *Mem = C.Allocate(totalSizeToAlloc(VL.size() + 1)); OMPFlushClause *Clause = new (Mem) OMPFlushClause(StartLoc, LParenLoc, EndLoc, VL.size()); Clause->setVarRefs(VL); return Clause; } OMPFlushClause *OMPFlushClause::CreateEmpty(const ASTContext &C, unsigned N) { void *Mem = C.Allocate(totalSizeToAlloc(N)); return new (Mem) OMPFlushClause(N); } OMPDepobjClause *OMPDepobjClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation RParenLoc, Expr *Depobj) { auto *Clause = new (C) OMPDepobjClause(StartLoc, LParenLoc, RParenLoc); Clause->setDepobj(Depobj); return Clause; } OMPDepobjClause *OMPDepobjClause::CreateEmpty(const ASTContext &C) { return new (C) OMPDepobjClause(); } OMPDependClause * OMPDependClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, DependDataTy Data, Expr *DepModifier, ArrayRef VL, unsigned NumLoops) { void *Mem = C.Allocate( totalSizeToAlloc(VL.size() + /*depend-modifier*/ 1 + NumLoops), alignof(OMPDependClause)); OMPDependClause *Clause = new (Mem) OMPDependClause(StartLoc, LParenLoc, EndLoc, VL.size(), NumLoops); Clause->setDependencyKind(Data.DepKind); Clause->setDependencyLoc(Data.DepLoc); Clause->setColonLoc(Data.ColonLoc); Clause->setOmpAllMemoryLoc(Data.OmpAllMemoryLoc); Clause->setModifier(DepModifier); Clause->setVarRefs(VL); for (unsigned I = 0 ; I < NumLoops; ++I) Clause->setLoopData(I, nullptr); return Clause; } OMPDependClause *OMPDependClause::CreateEmpty(const ASTContext &C, unsigned N, unsigned NumLoops) { void *Mem = C.Allocate(totalSizeToAlloc(N + /*depend-modifier*/ 1 + NumLoops), alignof(OMPDependClause)); return new (Mem) OMPDependClause(N, NumLoops); } void OMPDependClause::setLoopData(unsigned NumLoop, Expr *Cnt) { assert((getDependencyKind() == OMPC_DEPEND_sink || getDependencyKind() == OMPC_DEPEND_source) && NumLoop < NumLoops && "Expected sink or source depend + loop index must be less number of " "loops."); auto *It = std::next(getVarRefs().end(), NumLoop + 1); *It = Cnt; } Expr *OMPDependClause::getLoopData(unsigned NumLoop) { assert((getDependencyKind() == OMPC_DEPEND_sink || getDependencyKind() == OMPC_DEPEND_source) && NumLoop < NumLoops && "Expected sink or source depend + loop index must be less number of " "loops."); auto *It = std::next(getVarRefs().end(), NumLoop + 1); return *It; } const Expr *OMPDependClause::getLoopData(unsigned NumLoop) const { assert((getDependencyKind() == OMPC_DEPEND_sink || getDependencyKind() == OMPC_DEPEND_source) && NumLoop < NumLoops && "Expected sink or source depend + loop index must be less number of " "loops."); const auto *It = std::next(getVarRefs().end(), NumLoop + 1); return *It; } void OMPDependClause::setModifier(Expr *DepModifier) { *getVarRefs().end() = DepModifier; } Expr *OMPDependClause::getModifier() { return *getVarRefs().end(); } unsigned OMPClauseMappableExprCommon::getComponentsTotalNumber( MappableExprComponentListsRef ComponentLists) { unsigned TotalNum = 0u; for (auto &C : ComponentLists) TotalNum += C.size(); return TotalNum; } unsigned OMPClauseMappableExprCommon::getUniqueDeclarationsTotalNumber( ArrayRef Declarations) { unsigned TotalNum = 0u; llvm::SmallPtrSet Cache; for (const ValueDecl *D : Declarations) { const ValueDecl *VD = D ? cast(D->getCanonicalDecl()) : nullptr; if (Cache.count(VD)) continue; ++TotalNum; Cache.insert(VD); } return TotalNum; } OMPMapClause *OMPMapClause::Create( const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef Vars, ArrayRef Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef UDMapperRefs, Expr *IteratorModifier, ArrayRef MapModifiers, ArrayRef MapModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId, OpenMPMapClauseKind Type, bool TypeIsImplicit, SourceLocation TypeLoc) { OMPMappableExprListSizeTy Sizes; Sizes.NumVars = Vars.size(); Sizes.NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations); Sizes.NumComponentLists = ComponentLists.size(); Sizes.NumComponents = getComponentsTotalNumber(ComponentLists); // We need to allocate: // 2 x NumVars x Expr* - we have an original list expression and an associated // user-defined mapper for each clause list entry. // NumUniqueDeclarations x ValueDecl* - unique base declarations associated // with each component list. // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the // number of lists for each unique declaration and the size of each component // list. // NumComponents x MappableComponent - the total of all the components in all // the lists. void *Mem = C.Allocate( totalSizeToAlloc( 2 * Sizes.NumVars + 1, Sizes.NumUniqueDeclarations, Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, Sizes.NumComponents)); OMPMapClause *Clause = new (Mem) OMPMapClause(MapModifiers, MapModifiersLoc, UDMQualifierLoc, MapperId, Type, TypeIsImplicit, TypeLoc, Locs, Sizes); Clause->setVarRefs(Vars); Clause->setUDMapperRefs(UDMapperRefs); Clause->setIteratorModifier(IteratorModifier); Clause->setClauseInfo(Declarations, ComponentLists); Clause->setMapType(Type); Clause->setMapLoc(TypeLoc); return Clause; } OMPMapClause * OMPMapClause::CreateEmpty(const ASTContext &C, const OMPMappableExprListSizeTy &Sizes) { void *Mem = C.Allocate( totalSizeToAlloc( 2 * Sizes.NumVars + 1, Sizes.NumUniqueDeclarations, Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, Sizes.NumComponents)); OMPMapClause *Clause = new (Mem) OMPMapClause(Sizes); Clause->setIteratorModifier(nullptr); return Clause; } OMPToClause *OMPToClause::Create( const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef Vars, ArrayRef Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef UDMapperRefs, ArrayRef MotionModifiers, ArrayRef MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId) { OMPMappableExprListSizeTy Sizes; Sizes.NumVars = Vars.size(); Sizes.NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations); Sizes.NumComponentLists = ComponentLists.size(); Sizes.NumComponents = getComponentsTotalNumber(ComponentLists); // We need to allocate: // 2 x NumVars x Expr* - we have an original list expression and an associated // user-defined mapper for each clause list entry. // NumUniqueDeclarations x ValueDecl* - unique base declarations associated // with each component list. // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the // number of lists for each unique declaration and the size of each component // list. // NumComponents x MappableComponent - the total of all the components in all // the lists. void *Mem = C.Allocate( totalSizeToAlloc( 2 * Sizes.NumVars, Sizes.NumUniqueDeclarations, Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, Sizes.NumComponents)); auto *Clause = new (Mem) OMPToClause(MotionModifiers, MotionModifiersLoc, UDMQualifierLoc, MapperId, Locs, Sizes); Clause->setVarRefs(Vars); Clause->setUDMapperRefs(UDMapperRefs); Clause->setClauseInfo(Declarations, ComponentLists); return Clause; } OMPToClause *OMPToClause::CreateEmpty(const ASTContext &C, const OMPMappableExprListSizeTy &Sizes) { void *Mem = C.Allocate( totalSizeToAlloc( 2 * Sizes.NumVars, Sizes.NumUniqueDeclarations, Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, Sizes.NumComponents)); return new (Mem) OMPToClause(Sizes); } OMPFromClause *OMPFromClause::Create( const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef Vars, ArrayRef Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef UDMapperRefs, ArrayRef MotionModifiers, ArrayRef MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId) { OMPMappableExprListSizeTy Sizes; Sizes.NumVars = Vars.size(); Sizes.NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations); Sizes.NumComponentLists = ComponentLists.size(); Sizes.NumComponents = getComponentsTotalNumber(ComponentLists); // We need to allocate: // 2 x NumVars x Expr* - we have an original list expression and an associated // user-defined mapper for each clause list entry. // NumUniqueDeclarations x ValueDecl* - unique base declarations associated // with each component list. // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the // number of lists for each unique declaration and the size of each component // list. // NumComponents x MappableComponent - the total of all the components in all // the lists. void *Mem = C.Allocate( totalSizeToAlloc( 2 * Sizes.NumVars, Sizes.NumUniqueDeclarations, Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, Sizes.NumComponents)); auto *Clause = new (Mem) OMPFromClause(MotionModifiers, MotionModifiersLoc, UDMQualifierLoc, MapperId, Locs, Sizes); Clause->setVarRefs(Vars); Clause->setUDMapperRefs(UDMapperRefs); Clause->setClauseInfo(Declarations, ComponentLists); return Clause; } OMPFromClause * OMPFromClause::CreateEmpty(const ASTContext &C, const OMPMappableExprListSizeTy &Sizes) { void *Mem = C.Allocate( totalSizeToAlloc( 2 * Sizes.NumVars, Sizes.NumUniqueDeclarations, Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, Sizes.NumComponents)); return new (Mem) OMPFromClause(Sizes); } void OMPUseDevicePtrClause::setPrivateCopies(ArrayRef VL) { assert(VL.size() == varlist_size() && "Number of private copies is not the same as the preallocated buffer"); std::copy(VL.begin(), VL.end(), varlist_end()); } void OMPUseDevicePtrClause::setInits(ArrayRef VL) { assert(VL.size() == varlist_size() && "Number of inits is not the same as the preallocated buffer"); std::copy(VL.begin(), VL.end(), getPrivateCopies().end()); } OMPUseDevicePtrClause *OMPUseDevicePtrClause::Create( const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef Vars, ArrayRef PrivateVars, ArrayRef Inits, ArrayRef Declarations, MappableExprComponentListsRef ComponentLists) { OMPMappableExprListSizeTy Sizes; Sizes.NumVars = Vars.size(); Sizes.NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations); Sizes.NumComponentLists = ComponentLists.size(); Sizes.NumComponents = getComponentsTotalNumber(ComponentLists); // We need to allocate: // NumVars x Expr* - we have an original list expression for each clause // list entry. // NumUniqueDeclarations x ValueDecl* - unique base declarations associated // with each component list. // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the // number of lists for each unique declaration and the size of each component // list. // NumComponents x MappableComponent - the total of all the components in all // the lists. void *Mem = C.Allocate( totalSizeToAlloc( 3 * Sizes.NumVars, Sizes.NumUniqueDeclarations, Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, Sizes.NumComponents)); OMPUseDevicePtrClause *Clause = new (Mem) OMPUseDevicePtrClause(Locs, Sizes); Clause->setVarRefs(Vars); Clause->setPrivateCopies(PrivateVars); Clause->setInits(Inits); Clause->setClauseInfo(Declarations, ComponentLists); return Clause; } OMPUseDevicePtrClause * OMPUseDevicePtrClause::CreateEmpty(const ASTContext &C, const OMPMappableExprListSizeTy &Sizes) { void *Mem = C.Allocate( totalSizeToAlloc( 3 * Sizes.NumVars, Sizes.NumUniqueDeclarations, Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, Sizes.NumComponents)); return new (Mem) OMPUseDevicePtrClause(Sizes); } OMPUseDeviceAddrClause * OMPUseDeviceAddrClause::Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef Vars, ArrayRef Declarations, MappableExprComponentListsRef ComponentLists) { OMPMappableExprListSizeTy Sizes; Sizes.NumVars = Vars.size(); Sizes.NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations); Sizes.NumComponentLists = ComponentLists.size(); Sizes.NumComponents = getComponentsTotalNumber(ComponentLists); // We need to allocate: // 3 x NumVars x Expr* - we have an original list expression for each clause // list entry and an equal number of private copies and inits. // NumUniqueDeclarations x ValueDecl* - unique base declarations associated // with each component list. // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the // number of lists for each unique declaration and the size of each component // list. // NumComponents x MappableComponent - the total of all the components in all // the lists. void *Mem = C.Allocate( totalSizeToAlloc( Sizes.NumVars, Sizes.NumUniqueDeclarations, Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, Sizes.NumComponents)); auto *Clause = new (Mem) OMPUseDeviceAddrClause(Locs, Sizes); Clause->setVarRefs(Vars); Clause->setClauseInfo(Declarations, ComponentLists); return Clause; } OMPUseDeviceAddrClause * OMPUseDeviceAddrClause::CreateEmpty(const ASTContext &C, const OMPMappableExprListSizeTy &Sizes) { void *Mem = C.Allocate( totalSizeToAlloc( Sizes.NumVars, Sizes.NumUniqueDeclarations, Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, Sizes.NumComponents)); return new (Mem) OMPUseDeviceAddrClause(Sizes); } OMPIsDevicePtrClause * OMPIsDevicePtrClause::Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef Vars, ArrayRef Declarations, MappableExprComponentListsRef ComponentLists) { OMPMappableExprListSizeTy Sizes; Sizes.NumVars = Vars.size(); Sizes.NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations); Sizes.NumComponentLists = ComponentLists.size(); Sizes.NumComponents = getComponentsTotalNumber(ComponentLists); // We need to allocate: // NumVars x Expr* - we have an original list expression for each clause list // entry. // NumUniqueDeclarations x ValueDecl* - unique base declarations associated // with each component list. // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the // number of lists for each unique declaration and the size of each component // list. // NumComponents x MappableComponent - the total of all the components in all // the lists. void *Mem = C.Allocate( totalSizeToAlloc( Sizes.NumVars, Sizes.NumUniqueDeclarations, Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, Sizes.NumComponents)); OMPIsDevicePtrClause *Clause = new (Mem) OMPIsDevicePtrClause(Locs, Sizes); Clause->setVarRefs(Vars); Clause->setClauseInfo(Declarations, ComponentLists); return Clause; } OMPIsDevicePtrClause * OMPIsDevicePtrClause::CreateEmpty(const ASTContext &C, const OMPMappableExprListSizeTy &Sizes) { void *Mem = C.Allocate( totalSizeToAlloc( Sizes.NumVars, Sizes.NumUniqueDeclarations, Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, Sizes.NumComponents)); return new (Mem) OMPIsDevicePtrClause(Sizes); } OMPHasDeviceAddrClause * OMPHasDeviceAddrClause::Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef Vars, ArrayRef Declarations, MappableExprComponentListsRef ComponentLists) { OMPMappableExprListSizeTy Sizes; Sizes.NumVars = Vars.size(); Sizes.NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations); Sizes.NumComponentLists = ComponentLists.size(); Sizes.NumComponents = getComponentsTotalNumber(ComponentLists); // We need to allocate: // NumVars x Expr* - we have an original list expression for each clause list // entry. // NumUniqueDeclarations x ValueDecl* - unique base declarations associated // with each component list. // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the // number of lists for each unique declaration and the size of each component // list. // NumComponents x MappableComponent - the total of all the components in all // the lists. void *Mem = C.Allocate( totalSizeToAlloc( Sizes.NumVars, Sizes.NumUniqueDeclarations, Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, Sizes.NumComponents)); auto *Clause = new (Mem) OMPHasDeviceAddrClause(Locs, Sizes); Clause->setVarRefs(Vars); Clause->setClauseInfo(Declarations, ComponentLists); return Clause; } OMPHasDeviceAddrClause * OMPHasDeviceAddrClause::CreateEmpty(const ASTContext &C, const OMPMappableExprListSizeTy &Sizes) { void *Mem = C.Allocate( totalSizeToAlloc( Sizes.NumVars, Sizes.NumUniqueDeclarations, Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, Sizes.NumComponents)); return new (Mem) OMPHasDeviceAddrClause(Sizes); } OMPNontemporalClause *OMPNontemporalClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef VL) { // Allocate space for nontemporal variables + private references. void *Mem = C.Allocate(totalSizeToAlloc(2 * VL.size())); auto *Clause = new (Mem) OMPNontemporalClause(StartLoc, LParenLoc, EndLoc, VL.size()); Clause->setVarRefs(VL); return Clause; } OMPNontemporalClause *OMPNontemporalClause::CreateEmpty(const ASTContext &C, unsigned N) { void *Mem = C.Allocate(totalSizeToAlloc(2 * N)); return new (Mem) OMPNontemporalClause(N); } void OMPNontemporalClause::setPrivateRefs(ArrayRef VL) { assert(VL.size() == varlist_size() && "Number of private references is not " "the same as the preallocated buffer"); std::copy(VL.begin(), VL.end(), varlist_end()); } OMPInclusiveClause *OMPInclusiveClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef VL) { void *Mem = C.Allocate(totalSizeToAlloc(VL.size())); auto *Clause = new (Mem) OMPInclusiveClause(StartLoc, LParenLoc, EndLoc, VL.size()); Clause->setVarRefs(VL); return Clause; } OMPInclusiveClause *OMPInclusiveClause::CreateEmpty(const ASTContext &C, unsigned N) { void *Mem = C.Allocate(totalSizeToAlloc(N)); return new (Mem) OMPInclusiveClause(N); } OMPExclusiveClause *OMPExclusiveClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef VL) { void *Mem = C.Allocate(totalSizeToAlloc(VL.size())); auto *Clause = new (Mem) OMPExclusiveClause(StartLoc, LParenLoc, EndLoc, VL.size()); Clause->setVarRefs(VL); return Clause; } OMPExclusiveClause *OMPExclusiveClause::CreateEmpty(const ASTContext &C, unsigned N) { void *Mem = C.Allocate(totalSizeToAlloc(N)); return new (Mem) OMPExclusiveClause(N); } void OMPUsesAllocatorsClause::setAllocatorsData( ArrayRef Data) { assert(Data.size() == NumOfAllocators && "Size of allocators data is not the same as the preallocated buffer."); for (unsigned I = 0, E = Data.size(); I < E; ++I) { const OMPUsesAllocatorsClause::Data &D = Data[I]; getTrailingObjects()[I * static_cast(ExprOffsets::Total) + static_cast(ExprOffsets::Allocator)] = D.Allocator; getTrailingObjects()[I * static_cast(ExprOffsets::Total) + static_cast( ExprOffsets::AllocatorTraits)] = D.AllocatorTraits; getTrailingObjects< SourceLocation>()[I * static_cast(ParenLocsOffsets::Total) + static_cast(ParenLocsOffsets::LParen)] = D.LParenLoc; getTrailingObjects< SourceLocation>()[I * static_cast(ParenLocsOffsets::Total) + static_cast(ParenLocsOffsets::RParen)] = D.RParenLoc; } } OMPUsesAllocatorsClause::Data OMPUsesAllocatorsClause::getAllocatorData(unsigned I) const { OMPUsesAllocatorsClause::Data Data; Data.Allocator = getTrailingObjects()[I * static_cast(ExprOffsets::Total) + static_cast(ExprOffsets::Allocator)]; Data.AllocatorTraits = getTrailingObjects()[I * static_cast(ExprOffsets::Total) + static_cast( ExprOffsets::AllocatorTraits)]; Data.LParenLoc = getTrailingObjects< SourceLocation>()[I * static_cast(ParenLocsOffsets::Total) + static_cast(ParenLocsOffsets::LParen)]; Data.RParenLoc = getTrailingObjects< SourceLocation>()[I * static_cast(ParenLocsOffsets::Total) + static_cast(ParenLocsOffsets::RParen)]; return Data; } OMPUsesAllocatorsClause * OMPUsesAllocatorsClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef Data) { void *Mem = C.Allocate(totalSizeToAlloc( static_cast(ExprOffsets::Total) * Data.size(), static_cast(ParenLocsOffsets::Total) * Data.size())); auto *Clause = new (Mem) OMPUsesAllocatorsClause(StartLoc, LParenLoc, EndLoc, Data.size()); Clause->setAllocatorsData(Data); return Clause; } OMPUsesAllocatorsClause * OMPUsesAllocatorsClause::CreateEmpty(const ASTContext &C, unsigned N) { void *Mem = C.Allocate(totalSizeToAlloc( static_cast(ExprOffsets::Total) * N, static_cast(ParenLocsOffsets::Total) * N)); return new (Mem) OMPUsesAllocatorsClause(N); } OMPAffinityClause * OMPAffinityClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef Locators) { void *Mem = C.Allocate(totalSizeToAlloc(Locators.size() + 1)); auto *Clause = new (Mem) OMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc, Locators.size()); Clause->setModifier(Modifier); Clause->setVarRefs(Locators); return Clause; } OMPAffinityClause *OMPAffinityClause::CreateEmpty(const ASTContext &C, unsigned N) { void *Mem = C.Allocate(totalSizeToAlloc(N + 1)); return new (Mem) OMPAffinityClause(N); } OMPInitClause *OMPInitClause::Create(const ASTContext &C, Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) { void *Mem = C.Allocate(totalSizeToAlloc(InteropInfo.PreferTypes.size() + 1)); auto *Clause = new (Mem) OMPInitClause( InteropInfo.IsTarget, InteropInfo.IsTargetSync, StartLoc, LParenLoc, VarLoc, EndLoc, InteropInfo.PreferTypes.size() + 1); Clause->setInteropVar(InteropVar); llvm::copy(InteropInfo.PreferTypes, Clause->getTrailingObjects() + 1); return Clause; } OMPInitClause *OMPInitClause::CreateEmpty(const ASTContext &C, unsigned N) { void *Mem = C.Allocate(totalSizeToAlloc(N)); return new (Mem) OMPInitClause(N); } OMPBindClause * OMPBindClause::Create(const ASTContext &C, OpenMPBindClauseKind K, SourceLocation KLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { return new (C) OMPBindClause(K, KLoc, StartLoc, LParenLoc, EndLoc); } OMPBindClause *OMPBindClause::CreateEmpty(const ASTContext &C) { return new (C) OMPBindClause(); } OMPDoacrossClause * OMPDoacrossClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef VL, unsigned NumLoops) { void *Mem = C.Allocate(totalSizeToAlloc(VL.size() + NumLoops), alignof(OMPDoacrossClause)); OMPDoacrossClause *Clause = new (Mem) OMPDoacrossClause(StartLoc, LParenLoc, EndLoc, VL.size(), NumLoops); Clause->setDependenceType(DepType); Clause->setDependenceLoc(DepLoc); Clause->setColonLoc(ColonLoc); Clause->setVarRefs(VL); for (unsigned I = 0; I < NumLoops; ++I) Clause->setLoopData(I, nullptr); return Clause; } OMPDoacrossClause *OMPDoacrossClause::CreateEmpty(const ASTContext &C, unsigned N, unsigned NumLoops) { void *Mem = C.Allocate(totalSizeToAlloc(N + NumLoops), alignof(OMPDoacrossClause)); return new (Mem) OMPDoacrossClause(N, NumLoops); } void OMPDoacrossClause::setLoopData(unsigned NumLoop, Expr *Cnt) { assert(NumLoop < NumLoops && "Loop index must be less number of loops."); auto *It = std::next(getVarRefs().end(), NumLoop); *It = Cnt; } Expr *OMPDoacrossClause::getLoopData(unsigned NumLoop) { assert(NumLoop < NumLoops && "Loop index must be less number of loops."); auto *It = std::next(getVarRefs().end(), NumLoop); return *It; } const Expr *OMPDoacrossClause::getLoopData(unsigned NumLoop) const { assert(NumLoop < NumLoops && "Loop index must be less number of loops."); const auto *It = std::next(getVarRefs().end(), NumLoop); return *It; } //===----------------------------------------------------------------------===// // OpenMP clauses printing methods //===----------------------------------------------------------------------===// void OMPClausePrinter::VisitOMPIfClause(OMPIfClause *Node) { OS << "if("; if (Node->getNameModifier() != OMPD_unknown) OS << getOpenMPDirectiveName(Node->getNameModifier()) << ": "; Node->getCondition()->printPretty(OS, nullptr, Policy, 0); OS << ")"; } void OMPClausePrinter::VisitOMPFinalClause(OMPFinalClause *Node) { OS << "final("; Node->getCondition()->printPretty(OS, nullptr, Policy, 0); OS << ")"; } void OMPClausePrinter::VisitOMPNumThreadsClause(OMPNumThreadsClause *Node) { OS << "num_threads("; Node->getNumThreads()->printPretty(OS, nullptr, Policy, 0); OS << ")"; } void OMPClausePrinter::VisitOMPAlignClause(OMPAlignClause *Node) { OS << "align("; Node->getAlignment()->printPretty(OS, nullptr, Policy, 0); OS << ")"; } void OMPClausePrinter::VisitOMPSafelenClause(OMPSafelenClause *Node) { OS << "safelen("; Node->getSafelen()->printPretty(OS, nullptr, Policy, 0); OS << ")"; } void OMPClausePrinter::VisitOMPSimdlenClause(OMPSimdlenClause *Node) { OS << "simdlen("; Node->getSimdlen()->printPretty(OS, nullptr, Policy, 0); OS << ")"; } void OMPClausePrinter::VisitOMPSizesClause(OMPSizesClause *Node) { OS << "sizes("; bool First = true; for (auto *Size : Node->getSizesRefs()) { if (!First) OS << ", "; Size->printPretty(OS, nullptr, Policy, 0); First = false; } OS << ")"; } void OMPClausePrinter::VisitOMPFullClause(OMPFullClause *Node) { OS << "full"; } void OMPClausePrinter::VisitOMPPartialClause(OMPPartialClause *Node) { OS << "partial"; if (Expr *Factor = Node->getFactor()) { OS << '('; Factor->printPretty(OS, nullptr, Policy, 0); OS << ')'; } } void OMPClausePrinter::VisitOMPAllocatorClause(OMPAllocatorClause *Node) { OS << "allocator("; Node->getAllocator()->printPretty(OS, nullptr, Policy, 0); OS << ")"; } void OMPClausePrinter::VisitOMPCollapseClause(OMPCollapseClause *Node) { OS << "collapse("; Node->getNumForLoops()->printPretty(OS, nullptr, Policy, 0); OS << ")"; } void OMPClausePrinter::VisitOMPDetachClause(OMPDetachClause *Node) { OS << "detach("; Node->getEventHandler()->printPretty(OS, nullptr, Policy, 0); OS << ")"; } void OMPClausePrinter::VisitOMPDefaultClause(OMPDefaultClause *Node) { OS << "default(" << getOpenMPSimpleClauseTypeName(OMPC_default, unsigned(Node->getDefaultKind())) << ")"; } void OMPClausePrinter::VisitOMPProcBindClause(OMPProcBindClause *Node) { OS << "proc_bind(" << getOpenMPSimpleClauseTypeName(OMPC_proc_bind, unsigned(Node->getProcBindKind())) << ")"; } void OMPClausePrinter::VisitOMPUnifiedAddressClause(OMPUnifiedAddressClause *) { OS << "unified_address"; } void OMPClausePrinter::VisitOMPUnifiedSharedMemoryClause( OMPUnifiedSharedMemoryClause *) { OS << "unified_shared_memory"; } void OMPClausePrinter::VisitOMPReverseOffloadClause(OMPReverseOffloadClause *) { OS << "reverse_offload"; } void OMPClausePrinter::VisitOMPDynamicAllocatorsClause( OMPDynamicAllocatorsClause *) { OS << "dynamic_allocators"; } void OMPClausePrinter::VisitOMPAtomicDefaultMemOrderClause( OMPAtomicDefaultMemOrderClause *Node) { OS << "atomic_default_mem_order(" << getOpenMPSimpleClauseTypeName(OMPC_atomic_default_mem_order, Node->getAtomicDefaultMemOrderKind()) << ")"; } void OMPClausePrinter::VisitOMPAtClause(OMPAtClause *Node) { OS << "at(" << getOpenMPSimpleClauseTypeName(OMPC_at, Node->getAtKind()) << ")"; } void OMPClausePrinter::VisitOMPSeverityClause(OMPSeverityClause *Node) { OS << "severity(" << getOpenMPSimpleClauseTypeName(OMPC_severity, Node->getSeverityKind()) << ")"; } void OMPClausePrinter::VisitOMPMessageClause(OMPMessageClause *Node) { OS << "message(\"" << cast(Node->getMessageString())->getString() << "\")"; } void OMPClausePrinter::VisitOMPScheduleClause(OMPScheduleClause *Node) { OS << "schedule("; if (Node->getFirstScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown) { OS << getOpenMPSimpleClauseTypeName(OMPC_schedule, Node->getFirstScheduleModifier()); if (Node->getSecondScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown) { OS << ", "; OS << getOpenMPSimpleClauseTypeName(OMPC_schedule, Node->getSecondScheduleModifier()); } OS << ": "; } OS << getOpenMPSimpleClauseTypeName(OMPC_schedule, Node->getScheduleKind()); if (auto *E = Node->getChunkSize()) { OS << ", "; E->printPretty(OS, nullptr, Policy); } OS << ")"; } void OMPClausePrinter::VisitOMPOrderedClause(OMPOrderedClause *Node) { OS << "ordered"; if (auto *Num = Node->getNumForLoops()) { OS << "("; Num->printPretty(OS, nullptr, Policy, 0); OS << ")"; } } void OMPClausePrinter::VisitOMPNowaitClause(OMPNowaitClause *) { OS << "nowait"; } void OMPClausePrinter::VisitOMPUntiedClause(OMPUntiedClause *) { OS << "untied"; } void OMPClausePrinter::VisitOMPNogroupClause(OMPNogroupClause *) { OS << "nogroup"; } void OMPClausePrinter::VisitOMPMergeableClause(OMPMergeableClause *) { OS << "mergeable"; } void OMPClausePrinter::VisitOMPReadClause(OMPReadClause *) { OS << "read"; } void OMPClausePrinter::VisitOMPWriteClause(OMPWriteClause *) { OS << "write"; } void OMPClausePrinter::VisitOMPUpdateClause(OMPUpdateClause *Node) { OS << "update"; if (Node->isExtended()) { OS << "("; OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), Node->getDependencyKind()); OS << ")"; } } void OMPClausePrinter::VisitOMPCaptureClause(OMPCaptureClause *) { OS << "capture"; } void OMPClausePrinter::VisitOMPCompareClause(OMPCompareClause *) { OS << "compare"; } void OMPClausePrinter::VisitOMPFailClause(OMPFailClause *Node) { OS << "fail"; if (Node) { OS << "("; OS << getOpenMPSimpleClauseTypeName( Node->getClauseKind(), static_cast(Node->getFailParameter())); OS << ")"; } } void OMPClausePrinter::VisitOMPSeqCstClause(OMPSeqCstClause *) { OS << "seq_cst"; } void OMPClausePrinter::VisitOMPAcqRelClause(OMPAcqRelClause *) { OS << "acq_rel"; } void OMPClausePrinter::VisitOMPAcquireClause(OMPAcquireClause *) { OS << "acquire"; } void OMPClausePrinter::VisitOMPReleaseClause(OMPReleaseClause *) { OS << "release"; } void OMPClausePrinter::VisitOMPRelaxedClause(OMPRelaxedClause *) { OS << "relaxed"; } void OMPClausePrinter::VisitOMPWeakClause(OMPWeakClause *) { OS << "weak"; } void OMPClausePrinter::VisitOMPThreadsClause(OMPThreadsClause *) { OS << "threads"; } void OMPClausePrinter::VisitOMPSIMDClause(OMPSIMDClause *) { OS << "simd"; } void OMPClausePrinter::VisitOMPDeviceClause(OMPDeviceClause *Node) { OS << "device("; OpenMPDeviceClauseModifier Modifier = Node->getModifier(); if (Modifier != OMPC_DEVICE_unknown) { OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), Modifier) << ": "; } Node->getDevice()->printPretty(OS, nullptr, Policy, 0); OS << ")"; } void OMPClausePrinter::VisitOMPNumTeamsClause(OMPNumTeamsClause *Node) { OS << "num_teams("; Node->getNumTeams()->printPretty(OS, nullptr, Policy, 0); OS << ")"; } void OMPClausePrinter::VisitOMPThreadLimitClause(OMPThreadLimitClause *Node) { OS << "thread_limit("; Node->getThreadLimit()->printPretty(OS, nullptr, Policy, 0); OS << ")"; } void OMPClausePrinter::VisitOMPPriorityClause(OMPPriorityClause *Node) { OS << "priority("; Node->getPriority()->printPretty(OS, nullptr, Policy, 0); OS << ")"; } void OMPClausePrinter::VisitOMPGrainsizeClause(OMPGrainsizeClause *Node) { OS << "grainsize("; OpenMPGrainsizeClauseModifier Modifier = Node->getModifier(); if (Modifier != OMPC_GRAINSIZE_unknown) { OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), Modifier) << ": "; } Node->getGrainsize()->printPretty(OS, nullptr, Policy, 0); OS << ")"; } void OMPClausePrinter::VisitOMPNumTasksClause(OMPNumTasksClause *Node) { OS << "num_tasks("; OpenMPNumTasksClauseModifier Modifier = Node->getModifier(); if (Modifier != OMPC_NUMTASKS_unknown) { OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), Modifier) << ": "; } Node->getNumTasks()->printPretty(OS, nullptr, Policy, 0); OS << ")"; } void OMPClausePrinter::VisitOMPHintClause(OMPHintClause *Node) { OS << "hint("; Node->getHint()->printPretty(OS, nullptr, Policy, 0); 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::VisitOMPUseClause(OMPUseClause *Node) { OS << "use("; Node->getInteropVar()->printPretty(OS, nullptr, Policy); OS << ")"; } void OMPClausePrinter::VisitOMPDestroyClause(OMPDestroyClause *Node) { OS << "destroy"; if (Expr *E = Node->getInteropVar()) { OS << "("; E->printPretty(OS, nullptr, Policy); OS << ")"; } } void OMPClausePrinter::VisitOMPNovariantsClause(OMPNovariantsClause *Node) { OS << "novariants"; if (Expr *E = Node->getCondition()) { OS << "("; E->printPretty(OS, nullptr, Policy, 0); OS << ")"; } } void OMPClausePrinter::VisitOMPNocontextClause(OMPNocontextClause *Node) { OS << "nocontext"; if (Expr *E = Node->getCondition()) { OS << "("; E->printPretty(OS, nullptr, Policy, 0); OS << ")"; } } template void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) { for (typename T::varlist_iterator I = Node->varlist_begin(), E = Node->varlist_end(); I != E; ++I) { assert(*I && "Expected non-null Stmt"); OS << (I == Node->varlist_begin() ? StartSym : ','); if (auto *DRE = dyn_cast(*I)) { if (isa(DRE->getDecl())) DRE->printPretty(OS, nullptr, Policy, 0); else DRE->getDecl()->printQualifiedName(OS); } else (*I)->printPretty(OS, nullptr, Policy, 0); } } void OMPClausePrinter::VisitOMPAllocateClause(OMPAllocateClause *Node) { if (Node->varlist_empty()) return; OS << "allocate"; if (Expr *Allocator = Node->getAllocator()) { OS << "("; Allocator->printPretty(OS, nullptr, Policy, 0); OS << ":"; VisitOMPClauseList(Node, ' '); } else { VisitOMPClauseList(Node, '('); } OS << ")"; } void OMPClausePrinter::VisitOMPPrivateClause(OMPPrivateClause *Node) { if (!Node->varlist_empty()) { OS << "private"; VisitOMPClauseList(Node, '('); OS << ")"; } } void OMPClausePrinter::VisitOMPFirstprivateClause(OMPFirstprivateClause *Node) { if (!Node->varlist_empty()) { OS << "firstprivate"; VisitOMPClauseList(Node, '('); OS << ")"; } } void OMPClausePrinter::VisitOMPLastprivateClause(OMPLastprivateClause *Node) { if (!Node->varlist_empty()) { OS << "lastprivate"; OpenMPLastprivateModifier LPKind = Node->getKind(); if (LPKind != OMPC_LASTPRIVATE_unknown) { OS << "(" << getOpenMPSimpleClauseTypeName(OMPC_lastprivate, Node->getKind()) << ":"; } VisitOMPClauseList(Node, LPKind == OMPC_LASTPRIVATE_unknown ? '(' : ' '); OS << ")"; } } void OMPClausePrinter::VisitOMPSharedClause(OMPSharedClause *Node) { if (!Node->varlist_empty()) { OS << "shared"; VisitOMPClauseList(Node, '('); OS << ")"; } } void OMPClausePrinter::VisitOMPReductionClause(OMPReductionClause *Node) { if (!Node->varlist_empty()) { OS << "reduction("; if (Node->getModifierLoc().isValid()) OS << getOpenMPSimpleClauseTypeName(OMPC_reduction, Node->getModifier()) << ", "; NestedNameSpecifier *QualifierLoc = Node->getQualifierLoc().getNestedNameSpecifier(); OverloadedOperatorKind OOK = Node->getNameInfo().getName().getCXXOverloadedOperator(); if (QualifierLoc == nullptr && OOK != OO_None) { // Print reduction identifier in C format OS << getOperatorSpelling(OOK); } else { // Use C++ format if (QualifierLoc != nullptr) QualifierLoc->print(OS, Policy); OS << Node->getNameInfo(); } OS << ":"; VisitOMPClauseList(Node, ' '); OS << ")"; } } void OMPClausePrinter::VisitOMPTaskReductionClause( OMPTaskReductionClause *Node) { if (!Node->varlist_empty()) { OS << "task_reduction("; NestedNameSpecifier *QualifierLoc = Node->getQualifierLoc().getNestedNameSpecifier(); OverloadedOperatorKind OOK = Node->getNameInfo().getName().getCXXOverloadedOperator(); if (QualifierLoc == nullptr && OOK != OO_None) { // Print reduction identifier in C format OS << getOperatorSpelling(OOK); } else { // Use C++ format if (QualifierLoc != nullptr) QualifierLoc->print(OS, Policy); OS << Node->getNameInfo(); } OS << ":"; VisitOMPClauseList(Node, ' '); OS << ")"; } } void OMPClausePrinter::VisitOMPInReductionClause(OMPInReductionClause *Node) { if (!Node->varlist_empty()) { OS << "in_reduction("; NestedNameSpecifier *QualifierLoc = Node->getQualifierLoc().getNestedNameSpecifier(); OverloadedOperatorKind OOK = Node->getNameInfo().getName().getCXXOverloadedOperator(); if (QualifierLoc == nullptr && OOK != OO_None) { // Print reduction identifier in C format OS << getOperatorSpelling(OOK); } else { // Use C++ format if (QualifierLoc != nullptr) QualifierLoc->print(OS, Policy); OS << Node->getNameInfo(); } OS << ":"; VisitOMPClauseList(Node, ' '); OS << ")"; } } void OMPClausePrinter::VisitOMPLinearClause(OMPLinearClause *Node) { if (!Node->varlist_empty()) { OS << "linear"; VisitOMPClauseList(Node, '('); if (Node->getModifierLoc().isValid() || Node->getStep() != nullptr) { OS << ": "; } if (Node->getModifierLoc().isValid()) { OS << getOpenMPSimpleClauseTypeName(OMPC_linear, Node->getModifier()); } if (Node->getStep() != nullptr) { if (Node->getModifierLoc().isValid()) { OS << ", "; } OS << "step("; Node->getStep()->printPretty(OS, nullptr, Policy, 0); OS << ")"; } OS << ")"; } } void OMPClausePrinter::VisitOMPAlignedClause(OMPAlignedClause *Node) { if (!Node->varlist_empty()) { OS << "aligned"; VisitOMPClauseList(Node, '('); if (Node->getAlignment() != nullptr) { OS << ": "; Node->getAlignment()->printPretty(OS, nullptr, Policy, 0); } OS << ")"; } } void OMPClausePrinter::VisitOMPCopyinClause(OMPCopyinClause *Node) { if (!Node->varlist_empty()) { OS << "copyin"; VisitOMPClauseList(Node, '('); OS << ")"; } } void OMPClausePrinter::VisitOMPCopyprivateClause(OMPCopyprivateClause *Node) { if (!Node->varlist_empty()) { OS << "copyprivate"; VisitOMPClauseList(Node, '('); OS << ")"; } } void OMPClausePrinter::VisitOMPFlushClause(OMPFlushClause *Node) { if (!Node->varlist_empty()) { VisitOMPClauseList(Node, '('); OS << ")"; } } void OMPClausePrinter::VisitOMPDepobjClause(OMPDepobjClause *Node) { OS << "("; Node->getDepobj()->printPretty(OS, nullptr, Policy, 0); OS << ")"; } void OMPClausePrinter::VisitOMPDependClause(OMPDependClause *Node) { OS << "depend("; if (Expr *DepModifier = Node->getModifier()) { DepModifier->printPretty(OS, nullptr, Policy); OS << ", "; } OpenMPDependClauseKind DepKind = Node->getDependencyKind(); OpenMPDependClauseKind PrintKind = DepKind; bool IsOmpAllMemory = false; if (PrintKind == OMPC_DEPEND_outallmemory) { PrintKind = OMPC_DEPEND_out; IsOmpAllMemory = true; } else if (PrintKind == OMPC_DEPEND_inoutallmemory) { PrintKind = OMPC_DEPEND_inout; IsOmpAllMemory = true; } OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), PrintKind); if (!Node->varlist_empty() || IsOmpAllMemory) OS << " :"; VisitOMPClauseList(Node, ' '); if (IsOmpAllMemory) { OS << (Node->varlist_empty() ? " " : ","); OS << "omp_all_memory"; } OS << ")"; } template static void PrintMapper(raw_ostream &OS, T *Node, const PrintingPolicy &Policy) { OS << '('; NestedNameSpecifier *MapperNNS = Node->getMapperQualifierLoc().getNestedNameSpecifier(); if (MapperNNS) MapperNNS->print(OS, Policy); OS << Node->getMapperIdInfo() << ')'; } template static void PrintIterator(raw_ostream &OS, T *Node, const PrintingPolicy &Policy) { if (Expr *IteratorModifier = Node->getIteratorModifier()) IteratorModifier->printPretty(OS, nullptr, Policy); } void OMPClausePrinter::VisitOMPMapClause(OMPMapClause *Node) { if (!Node->varlist_empty()) { OS << "map("; if (Node->getMapType() != OMPC_MAP_unknown) { for (unsigned I = 0; I < NumberOfOMPMapClauseModifiers; ++I) { if (Node->getMapTypeModifier(I) != OMPC_MAP_MODIFIER_unknown) { if (Node->getMapTypeModifier(I) == OMPC_MAP_MODIFIER_iterator) { PrintIterator(OS, Node, Policy); } else { OS << getOpenMPSimpleClauseTypeName(OMPC_map, Node->getMapTypeModifier(I)); if (Node->getMapTypeModifier(I) == OMPC_MAP_MODIFIER_mapper) PrintMapper(OS, Node, Policy); } OS << ','; } } OS << getOpenMPSimpleClauseTypeName(OMPC_map, Node->getMapType()); OS << ':'; } VisitOMPClauseList(Node, ' '); OS << ")"; } } template void OMPClausePrinter::VisitOMPMotionClause(T *Node) { if (Node->varlist_empty()) return; OS << getOpenMPClauseName(Node->getClauseKind()); unsigned ModifierCount = 0; for (unsigned I = 0; I < NumberOfOMPMotionModifiers; ++I) { if (Node->getMotionModifier(I) != OMPC_MOTION_MODIFIER_unknown) ++ModifierCount; } if (ModifierCount) { OS << '('; for (unsigned I = 0; I < NumberOfOMPMotionModifiers; ++I) { if (Node->getMotionModifier(I) != OMPC_MOTION_MODIFIER_unknown) { OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), Node->getMotionModifier(I)); if (Node->getMotionModifier(I) == OMPC_MOTION_MODIFIER_mapper) PrintMapper(OS, Node, Policy); if (I < ModifierCount - 1) OS << ", "; } } OS << ':'; VisitOMPClauseList(Node, ' '); } else { VisitOMPClauseList(Node, '('); } OS << ")"; } void OMPClausePrinter::VisitOMPToClause(OMPToClause *Node) { VisitOMPMotionClause(Node); } void OMPClausePrinter::VisitOMPFromClause(OMPFromClause *Node) { VisitOMPMotionClause(Node); } void OMPClausePrinter::VisitOMPDistScheduleClause(OMPDistScheduleClause *Node) { OS << "dist_schedule(" << getOpenMPSimpleClauseTypeName( OMPC_dist_schedule, Node->getDistScheduleKind()); if (auto *E = Node->getChunkSize()) { OS << ", "; E->printPretty(OS, nullptr, Policy); } OS << ")"; } void OMPClausePrinter::VisitOMPDefaultmapClause(OMPDefaultmapClause *Node) { OS << "defaultmap("; OS << getOpenMPSimpleClauseTypeName(OMPC_defaultmap, Node->getDefaultmapModifier()); if (Node->getDefaultmapKind() != OMPC_DEFAULTMAP_unknown) { OS << ": "; OS << getOpenMPSimpleClauseTypeName(OMPC_defaultmap, Node->getDefaultmapKind()); } OS << ")"; } void OMPClausePrinter::VisitOMPUseDevicePtrClause(OMPUseDevicePtrClause *Node) { if (!Node->varlist_empty()) { OS << "use_device_ptr"; VisitOMPClauseList(Node, '('); OS << ")"; } } void OMPClausePrinter::VisitOMPUseDeviceAddrClause( OMPUseDeviceAddrClause *Node) { if (!Node->varlist_empty()) { OS << "use_device_addr"; VisitOMPClauseList(Node, '('); OS << ")"; } } void OMPClausePrinter::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *Node) { if (!Node->varlist_empty()) { OS << "is_device_ptr"; VisitOMPClauseList(Node, '('); OS << ")"; } } void OMPClausePrinter::VisitOMPHasDeviceAddrClause(OMPHasDeviceAddrClause *Node) { if (!Node->varlist_empty()) { OS << "has_device_addr"; VisitOMPClauseList(Node, '('); OS << ")"; } } void OMPClausePrinter::VisitOMPNontemporalClause(OMPNontemporalClause *Node) { if (!Node->varlist_empty()) { OS << "nontemporal"; VisitOMPClauseList(Node, '('); OS << ")"; } } void OMPClausePrinter::VisitOMPOrderClause(OMPOrderClause *Node) { OS << "order("; if (Node->getModifier() != OMPC_ORDER_MODIFIER_unknown) { OS << getOpenMPSimpleClauseTypeName(OMPC_order, Node->getModifier()); OS << ": "; } OS << getOpenMPSimpleClauseTypeName(OMPC_order, Node->getKind()) << ")"; } void OMPClausePrinter::VisitOMPInclusiveClause(OMPInclusiveClause *Node) { if (!Node->varlist_empty()) { OS << "inclusive"; VisitOMPClauseList(Node, '('); OS << ")"; } } void OMPClausePrinter::VisitOMPExclusiveClause(OMPExclusiveClause *Node) { if (!Node->varlist_empty()) { OS << "exclusive"; VisitOMPClauseList(Node, '('); OS << ")"; } } void OMPClausePrinter::VisitOMPUsesAllocatorsClause( OMPUsesAllocatorsClause *Node) { if (Node->getNumberOfAllocators() == 0) return; OS << "uses_allocators("; for (unsigned I = 0, E = Node->getNumberOfAllocators(); I < E; ++I) { OMPUsesAllocatorsClause::Data Data = Node->getAllocatorData(I); Data.Allocator->printPretty(OS, nullptr, Policy); if (Data.AllocatorTraits) { OS << "("; Data.AllocatorTraits->printPretty(OS, nullptr, Policy); OS << ")"; } if (I < E - 1) OS << ","; } OS << ")"; } void OMPClausePrinter::VisitOMPAffinityClause(OMPAffinityClause *Node) { if (Node->varlist_empty()) return; OS << "affinity"; char StartSym = '('; if (Expr *Modifier = Node->getModifier()) { OS << "("; Modifier->printPretty(OS, nullptr, Policy); OS << " :"; StartSym = ' '; } VisitOMPClauseList(Node, StartSym); OS << ")"; } void OMPClausePrinter::VisitOMPFilterClause(OMPFilterClause *Node) { OS << "filter("; Node->getThreadID()->printPretty(OS, nullptr, Policy, 0); OS << ")"; } void OMPClausePrinter::VisitOMPBindClause(OMPBindClause *Node) { OS << "bind(" << getOpenMPSimpleClauseTypeName(OMPC_bind, unsigned(Node->getBindKind())) << ")"; } void OMPClausePrinter::VisitOMPXDynCGroupMemClause( OMPXDynCGroupMemClause *Node) { OS << "ompx_dyn_cgroup_mem("; Node->getSize()->printPretty(OS, nullptr, Policy, 0); OS << ")"; } void OMPClausePrinter::VisitOMPDoacrossClause(OMPDoacrossClause *Node) { OS << "doacross("; OpenMPDoacrossClauseModifier DepType = Node->getDependenceType(); switch (DepType) { case OMPC_DOACROSS_source: OS << "source:"; break; case OMPC_DOACROSS_sink: OS << "sink:"; break; case OMPC_DOACROSS_source_omp_cur_iteration: OS << "source: omp_cur_iteration"; break; case OMPC_DOACROSS_sink_omp_cur_iteration: OS << "sink: omp_cur_iteration - 1"; break; default: llvm_unreachable("unknown docaross modifier"); } VisitOMPClauseList(Node, ' '); OS << ")"; } void OMPClausePrinter::VisitOMPXAttributeClause(OMPXAttributeClause *Node) { OS << "ompx_attribute("; bool IsFirst = true; for (auto &Attr : Node->getAttrs()) { if (!IsFirst) OS << ", "; Attr->printPretty(OS, Policy); IsFirst = false; } OS << ")"; } void OMPClausePrinter::VisitOMPXBareClause(OMPXBareClause *Node) { OS << "ompx_bare"; } void OMPTraitInfo::getAsVariantMatchInfo(ASTContext &ASTCtx, VariantMatchInfo &VMI) const { for (const OMPTraitSet &Set : Sets) { for (const OMPTraitSelector &Selector : Set.Selectors) { // User conditions are special as we evaluate the condition here. if (Selector.Kind == TraitSelector::user_condition) { assert(Selector.ScoreOrCondition && "Ill-formed user condition, expected condition expression!"); assert(Selector.Properties.size() == 1 && Selector.Properties.front().Kind == TraitProperty::user_condition_unknown && "Ill-formed user condition, expected unknown trait property!"); if (std::optional CondVal = Selector.ScoreOrCondition->getIntegerConstantExpr(ASTCtx)) VMI.addTrait(CondVal->isZero() ? TraitProperty::user_condition_false : TraitProperty::user_condition_true, ""); else VMI.addTrait(TraitProperty::user_condition_false, ""); continue; } std::optional Score; llvm::APInt *ScorePtr = nullptr; if (Selector.ScoreOrCondition) { if ((Score = Selector.ScoreOrCondition->getIntegerConstantExpr(ASTCtx))) ScorePtr = &*Score; else VMI.addTrait(TraitProperty::user_condition_false, ""); } for (const OMPTraitProperty &Property : Selector.Properties) VMI.addTrait(Set.Kind, Property.Kind, Property.RawString, ScorePtr); if (Set.Kind != TraitSet::construct) continue; // TODO: This might not hold once we implement SIMD properly. assert(Selector.Properties.size() == 1 && Selector.Properties.front().Kind == getOpenMPContextTraitPropertyForSelector( Selector.Kind) && "Ill-formed construct selector!"); } } } void OMPTraitInfo::print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const { bool FirstSet = true; for (const OMPTraitSet &Set : Sets) { if (!FirstSet) OS << ", "; FirstSet = false; OS << getOpenMPContextTraitSetName(Set.Kind) << "={"; bool FirstSelector = true; for (const OMPTraitSelector &Selector : Set.Selectors) { if (!FirstSelector) OS << ", "; FirstSelector = false; OS << getOpenMPContextTraitSelectorName(Selector.Kind); bool AllowsTraitScore = false; bool RequiresProperty = false; isValidTraitSelectorForTraitSet( Selector.Kind, Set.Kind, AllowsTraitScore, RequiresProperty); if (!RequiresProperty) continue; OS << "("; if (Selector.Kind == TraitSelector::user_condition) { if (Selector.ScoreOrCondition) Selector.ScoreOrCondition->printPretty(OS, nullptr, Policy); else OS << "..."; } else { if (Selector.ScoreOrCondition) { OS << "score("; Selector.ScoreOrCondition->printPretty(OS, nullptr, Policy); OS << "): "; } bool FirstProperty = true; for (const OMPTraitProperty &Property : Selector.Properties) { if (!FirstProperty) OS << ", "; FirstProperty = false; OS << getOpenMPContextTraitPropertyName(Property.Kind, Property.RawString); } } OS << ")"; } OS << "}"; } } std::string OMPTraitInfo::getMangledName() const { std::string MangledName; llvm::raw_string_ostream OS(MangledName); for (const OMPTraitSet &Set : Sets) { OS << '$' << 'S' << unsigned(Set.Kind); for (const OMPTraitSelector &Selector : Set.Selectors) { bool AllowsTraitScore = false; bool RequiresProperty = false; isValidTraitSelectorForTraitSet( Selector.Kind, Set.Kind, AllowsTraitScore, RequiresProperty); OS << '$' << 's' << unsigned(Selector.Kind); if (!RequiresProperty || Selector.Kind == TraitSelector::user_condition) continue; for (const OMPTraitProperty &Property : Selector.Properties) OS << '$' << 'P' << getOpenMPContextTraitPropertyName(Property.Kind, Property.RawString); } } return MangledName; } OMPTraitInfo::OMPTraitInfo(StringRef MangledName) { unsigned long U; do { if (!MangledName.consume_front("$S")) break; if (MangledName.consumeInteger(10, U)) break; Sets.push_back(OMPTraitSet()); OMPTraitSet &Set = Sets.back(); Set.Kind = TraitSet(U); do { if (!MangledName.consume_front("$s")) break; if (MangledName.consumeInteger(10, U)) break; Set.Selectors.push_back(OMPTraitSelector()); OMPTraitSelector &Selector = Set.Selectors.back(); Selector.Kind = TraitSelector(U); do { if (!MangledName.consume_front("$P")) break; Selector.Properties.push_back(OMPTraitProperty()); OMPTraitProperty &Property = Selector.Properties.back(); std::pair PropRestPair = MangledName.split('$'); Property.RawString = PropRestPair.first; Property.Kind = getOpenMPContextTraitPropertyKind( Set.Kind, Selector.Kind, PropRestPair.first); MangledName = MangledName.drop_front(PropRestPair.first.size()); } while (true); } while (true); } while (true); } llvm::raw_ostream &clang::operator<<(llvm::raw_ostream &OS, const OMPTraitInfo &TI) { LangOptions LO; PrintingPolicy Policy(LO); TI.print(OS, Policy); return OS; } llvm::raw_ostream &clang::operator<<(llvm::raw_ostream &OS, const OMPTraitInfo *TI) { return TI ? OS << *TI : OS; } TargetOMPContext::TargetOMPContext( ASTContext &ASTCtx, std::function &&DiagUnknownTrait, const FunctionDecl *CurrentFunctionDecl, ArrayRef ConstructTraits) : OMPContext(ASTCtx.getLangOpts().OpenMPIsTargetDevice, ASTCtx.getTargetInfo().getTriple()), FeatureValidityCheck([&](StringRef FeatureName) { return ASTCtx.getTargetInfo().isValidFeatureName(FeatureName); }), DiagUnknownTrait(std::move(DiagUnknownTrait)) { ASTCtx.getFunctionFeatureMap(FeatureMap, CurrentFunctionDecl); for (llvm::omp::TraitProperty Property : ConstructTraits) addTrait(Property); } bool TargetOMPContext::matchesISATrait(StringRef RawString) const { auto It = FeatureMap.find(RawString); if (It != FeatureMap.end()) return It->second; if (!FeatureValidityCheck(RawString)) DiagUnknownTrait(RawString); return false; }