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