FLANG
Clauses.h
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/Evaluate/type.h"
13#include "flang/Parser/parse-tree.h"
14#include "flang/Semantics/expression.h"
15#include "flang/Semantics/semantics.h"
16#include "flang/Semantics/symbol.h"
17
18#include "llvm/ADT/STLExtras.h"
19#include "llvm/Frontend/OpenMP/ClauseT.h"
20
21#include <optional>
22#include <type_traits>
23#include <utility>
24
25namespace Fortran::semantics {
26class Symbol;
27}
28
29namespace Fortran::lower::omp {
30using namespace Fortran;
31using SomeExpr = semantics::SomeExpr;
32using MaybeExpr = semantics::MaybeExpr;
33using TypeTy = evaluate::DynamicType;
34
35template <typename ExprTy>
37 // "symbol" is always non-null for id's of actual objects.
39 std::optional<ExprTy> designator;
40
41 bool operator==(const IdTyTemplate &other) const {
42 // If symbols are different, then the objects are different.
43 if (symbol != other.symbol)
44 return false;
45 if (symbol == nullptr)
46 return true;
47 // Equal symbols don't necessarily indicate identical objects,
48 // for example, a derived object component may use a single symbol,
49 // which will refer to different objects for different designators,
50 // e.g. a%c and b%c.
51 return designator == other.designator;
52 }
53
54 // Defining an "ordering" which allows types derived from this to be
55 // utilised in maps and other containers that require comparison
56 // operators for ordering
57 bool operator<(const IdTyTemplate &other) const {
58 return symbol < other.symbol;
59 }
60
61 operator bool() const { return symbol != nullptr; }
62};
63
64using ExprTy = SomeExpr;
65
66template <typename T>
67using List = tomp::ListT<T>;
68} // namespace Fortran::lower::omp
69
70// Specialization of the ObjectT template
71namespace tomp::type {
72template <>
73struct ObjectT<Fortran::lower::omp::IdTyTemplate<Fortran::lower::omp::ExprTy>,
77
78 IdTy id() const { return identity; }
79 Fortran::semantics::Symbol *sym() const { return identity.symbol; }
80 const std::optional<ExprTy> &ref() const { return identity.designator; }
81
82 bool operator<(const ObjectT<IdTy, ExprTy> &other) const {
83 return identity < other.identity;
84 }
85
86 IdTy identity;
87};
88} // namespace tomp::type
89
90namespace Fortran::lower::omp {
91using IdTy = IdTyTemplate<ExprTy>;
92}
93
94namespace std {
95template <>
97 size_t operator()(const Fortran::lower::omp::IdTy &id) const {
98 return static_cast<size_t>(reinterpret_cast<uintptr_t>(id.symbol));
99 }
100};
101} // namespace std
102
103namespace Fortran::lower::omp {
104using Object = tomp::ObjectT<IdTy, ExprTy>;
105using ObjectList = tomp::ObjectListT<IdTy, ExprTy>;
106
107Object makeObject(const parser::OmpObject &object,
109Object makeObject(const parser::Name &name,
111Object makeObject(const parser::Designator &dsg,
113Object makeObject(const parser::StructureComponent &comp,
115
116inline auto makeObjectFn(semantics::SemanticsContext &semaCtx) {
117 return [&](auto &&s) { return makeObject(s, semaCtx); };
118}
119
120template <typename T>
121SomeExpr makeExpr(T &&pftExpr, semantics::SemanticsContext &semaCtx) {
122 auto maybeExpr = evaluate::ExpressionAnalyzer(semaCtx).Analyze(pftExpr);
123 assert(maybeExpr);
124 return std::move(*maybeExpr);
125}
126
127inline auto makeExprFn(semantics::SemanticsContext &semaCtx) {
128 return [&](auto &&s) { return makeExpr(s, semaCtx); };
129}
130
131template <
132 typename ContainerTy, typename FunctionTy,
133 typename ElemTy = typename llvm::remove_cvref_t<ContainerTy>::value_type,
134 typename ResultTy = std::invoke_result_t<FunctionTy, ElemTy>>
135List<ResultTy> makeList(ContainerTy &&container, FunctionTy &&func) {
136 List<ResultTy> v;
137 llvm::transform(container, std::back_inserter(v), func);
138 return v;
139}
140
141inline ObjectList makeObjects(const parser::OmpObjectList &objects,
143 return makeList(objects.v, makeObjectFn(semaCtx));
144}
145
146template <typename FuncTy, //
147 typename ArgTy, //
148 typename ResultTy = std::invoke_result_t<FuncTy, ArgTy>>
149std::optional<ResultTy> maybeApply(FuncTy &&func,
150 const std::optional<ArgTy> &arg) {
151 if (!arg)
152 return std::nullopt;
153 return func(*arg);
154}
155
156template < //
157 typename FuncTy, //
158 typename ArgTy, //
159 typename ResultTy =
160 std::invoke_result_t<FuncTy, decltype(std::declval<ArgTy>().v)>>
161std::optional<ResultTy> maybeApplyToV(FuncTy &&func, const ArgTy *arg) {
162 if (!arg)
163 return std::nullopt;
164 return func(arg->v);
165}
166
167std::optional<Object> getBaseObject(const Object &object,
169
170namespace clause {
171using Range = tomp::type::RangeT<ExprTy>;
172using Mapper = tomp::type::MapperT<IdTy, ExprTy>;
173using Iterator = tomp::type::IteratorT<TypeTy, IdTy, ExprTy>;
174using IteratorSpecifier = tomp::type::IteratorSpecifierT<TypeTy, IdTy, ExprTy>;
175using DefinedOperator = tomp::type::DefinedOperatorT<IdTy, ExprTy>;
176using ProcedureDesignator = tomp::type::ProcedureDesignatorT<IdTy, ExprTy>;
177using ReductionOperator = tomp::type::ReductionIdentifierT<IdTy, ExprTy>;
178using DependenceType = tomp::type::DependenceType;
179using Prescriptiveness = tomp::type::Prescriptiveness;
180
181// "Requires" clauses are handled early on, and the aggregated information
182// is stored in the Symbol details of modules, programs, and subprograms.
183// These clauses are still handled here to cover all alternatives in the
184// main clause variant.
185
186using Absent = tomp::clause::AbsentT<TypeTy, IdTy, ExprTy>;
187using AcqRel = tomp::clause::AcqRelT<TypeTy, IdTy, ExprTy>;
188using Acquire = tomp::clause::AcquireT<TypeTy, IdTy, ExprTy>;
189using AdjustArgs = tomp::clause::AdjustArgsT<TypeTy, IdTy, ExprTy>;
190using Affinity = tomp::clause::AffinityT<TypeTy, IdTy, ExprTy>;
191using Aligned = tomp::clause::AlignedT<TypeTy, IdTy, ExprTy>;
192using Align = tomp::clause::AlignT<TypeTy, IdTy, ExprTy>;
193using Allocate = tomp::clause::AllocateT<TypeTy, IdTy, ExprTy>;
194using Allocator = tomp::clause::AllocatorT<TypeTy, IdTy, ExprTy>;
195using AppendArgs = tomp::clause::AppendArgsT<TypeTy, IdTy, ExprTy>;
196using AtomicDefaultMemOrder =
197 tomp::clause::AtomicDefaultMemOrderT<TypeTy, IdTy, ExprTy>;
198using At = tomp::clause::AtT<TypeTy, IdTy, ExprTy>;
199using Bind = tomp::clause::BindT<TypeTy, IdTy, ExprTy>;
200using Capture = tomp::clause::CaptureT<TypeTy, IdTy, ExprTy>;
201using Collapse = tomp::clause::CollapseT<TypeTy, IdTy, ExprTy>;
202using Compare = tomp::clause::CompareT<TypeTy, IdTy, ExprTy>;
203using Contains = tomp::clause::ContainsT<TypeTy, IdTy, ExprTy>;
204using Copyin = tomp::clause::CopyinT<TypeTy, IdTy, ExprTy>;
205using Copyprivate = tomp::clause::CopyprivateT<TypeTy, IdTy, ExprTy>;
206using Defaultmap = tomp::clause::DefaultmapT<TypeTy, IdTy, ExprTy>;
207using Default = tomp::clause::DefaultT<TypeTy, IdTy, ExprTy>;
208using Depend = tomp::clause::DependT<TypeTy, IdTy, ExprTy>;
209using Destroy = tomp::clause::DestroyT<TypeTy, IdTy, ExprTy>;
210using Detach = tomp::clause::DetachT<TypeTy, IdTy, ExprTy>;
211using Device = tomp::clause::DeviceT<TypeTy, IdTy, ExprTy>;
212using DeviceType = tomp::clause::DeviceTypeT<TypeTy, IdTy, ExprTy>;
213using DistSchedule = tomp::clause::DistScheduleT<TypeTy, IdTy, ExprTy>;
214using Doacross = tomp::clause::DoacrossT<TypeTy, IdTy, ExprTy>;
215using DynamicAllocators =
216 tomp::clause::DynamicAllocatorsT<TypeTy, IdTy, ExprTy>;
217using Enter = tomp::clause::EnterT<TypeTy, IdTy, ExprTy>;
218using Exclusive = tomp::clause::ExclusiveT<TypeTy, IdTy, ExprTy>;
219using Fail = tomp::clause::FailT<TypeTy, IdTy, ExprTy>;
220using Filter = tomp::clause::FilterT<TypeTy, IdTy, ExprTy>;
221using Final = tomp::clause::FinalT<TypeTy, IdTy, ExprTy>;
222using Firstprivate = tomp::clause::FirstprivateT<TypeTy, IdTy, ExprTy>;
223using From = tomp::clause::FromT<TypeTy, IdTy, ExprTy>;
224using Full = tomp::clause::FullT<TypeTy, IdTy, ExprTy>;
225using Grainsize = tomp::clause::GrainsizeT<TypeTy, IdTy, ExprTy>;
226using HasDeviceAddr = tomp::clause::HasDeviceAddrT<TypeTy, IdTy, ExprTy>;
227using Hint = tomp::clause::HintT<TypeTy, IdTy, ExprTy>;
228using Holds = tomp::clause::HoldsT<TypeTy, IdTy, ExprTy>;
229using If = tomp::clause::IfT<TypeTy, IdTy, ExprTy>;
230using Inbranch = tomp::clause::InbranchT<TypeTy, IdTy, ExprTy>;
231using Inclusive = tomp::clause::InclusiveT<TypeTy, IdTy, ExprTy>;
232using Indirect = tomp::clause::IndirectT<TypeTy, IdTy, ExprTy>;
233using Init = tomp::clause::InitT<TypeTy, IdTy, ExprTy>;
234using InReduction = tomp::clause::InReductionT<TypeTy, IdTy, ExprTy>;
235using IsDevicePtr = tomp::clause::IsDevicePtrT<TypeTy, IdTy, ExprTy>;
236using Lastprivate = tomp::clause::LastprivateT<TypeTy, IdTy, ExprTy>;
237using Linear = tomp::clause::LinearT<TypeTy, IdTy, ExprTy>;
238using Link = tomp::clause::LinkT<TypeTy, IdTy, ExprTy>;
239using Map = tomp::clause::MapT<TypeTy, IdTy, ExprTy>;
240using Match = tomp::clause::MatchT<TypeTy, IdTy, ExprTy>;
241using Mergeable = tomp::clause::MergeableT<TypeTy, IdTy, ExprTy>;
242using Message = tomp::clause::MessageT<TypeTy, IdTy, ExprTy>;
243using NoOpenmp = tomp::clause::NoOpenmpT<TypeTy, IdTy, ExprTy>;
244using NoOpenmpRoutines = tomp::clause::NoOpenmpRoutinesT<TypeTy, IdTy, ExprTy>;
245using NoParallelism = tomp::clause::NoParallelismT<TypeTy, IdTy, ExprTy>;
246using Nocontext = tomp::clause::NocontextT<TypeTy, IdTy, ExprTy>;
247using Nogroup = tomp::clause::NogroupT<TypeTy, IdTy, ExprTy>;
248using Nontemporal = tomp::clause::NontemporalT<TypeTy, IdTy, ExprTy>;
249using Notinbranch = tomp::clause::NotinbranchT<TypeTy, IdTy, ExprTy>;
250using Novariants = tomp::clause::NovariantsT<TypeTy, IdTy, ExprTy>;
251using Nowait = tomp::clause::NowaitT<TypeTy, IdTy, ExprTy>;
252using NumTasks = tomp::clause::NumTasksT<TypeTy, IdTy, ExprTy>;
253using NumTeams = tomp::clause::NumTeamsT<TypeTy, IdTy, ExprTy>;
254using NumThreads = tomp::clause::NumThreadsT<TypeTy, IdTy, ExprTy>;
255using OmpxAttribute = tomp::clause::OmpxAttributeT<TypeTy, IdTy, ExprTy>;
256using OmpxBare = tomp::clause::OmpxBareT<TypeTy, IdTy, ExprTy>;
257using OmpxDynCgroupMem = tomp::clause::OmpxDynCgroupMemT<TypeTy, IdTy, ExprTy>;
258using Ordered = tomp::clause::OrderedT<TypeTy, IdTy, ExprTy>;
259using Order = tomp::clause::OrderT<TypeTy, IdTy, ExprTy>;
260using Partial = tomp::clause::PartialT<TypeTy, IdTy, ExprTy>;
261using Priority = tomp::clause::PriorityT<TypeTy, IdTy, ExprTy>;
262using Private = tomp::clause::PrivateT<TypeTy, IdTy, ExprTy>;
263using ProcBind = tomp::clause::ProcBindT<TypeTy, IdTy, ExprTy>;
264using Read = tomp::clause::ReadT<TypeTy, IdTy, ExprTy>;
265using Reduction = tomp::clause::ReductionT<TypeTy, IdTy, ExprTy>;
266using Relaxed = tomp::clause::RelaxedT<TypeTy, IdTy, ExprTy>;
267using Release = tomp::clause::ReleaseT<TypeTy, IdTy, ExprTy>;
268using ReverseOffload = tomp::clause::ReverseOffloadT<TypeTy, IdTy, ExprTy>;
269using Safelen = tomp::clause::SafelenT<TypeTy, IdTy, ExprTy>;
270using Schedule = tomp::clause::ScheduleT<TypeTy, IdTy, ExprTy>;
271using SeqCst = tomp::clause::SeqCstT<TypeTy, IdTy, ExprTy>;
272using Severity = tomp::clause::SeverityT<TypeTy, IdTy, ExprTy>;
273using Shared = tomp::clause::SharedT<TypeTy, IdTy, ExprTy>;
274using Simdlen = tomp::clause::SimdlenT<TypeTy, IdTy, ExprTy>;
275using Simd = tomp::clause::SimdT<TypeTy, IdTy, ExprTy>;
276using Sizes = tomp::clause::SizesT<TypeTy, IdTy, ExprTy>;
277using Permutation = tomp::clause::PermutationT<TypeTy, IdTy, ExprTy>;
278using TaskReduction = tomp::clause::TaskReductionT<TypeTy, IdTy, ExprTy>;
279using ThreadLimit = tomp::clause::ThreadLimitT<TypeTy, IdTy, ExprTy>;
280using Threads = tomp::clause::ThreadsT<TypeTy, IdTy, ExprTy>;
281using To = tomp::clause::ToT<TypeTy, IdTy, ExprTy>;
282using UnifiedAddress = tomp::clause::UnifiedAddressT<TypeTy, IdTy, ExprTy>;
283using UnifiedSharedMemory =
284 tomp::clause::UnifiedSharedMemoryT<TypeTy, IdTy, ExprTy>;
285using Uniform = tomp::clause::UniformT<TypeTy, IdTy, ExprTy>;
286using Unknown = tomp::clause::UnknownT<TypeTy, IdTy, ExprTy>;
287using Untied = tomp::clause::UntiedT<TypeTy, IdTy, ExprTy>;
288using Update = tomp::clause::UpdateT<TypeTy, IdTy, ExprTy>;
289using UseDeviceAddr = tomp::clause::UseDeviceAddrT<TypeTy, IdTy, ExprTy>;
290using UseDevicePtr = tomp::clause::UseDevicePtrT<TypeTy, IdTy, ExprTy>;
291using UsesAllocators = tomp::clause::UsesAllocatorsT<TypeTy, IdTy, ExprTy>;
292using Use = tomp::clause::UseT<TypeTy, IdTy, ExprTy>;
293using Weak = tomp::clause::WeakT<TypeTy, IdTy, ExprTy>;
294using When = tomp::clause::WhenT<TypeTy, IdTy, ExprTy>;
295using Write = tomp::clause::WriteT<TypeTy, IdTy, ExprTy>;
296} // namespace clause
297
298using tomp::type::operator==;
299
301 using EmptyTrait = std::true_type;
302};
303struct Depobj {
304 using EmptyTrait = std::true_type;
305};
306struct Flush {
307 using EmptyTrait = std::true_type;
308};
310 using EmptyTrait = std::true_type;
311};
313 using EmptyTrait = std::true_type;
314};
315
316using ClauseBase = tomp::ClauseT<TypeTy, IdTy, ExprTy,
317 // Extras...
320
321struct Clause : public ClauseBase {
322 Clause(ClauseBase &&base, const parser::CharBlock source = {})
323 : ClauseBase(std::move(base)), source(source) {}
324 // "source" will be ignored by tomp::type::operator==.
325 parser::CharBlock source;
326};
327
328template <typename Specific>
329Clause makeClause(llvm::omp::Clause id, Specific &&specific,
330 parser::CharBlock source = {}) {
331 return Clause(typename Clause::BaseT{id, specific}, source);
332}
333
334Clause makeClause(const parser::OmpClause &cls,
336
337List<Clause> makeClauses(const parser::OmpClauseList &clauses,
339
340bool transferLocations(const List<Clause> &from, List<Clause> &to);
341} // namespace Fortran::lower::omp
342
343#endif // FORTRAN_LOWER_OPENMP_CLAUSES_H
Definition: type.h:95
Definition: expression.h:102
Definition: char-block.h:28
Definition: semantics.h:67
Definition: symbol.h:712
Definition: bit-population-count.h:20
Definition: Clauses.h:321
Definition: Clauses.h:303
Definition: Clauses.h:306
Definition: Clauses.h:36
Definition: Clauses.h:309
Definition: Clauses.h:312
Definition: parse-tree.h:1857
Definition: parse-tree.h:580
Definition: parse-tree.h:4333
Definition: parse-tree.h:4317
Definition: parse-tree.h:3463
Definition: parse-tree.h:1887