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(s.begin(), s.end(), s.begin(), 30 [](unsigned char c) { return llvm::toLower(c); }); 31 return s; 32 } 33 ClauseInfo OpenMPCounterVisitor::normalize_clause_name( 34 const llvm::StringRef s) { 35 std::size_t start = s.find('('); 36 std::size_t end = s.find(')'); 37 std::string clauseName; 38 if (start != llvm::StringRef::npos && end != llvm::StringRef::npos) { 39 clauseName = s.substr(0, start); 40 clauseDetails = s.substr(start + 1, end - start - 1); 41 } else { 42 clauseName = s; 43 } 44 std::transform(clauseName.begin(), clauseName.end(), clauseName.begin(), 45 [](unsigned char c) { return llvm::toLower(c); }); 46 std::transform(clauseDetails.begin(), clauseDetails.end(), 47 clauseDetails.begin(), [](unsigned char c) { return llvm::toLower(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(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 OpenMPAtomicConstruct &c) -> std::string { 132 return std::visit( 133 [&](const auto &c) { 134 // Get source from the verbatim fields 135 const CharBlock &source{std::get<Verbatim>(c.t).source}; 136 return "atomic-" + 137 normalize_construct_name(source.ToString()); 138 }, 139 c.u); 140 }, 141 [&](const OpenMPSectionConstruct &c) -> std::string { 142 return "section"; 143 }, 144 // OpenMPSectionsConstruct, OpenMPLoopConstruct, 145 // OpenMPBlockConstruct, OpenMPCriticalConstruct Get the source from 146 // the directive field of the begin directive or from the verbatim 147 // field of the begin directive in Critical 148 [&](const auto &c) -> std::string { 149 const CharBlock &source{std::get<0>(std::get<0>(c.t).t).source}; 150 return normalize_construct_name(source.ToString()); 151 }, 152 }, 153 c.u); 154 } 155 156 bool OpenMPCounterVisitor::Pre(const OpenMPDeclarativeConstruct &c) { 157 OmpWrapperType *ow{new OmpWrapperType(&c)}; 158 ompWrapperStack.push_back(ow); 159 return true; 160 } 161 bool OpenMPCounterVisitor::Pre(const OpenMPConstruct &c) { 162 OmpWrapperType *ow{new OmpWrapperType(&c)}; 163 ompWrapperStack.push_back(ow); 164 return true; 165 } 166 167 void OpenMPCounterVisitor::Post(const OpenMPDeclarativeConstruct &) { 168 PostConstructsCommon(); 169 } 170 void OpenMPCounterVisitor::Post(const OpenMPConstruct &) { 171 PostConstructsCommon(); 172 } 173 void OpenMPCounterVisitor::PostConstructsCommon() { 174 OmpWrapperType *curConstruct = ompWrapperStack.back(); 175 std::sort( 176 clauseStrings[curConstruct].begin(), clauseStrings[curConstruct].end()); 177 178 SourcePosition s{getLocation(*curConstruct)}; 179 LogRecord r{s.file.path(), s.line, getName(*curConstruct), 180 clauseStrings[curConstruct]}; 181 constructClauses.push_back(r); 182 183 auto it = clauseStrings.find(curConstruct); 184 clauseStrings.erase(it); 185 ompWrapperStack.pop_back(); 186 delete curConstruct; 187 } 188 189 void OpenMPCounterVisitor::Post(const OmpProcBindClause::Type &c) { 190 clauseDetails += "type=" + OmpProcBindClause::EnumToString(c) + ";"; 191 } 192 void OpenMPCounterVisitor::Post(const OmpDefaultClause::Type &c) { 193 clauseDetails += "type=" + OmpDefaultClause::EnumToString(c) + ";"; 194 } 195 void OpenMPCounterVisitor::Post( 196 const OmpDefaultmapClause::ImplicitBehavior &c) { 197 clauseDetails += 198 "implicit_behavior=" + OmpDefaultmapClause::EnumToString(c) + ";"; 199 } 200 void OpenMPCounterVisitor::Post( 201 const OmpDefaultmapClause::VariableCategory &c) { 202 clauseDetails += 203 "variable_category=" + OmpDefaultmapClause::EnumToString(c) + ";"; 204 } 205 void OpenMPCounterVisitor::Post(const OmpScheduleModifierType::ModType &c) { 206 clauseDetails += "modifier=" + OmpScheduleModifierType::EnumToString(c) + ";"; 207 } 208 void OpenMPCounterVisitor::Post(const OmpLinearModifier::Type &c) { 209 clauseDetails += "modifier=" + OmpLinearModifier::EnumToString(c) + ";"; 210 } 211 void OpenMPCounterVisitor::Post(const OmpDependenceType::Type &c) { 212 clauseDetails += "type=" + OmpDependenceType::EnumToString(c) + ";"; 213 } 214 void OpenMPCounterVisitor::Post(const OmpMapType::Type &c) { 215 clauseDetails += "type=" + OmpMapType::EnumToString(c) + ";"; 216 } 217 void OpenMPCounterVisitor::Post(const OmpScheduleClause::ScheduleType &c) { 218 clauseDetails += "type=" + OmpScheduleClause::EnumToString(c) + ";"; 219 } 220 void OpenMPCounterVisitor::Post(const OmpIfClause::DirectiveNameModifier &c) { 221 clauseDetails += "name_modifier=" + OmpIfClause::EnumToString(c) + ";"; 222 } 223 void OpenMPCounterVisitor::Post(const OmpCancelType::Type &c) { 224 clauseDetails += "type=" + OmpCancelType::EnumToString(c) + ";"; 225 } 226 void OpenMPCounterVisitor::Post(const OmpClause &c) { 227 PostClauseCommon(normalize_clause_name(c.source.ToString())); 228 clauseDetails.clear(); 229 } 230 void OpenMPCounterVisitor::PostClauseCommon(const ClauseInfo &ci) { 231 assert( 232 !ompWrapperStack.empty() && "Construct should be visited before clause"); 233 clauseStrings[ompWrapperStack.back()].push_back(ci); 234 } 235 } // namespace parser 236 } // namespace Fortran 237