1 | //===-- Clauses.h -- OpenMP clause handling -------------------------------===// |
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 | #ifndef FORTRAN_LOWER_OPENMP_CLAUSES_H |
9 | #define FORTRAN_LOWER_OPENMP_CLAUSES_H |
10 | |
11 | #include "flang/Evaluate/expression.h" |
12 | #include "flang/Parser/parse-tree.h" |
13 | #include "flang/Semantics/expression.h" |
14 | #include "flang/Semantics/semantics.h" |
15 | #include "flang/Semantics/symbol.h" |
16 | |
17 | #include "llvm/ADT/STLExtras.h" |
18 | #include "llvm/Frontend/OpenMP/ClauseT.h" |
19 | |
20 | #include <optional> |
21 | #include <type_traits> |
22 | #include <utility> |
23 | |
24 | namespace Fortran::lower::omp { |
25 | using namespace Fortran; |
26 | using SomeType = evaluate::SomeType; |
27 | using SomeExpr = semantics::SomeExpr; |
28 | using MaybeExpr = semantics::MaybeExpr; |
29 | |
30 | using TypeTy = SomeType; |
31 | using IdTy = semantics::Symbol *; |
32 | using ExprTy = SomeExpr; |
33 | |
34 | template <typename T> |
35 | using List = tomp::ListT<T>; |
36 | } // namespace Fortran::lower::omp |
37 | |
38 | namespace tomp::type { |
39 | template <> |
40 | struct ObjectT<Fortran::lower::omp::IdTy, Fortran::lower::omp::ExprTy> { |
41 | using IdTy = Fortran::lower::omp::IdTy; |
42 | using ExprTy = Fortran::lower::omp::ExprTy; |
43 | |
44 | const IdTy &id() const { return symbol; } |
45 | const std::optional<ExprTy> &ref() const { return designator; } |
46 | |
47 | IdTy symbol; |
48 | std::optional<ExprTy> designator; |
49 | }; |
50 | } // namespace tomp::type |
51 | |
52 | namespace Fortran::lower::omp { |
53 | |
54 | using Object = tomp::ObjectT<IdTy, ExprTy>; |
55 | using ObjectList = tomp::ObjectListT<IdTy, ExprTy>; |
56 | |
57 | Object makeObject(const parser::OmpObject &object, |
58 | semantics::SemanticsContext &semaCtx); |
59 | Object makeObject(const parser::Name &name, |
60 | semantics::SemanticsContext &semaCtx); |
61 | Object makeObject(const parser::Designator &dsg, |
62 | semantics::SemanticsContext &semaCtx); |
63 | Object makeObject(const parser::StructureComponent &comp, |
64 | semantics::SemanticsContext &semaCtx); |
65 | |
66 | inline auto makeObjectFn(semantics::SemanticsContext &semaCtx) { |
67 | return [&](auto &&s) { return makeObject(s, semaCtx); }; |
68 | } |
69 | |
70 | template <typename T> |
71 | SomeExpr makeExpr(T &&pftExpr, semantics::SemanticsContext &semaCtx) { |
72 | auto maybeExpr = evaluate::ExpressionAnalyzer(semaCtx).Analyze(pftExpr); |
73 | assert(maybeExpr); |
74 | return std::move(*maybeExpr); |
75 | } |
76 | |
77 | inline auto makeExprFn(semantics::SemanticsContext &semaCtx) { |
78 | return [&](auto &&s) { return makeExpr(s, semaCtx); }; |
79 | } |
80 | |
81 | template < |
82 | typename ContainerTy, typename FunctionTy, |
83 | typename ElemTy = typename llvm::remove_cvref_t<ContainerTy>::value_type, |
84 | typename ResultTy = std::invoke_result_t<FunctionTy, ElemTy>> |
85 | List<ResultTy> makeList(ContainerTy &&container, FunctionTy &&func) { |
86 | List<ResultTy> v; |
87 | llvm::transform(container, std::back_inserter(v), func); |
88 | return v; |
89 | } |
90 | |
91 | inline ObjectList makeObjects(const parser::OmpObjectList &objects, |
92 | semantics::SemanticsContext &semaCtx) { |
93 | return makeList(objects.v, makeObjectFn(semaCtx)); |
94 | } |
95 | |
96 | template <typename FuncTy, // |
97 | typename ArgTy, // |
98 | typename ResultTy = std::invoke_result_t<FuncTy, ArgTy>> |
99 | std::optional<ResultTy> maybeApply(FuncTy &&func, |
100 | const std::optional<ArgTy> &arg) { |
101 | if (!arg) |
102 | return std::nullopt; |
103 | return std::move(func(*arg)); |
104 | } |
105 | |
106 | std::optional<Object> |
107 | getBaseObject(const Object &object, |
108 | Fortran::semantics::SemanticsContext &semaCtx); |
109 | |
110 | namespace clause { |
111 | using DefinedOperator = tomp::type::DefinedOperatorT<IdTy, ExprTy>; |
112 | using ProcedureDesignator = tomp::type::ProcedureDesignatorT<IdTy, ExprTy>; |
113 | using ReductionOperator = tomp::type::ReductionIdentifierT<IdTy, ExprTy>; |
114 | |
115 | // "Requires" clauses are handled early on, and the aggregated information |
116 | // is stored in the Symbol details of modules, programs, and subprograms. |
117 | // These clauses are still handled here to cover all alternatives in the |
118 | // main clause variant. |
119 | |
120 | using AcqRel = tomp::clause::AcqRelT<TypeTy, IdTy, ExprTy>; |
121 | using Acquire = tomp::clause::AcquireT<TypeTy, IdTy, ExprTy>; |
122 | using AdjustArgs = tomp::clause::AdjustArgsT<TypeTy, IdTy, ExprTy>; |
123 | using Affinity = tomp::clause::AffinityT<TypeTy, IdTy, ExprTy>; |
124 | using Aligned = tomp::clause::AlignedT<TypeTy, IdTy, ExprTy>; |
125 | using Align = tomp::clause::AlignT<TypeTy, IdTy, ExprTy>; |
126 | using Allocate = tomp::clause::AllocateT<TypeTy, IdTy, ExprTy>; |
127 | using Allocator = tomp::clause::AllocatorT<TypeTy, IdTy, ExprTy>; |
128 | using AppendArgs = tomp::clause::AppendArgsT<TypeTy, IdTy, ExprTy>; |
129 | using AtomicDefaultMemOrder = |
130 | tomp::clause::AtomicDefaultMemOrderT<TypeTy, IdTy, ExprTy>; |
131 | using At = tomp::clause::AtT<TypeTy, IdTy, ExprTy>; |
132 | using Bind = tomp::clause::BindT<TypeTy, IdTy, ExprTy>; |
133 | using Capture = tomp::clause::CaptureT<TypeTy, IdTy, ExprTy>; |
134 | using Collapse = tomp::clause::CollapseT<TypeTy, IdTy, ExprTy>; |
135 | using Compare = tomp::clause::CompareT<TypeTy, IdTy, ExprTy>; |
136 | using Copyin = tomp::clause::CopyinT<TypeTy, IdTy, ExprTy>; |
137 | using Copyprivate = tomp::clause::CopyprivateT<TypeTy, IdTy, ExprTy>; |
138 | using Defaultmap = tomp::clause::DefaultmapT<TypeTy, IdTy, ExprTy>; |
139 | using Default = tomp::clause::DefaultT<TypeTy, IdTy, ExprTy>; |
140 | using Depend = tomp::clause::DependT<TypeTy, IdTy, ExprTy>; |
141 | using Destroy = tomp::clause::DestroyT<TypeTy, IdTy, ExprTy>; |
142 | using Detach = tomp::clause::DetachT<TypeTy, IdTy, ExprTy>; |
143 | using Device = tomp::clause::DeviceT<TypeTy, IdTy, ExprTy>; |
144 | using DeviceType = tomp::clause::DeviceTypeT<TypeTy, IdTy, ExprTy>; |
145 | using DistSchedule = tomp::clause::DistScheduleT<TypeTy, IdTy, ExprTy>; |
146 | using Doacross = tomp::clause::DoacrossT<TypeTy, IdTy, ExprTy>; |
147 | using DynamicAllocators = |
148 | tomp::clause::DynamicAllocatorsT<TypeTy, IdTy, ExprTy>; |
149 | using Enter = tomp::clause::EnterT<TypeTy, IdTy, ExprTy>; |
150 | using Exclusive = tomp::clause::ExclusiveT<TypeTy, IdTy, ExprTy>; |
151 | using Fail = tomp::clause::FailT<TypeTy, IdTy, ExprTy>; |
152 | using Filter = tomp::clause::FilterT<TypeTy, IdTy, ExprTy>; |
153 | using Final = tomp::clause::FinalT<TypeTy, IdTy, ExprTy>; |
154 | using Firstprivate = tomp::clause::FirstprivateT<TypeTy, IdTy, ExprTy>; |
155 | using From = tomp::clause::FromT<TypeTy, IdTy, ExprTy>; |
156 | using Full = tomp::clause::FullT<TypeTy, IdTy, ExprTy>; |
157 | using Grainsize = tomp::clause::GrainsizeT<TypeTy, IdTy, ExprTy>; |
158 | using HasDeviceAddr = tomp::clause::HasDeviceAddrT<TypeTy, IdTy, ExprTy>; |
159 | using Hint = tomp::clause::HintT<TypeTy, IdTy, ExprTy>; |
160 | using If = tomp::clause::IfT<TypeTy, IdTy, ExprTy>; |
161 | using Inbranch = tomp::clause::InbranchT<TypeTy, IdTy, ExprTy>; |
162 | using Inclusive = tomp::clause::InclusiveT<TypeTy, IdTy, ExprTy>; |
163 | using Indirect = tomp::clause::IndirectT<TypeTy, IdTy, ExprTy>; |
164 | using Init = tomp::clause::InitT<TypeTy, IdTy, ExprTy>; |
165 | using InReduction = tomp::clause::InReductionT<TypeTy, IdTy, ExprTy>; |
166 | using IsDevicePtr = tomp::clause::IsDevicePtrT<TypeTy, IdTy, ExprTy>; |
167 | using Lastprivate = tomp::clause::LastprivateT<TypeTy, IdTy, ExprTy>; |
168 | using Linear = tomp::clause::LinearT<TypeTy, IdTy, ExprTy>; |
169 | using Link = tomp::clause::LinkT<TypeTy, IdTy, ExprTy>; |
170 | using Map = tomp::clause::MapT<TypeTy, IdTy, ExprTy>; |
171 | using Match = tomp::clause::MatchT<TypeTy, IdTy, ExprTy>; |
172 | using Mergeable = tomp::clause::MergeableT<TypeTy, IdTy, ExprTy>; |
173 | using Message = tomp::clause::MessageT<TypeTy, IdTy, ExprTy>; |
174 | using Nocontext = tomp::clause::NocontextT<TypeTy, IdTy, ExprTy>; |
175 | using Nogroup = tomp::clause::NogroupT<TypeTy, IdTy, ExprTy>; |
176 | using Nontemporal = tomp::clause::NontemporalT<TypeTy, IdTy, ExprTy>; |
177 | using Notinbranch = tomp::clause::NotinbranchT<TypeTy, IdTy, ExprTy>; |
178 | using Novariants = tomp::clause::NovariantsT<TypeTy, IdTy, ExprTy>; |
179 | using Nowait = tomp::clause::NowaitT<TypeTy, IdTy, ExprTy>; |
180 | using NumTasks = tomp::clause::NumTasksT<TypeTy, IdTy, ExprTy>; |
181 | using NumTeams = tomp::clause::NumTeamsT<TypeTy, IdTy, ExprTy>; |
182 | using NumThreads = tomp::clause::NumThreadsT<TypeTy, IdTy, ExprTy>; |
183 | using OmpxAttribute = tomp::clause::OmpxAttributeT<TypeTy, IdTy, ExprTy>; |
184 | using OmpxBare = tomp::clause::OmpxBareT<TypeTy, IdTy, ExprTy>; |
185 | using OmpxDynCgroupMem = tomp::clause::OmpxDynCgroupMemT<TypeTy, IdTy, ExprTy>; |
186 | using Ordered = tomp::clause::OrderedT<TypeTy, IdTy, ExprTy>; |
187 | using Order = tomp::clause::OrderT<TypeTy, IdTy, ExprTy>; |
188 | using Partial = tomp::clause::PartialT<TypeTy, IdTy, ExprTy>; |
189 | using Priority = tomp::clause::PriorityT<TypeTy, IdTy, ExprTy>; |
190 | using Private = tomp::clause::PrivateT<TypeTy, IdTy, ExprTy>; |
191 | using ProcBind = tomp::clause::ProcBindT<TypeTy, IdTy, ExprTy>; |
192 | using Read = tomp::clause::ReadT<TypeTy, IdTy, ExprTy>; |
193 | using Reduction = tomp::clause::ReductionT<TypeTy, IdTy, ExprTy>; |
194 | using Relaxed = tomp::clause::RelaxedT<TypeTy, IdTy, ExprTy>; |
195 | using Release = tomp::clause::ReleaseT<TypeTy, IdTy, ExprTy>; |
196 | using ReverseOffload = tomp::clause::ReverseOffloadT<TypeTy, IdTy, ExprTy>; |
197 | using Safelen = tomp::clause::SafelenT<TypeTy, IdTy, ExprTy>; |
198 | using Schedule = tomp::clause::ScheduleT<TypeTy, IdTy, ExprTy>; |
199 | using SeqCst = tomp::clause::SeqCstT<TypeTy, IdTy, ExprTy>; |
200 | using Severity = tomp::clause::SeverityT<TypeTy, IdTy, ExprTy>; |
201 | using Shared = tomp::clause::SharedT<TypeTy, IdTy, ExprTy>; |
202 | using Simdlen = tomp::clause::SimdlenT<TypeTy, IdTy, ExprTy>; |
203 | using Simd = tomp::clause::SimdT<TypeTy, IdTy, ExprTy>; |
204 | using Sizes = tomp::clause::SizesT<TypeTy, IdTy, ExprTy>; |
205 | using TaskReduction = tomp::clause::TaskReductionT<TypeTy, IdTy, ExprTy>; |
206 | using ThreadLimit = tomp::clause::ThreadLimitT<TypeTy, IdTy, ExprTy>; |
207 | using Threads = tomp::clause::ThreadsT<TypeTy, IdTy, ExprTy>; |
208 | using To = tomp::clause::ToT<TypeTy, IdTy, ExprTy>; |
209 | using UnifiedAddress = tomp::clause::UnifiedAddressT<TypeTy, IdTy, ExprTy>; |
210 | using UnifiedSharedMemory = |
211 | tomp::clause::UnifiedSharedMemoryT<TypeTy, IdTy, ExprTy>; |
212 | using Uniform = tomp::clause::UniformT<TypeTy, IdTy, ExprTy>; |
213 | using Unknown = tomp::clause::UnknownT<TypeTy, IdTy, ExprTy>; |
214 | using Untied = tomp::clause::UntiedT<TypeTy, IdTy, ExprTy>; |
215 | using Update = tomp::clause::UpdateT<TypeTy, IdTy, ExprTy>; |
216 | using UseDeviceAddr = tomp::clause::UseDeviceAddrT<TypeTy, IdTy, ExprTy>; |
217 | using UseDevicePtr = tomp::clause::UseDevicePtrT<TypeTy, IdTy, ExprTy>; |
218 | using UsesAllocators = tomp::clause::UsesAllocatorsT<TypeTy, IdTy, ExprTy>; |
219 | using Use = tomp::clause::UseT<TypeTy, IdTy, ExprTy>; |
220 | using Weak = tomp::clause::WeakT<TypeTy, IdTy, ExprTy>; |
221 | using When = tomp::clause::WhenT<TypeTy, IdTy, ExprTy>; |
222 | using Write = tomp::clause::WriteT<TypeTy, IdTy, ExprTy>; |
223 | } // namespace clause |
224 | |
225 | struct CancellationConstructType { |
226 | using EmptyTrait = std::true_type; |
227 | }; |
228 | struct Depobj { |
229 | using EmptyTrait = std::true_type; |
230 | }; |
231 | struct Flush { |
232 | using EmptyTrait = std::true_type; |
233 | }; |
234 | struct MemoryOrder { |
235 | using EmptyTrait = std::true_type; |
236 | }; |
237 | struct Threadprivate { |
238 | using EmptyTrait = std::true_type; |
239 | }; |
240 | |
241 | using ClauseBase = tomp::ClauseT<TypeTy, IdTy, ExprTy, |
242 | // Extras... |
243 | CancellationConstructType, Depobj, Flush, |
244 | MemoryOrder, Threadprivate>; |
245 | |
246 | struct Clause : public ClauseBase { |
247 | parser::CharBlock source; |
248 | }; |
249 | |
250 | template <typename Specific> |
251 | Clause makeClause(llvm::omp::Clause id, Specific &&specific, |
252 | parser::CharBlock source = {}) { |
253 | return Clause{{id, specific}, source}; |
254 | } |
255 | |
256 | Clause makeClause(const Fortran::parser::OmpClause &cls, |
257 | semantics::SemanticsContext &semaCtx); |
258 | |
259 | List<Clause> makeClauses(const parser::OmpClauseList &clauses, |
260 | semantics::SemanticsContext &semaCtx); |
261 | } // namespace Fortran::lower::omp |
262 | |
263 | #endif // FORTRAN_LOWER_OPENMP_CLAUSES_H |
264 | |