1//===-- examples/flang-omp-report-plugin/flang-omp-report-visitor.cpp -----===//
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#include "FlangOmpReportVisitor.h"
10#include "llvm/ADT/StringExtras.h"
11
12namespace Fortran {
13namespace parser {
14bool operator<(const ClauseInfo &a, const ClauseInfo &b) {
15 return a.clause < b.clause;
16}
17bool operator==(const ClauseInfo &a, const ClauseInfo &b) {
18 return a.clause == b.clause && a.clauseDetails == b.clauseDetails;
19}
20bool operator!=(const ClauseInfo &a, const ClauseInfo &b) { return !(a == b); }
21
22bool operator==(const LogRecord &a, const LogRecord &b) {
23 return a.file == b.file && a.line == b.line && a.construct == b.construct &&
24 a.clauses == b.clauses;
25}
26bool operator!=(const LogRecord &a, const LogRecord &b) { return !(a == b); }
27
28std::string OpenMPCounterVisitor::normalize_construct_name(std::string s) {
29 std::transform(first: s.begin(), last: s.end(), result: s.begin(),
30 unary_op: [](unsigned char c) { return llvm::toLower(x: c); });
31 return s;
32}
33ClauseInfo OpenMPCounterVisitor::normalize_clause_name(
34 const llvm::StringRef s) {
35 std::size_t start = s.find(C: '(');
36 std::size_t end = s.find(C: ')');
37 std::string clauseName;
38 if (start != llvm::StringRef::npos && end != llvm::StringRef::npos) {
39 clauseName = s.substr(Start: 0, N: start);
40 clauseDetails = s.substr(Start: start + 1, N: end - start - 1);
41 } else {
42 clauseName = s;
43 }
44 std::transform(first: clauseName.begin(), last: clauseName.end(), result: clauseName.begin(),
45 unary_op: [](unsigned char c) { return llvm::toLower(x: c); });
46 std::transform(first: clauseDetails.begin(), last: clauseDetails.end(),
47 result: clauseDetails.begin(), unary_op: [](unsigned char c) { return llvm::toLower(x: c); });
48 return ClauseInfo{clauseName, clauseDetails};
49}
50SourcePosition OpenMPCounterVisitor::getLocation(const OmpWrapperType &w) {
51 if (auto *val = std::get_if<const OpenMPConstruct *>(&w)) {
52 const OpenMPConstruct *o{*val};
53 return getLocation(*o);
54 }
55 return getLocation(*std::get<const OpenMPDeclarativeConstruct *>(w));
56}
57SourcePosition OpenMPCounterVisitor::getLocation(
58 const OpenMPDeclarativeConstruct &c) {
59 return std::visit(
60 [&](const auto &o) -> SourcePosition {
61 return parsing->allCooked().GetSourcePositionRange(o.source)->first;
62 },
63 c.u);
64}
65SourcePosition OpenMPCounterVisitor::getLocation(const OpenMPConstruct &c) {
66 return std::visit(
67 Fortran::common::visitors{
68 [&](const OpenMPStandaloneConstruct &c) -> SourcePosition {
69 return parsing->allCooked().GetSourcePositionRange(c.source)->first;
70 },
71 // OpenMPSectionsConstruct, OpenMPLoopConstruct,
72 // OpenMPBlockConstruct, OpenMPCriticalConstruct Get the source from
73 // the directive field.
74 [&](const auto &c) -> SourcePosition {
75 const CharBlock &source{std::get<0>(c.t).source};
76 return (parsing->allCooked().GetSourcePositionRange(source))->first;
77 },
78 [&](const OpenMPAtomicConstruct &c) -> SourcePosition {
79 return std::visit(
80 [&](const auto &o) -> SourcePosition {
81 const CharBlock &source{std::get<Verbatim>(o.t).source};
82 return parsing->allCooked()
83 .GetSourcePositionRange(source)
84 ->first;
85 },
86 c.u);
87 },
88 [&](const OpenMPSectionConstruct &c) -> SourcePosition {
89 const CharBlock &source{c.source};
90 return (parsing->allCooked().GetSourcePositionRange(source))->first;
91 },
92 },
93 c.u);
94}
95
96std::string OpenMPCounterVisitor::getName(const OmpWrapperType &w) {
97 if (auto *val = std::get_if<const OpenMPConstruct *>(&w)) {
98 const OpenMPConstruct *o{*val};
99 return getName(*o);
100 }
101 return getName(*std::get<const OpenMPDeclarativeConstruct *>(w));
102}
103std::string OpenMPCounterVisitor::getName(const OpenMPDeclarativeConstruct &c) {
104 return std::visit(
105 [&](const auto &o) -> std::string {
106 const CharBlock &source{std::get<Verbatim>(o.t).source};
107 return normalize_construct_name(s: source.ToString());
108 },
109 c.u);
110}
111std::string OpenMPCounterVisitor::getName(const OpenMPConstruct &c) {
112 return std::visit(
113 Fortran::common::visitors{
114 [&](const OpenMPStandaloneConstruct &c) -> std::string {
115 return std::visit(
116 [&](const auto &c) {
117 // Get source from the directive or verbatim fields
118 const CharBlock &source{std::get<0>(c.t).source};
119 return normalize_construct_name(source.ToString());
120 },
121 c.u);
122 },
123 [&](const OpenMPExecutableAllocate &c) -> std::string {
124 const CharBlock &source{std::get<0>(c.t).source};
125 return normalize_construct_name(source.ToString());
126 },
127 [&](const OpenMPDeclarativeAllocate &c) -> std::string {
128 const CharBlock &source{std::get<0>(c.t).source};
129 return normalize_construct_name(source.ToString());
130 },
131 [&](const OpenMPAllocatorsConstruct &c) -> std::string {
132 const CharBlock &source{std::get<0>(c.t).source};
133 return normalize_construct_name(source.ToString());
134 },
135 [&](const OpenMPAtomicConstruct &c) -> std::string {
136 return std::visit(
137 [&](const auto &c) {
138 // Get source from the verbatim fields
139 const CharBlock &source{std::get<Verbatim>(c.t).source};
140 return "atomic-" +
141 normalize_construct_name(source.ToString());
142 },
143 c.u);
144 },
145 [&](const OpenMPSectionConstruct &c) -> std::string {
146 return "section";
147 },
148 // OpenMPSectionsConstruct, OpenMPLoopConstruct,
149 // OpenMPBlockConstruct, OpenMPCriticalConstruct Get the source from
150 // the directive field of the begin directive or from the verbatim
151 // field of the begin directive in Critical
152 [&](const auto &c) -> std::string {
153 const CharBlock &source{std::get<0>(std::get<0>(c.t).t).source};
154 return normalize_construct_name(source.ToString());
155 },
156 },
157 c.u);
158}
159
160bool OpenMPCounterVisitor::Pre(const OpenMPDeclarativeConstruct &c) {
161 OmpWrapperType *ow{new OmpWrapperType(&c)};
162 ompWrapperStack.push_back(ow);
163 return true;
164}
165bool OpenMPCounterVisitor::Pre(const OpenMPConstruct &c) {
166 OmpWrapperType *ow{new OmpWrapperType(&c)};
167 ompWrapperStack.push_back(ow);
168 return true;
169}
170
171void OpenMPCounterVisitor::Post(const OpenMPDeclarativeConstruct &) {
172 PostConstructsCommon();
173}
174void OpenMPCounterVisitor::Post(const OpenMPConstruct &) {
175 PostConstructsCommon();
176}
177void OpenMPCounterVisitor::PostConstructsCommon() {
178 OmpWrapperType *curConstruct = ompWrapperStack.back();
179 std::sort(
180 clauseStrings[curConstruct].begin(), clauseStrings[curConstruct].end());
181
182 SourcePosition s{getLocation(*curConstruct)};
183 LogRecord r{
184 s.path, s.line, getName(*curConstruct), clauseStrings[curConstruct]};
185 constructClauses.push_back(Elt: r);
186
187 auto it = clauseStrings.find(curConstruct);
188 clauseStrings.erase(it);
189 ompWrapperStack.pop_back();
190 delete curConstruct;
191}
192
193void OpenMPCounterVisitor::Post(const OmpProcBindClause::Type &c) {
194 clauseDetails +=
195 "type=" + std::string{OmpProcBindClause::EnumToString(c)} + ";";
196}
197void OpenMPCounterVisitor::Post(const OmpDefaultClause::Type &c) {
198 clauseDetails +=
199 "type=" + std::string{OmpDefaultClause::EnumToString(c)} + ";";
200}
201void OpenMPCounterVisitor::Post(const OmpDeviceTypeClause::Type &c) {
202 clauseDetails +=
203 "type=" + std::string{OmpDeviceTypeClause::EnumToString(c)} + ";";
204}
205void OpenMPCounterVisitor::Post(
206 const OmpDefaultmapClause::ImplicitBehavior &c) {
207 clauseDetails +=
208 "implicit_behavior=" + std::string{OmpDefaultmapClause::EnumToString(c)} +
209 ";";
210}
211void OpenMPCounterVisitor::Post(
212 const OmpDefaultmapClause::VariableCategory &c) {
213 clauseDetails +=
214 "variable_category=" + std::string{OmpDefaultmapClause::EnumToString(c)} +
215 ";";
216}
217void OpenMPCounterVisitor::Post(const OmpScheduleModifierType::ModType &c) {
218 clauseDetails +=
219 "modifier=" + std::string{OmpScheduleModifierType::EnumToString(c)} + ";";
220}
221void OpenMPCounterVisitor::Post(const OmpLinearModifier::Type &c) {
222 clauseDetails +=
223 "modifier=" + std::string{OmpLinearModifier::EnumToString(c)} + ";";
224}
225void OpenMPCounterVisitor::Post(const OmpDependenceType::Type &c) {
226 clauseDetails +=
227 "type=" + std::string{OmpDependenceType::EnumToString(c)} + ";";
228}
229void OpenMPCounterVisitor::Post(const OmpMapType::Type &c) {
230 clauseDetails += "type=" + std::string{OmpMapType::EnumToString(c)} + ";";
231}
232void OpenMPCounterVisitor::Post(const OmpScheduleClause::ScheduleType &c) {
233 clauseDetails +=
234 "type=" + std::string{OmpScheduleClause::EnumToString(c)} + ";";
235}
236void OpenMPCounterVisitor::Post(const OmpIfClause::DirectiveNameModifier &c) {
237 clauseDetails +=
238 "name_modifier=" + std::string{OmpIfClause::EnumToString(c)} + ";";
239}
240void OpenMPCounterVisitor::Post(const OmpCancelType::Type &c) {
241 clauseDetails += "type=" + std::string{OmpCancelType::EnumToString(c)} + ";";
242}
243void OpenMPCounterVisitor::Post(const OmpClause &c) {
244 PostClauseCommon(ci: normalize_clause_name(s: c.source.ToString()));
245 clauseDetails.clear();
246}
247void OpenMPCounterVisitor::PostClauseCommon(const ClauseInfo &ci) {
248 assert(
249 !ompWrapperStack.empty() && "Construct should be visited before clause");
250 clauseStrings[ompWrapperStack.back()].push_back(ci);
251}
252} // namespace parser
253} // namespace Fortran
254

source code of flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp