1 //===- llvm/IR/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 "llvm/ADT/StringExtras.h" 16 #include "llvm/ADT/Twine.h" 17 #include "llvm/ADT/iterator_range.h" 18 #include "llvm/Demangle/Demangle.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/Instructions.h" 28 #include "llvm/IR/LLVMContext.h" 29 #include "llvm/IR/Metadata.h" 30 #include "llvm/IR/Module.h" 31 #include "llvm/IR/Type.h" 32 #include "llvm/IR/Value.h" 33 #include "llvm/Support/Casting.h" 34 #include "llvm/Support/ErrorHandling.h" 35 #include "llvm/Support/InstructionCost.h" 36 #include "llvm/Support/Path.h" 37 #include "llvm/Support/ScopedPrinter.h" 38 #include "llvm/Support/raw_ostream.h" 39 #include <atomic> 40 #include <string> 41 42 using namespace llvm; 43 44 int llvm::getNextAvailablePluginDiagnosticKind() { 45 static std::atomic<int> PluginKindID(DK_FirstPluginKind); 46 return ++PluginKindID; 47 } 48 49 const char *OptimizationRemarkAnalysis::AlwaysPrint = ""; 50 51 void DiagnosticInfoGeneric::print(DiagnosticPrinter &DP) const { 52 DP << getMsgStr(); 53 } 54 55 void DiagnosticInfoGenericWithLoc::print(DiagnosticPrinter &DP) const { 56 DP << getLocationStr() << ": " << getMsgStr(); 57 } 58 59 DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(uint64_t LocCookie, 60 const Twine &MsgStr, 61 DiagnosticSeverity Severity) 62 : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(LocCookie), 63 MsgStr(MsgStr) {} 64 65 DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(const Instruction &I, 66 const Twine &MsgStr, 67 DiagnosticSeverity Severity) 68 : DiagnosticInfo(DK_InlineAsm, Severity), MsgStr(MsgStr), Instr(&I) { 69 if (const MDNode *SrcLoc = I.getMetadata("srcloc")) { 70 if (SrcLoc->getNumOperands() != 0) 71 if (const auto *CI = 72 mdconst::dyn_extract<ConstantInt>(SrcLoc->getOperand(0))) 73 LocCookie = CI->getZExtValue(); 74 } 75 } 76 77 void DiagnosticInfoInlineAsm::print(DiagnosticPrinter &DP) const { 78 DP << getMsgStr(); 79 if (getLocCookie()) 80 DP << " at line " << getLocCookie(); 81 } 82 83 DiagnosticInfoRegAllocFailure::DiagnosticInfoRegAllocFailure( 84 const Twine &MsgStr, const Function &Fn, const DiagnosticLocation &DL, 85 DiagnosticSeverity Severity) 86 : DiagnosticInfoWithLocationBase(DK_RegAllocFailure, Severity, Fn, 87 DL.isValid() ? DL : Fn.getSubprogram()), 88 MsgStr(MsgStr) {} 89 90 DiagnosticInfoRegAllocFailure::DiagnosticInfoRegAllocFailure( 91 const Twine &MsgStr, const Function &Fn, DiagnosticSeverity Severity) 92 : DiagnosticInfoWithLocationBase(DK_RegAllocFailure, Severity, Fn, 93 Fn.getSubprogram()), 94 MsgStr(MsgStr) {} 95 96 void DiagnosticInfoRegAllocFailure::print(DiagnosticPrinter &DP) const { 97 DP << getLocationStr() << ": " << MsgStr << " in function '" << getFunction() 98 << '\''; 99 } 100 101 DiagnosticInfoResourceLimit::DiagnosticInfoResourceLimit( 102 const Function &Fn, const char *ResourceName, uint64_t ResourceSize, 103 uint64_t ResourceLimit, DiagnosticSeverity Severity, DiagnosticKind Kind) 104 : DiagnosticInfoWithLocationBase(Kind, Severity, Fn, Fn.getSubprogram()), 105 Fn(Fn), ResourceName(ResourceName), ResourceSize(ResourceSize), 106 ResourceLimit(ResourceLimit) {} 107 108 void DiagnosticInfoResourceLimit::print(DiagnosticPrinter &DP) const { 109 DP << getLocationStr() << ": " << getResourceName() << " (" 110 << getResourceSize() << ") exceeds limit (" << getResourceLimit() 111 << ") in function '" << getFunction() << '\''; 112 } 113 114 void DiagnosticInfoDebugMetadataVersion::print(DiagnosticPrinter &DP) const { 115 DP << "ignoring debug info with an invalid version (" << getMetadataVersion() 116 << ") in " << getModule(); 117 } 118 119 void DiagnosticInfoIgnoringInvalidDebugMetadata::print( 120 DiagnosticPrinter &DP) const { 121 DP << "ignoring invalid debug info in " << getModule().getModuleIdentifier(); 122 } 123 124 void DiagnosticInfoSampleProfile::print(DiagnosticPrinter &DP) const { 125 if (!FileName.empty()) { 126 DP << getFileName(); 127 if (LineNum > 0) 128 DP << ":" << getLineNum(); 129 DP << ": "; 130 } 131 DP << getMsg(); 132 } 133 134 void DiagnosticInfoPGOProfile::print(DiagnosticPrinter &DP) const { 135 if (getFileName()) 136 DP << getFileName() << ": "; 137 DP << getMsg(); 138 } 139 140 void DiagnosticInfo::anchor() {} 141 void DiagnosticInfoStackSize::anchor() {} 142 void DiagnosticInfoWithLocationBase::anchor() {} 143 void DiagnosticInfoIROptimization::anchor() {} 144 145 DiagnosticLocation::DiagnosticLocation(const DebugLoc &DL) { 146 if (!DL) 147 return; 148 File = DL->getFile(); 149 Line = DL->getLine(); 150 Column = DL->getColumn(); 151 } 152 153 DiagnosticLocation::DiagnosticLocation(const DISubprogram *SP) { 154 if (!SP) 155 return; 156 157 File = SP->getFile(); 158 Line = SP->getScopeLine(); 159 Column = 0; 160 } 161 162 StringRef DiagnosticLocation::getRelativePath() const { 163 return File->getFilename(); 164 } 165 166 std::string DiagnosticLocation::getAbsolutePath() const { 167 StringRef Name = File->getFilename(); 168 if (sys::path::is_absolute(Name)) 169 return std::string(Name); 170 171 SmallString<128> Path; 172 sys::path::append(Path, File->getDirectory(), Name); 173 return sys::path::remove_leading_dotslash(Path).str(); 174 } 175 176 std::string DiagnosticInfoWithLocationBase::getAbsolutePath() const { 177 return Loc.getAbsolutePath(); 178 } 179 180 void DiagnosticInfoWithLocationBase::getLocation(StringRef &RelativePath, 181 unsigned &Line, 182 unsigned &Column) const { 183 RelativePath = Loc.getRelativePath(); 184 Line = Loc.getLine(); 185 Column = Loc.getColumn(); 186 } 187 188 std::string DiagnosticInfoWithLocationBase::getLocationStr() const { 189 StringRef Filename("<unknown>"); 190 unsigned Line = 0; 191 unsigned Column = 0; 192 if (isLocationAvailable()) 193 getLocation(Filename, Line, Column); 194 return (Filename + ":" + Twine(Line) + ":" + Twine(Column)).str(); 195 } 196 197 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, 198 const Value *V) 199 : Key(std::string(Key)) { 200 if (auto *F = dyn_cast<Function>(V)) { 201 if (DISubprogram *SP = F->getSubprogram()) 202 Loc = SP; 203 } 204 else if (auto *I = dyn_cast<Instruction>(V)) 205 Loc = I->getDebugLoc(); 206 207 // Only include names that correspond to user variables. FIXME: We should use 208 // debug info if available to get the name of the user variable. 209 if (isa<llvm::Argument>(V) || isa<GlobalValue>(V)) 210 Val = std::string(GlobalValue::dropLLVMManglingEscape(V->getName())); 211 else if (isa<Constant>(V)) { 212 raw_string_ostream OS(Val); 213 V->printAsOperand(OS, /*PrintType=*/false); 214 } else if (auto *I = dyn_cast<Instruction>(V)) { 215 Val = I->getOpcodeName(); 216 } else if (auto *MD = dyn_cast<MetadataAsValue>(V)) { 217 if (auto *S = dyn_cast<MDString>(MD->getMetadata())) 218 Val = S->getString(); 219 } 220 } 221 222 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, const Type *T) 223 : Key(std::string(Key)) { 224 raw_string_ostream OS(Val); 225 OS << *T; 226 } 227 228 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, StringRef S) 229 : Key(std::string(Key)), Val(S.str()) {} 230 231 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, int N) 232 : Key(std::string(Key)), Val(itostr(N)) {} 233 234 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, float N) 235 : Key(std::string(Key)), Val(llvm::to_string(N)) {} 236 237 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, long N) 238 : Key(std::string(Key)), Val(itostr(N)) {} 239 240 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, long long N) 241 : Key(std::string(Key)), Val(itostr(N)) {} 242 243 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, unsigned N) 244 : Key(std::string(Key)), Val(utostr(N)) {} 245 246 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, 247 unsigned long N) 248 : Key(std::string(Key)), Val(utostr(N)) {} 249 250 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, 251 unsigned long long N) 252 : Key(std::string(Key)), Val(utostr(N)) {} 253 254 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, 255 ElementCount EC) 256 : Key(std::string(Key)) { 257 raw_string_ostream OS(Val); 258 EC.print(OS); 259 } 260 261 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, 262 InstructionCost C) 263 : Key(std::string(Key)) { 264 raw_string_ostream OS(Val); 265 C.print(OS); 266 } 267 268 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, DebugLoc Loc) 269 : Key(std::string(Key)), Loc(Loc) { 270 if (Loc) { 271 Val = (Loc->getFilename() + ":" + Twine(Loc.getLine()) + ":" + 272 Twine(Loc.getCol())).str(); 273 } else { 274 Val = "<UNKNOWN LOCATION>"; 275 } 276 } 277 278 void DiagnosticInfoOptimizationBase::print(DiagnosticPrinter &DP) const { 279 DP << getLocationStr() << ": " << getMsg(); 280 if (Hotness) 281 DP << " (hotness: " << *Hotness << ")"; 282 } 283 284 OptimizationRemark::OptimizationRemark(const char *PassName, 285 StringRef RemarkName, 286 const DiagnosticLocation &Loc, 287 const Value *CodeRegion) 288 : DiagnosticInfoIROptimization( 289 DK_OptimizationRemark, DS_Remark, PassName, RemarkName, 290 *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {} 291 292 OptimizationRemark::OptimizationRemark(const char *PassName, 293 StringRef RemarkName, 294 const Instruction *Inst) 295 : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName, 296 RemarkName, *Inst->getParent()->getParent(), 297 Inst->getDebugLoc(), Inst->getParent()) {} 298 299 static const BasicBlock *getFirstFunctionBlock(const Function *Func) { 300 return Func->empty() ? nullptr : &Func->front(); 301 } 302 303 OptimizationRemark::OptimizationRemark(const char *PassName, 304 StringRef RemarkName, 305 const Function *Func) 306 : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName, 307 RemarkName, *Func, Func->getSubprogram(), 308 getFirstFunctionBlock(Func)) {} 309 310 bool OptimizationRemark::isEnabled() const { 311 const Function &Fn = getFunction(); 312 LLVMContext &Ctx = Fn.getContext(); 313 return Ctx.getDiagHandlerPtr()->isPassedOptRemarkEnabled(getPassName()); 314 } 315 316 OptimizationRemarkMissed::OptimizationRemarkMissed( 317 const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc, 318 const Value *CodeRegion) 319 : DiagnosticInfoIROptimization( 320 DK_OptimizationRemarkMissed, DS_Remark, PassName, RemarkName, 321 *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {} 322 323 OptimizationRemarkMissed::OptimizationRemarkMissed(const char *PassName, 324 StringRef RemarkName, 325 const Instruction *Inst) 326 : DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark, 327 PassName, RemarkName, 328 *Inst->getParent()->getParent(), 329 Inst->getDebugLoc(), Inst->getParent()) {} 330 331 OptimizationRemarkMissed::OptimizationRemarkMissed(const char *PassName, 332 StringRef RemarkName, 333 const Function *Func) 334 : DiagnosticInfoIROptimization( 335 DK_OptimizationRemarkMissed, DS_Remark, PassName, RemarkName, *Func, 336 Func->getSubprogram(), getFirstFunctionBlock(Func)) {} 337 338 bool OptimizationRemarkMissed::isEnabled() const { 339 const Function &Fn = getFunction(); 340 LLVMContext &Ctx = Fn.getContext(); 341 return Ctx.getDiagHandlerPtr()->isMissedOptRemarkEnabled(getPassName()); 342 } 343 344 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis( 345 const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc, 346 const Value *CodeRegion) 347 : DiagnosticInfoIROptimization( 348 DK_OptimizationRemarkAnalysis, DS_Remark, PassName, RemarkName, 349 *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {} 350 351 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(const char *PassName, 352 StringRef RemarkName, 353 const Instruction *Inst) 354 : DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark, 355 PassName, RemarkName, 356 *Inst->getParent()->getParent(), 357 Inst->getDebugLoc(), Inst->getParent()) {} 358 359 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis( 360 enum DiagnosticKind Kind, const char *PassName, StringRef RemarkName, 361 const DiagnosticLocation &Loc, const Value *CodeRegion) 362 : DiagnosticInfoIROptimization(Kind, DS_Remark, PassName, RemarkName, 363 *cast<BasicBlock>(CodeRegion)->getParent(), 364 Loc, CodeRegion) {} 365 366 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(const char *PassName, 367 StringRef RemarkName, 368 const Function *Func) 369 : DiagnosticInfoIROptimization( 370 DK_OptimizationRemarkAnalysis, DS_Remark, PassName, RemarkName, *Func, 371 Func->getSubprogram(), getFirstFunctionBlock(Func)) {} 372 373 bool OptimizationRemarkAnalysis::isEnabled() const { 374 const Function &Fn = getFunction(); 375 LLVMContext &Ctx = Fn.getContext(); 376 return Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(getPassName()) || 377 shouldAlwaysPrint(); 378 } 379 380 void DiagnosticInfoMIRParser::print(DiagnosticPrinter &DP) const { 381 DP << Diagnostic; 382 } 383 384 void DiagnosticInfoSrcMgr::print(DiagnosticPrinter &DP) const { 385 DP << Diagnostic; 386 } 387 388 DiagnosticInfoOptimizationFailure::DiagnosticInfoOptimizationFailure( 389 const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc, 390 const Value *CodeRegion) 391 : DiagnosticInfoIROptimization( 392 DK_OptimizationFailure, DS_Warning, PassName, RemarkName, 393 *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {} 394 395 bool DiagnosticInfoOptimizationFailure::isEnabled() const { 396 // Only print warnings. 397 return getSeverity() == DS_Warning; 398 } 399 400 void DiagnosticInfoUnsupported::print(DiagnosticPrinter &DP) const { 401 std::string Str; 402 raw_string_ostream OS(Str); 403 404 OS << getLocationStr() << ": in function " << getFunction().getName() << ' ' 405 << *getFunction().getFunctionType() << ": " << Msg << '\n'; 406 OS.flush(); 407 DP << Str; 408 } 409 410 void DiagnosticInfoInstrumentation::print(DiagnosticPrinter &DP) const { 411 DP << Msg; 412 } 413 414 void DiagnosticInfoISelFallback::print(DiagnosticPrinter &DP) const { 415 DP << "Instruction selection used fallback path for " << getFunction(); 416 } 417 418 void DiagnosticInfoOptimizationBase::insert(StringRef S) { 419 Args.emplace_back(S); 420 } 421 422 void DiagnosticInfoOptimizationBase::insert(Argument A) { 423 Args.push_back(std::move(A)); 424 } 425 426 void DiagnosticInfoOptimizationBase::insert(setIsVerbose V) { 427 IsVerbose = true; 428 } 429 430 void DiagnosticInfoOptimizationBase::insert(setExtraArgs EA) { 431 FirstExtraArgIndex = Args.size(); 432 } 433 434 std::string DiagnosticInfoOptimizationBase::getMsg() const { 435 std::string Str; 436 raw_string_ostream OS(Str); 437 for (const DiagnosticInfoOptimizationBase::Argument &Arg : 438 make_range(Args.begin(), FirstExtraArgIndex == -1 439 ? Args.end() 440 : Args.begin() + FirstExtraArgIndex)) 441 OS << Arg.Val; 442 return Str; 443 } 444 445 DiagnosticInfoMisExpect::DiagnosticInfoMisExpect(const Instruction *Inst, 446 Twine &Msg) 447 : DiagnosticInfoWithLocationBase(DK_MisExpect, DS_Warning, 448 *Inst->getParent()->getParent(), 449 Inst->getDebugLoc()), 450 Msg(Msg) {} 451 452 void DiagnosticInfoMisExpect::print(DiagnosticPrinter &DP) const { 453 DP << getLocationStr() << ": " << getMsg(); 454 } 455 456 void OptimizationRemarkAnalysisFPCommute::anchor() {} 457 void OptimizationRemarkAnalysisAliasing::anchor() {} 458 459 void llvm::diagnoseDontCall(const CallInst &CI) { 460 const auto *F = 461 dyn_cast<Function>(CI.getCalledOperand()->stripPointerCasts()); 462 463 if (!F) 464 return; 465 466 for (int i = 0; i != 2; ++i) { 467 auto AttrName = i == 0 ? "dontcall-error" : "dontcall-warn"; 468 auto Sev = i == 0 ? DS_Error : DS_Warning; 469 470 if (F->hasFnAttribute(AttrName)) { 471 uint64_t LocCookie = 0; 472 auto A = F->getFnAttribute(AttrName); 473 if (MDNode *MD = CI.getMetadata("srcloc")) 474 LocCookie = 475 mdconst::extract<ConstantInt>(MD->getOperand(0))->getZExtValue(); 476 DiagnosticInfoDontCall D(F->getName(), A.getValueAsString(), Sev, 477 LocCookie); 478 F->getContext().diagnose(D); 479 } 480 } 481 } 482 483 void DiagnosticInfoDontCall::print(DiagnosticPrinter &DP) const { 484 DP << "call to " << demangle(getFunctionName()) << " marked \"dontcall-"; 485 if (getSeverity() == DiagnosticSeverity::DS_Error) 486 DP << "error\""; 487 else 488 DP << "warn\""; 489 if (!getNote().empty()) 490 DP << ": " << getNote(); 491 } 492