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