LLVM 20.0.0git
DiagnosticInfo.cpp
Go to the documentation of this file.
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
16#include "llvm/ADT/Twine.h"
19#include "llvm/IR/BasicBlock.h"
20#include "llvm/IR/Constants.h"
24#include "llvm/IR/Function.h"
25#include "llvm/IR/GlobalValue.h"
26#include "llvm/IR/Instruction.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"
36#include "llvm/Support/Path.h"
39#include <atomic>
40#include <string>
41
42using namespace llvm;
43
45 static std::atomic<int> PluginKindID(DK_FirstPluginKind);
46 return ++PluginKindID;
47}
48
50
52 DP << getMsgStr();
53}
54
56 DP << getLocationStr() << ": " << getMsgStr();
57}
58
60 const Twine &MsgStr,
61 DiagnosticSeverity Severity)
62 : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(LocCookie),
63 MsgStr(MsgStr) {}
64
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
78 DP << getMsgStr();
79 if (getLocCookie())
80 DP << " at line " << getLocCookie();
81}
82
84 const Twine &MsgStr, const Function &Fn, const DiagnosticLocation &DL,
85 DiagnosticSeverity Severity)
87 DL.isValid() ? DL : Fn.getSubprogram()),
88 MsgStr(MsgStr) {}
89
91 const Twine &MsgStr, const Function &Fn, DiagnosticSeverity Severity)
93 Fn.getSubprogram()),
94 MsgStr(MsgStr) {}
95
97 DP << getLocationStr() << ": " << MsgStr << " in function '" << getFunction()
98 << '\'';
99}
100
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
109 DP << getLocationStr() << ": " << getResourceName() << " ("
110 << getResourceSize() << ") exceeds limit (" << getResourceLimit()
111 << ") in function '" << getFunction() << '\'';
112}
113
115 DP << "ignoring debug info with an invalid version (" << getMetadataVersion()
116 << ") in " << getModule();
117}
118
120 DiagnosticPrinter &DP) const {
121 DP << "ignoring invalid debug info in " << getModule().getModuleIdentifier();
122}
123
125 if (!FileName.empty()) {
126 DP << getFileName();
127 if (LineNum > 0)
128 DP << ":" << getLineNum();
129 DP << ": ";
130 }
131 DP << getMsg();
132}
133
135 if (getFileName())
136 DP << getFileName() << ": ";
137 DP << getMsg();
138}
139
140void DiagnosticInfo::anchor() {}
141void DiagnosticInfoStackSize::anchor() {}
142void DiagnosticInfoWithLocationBase::anchor() {}
143void DiagnosticInfoIROptimization::anchor() {}
144
146 if (!DL)
147 return;
148 File = DL->getFile();
149 Line = DL->getLine();
150 Column = DL->getColumn();
151}
152
154 if (!SP)
155 return;
156
157 File = SP->getFile();
158 Line = SP->getScopeLine();
159 Column = 0;
160}
161
163 return File->getFilename();
164}
165
167 StringRef Name = File->getFilename();
169 return std::string(Name);
170
171 SmallString<128> Path;
172 sys::path::append(Path, File->getDirectory(), Name);
174}
175
177 return Loc.getAbsolutePath();
178}
179
181 unsigned &Line,
182 unsigned &Column) const {
183 RelativePath = Loc.getRelativePath();
184 Line = Loc.getLine();
185 Column = Loc.getColumn();
186}
187
189 StringRef Filename("<unknown>");
190 unsigned Line = 0;
191 unsigned Column = 0;
193 getLocation(Filename, Line, Column);
194 return (Filename + ":" + Twine(Line) + ":" + Twine(Column)).str();
195}
196
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)) {
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
223 : Key(std::string(Key)) {
225 OS << *T;
226}
227
229 : Key(std::string(Key)), Val(S.str()) {}
230
232 : Key(std::string(Key)), Val(itostr(N)) {}
233
235 : Key(std::string(Key)), Val(llvm::to_string(N)) {}
236
238 : Key(std::string(Key)), Val(itostr(N)) {}
239
241 : Key(std::string(Key)), Val(itostr(N)) {}
242
244 : Key(std::string(Key)), Val(utostr(N)) {}
245
247 unsigned long N)
248 : Key(std::string(Key)), Val(utostr(N)) {}
249
251 unsigned long long N)
252 : Key(std::string(Key)), Val(utostr(N)) {}
253
255 ElementCount EC)
256 : Key(std::string(Key)) {
258 EC.print(OS);
259}
260
263 : Key(std::string(Key)) {
265 C.print(OS);
266}
267
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
279 DP << getLocationStr() << ": " << getMsg();
280 if (Hotness)
281 DP << " (hotness: " << *Hotness << ")";
282}
283
286 const DiagnosticLocation &Loc,
287 const Value *CodeRegion)
290 *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {}
291
293 StringRef RemarkName,
294 const Instruction *Inst)
296 RemarkName, *Inst->getParent()->getParent(),
297 Inst->getDebugLoc(), Inst->getParent()) {}
298
299static const BasicBlock *getFirstFunctionBlock(const Function *Func) {
300 return Func->empty() ? nullptr : &Func->front();
301}
302
304 StringRef RemarkName,
305 const Function *Func)
307 RemarkName, *Func, Func->getSubprogram(),
308 getFirstFunctionBlock(Func)) {}
309
311 const Function &Fn = getFunction();
312 LLVMContext &Ctx = Fn.getContext();
314}
315
317 const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc,
318 const Value *CodeRegion)
321 *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {}
322
324 StringRef RemarkName,
325 const Instruction *Inst)
327 PassName, RemarkName,
328 *Inst->getParent()->getParent(),
329 Inst->getDebugLoc(), Inst->getParent()) {}
330
332 StringRef RemarkName,
333 const Function *Func)
336 Func->getSubprogram(), getFirstFunctionBlock(Func)) {}
337
339 const Function &Fn = getFunction();
340 LLVMContext &Ctx = Fn.getContext();
342}
343
345 const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc,
346 const Value *CodeRegion)
349 *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {}
350
352 StringRef RemarkName,
353 const Instruction *Inst)
355 PassName, RemarkName,
356 *Inst->getParent()->getParent(),
357 Inst->getDebugLoc(), Inst->getParent()) {}
358
360 enum DiagnosticKind Kind, const char *PassName, StringRef RemarkName,
361 const DiagnosticLocation &Loc, const Value *CodeRegion)
363 *cast<BasicBlock>(CodeRegion)->getParent(),
364 Loc, CodeRegion) {}
365
367 StringRef RemarkName,
368 const Function *Func)
371 Func->getSubprogram(), getFirstFunctionBlock(Func)) {}
372
374 const Function &Fn = getFunction();
375 LLVMContext &Ctx = Fn.getContext();
378}
379
381 DP << Diagnostic;
382}
383
385 DP << Diagnostic;
386}
387
389 const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc,
390 const Value *CodeRegion)
393 *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {}
394
396 // Only print warnings.
397 return getSeverity() == DS_Warning;
398}
399
401 std::string Str;
403
404 OS << getLocationStr() << ": in function " << getFunction().getName() << ' '
405 << *getFunction().getFunctionType() << ": " << Msg << '\n';
406 OS.flush();
407 DP << Str;
408}
409
411 DP << Msg;
412}
413
415 DP << "Instruction selection used fallback path for " << getFunction();
416}
417
419 Args.emplace_back(S);
420}
421
423 Args.push_back(std::move(A));
424}
425
427 IsVerbose = true;
428}
429
431 FirstExtraArgIndex = Args.size();
432}
433
435 std::string Str;
438 make_range(Args.begin(), FirstExtraArgIndex == -1
439 ? Args.end()
440 : Args.begin() + FirstExtraArgIndex))
441 OS << Arg.Val;
442 return Str;
443}
444
446 Twine &Msg)
448 *Inst->getParent()->getParent(),
449 Inst->getDebugLoc()),
450 Msg(Msg) {}
451
453 DP << getLocationStr() << ": " << getMsg();
454}
455
456void OptimizationRemarkAnalysisFPCommute::anchor() {}
457void OptimizationRemarkAnalysisAliasing::anchor() {}
458
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
484 DP << "call to " << demangle(getFunctionName()) << " marked \"dontcall-";
486 DP << "error\"";
487 else
488 DP << "warn\"";
489 if (!getNote().empty())
490 DP << ": " << getNote();
491}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static const Function * getParent(const Value *V)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static DISubprogram * getSubprogram(bool IsDistinct, Ts &&...Args)
Definition: DIBuilder.cpp:852
static const BasicBlock * getFirstFunctionBlock(const Function *Func)
std::string Name
Module.h This file contains the declarations for the Module class.
This file defines an InstructionCost class that is used when calculating the cost of an instruction,...
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
Return the first found DebugLoc that has a DILocation, given a range of instructions.
This file contains the declarations for metadata subclasses.
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
raw_pwrite_stream & OS
This file contains some functions that are useful when dealing with strings.
static const char PassName[]
LLVM Basic Block Representation.
Definition: BasicBlock.h:61
Value * getCalledOperand() const
Definition: InstrTypes.h:1342
This class represents a function call, abstracting a target machine's calling convention.
StringRef getFilename() const
DIFile * getFile() const
StringRef getDirectory() const
Subprogram description.
A debug info location.
Definition: DebugLoc.h:33
void print(DiagnosticPrinter &DP) const override
StringRef getFunctionName() const
void print(DiagnosticPrinter &DP) const override
Print using the given DP a user-friendly message.
void print(DiagnosticPrinter &DP) const override
const Twine & getMsgStr() const
void print(DiagnosticPrinter &DP) const override
Common features for diagnostics dealing with optimization remarks that are used by IR passes.
const Function & getFunction() const
void print(DiagnosticPrinter &DP) const override
Print using the given DP a user-friendly message.
void print(DiagnosticPrinter &DP) const override
DiagnosticInfoInlineAsm(uint64_t LocCookie, const Twine &MsgStr, DiagnosticSeverity Severity=DS_Error)
LocCookie if non-zero gives the line number for this report.
const Twine & getMsgStr() const
void print(DiagnosticPrinter &DP) const override
void print(DiagnosticPrinter &DP) const override
Print using the given DP a user-friendly message.
void print(DiagnosticPrinter &DP) const override
Print using the given DP a user-friendly message.
const Twine & getMsg() const
void print(DiagnosticPrinter &DP) const override
DiagnosticInfoMisExpect(const Instruction *Inst, Twine &Msg)
int FirstExtraArgIndex
If positive, the index of the first argument that only appear in the optimization records and not in ...
const char * PassName
Name of the pass that triggers this report.
StringRef RemarkName
Textual identifier for the remark (single-word, camel-case).
void print(DiagnosticPrinter &DP) const override
bool IsVerbose
The remark is expected to be noisy.
std::optional< uint64_t > Hotness
If profile information is available, this is the number of times the corresponding code was executed ...
SmallVector< Argument, 4 > Args
Arguments collected via the streaming interface.
DiagnosticInfoOptimizationFailure(const Function &Fn, const DiagnosticLocation &Loc, const Twine &Msg)
Fn is the function where the diagnostic is being emitted.
const char * getFileName() const
void print(DiagnosticPrinter &DP) const override
const Twine & getMsg() const
DiagnosticInfoRegAllocFailure(const Twine &MsgStr, const Function &Fn, const DiagnosticLocation &DL, DiagnosticSeverity Severity=DS_Error)
MsgStr is the message to be reported to the frontend.
void print(DiagnosticPrinter &DP) const override
const Function & getFunction() const
void print(DiagnosticPrinter &DP) const override
const char * getResourceName() const
DiagnosticInfoResourceLimit(const Function &Fn, const char *ResourceName, uint64_t ResourceSize, uint64_t ResourceLimit, DiagnosticSeverity Severity=DS_Warning, DiagnosticKind Kind=DK_ResourceLimit)
The function that is concerned by this stack size diagnostic.
void print(DiagnosticPrinter &DP) const override
void print(DiagnosticPrinter &DP) const override
Print using the given DP a user-friendly message.
void print(DiagnosticPrinter &DP) const override
Print using the given DP a user-friendly message.
Common features for diagnostics with an associated location.
std::string getLocationStr() const
Return a string with the location information for this diagnostic in the format "file:line:col".
std::string getAbsolutePath() const
Return the absolute path tot the file.
bool isLocationAvailable() const
Return true if location information is available for this diagnostic.
const Function & getFunction() const
DiagnosticLocation getLocation() const
This is the base abstract class for diagnostic reporting in the backend.
DiagnosticSeverity getSeverity() const
unsigned getLine() const
std::string getAbsolutePath() const
Return the full path to the file.
StringRef getRelativePath() const
Return the file name relative to the compilation directory.
unsigned getColumn() const
Interface for custom diagnostic printing.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition: Function.h:216
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition: Function.cpp:369
static StringRef dropLLVMManglingEscape(StringRef Name)
If the given string begins with the GlobalValue name mangling escape character '\1',...
Definition: GlobalValue.h:567
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
Definition: Instruction.h:390
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
const DiagnosticHandler * getDiagHandlerPtr() const
getDiagHandlerPtr - Returns const raw pointer of DiagnosticHandler set by setDiagnosticHandler.
Metadata node.
Definition: Metadata.h:1069
const std::string & getModuleIdentifier() const
Get the module identifier which is, essentially, the name of the module.
Definition: Module.h:268
OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc, const Value *CodeRegion)
PassName is the name of the pass emitting this diagnostic.
OptimizationRemarkMissed(const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc, const Value *CodeRegion)
PassName is the name of the pass emitting this diagnostic.
bool isEnabled() const override
bool isEnabled() const override
OptimizationRemark(const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc, const Value *CodeRegion)
PassName is the name of the pass emitting this diagnostic.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:229
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:147
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
LLVM Value Representation.
Definition: Value.h:74
const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
Definition: Value.cpp:694
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:309
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:661
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
Definition: Path.cpp:671
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:456
StringRef remove_leading_dotslash(StringRef path, Style style=Style::native)
Remove redundant leading "./" pieces and consecutive separators.
Definition: Path.cpp:703
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
std::string to_string(const T &Value)
Definition: ScopedPrinter.h:85
void diagnoseDontCall(const CallInst &CI)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
DiagnosticKind
Defines the different supported kind of a diagnostic.
@ DK_OptimizationRemarkAnalysis
@ DK_OptimizationRemarkMissed
@ DK_OptimizationRemark
@ DK_InlineAsm
@ DK_OptimizationFailure
@ DK_MisExpect
@ DK_FirstPluginKind
@ DK_RegAllocFailure
int getNextAvailablePluginDiagnosticKind()
Get the next available kind ID for a plugin diagnostic.
DiagnosticSeverity
Defines the different supported severity of a diagnostic.
@ DS_Remark
@ DS_Warning
@ DS_Error
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition: Casting.h:565
std::string demangle(std::string_view MangledName)
Attempt to demangle a string using different demangling schemes.
Definition: Demangle.cpp:20
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
#define N
virtual bool isPassedOptRemarkEnabled(StringRef PassName) const
Return true if passed optimization remarks are enabled, override to provide different implementation.
virtual bool isAnalysisRemarkEnabled(StringRef PassName) const
Return true if analysis remarks are enabled, override to provide different implementation.
virtual bool isMissedOptRemarkEnabled(StringRef PassName) const
Return true if missed optimization remarks are enabled, override to provide different implementation.
Used in the streaming interface as the general argument type.
When an instance of this is inserted into the stream, the arguments following will not appear in the ...
Used to set IsVerbose via the stream interface.