FLANG
openmp-utils.h
1//===-- flang/Parser/openmp-utils.h ---------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Common OpenMP utilities.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef FORTRAN_PARSER_OPENMP_UTILS_H
14#define FORTRAN_PARSER_OPENMP_UTILS_H
15
16#include "flang/Common/indirection.h"
17#include "flang/Parser/parse-tree.h"
18#include "llvm/Frontend/OpenMP/OMP.h"
19
20#include <cassert>
21#include <tuple>
22#include <type_traits>
23#include <utility>
24#include <variant>
25
26namespace Fortran::parser::omp {
27
28template <typename T> constexpr auto addr_if(std::optional<T> &x) {
29 return x ? &*x : nullptr;
30}
31template <typename T> constexpr auto addr_if(const std::optional<T> &x) {
32 return x ? &*x : nullptr;
33}
34
35namespace detail {
36using D = llvm::omp::Directive;
37
38template <typename Construct> //
40 static constexpr llvm::omp::Directive id{D::OMPD_unknown};
41};
42
43#define MAKE_CONSTR_ID(Construct, Id) \
44 template <> struct ConstructId<Construct> { \
45 static constexpr llvm::omp::Directive id{Id}; \
46 }
47
48MAKE_CONSTR_ID(OpenMPDeclarativeAllocate, D::OMPD_allocate);
49MAKE_CONSTR_ID(OpenMPExecutableAllocate, D::OMPD_allocate);
50
51#undef MAKE_CONSTR_ID
52
54 static OmpDirectiveName MakeName(CharBlock source = {},
55 llvm::omp::Directive id = llvm::omp::Directive::OMPD_unknown) {
57 name.source = source;
58 name.v = id;
59 return name;
60 }
61
62 static OmpDirectiveName GetOmpDirectiveName(const OmpDirectiveName &x) {
63 return x;
64 }
65
66 static OmpDirectiveName GetOmpDirectiveName(const OmpBeginLoopDirective &x) {
67 return x.DirName();
68 }
69
70 static OmpDirectiveName GetOmpDirectiveName(const OpenMPSectionConstruct &x) {
71 if (auto &spec{std::get<std::optional<OmpDirectiveSpecification>>(x.t)}) {
72 return spec->DirName();
73 } else {
74 return MakeName({}, llvm::omp::Directive::OMPD_section);
75 }
76 }
77
78 static OmpDirectiveName GetOmpDirectiveName(
80 return x.DirName();
81 }
82
83 template <typename T>
84 static OmpDirectiveName GetOmpDirectiveName(const T &x) {
85 if constexpr (WrapperTrait<T>) {
86 if constexpr (std::is_same_v<T, OpenMPCancelConstruct> ||
87 std::is_same_v<T, OpenMPCancellationPointConstruct> ||
88 std::is_same_v<T, OpenMPDepobjConstruct> ||
89 std::is_same_v<T, OpenMPFlushConstruct> ||
90 std::is_same_v<T, OpenMPInteropConstruct> ||
91 std::is_same_v<T, OpenMPSimpleStandaloneConstruct> ||
92 std::is_same_v<T, OpenMPGroupprivate>) {
93 return x.v.DirName();
94 } else {
95 return GetOmpDirectiveName(x.v);
96 }
97 } else if constexpr (TupleTrait<T>) {
98 if constexpr (std::is_base_of_v<OmpBlockConstruct, T>) {
99 return std::get<OmpBeginDirective>(x.t).DirName();
100 } else if constexpr (std::is_same_v<T, OpenMPDeclarativeAllocate> ||
101 std::is_same_v<T, OpenMPExecutableAllocate>) {
102 return MakeName(std::get<Verbatim>(x.t).source, ConstructId<T>::id);
103 } else {
104 return GetFromTuple(
105 x.t, std::make_index_sequence<std::tuple_size_v<decltype(x.t)>>{});
106 }
107 } else if constexpr (UnionTrait<T>) {
108 return common::visit(
109 [](auto &&s) { return GetOmpDirectiveName(s); }, x.u);
110 } else {
111 return MakeName();
112 }
113 }
114
115 template <typename... Ts, size_t... Is>
116 static OmpDirectiveName GetFromTuple(
117 const std::tuple<Ts...> &t, std::index_sequence<Is...>) {
118 OmpDirectiveName name = MakeName();
119 auto accumulate = [&](const OmpDirectiveName &n) {
120 if (name.v == llvm::omp::Directive::OMPD_unknown) {
121 name = n;
122 } else {
123 assert(
124 n.v == llvm::omp::Directive::OMPD_unknown && "Conflicting names");
125 }
126 };
127 (accumulate(GetOmpDirectiveName(std::get<Is>(t))), ...);
128 return name;
129 }
130
131 template <typename T>
132 static OmpDirectiveName GetOmpDirectiveName(const common::Indirection<T> &x) {
133 return GetOmpDirectiveName(x.value());
134 }
135};
136} // namespace detail
137
138template <typename T> OmpDirectiveName GetOmpDirectiveName(const T &x) {
139 return detail::DirectiveNameScope::GetOmpDirectiveName(x);
140}
141
142const OmpObjectList *GetOmpObjectList(const OmpClause &clause);
143
144template <typename T>
145const T *GetFirstArgument(const OmpDirectiveSpecification &spec) {
146 for (const OmpArgument &arg : spec.Arguments().v) {
147 if (auto *t{std::get_if<T>(&arg.u)}) {
148 return t;
149 }
150 }
151 return nullptr;
152}
153
154const BlockConstruct *GetFortranBlockConstruct(
155 const ExecutionPartConstruct &epc);
156
157const OmpCombinerExpression *GetCombinerExpr(
158 const OmpReductionSpecifier &rspec);
159const OmpInitializerExpression *GetInitializerExpr(const OmpClause &init);
160
161} // namespace Fortran::parser::omp
162
163#endif // FORTRAN_PARSER_OPENMP_UTILS_H
Definition indirection.h:31
Definition char-block.h:28
Definition parse-tree.h:5307
Definition parse-tree.h:5047
Definition parse-tree.h:4931
Definition parse-tree.h:3496
Definition parse-tree.h:4954
Definition parse-tree.h:3541
Definition parse-tree.h:5155
Definition parse-tree.h:5181
Definition parse-tree.h:5061
Definition parse-tree.h:3660
Definition openmp-utils.h:39