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