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