1 //===- llvm/Support/DiagnosticInfo.cpp - Diagnostic Definitions -*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the different classes involved in low level diagnostics.
12 // Diagnostics reporting is still done as part of the LLVMContext.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/IR/DiagnosticInfo.h"
16 #include "LLVMContextImpl.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/ADT/Twine.h"
19 #include "llvm/IR/Constants.h"
20 #include "llvm/IR/DebugInfo.h"
21 #include "llvm/IR/DiagnosticPrinter.h"
22 #include "llvm/IR/Function.h"
23 #include "llvm/IR/Instruction.h"
24 #include "llvm/IR/Metadata.h"
25 #include "llvm/IR/Module.h"
26 #include "llvm/Support/CommandLine.h"
27 #include "llvm/Support/Regex.h"
35 /// \brief Regular expression corresponding to the value given in one of the
36 /// -pass-remarks* command line flags. Passes whose name matches this regexp
37 /// will emit a diagnostic when calling the associated diagnostic function
38 /// (emitOptimizationRemark, emitOptimizationRemarkMissed or
39 /// emitOptimizationRemarkAnalysis).
40 struct PassRemarksOpt {
41 std::shared_ptr<Regex> Pattern;
43 void operator=(const std::string &Val) {
44 // Create a regexp object to match pass names for emitOptimizationRemark.
46 Pattern = std::make_shared<Regex>(Val);
47 std::string RegexError;
48 if (!Pattern->isValid(RegexError))
49 report_fatal_error("Invalid regular expression '" + Val +
50 "' in -pass-remarks: " + RegexError,
56 static PassRemarksOpt PassRemarksOptLoc;
57 static PassRemarksOpt PassRemarksMissedOptLoc;
58 static PassRemarksOpt PassRemarksAnalysisOptLoc;
61 // Command line flag to enable emitOptimizationRemark()
62 static cl::opt<PassRemarksOpt, true, cl::parser<std::string>>
63 PassRemarks("pass-remarks", cl::value_desc("pattern"),
64 cl::desc("Enable optimization remarks from passes whose name match "
65 "the given regular expression"),
66 cl::Hidden, cl::location(PassRemarksOptLoc), cl::ValueRequired,
69 // -pass-remarks-missed
70 // Command line flag to enable emitOptimizationRemarkMissed()
71 static cl::opt<PassRemarksOpt, true, cl::parser<std::string>> PassRemarksMissed(
72 "pass-remarks-missed", cl::value_desc("pattern"),
73 cl::desc("Enable missed optimization remarks from passes whose name match "
74 "the given regular expression"),
75 cl::Hidden, cl::location(PassRemarksMissedOptLoc), cl::ValueRequired,
78 // -pass-remarks-analysis
79 // Command line flag to enable emitOptimizationRemarkAnalysis()
80 static cl::opt<PassRemarksOpt, true, cl::parser<std::string>>
82 "pass-remarks-analysis", cl::value_desc("pattern"),
84 "Enable optimization analysis remarks from passes whose name match "
85 "the given regular expression"),
86 cl::Hidden, cl::location(PassRemarksAnalysisOptLoc), cl::ValueRequired,
90 int llvm::getNextAvailablePluginDiagnosticKind() {
91 static std::atomic<int> PluginKindID(DK_FirstPluginKind);
92 return ++PluginKindID;
95 const char *OptimizationRemarkAnalysis::AlwaysPrint = "";
97 DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(const Instruction &I,
99 DiagnosticSeverity Severity)
100 : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(0), MsgStr(MsgStr),
102 if (const MDNode *SrcLoc = I.getMetadata("srcloc")) {
103 if (SrcLoc->getNumOperands() != 0)
105 mdconst::dyn_extract<ConstantInt>(SrcLoc->getOperand(0)))
106 LocCookie = CI->getZExtValue();
110 void DiagnosticInfoInlineAsm::print(DiagnosticPrinter &DP) const {
113 DP << " at line " << getLocCookie();
116 void DiagnosticInfoResourceLimit::print(DiagnosticPrinter &DP) const {
117 DP << getResourceName() << " limit";
119 if (getResourceLimit() != 0)
120 DP << " of " << getResourceLimit();
122 DP << " exceeded (" << getResourceSize() << ") in " << getFunction();
125 void DiagnosticInfoDebugMetadataVersion::print(DiagnosticPrinter &DP) const {
126 DP << "ignoring debug info with an invalid version (" << getMetadataVersion()
127 << ") in " << getModule();
130 void DiagnosticInfoIgnoringInvalidDebugMetadata::print(
131 DiagnosticPrinter &DP) const {
132 DP << "ignoring invalid debug info in " << getModule().getModuleIdentifier();
135 void DiagnosticInfoSampleProfile::print(DiagnosticPrinter &DP) const {
136 if (!FileName.empty()) {
139 DP << ":" << getLineNum();
145 void DiagnosticInfoPGOProfile::print(DiagnosticPrinter &DP) const {
147 DP << getFileName() << ": ";
151 DiagnosticLocation::DiagnosticLocation(const DebugLoc &DL) {
154 Filename = DL->getFilename();
155 Line = DL->getLine();
156 Column = DL->getColumn();
159 DiagnosticLocation::DiagnosticLocation(const DISubprogram *SP) {
162 Filename = SP->getFilename();
163 Line = SP->getScopeLine();
167 void DiagnosticInfoWithLocationBase::getLocation(StringRef *Filename,
169 unsigned *Column) const {
170 *Filename = Loc.getFilename();
171 *Line = Loc.getLine();
172 *Column = Loc.getColumn();
175 const std::string DiagnosticInfoWithLocationBase::getLocationStr() const {
176 StringRef Filename("<unknown>");
179 if (isLocationAvailable())
180 getLocation(&Filename, &Line, &Column);
181 return (Filename + ":" + Twine(Line) + ":" + Twine(Column)).str();
184 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, const Value *V)
186 if (auto *F = dyn_cast<Function>(V)) {
187 if (DISubprogram *SP = F->getSubprogram())
190 else if (auto *I = dyn_cast<Instruction>(V))
191 Loc = I->getDebugLoc();
193 // Only include names that correspond to user variables. FIXME: we should use
194 // debug info if available to get the name of the user variable.
195 if (isa<llvm::Argument>(V) || isa<GlobalValue>(V))
196 Val = GlobalValue::getRealLinkageName(V->getName());
197 else if (isa<Constant>(V)) {
198 raw_string_ostream OS(Val);
199 V->printAsOperand(OS, /*PrintType=*/false);
200 } else if (auto *I = dyn_cast<Instruction>(V))
201 Val = I->getOpcodeName();
204 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, const Type *T)
206 raw_string_ostream OS(Val);
210 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, int N)
211 : Key(Key), Val(itostr(N)) {}
213 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, unsigned N)
214 : Key(Key), Val(utostr(N)) {}
216 void DiagnosticInfoOptimizationBase::print(DiagnosticPrinter &DP) const {
217 DP << getLocationStr() << ": " << getMsg();
219 DP << " (hotness: " << *Hotness << ")";
222 OptimizationRemark::OptimizationRemark(const char *PassName,
223 StringRef RemarkName,
224 const DiagnosticLocation &Loc,
225 const Value *CodeRegion)
226 : DiagnosticInfoIROptimization(
227 DK_OptimizationRemark, DS_Remark, PassName, RemarkName,
228 *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {}
230 OptimizationRemark::OptimizationRemark(const char *PassName,
231 StringRef RemarkName,
232 const Instruction *Inst)
233 : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,
234 RemarkName, *Inst->getParent()->getParent(),
235 Inst->getDebugLoc(), Inst->getParent()) {}
237 // Helper to allow for an assert before attempting to return an invalid
239 static const BasicBlock &getFirstFunctionBlock(const Function *Func) {
240 assert(!Func->empty() && "Function does not have a body");
241 return Func->front();
244 OptimizationRemark::OptimizationRemark(const char *PassName,
245 StringRef RemarkName,
246 const Function *Func)
247 : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,
248 RemarkName, *Func, Func->getSubprogram(),
249 &getFirstFunctionBlock(Func)) {}
251 bool OptimizationRemark::isEnabled(StringRef PassName) {
252 return PassRemarksOptLoc.Pattern &&
253 PassRemarksOptLoc.Pattern->match(PassName);
256 OptimizationRemarkMissed::OptimizationRemarkMissed(
257 const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc,
258 const Value *CodeRegion)
259 : DiagnosticInfoIROptimization(
260 DK_OptimizationRemarkMissed, DS_Remark, PassName, RemarkName,
261 *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {}
263 OptimizationRemarkMissed::OptimizationRemarkMissed(const char *PassName,
264 StringRef RemarkName,
265 const Instruction *Inst)
266 : DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark,
267 PassName, RemarkName,
268 *Inst->getParent()->getParent(),
269 Inst->getDebugLoc(), Inst->getParent()) {}
271 bool OptimizationRemarkMissed::isEnabled(StringRef PassName) {
272 return PassRemarksMissedOptLoc.Pattern &&
273 PassRemarksMissedOptLoc.Pattern->match(PassName);
276 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(
277 const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc,
278 const Value *CodeRegion)
279 : DiagnosticInfoIROptimization(
280 DK_OptimizationRemarkAnalysis, DS_Remark, PassName, RemarkName,
281 *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {}
283 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(const char *PassName,
284 StringRef RemarkName,
285 const Instruction *Inst)
286 : DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark,
287 PassName, RemarkName,
288 *Inst->getParent()->getParent(),
289 Inst->getDebugLoc(), Inst->getParent()) {}
291 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(
292 enum DiagnosticKind Kind, const char *PassName, StringRef RemarkName,
293 const DiagnosticLocation &Loc, const Value *CodeRegion)
294 : DiagnosticInfoIROptimization(Kind, DS_Remark, PassName, RemarkName,
295 *cast<BasicBlock>(CodeRegion)->getParent(),
298 bool OptimizationRemarkAnalysis::isEnabled(StringRef PassName) {
299 return PassRemarksAnalysisOptLoc.Pattern &&
300 PassRemarksAnalysisOptLoc.Pattern->match(PassName);
303 void DiagnosticInfoMIRParser::print(DiagnosticPrinter &DP) const {
307 void llvm::emitOptimizationRemark(LLVMContext &Ctx, const char *PassName,
309 const DiagnosticLocation &Loc,
311 Ctx.diagnose(OptimizationRemark(PassName, Fn, Loc, Msg));
314 void llvm::emitOptimizationRemarkMissed(LLVMContext &Ctx, const char *PassName,
316 const DiagnosticLocation &Loc,
318 Ctx.diagnose(OptimizationRemarkMissed(PassName, Fn, Loc, Msg));
321 void llvm::emitOptimizationRemarkAnalysis(LLVMContext &Ctx,
322 const char *PassName,
324 const DiagnosticLocation &Loc,
326 Ctx.diagnose(OptimizationRemarkAnalysis(PassName, Fn, Loc, Msg));
329 void llvm::emitOptimizationRemarkAnalysisFPCommute(
330 LLVMContext &Ctx, const char *PassName, const Function &Fn,
331 const DiagnosticLocation &Loc, const Twine &Msg) {
332 Ctx.diagnose(OptimizationRemarkAnalysisFPCommute(PassName, Fn, Loc, Msg));
335 void llvm::emitOptimizationRemarkAnalysisAliasing(LLVMContext &Ctx,
336 const char *PassName,
338 const DiagnosticLocation &Loc,
340 Ctx.diagnose(OptimizationRemarkAnalysisAliasing(PassName, Fn, Loc, Msg));
343 DiagnosticInfoOptimizationFailure::DiagnosticInfoOptimizationFailure(
344 const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc,
345 const Value *CodeRegion)
346 : DiagnosticInfoIROptimization(
347 DK_OptimizationFailure, DS_Warning, PassName, RemarkName,
348 *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {}
350 bool DiagnosticInfoOptimizationFailure::isEnabled() const {
351 // Only print warnings.
352 return getSeverity() == DS_Warning;
355 void DiagnosticInfoUnsupported::print(DiagnosticPrinter &DP) const {
357 raw_string_ostream OS(Str);
359 OS << getLocationStr() << ": in function " << getFunction().getName() << ' '
360 << *getFunction().getFunctionType() << ": " << Msg << '\n';
365 void DiagnosticInfoISelFallback::print(DiagnosticPrinter &DP) const {
366 DP << "Instruction selection used fallback path for " << getFunction();
369 DiagnosticInfoOptimizationBase &DiagnosticInfoOptimizationBase::
370 operator<<(StringRef S) {
371 Args.emplace_back(S);
375 DiagnosticInfoOptimizationBase &DiagnosticInfoOptimizationBase::
376 operator<<(Argument A) {
377 Args.push_back(std::move(A));
381 DiagnosticInfoOptimizationBase &DiagnosticInfoOptimizationBase::
382 operator<<(setIsVerbose V) {
387 DiagnosticInfoOptimizationBase &DiagnosticInfoOptimizationBase::
388 operator<<(setExtraArgs EA) {
389 FirstExtraArgIndex = Args.size();
393 std::string DiagnosticInfoOptimizationBase::getMsg() const {
395 raw_string_ostream OS(Str);
396 for (const DiagnosticInfoOptimizationBase::Argument &Arg :
397 make_range(Args.begin(), FirstExtraArgIndex == -1
399 : Args.begin() + FirstExtraArgIndex))