File: Clauses.h

package info (click to toggle)
llvm-toolchain-20 1%3A20.1.8-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 2,111,696 kB
  • sloc: cpp: 7,438,781; ansic: 1,393,871; asm: 1,012,926; python: 241,771; f90: 86,635; objc: 75,411; lisp: 42,144; pascal: 17,286; sh: 8,596; ml: 5,082; perl: 4,730; makefile: 3,591; awk: 3,523; javascript: 2,251; xml: 892; fortran: 672
file content (343 lines) | stat: -rw-r--r-- 14,588 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
//===-- Clauses.h -- OpenMP clause handling -------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef FORTRAN_LOWER_OPENMP_CLAUSES_H
#define FORTRAN_LOWER_OPENMP_CLAUSES_H

#include "flang/Evaluate/expression.h"
#include "flang/Evaluate/type.h"
#include "flang/Parser/parse-tree.h"
#include "flang/Semantics/expression.h"
#include "flang/Semantics/semantics.h"
#include "flang/Semantics/symbol.h"

#include "llvm/ADT/STLExtras.h"
#include "llvm/Frontend/OpenMP/ClauseT.h"

#include <optional>
#include <type_traits>
#include <utility>

namespace Fortran::semantics {
class Symbol;
}

namespace Fortran::lower::omp {
using namespace Fortran;
using SomeExpr = semantics::SomeExpr;
using MaybeExpr = semantics::MaybeExpr;
using TypeTy = evaluate::DynamicType;

template <typename ExprTy>
struct IdTyTemplate {
  // "symbol" is always non-null for id's of actual objects.
  Fortran::semantics::Symbol *symbol;
  std::optional<ExprTy> designator;

  bool operator==(const IdTyTemplate &other) const {
    // If symbols are different, then the objects are different.
    if (symbol != other.symbol)
      return false;
    if (symbol == nullptr)
      return true;
    // Equal symbols don't necessarily indicate identical objects,
    // for example, a derived object component may use a single symbol,
    // which will refer to different objects for different designators,
    // e.g. a%c and b%c.
    return designator == other.designator;
  }

  // Defining an "ordering" which allows types derived from this to be
  // utilised in maps and other containers that require comparison
  // operators for ordering
  bool operator<(const IdTyTemplate &other) const {
    return symbol < other.symbol;
  }

  operator bool() const { return symbol != nullptr; }
};

using ExprTy = SomeExpr;

template <typename T>
using List = tomp::ListT<T>;
} // namespace Fortran::lower::omp

// Specialization of the ObjectT template
namespace tomp::type {
template <>
struct ObjectT<Fortran::lower::omp::IdTyTemplate<Fortran::lower::omp::ExprTy>,
               Fortran::lower::omp::ExprTy> {
  using IdTy = Fortran::lower::omp::IdTyTemplate<Fortran::lower::omp::ExprTy>;
  using ExprTy = Fortran::lower::omp::ExprTy;

  IdTy id() const { return identity; }
  Fortran::semantics::Symbol *sym() const { return identity.symbol; }
  const std::optional<ExprTy> &ref() const { return identity.designator; }

  bool operator<(const ObjectT<IdTy, ExprTy> &other) const {
    return identity < other.identity;
  }

  IdTy identity;
};
} // namespace tomp::type

namespace Fortran::lower::omp {
using IdTy = IdTyTemplate<ExprTy>;
}

namespace std {
template <>
struct hash<Fortran::lower::omp::IdTy> {
  size_t operator()(const Fortran::lower::omp::IdTy &id) const {
    return static_cast<size_t>(reinterpret_cast<uintptr_t>(id.symbol));
  }
};
} // namespace std

namespace Fortran::lower::omp {
using Object = tomp::ObjectT<IdTy, ExprTy>;
using ObjectList = tomp::ObjectListT<IdTy, ExprTy>;

Object makeObject(const parser::OmpObject &object,
                  semantics::SemanticsContext &semaCtx);
Object makeObject(const parser::Name &name,
                  semantics::SemanticsContext &semaCtx);
Object makeObject(const parser::Designator &dsg,
                  semantics::SemanticsContext &semaCtx);
Object makeObject(const parser::StructureComponent &comp,
                  semantics::SemanticsContext &semaCtx);

inline auto makeObjectFn(semantics::SemanticsContext &semaCtx) {
  return [&](auto &&s) { return makeObject(s, semaCtx); };
}

template <typename T>
SomeExpr makeExpr(T &&pftExpr, semantics::SemanticsContext &semaCtx) {
  auto maybeExpr = evaluate::ExpressionAnalyzer(semaCtx).Analyze(pftExpr);
  assert(maybeExpr);
  return std::move(*maybeExpr);
}

inline auto makeExprFn(semantics::SemanticsContext &semaCtx) {
  return [&](auto &&s) { return makeExpr(s, semaCtx); };
}

template <
    typename ContainerTy, typename FunctionTy,
    typename ElemTy = typename llvm::remove_cvref_t<ContainerTy>::value_type,
    typename ResultTy = std::invoke_result_t<FunctionTy, ElemTy>>
List<ResultTy> makeList(ContainerTy &&container, FunctionTy &&func) {
  List<ResultTy> v;
  llvm::transform(container, std::back_inserter(v), func);
  return v;
}

inline ObjectList makeObjects(const parser::OmpObjectList &objects,
                              semantics::SemanticsContext &semaCtx) {
  return makeList(objects.v, makeObjectFn(semaCtx));
}

template <typename FuncTy, //
          typename ArgTy,  //
          typename ResultTy = std::invoke_result_t<FuncTy, ArgTy>>
std::optional<ResultTy> maybeApply(FuncTy &&func,
                                   const std::optional<ArgTy> &arg) {
  if (!arg)
    return std::nullopt;
  return func(*arg);
}

template <           //
    typename FuncTy, //
    typename ArgTy,  //
    typename ResultTy =
        std::invoke_result_t<FuncTy, decltype(std::declval<ArgTy>().v)>>
std::optional<ResultTy> maybeApplyToV(FuncTy &&func, const ArgTy *arg) {
  if (!arg)
    return std::nullopt;
  return func(arg->v);
}

std::optional<Object> getBaseObject(const Object &object,
                                    semantics::SemanticsContext &semaCtx);

namespace clause {
using Range = tomp::type::RangeT<ExprTy>;
using Mapper = tomp::type::MapperT<IdTy, ExprTy>;
using Iterator = tomp::type::IteratorT<TypeTy, IdTy, ExprTy>;
using IteratorSpecifier = tomp::type::IteratorSpecifierT<TypeTy, IdTy, ExprTy>;
using DefinedOperator = tomp::type::DefinedOperatorT<IdTy, ExprTy>;
using ProcedureDesignator = tomp::type::ProcedureDesignatorT<IdTy, ExprTy>;
using ReductionOperator = tomp::type::ReductionIdentifierT<IdTy, ExprTy>;
using DependenceType = tomp::type::DependenceType;
using Prescriptiveness = tomp::type::Prescriptiveness;

// "Requires" clauses are handled early on, and the aggregated information
// is stored in the Symbol details of modules, programs, and subprograms.
// These clauses are still handled here to cover all alternatives in the
// main clause variant.

using Absent = tomp::clause::AbsentT<TypeTy, IdTy, ExprTy>;
using AcqRel = tomp::clause::AcqRelT<TypeTy, IdTy, ExprTy>;
using Acquire = tomp::clause::AcquireT<TypeTy, IdTy, ExprTy>;
using AdjustArgs = tomp::clause::AdjustArgsT<TypeTy, IdTy, ExprTy>;
using Affinity = tomp::clause::AffinityT<TypeTy, IdTy, ExprTy>;
using Aligned = tomp::clause::AlignedT<TypeTy, IdTy, ExprTy>;
using Align = tomp::clause::AlignT<TypeTy, IdTy, ExprTy>;
using Allocate = tomp::clause::AllocateT<TypeTy, IdTy, ExprTy>;
using Allocator = tomp::clause::AllocatorT<TypeTy, IdTy, ExprTy>;
using AppendArgs = tomp::clause::AppendArgsT<TypeTy, IdTy, ExprTy>;
using AtomicDefaultMemOrder =
    tomp::clause::AtomicDefaultMemOrderT<TypeTy, IdTy, ExprTy>;
using At = tomp::clause::AtT<TypeTy, IdTy, ExprTy>;
using Bind = tomp::clause::BindT<TypeTy, IdTy, ExprTy>;
using Capture = tomp::clause::CaptureT<TypeTy, IdTy, ExprTy>;
using Collapse = tomp::clause::CollapseT<TypeTy, IdTy, ExprTy>;
using Compare = tomp::clause::CompareT<TypeTy, IdTy, ExprTy>;
using Contains = tomp::clause::ContainsT<TypeTy, IdTy, ExprTy>;
using Copyin = tomp::clause::CopyinT<TypeTy, IdTy, ExprTy>;
using Copyprivate = tomp::clause::CopyprivateT<TypeTy, IdTy, ExprTy>;
using Defaultmap = tomp::clause::DefaultmapT<TypeTy, IdTy, ExprTy>;
using Default = tomp::clause::DefaultT<TypeTy, IdTy, ExprTy>;
using Depend = tomp::clause::DependT<TypeTy, IdTy, ExprTy>;
using Destroy = tomp::clause::DestroyT<TypeTy, IdTy, ExprTy>;
using Detach = tomp::clause::DetachT<TypeTy, IdTy, ExprTy>;
using Device = tomp::clause::DeviceT<TypeTy, IdTy, ExprTy>;
using DeviceType = tomp::clause::DeviceTypeT<TypeTy, IdTy, ExprTy>;
using DistSchedule = tomp::clause::DistScheduleT<TypeTy, IdTy, ExprTy>;
using Doacross = tomp::clause::DoacrossT<TypeTy, IdTy, ExprTy>;
using DynamicAllocators =
    tomp::clause::DynamicAllocatorsT<TypeTy, IdTy, ExprTy>;
using Enter = tomp::clause::EnterT<TypeTy, IdTy, ExprTy>;
using Exclusive = tomp::clause::ExclusiveT<TypeTy, IdTy, ExprTy>;
using Fail = tomp::clause::FailT<TypeTy, IdTy, ExprTy>;
using Filter = tomp::clause::FilterT<TypeTy, IdTy, ExprTy>;
using Final = tomp::clause::FinalT<TypeTy, IdTy, ExprTy>;
using Firstprivate = tomp::clause::FirstprivateT<TypeTy, IdTy, ExprTy>;
using From = tomp::clause::FromT<TypeTy, IdTy, ExprTy>;
using Full = tomp::clause::FullT<TypeTy, IdTy, ExprTy>;
using Grainsize = tomp::clause::GrainsizeT<TypeTy, IdTy, ExprTy>;
using HasDeviceAddr = tomp::clause::HasDeviceAddrT<TypeTy, IdTy, ExprTy>;
using Hint = tomp::clause::HintT<TypeTy, IdTy, ExprTy>;
using Holds = tomp::clause::HoldsT<TypeTy, IdTy, ExprTy>;
using If = tomp::clause::IfT<TypeTy, IdTy, ExprTy>;
using Inbranch = tomp::clause::InbranchT<TypeTy, IdTy, ExprTy>;
using Inclusive = tomp::clause::InclusiveT<TypeTy, IdTy, ExprTy>;
using Indirect = tomp::clause::IndirectT<TypeTy, IdTy, ExprTy>;
using Init = tomp::clause::InitT<TypeTy, IdTy, ExprTy>;
using InReduction = tomp::clause::InReductionT<TypeTy, IdTy, ExprTy>;
using IsDevicePtr = tomp::clause::IsDevicePtrT<TypeTy, IdTy, ExprTy>;
using Lastprivate = tomp::clause::LastprivateT<TypeTy, IdTy, ExprTy>;
using Linear = tomp::clause::LinearT<TypeTy, IdTy, ExprTy>;
using Link = tomp::clause::LinkT<TypeTy, IdTy, ExprTy>;
using Map = tomp::clause::MapT<TypeTy, IdTy, ExprTy>;
using Match = tomp::clause::MatchT<TypeTy, IdTy, ExprTy>;
using Mergeable = tomp::clause::MergeableT<TypeTy, IdTy, ExprTy>;
using Message = tomp::clause::MessageT<TypeTy, IdTy, ExprTy>;
using NoOpenmp = tomp::clause::NoOpenmpT<TypeTy, IdTy, ExprTy>;
using NoOpenmpRoutines = tomp::clause::NoOpenmpRoutinesT<TypeTy, IdTy, ExprTy>;
using NoParallelism = tomp::clause::NoParallelismT<TypeTy, IdTy, ExprTy>;
using Nocontext = tomp::clause::NocontextT<TypeTy, IdTy, ExprTy>;
using Nogroup = tomp::clause::NogroupT<TypeTy, IdTy, ExprTy>;
using Nontemporal = tomp::clause::NontemporalT<TypeTy, IdTy, ExprTy>;
using Notinbranch = tomp::clause::NotinbranchT<TypeTy, IdTy, ExprTy>;
using Novariants = tomp::clause::NovariantsT<TypeTy, IdTy, ExprTy>;
using Nowait = tomp::clause::NowaitT<TypeTy, IdTy, ExprTy>;
using NumTasks = tomp::clause::NumTasksT<TypeTy, IdTy, ExprTy>;
using NumTeams = tomp::clause::NumTeamsT<TypeTy, IdTy, ExprTy>;
using NumThreads = tomp::clause::NumThreadsT<TypeTy, IdTy, ExprTy>;
using OmpxAttribute = tomp::clause::OmpxAttributeT<TypeTy, IdTy, ExprTy>;
using OmpxBare = tomp::clause::OmpxBareT<TypeTy, IdTy, ExprTy>;
using OmpxDynCgroupMem = tomp::clause::OmpxDynCgroupMemT<TypeTy, IdTy, ExprTy>;
using Ordered = tomp::clause::OrderedT<TypeTy, IdTy, ExprTy>;
using Order = tomp::clause::OrderT<TypeTy, IdTy, ExprTy>;
using Partial = tomp::clause::PartialT<TypeTy, IdTy, ExprTy>;
using Priority = tomp::clause::PriorityT<TypeTy, IdTy, ExprTy>;
using Private = tomp::clause::PrivateT<TypeTy, IdTy, ExprTy>;
using ProcBind = tomp::clause::ProcBindT<TypeTy, IdTy, ExprTy>;
using Read = tomp::clause::ReadT<TypeTy, IdTy, ExprTy>;
using Reduction = tomp::clause::ReductionT<TypeTy, IdTy, ExprTy>;
using Relaxed = tomp::clause::RelaxedT<TypeTy, IdTy, ExprTy>;
using Release = tomp::clause::ReleaseT<TypeTy, IdTy, ExprTy>;
using ReverseOffload = tomp::clause::ReverseOffloadT<TypeTy, IdTy, ExprTy>;
using Safelen = tomp::clause::SafelenT<TypeTy, IdTy, ExprTy>;
using Schedule = tomp::clause::ScheduleT<TypeTy, IdTy, ExprTy>;
using SeqCst = tomp::clause::SeqCstT<TypeTy, IdTy, ExprTy>;
using Severity = tomp::clause::SeverityT<TypeTy, IdTy, ExprTy>;
using Shared = tomp::clause::SharedT<TypeTy, IdTy, ExprTy>;
using Simdlen = tomp::clause::SimdlenT<TypeTy, IdTy, ExprTy>;
using Simd = tomp::clause::SimdT<TypeTy, IdTy, ExprTy>;
using Sizes = tomp::clause::SizesT<TypeTy, IdTy, ExprTy>;
using Permutation = tomp::clause::PermutationT<TypeTy, IdTy, ExprTy>;
using TaskReduction = tomp::clause::TaskReductionT<TypeTy, IdTy, ExprTy>;
using ThreadLimit = tomp::clause::ThreadLimitT<TypeTy, IdTy, ExprTy>;
using Threads = tomp::clause::ThreadsT<TypeTy, IdTy, ExprTy>;
using To = tomp::clause::ToT<TypeTy, IdTy, ExprTy>;
using UnifiedAddress = tomp::clause::UnifiedAddressT<TypeTy, IdTy, ExprTy>;
using UnifiedSharedMemory =
    tomp::clause::UnifiedSharedMemoryT<TypeTy, IdTy, ExprTy>;
using Uniform = tomp::clause::UniformT<TypeTy, IdTy, ExprTy>;
using Unknown = tomp::clause::UnknownT<TypeTy, IdTy, ExprTy>;
using Untied = tomp::clause::UntiedT<TypeTy, IdTy, ExprTy>;
using Update = tomp::clause::UpdateT<TypeTy, IdTy, ExprTy>;
using UseDeviceAddr = tomp::clause::UseDeviceAddrT<TypeTy, IdTy, ExprTy>;
using UseDevicePtr = tomp::clause::UseDevicePtrT<TypeTy, IdTy, ExprTy>;
using UsesAllocators = tomp::clause::UsesAllocatorsT<TypeTy, IdTy, ExprTy>;
using Use = tomp::clause::UseT<TypeTy, IdTy, ExprTy>;
using Weak = tomp::clause::WeakT<TypeTy, IdTy, ExprTy>;
using When = tomp::clause::WhenT<TypeTy, IdTy, ExprTy>;
using Write = tomp::clause::WriteT<TypeTy, IdTy, ExprTy>;
} // namespace clause

using tomp::type::operator==;

struct CancellationConstructType {
  using EmptyTrait = std::true_type;
};
struct Depobj {
  using EmptyTrait = std::true_type;
};
struct Flush {
  using EmptyTrait = std::true_type;
};
struct MemoryOrder {
  using EmptyTrait = std::true_type;
};
struct Threadprivate {
  using EmptyTrait = std::true_type;
};

using ClauseBase = tomp::ClauseT<TypeTy, IdTy, ExprTy,
                                 // Extras...
                                 CancellationConstructType, Depobj, Flush,
                                 MemoryOrder, Threadprivate>;

struct Clause : public ClauseBase {
  Clause(ClauseBase &&base, const parser::CharBlock source = {})
      : ClauseBase(std::move(base)), source(source) {}
  // "source" will be ignored by tomp::type::operator==.
  parser::CharBlock source;
};

template <typename Specific>
Clause makeClause(llvm::omp::Clause id, Specific &&specific,
                  parser::CharBlock source = {}) {
  return Clause(typename Clause::BaseT{id, specific}, source);
}

Clause makeClause(const parser::OmpClause &cls,
                  semantics::SemanticsContext &semaCtx);

List<Clause> makeClauses(const parser::OmpClauseList &clauses,
                         semantics::SemanticsContext &semaCtx);

bool transferLocations(const List<Clause> &from, List<Clause> &to);
} // namespace Fortran::lower::omp

#endif // FORTRAN_LOWER_OPENMP_CLAUSES_H