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#include "llvm/Frontend/OpenMP/OMP.h.inc"
21
22#include <optional>
23#include <type_traits>
24#include <utility>
25
26namespace Fortran::semantics {
27class Symbol;
28}
29
30namespace Fortran::lower::omp {
31using namespace Fortran;
32using SomeExpr = semantics::SomeExpr;
33using MaybeExpr = semantics::MaybeExpr;
34using TypeTy = evaluate::DynamicType;
35
36template <typename ExprTy>
38 // "symbol" is always non-null for id's of actual objects.
40 std::optional<ExprTy> designator;
41
42 bool operator==(const IdTyTemplate &other) const {
43 // If symbols are different, then the objects are different.
44 if (symbol != other.symbol)
45 return false;
46 if (symbol == nullptr)
47 return true;
48 // Equal symbols don't necessarily indicate identical objects,
49 // for example, a derived object component may use a single symbol,
50 // which will refer to different objects for different designators,
51 // e.g. a%c and b%c.
52 return designator == other.designator;
53 }
54
55 // Defining an "ordering" which allows types derived from this to be
56 // utilised in maps and other containers that require comparison
57 // operators for ordering
58 bool operator<(const IdTyTemplate &other) const {
59 return symbol < other.symbol;
60 }
61
62 operator bool() const { return symbol != nullptr; }
63};
64
65using ExprTy = SomeExpr;
66
67template <typename T>
68using List = tomp::ListT<T>;
69} // namespace Fortran::lower::omp
70
71// Specialization of the ObjectT template
72namespace tomp::type {
73template <>
74struct ObjectT<Fortran::lower::omp::IdTyTemplate<Fortran::lower::omp::ExprTy>,
75 Fortran::lower::omp::ExprTy> {
77 using ExprTy = Fortran::lower::omp::ExprTy;
78
79 ObjectT() = default;
80 ObjectT(IdTy id) : identity(std::move(id)) {}
81 ObjectT(Fortran::semantics::Symbol *symbol, std::optional<ExprTy> designator)
82 : identity{symbol, std::move(designator)} {}
83
84 IdTy id() const { return identity; }
85 Fortran::semantics::Symbol *sym() const { return identity.symbol; }
86 const std::optional<ExprTy> &ref() const { return identity.designator; }
87
88 bool operator<(const ObjectT<IdTy, ExprTy> &other) const {
89 return identity < other.identity;
90 }
91
92 IdTy identity;
93
94 // Resolved iterator references in the source locator, before expression
95 // folding can remove them. This is per-occurrence metadata, not object
96 // identity: a(j) and a(j + 0*i) may have equal folded designators.
97 // An engaged, empty list means the locator references no clause iterators.
98 std::optional<Fortran::lower::omp::List<const Fortran::semantics::Symbol *>>
99 sourceIteratorReferences = std::nullopt;
100};
101} // namespace tomp::type
102
103namespace Fortran::lower::omp {
104using IdTy = IdTyTemplate<ExprTy>;
105}
106
107namespace std {
108template <>
109struct hash<Fortran::lower::omp::IdTy> {
110 size_t operator()(const Fortran::lower::omp::IdTy &id) const {
111 return static_cast<size_t>(reinterpret_cast<uintptr_t>(id.symbol));
112 }
113};
114} // namespace std
115
116namespace Fortran::lower::omp {
117using Object = tomp::ObjectT<IdTy, ExprTy>;
118using ObjectList = tomp::ObjectListT<IdTy, ExprTy>;
119using StylizedInstance = tomp::type::StylizedInstanceT<IdTy, ExprTy>;
120
121Object makeObject(const parser::OmpObject &object,
123Object makeObject(const parser::Name &name,
125Object makeObject(const parser::Designator &dsg,
127Object makeObject(const parser::StructureComponent &comp,
129Object makeObject(const parser::EntityDecl &decl,
131
132inline auto makeObjectFn(semantics::SemanticsContext &semaCtx) {
133 return [&](auto &&s) { return makeObject(s, semaCtx); };
134}
135
136template <typename T>
137SomeExpr makeExpr(T &&pftExpr, semantics::SemanticsContext &semaCtx) {
138 auto maybeExpr = evaluate::ExpressionAnalyzer(semaCtx).Analyze(pftExpr);
139 assert(maybeExpr);
140 return std::move(*maybeExpr);
141}
142
143inline auto makeExprFn(semantics::SemanticsContext &semaCtx) {
144 return [&](auto &&s) { return makeExpr(s, semaCtx); };
145}
146
147template <
148 typename ContainerTy, typename FunctionTy,
149 typename ElemTy = typename llvm::remove_cvref_t<ContainerTy>::value_type,
150 typename ResultTy = std::invoke_result_t<FunctionTy, ElemTy>>
151List<ResultTy> makeList(ContainerTy &&container, FunctionTy &&func) {
152 List<ResultTy> v;
153 llvm::transform(container, std::back_inserter(v), func);
154 return v;
155}
156
157inline ObjectList makeObjects(const parser::OmpObjectList &objects,
158 semantics::SemanticsContext &semaCtx) {
159 return makeList(objects.v, makeObjectFn(semaCtx));
160}
161
162ObjectList makeObjects(const parser::OmpArgumentList &objects,
163 semantics::SemanticsContext &semaCtx);
164
165template <typename FuncTy, //
166 typename ArgTy, //
167 typename ResultTy = std::invoke_result_t<FuncTy, ArgTy>>
168std::optional<ResultTy> maybeApply(FuncTy &&func,
169 const std::optional<ArgTy> &arg) {
170 if (!arg)
171 return std::nullopt;
172 return func(*arg);
173}
174
175template < //
176 typename FuncTy, //
177 typename ArgTy, //
178 typename ResultTy =
179 std::invoke_result_t<FuncTy, decltype(std::declval<ArgTy>().v)>>
180std::optional<ResultTy> maybeApplyToV(FuncTy &&func, const ArgTy *arg) {
181 if (!arg)
182 return std::nullopt;
183 return func(arg->v);
184}
185
186std::optional<Object> getBaseObject(const Object &object,
187 semantics::SemanticsContext &semaCtx);
188
189StylizedInstance makeStylizedInstance(const parser::OmpStylizedInstance &inp,
190 semantics::SemanticsContext &semaCtx);
191
192namespace clause {
193using Range = tomp::type::RangeT<ExprTy>;
194using Mapper = tomp::type::MapperT<IdTy, ExprTy>;
195using Iterator = tomp::type::IteratorT<TypeTy, IdTy, ExprTy>;
196using IteratorSpecifier = tomp::type::IteratorSpecifierT<TypeTy, IdTy, ExprTy>;
197using DefinedOperator = tomp::type::DefinedOperatorT<IdTy, ExprTy>;
198using ProcedureDesignator = tomp::type::ProcedureDesignatorT<IdTy, ExprTy>;
199using ReductionOperator = tomp::type::ReductionIdentifierT<IdTy, ExprTy>;
200using ReductionOperatorList = List<ReductionOperator>;
201using DependenceType = tomp::type::DependenceType;
202using Prescriptiveness = tomp::type::Prescriptiveness;
203
204// "Requires" clauses are handled early on, and the aggregated information
205// is stored in the Symbol details of modules, programs, and subprograms.
206// These clauses are still handled here to cover all alternatives in the
207// main clause variant.
208
209using Absent = tomp::clause::AbsentT<TypeTy, IdTy, ExprTy>;
210using AcqRel = tomp::clause::AcqRelT<TypeTy, IdTy, ExprTy>;
211using Acquire = tomp::clause::AcquireT<TypeTy, IdTy, ExprTy>;
212using AdjustArgs = tomp::clause::AdjustArgsT<TypeTy, IdTy, ExprTy>;
213using Affinity = tomp::clause::AffinityT<TypeTy, IdTy, ExprTy>;
214using Aligned = tomp::clause::AlignedT<TypeTy, IdTy, ExprTy>;
215using Align = tomp::clause::AlignT<TypeTy, IdTy, ExprTy>;
216using Allocate = tomp::clause::AllocateT<TypeTy, IdTy, ExprTy>;
217using Allocator = tomp::clause::AllocatorT<TypeTy, IdTy, ExprTy>;
218using AppendArgs = tomp::clause::AppendArgsT<TypeTy, IdTy, ExprTy>;
219using Apply = tomp::clause::ApplyT<TypeTy, IdTy, ExprTy>;
220using At = tomp::clause::AtT<TypeTy, IdTy, ExprTy>;
221using AtomicDefaultMemOrder =
222 tomp::clause::AtomicDefaultMemOrderT<TypeTy, IdTy, ExprTy>;
223using Bind = tomp::clause::BindT<TypeTy, IdTy, ExprTy>;
224using Capture = tomp::clause::CaptureT<TypeTy, IdTy, ExprTy>;
225using Collapse = tomp::clause::CollapseT<TypeTy, IdTy, ExprTy>;
226using Collector = tomp::clause::CollectorT<TypeTy, IdTy, ExprTy>;
227using Combiner = tomp::clause::CombinerT<TypeTy, IdTy, ExprTy>;
228using Compare = tomp::clause::CompareT<TypeTy, IdTy, ExprTy>;
229using Contains = tomp::clause::ContainsT<TypeTy, IdTy, ExprTy>;
230using Copyin = tomp::clause::CopyinT<TypeTy, IdTy, ExprTy>;
231using Copyprivate = tomp::clause::CopyprivateT<TypeTy, IdTy, ExprTy>;
232using Counts = tomp::clause::CountsT<TypeTy, IdTy, ExprTy>;
233using Default = tomp::clause::DefaultT<TypeTy, IdTy, ExprTy>;
234using Defaultmap = tomp::clause::DefaultmapT<TypeTy, IdTy, ExprTy>;
235using Depend = tomp::clause::DependT<TypeTy, IdTy, ExprTy>;
236using Depth = tomp::clause::DepthT<TypeTy, IdTy, ExprTy>;
237using Destroy = tomp::clause::DestroyT<TypeTy, IdTy, ExprTy>;
238using Detach = tomp::clause::DetachT<TypeTy, IdTy, ExprTy>;
239using Device = tomp::clause::DeviceT<TypeTy, IdTy, ExprTy>;
240using DeviceSafesync = tomp::clause::DeviceSafesyncT<TypeTy, IdTy, ExprTy>;
241using DeviceType = tomp::clause::DeviceTypeT<TypeTy, IdTy, ExprTy>;
242using DistSchedule = tomp::clause::DistScheduleT<TypeTy, IdTy, ExprTy>;
243using Doacross = tomp::clause::DoacrossT<TypeTy, IdTy, ExprTy>;
244using DynamicAllocators =
245 tomp::clause::DynamicAllocatorsT<TypeTy, IdTy, ExprTy>;
246using DynGroupprivate = tomp::clause::DynGroupprivateT<TypeTy, IdTy, ExprTy>;
247using Enter = tomp::clause::EnterT<TypeTy, IdTy, ExprTy>;
248using Exclusive = tomp::clause::ExclusiveT<TypeTy, IdTy, ExprTy>;
249using Fail = tomp::clause::FailT<TypeTy, IdTy, ExprTy>;
250using Filter = tomp::clause::FilterT<TypeTy, IdTy, ExprTy>;
251using Final = tomp::clause::FinalT<TypeTy, IdTy, ExprTy>;
252using Firstprivate = tomp::clause::FirstprivateT<TypeTy, IdTy, ExprTy>;
253using From = tomp::clause::FromT<TypeTy, IdTy, ExprTy>;
254using Full = tomp::clause::FullT<TypeTy, IdTy, ExprTy>;
255using Grainsize = tomp::clause::GrainsizeT<TypeTy, IdTy, ExprTy>;
256using GraphId = tomp::clause::GraphIdT<TypeTy, IdTy, ExprTy>;
257using GraphReset = tomp::clause::GraphResetT<TypeTy, IdTy, ExprTy>;
258using HasDeviceAddr = tomp::clause::HasDeviceAddrT<TypeTy, IdTy, ExprTy>;
259using Hint = tomp::clause::HintT<TypeTy, IdTy, ExprTy>;
260using Holds = tomp::clause::HoldsT<TypeTy, IdTy, ExprTy>;
261using If = tomp::clause::IfT<TypeTy, IdTy, ExprTy>;
262using Inbranch = tomp::clause::InbranchT<TypeTy, IdTy, ExprTy>;
263using Inclusive = tomp::clause::InclusiveT<TypeTy, IdTy, ExprTy>;
264using Indirect = tomp::clause::IndirectT<TypeTy, IdTy, ExprTy>;
265using Induction = tomp::clause::InductionT<TypeTy, IdTy, ExprTy>;
266using Inductor = tomp::clause::InductorT<TypeTy, IdTy, ExprTy>;
267using Init = tomp::clause::InitT<TypeTy, IdTy, ExprTy>;
268using InitComplete = tomp::clause::InitCompleteT<TypeTy, IdTy, ExprTy>;
269using Initializer = tomp::clause::InitializerT<TypeTy, IdTy, ExprTy>;
270using InReduction = tomp::clause::InReductionT<TypeTy, IdTy, ExprTy>;
271using Interop = tomp::clause::InteropT<TypeTy, IdTy, ExprTy>;
272using IsDevicePtr = tomp::clause::IsDevicePtrT<TypeTy, IdTy, ExprTy>;
273using Lastprivate = tomp::clause::LastprivateT<TypeTy, IdTy, ExprTy>;
274using Linear = tomp::clause::LinearT<TypeTy, IdTy, ExprTy>;
275using Link = tomp::clause::LinkT<TypeTy, IdTy, ExprTy>;
276using Local = tomp::clause::LocalT<TypeTy, IdTy, ExprTy>;
277using Looprange = tomp::clause::LooprangeT<TypeTy, IdTy, ExprTy>;
278using Map = tomp::clause::MapT<TypeTy, IdTy, ExprTy>;
279using Match = tomp::clause::MatchT<TypeTy, IdTy, ExprTy>;
280using Memscope = tomp::clause::MemscopeT<TypeTy, IdTy, ExprTy>;
281using Mergeable = tomp::clause::MergeableT<TypeTy, IdTy, ExprTy>;
282using Message = tomp::clause::MessageT<TypeTy, IdTy, ExprTy>;
283using Nocontext = tomp::clause::NocontextT<TypeTy, IdTy, ExprTy>;
284using Nogroup = tomp::clause::NogroupT<TypeTy, IdTy, ExprTy>;
285using Nontemporal = tomp::clause::NontemporalT<TypeTy, IdTy, ExprTy>;
286using NoOpenmp = tomp::clause::NoOpenmpT<TypeTy, IdTy, ExprTy>;
287using NoOpenmpConstructs =
288 tomp::clause::NoOpenmpConstructsT<TypeTy, IdTy, ExprTy>;
289using NoOpenmpRoutines = tomp::clause::NoOpenmpRoutinesT<TypeTy, IdTy, ExprTy>;
290using NoParallelism = tomp::clause::NoParallelismT<TypeTy, IdTy, ExprTy>;
291using Notinbranch = tomp::clause::NotinbranchT<TypeTy, IdTy, ExprTy>;
292using Novariants = tomp::clause::NovariantsT<TypeTy, IdTy, ExprTy>;
293using Nowait = tomp::clause::NowaitT<TypeTy, IdTy, ExprTy>;
294using NumTasks = tomp::clause::NumTasksT<TypeTy, IdTy, ExprTy>;
295using NumTeams = tomp::clause::NumTeamsT<TypeTy, IdTy, ExprTy>;
296using NumThreads = tomp::clause::NumThreadsT<TypeTy, IdTy, ExprTy>;
297using OmpxAttribute = tomp::clause::OmpxAttributeT<TypeTy, IdTy, ExprTy>;
298using OmpxBare = tomp::clause::OmpxBareT<TypeTy, IdTy, ExprTy>;
299using OmpxDynCgroupMem = tomp::clause::OmpxDynCgroupMemT<TypeTy, IdTy, ExprTy>;
300using Order = tomp::clause::OrderT<TypeTy, IdTy, ExprTy>;
301using Ordered = tomp::clause::OrderedT<TypeTy, IdTy, ExprTy>;
302using Otherwise = tomp::clause::OtherwiseT<TypeTy, IdTy, ExprTy>;
303using Partial = tomp::clause::PartialT<TypeTy, IdTy, ExprTy>;
304using Permutation = tomp::clause::PermutationT<TypeTy, IdTy, ExprTy>;
305using Priority = tomp::clause::PriorityT<TypeTy, IdTy, ExprTy>;
306using Private = tomp::clause::PrivateT<TypeTy, IdTy, ExprTy>;
307using ProcBind = tomp::clause::ProcBindT<TypeTy, IdTy, ExprTy>;
308using Read = tomp::clause::ReadT<TypeTy, IdTy, ExprTy>;
309using Reduction = tomp::clause::ReductionT<TypeTy, IdTy, ExprTy>;
310using ReductionKind = tomp::clause::ReductionKindT<TypeTy, IdTy, ExprTy>;
311using Relaxed = tomp::clause::RelaxedT<TypeTy, IdTy, ExprTy>;
312using Release = tomp::clause::ReleaseT<TypeTy, IdTy, ExprTy>;
313using Replayable = tomp::clause::ReplayableT<TypeTy, IdTy, ExprTy>;
314using ReverseOffload = tomp::clause::ReverseOffloadT<TypeTy, IdTy, ExprTy>;
315using Safelen = tomp::clause::SafelenT<TypeTy, IdTy, ExprTy>;
316using Safesync = tomp::clause::SafesyncT<TypeTy, IdTy, ExprTy>;
317using Schedule = tomp::clause::ScheduleT<TypeTy, IdTy, ExprTy>;
318using SelfMaps = tomp::clause::SelfMapsT<TypeTy, IdTy, ExprTy>;
319using SeqCst = tomp::clause::SeqCstT<TypeTy, IdTy, ExprTy>;
320using Severity = tomp::clause::SeverityT<TypeTy, IdTy, ExprTy>;
321using Shared = tomp::clause::SharedT<TypeTy, IdTy, ExprTy>;
322using Simd = tomp::clause::SimdT<TypeTy, IdTy, ExprTy>;
323using Shift = tomp::clause::ShiftT<TypeTy, IdTy, ExprTy>;
324using Simdlen = tomp::clause::SimdlenT<TypeTy, IdTy, ExprTy>;
325using Sizes = tomp::clause::SizesT<TypeTy, IdTy, ExprTy>;
326using TaskReduction = tomp::clause::TaskReductionT<TypeTy, IdTy, ExprTy>;
327using ThreadLimit = tomp::clause::ThreadLimitT<TypeTy, IdTy, ExprTy>;
328using Threads = tomp::clause::ThreadsT<TypeTy, IdTy, ExprTy>;
329using Threadset = tomp::clause::ThreadsetT<TypeTy, IdTy, ExprTy>;
330using To = tomp::clause::ToT<TypeTy, IdTy, ExprTy>;
331using Transparent = tomp::clause::TransparentT<TypeTy, IdTy, ExprTy>;
332using UnifiedAddress = tomp::clause::UnifiedAddressT<TypeTy, IdTy, ExprTy>;
333using UnifiedSharedMemory =
334 tomp::clause::UnifiedSharedMemoryT<TypeTy, IdTy, ExprTy>;
335using Uniform = tomp::clause::UniformT<TypeTy, IdTy, ExprTy>;
336using Unknown = tomp::clause::UnknownT<TypeTy, IdTy, ExprTy>;
337using Untied = tomp::clause::UntiedT<TypeTy, IdTy, ExprTy>;
338using Update = tomp::clause::UpdateT<TypeTy, IdTy, ExprTy>;
339using UpdateDependObjects =
340 tomp::clause::UpdateDependObjectsT<TypeTy, IdTy, ExprTy>;
341using Use = tomp::clause::UseT<TypeTy, IdTy, ExprTy>;
342using UseDeviceAddr = tomp::clause::UseDeviceAddrT<TypeTy, IdTy, ExprTy>;
343using UseDevicePtr = tomp::clause::UseDevicePtrT<TypeTy, IdTy, ExprTy>;
344using UsesAllocators = tomp::clause::UsesAllocatorsT<TypeTy, IdTy, ExprTy>;
345using Weak = tomp::clause::WeakT<TypeTy, IdTy, ExprTy>;
346using When = tomp::clause::WhenT<TypeTy, IdTy, ExprTy>;
347using Write = tomp::clause::WriteT<TypeTy, IdTy, ExprTy>;
348
349DefinedOperator makeDefinedOperator(const parser::DefinedOperator &inp,
350 semantics::SemanticsContext &semaCtx);
351
352ProcedureDesignator
353makeProcedureDesignator(const parser::ProcedureDesignator &inp,
354 semantics::SemanticsContext &semaCtx);
355
356ReductionOperator
357makeReductionOperator(const parser::OmpReductionIdentifier &inp,
358 semantics::SemanticsContext &semaCtx);
359} // namespace clause
360
361using tomp::type::operator==;
362
364 using WrapperTrait = std::true_type;
365 llvm::omp::CancellationConstructType v;
366};
367struct Depobj {
368 using EmptyTrait = std::true_type;
369};
370struct Flush {
371 using EmptyTrait = std::true_type;
372};
374 using EmptyTrait = std::true_type;
375};
377 using EmptyTrait = std::true_type;
378};
380 using EmptyTrait = std::true_type;
381};
382
383using ClauseBase = tomp::ClauseT<TypeTy, IdTy, ExprTy,
384 // Extras...
387
388struct Clause : public ClauseBase {
389 Clause(ClauseBase &&base, const parser::CharBlock source = {})
390 : ClauseBase(std::move(base)), source(source) {}
391 // "source" will be ignored by tomp::type::operator==.
392 parser::CharBlock source;
393};
394
395template <typename Specific>
396Clause makeClause(llvm::omp::Clause id, Specific &&specific,
397 parser::CharBlock source = {}) {
398 return Clause(typename Clause::BaseT{id, specific}, source);
399}
400
401Clause makeClause(const parser::OmpClause &cls,
403
404List<Clause> makeClauses(const parser::OmpClauseList &clauses,
406
407bool transferLocations(const List<Clause> &from, List<Clause> &to);
408} // namespace Fortran::lower::omp
409
410#endif // FORTRAN_LOWER_OPENMP_CLAUSES_H
Definition char-block.h:27
Definition semantics.h:71
Definition symbol.h:916
Definition bit-population-count.h:20
Definition Clauses.h:388
Definition Clauses.h:367
Definition Clauses.h:370
Definition Clauses.h:379
Definition Clauses.h:37
Definition Clauses.h:373
Definition Clauses.h:376
Definition parse-tree.h:1901
Definition parse-tree.h:1436
Definition parse-tree.h:592
Definition parse-tree.h:5287
Definition parse-tree.h:5271
Definition parse-tree.h:3634
Definition parse-tree.h:1931