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