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 } 185 186 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, const Type *T) 187 : Key(std::string(Key)) { 188 raw_string_ostream OS(Val); 189 OS << *T; 190 } 191 192 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, StringRef S) 193 : Key(std::string(Key)), Val(S.str()) {} 194 195 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, int N) 196 : Key(std::string(Key)), Val(itostr(N)) {} 197 198 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, float N) 199 : Key(std::string(Key)), Val(llvm::to_string(N)) {} 200 201 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, long N) 202 : Key(std::string(Key)), Val(itostr(N)) {} 203 204 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, long long N) 205 : Key(std::string(Key)), Val(itostr(N)) {} 206 207 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, unsigned N) 208 : Key(std::string(Key)), Val(utostr(N)) {} 209 210 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, 211 unsigned long N) 212 : Key(std::string(Key)), Val(utostr(N)) {} 213 214 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, 215 unsigned long long N) 216 : Key(std::string(Key)), Val(utostr(N)) {} 217 218 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, 219 ElementCount EC) 220 : Key(std::string(Key)) { 221 raw_string_ostream OS(Val); 222 EC.print(OS); 223 } 224 225 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, 226 InstructionCost C) 227 : Key(std::string(Key)) { 228 raw_string_ostream OS(Val); 229 C.print(OS); 230 } 231 232 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, DebugLoc Loc) 233 : Key(std::string(Key)), Loc(Loc) { 234 if (Loc) { 235 Val = (Loc->getFilename() + ":" + Twine(Loc.getLine()) + ":" + 236 Twine(Loc.getCol())).str(); 237 } else { 238 Val = "<UNKNOWN LOCATION>"; 239 } 240 } 241 242 void DiagnosticInfoOptimizationBase::print(DiagnosticPrinter &DP) const { 243 DP << getLocationStr() << ": " << getMsg(); 244 if (Hotness) 245 DP << " (hotness: " << *Hotness << ")"; 246 } 247 248 OptimizationRemark::OptimizationRemark(const char *PassName, 249 StringRef RemarkName, 250 const DiagnosticLocation &Loc, 251 const Value *CodeRegion) 252 : DiagnosticInfoIROptimization( 253 DK_OptimizationRemark, DS_Remark, PassName, RemarkName, 254 *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {} 255 256 OptimizationRemark::OptimizationRemark(const char *PassName, 257 StringRef RemarkName, 258 const Instruction *Inst) 259 : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName, 260 RemarkName, *Inst->getParent()->getParent(), 261 Inst->getDebugLoc(), Inst->getParent()) {} 262 263 static const BasicBlock *getFirstFunctionBlock(const Function *Func) { 264 return Func->empty() ? nullptr : &Func->front(); 265 } 266 267 OptimizationRemark::OptimizationRemark(const char *PassName, 268 StringRef RemarkName, 269 const Function *Func) 270 : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName, 271 RemarkName, *Func, Func->getSubprogram(), 272 getFirstFunctionBlock(Func)) {} 273 274 bool OptimizationRemark::isEnabled() const { 275 const Function &Fn = getFunction(); 276 LLVMContext &Ctx = Fn.getContext(); 277 return Ctx.getDiagHandlerPtr()->isPassedOptRemarkEnabled(getPassName()); 278 } 279 280 OptimizationRemarkMissed::OptimizationRemarkMissed( 281 const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc, 282 const Value *CodeRegion) 283 : DiagnosticInfoIROptimization( 284 DK_OptimizationRemarkMissed, DS_Remark, PassName, RemarkName, 285 *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {} 286 287 OptimizationRemarkMissed::OptimizationRemarkMissed(const char *PassName, 288 StringRef RemarkName, 289 const Instruction *Inst) 290 : DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark, 291 PassName, RemarkName, 292 *Inst->getParent()->getParent(), 293 Inst->getDebugLoc(), Inst->getParent()) {} 294 295 OptimizationRemarkMissed::OptimizationRemarkMissed(const char *PassName, 296 StringRef RemarkName, 297 const Function *Func) 298 : DiagnosticInfoIROptimization( 299 DK_OptimizationRemarkMissed, DS_Remark, PassName, RemarkName, *Func, 300 Func->getSubprogram(), getFirstFunctionBlock(Func)) {} 301 302 bool OptimizationRemarkMissed::isEnabled() const { 303 const Function &Fn = getFunction(); 304 LLVMContext &Ctx = Fn.getContext(); 305 return Ctx.getDiagHandlerPtr()->isMissedOptRemarkEnabled(getPassName()); 306 } 307 308 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis( 309 const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc, 310 const Value *CodeRegion) 311 : DiagnosticInfoIROptimization( 312 DK_OptimizationRemarkAnalysis, DS_Remark, PassName, RemarkName, 313 *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {} 314 315 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(const char *PassName, 316 StringRef RemarkName, 317 const Instruction *Inst) 318 : DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark, 319 PassName, RemarkName, 320 *Inst->getParent()->getParent(), 321 Inst->getDebugLoc(), Inst->getParent()) {} 322 323 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis( 324 enum DiagnosticKind Kind, const char *PassName, StringRef RemarkName, 325 const DiagnosticLocation &Loc, const Value *CodeRegion) 326 : DiagnosticInfoIROptimization(Kind, DS_Remark, PassName, RemarkName, 327 *cast<BasicBlock>(CodeRegion)->getParent(), 328 Loc, CodeRegion) {} 329 330 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(const char *PassName, 331 StringRef RemarkName, 332 const Function *Func) 333 : DiagnosticInfoIROptimization( 334 DK_OptimizationRemarkAnalysis, DS_Remark, PassName, RemarkName, *Func, 335 Func->getSubprogram(), getFirstFunctionBlock(Func)) {} 336 337 bool OptimizationRemarkAnalysis::isEnabled() const { 338 const Function &Fn = getFunction(); 339 LLVMContext &Ctx = Fn.getContext(); 340 return Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(getPassName()) || 341 shouldAlwaysPrint(); 342 } 343 344 void DiagnosticInfoMIRParser::print(DiagnosticPrinter &DP) const { 345 DP << Diagnostic; 346 } 347 348 void DiagnosticInfoSrcMgr::print(DiagnosticPrinter &DP) const { 349 DP << Diagnostic; 350 } 351 352 DiagnosticInfoOptimizationFailure::DiagnosticInfoOptimizationFailure( 353 const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc, 354 const Value *CodeRegion) 355 : DiagnosticInfoIROptimization( 356 DK_OptimizationFailure, DS_Warning, PassName, RemarkName, 357 *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {} 358 359 bool DiagnosticInfoOptimizationFailure::isEnabled() const { 360 // Only print warnings. 361 return getSeverity() == DS_Warning; 362 } 363 364 void DiagnosticInfoUnsupported::print(DiagnosticPrinter &DP) const { 365 std::string Str; 366 raw_string_ostream OS(Str); 367 368 OS << getLocationStr() << ": in function " << getFunction().getName() << ' ' 369 << *getFunction().getFunctionType() << ": " << Msg << '\n'; 370 OS.flush(); 371 DP << Str; 372 } 373 374 void DiagnosticInfoISelFallback::print(DiagnosticPrinter &DP) const { 375 DP << "Instruction selection used fallback path for " << getFunction(); 376 } 377 378 void DiagnosticInfoOptimizationBase::insert(StringRef S) { 379 Args.emplace_back(S); 380 } 381 382 void DiagnosticInfoOptimizationBase::insert(Argument A) { 383 Args.push_back(std::move(A)); 384 } 385 386 void DiagnosticInfoOptimizationBase::insert(setIsVerbose V) { 387 IsVerbose = true; 388 } 389 390 void DiagnosticInfoOptimizationBase::insert(setExtraArgs EA) { 391 FirstExtraArgIndex = Args.size(); 392 } 393 394 std::string DiagnosticInfoOptimizationBase::getMsg() const { 395 std::string Str; 396 raw_string_ostream OS(Str); 397 for (const DiagnosticInfoOptimizationBase::Argument &Arg : 398 make_range(Args.begin(), FirstExtraArgIndex == -1 399 ? Args.end() 400 : Args.begin() + FirstExtraArgIndex)) 401 OS << Arg.Val; 402 return OS.str(); 403 } 404 405 DiagnosticInfoMisExpect::DiagnosticInfoMisExpect(const Instruction *Inst, 406 Twine &Msg) 407 : DiagnosticInfoWithLocationBase(DK_MisExpect, DS_Warning, 408 *Inst->getParent()->getParent(), 409 Inst->getDebugLoc()), 410 Msg(Msg) {} 411 412 void DiagnosticInfoMisExpect::print(DiagnosticPrinter &DP) const { 413 DP << getLocationStr() << ": " << getMsg(); 414 } 415 416 void OptimizationRemarkAnalysisFPCommute::anchor() {} 417 void OptimizationRemarkAnalysisAliasing::anchor() {} 418 419 void llvm::diagnoseDontCall(const CallInst &CI) { 420 const auto *F = 421 dyn_cast<Function>(CI.getCalledOperand()->stripPointerCasts()); 422 423 if (!F) 424 return; 425 426 for (int i = 0; i != 2; ++i) { 427 auto AttrName = i == 0 ? "dontcall-error" : "dontcall-warn"; 428 auto Sev = i == 0 ? DS_Error : DS_Warning; 429 430 if (F->hasFnAttribute(AttrName)) { 431 unsigned LocCookie = 0; 432 auto A = F->getFnAttribute(AttrName); 433 if (MDNode *MD = CI.getMetadata("srcloc")) 434 LocCookie = 435 mdconst::extract<ConstantInt>(MD->getOperand(0))->getZExtValue(); 436 DiagnosticInfoDontCall D(F->getName(), A.getValueAsString(), Sev, 437 LocCookie); 438 F->getContext().diagnose(D); 439 } 440 } 441 } 442 443 void DiagnosticInfoDontCall::print(DiagnosticPrinter &DP) const { 444 DP << "call to " << demangle(getFunctionName()) << " marked \"dontcall-"; 445 if (getSeverity() == DiagnosticSeverity::DS_Error) 446 DP << "error\""; 447 else 448 DP << "warn\""; 449 if (!getNote().empty()) 450 DP << ": " << getNote(); 451 } 452