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"
30namespace Fortran::parser::omp {
32template <
typename T>
constexpr auto addr_if(std::optional<T> &x) {
33 return x ? &*x :
nullptr;
35template <
typename T>
constexpr auto addr_if(
const std::optional<T> &x) {
36 return x ? &*x :
nullptr;
39const parser::Designator *GetDesignatorFromObj(
const parser::OmpObject &
object);
40const parser::DataRef *GetDataRefFromObj(
const parser::OmpObject &
object);
41const parser::OmpLocator *GetLocatorFromObj(
const parser::OmpObject &
object);
42const parser::Name *GetCommonBlockFromObj(
const parser::OmpObject &
object);
44const parser::ArrayElement *GetArrayElementFromObj(
45 const parser::OmpObject &
object);
46std::optional<parser::CharBlock> GetObjectSource(
47 const parser::OmpObject &
object);
48const parser::OmpObject *GetArgumentObject(
const parser::OmpArgument &argument);
50const OmpDirectiveSpecification &GetOmpDirectiveSpecification(
51 const OpenMPConstruct &x);
52const OmpDirectiveSpecification &GetOmpDirectiveSpecification(
53 const OpenMPDeclarativeConstruct &x);
55template <
typename T>
struct WithSource {
57 typename U = std::remove_reference_t<T>,
58 typename = std::enable_if_t<std::is_default_constructible_v<U>>>
59 WithSource() : value(), source() {}
60 WithSource(
const WithSource<T> &) =
default;
61 WithSource(WithSource<T> &&) =
default;
64 WithSource &operator=(
const WithSource<T> &) =
default;
65 WithSource &operator=(WithSource<T> &&) =
default;
75 llvm::omp::Directive
id = llvm::omp::Directive::OMPD_unknown) {
87 if (
auto &spec{std::get<std::optional<OmpDirectiveSpecification>>(x.t)}) {
88 return spec->DirName();
90 return MakeName({}, llvm::omp::Directive::OMPD_section);
101 if constexpr (WrapperTrait<T>) {
102 return GetOmpDirectiveName(x.v);
103 }
else if constexpr (TupleTrait<T>) {
104 if constexpr (std::is_base_of_v<OmpBlockConstruct, T>) {
105 return std::get<OmpBeginDirective>(x.t).DirName();
108 x.t, std::make_index_sequence<std::tuple_size_v<
decltype(x.t)>>{});
110 }
else if constexpr (UnionTrait<T>) {
111 return common::visit(
112 [](
auto &&s) {
return GetOmpDirectiveName(s); }, x.u);
118 template <
typename... Ts,
size_t... Is>
120 const std::tuple<Ts...> &t, std::index_sequence<Is...>) {
123 if (name.v == llvm::omp::Directive::OMPD_unknown) {
127 n.v == llvm::omp::Directive::OMPD_unknown &&
"Conflicting names");
130 (accumulate(GetOmpDirectiveName(std::get<Is>(t))), ...);
134 template <
typename T>
136 return GetOmpDirectiveName(x.value());
142 return detail::DirectiveNameScope::GetOmpDirectiveName(x);
145std::string GetUpperName(
146 llvm::omp::Clause
id, llvm::omp::Version version,
bool annotate =
true);
147std::string GetUpperName(
148 llvm::omp::Directive
id, llvm::omp::Version version,
bool annotate =
true);
158 template <
typename T>
static const OmpObjectList *Get(
const T &x) {
159 if constexpr (std::is_same_v<OmpObjectList, T>) {
161 }
else if constexpr (WrapperTrait<T>) {
163 }
else if constexpr (UnionTrait<T>) {
164 return std::visit([](
auto &&s) {
return Get(s); }, x.u);
165 }
else if constexpr (TupleTrait<T>) {
167 x.t, std::make_index_sequence<std::tuple_size_v<
decltype(x.t)>>{});
168 }
else if constexpr (ConstraintTrait<T>) {
175 template <
typename T>
177 return Get(x.value());
180 template <
typename... Ts,
size_t... Is>
182 const std::tuple<Ts...> &t, std::index_sequence<Is...>) {
184 ((objects = objects ? objects : Get(std::get<Is>(t))), ...);
190template <
typename T>
const OmpObjectList *GetOmpObjectList(
const T &clause) {
191 static_assert(std::is_class_v<T>,
"Unexpected argument type");
192 return detail::OmpObjectListScope::Get(clause);
197 for (
const OmpArgument &arg : spec.Arguments().v) {
198 if (
auto *t{std::get_if<T>(&arg.u)}) {
205const OmpClause *FindClause(
206 const OmpDirectiveSpecification &spec, llvm::omp::Clause clauseId);
208const BlockConstruct *GetFortranBlockConstruct(
209 const ExecutionPartConstruct &epc);
210const Block &GetInnermostExecPart(
const Block &block);
211bool IsStrictlyStructuredBlock(
const Block &block);
213const OmpCombinerExpression *GetCombinerExpr(
const OmpReductionSpecifier &x);
214const OmpCombinerExpression *GetCombinerExpr(
const OmpClause &x);
215const OmpInitializerExpression *GetInitializerExpr(
const OmpClause &x);
218 std::vector<const OmpAllocateDirective *> dirs;
226 static constexpr bool value{
false};
228template <
typename ClauseTy>
230 static constexpr bool value{
true};
233template <
typename ClauseTy>
234static constexpr bool HasModifier = detail::HasModifierImpl<ClauseTy>::value;
236template <
typename R,
typename =
void,
typename =
void>
struct is_range {
237 static constexpr bool value{
false};
242 std::void_t<decltype(std::declval<R>().begin())>,
243 std::void_t<decltype(std::declval<R>().end())>> {
244 static constexpr bool value{
true};
247template <
typename R>
constexpr bool is_range_v = is_range<R>::value;
277struct ExecutionPartIterator {
284 using IteratorType = Block::const_iterator;
285 using IteratorRange = llvm::iterator_range<IteratorType>;
289 struct IteratorGauge :
public IteratorRange {
290 IteratorGauge(IteratorType b, IteratorType e)
291 : IteratorRange(b, e), at(b) {}
292 IteratorGauge(IteratorRange r) : IteratorRange(r), at(r.begin()) {}
294 bool atEnd()
const {
return at == end(); }
300 : location(b, e), owner(c) {}
301 template <
typename R>
303 : location(r), owner(c) {}
304 Construct(
const Construct &c) =
default;
312 ExecutionPartIterator() =
default;
314 ExecutionPartIterator(IteratorType b, IteratorType e, Step s = Step::Default,
317 stack_.emplace_back(b, e, c);
320 template <
typename R,
typename = std::enable_if_t<is_range_v<R>>>
335 bool valid()
const {
return !stack_.empty(); }
337 const std::vector<Construct> &stack()
const {
return stack_; }
338 decltype(
auto)
operator*()
const {
return *at(); }
339 bool operator==(
const ExecutionPartIterator &other)
const {
340 if (valid() != other.valid()) {
345 stack_.back().location.at == other.stack_.back().location.at;
347 bool operator!=(
const ExecutionPartIterator &other)
const {
348 return !(*
this == other);
351 ExecutionPartIterator &operator++() {
352 if (stepping_ == Step::Into) {
355 assert(stepping_ == Step::Over &&
"Unexpected stepping");
361 ExecutionPartIterator operator++(
int) {
362 ExecutionPartIterator copy{*
this};
367 using difference_type = IteratorType::difference_type;
368 using value_type = IteratorType::value_type;
369 using reference = IteratorType::reference;
370 using pointer = IteratorType::pointer;
371 using iterator_category = std::forward_iterator_tag;
374 IteratorType at()
const {
return stack_.back().location.at; };
380 const Step stepping_ = Step::Default;
381 std::vector<Construct> stack_;
384template <
typename Iterator = ExecutionPartIterator>
struct ExecutionPartRange {
385 using Step =
typename Iterator::Step;
387 ExecutionPartRange(Block::const_iterator begin, Block::const_iterator end,
388 Step stepping = Step::Default,
390 : begin_(begin, end, stepping, owner), end_() {}
391 template <
typename R,
typename = std::enable_if_t<is_range_v<R>>>
392 ExecutionPartRange(
const R &range, Step stepping = Step::Default,
394 : ExecutionPartRange(range.begin(), range.end(), stepping, owner) {}
396 Iterator begin()
const {
return begin_; }
397 Iterator end()
const {
return end_; }
400 Iterator begin_, end_;
403struct LoopNestIterator :
public ExecutionPartIterator {
404 LoopNestIterator() =
default;
406 LoopNestIterator(IteratorType b, IteratorType e, Step s = Step::Default,
408 : ExecutionPartIterator(b, e, s, c) {
411 template <
typename R,
typename = std::enable_if_t<is_range_v<R>>>
412 LoopNestIterator(
const R &range, Step stepping = Step::Default,
414 : LoopNestIterator(range.begin(), range.end(), stepping, construct) {}
416 LoopNestIterator &operator++() {
417 ExecutionPartIterator::operator++();
422 LoopNestIterator operator++(
int) {
423 LoopNestIterator copy{*
this};
432 while (valid() && !isLoop(**
this)) {
433 ExecutionPartIterator::operator++();
Definition indirection.h:31
Definition char-block.h:26
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:289
Definition openmp-utils.h:277
Definition openmp-utils.h:384
Definition openmp-utils.h:217
Definition openmp-utils.h:73
Definition openmp-utils.h:225
Definition openmp-utils.h:157
Definition openmp-utils.h:236