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 | |
12 | namespace Fortran { |
13 | namespace parser { |
14 | bool operator<(const ClauseInfo &a, const ClauseInfo &b) { |
15 | return a.clause < b.clause; |
16 | } |
17 | bool operator==(const ClauseInfo &a, const ClauseInfo &b) { |
18 | return a.clause == b.clause && a.clauseDetails == b.clauseDetails; |
19 | } |
20 | bool operator!=(const ClauseInfo &a, const ClauseInfo &b) { return !(a == b); } |
21 | |
22 | bool 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 | } |
26 | bool operator!=(const LogRecord &a, const LogRecord &b) { return !(a == b); } |
27 | |
28 | std::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 | } |
33 | ClauseInfo 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 | } |
50 | SourcePosition 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 | } |
57 | SourcePosition 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 | } |
65 | SourcePosition 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 | |
96 | std::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 | } |
103 | std::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 | } |
111 | std::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 | |
160 | bool OpenMPCounterVisitor::Pre(const OpenMPDeclarativeConstruct &c) { |
161 | OmpWrapperType *ow{new OmpWrapperType(&c)}; |
162 | ompWrapperStack.push_back(ow); |
163 | return true; |
164 | } |
165 | bool OpenMPCounterVisitor::Pre(const OpenMPConstruct &c) { |
166 | OmpWrapperType *ow{new OmpWrapperType(&c)}; |
167 | ompWrapperStack.push_back(ow); |
168 | return true; |
169 | } |
170 | |
171 | void OpenMPCounterVisitor::Post(const OpenMPDeclarativeConstruct &) { |
172 | PostConstructsCommon(); |
173 | } |
174 | void OpenMPCounterVisitor::Post(const OpenMPConstruct &) { |
175 | PostConstructsCommon(); |
176 | } |
177 | void 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 | |
193 | void OpenMPCounterVisitor::Post(const OmpProcBindClause::Type &c) { |
194 | clauseDetails += |
195 | "type=" + std::string{OmpProcBindClause::EnumToString(c)} + ";" ; |
196 | } |
197 | void OpenMPCounterVisitor::Post(const OmpDefaultClause::Type &c) { |
198 | clauseDetails += |
199 | "type=" + std::string{OmpDefaultClause::EnumToString(c)} + ";" ; |
200 | } |
201 | void OpenMPCounterVisitor::Post(const OmpDeviceTypeClause::Type &c) { |
202 | clauseDetails += |
203 | "type=" + std::string{OmpDeviceTypeClause::EnumToString(c)} + ";" ; |
204 | } |
205 | void OpenMPCounterVisitor::Post( |
206 | const OmpDefaultmapClause::ImplicitBehavior &c) { |
207 | clauseDetails += |
208 | "implicit_behavior=" + std::string{OmpDefaultmapClause::EnumToString(c)} + |
209 | ";" ; |
210 | } |
211 | void OpenMPCounterVisitor::Post( |
212 | const OmpDefaultmapClause::VariableCategory &c) { |
213 | clauseDetails += |
214 | "variable_category=" + std::string{OmpDefaultmapClause::EnumToString(c)} + |
215 | ";" ; |
216 | } |
217 | void OpenMPCounterVisitor::Post(const OmpScheduleModifierType::ModType &c) { |
218 | clauseDetails += |
219 | "modifier=" + std::string{OmpScheduleModifierType::EnumToString(c)} + ";" ; |
220 | } |
221 | void OpenMPCounterVisitor::Post(const OmpLinearModifier::Type &c) { |
222 | clauseDetails += |
223 | "modifier=" + std::string{OmpLinearModifier::EnumToString(c)} + ";" ; |
224 | } |
225 | void OpenMPCounterVisitor::Post(const OmpDependenceType::Type &c) { |
226 | clauseDetails += |
227 | "type=" + std::string{OmpDependenceType::EnumToString(c)} + ";" ; |
228 | } |
229 | void OpenMPCounterVisitor::Post(const OmpMapType::Type &c) { |
230 | clauseDetails += "type=" + std::string{OmpMapType::EnumToString(c)} + ";" ; |
231 | } |
232 | void OpenMPCounterVisitor::Post(const OmpScheduleClause::ScheduleType &c) { |
233 | clauseDetails += |
234 | "type=" + std::string{OmpScheduleClause::EnumToString(c)} + ";" ; |
235 | } |
236 | void OpenMPCounterVisitor::Post(const OmpIfClause::DirectiveNameModifier &c) { |
237 | clauseDetails += |
238 | "name_modifier=" + std::string{OmpIfClause::EnumToString(c)} + ";" ; |
239 | } |
240 | void OpenMPCounterVisitor::Post(const OmpCancelType::Type &c) { |
241 | clauseDetails += "type=" + std::string{OmpCancelType::EnumToString(c)} + ";" ; |
242 | } |
243 | void OpenMPCounterVisitor::Post(const OmpClause &c) { |
244 | PostClauseCommon(ci: normalize_clause_name(s: c.source.ToString())); |
245 | clauseDetails.clear(); |
246 | } |
247 | void 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 | |