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