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