1 //===- llvm/Support/DiagnosticInfo.cpp - Diagnostic Definitions -*- C++ -*-===// 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 // This file defines the different classes involved in low level diagnostics. 10 // 11 // Diagnostics reporting is still done as part of the LLVMContext. 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/IR/DiagnosticInfo.h" 15 #include "LLVMContextImpl.h" 16 #include "llvm/ADT/StringExtras.h" 17 #include "llvm/ADT/Twine.h" 18 #include "llvm/ADT/iterator_range.h" 19 #include "llvm/IR/BasicBlock.h" 20 #include "llvm/IR/Constants.h" 21 #include "llvm/IR/DebugInfoMetadata.h" 22 #include "llvm/IR/DerivedTypes.h" 23 #include "llvm/IR/DiagnosticPrinter.h" 24 #include "llvm/IR/Function.h" 25 #include "llvm/IR/GlobalValue.h" 26 #include "llvm/IR/Instruction.h" 27 #include "llvm/IR/LLVMContext.h" 28 #include "llvm/IR/Metadata.h" 29 #include "llvm/IR/Module.h" 30 #include "llvm/IR/Type.h" 31 #include "llvm/IR/Value.h" 32 #include "llvm/Support/Casting.h" 33 #include "llvm/Support/CommandLine.h" 34 #include "llvm/Support/ErrorHandling.h" 35 #include "llvm/Support/InstructionCost.h" 36 #include "llvm/Support/Path.h" 37 #include "llvm/Support/Regex.h" 38 #include "llvm/Support/ScopedPrinter.h" 39 #include "llvm/Support/raw_ostream.h" 40 #include <atomic> 41 #include <cassert> 42 #include <memory> 43 #include <string> 44 45 using namespace llvm; 46 47 int llvm::getNextAvailablePluginDiagnosticKind() { 48 static std::atomic<int> PluginKindID(DK_FirstPluginKind); 49 return ++PluginKindID; 50 } 51 52 const char *OptimizationRemarkAnalysis::AlwaysPrint = ""; 53 54 DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(const Instruction &I, 55 const Twine &MsgStr, 56 DiagnosticSeverity Severity) 57 : DiagnosticInfo(DK_InlineAsm, Severity), MsgStr(MsgStr), Instr(&I) { 58 if (const MDNode *SrcLoc = I.getMetadata("srcloc")) { 59 if (SrcLoc->getNumOperands() != 0) 60 if (const auto *CI = 61 mdconst::dyn_extract<ConstantInt>(SrcLoc->getOperand(0))) 62 LocCookie = CI->getZExtValue(); 63 } 64 } 65 66 void DiagnosticInfoInlineAsm::print(DiagnosticPrinter &DP) const { 67 DP << getMsgStr(); 68 if (getLocCookie()) 69 DP << " at line " << getLocCookie(); 70 } 71 72 void DiagnosticInfoResourceLimit::print(DiagnosticPrinter &DP) const { 73 DP << getResourceName() << " (" << getResourceSize() << ") exceeds limit"; 74 if (getResourceLimit() != 0) 75 DP << " (" << getResourceLimit() << ')'; 76 DP << " in function '" << getFunction() << '\''; 77 } 78 79 void DiagnosticInfoDebugMetadataVersion::print(DiagnosticPrinter &DP) const { 80 DP << "ignoring debug info with an invalid version (" << getMetadataVersion() 81 << ") in " << getModule(); 82 } 83 84 void DiagnosticInfoIgnoringInvalidDebugMetadata::print( 85 DiagnosticPrinter &DP) const { 86 DP << "ignoring invalid debug info in " << getModule().getModuleIdentifier(); 87 } 88 89 void DiagnosticInfoSampleProfile::print(DiagnosticPrinter &DP) const { 90 if (!FileName.empty()) { 91 DP << getFileName(); 92 if (LineNum > 0) 93 DP << ":" << getLineNum(); 94 DP << ": "; 95 } 96 DP << getMsg(); 97 } 98 99 void DiagnosticInfoPGOProfile::print(DiagnosticPrinter &DP) const { 100 if (getFileName()) 101 DP << getFileName() << ": "; 102 DP << getMsg(); 103 } 104 105 void DiagnosticInfo::anchor() {} 106 void DiagnosticInfoStackSize::anchor() {} 107 void DiagnosticInfoWithLocationBase::anchor() {} 108 void DiagnosticInfoIROptimization::anchor() {} 109 110 DiagnosticLocation::DiagnosticLocation(const DebugLoc &DL) { 111 if (!DL) 112 return; 113 File = DL->getFile(); 114 Line = DL->getLine(); 115 Column = DL->getColumn(); 116 } 117 118 DiagnosticLocation::DiagnosticLocation(const DISubprogram *SP) { 119 if (!SP) 120 return; 121 122 File = SP->getFile(); 123 Line = SP->getScopeLine(); 124 Column = 0; 125 } 126 127 StringRef DiagnosticLocation::getRelativePath() const { 128 return File->getFilename(); 129 } 130 131 std::string DiagnosticLocation::getAbsolutePath() const { 132 StringRef Name = File->getFilename(); 133 if (sys::path::is_absolute(Name)) 134 return std::string(Name); 135 136 SmallString<128> Path; 137 sys::path::append(Path, File->getDirectory(), Name); 138 return sys::path::remove_leading_dotslash(Path).str(); 139 } 140 141 std::string DiagnosticInfoWithLocationBase::getAbsolutePath() const { 142 return Loc.getAbsolutePath(); 143 } 144 145 void DiagnosticInfoWithLocationBase::getLocation(StringRef &RelativePath, 146 unsigned &Line, 147 unsigned &Column) const { 148 RelativePath = Loc.getRelativePath(); 149 Line = Loc.getLine(); 150 Column = Loc.getColumn(); 151 } 152 153 std::string DiagnosticInfoWithLocationBase::getLocationStr() const { 154 StringRef Filename("<unknown>"); 155 unsigned Line = 0; 156 unsigned Column = 0; 157 if (isLocationAvailable()) 158 getLocation(Filename, Line, Column); 159 return (Filename + ":" + Twine(Line) + ":" + Twine(Column)).str(); 160 } 161 162 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, 163 const Value *V) 164 : Key(std::string(Key)) { 165 if (auto *F = dyn_cast<Function>(V)) { 166 if (DISubprogram *SP = F->getSubprogram()) 167 Loc = SP; 168 } 169 else if (auto *I = dyn_cast<Instruction>(V)) 170 Loc = I->getDebugLoc(); 171 172 // Only include names that correspond to user variables. FIXME: We should use 173 // debug info if available to get the name of the user variable. 174 if (isa<llvm::Argument>(V) || isa<GlobalValue>(V)) 175 Val = std::string(GlobalValue::dropLLVMManglingEscape(V->getName())); 176 else if (isa<Constant>(V)) { 177 raw_string_ostream OS(Val); 178 V->printAsOperand(OS, /*PrintType=*/false); 179 } else if (auto *I = dyn_cast<Instruction>(V)) 180 Val = I->getOpcodeName(); 181 } 182 183 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, const Type *T) 184 : Key(std::string(Key)) { 185 raw_string_ostream OS(Val); 186 OS << *T; 187 } 188 189 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, StringRef S) 190 : Key(std::string(Key)), Val(S.str()) {} 191 192 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, int N) 193 : Key(std::string(Key)), Val(itostr(N)) {} 194 195 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, float N) 196 : Key(std::string(Key)), Val(llvm::to_string(N)) {} 197 198 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, long N) 199 : Key(std::string(Key)), Val(itostr(N)) {} 200 201 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, long long N) 202 : Key(std::string(Key)), Val(itostr(N)) {} 203 204 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, unsigned N) 205 : Key(std::string(Key)), Val(utostr(N)) {} 206 207 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, 208 unsigned long N) 209 : Key(std::string(Key)), Val(utostr(N)) {} 210 211 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, 212 unsigned long long N) 213 : Key(std::string(Key)), Val(utostr(N)) {} 214 215 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, 216 ElementCount EC) 217 : Key(std::string(Key)) { 218 raw_string_ostream OS(Val); 219 EC.print(OS); 220 } 221 222 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, 223 InstructionCost C) 224 : Key(std::string(Key)) { 225 raw_string_ostream OS(Val); 226 C.print(OS); 227 } 228 229 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, DebugLoc Loc) 230 : Key(std::string(Key)), Loc(Loc) { 231 if (Loc) { 232 Val = (Loc->getFilename() + ":" + Twine(Loc.getLine()) + ":" + 233 Twine(Loc.getCol())).str(); 234 } else { 235 Val = "<UNKNOWN LOCATION>"; 236 } 237 } 238 239 void DiagnosticInfoOptimizationBase::print(DiagnosticPrinter &DP) const { 240 DP << getLocationStr() << ": " << getMsg(); 241 if (Hotness) 242 DP << " (hotness: " << *Hotness << ")"; 243 } 244 245 OptimizationRemark::OptimizationRemark(const char *PassName, 246 StringRef RemarkName, 247 const DiagnosticLocation &Loc, 248 const Value *CodeRegion) 249 : DiagnosticInfoIROptimization( 250 DK_OptimizationRemark, DS_Remark, PassName, RemarkName, 251 *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {} 252 253 OptimizationRemark::OptimizationRemark(const char *PassName, 254 StringRef RemarkName, 255 const Instruction *Inst) 256 : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName, 257 RemarkName, *Inst->getParent()->getParent(), 258 Inst->getDebugLoc(), Inst->getParent()) {} 259 260 static const BasicBlock *getFirstFunctionBlock(const Function *Func) { 261 return Func->empty() ? nullptr : &Func->front(); 262 } 263 264 OptimizationRemark::OptimizationRemark(const char *PassName, 265 StringRef RemarkName, 266 const Function *Func) 267 : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName, 268 RemarkName, *Func, Func->getSubprogram(), 269 getFirstFunctionBlock(Func)) {} 270 271 bool OptimizationRemark::isEnabled() const { 272 const Function &Fn = getFunction(); 273 LLVMContext &Ctx = Fn.getContext(); 274 return Ctx.getDiagHandlerPtr()->isPassedOptRemarkEnabled(getPassName()); 275 } 276 277 OptimizationRemarkMissed::OptimizationRemarkMissed( 278 const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc, 279 const Value *CodeRegion) 280 : DiagnosticInfoIROptimization( 281 DK_OptimizationRemarkMissed, DS_Remark, PassName, RemarkName, 282 *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {} 283 284 OptimizationRemarkMissed::OptimizationRemarkMissed(const char *PassName, 285 StringRef RemarkName, 286 const Instruction *Inst) 287 : DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark, 288 PassName, RemarkName, 289 *Inst->getParent()->getParent(), 290 Inst->getDebugLoc(), Inst->getParent()) {} 291 292 OptimizationRemarkMissed::OptimizationRemarkMissed(const char *PassName, 293 StringRef RemarkName, 294 const Function *Func) 295 : DiagnosticInfoIROptimization( 296 DK_OptimizationRemarkMissed, DS_Remark, PassName, RemarkName, *Func, 297 Func->getSubprogram(), getFirstFunctionBlock(Func)) {} 298 299 bool OptimizationRemarkMissed::isEnabled() const { 300 const Function &Fn = getFunction(); 301 LLVMContext &Ctx = Fn.getContext(); 302 return Ctx.getDiagHandlerPtr()->isMissedOptRemarkEnabled(getPassName()); 303 } 304 305 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis( 306 const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc, 307 const Value *CodeRegion) 308 : DiagnosticInfoIROptimization( 309 DK_OptimizationRemarkAnalysis, DS_Remark, PassName, RemarkName, 310 *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {} 311 312 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(const char *PassName, 313 StringRef RemarkName, 314 const Instruction *Inst) 315 : DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark, 316 PassName, RemarkName, 317 *Inst->getParent()->getParent(), 318 Inst->getDebugLoc(), Inst->getParent()) {} 319 320 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis( 321 enum DiagnosticKind Kind, const char *PassName, StringRef RemarkName, 322 const DiagnosticLocation &Loc, const Value *CodeRegion) 323 : DiagnosticInfoIROptimization(Kind, DS_Remark, PassName, RemarkName, 324 *cast<BasicBlock>(CodeRegion)->getParent(), 325 Loc, CodeRegion) {} 326 327 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(const char *PassName, 328 StringRef RemarkName, 329 const Function *Func) 330 : DiagnosticInfoIROptimization( 331 DK_OptimizationRemarkAnalysis, DS_Remark, PassName, RemarkName, *Func, 332 Func->getSubprogram(), getFirstFunctionBlock(Func)) {} 333 334 bool OptimizationRemarkAnalysis::isEnabled() const { 335 const Function &Fn = getFunction(); 336 LLVMContext &Ctx = Fn.getContext(); 337 return Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(getPassName()) || 338 shouldAlwaysPrint(); 339 } 340 341 void DiagnosticInfoMIRParser::print(DiagnosticPrinter &DP) const { 342 DP << Diagnostic; 343 } 344 345 void DiagnosticInfoSrcMgr::print(DiagnosticPrinter &DP) const { 346 DP << Diagnostic; 347 } 348 349 DiagnosticInfoOptimizationFailure::DiagnosticInfoOptimizationFailure( 350 const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc, 351 const Value *CodeRegion) 352 : DiagnosticInfoIROptimization( 353 DK_OptimizationFailure, DS_Warning, PassName, RemarkName, 354 *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {} 355 356 bool DiagnosticInfoOptimizationFailure::isEnabled() const { 357 // Only print warnings. 358 return getSeverity() == DS_Warning; 359 } 360 361 void DiagnosticInfoUnsupported::print(DiagnosticPrinter &DP) const { 362 std::string Str; 363 raw_string_ostream OS(Str); 364 365 OS << getLocationStr() << ": in function " << getFunction().getName() << ' ' 366 << *getFunction().getFunctionType() << ": " << Msg << '\n'; 367 OS.flush(); 368 DP << Str; 369 } 370 371 void DiagnosticInfoISelFallback::print(DiagnosticPrinter &DP) const { 372 DP << "Instruction selection used fallback path for " << getFunction(); 373 } 374 375 void DiagnosticInfoOptimizationBase::insert(StringRef S) { 376 Args.emplace_back(S); 377 } 378 379 void DiagnosticInfoOptimizationBase::insert(Argument A) { 380 Args.push_back(std::move(A)); 381 } 382 383 void DiagnosticInfoOptimizationBase::insert(setIsVerbose V) { 384 IsVerbose = true; 385 } 386 387 void DiagnosticInfoOptimizationBase::insert(setExtraArgs EA) { 388 FirstExtraArgIndex = Args.size(); 389 } 390 391 std::string DiagnosticInfoOptimizationBase::getMsg() const { 392 std::string Str; 393 raw_string_ostream OS(Str); 394 for (const DiagnosticInfoOptimizationBase::Argument &Arg : 395 make_range(Args.begin(), FirstExtraArgIndex == -1 396 ? Args.end() 397 : Args.begin() + FirstExtraArgIndex)) 398 OS << Arg.Val; 399 return OS.str(); 400 } 401 402 void OptimizationRemarkAnalysisFPCommute::anchor() {} 403 void OptimizationRemarkAnalysisAliasing::anchor() {} 404