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