13#ifndef FORTRAN_PARSER_OPENMP_UTILS_H
14#define FORTRAN_PARSER_OPENMP_UTILS_H
16#include "flang/Common/indirection.h"
17#include "flang/Parser/parse-tree.h"
18#include "llvm/ADT/iterator_range.h"
19#include "llvm/Frontend/OpenMP/OMP.h"
29namespace Fortran::parser::omp {
31template <
typename T>
constexpr auto addr_if(std::optional<T> &x) {
32 return x ? &*x :
nullptr;
34template <
typename T>
constexpr auto addr_if(
const std::optional<T> &x) {
35 return x ? &*x :
nullptr;
38const parser::Designator *GetDesignatorFromObj(
const parser::OmpObject &
object);
39const parser::DataRef *GetDataRefFromObj(
const parser::OmpObject &
object);
40const parser::OmpLocator *GetLocatorFromObj(
const parser::OmpObject &
object);
41const parser::Name *GetCommonBlockFromObj(
const parser::OmpObject &
object);
43const parser::ArrayElement *GetArrayElementFromObj(
44 const parser::OmpObject &
object);
45std::optional<parser::CharBlock> GetObjectSource(
46 const parser::OmpObject &
object);
47const parser::OmpObject *GetArgumentObject(
const parser::OmpArgument &argument);
49const OmpDirectiveSpecification &GetOmpDirectiveSpecification(
50 const OpenMPConstruct &x);
51const OmpDirectiveSpecification &GetOmpDirectiveSpecification(
52 const OpenMPDeclarativeConstruct &x);
57 llvm::omp::Directive
id = llvm::omp::Directive::OMPD_unknown) {
69 if (
auto &spec{std::get<std::optional<OmpDirectiveSpecification>>(x.t)}) {
70 return spec->DirName();
72 return MakeName({}, llvm::omp::Directive::OMPD_section);
83 if constexpr (WrapperTrait<T>) {
84 return GetOmpDirectiveName(x.v);
85 }
else if constexpr (TupleTrait<T>) {
86 if constexpr (std::is_base_of_v<OmpBlockConstruct, T>) {
87 return std::get<OmpBeginDirective>(x.t).DirName();
90 x.t, std::make_index_sequence<std::tuple_size_v<
decltype(x.t)>>{});
92 }
else if constexpr (UnionTrait<T>) {
94 [](
auto &&s) {
return GetOmpDirectiveName(s); }, x.u);
100 template <
typename... Ts,
size_t... Is>
102 const std::tuple<Ts...> &t, std::index_sequence<Is...>) {
105 if (name.v == llvm::omp::Directive::OMPD_unknown) {
109 n.v == llvm::omp::Directive::OMPD_unknown &&
"Conflicting names");
112 (accumulate(GetOmpDirectiveName(std::get<Is>(t))), ...);
116 template <
typename T>
118 return GetOmpDirectiveName(x.value());
124 return detail::DirectiveNameScope::GetOmpDirectiveName(x);
127std::string GetUpperName(llvm::omp::Clause
id,
unsigned version);
128std::string GetUpperName(llvm::omp::Directive
id,
unsigned version);
138 template <
typename T>
static const OmpObjectList *Get(
const T &x) {
139 if constexpr (std::is_same_v<OmpObjectList, T>) {
141 }
else if constexpr (WrapperTrait<T>) {
143 }
else if constexpr (UnionTrait<T>) {
144 return std::visit([](
auto &&s) {
return Get(s); }, x.u);
145 }
else if constexpr (TupleTrait<T>) {
147 x.t, std::make_index_sequence<std::tuple_size_v<
decltype(x.t)>>{});
148 }
else if constexpr (ConstraintTrait<T>) {
155 template <
typename T>
157 return Get(x.value());
160 template <
typename... Ts,
size_t... Is>
162 const std::tuple<Ts...> &t, std::index_sequence<Is...>) {
164 ((objects = objects ? objects : Get(std::get<Is>(t))), ...);
170template <
typename T>
const OmpObjectList *GetOmpObjectList(
const T &clause) {
171 static_assert(std::is_class_v<T>,
"Unexpected argument type");
172 return detail::OmpObjectListScope::Get(clause);
177 for (
const OmpArgument &arg : spec.Arguments().v) {
178 if (
auto *t{std::get_if<T>(&arg.u)}) {
185const OmpClause *FindClause(
186 const OmpDirectiveSpecification &spec, llvm::omp::Clause clauseId);
188const BlockConstruct *GetFortranBlockConstruct(
189 const ExecutionPartConstruct &epc);
190const Block &GetInnermostExecPart(
const Block &block);
191bool IsStrictlyStructuredBlock(
const Block &block);
193const OmpCombinerExpression *GetCombinerExpr(
const OmpReductionSpecifier &x);
194const OmpCombinerExpression *GetCombinerExpr(
const OmpClause &x);
195const OmpInitializerExpression *GetInitializerExpr(
const OmpClause &x);
198 std::vector<const OmpAllocateDirective *> dirs;
204template <
typename R,
typename =
void,
typename =
void>
struct is_range {
205 static constexpr bool value{
false};
210 std::void_t<decltype(std::declval<R>().begin())>,
211 std::void_t<decltype(std::declval<R>().end())>> {
212 static constexpr bool value{
true};
215template <
typename R>
constexpr bool is_range_v = is_range<R>::value;
245struct ExecutionPartIterator {
252 using IteratorType = Block::const_iterator;
253 using IteratorRange = llvm::iterator_range<IteratorType>;
257 struct IteratorGauge :
public IteratorRange {
258 IteratorGauge(IteratorType b, IteratorType e)
259 : IteratorRange(b, e), at(b) {}
260 IteratorGauge(IteratorRange r) : IteratorRange(r), at(r.begin()) {}
262 bool atEnd()
const {
return at == end(); }
268 : location(b, e), owner(c) {}
269 template <
typename R>
271 : location(r), owner(c) {}
272 Construct(
const Construct &c) =
default;
280 ExecutionPartIterator() =
default;
282 ExecutionPartIterator(IteratorType b, IteratorType e, Step s = Step::Default,
285 stack_.emplace_back(b, e, c);
288 template <
typename R,
typename = std::enable_if_t<is_range_v<R>>>
303 bool valid()
const {
return !stack_.empty(); }
305 const std::vector<Construct> &stack()
const {
return stack_; }
306 decltype(
auto)
operator*()
const {
return *at(); }
307 bool operator==(
const ExecutionPartIterator &other)
const {
308 if (valid() != other.valid()) {
313 stack_.back().location.at == other.stack_.back().location.at;
315 bool operator!=(
const ExecutionPartIterator &other)
const {
316 return !(*
this == other);
319 ExecutionPartIterator &operator++() {
320 if (stepping_ == Step::Into) {
323 assert(stepping_ == Step::Over &&
"Unexpected stepping");
329 ExecutionPartIterator operator++(
int) {
330 ExecutionPartIterator copy{*
this};
335 using difference_type = IteratorType::difference_type;
336 using value_type = IteratorType::value_type;
337 using reference = IteratorType::reference;
338 using pointer = IteratorType::pointer;
339 using iterator_category = std::forward_iterator_tag;
342 IteratorType at()
const {
return stack_.back().location.at; };
348 const Step stepping_ = Step::Default;
349 std::vector<Construct> stack_;
352template <
typename Iterator = ExecutionPartIterator>
struct ExecutionPartRange {
353 using Step =
typename Iterator::Step;
355 ExecutionPartRange(Block::const_iterator begin, Block::const_iterator end,
356 Step stepping = Step::Default,
358 : begin_(begin, end, stepping, owner), end_() {}
359 template <
typename R,
typename = std::enable_if_t<is_range_v<R>>>
360 ExecutionPartRange(
const R &range, Step stepping = Step::Default,
362 : ExecutionPartRange(range.begin(), range.end(), stepping, owner) {}
364 Iterator begin()
const {
return begin_; }
365 Iterator end()
const {
return end_; }
368 Iterator begin_, end_;
371struct LoopNestIterator :
public ExecutionPartIterator {
372 LoopNestIterator() =
default;
374 LoopNestIterator(IteratorType b, IteratorType e, Step s = Step::Default,
376 : ExecutionPartIterator(b, e, s, c) {
379 template <
typename R,
typename = std::enable_if_t<is_range_v<R>>>
380 LoopNestIterator(
const R &range, Step stepping = Step::Default,
382 : LoopNestIterator(range.begin(), range.end(), stepping, construct) {}
384 LoopNestIterator &operator++() {
385 ExecutionPartIterator::operator++();
390 LoopNestIterator operator++(
int) {
391 LoopNestIterator copy{*
this};
400 while (valid() && !isLoop(**
this)) {
401 ExecutionPartIterator::operator++();
Definition indirection.h:31
Definition char-block.h:26
Definition parse-tree.h:441
Definition parse-tree.h:2365
Definition parse-tree.h:558
Definition parse-tree.h:5397
Definition parse-tree.h:5261
Definition parse-tree.h:3577
Definition parse-tree.h:5162
Definition parse-tree.h:3632
Definition parse-tree.h:5275
Definition parse-tree.h:5549
Definition parse-tree.h:5401
Definition parse-tree.h:5535
Definition parse-tree.h:3742
Definition openmp-utils.h:257
Definition openmp-utils.h:245
Definition openmp-utils.h:352
Definition openmp-utils.h:197
Definition openmp-utils.h:55
Definition openmp-utils.h:137
Definition openmp-utils.h:204