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(llvm::omp::Clause
id, llvm::omp::Version version);
146std::string GetUpperName(llvm::omp::Directive
id, llvm::omp::Version version);
156 template <
typename T>
static const OmpObjectList *Get(
const T &x) {
157 if constexpr (std::is_same_v<OmpObjectList, T>) {
159 }
else if constexpr (WrapperTrait<T>) {
161 }
else if constexpr (UnionTrait<T>) {
162 return std::visit([](
auto &&s) {
return Get(s); }, x.u);
163 }
else if constexpr (TupleTrait<T>) {
165 x.t, std::make_index_sequence<std::tuple_size_v<
decltype(x.t)>>{});
166 }
else if constexpr (ConstraintTrait<T>) {
173 template <
typename T>
175 return Get(x.value());
178 template <
typename... Ts,
size_t... Is>
180 const std::tuple<Ts...> &t, std::index_sequence<Is...>) {
182 ((objects = objects ? objects : Get(std::get<Is>(t))), ...);
188template <
typename T>
const OmpObjectList *GetOmpObjectList(
const T &clause) {
189 static_assert(std::is_class_v<T>,
"Unexpected argument type");
190 return detail::OmpObjectListScope::Get(clause);
195 for (
const OmpArgument &arg : spec.Arguments().v) {
196 if (
auto *t{std::get_if<T>(&arg.u)}) {
203const OmpClause *FindClause(
204 const OmpDirectiveSpecification &spec, llvm::omp::Clause clauseId);
206const BlockConstruct *GetFortranBlockConstruct(
207 const ExecutionPartConstruct &epc);
208const Block &GetInnermostExecPart(
const Block &block);
209bool IsStrictlyStructuredBlock(
const Block &block);
211const OmpCombinerExpression *GetCombinerExpr(
const OmpReductionSpecifier &x);
212const OmpCombinerExpression *GetCombinerExpr(
const OmpClause &x);
213const OmpInitializerExpression *GetInitializerExpr(
const OmpClause &x);
216 std::vector<const OmpAllocateDirective *> dirs;
224 static constexpr bool value{
false};
226template <
typename ClauseTy>
228 static constexpr bool value{
true};
231template <
typename ClauseTy>
232static constexpr bool HasModifier = detail::HasModifierImpl<ClauseTy>::value;
234template <
typename R,
typename =
void,
typename =
void>
struct is_range {
235 static constexpr bool value{
false};
240 std::void_t<decltype(std::declval<R>().begin())>,
241 std::void_t<decltype(std::declval<R>().end())>> {
242 static constexpr bool value{
true};
245template <
typename R>
constexpr bool is_range_v = is_range<R>::value;
275struct ExecutionPartIterator {
282 using IteratorType = Block::const_iterator;
283 using IteratorRange = llvm::iterator_range<IteratorType>;
287 struct IteratorGauge :
public IteratorRange {
288 IteratorGauge(IteratorType b, IteratorType e)
289 : IteratorRange(b, e), at(b) {}
290 IteratorGauge(IteratorRange r) : IteratorRange(r), at(r.begin()) {}
292 bool atEnd()
const {
return at == end(); }
298 : location(b, e), owner(c) {}
299 template <
typename R>
301 : location(r), owner(c) {}
302 Construct(
const Construct &c) =
default;
310 ExecutionPartIterator() =
default;
312 ExecutionPartIterator(IteratorType b, IteratorType e, Step s = Step::Default,
315 stack_.emplace_back(b, e, c);
318 template <
typename R,
typename = std::enable_if_t<is_range_v<R>>>
333 bool valid()
const {
return !stack_.empty(); }
335 const std::vector<Construct> &stack()
const {
return stack_; }
336 decltype(
auto)
operator*()
const {
return *at(); }
337 bool operator==(
const ExecutionPartIterator &other)
const {
338 if (valid() != other.valid()) {
343 stack_.back().location.at == other.stack_.back().location.at;
345 bool operator!=(
const ExecutionPartIterator &other)
const {
346 return !(*
this == other);
349 ExecutionPartIterator &operator++() {
350 if (stepping_ == Step::Into) {
353 assert(stepping_ == Step::Over &&
"Unexpected stepping");
359 ExecutionPartIterator operator++(
int) {
360 ExecutionPartIterator copy{*
this};
365 using difference_type = IteratorType::difference_type;
366 using value_type = IteratorType::value_type;
367 using reference = IteratorType::reference;
368 using pointer = IteratorType::pointer;
369 using iterator_category = std::forward_iterator_tag;
372 IteratorType at()
const {
return stack_.back().location.at; };
378 const Step stepping_ = Step::Default;
379 std::vector<Construct> stack_;
382template <
typename Iterator = ExecutionPartIterator>
struct ExecutionPartRange {
383 using Step =
typename Iterator::Step;
385 ExecutionPartRange(Block::const_iterator begin, Block::const_iterator end,
386 Step stepping = Step::Default,
388 : begin_(begin, end, stepping, owner), end_() {}
389 template <
typename R,
typename = std::enable_if_t<is_range_v<R>>>
390 ExecutionPartRange(
const R &range, Step stepping = Step::Default,
392 : ExecutionPartRange(range.begin(), range.end(), stepping, owner) {}
394 Iterator begin()
const {
return begin_; }
395 Iterator end()
const {
return end_; }
398 Iterator begin_, end_;
401struct LoopNestIterator :
public ExecutionPartIterator {
402 LoopNestIterator() =
default;
404 LoopNestIterator(IteratorType b, IteratorType e, Step s = Step::Default,
406 : ExecutionPartIterator(b, e, s, c) {
409 template <
typename R,
typename = std::enable_if_t<is_range_v<R>>>
410 LoopNestIterator(
const R &range, Step stepping = Step::Default,
412 : LoopNestIterator(range.begin(), range.end(), stepping, construct) {}
414 LoopNestIterator &operator++() {
415 ExecutionPartIterator::operator++();
420 LoopNestIterator operator++(
int) {
421 LoopNestIterator copy{*
this};
430 while (valid() && !isLoop(**
this)) {
431 ExecutionPartIterator::operator++();
Definition indirection.h:31
Definition char-block.h:26
Definition parse-tree.h:442
Definition parse-tree.h:2368
Definition parse-tree.h:559
Definition parse-tree.h:5518
Definition parse-tree.h:5382
Definition parse-tree.h:3580
Definition parse-tree.h:5283
Definition parse-tree.h:3635
Definition parse-tree.h:5396
Definition parse-tree.h:5670
Definition parse-tree.h:5522
Definition parse-tree.h:5656
Definition parse-tree.h:3746
Definition openmp-utils.h:287
Definition openmp-utils.h:275
Definition openmp-utils.h:382
Definition openmp-utils.h:215
Definition openmp-utils.h:73
Definition openmp-utils.h:223
Definition openmp-utils.h:155
Definition openmp-utils.h:234