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{llvm::omp::Version::Max()};
83 llvm::omp::Version maxVer{0};
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{minVer, maxVer};
94llvm::directive::VersionRange GetVersionRangeForDirective(
95 llvm::omp::Directive dirId);
98const parser::Designator *GetDesignatorFromObj(
const parser::OmpObject &
object);
99const parser::DataRef *GetDataRefFromObj(
const parser::OmpObject &
object);
100const parser::OmpLocator *GetLocatorFromObj(
const parser::OmpObject &
object);
101const parser::Name *GetCommonBlockFromObj(
const parser::OmpObject &
object);
103const parser::ArrayElement *GetArrayElementFromObj(
104 const parser::OmpObject &
object);
105std::optional<parser::CharBlock> GetObjectSource(
106 const parser::OmpObject &
object);
107const parser::OmpObject *GetArgumentObject(
const parser::OmpArgument &argument);
109const OmpDirectiveSpecification &GetOmpDirectiveSpecification(
110 const OpenMPConstruct &x);
111const OmpDirectiveSpecification &GetOmpDirectiveSpecification(
112 const OpenMPDeclarativeConstruct &x);
114template <
typename T>
struct WithSource {
116 typename U = std::remove_reference_t<T>,
117 typename = std::enable_if_t<std::is_default_constructible_v<U>>>
118 WithSource() : value(), source() {}
119 WithSource(
const WithSource<T> &) =
default;
120 WithSource(WithSource<T> &&) =
default;
123 WithSource &operator=(
const WithSource<T> &) =
default;
124 WithSource &operator=(WithSource<T> &&) =
default;
126 using value_type = T;
134 llvm::omp::Directive
id = llvm::omp::Directive::OMPD_unknown) {
136 name.source = source;
146 if (
auto &spec{std::get<std::optional<OmpDirectiveSpecification>>(x.t)}) {
147 return spec->DirName();
149 return MakeName({}, llvm::omp::Directive::OMPD_section);
158 template <
typename T>
160 if constexpr (WrapperTrait<T>) {
161 return GetOmpDirectiveName(x.v);
162 }
else if constexpr (TupleTrait<T>) {
163 if constexpr (std::is_base_of_v<OmpBlockConstruct, T>) {
164 return std::get<OmpBeginDirective>(x.t).DirName();
167 x.t, std::make_index_sequence<std::tuple_size_v<
decltype(x.t)>>{});
169 }
else if constexpr (UnionTrait<T>) {
170 return common::visit(
171 [](
auto &&s) {
return GetOmpDirectiveName(s); }, x.u);
177 template <
typename... Ts,
size_t... Is>
179 const std::tuple<Ts...> &t, std::index_sequence<Is...>) {
182 if (name.v == llvm::omp::Directive::OMPD_unknown) {
186 n.v == llvm::omp::Directive::OMPD_unknown &&
"Conflicting names");
189 (accumulate(GetOmpDirectiveName(std::get<Is>(t))), ...);
193 template <
typename T>
195 return GetOmpDirectiveName(x.value());
201 return detail::DirectiveNameScope::GetOmpDirectiveName(x);
204std::string GetUpperName(
205 llvm::omp::Clause
id, llvm::omp::Version version,
bool annotate =
true);
206std::string GetUpperName(
207 llvm::omp::Directive
id, llvm::omp::Version version,
bool annotate =
true);
217 template <
typename T>
static const OmpObjectList *Get(
const T &x) {
218 if constexpr (std::is_same_v<OmpObjectList, T>) {
220 }
else if constexpr (WrapperTrait<T>) {
222 }
else if constexpr (UnionTrait<T>) {
223 return std::visit([](
auto &&s) {
return Get(s); }, x.u);
224 }
else if constexpr (TupleTrait<T>) {
226 x.t, std::make_index_sequence<std::tuple_size_v<
decltype(x.t)>>{});
227 }
else if constexpr (ConstraintTrait<T>) {
234 template <
typename T>
236 return Get(x.value());
239 template <
typename... Ts,
size_t... Is>
241 const std::tuple<Ts...> &t, std::index_sequence<Is...>) {
243 ((objects = objects ? objects : Get(std::get<Is>(t))), ...);
249template <
typename T>
const OmpObjectList *GetOmpObjectList(
const T &clause) {
250 static_assert(std::is_class_v<T>,
"Unexpected argument type");
251 return detail::OmpObjectListScope::Get(clause);
256 for (
const OmpArgument &arg : spec.Arguments().v) {
257 if (
auto *t{std::get_if<T>(&arg.u)}) {
264const OmpClause *FindClause(
265 const OmpDirectiveSpecification &spec, llvm::omp::Clause clauseId);
267const BlockConstruct *GetFortranBlockConstruct(
268 const ExecutionPartConstruct &epc);
269const Block &GetInnermostExecPart(
const Block &block);
270bool IsStrictlyStructuredBlock(
const Block &block);
272const OmpCombinerExpression *GetCombinerExpr(
const OmpReductionSpecifier &x);
273const OmpCombinerExpression *GetCombinerExpr(
const OmpClause &x);
274const OmpInitializerExpression *GetInitializerExpr(
const OmpClause &x);
277 std::vector<const OmpAllocateDirective *> dirs;
285 static constexpr bool value{
false};
287template <
typename ClauseTy>
289 static constexpr bool value{
true};
292template <
typename ClauseTy>
293static constexpr bool HasModifier = detail::HasModifierImpl<ClauseTy>::value;
295template <
typename R,
typename =
void,
typename =
void>
struct is_range {
296 static constexpr bool value{
false};
301 std::void_t<decltype(std::declval<R>().begin())>,
302 std::void_t<decltype(std::declval<R>().end())>> {
303 static constexpr bool value{
true};
306template <
typename R>
constexpr bool is_range_v = is_range<R>::value;
336struct ExecutionPartIterator {
343 using IteratorType = Block::const_iterator;
344 using IteratorRange = llvm::iterator_range<IteratorType>;
348 struct IteratorGauge :
public IteratorRange {
349 IteratorGauge(IteratorType b, IteratorType e)
350 : IteratorRange(b, e), at(b) {}
351 IteratorGauge(IteratorRange r) : IteratorRange(r), at(r.begin()) {}
353 bool atEnd()
const {
return at == end(); }
359 : location(b, e), owner(c) {}
360 template <
typename R>
362 : location(r), owner(c) {}
363 Construct(
const Construct &c) =
default;
371 ExecutionPartIterator() =
default;
373 ExecutionPartIterator(IteratorType b, IteratorType e, Step s = Step::Default,
376 stack_.emplace_back(b, e, c);
379 template <
typename R,
typename = std::enable_if_t<is_range_v<R>>>
394 bool valid()
const {
return !stack_.empty(); }
396 const std::vector<Construct> &stack()
const {
return stack_; }
397 decltype(
auto)
operator*()
const {
return *at(); }
398 bool operator==(
const ExecutionPartIterator &other)
const {
399 if (valid() != other.valid()) {
404 stack_.back().location.at == other.stack_.back().location.at;
406 bool operator!=(
const ExecutionPartIterator &other)
const {
407 return !(*
this == other);
410 ExecutionPartIterator &operator++() {
411 if (stepping_ == Step::Into) {
414 assert(stepping_ == Step::Over &&
"Unexpected stepping");
420 ExecutionPartIterator operator++(
int) {
421 ExecutionPartIterator copy{*
this};
426 using difference_type = IteratorType::difference_type;
427 using value_type = IteratorType::value_type;
428 using reference = IteratorType::reference;
429 using pointer = IteratorType::pointer;
430 using iterator_category = std::forward_iterator_tag;
433 IteratorType at()
const {
return stack_.back().location.at; };
439 const Step stepping_ = Step::Default;
440 std::vector<Construct> stack_;
443template <
typename Iterator = ExecutionPartIterator>
struct ExecutionPartRange {
444 using Step =
typename Iterator::Step;
446 ExecutionPartRange(Block::const_iterator begin, Block::const_iterator end,
447 Step stepping = Step::Default,
449 : begin_(begin, end, stepping, owner), end_() {}
450 template <
typename R,
typename = std::enable_if_t<is_range_v<R>>>
451 ExecutionPartRange(
const R &range, Step stepping = Step::Default,
453 : ExecutionPartRange(range.begin(), range.end(), stepping, owner) {}
455 Iterator begin()
const {
return begin_; }
456 Iterator end()
const {
return end_; }
459 Iterator begin_, end_;
462struct LoopNestIterator :
public ExecutionPartIterator {
463 LoopNestIterator() =
default;
465 LoopNestIterator(IteratorType b, IteratorType e, Step s = Step::Default,
467 : ExecutionPartIterator(b, e, s, c) {
470 template <
typename R,
typename = std::enable_if_t<is_range_v<R>>>
471 LoopNestIterator(
const R &range, Step stepping = Step::Default,
473 : LoopNestIterator(range.begin(), range.end(), stepping, construct) {}
475 LoopNestIterator &operator++() {
476 ExecutionPartIterator::operator++();
481 LoopNestIterator operator++(
int) {
482 LoopNestIterator copy{*
this};
491 while (valid() && !isLoop(**
this)) {
492 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:5530
Definition parse-tree.h:5394
Definition parse-tree.h:3591
Definition parse-tree.h:5295
Definition parse-tree.h:3646
Definition parse-tree.h:5408
Definition parse-tree.h:5682
Definition parse-tree.h:5534
Definition parse-tree.h:5668
Definition parse-tree.h:3757
Definition openmp-utils.h:348
Definition openmp-utils.h:336
Definition openmp-utils.h:443
Definition openmp-utils.h:276
Definition openmp-utils.h:132
Definition openmp-utils.h:284
Definition openmp-utils.h:216
Definition openmp-utils.h:295