1 //===- llvm/Support/DiagnosticInfo.cpp - Diagnostic Definitions -*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines the different classes involved in low level diagnostics. 11 // 12 // Diagnostics reporting is still done as part of the LLVMContext. 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/IR/DiagnosticInfo.h" 16 #include "LLVMContextImpl.h" 17 #include "llvm/ADT/StringExtras.h" 18 #include "llvm/ADT/Twine.h" 19 #include "llvm/IR/Constants.h" 20 #include "llvm/IR/DebugInfo.h" 21 #include "llvm/IR/DiagnosticPrinter.h" 22 #include "llvm/IR/Function.h" 23 #include "llvm/IR/Instruction.h" 24 #include "llvm/IR/Metadata.h" 25 #include "llvm/IR/Module.h" 26 #include "llvm/Support/CommandLine.h" 27 #include "llvm/Support/Regex.h" 28 #include <atomic> 29 #include <string> 30 31 using namespace llvm; 32 33 namespace { 34 35 /// \brief Regular expression corresponding to the value given in one of the 36 /// -pass-remarks* command line flags. Passes whose name matches this regexp 37 /// will emit a diagnostic when calling the associated diagnostic function 38 /// (emitOptimizationRemark, emitOptimizationRemarkMissed or 39 /// emitOptimizationRemarkAnalysis). 40 struct PassRemarksOpt { 41 std::shared_ptr<Regex> Pattern; 42 43 void operator=(const std::string &Val) { 44 // Create a regexp object to match pass names for emitOptimizationRemark. 45 if (!Val.empty()) { 46 Pattern = std::make_shared<Regex>(Val); 47 std::string RegexError; 48 if (!Pattern->isValid(RegexError)) 49 report_fatal_error("Invalid regular expression '" + Val + 50 "' in -pass-remarks: " + RegexError, 51 false); 52 } 53 } 54 }; 55 56 static PassRemarksOpt PassRemarksOptLoc; 57 static PassRemarksOpt PassRemarksMissedOptLoc; 58 static PassRemarksOpt PassRemarksAnalysisOptLoc; 59 60 // -pass-remarks 61 // Command line flag to enable emitOptimizationRemark() 62 static cl::opt<PassRemarksOpt, true, cl::parser<std::string>> 63 PassRemarks("pass-remarks", cl::value_desc("pattern"), 64 cl::desc("Enable optimization remarks from passes whose name match " 65 "the given regular expression"), 66 cl::Hidden, cl::location(PassRemarksOptLoc), cl::ValueRequired, 67 cl::ZeroOrMore); 68 69 // -pass-remarks-missed 70 // Command line flag to enable emitOptimizationRemarkMissed() 71 static cl::opt<PassRemarksOpt, true, cl::parser<std::string>> PassRemarksMissed( 72 "pass-remarks-missed", cl::value_desc("pattern"), 73 cl::desc("Enable missed optimization remarks from passes whose name match " 74 "the given regular expression"), 75 cl::Hidden, cl::location(PassRemarksMissedOptLoc), cl::ValueRequired, 76 cl::ZeroOrMore); 77 78 // -pass-remarks-analysis 79 // Command line flag to enable emitOptimizationRemarkAnalysis() 80 static cl::opt<PassRemarksOpt, true, cl::parser<std::string>> 81 PassRemarksAnalysis( 82 "pass-remarks-analysis", cl::value_desc("pattern"), 83 cl::desc( 84 "Enable optimization analysis remarks from passes whose name match " 85 "the given regular expression"), 86 cl::Hidden, cl::location(PassRemarksAnalysisOptLoc), cl::ValueRequired, 87 cl::ZeroOrMore); 88 } 89 90 int llvm::getNextAvailablePluginDiagnosticKind() { 91 static std::atomic<int> PluginKindID(DK_FirstPluginKind); 92 return ++PluginKindID; 93 } 94 95 const char *OptimizationRemarkAnalysis::AlwaysPrint = ""; 96 97 DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(const Instruction &I, 98 const Twine &MsgStr, 99 DiagnosticSeverity Severity) 100 : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(0), MsgStr(MsgStr), 101 Instr(&I) { 102 if (const MDNode *SrcLoc = I.getMetadata("srcloc")) { 103 if (SrcLoc->getNumOperands() != 0) 104 if (const auto *CI = 105 mdconst::dyn_extract<ConstantInt>(SrcLoc->getOperand(0))) 106 LocCookie = CI->getZExtValue(); 107 } 108 } 109 110 void DiagnosticInfoInlineAsm::print(DiagnosticPrinter &DP) const { 111 DP << getMsgStr(); 112 if (getLocCookie()) 113 DP << " at line " << getLocCookie(); 114 } 115 116 void DiagnosticInfoResourceLimit::print(DiagnosticPrinter &DP) const { 117 DP << getResourceName() << " limit"; 118 119 if (getResourceLimit() != 0) 120 DP << " of " << getResourceLimit(); 121 122 DP << " exceeded (" << getResourceSize() << ") in " << getFunction(); 123 } 124 125 void DiagnosticInfoDebugMetadataVersion::print(DiagnosticPrinter &DP) const { 126 DP << "ignoring debug info with an invalid version (" << getMetadataVersion() 127 << ") in " << getModule(); 128 } 129 130 void DiagnosticInfoIgnoringInvalidDebugMetadata::print( 131 DiagnosticPrinter &DP) const { 132 DP << "ignoring invalid debug info in " << getModule().getModuleIdentifier(); 133 } 134 135 void DiagnosticInfoSampleProfile::print(DiagnosticPrinter &DP) const { 136 if (!FileName.empty()) { 137 DP << getFileName(); 138 if (LineNum > 0) 139 DP << ":" << getLineNum(); 140 DP << ": "; 141 } 142 DP << getMsg(); 143 } 144 145 void DiagnosticInfoPGOProfile::print(DiagnosticPrinter &DP) const { 146 if (getFileName()) 147 DP << getFileName() << ": "; 148 DP << getMsg(); 149 } 150 151 bool DiagnosticInfoWithDebugLocBase::isLocationAvailable() const { 152 return getDebugLoc(); 153 } 154 155 void DiagnosticInfoWithDebugLocBase::getLocation(StringRef *Filename, 156 unsigned *Line, 157 unsigned *Column) const { 158 DILocation *L = getDebugLoc(); 159 assert(L != nullptr && "debug location is invalid"); 160 *Filename = L->getFilename(); 161 *Line = L->getLine(); 162 *Column = L->getColumn(); 163 } 164 165 const std::string DiagnosticInfoWithDebugLocBase::getLocationStr() const { 166 StringRef Filename("<unknown>"); 167 unsigned Line = 0; 168 unsigned Column = 0; 169 if (isLocationAvailable()) 170 getLocation(&Filename, &Line, &Column); 171 return (Filename + ":" + Twine(Line) + ":" + Twine(Column)).str(); 172 } 173 174 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, Value *V) 175 : Key(Key) { 176 if (auto *F = dyn_cast<Function>(V)) { 177 if (DISubprogram *SP = F->getSubprogram()) 178 DLoc = DebugLoc::get(SP->getScopeLine(), 0, SP); 179 } 180 else if (auto *I = dyn_cast<Instruction>(V)) 181 DLoc = I->getDebugLoc(); 182 183 // Only include names that correspond to user variables. FIXME: we should use 184 // debug info if available to get the name of the user variable. 185 if (isa<llvm::Argument>(V) || isa<GlobalValue>(V)) 186 Val = GlobalValue::getRealLinkageName(V->getName()); 187 else if (isa<Constant>(V)) { 188 raw_string_ostream OS(Val); 189 V->printAsOperand(OS, /*PrintType=*/false); 190 } else if (auto *I = dyn_cast<Instruction>(V)) 191 Val = I->getOpcodeName(); 192 } 193 194 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, Type *T) 195 : Key(Key) { 196 raw_string_ostream OS(Val); 197 OS << *T; 198 } 199 200 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, int N) 201 : Key(Key), Val(itostr(N)) {} 202 203 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, unsigned N) 204 : Key(Key), Val(utostr(N)) {} 205 206 void DiagnosticInfoOptimizationBase::print(DiagnosticPrinter &DP) const { 207 DP << getLocationStr() << ": " << getMsg(); 208 if (Hotness) 209 DP << " (hotness: " << *Hotness << ")"; 210 } 211 212 OptimizationRemark::OptimizationRemark(const char *PassName, 213 StringRef RemarkName, 214 const DebugLoc &DLoc, Value *CodeRegion) 215 : DiagnosticInfoOptimizationBase( 216 DK_OptimizationRemark, DS_Remark, PassName, RemarkName, 217 *cast<BasicBlock>(CodeRegion)->getParent(), DLoc, CodeRegion) {} 218 219 OptimizationRemark::OptimizationRemark(const char *PassName, 220 StringRef RemarkName, Instruction *Inst) 221 : DiagnosticInfoOptimizationBase(DK_OptimizationRemark, DS_Remark, PassName, 222 RemarkName, 223 *Inst->getParent()->getParent(), 224 Inst->getDebugLoc(), Inst->getParent()) {} 225 226 bool OptimizationRemark::isEnabled() const { 227 return PassRemarksOptLoc.Pattern && 228 PassRemarksOptLoc.Pattern->match(getPassName()); 229 } 230 231 OptimizationRemarkMissed::OptimizationRemarkMissed(const char *PassName, 232 StringRef RemarkName, 233 const DebugLoc &DLoc, 234 Value *CodeRegion) 235 : DiagnosticInfoOptimizationBase( 236 DK_OptimizationRemarkMissed, DS_Remark, PassName, RemarkName, 237 *cast<BasicBlock>(CodeRegion)->getParent(), DLoc, CodeRegion) {} 238 239 OptimizationRemarkMissed::OptimizationRemarkMissed(const char *PassName, 240 StringRef RemarkName, 241 Instruction *Inst) 242 : DiagnosticInfoOptimizationBase(DK_OptimizationRemarkMissed, DS_Remark, 243 PassName, RemarkName, 244 *Inst->getParent()->getParent(), 245 Inst->getDebugLoc(), Inst->getParent()) {} 246 247 bool OptimizationRemarkMissed::isEnabled() const { 248 return PassRemarksMissedOptLoc.Pattern && 249 PassRemarksMissedOptLoc.Pattern->match(getPassName()); 250 } 251 252 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(const char *PassName, 253 StringRef RemarkName, 254 const DebugLoc &DLoc, 255 Value *CodeRegion) 256 : DiagnosticInfoOptimizationBase( 257 DK_OptimizationRemarkAnalysis, DS_Remark, PassName, RemarkName, 258 *cast<BasicBlock>(CodeRegion)->getParent(), DLoc, CodeRegion) {} 259 260 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(const char *PassName, 261 StringRef RemarkName, 262 Instruction *Inst) 263 : DiagnosticInfoOptimizationBase(DK_OptimizationRemarkAnalysis, DS_Remark, 264 PassName, RemarkName, 265 *Inst->getParent()->getParent(), 266 Inst->getDebugLoc(), Inst->getParent()) {} 267 268 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(enum DiagnosticKind Kind, 269 const char *PassName, 270 StringRef RemarkName, 271 const DebugLoc &DLoc, 272 Value *CodeRegion) 273 : DiagnosticInfoOptimizationBase(Kind, DS_Remark, PassName, RemarkName, 274 *cast<BasicBlock>(CodeRegion)->getParent(), 275 DLoc, CodeRegion) {} 276 277 bool OptimizationRemarkAnalysis::isEnabled() const { 278 return shouldAlwaysPrint() || 279 (PassRemarksAnalysisOptLoc.Pattern && 280 PassRemarksAnalysisOptLoc.Pattern->match(getPassName())); 281 } 282 283 void DiagnosticInfoMIRParser::print(DiagnosticPrinter &DP) const { 284 DP << Diagnostic; 285 } 286 287 void llvm::emitOptimizationRemark(LLVMContext &Ctx, const char *PassName, 288 const Function &Fn, const DebugLoc &DLoc, 289 const Twine &Msg) { 290 Ctx.diagnose(OptimizationRemark(PassName, Fn, DLoc, Msg)); 291 } 292 293 void llvm::emitOptimizationRemarkMissed(LLVMContext &Ctx, const char *PassName, 294 const Function &Fn, 295 const DebugLoc &DLoc, 296 const Twine &Msg) { 297 Ctx.diagnose(OptimizationRemarkMissed(PassName, Fn, DLoc, Msg)); 298 } 299 300 void llvm::emitOptimizationRemarkAnalysis(LLVMContext &Ctx, 301 const char *PassName, 302 const Function &Fn, 303 const DebugLoc &DLoc, 304 const Twine &Msg) { 305 Ctx.diagnose(OptimizationRemarkAnalysis(PassName, Fn, DLoc, Msg)); 306 } 307 308 void llvm::emitOptimizationRemarkAnalysisFPCommute(LLVMContext &Ctx, 309 const char *PassName, 310 const Function &Fn, 311 const DebugLoc &DLoc, 312 const Twine &Msg) { 313 Ctx.diagnose(OptimizationRemarkAnalysisFPCommute(PassName, Fn, DLoc, Msg)); 314 } 315 316 void llvm::emitOptimizationRemarkAnalysisAliasing(LLVMContext &Ctx, 317 const char *PassName, 318 const Function &Fn, 319 const DebugLoc &DLoc, 320 const Twine &Msg) { 321 Ctx.diagnose(OptimizationRemarkAnalysisAliasing(PassName, Fn, DLoc, Msg)); 322 } 323 324 bool DiagnosticInfoOptimizationFailure::isEnabled() const { 325 // Only print warnings. 326 return getSeverity() == DS_Warning; 327 } 328 329 void DiagnosticInfoUnsupported::print(DiagnosticPrinter &DP) const { 330 std::string Str; 331 raw_string_ostream OS(Str); 332 333 OS << getLocationStr() << ": in function " << getFunction().getName() << ' ' 334 << *getFunction().getFunctionType() << ": " << Msg << '\n'; 335 OS.flush(); 336 DP << Str; 337 } 338 339 void llvm::emitLoopVectorizeWarning(LLVMContext &Ctx, const Function &Fn, 340 const DebugLoc &DLoc, const Twine &Msg) { 341 Ctx.diagnose(DiagnosticInfoOptimizationFailure( 342 Fn, DLoc, Twine("loop not vectorized: " + Msg))); 343 } 344 345 void llvm::emitLoopInterleaveWarning(LLVMContext &Ctx, const Function &Fn, 346 const DebugLoc &DLoc, const Twine &Msg) { 347 Ctx.diagnose(DiagnosticInfoOptimizationFailure( 348 Fn, DLoc, Twine("loop not interleaved: " + Msg))); 349 } 350 351 void DiagnosticInfoISelFallback::print(DiagnosticPrinter &DP) const { 352 DP << "Instruction selection used fallback path for " << getFunction(); 353 } 354 355 DiagnosticInfoOptimizationBase &DiagnosticInfoOptimizationBase:: 356 operator<<(StringRef S) { 357 Args.emplace_back(S); 358 return *this; 359 } 360 361 DiagnosticInfoOptimizationBase &DiagnosticInfoOptimizationBase:: 362 operator<<(Argument A) { 363 Args.push_back(std::move(A)); 364 return *this; 365 } 366 367 DiagnosticInfoOptimizationBase &DiagnosticInfoOptimizationBase:: 368 operator<<(setIsVerbose V) { 369 IsVerbose = true; 370 return *this; 371 } 372 373 DiagnosticInfoOptimizationBase &DiagnosticInfoOptimizationBase:: 374 operator<<(setExtraArgs EA) { 375 FirstExtraArgIndex = Args.size(); 376 return *this; 377 } 378 379 std::string DiagnosticInfoOptimizationBase::getMsg() const { 380 std::string Str; 381 raw_string_ostream OS(Str); 382 for (const DiagnosticInfoOptimizationBase::Argument &Arg : 383 make_range(Args.begin(), FirstExtraArgIndex == -1 384 ? Args.end() 385 : Args.begin() + FirstExtraArgIndex)) 386 OS << Arg.Val; 387 return OS.str(); 388 } 389