1 //===-- lib/Semantics/check-omp-structure.h ---------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // OpenMP structure validity check list 10 // 1. invalid clauses on directive 11 // 2. invalid repeated clauses on directive 12 // 3. TODO: invalid nesting of regions 13 14 #ifndef FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_ 15 #define FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_ 16 17 #include "check-directive-structure.h" 18 #include "flang/Common/enum-set.h" 19 #include "flang/Parser/parse-tree.h" 20 #include "flang/Semantics/semantics.h" 21 #include "llvm/Frontend/OpenMP/OMPConstants.h" 22 23 using OmpDirectiveSet = Fortran::common::EnumSet<llvm::omp::Directive, 24 llvm::omp::Directive_enumSize>; 25 26 using OmpClauseSet = 27 Fortran::common::EnumSet<llvm::omp::Clause, llvm::omp::Clause_enumSize>; 28 29 #define GEN_FLANG_DIRECTIVE_CLAUSE_SETS 30 #include "llvm/Frontend/OpenMP/OMP.cpp.inc" 31 32 namespace llvm { 33 namespace omp { 34 static OmpDirectiveSet parallelSet{Directive::OMPD_distribute_parallel_do, 35 Directive::OMPD_distribute_parallel_do_simd, Directive::OMPD_parallel, 36 Directive::OMPD_parallel_do, Directive::OMPD_parallel_do_simd, 37 Directive::OMPD_parallel_sections, Directive::OMPD_parallel_workshare, 38 Directive::OMPD_target_parallel, Directive::OMPD_target_parallel_do, 39 Directive::OMPD_target_parallel_do_simd, 40 Directive::OMPD_target_teams_distribute_parallel_do, 41 Directive::OMPD_target_teams_distribute_parallel_do_simd, 42 Directive::OMPD_teams_distribute_parallel_do, 43 Directive::OMPD_teams_distribute_parallel_do_simd}; 44 static OmpDirectiveSet doSet{Directive::OMPD_distribute_parallel_do, 45 Directive::OMPD_distribute_parallel_do_simd, Directive::OMPD_parallel, 46 Directive::OMPD_parallel_do, Directive::OMPD_parallel_do_simd, 47 Directive::OMPD_do, Directive::OMPD_do_simd, 48 Directive::OMPD_target_parallel_do, Directive::OMPD_target_parallel_do_simd, 49 Directive::OMPD_target_teams_distribute_parallel_do, 50 Directive::OMPD_target_teams_distribute_parallel_do_simd, 51 Directive::OMPD_teams_distribute_parallel_do, 52 Directive::OMPD_teams_distribute_parallel_do_simd}; 53 static OmpDirectiveSet doSimdSet{Directive::OMPD_distribute_parallel_do_simd, 54 Directive::OMPD_parallel_do_simd, Directive::OMPD_do_simd, 55 Directive::OMPD_target_parallel_do_simd, 56 Directive::OMPD_target_teams_distribute_parallel_do_simd, 57 Directive::OMPD_teams_distribute_parallel_do_simd}; 58 static OmpDirectiveSet taskloopSet{ 59 Directive::OMPD_taskloop, Directive::OMPD_taskloop_simd}; 60 static OmpDirectiveSet targetSet{Directive::OMPD_target, 61 Directive::OMPD_target_parallel, Directive::OMPD_target_parallel_do, 62 Directive::OMPD_target_parallel_do_simd, Directive::OMPD_target_simd, 63 Directive::OMPD_target_teams, Directive::OMPD_target_teams_distribute, 64 Directive::OMPD_target_teams_distribute_simd}; 65 static OmpDirectiveSet simdSet{Directive::OMPD_distribute_parallel_do_simd, 66 Directive::OMPD_distribute_simd, Directive::OMPD_parallel_do_simd, 67 Directive::OMPD_do_simd, Directive::OMPD_simd, 68 Directive::OMPD_target_parallel_do_simd, 69 Directive::OMPD_target_teams_distribute_parallel_do_simd, 70 Directive::OMPD_target_teams_distribute_simd, Directive::OMPD_target_simd, 71 Directive::OMPD_taskloop_simd, 72 Directive::OMPD_teams_distribute_parallel_do_simd, 73 Directive::OMPD_teams_distribute_simd}; 74 static OmpDirectiveSet taskGeneratingSet{ 75 OmpDirectiveSet{Directive::OMPD_task} | taskloopSet}; 76 } // namespace omp 77 } // namespace llvm 78 79 namespace Fortran::semantics { 80 81 class OmpStructureChecker 82 : public DirectiveStructureChecker<llvm::omp::Directive, llvm::omp::Clause, 83 parser::OmpClause, llvm::omp::Clause_enumSize> { 84 public: OmpStructureChecker(SemanticsContext & context)85 OmpStructureChecker(SemanticsContext &context) 86 : DirectiveStructureChecker(context, 87 #define GEN_FLANG_DIRECTIVE_CLAUSE_MAP 88 #include "llvm/Frontend/OpenMP/OMP.cpp.inc" 89 ) { 90 } 91 92 void Enter(const parser::OpenMPConstruct &); 93 void Enter(const parser::OpenMPLoopConstruct &); 94 void Leave(const parser::OpenMPLoopConstruct &); 95 void Enter(const parser::OmpEndLoopDirective &); 96 97 void Enter(const parser::OpenMPBlockConstruct &); 98 void Leave(const parser::OpenMPBlockConstruct &); 99 void Enter(const parser::OmpEndBlockDirective &); 100 101 void Enter(const parser::OpenMPSectionsConstruct &); 102 void Leave(const parser::OpenMPSectionsConstruct &); 103 void Enter(const parser::OmpEndSectionsDirective &); 104 105 void Enter(const parser::OpenMPDeclareSimdConstruct &); 106 void Leave(const parser::OpenMPDeclareSimdConstruct &); 107 void Enter(const parser::OpenMPDeclareTargetConstruct &); 108 void Leave(const parser::OpenMPDeclareTargetConstruct &); 109 110 void Enter(const parser::OpenMPSimpleStandaloneConstruct &); 111 void Leave(const parser::OpenMPSimpleStandaloneConstruct &); 112 void Enter(const parser::OpenMPFlushConstruct &); 113 void Leave(const parser::OpenMPFlushConstruct &); 114 void Enter(const parser::OpenMPCancelConstruct &); 115 void Leave(const parser::OpenMPCancelConstruct &); 116 void Enter(const parser::OpenMPCancellationPointConstruct &); 117 void Leave(const parser::OpenMPCancellationPointConstruct &); 118 void Enter(const parser::OpenMPCriticalConstruct &); 119 void Leave(const parser::OpenMPCriticalConstruct &); 120 121 void Leave(const parser::OmpClauseList &); 122 void Enter(const parser::OmpClause &); 123 void Enter(const parser::OmpNowait &); 124 void Enter(const parser::OmpClause::Inbranch &); 125 void Enter(const parser::OmpClause::Mergeable &); 126 void Enter(const parser::OmpClause::Nogroup &); 127 void Enter(const parser::OmpClause::Notinbranch &); 128 void Enter(const parser::OmpClause::Untied &); 129 void Enter(const parser::OmpClause::Collapse &); 130 void Enter(const parser::OmpClause::Copyin &); 131 void Enter(const parser::OmpClause::Copyprivate &); 132 void Enter(const parser::OmpClause::Device &); 133 void Enter(const parser::OmpClause::Final &); 134 void Enter(const parser::OmpClause::Firstprivate &); 135 void Enter(const parser::OmpClause::From &); 136 void Enter(const parser::OmpClause::Grainsize &); 137 void Enter(const parser::OmpClause::Lastprivate &); 138 void Enter(const parser::OmpClause::NumTasks &); 139 void Enter(const parser::OmpClause::NumTeams &); 140 void Enter(const parser::OmpClause::NumThreads &); 141 void Enter(const parser::OmpClause::Ordered &); 142 void Enter(const parser::OmpClause::Priority &); 143 void Enter(const parser::OmpClause::Private &); 144 void Enter(const parser::OmpClause::Safelen &); 145 void Enter(const parser::OmpClause::Shared &); 146 void Enter(const parser::OmpClause::Simdlen &); 147 void Enter(const parser::OmpClause::ThreadLimit &); 148 void Enter(const parser::OmpClause::To &); 149 void Enter(const parser::OmpClause::Link &); 150 void Enter(const parser::OmpClause::Uniform &); 151 void Enter(const parser::OmpClause::UseDevicePtr &); 152 void Enter(const parser::OmpClause::IsDevicePtr &); 153 // Memory-order-clause 154 void Enter(const parser::OmpClause::SeqCst &); 155 void Enter(const parser::OmpClause::AcqRel &); 156 void Enter(const parser::OmpClause::Release &); 157 void Enter(const parser::OmpClause::Acquire &); 158 void Enter(const parser::OmpClause::Relaxed &); 159 160 void Enter(const parser::OmpAlignedClause &); 161 void Enter(const parser::OmpAllocateClause &); 162 void Enter(const parser::OmpDefaultClause &); 163 void Enter(const parser::OmpDefaultmapClause &); 164 void Enter(const parser::OmpDependClause &); 165 void Enter(const parser::OmpDistScheduleClause &); 166 void Enter(const parser::OmpIfClause &); 167 void Enter(const parser::OmpLinearClause &); 168 void Enter(const parser::OmpMapClause &); 169 void Enter(const parser::OmpProcBindClause &); 170 void Enter(const parser::OmpReductionClause &); 171 void Enter(const parser::OmpScheduleClause &); 172 173 private: 174 bool HasInvalidWorksharingNesting( 175 const parser::CharBlock &, const OmpDirectiveSet &); 176 177 // specific clause related 178 bool ScheduleModifierHasType(const parser::OmpScheduleClause &, 179 const parser::OmpScheduleModifierType::ModType &); 180 void CheckAllowedMapTypes(const parser::OmpMapType::Type &, 181 const std::list<parser::OmpMapType::Type> &); 182 llvm::StringRef getClauseName(llvm::omp::Clause clause) override; 183 llvm::StringRef getDirectiveName(llvm::omp::Directive directive) override; 184 185 void CheckDependList(const parser::DataRef &); 186 void CheckDependArraySection( 187 const common::Indirection<parser::ArrayElement> &, const parser::Name &); 188 void CheckIsVarPartOfAnotherVar(const parser::OmpObjectList &objList); 189 void CheckIntentInPointer( 190 const parser::OmpObjectList &, const llvm::omp::Clause); 191 void GetSymbolsInObjectList( 192 const parser::OmpObjectList &, std::vector<const Symbol *> &); 193 }; 194 } // namespace Fortran::semantics 195 #endif // FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_ 196