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 }, 89 c.u); 90 } 91 92 std::string OpenMPCounterVisitor::getName(const OmpWrapperType &w) { 93 if (auto *val = std::get_if<const OpenMPConstruct *>(&w)) { 94 const OpenMPConstruct *o{*val}; 95 return getName(*o); 96 } 97 return getName(*std::get<const OpenMPDeclarativeConstruct *>(w)); 98 } 99 std::string OpenMPCounterVisitor::getName(const OpenMPDeclarativeConstruct &c) { 100 return std::visit( 101 [&](const auto &o) -> std::string { 102 const CharBlock &source{std::get<Verbatim>(o.t).source}; 103 return normalize_construct_name(source.ToString()); 104 }, 105 c.u); 106 } 107 std::string OpenMPCounterVisitor::getName(const OpenMPConstruct &c) { 108 return std::visit( 109 Fortran::common::visitors{ 110 [&](const OpenMPStandaloneConstruct &c) -> std::string { 111 return std::visit( 112 [&](const auto &c) { 113 // Get source from the directive or verbatim fields 114 const CharBlock &source{std::get<0>(c.t).source}; 115 return normalize_construct_name(source.ToString()); 116 }, 117 c.u); 118 }, 119 [&](const OpenMPExecutableAllocate &c) -> std::string { 120 const CharBlock &source{std::get<0>(c.t).source}; 121 return normalize_construct_name(source.ToString()); 122 }, 123 [&](const OpenMPDeclarativeAllocate &c) -> std::string { 124 const CharBlock &source{std::get<0>(c.t).source}; 125 return normalize_construct_name(source.ToString()); 126 }, 127 [&](const OpenMPAtomicConstruct &c) -> std::string { 128 return std::visit( 129 [&](const auto &c) { 130 // Get source from the verbatim fields 131 const CharBlock &source{std::get<Verbatim>(c.t).source}; 132 return "atomic-" + 133 normalize_construct_name(source.ToString()); 134 }, 135 c.u); 136 }, 137 // OpenMPSectionsConstruct, OpenMPLoopConstruct, 138 // OpenMPBlockConstruct, OpenMPCriticalConstruct Get the source from 139 // the directive field of the begin directive or from the verbatim 140 // field of the begin directive in Critical 141 [&](const auto &c) -> std::string { 142 const CharBlock &source{std::get<0>(std::get<0>(c.t).t).source}; 143 return normalize_construct_name(source.ToString()); 144 }, 145 }, 146 c.u); 147 } 148 149 bool OpenMPCounterVisitor::Pre(const OpenMPDeclarativeConstruct &c) { 150 OmpWrapperType *ow{new OmpWrapperType(&c)}; 151 ompWrapperStack.push_back(ow); 152 return true; 153 } 154 bool OpenMPCounterVisitor::Pre(const OpenMPConstruct &c) { 155 OmpWrapperType *ow{new OmpWrapperType(&c)}; 156 ompWrapperStack.push_back(ow); 157 return true; 158 } 159 160 void OpenMPCounterVisitor::Post(const OpenMPDeclarativeConstruct &) { 161 PostConstructsCommon(); 162 } 163 void OpenMPCounterVisitor::Post(const OpenMPConstruct &) { 164 PostConstructsCommon(); 165 } 166 void OpenMPCounterVisitor::PostConstructsCommon() { 167 OmpWrapperType *curConstruct = ompWrapperStack.back(); 168 std::sort( 169 clauseStrings[curConstruct].begin(), clauseStrings[curConstruct].end()); 170 171 SourcePosition s{getLocation(*curConstruct)}; 172 LogRecord r{s.file.path(), s.line, getName(*curConstruct), 173 clauseStrings[curConstruct]}; 174 constructClauses.push_back(r); 175 176 auto it = clauseStrings.find(curConstruct); 177 clauseStrings.erase(it); 178 ompWrapperStack.pop_back(); 179 delete curConstruct; 180 } 181 182 void OpenMPCounterVisitor::Post(const OmpProcBindClause::Type &c) { 183 clauseDetails += "type=" + OmpProcBindClause::EnumToString(c) + ";"; 184 } 185 void OpenMPCounterVisitor::Post(const OmpDefaultClause::Type &c) { 186 clauseDetails += "type=" + OmpDefaultClause::EnumToString(c) + ";"; 187 } 188 void OpenMPCounterVisitor::Post( 189 const OmpDefaultmapClause::ImplicitBehavior &c) { 190 clauseDetails += 191 "implicit_behavior=" + OmpDefaultmapClause::EnumToString(c) + ";"; 192 } 193 void OpenMPCounterVisitor::Post( 194 const OmpDefaultmapClause::VariableCategory &c) { 195 clauseDetails += 196 "variable_category=" + OmpDefaultmapClause::EnumToString(c) + ";"; 197 } 198 void OpenMPCounterVisitor::Post(const OmpScheduleModifierType::ModType &c) { 199 clauseDetails += "modifier=" + OmpScheduleModifierType::EnumToString(c) + ";"; 200 } 201 void OpenMPCounterVisitor::Post(const OmpLinearModifier::Type &c) { 202 clauseDetails += "modifier=" + OmpLinearModifier::EnumToString(c) + ";"; 203 } 204 void OpenMPCounterVisitor::Post(const OmpDependenceType::Type &c) { 205 clauseDetails += "type=" + OmpDependenceType::EnumToString(c) + ";"; 206 } 207 void OpenMPCounterVisitor::Post(const OmpMapType::Type &c) { 208 clauseDetails += "type=" + OmpMapType::EnumToString(c) + ";"; 209 } 210 void OpenMPCounterVisitor::Post(const OmpScheduleClause::ScheduleType &c) { 211 clauseDetails += "type=" + OmpScheduleClause::EnumToString(c) + ";"; 212 } 213 void OpenMPCounterVisitor::Post(const OmpIfClause::DirectiveNameModifier &c) { 214 clauseDetails += "name_modifier=" + OmpIfClause::EnumToString(c) + ";"; 215 } 216 void OpenMPCounterVisitor::Post(const OmpCancelType::Type &c) { 217 clauseDetails += "type=" + OmpCancelType::EnumToString(c) + ";"; 218 } 219 void OpenMPCounterVisitor::Post(const OmpClause &c) { 220 PostClauseCommon(normalize_clause_name(c.source.ToString())); 221 clauseDetails.clear(); 222 } 223 void OpenMPCounterVisitor::PostClauseCommon(const ClauseInfo &ci) { 224 assert( 225 !ompWrapperStack.empty() && "Construct should be visited before clause"); 226 clauseStrings[ompWrapperStack.back()].push_back(ci); 227 } 228 } // namespace parser 229 } // namespace Fortran 230