]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/IR/DiagnosticInfo.cpp
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r301441, and update
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / IR / DiagnosticInfo.cpp
1 //===- llvm/Support/DiagnosticInfo.cpp - Diagnostic Definitions -*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the different classes involved in low level diagnostics.
11 //
12 // Diagnostics reporting is still done as part of the LLVMContext.
13 //===----------------------------------------------------------------------===//
14
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"
28 #include <atomic>
29 #include <string>
30
31 using namespace llvm;
32
33 namespace {
34
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;
42
43   void operator=(const std::string &Val) {
44     // Create a regexp object to match pass names for emitOptimizationRemark.
45     if (!Val.empty()) {
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,
51                            false);
52     }
53   }
54 };
55
56 static PassRemarksOpt PassRemarksOptLoc;
57 static PassRemarksOpt PassRemarksMissedOptLoc;
58 static PassRemarksOpt PassRemarksAnalysisOptLoc;
59
60 // -pass-remarks
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,
67             cl::ZeroOrMore);
68
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,
76     cl::ZeroOrMore);
77
78 // -pass-remarks-analysis
79 //    Command line flag to enable emitOptimizationRemarkAnalysis()
80 static cl::opt<PassRemarksOpt, true, cl::parser<std::string>>
81 PassRemarksAnalysis(
82     "pass-remarks-analysis", cl::value_desc("pattern"),
83     cl::desc(
84         "Enable optimization analysis remarks from passes whose name match "
85         "the given regular expression"),
86     cl::Hidden, cl::location(PassRemarksAnalysisOptLoc), cl::ValueRequired,
87     cl::ZeroOrMore);
88 }
89
90 int llvm::getNextAvailablePluginDiagnosticKind() {
91   static std::atomic<int> PluginKindID(DK_FirstPluginKind);
92   return ++PluginKindID;
93 }
94
95 const char *OptimizationRemarkAnalysis::AlwaysPrint = "";
96
97 DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(const Instruction &I,
98                                                  const Twine &MsgStr,
99                                                  DiagnosticSeverity Severity)
100     : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(0), MsgStr(MsgStr),
101       Instr(&I) {
102   if (const MDNode *SrcLoc = I.getMetadata("srcloc")) {
103     if (SrcLoc->getNumOperands() != 0)
104       if (const auto *CI =
105               mdconst::dyn_extract<ConstantInt>(SrcLoc->getOperand(0)))
106         LocCookie = CI->getZExtValue();
107   }
108 }
109
110 void DiagnosticInfoInlineAsm::print(DiagnosticPrinter &DP) const {
111   DP << getMsgStr();
112   if (getLocCookie())
113     DP << " at line " << getLocCookie();
114 }
115
116 void DiagnosticInfoResourceLimit::print(DiagnosticPrinter &DP) const {
117   DP << getResourceName() << " limit";
118
119   if (getResourceLimit() != 0)
120     DP << " of " << getResourceLimit();
121
122   DP << " exceeded (" <<  getResourceSize() << ") in " << getFunction();
123 }
124
125 void DiagnosticInfoDebugMetadataVersion::print(DiagnosticPrinter &DP) const {
126   DP << "ignoring debug info with an invalid version (" << getMetadataVersion()
127      << ") in " << getModule();
128 }
129
130 void DiagnosticInfoIgnoringInvalidDebugMetadata::print(
131     DiagnosticPrinter &DP) const {
132   DP << "ignoring invalid debug info in " << getModule().getModuleIdentifier();
133 }
134
135 void DiagnosticInfoSampleProfile::print(DiagnosticPrinter &DP) const {
136   if (!FileName.empty()) {
137     DP << getFileName();
138     if (LineNum > 0)
139       DP << ":" << getLineNum();
140     DP << ": ";
141   }
142   DP << getMsg();
143 }
144
145 void DiagnosticInfoPGOProfile::print(DiagnosticPrinter &DP) const {
146   if (getFileName())
147     DP << getFileName() << ": ";
148   DP << getMsg();
149 }
150
151 DiagnosticLocation::DiagnosticLocation(const DebugLoc &DL) {
152   if (!DL)
153     return;
154   Filename = DL->getFilename();
155   Line = DL->getLine();
156   Column = DL->getColumn();
157 }
158
159 DiagnosticLocation::DiagnosticLocation(const DISubprogram *SP) {
160   if (!SP)
161     return;
162   Filename = SP->getFilename();
163   Line = SP->getScopeLine();
164   Column = 0;
165 }
166
167 void DiagnosticInfoWithLocationBase::getLocation(StringRef *Filename,
168                                                  unsigned *Line,
169                                                  unsigned *Column) const {
170   *Filename = Loc.getFilename();
171   *Line = Loc.getLine();
172   *Column = Loc.getColumn();
173 }
174
175 const std::string DiagnosticInfoWithLocationBase::getLocationStr() const {
176   StringRef Filename("<unknown>");
177   unsigned Line = 0;
178   unsigned Column = 0;
179   if (isLocationAvailable())
180     getLocation(&Filename, &Line, &Column);
181   return (Filename + ":" + Twine(Line) + ":" + Twine(Column)).str();
182 }
183
184 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, const Value *V)
185     : Key(Key) {
186   if (auto *F = dyn_cast<Function>(V)) {
187     if (DISubprogram *SP = F->getSubprogram())
188       Loc = SP;
189   }
190   else if (auto *I = dyn_cast<Instruction>(V))
191     Loc = I->getDebugLoc();
192
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();
202 }
203
204 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, const Type *T)
205     : Key(Key) {
206   raw_string_ostream OS(Val);
207   OS << *T;
208 }
209
210 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, int N)
211     : Key(Key), Val(itostr(N)) {}
212
213 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, unsigned N)
214     : Key(Key), Val(utostr(N)) {}
215
216 void DiagnosticInfoOptimizationBase::print(DiagnosticPrinter &DP) const {
217   DP << getLocationStr() << ": " << getMsg();
218   if (Hotness)
219     DP << " (hotness: " << *Hotness << ")";
220 }
221
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) {}
229
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()) {}
236
237 // Helper to allow for an assert before attempting to return an invalid
238 // reference.
239 static const BasicBlock &getFirstFunctionBlock(const Function *Func) {
240   assert(!Func->empty() && "Function does not have a body");
241   return Func->front();
242 }
243
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)) {}
250
251 bool OptimizationRemark::isEnabled(StringRef PassName) {
252   return PassRemarksOptLoc.Pattern &&
253          PassRemarksOptLoc.Pattern->match(PassName);
254 }
255
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) {}
262
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()) {}
270
271 bool OptimizationRemarkMissed::isEnabled(StringRef PassName) {
272   return PassRemarksMissedOptLoc.Pattern &&
273          PassRemarksMissedOptLoc.Pattern->match(PassName);
274 }
275
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) {}
282
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()) {}
290
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(),
296                                    Loc, CodeRegion) {}
297
298 bool OptimizationRemarkAnalysis::isEnabled(StringRef PassName) {
299   return PassRemarksAnalysisOptLoc.Pattern &&
300          PassRemarksAnalysisOptLoc.Pattern->match(PassName);
301 }
302
303 void DiagnosticInfoMIRParser::print(DiagnosticPrinter &DP) const {
304   DP << Diagnostic;
305 }
306
307 void llvm::emitOptimizationRemark(LLVMContext &Ctx, const char *PassName,
308                                   const Function &Fn,
309                                   const DiagnosticLocation &Loc,
310                                   const Twine &Msg) {
311   Ctx.diagnose(OptimizationRemark(PassName, Fn, Loc, Msg));
312 }
313
314 void llvm::emitOptimizationRemarkMissed(LLVMContext &Ctx, const char *PassName,
315                                         const Function &Fn,
316                                         const DiagnosticLocation &Loc,
317                                         const Twine &Msg) {
318   Ctx.diagnose(OptimizationRemarkMissed(PassName, Fn, Loc, Msg));
319 }
320
321 void llvm::emitOptimizationRemarkAnalysis(LLVMContext &Ctx,
322                                           const char *PassName,
323                                           const Function &Fn,
324                                           const DiagnosticLocation &Loc,
325                                           const Twine &Msg) {
326   Ctx.diagnose(OptimizationRemarkAnalysis(PassName, Fn, Loc, Msg));
327 }
328
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));
333 }
334
335 void llvm::emitOptimizationRemarkAnalysisAliasing(LLVMContext &Ctx,
336                                                   const char *PassName,
337                                                   const Function &Fn,
338                                                   const DiagnosticLocation &Loc,
339                                                   const Twine &Msg) {
340   Ctx.diagnose(OptimizationRemarkAnalysisAliasing(PassName, Fn, Loc, Msg));
341 }
342
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) {}
349
350 bool DiagnosticInfoOptimizationFailure::isEnabled() const {
351   // Only print warnings.
352   return getSeverity() == DS_Warning;
353 }
354
355 void DiagnosticInfoUnsupported::print(DiagnosticPrinter &DP) const {
356   std::string Str;
357   raw_string_ostream OS(Str);
358
359   OS << getLocationStr() << ": in function " << getFunction().getName() << ' '
360      << *getFunction().getFunctionType() << ": " << Msg << '\n';
361   OS.flush();
362   DP << Str;
363 }
364
365 void DiagnosticInfoISelFallback::print(DiagnosticPrinter &DP) const {
366   DP << "Instruction selection used fallback path for " << getFunction();
367 }
368
369 DiagnosticInfoOptimizationBase &DiagnosticInfoOptimizationBase::
370 operator<<(StringRef S) {
371   Args.emplace_back(S);
372   return *this;
373 }
374
375 DiagnosticInfoOptimizationBase &DiagnosticInfoOptimizationBase::
376 operator<<(Argument A) {
377   Args.push_back(std::move(A));
378   return *this;
379 }
380
381 DiagnosticInfoOptimizationBase &DiagnosticInfoOptimizationBase::
382 operator<<(setIsVerbose V) {
383   IsVerbose = true;
384   return *this;
385 }
386
387 DiagnosticInfoOptimizationBase &DiagnosticInfoOptimizationBase::
388 operator<<(setExtraArgs EA) {
389   FirstExtraArgIndex = Args.size();
390   return *this;
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 }