13#ifndef FORTRAN_PARSER_OPENMP_UTILS_H
14#define FORTRAN_PARSER_OPENMP_UTILS_H
16#include "flang/Common/indirection.h"
17#include "flang/Parser/char-block.h"
18#include "flang/Parser/parse-tree.h"
19#include "llvm/ADT/iterator_range.h"
20#include "llvm/Frontend/OpenMP/OMP.h"
21#include "llvm/Frontend/OpenMP/OMPDescriptors.h"
32namespace Fortran::parser::omp {
34template <
typename T>
constexpr auto addr_if(std::optional<T> &x) {
35 return x ? &*x :
nullptr;
37template <
typename T>
constexpr auto addr_if(
const std::optional<T> &x) {
38 return x ? &*x :
nullptr;
53llvm::omp::Modifiers GetElements(
54 const llvm::omp::descriptor::Clause &desc, llvm::omp::Version version);
55llvm::omp::ModifierSets GetSets(
56 const llvm::omp::descriptor::Clause &desc, llvm::omp::Version version);
57llvm::omp::Clauses GetElements(
58 const llvm::omp::descriptor::Directive &desc, llvm::omp::Version version);
59llvm::omp::ClauseSets GetSets(
60 const llvm::omp::descriptor::Directive &desc, llvm::omp::Version version);
61llvm::omp::Clauses GetElements(
62 const llvm::omp::descriptor::ClauseSet &desc, llvm::omp::Version version);
63llvm::omp::Modifiers GetElements(
64 const llvm::omp::descriptor::ModifierSet &desc, llvm::omp::Version version);
70template <
typename DescriptorTy>
71auto GetAllowedElements(
const DescriptorTy &desc, llvm::omp::Version version) {
72 auto allowed{GetElements(desc, version)};
73 for (
auto s : GetSets(desc, version)) {
74 allowed |= GetElements(llvm::omp::getDescriptor(s), version);
79template <
typename ElemTy,
typename OwnerTy>
80llvm::directive::VersionRange GetVersionRangeForElement(
81 ElemTy elemId, OwnerTy ownerId) {
82 llvm::omp::Version minVer{std::numeric_limits<int>::max()};
83 llvm::omp::Version maxVer{0u};
84 const auto &desc{llvm::omp::getDescriptor(ownerId)};
85 for (llvm::omp::Version v : desc.getVersions()) {
86 if (GetAllowedElements(desc, v).test(elemId)) {
87 minVer = std::min(minVer, v);
88 maxVer = std::max(maxVer, v);
91 return llvm::directive::VersionRange{
92 static_cast<int>(
static_cast<unsigned>(minVer)),
93 static_cast<int>(
static_cast<unsigned>(maxVer))};
97const parser::Designator *GetDesignatorFromObj(
const parser::OmpObject &
object);
98const parser::DataRef *GetDataRefFromObj(
const parser::OmpObject &
object);
99const parser::OmpLocator *GetLocatorFromObj(
const parser::OmpObject &
object);
100const parser::Name *GetCommonBlockFromObj(
const parser::OmpObject &
object);
102const parser::ArrayElement *GetArrayElementFromObj(
103 const parser::OmpObject &
object);
104std::optional<parser::CharBlock> GetObjectSource(
105 const parser::OmpObject &
object);
106const parser::OmpObject *GetArgumentObject(
const parser::OmpArgument &argument);
108const OmpDirectiveSpecification &GetOmpDirectiveSpecification(
109 const OpenMPConstruct &x);
110const OmpDirectiveSpecification &GetOmpDirectiveSpecification(
111 const OpenMPDeclarativeConstruct &x);
113template <
typename T>
struct WithSource {
115 typename U = std::remove_reference_t<T>,
116 typename = std::enable_if_t<std::is_default_constructible_v<U>>>
117 WithSource() : value(), source() {}
118 WithSource(
const WithSource<T> &) =
default;
119 WithSource(WithSource<T> &&) =
default;
122 WithSource &operator=(
const WithSource<T> &) =
default;
123 WithSource &operator=(WithSource<T> &&) =
default;
125 using value_type = T;
133 llvm::omp::Directive
id = llvm::omp::Directive::OMPD_unknown) {
135 name.source = source;
145 if (
auto &spec{std::get<std::optional<OmpDirectiveSpecification>>(x.t)}) {
146 return spec->DirName();
148 return MakeName({}, llvm::omp::Directive::OMPD_section);
157 template <
typename T>
159 if constexpr (WrapperTrait<T>) {
160 return GetOmpDirectiveName(x.v);
161 }
else if constexpr (TupleTrait<T>) {
162 if constexpr (std::is_base_of_v<OmpBlockConstruct, T>) {
163 return std::get<OmpBeginDirective>(x.t).DirName();
166 x.t, std::make_index_sequence<std::tuple_size_v<
decltype(x.t)>>{});
168 }
else if constexpr (UnionTrait<T>) {
169 return common::visit(
170 [](
auto &&s) {
return GetOmpDirectiveName(s); }, x.u);
176 template <
typename... Ts,
size_t... Is>
178 const std::tuple<Ts...> &t, std::index_sequence<Is...>) {
181 if (name.v == llvm::omp::Directive::OMPD_unknown) {
185 n.v == llvm::omp::Directive::OMPD_unknown &&
"Conflicting names");
188 (accumulate(GetOmpDirectiveName(std::get<Is>(t))), ...);
192 template <
typename T>
194 return GetOmpDirectiveName(x.value());
200 return detail::DirectiveNameScope::GetOmpDirectiveName(x);
203std::string GetUpperName(
204 llvm::omp::Clause
id, llvm::omp::Version version,
bool annotate =
true);
205std::string GetUpperName(
206 llvm::omp::Directive
id, llvm::omp::Version version,
bool annotate =
true);
216 template <
typename T>
static const OmpObjectList *Get(
const T &x) {
217 if constexpr (std::is_same_v<OmpObjectList, T>) {
219 }
else if constexpr (WrapperTrait<T>) {
221 }
else if constexpr (UnionTrait<T>) {
222 return std::visit([](
auto &&s) {
return Get(s); }, x.u);
223 }
else if constexpr (TupleTrait<T>) {
225 x.t, std::make_index_sequence<std::tuple_size_v<
decltype(x.t)>>{});
226 }
else if constexpr (ConstraintTrait<T>) {
233 template <
typename T>
235 return Get(x.value());
238 template <
typename... Ts,
size_t... Is>
240 const std::tuple<Ts...> &t, std::index_sequence<Is...>) {
242 ((objects = objects ? objects : Get(std::get<Is>(t))), ...);
248template <
typename T>
const OmpObjectList *GetOmpObjectList(
const T &clause) {
249 static_assert(std::is_class_v<T>,
"Unexpected argument type");
250 return detail::OmpObjectListScope::Get(clause);
255 for (
const OmpArgument &arg : spec.Arguments().v) {
256 if (
auto *t{std::get_if<T>(&arg.u)}) {
263const OmpClause *FindClause(
264 const OmpDirectiveSpecification &spec, llvm::omp::Clause clauseId);
266const BlockConstruct *GetFortranBlockConstruct(
267 const ExecutionPartConstruct &epc);
268const Block &GetInnermostExecPart(
const Block &block);
269bool IsStrictlyStructuredBlock(
const Block &block);
271const OmpCombinerExpression *GetCombinerExpr(
const OmpReductionSpecifier &x);
272const OmpCombinerExpression *GetCombinerExpr(
const OmpClause &x);
273const OmpInitializerExpression *GetInitializerExpr(
const OmpClause &x);
276 std::vector<const OmpAllocateDirective *> dirs;
284 static constexpr bool value{
false};
286template <
typename ClauseTy>
288 static constexpr bool value{
true};
291template <
typename ClauseTy>
292static constexpr bool HasModifier = detail::HasModifierImpl<ClauseTy>::value;
294template <
typename R,
typename =
void,
typename =
void>
struct is_range {
295 static constexpr bool value{
false};
300 std::void_t<decltype(std::declval<R>().begin())>,
301 std::void_t<decltype(std::declval<R>().end())>> {
302 static constexpr bool value{
true};
305template <
typename R>
constexpr bool is_range_v = is_range<R>::value;
335struct ExecutionPartIterator {
342 using IteratorType = Block::const_iterator;
343 using IteratorRange = llvm::iterator_range<IteratorType>;
347 struct IteratorGauge :
public IteratorRange {
348 IteratorGauge(IteratorType b, IteratorType e)
349 : IteratorRange(b, e), at(b) {}
350 IteratorGauge(IteratorRange r) : IteratorRange(r), at(r.begin()) {}
352 bool atEnd()
const {
return at == end(); }
358 : location(b, e), owner(c) {}
359 template <
typename R>
361 : location(r), owner(c) {}
362 Construct(
const Construct &c) =
default;
370 ExecutionPartIterator() =
default;
372 ExecutionPartIterator(IteratorType b, IteratorType e, Step s = Step::Default,
375 stack_.emplace_back(b, e, c);
378 template <
typename R,
typename = std::enable_if_t<is_range_v<R>>>
393 bool valid()
const {
return !stack_.empty(); }
395 const std::vector<Construct> &stack()
const {
return stack_; }
396 decltype(
auto)
operator*()
const {
return *at(); }
397 bool operator==(
const ExecutionPartIterator &other)
const {
398 if (valid() != other.valid()) {
403 stack_.back().location.at == other.stack_.back().location.at;
405 bool operator!=(
const ExecutionPartIterator &other)
const {
406 return !(*
this == other);
409 ExecutionPartIterator &operator++() {
410 if (stepping_ == Step::Into) {
413 assert(stepping_ == Step::Over &&
"Unexpected stepping");
419 ExecutionPartIterator operator++(
int) {
420 ExecutionPartIterator copy{*
this};
425 using difference_type = IteratorType::difference_type;
426 using value_type = IteratorType::value_type;
427 using reference = IteratorType::reference;
428 using pointer = IteratorType::pointer;
429 using iterator_category = std::forward_iterator_tag;
432 IteratorType at()
const {
return stack_.back().location.at; };
438 const Step stepping_ = Step::Default;
439 std::vector<Construct> stack_;
442template <
typename Iterator = ExecutionPartIterator>
struct ExecutionPartRange {
443 using Step =
typename Iterator::Step;
445 ExecutionPartRange(Block::const_iterator begin, Block::const_iterator end,
446 Step stepping = Step::Default,
448 : begin_(begin, end, stepping, owner), end_() {}
449 template <
typename R,
typename = std::enable_if_t<is_range_v<R>>>
450 ExecutionPartRange(
const R &range, Step stepping = Step::Default,
452 : ExecutionPartRange(range.begin(), range.end(), stepping, owner) {}
454 Iterator begin()
const {
return begin_; }
455 Iterator end()
const {
return end_; }
458 Iterator begin_, end_;
461struct LoopNestIterator :
public ExecutionPartIterator {
462 LoopNestIterator() =
default;
464 LoopNestIterator(IteratorType b, IteratorType e, Step s = Step::Default,
466 : ExecutionPartIterator(b, e, s, c) {
469 template <
typename R,
typename = std::enable_if_t<is_range_v<R>>>
470 LoopNestIterator(
const R &range, Step stepping = Step::Default,
472 : LoopNestIterator(range.begin(), range.end(), stepping, construct) {}
474 LoopNestIterator &operator++() {
475 ExecutionPartIterator::operator++();
480 LoopNestIterator operator++(
int) {
481 LoopNestIterator copy{*
this};
490 while (valid() && !isLoop(**
this)) {
491 ExecutionPartIterator::operator++();
Definition indirection.h:31
Definition char-block.h:27
Definition parse-tree.h:442
Definition parse-tree.h:2379
Definition parse-tree.h:559
Definition parse-tree.h:5529
Definition parse-tree.h:5393
Definition parse-tree.h:3591
Definition parse-tree.h:5294
Definition parse-tree.h:3646
Definition parse-tree.h:5407
Definition parse-tree.h:5681
Definition parse-tree.h:5533
Definition parse-tree.h:5667
Definition parse-tree.h:3757
Definition openmp-utils.h:347
Definition openmp-utils.h:335
Definition openmp-utils.h:442
Definition openmp-utils.h:275
Definition openmp-utils.h:131
Definition openmp-utils.h:283
Definition openmp-utils.h:215
Definition openmp-utils.h:294