• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- llvm/IR/DiagnosticInfo.h - Diagnostic Declaration --------*- 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 declares the different classes involved in low level diagnostics.
11 //
12 // Diagnostics reporting is still done as part of the LLVMContext.
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_IR_DIAGNOSTICINFO_H
16 #define LLVM_IR_DIAGNOSTICINFO_H
17 
18 #include "llvm-c/Types.h"
19 #include "llvm/ADT/Optional.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/ADT/Twine.h"
23 #include "llvm/IR/DebugLoc.h"
24 #include "llvm/Support/CBindingWrapping.h"
25 #include "llvm/Support/YAMLTraits.h"
26 #include <algorithm>
27 #include <cstdint>
28 #include <functional>
29 #include <iterator>
30 #include <string>
31 
32 namespace llvm {
33 
34 // Forward declarations.
35 class DiagnosticPrinter;
36 class Function;
37 class Instruction;
38 class LLVMContext;
39 class Module;
40 class SMDiagnostic;
41 
42 /// Defines the different supported severity of a diagnostic.
43 enum DiagnosticSeverity : char {
44   DS_Error,
45   DS_Warning,
46   DS_Remark,
47   // A note attaches additional information to one of the previous diagnostic
48   // types.
49   DS_Note
50 };
51 
52 /// Defines the different supported kind of a diagnostic.
53 /// This enum should be extended with a new ID for each added concrete subclass.
54 enum DiagnosticKind {
55   DK_InlineAsm,
56   DK_ResourceLimit,
57   DK_StackSize,
58   DK_Linker,
59   DK_DebugMetadataVersion,
60   DK_DebugMetadataInvalid,
61   DK_ISelFallback,
62   DK_SampleProfile,
63   DK_OptimizationRemark,
64   DK_OptimizationRemarkMissed,
65   DK_OptimizationRemarkAnalysis,
66   DK_OptimizationRemarkAnalysisFPCommute,
67   DK_OptimizationRemarkAnalysisAliasing,
68   DK_OptimizationFailure,
69   DK_FirstRemark = DK_OptimizationRemark,
70   DK_LastRemark = DK_OptimizationFailure,
71   DK_MachineOptimizationRemark,
72   DK_MachineOptimizationRemarkMissed,
73   DK_MachineOptimizationRemarkAnalysis,
74   DK_FirstMachineRemark = DK_MachineOptimizationRemark,
75   DK_LastMachineRemark = DK_MachineOptimizationRemarkAnalysis,
76   DK_MIRParser,
77   DK_PGOProfile,
78   DK_Unsupported,
79   DK_FirstPluginKind
80 };
81 
82 /// Get the next available kind ID for a plugin diagnostic.
83 /// Each time this function is called, it returns a different number.
84 /// Therefore, a plugin that wants to "identify" its own classes
85 /// with a dynamic identifier, just have to use this method to get a new ID
86 /// and assign it to each of its classes.
87 /// The returned ID will be greater than or equal to DK_FirstPluginKind.
88 /// Thus, the plugin identifiers will not conflict with the
89 /// DiagnosticKind values.
90 int getNextAvailablePluginDiagnosticKind();
91 
92 /// This is the base abstract class for diagnostic reporting in
93 /// the backend.
94 /// The print method must be overloaded by the subclasses to print a
95 /// user-friendly message in the client of the backend (let us call it a
96 /// frontend).
97 class DiagnosticInfo {
98 private:
99   /// Kind defines the kind of report this is about.
100   const /* DiagnosticKind */ int Kind;
101   /// Severity gives the severity of the diagnostic.
102   const DiagnosticSeverity Severity;
103 
104 public:
DiagnosticInfo(int Kind,DiagnosticSeverity Severity)105   DiagnosticInfo(/* DiagnosticKind */ int Kind, DiagnosticSeverity Severity)
106       : Kind(Kind), Severity(Severity) {}
107 
108   virtual ~DiagnosticInfo() = default;
109 
getKind()110   /* DiagnosticKind */ int getKind() const { return Kind; }
getSeverity()111   DiagnosticSeverity getSeverity() const { return Severity; }
112 
113   /// Print using the given \p DP a user-friendly message.
114   /// This is the default message that will be printed to the user.
115   /// It is used when the frontend does not directly take advantage
116   /// of the information contained in fields of the subclasses.
117   /// The printed message must not end with '.' nor start with a severity
118   /// keyword.
119   virtual void print(DiagnosticPrinter &DP) const = 0;
120 };
121 
122 using DiagnosticHandlerFunction = std::function<void(const DiagnosticInfo &)>;
123 
124 /// Diagnostic information for inline asm reporting.
125 /// This is basically a message and an optional location.
126 class DiagnosticInfoInlineAsm : public DiagnosticInfo {
127 private:
128   /// Optional line information. 0 if not set.
129   unsigned LocCookie = 0;
130   /// Message to be reported.
131   const Twine &MsgStr;
132   /// Optional origin of the problem.
133   const Instruction *Instr = nullptr;
134 
135 public:
136   /// \p MsgStr is the message to be reported to the frontend.
137   /// This class does not copy \p MsgStr, therefore the reference must be valid
138   /// for the whole life time of the Diagnostic.
139   DiagnosticInfoInlineAsm(const Twine &MsgStr,
140                           DiagnosticSeverity Severity = DS_Error)
DiagnosticInfo(DK_InlineAsm,Severity)141       : DiagnosticInfo(DK_InlineAsm, Severity), MsgStr(MsgStr) {}
142 
143   /// \p LocCookie if non-zero gives the line number for this report.
144   /// \p MsgStr gives the message.
145   /// This class does not copy \p MsgStr, therefore the reference must be valid
146   /// for the whole life time of the Diagnostic.
147   DiagnosticInfoInlineAsm(unsigned LocCookie, const Twine &MsgStr,
148                           DiagnosticSeverity Severity = DS_Error)
DiagnosticInfo(DK_InlineAsm,Severity)149       : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(LocCookie),
150         MsgStr(MsgStr) {}
151 
152   /// \p Instr gives the original instruction that triggered the diagnostic.
153   /// \p MsgStr gives the message.
154   /// This class does not copy \p MsgStr, therefore the reference must be valid
155   /// for the whole life time of the Diagnostic.
156   /// Same for \p I.
157   DiagnosticInfoInlineAsm(const Instruction &I, const Twine &MsgStr,
158                           DiagnosticSeverity Severity = DS_Error);
159 
getLocCookie()160   unsigned getLocCookie() const { return LocCookie; }
getMsgStr()161   const Twine &getMsgStr() const { return MsgStr; }
getInstruction()162   const Instruction *getInstruction() const { return Instr; }
163 
164   /// \see DiagnosticInfo::print.
165   void print(DiagnosticPrinter &DP) const override;
166 
classof(const DiagnosticInfo * DI)167   static bool classof(const DiagnosticInfo *DI) {
168     return DI->getKind() == DK_InlineAsm;
169   }
170 };
171 
172 /// Diagnostic information for stack size etc. reporting.
173 /// This is basically a function and a size.
174 class DiagnosticInfoResourceLimit : public DiagnosticInfo {
175 private:
176   /// The function that is concerned by this resource limit diagnostic.
177   const Function &Fn;
178 
179   /// Description of the resource type (e.g. stack size)
180   const char *ResourceName;
181 
182   /// The computed size usage
183   uint64_t ResourceSize;
184 
185   // Threshould passed
186   uint64_t ResourceLimit;
187 
188 public:
189   /// \p The function that is concerned by this stack size diagnostic.
190   /// \p The computed stack size.
191   DiagnosticInfoResourceLimit(const Function &Fn, const char *ResourceName,
192                               uint64_t ResourceSize,
193                               DiagnosticSeverity Severity = DS_Warning,
194                               DiagnosticKind Kind = DK_ResourceLimit,
195                               uint64_t ResourceLimit = 0)
DiagnosticInfo(Kind,Severity)196       : DiagnosticInfo(Kind, Severity), Fn(Fn), ResourceName(ResourceName),
197         ResourceSize(ResourceSize), ResourceLimit(ResourceLimit) {}
198 
getFunction()199   const Function &getFunction() const { return Fn; }
getResourceName()200   const char *getResourceName() const { return ResourceName; }
getResourceSize()201   uint64_t getResourceSize() const { return ResourceSize; }
getResourceLimit()202   uint64_t getResourceLimit() const { return ResourceLimit; }
203 
204   /// \see DiagnosticInfo::print.
205   void print(DiagnosticPrinter &DP) const override;
206 
classof(const DiagnosticInfo * DI)207   static bool classof(const DiagnosticInfo *DI) {
208     return DI->getKind() == DK_ResourceLimit || DI->getKind() == DK_StackSize;
209   }
210 };
211 
212 class DiagnosticInfoStackSize : public DiagnosticInfoResourceLimit {
213 public:
214   DiagnosticInfoStackSize(const Function &Fn, uint64_t StackSize,
215                           DiagnosticSeverity Severity = DS_Warning,
216                           uint64_t StackLimit = 0)
217       : DiagnosticInfoResourceLimit(Fn, "stack size", StackSize, Severity,
218                                     DK_StackSize, StackLimit) {}
219 
getStackSize()220   uint64_t getStackSize() const { return getResourceSize(); }
getStackLimit()221   uint64_t getStackLimit() const { return getResourceLimit(); }
222 
classof(const DiagnosticInfo * DI)223   static bool classof(const DiagnosticInfo *DI) {
224     return DI->getKind() == DK_StackSize;
225   }
226 };
227 
228 /// Diagnostic information for debug metadata version reporting.
229 /// This is basically a module and a version.
230 class DiagnosticInfoDebugMetadataVersion : public DiagnosticInfo {
231 private:
232   /// The module that is concerned by this debug metadata version diagnostic.
233   const Module &M;
234   /// The actual metadata version.
235   unsigned MetadataVersion;
236 
237 public:
238   /// \p The module that is concerned by this debug metadata version diagnostic.
239   /// \p The actual metadata version.
240   DiagnosticInfoDebugMetadataVersion(const Module &M, unsigned MetadataVersion,
241                                      DiagnosticSeverity Severity = DS_Warning)
DiagnosticInfo(DK_DebugMetadataVersion,Severity)242       : DiagnosticInfo(DK_DebugMetadataVersion, Severity), M(M),
243         MetadataVersion(MetadataVersion) {}
244 
getModule()245   const Module &getModule() const { return M; }
getMetadataVersion()246   unsigned getMetadataVersion() const { return MetadataVersion; }
247 
248   /// \see DiagnosticInfo::print.
249   void print(DiagnosticPrinter &DP) const override;
250 
classof(const DiagnosticInfo * DI)251   static bool classof(const DiagnosticInfo *DI) {
252     return DI->getKind() == DK_DebugMetadataVersion;
253   }
254 };
255 
256 /// Diagnostic information for stripping invalid debug metadata.
257 class DiagnosticInfoIgnoringInvalidDebugMetadata : public DiagnosticInfo {
258 private:
259   /// The module that is concerned by this debug metadata version diagnostic.
260   const Module &M;
261 
262 public:
263   /// \p The module that is concerned by this debug metadata version diagnostic.
264   DiagnosticInfoIgnoringInvalidDebugMetadata(
265       const Module &M, DiagnosticSeverity Severity = DS_Warning)
DiagnosticInfo(DK_DebugMetadataVersion,Severity)266       : DiagnosticInfo(DK_DebugMetadataVersion, Severity), M(M) {}
267 
getModule()268   const Module &getModule() const { return M; }
269 
270   /// \see DiagnosticInfo::print.
271   void print(DiagnosticPrinter &DP) const override;
272 
classof(const DiagnosticInfo * DI)273   static bool classof(const DiagnosticInfo *DI) {
274     return DI->getKind() == DK_DebugMetadataInvalid;
275   }
276 };
277 
278 /// Diagnostic information for the sample profiler.
279 class DiagnosticInfoSampleProfile : public DiagnosticInfo {
280 public:
281   DiagnosticInfoSampleProfile(StringRef FileName, unsigned LineNum,
282                               const Twine &Msg,
283                               DiagnosticSeverity Severity = DS_Error)
DiagnosticInfo(DK_SampleProfile,Severity)284       : DiagnosticInfo(DK_SampleProfile, Severity), FileName(FileName),
285         LineNum(LineNum), Msg(Msg) {}
286   DiagnosticInfoSampleProfile(StringRef FileName, const Twine &Msg,
287                               DiagnosticSeverity Severity = DS_Error)
DiagnosticInfo(DK_SampleProfile,Severity)288       : DiagnosticInfo(DK_SampleProfile, Severity), FileName(FileName),
289         Msg(Msg) {}
290   DiagnosticInfoSampleProfile(const Twine &Msg,
291                               DiagnosticSeverity Severity = DS_Error)
DiagnosticInfo(DK_SampleProfile,Severity)292       : DiagnosticInfo(DK_SampleProfile, Severity), Msg(Msg) {}
293 
294   /// \see DiagnosticInfo::print.
295   void print(DiagnosticPrinter &DP) const override;
296 
classof(const DiagnosticInfo * DI)297   static bool classof(const DiagnosticInfo *DI) {
298     return DI->getKind() == DK_SampleProfile;
299   }
300 
getFileName()301   StringRef getFileName() const { return FileName; }
getLineNum()302   unsigned getLineNum() const { return LineNum; }
getMsg()303   const Twine &getMsg() const { return Msg; }
304 
305 private:
306   /// Name of the input file associated with this diagnostic.
307   StringRef FileName;
308 
309   /// Line number where the diagnostic occurred. If 0, no line number will
310   /// be emitted in the message.
311   unsigned LineNum = 0;
312 
313   /// Message to report.
314   const Twine &Msg;
315 };
316 
317 /// Diagnostic information for the PGO profiler.
318 class DiagnosticInfoPGOProfile : public DiagnosticInfo {
319 public:
320   DiagnosticInfoPGOProfile(const char *FileName, const Twine &Msg,
321                            DiagnosticSeverity Severity = DS_Error)
DiagnosticInfo(DK_PGOProfile,Severity)322       : DiagnosticInfo(DK_PGOProfile, Severity), FileName(FileName), Msg(Msg) {}
323 
324   /// \see DiagnosticInfo::print.
325   void print(DiagnosticPrinter &DP) const override;
326 
classof(const DiagnosticInfo * DI)327   static bool classof(const DiagnosticInfo *DI) {
328     return DI->getKind() == DK_PGOProfile;
329   }
330 
getFileName()331   const char *getFileName() const { return FileName; }
getMsg()332   const Twine &getMsg() const { return Msg; }
333 
334 private:
335   /// Name of the input file associated with this diagnostic.
336   const char *FileName;
337 
338   /// Message to report.
339   const Twine &Msg;
340 };
341 
342 class DiagnosticLocation {
343   StringRef Filename;
344   unsigned Line = 0;
345   unsigned Column = 0;
346 
347 public:
348   DiagnosticLocation() = default;
349   DiagnosticLocation(const DebugLoc &DL);
350   DiagnosticLocation(const DISubprogram *SP);
351 
isValid()352   bool isValid() const { return !Filename.empty(); }
getFilename()353   StringRef getFilename() const { return Filename; }
getLine()354   unsigned getLine() const { return Line; }
getColumn()355   unsigned getColumn() const { return Column; }
356 };
357 
358 /// Common features for diagnostics with an associated location.
359 class DiagnosticInfoWithLocationBase : public DiagnosticInfo {
360 public:
361   /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
362   /// the location information to use in the diagnostic.
DiagnosticInfoWithLocationBase(enum DiagnosticKind Kind,enum DiagnosticSeverity Severity,const Function & Fn,const DiagnosticLocation & Loc)363   DiagnosticInfoWithLocationBase(enum DiagnosticKind Kind,
364                                  enum DiagnosticSeverity Severity,
365                                  const Function &Fn,
366                                  const DiagnosticLocation &Loc)
367       : DiagnosticInfo(Kind, Severity), Fn(Fn), Loc(Loc) {}
368 
369   /// Return true if location information is available for this diagnostic.
isLocationAvailable()370   bool isLocationAvailable() const { return Loc.isValid(); }
371 
372   /// Return a string with the location information for this diagnostic
373   /// in the format "file:line:col". If location information is not available,
374   /// it returns "<unknown>:0:0".
375   const std::string getLocationStr() const;
376 
377   /// Return location information for this diagnostic in three parts:
378   /// the source file name, line number and column.
379   void getLocation(StringRef *Filename, unsigned *Line, unsigned *Column) const;
380 
getFunction()381   const Function &getFunction() const { return Fn; }
getLocation()382   DiagnosticLocation getLocation() const { return Loc; }
383 
384 private:
385   /// Function where this diagnostic is triggered.
386   const Function &Fn;
387 
388   /// Debug location where this diagnostic is triggered.
389   DiagnosticLocation Loc;
390 };
391 
392 /// Common features for diagnostics dealing with optimization remarks
393 /// that are used by both IR and MIR passes.
394 class DiagnosticInfoOptimizationBase : public DiagnosticInfoWithLocationBase {
395 public:
396   /// Used to set IsVerbose via the stream interface.
397   struct setIsVerbose {};
398 
399   /// When an instance of this is inserted into the stream, the arguments
400   /// following will not appear in the remark printed in the compiler output
401   /// (-Rpass) but only in the optimization record file
402   /// (-fsave-optimization-record).
403   struct setExtraArgs {};
404 
405   /// Used in the streaming interface as the general argument type.  It
406   /// internally converts everything into a key-value pair.
407   struct Argument {
408     std::string Key;
409     std::string Val;
410     // If set, the debug location corresponding to the value.
411     DiagnosticLocation Loc;
412 
413     explicit Argument(StringRef Str = "") : Key("String"), Val(Str) {}
414     Argument(StringRef Key, const Value *V);
415     Argument(StringRef Key, const Type *T);
416     Argument(StringRef Key, StringRef S);
417     Argument(StringRef Key, int N);
418     Argument(StringRef Key, float N);
419     Argument(StringRef Key, long N);
420     Argument(StringRef Key, long long N);
421     Argument(StringRef Key, unsigned N);
422     Argument(StringRef Key, unsigned long N);
423     Argument(StringRef Key, unsigned long long N);
ArgumentArgument424     Argument(StringRef Key, bool B) : Key(Key), Val(B ? "true" : "false") {}
425     Argument(StringRef Key, DebugLoc dl);
426   };
427 
428   /// \p PassName is the name of the pass emitting this diagnostic. \p
429   /// RemarkName is a textual identifier for the remark (single-word,
430   /// camel-case). \p Fn is the function where the diagnostic is being emitted.
431   /// \p Loc is the location information to use in the diagnostic. If line table
432   /// information is available, the diagnostic will include the source code
433   /// location.
DiagnosticInfoOptimizationBase(enum DiagnosticKind Kind,enum DiagnosticSeverity Severity,const char * PassName,StringRef RemarkName,const Function & Fn,const DiagnosticLocation & Loc)434   DiagnosticInfoOptimizationBase(enum DiagnosticKind Kind,
435                                  enum DiagnosticSeverity Severity,
436                                  const char *PassName, StringRef RemarkName,
437                                  const Function &Fn,
438                                  const DiagnosticLocation &Loc)
439       : DiagnosticInfoWithLocationBase(Kind, Severity, Fn, Loc),
440         PassName(PassName), RemarkName(RemarkName) {}
441 
442   void insert(StringRef S);
443   void insert(Argument A);
444   void insert(setIsVerbose V);
445   void insert(setExtraArgs EA);
446 
447   /// \see DiagnosticInfo::print.
448   void print(DiagnosticPrinter &DP) const override;
449 
450   /// Return true if this optimization remark is enabled by one of
451   /// of the LLVM command line flags (-pass-remarks, -pass-remarks-missed,
452   /// or -pass-remarks-analysis). Note that this only handles the LLVM
453   /// flags. We cannot access Clang flags from here (they are handled
454   /// in BackendConsumer::OptimizationRemarkHandler).
455   virtual bool isEnabled() const = 0;
456 
getPassName()457   StringRef getPassName() const { return PassName; }
458   std::string getMsg() const;
getHotness()459   Optional<uint64_t> getHotness() const { return Hotness; }
setHotness(Optional<uint64_t> H)460   void setHotness(Optional<uint64_t> H) { Hotness = H; }
461 
isVerbose()462   bool isVerbose() const { return IsVerbose; }
463 
classof(const DiagnosticInfo * DI)464   static bool classof(const DiagnosticInfo *DI) {
465     return (DI->getKind() >= DK_FirstRemark &&
466             DI->getKind() <= DK_LastRemark) ||
467            (DI->getKind() >= DK_FirstMachineRemark &&
468             DI->getKind() <= DK_LastMachineRemark);
469   }
470 
isPassed()471   bool isPassed() const {
472     return (getKind() == DK_OptimizationRemark ||
473             getKind() == DK_MachineOptimizationRemark);
474   }
475 
isMissed()476   bool isMissed() const {
477     return (getKind() == DK_OptimizationRemarkMissed ||
478             getKind() == DK_MachineOptimizationRemarkMissed);
479   }
480 
isAnalysis()481   bool isAnalysis() const {
482     return (getKind() == DK_OptimizationRemarkAnalysis ||
483             getKind() == DK_MachineOptimizationRemarkAnalysis);
484   }
485 
486 protected:
487   /// Name of the pass that triggers this report. If this matches the
488   /// regular expression given in -Rpass=regexp, then the remark will
489   /// be emitted.
490   const char *PassName;
491 
492   /// Textual identifier for the remark (single-word, camel-case). Can be used
493   /// by external tools reading the YAML output file for optimization remarks to
494   /// identify the remark.
495   StringRef RemarkName;
496 
497   /// If profile information is available, this is the number of times the
498   /// corresponding code was executed in a profile instrumentation run.
499   Optional<uint64_t> Hotness;
500 
501   /// Arguments collected via the streaming interface.
502   SmallVector<Argument, 4> Args;
503 
504   /// The remark is expected to be noisy.
505   bool IsVerbose = false;
506 
507   /// If positive, the index of the first argument that only appear in
508   /// the optimization records and not in the remark printed in the compiler
509   /// output.
510   int FirstExtraArgIndex = -1;
511 
512   friend struct yaml::MappingTraits<DiagnosticInfoOptimizationBase *>;
513 };
514 
515 /// Allow the insertion operator to return the actual remark type rather than a
516 /// common base class.  This allows returning the result of the insertion
517 /// directly by value, e.g. return OptimizationRemarkAnalysis(...) << "blah".
518 template <class RemarkT>
519 RemarkT &
520 operator<<(RemarkT &R,
521            typename std::enable_if<
522                std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
523                StringRef>::type S) {
524   R.insert(S);
525   return R;
526 }
527 
528 /// Also allow r-value for the remark to allow insertion into a
529 /// temporarily-constructed remark.
530 template <class RemarkT>
531 RemarkT &
532 operator<<(RemarkT &&R,
533            typename std::enable_if<
534                std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
535                StringRef>::type S) {
536   R.insert(S);
537   return R;
538 }
539 
540 template <class RemarkT>
541 RemarkT &
542 operator<<(RemarkT &R,
543            typename std::enable_if<
544                std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
545                DiagnosticInfoOptimizationBase::Argument>::type A) {
546   R.insert(A);
547   return R;
548 }
549 
550 template <class RemarkT>
551 RemarkT &
552 operator<<(RemarkT &&R,
553            typename std::enable_if<
554                std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
555                DiagnosticInfoOptimizationBase::Argument>::type A) {
556   R.insert(A);
557   return R;
558 }
559 
560 template <class RemarkT>
561 RemarkT &
562 operator<<(RemarkT &R,
563            typename std::enable_if<
564                std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
565                DiagnosticInfoOptimizationBase::setIsVerbose>::type V) {
566   R.insert(V);
567   return R;
568 }
569 
570 template <class RemarkT>
571 RemarkT &
572 operator<<(RemarkT &&R,
573            typename std::enable_if<
574                std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
575                DiagnosticInfoOptimizationBase::setIsVerbose>::type V) {
576   R.insert(V);
577   return R;
578 }
579 
580 template <class RemarkT>
581 RemarkT &
582 operator<<(RemarkT &R,
583            typename std::enable_if<
584                std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
585                DiagnosticInfoOptimizationBase::setExtraArgs>::type EA) {
586   R.insert(EA);
587   return R;
588 }
589 
590 /// Common features for diagnostics dealing with optimization remarks
591 /// that are used by IR passes.
592 class DiagnosticInfoIROptimization : public DiagnosticInfoOptimizationBase {
593 public:
594   /// \p PassName is the name of the pass emitting this diagnostic. \p
595   /// RemarkName is a textual identifier for the remark (single-word,
596   /// camel-case). \p Fn is the function where the diagnostic is being emitted.
597   /// \p Loc is the location information to use in the diagnostic. If line table
598   /// information is available, the diagnostic will include the source code
599   /// location. \p CodeRegion is IR value (currently basic block) that the
600   /// optimization operates on. This is currently used to provide run-time
601   /// hotness information with PGO.
602   DiagnosticInfoIROptimization(enum DiagnosticKind Kind,
603                                enum DiagnosticSeverity Severity,
604                                const char *PassName, StringRef RemarkName,
605                                const Function &Fn,
606                                const DiagnosticLocation &Loc,
607                                const Value *CodeRegion = nullptr)
608       : DiagnosticInfoOptimizationBase(Kind, Severity, PassName, RemarkName, Fn,
609                                        Loc),
610         CodeRegion(CodeRegion) {}
611 
612   /// This is ctor variant allows a pass to build an optimization remark
613   /// from an existing remark.
614   ///
615   /// This is useful when a transformation pass (e.g LV) wants to emit a remark
616   /// (\p Orig) generated by one of its analyses (e.g. LAA) as its own analysis
617   /// remark.  The string \p Prepend will be emitted before the original
618   /// message.
619   DiagnosticInfoIROptimization(const char *PassName, StringRef Prepend,
620                                const DiagnosticInfoIROptimization &Orig)
621       : DiagnosticInfoOptimizationBase(
622             (DiagnosticKind)Orig.getKind(), Orig.getSeverity(), PassName,
623             Orig.RemarkName, Orig.getFunction(), Orig.getLocation()),
624         CodeRegion(Orig.getCodeRegion()) {
625     *this << Prepend;
626     std::copy(Orig.Args.begin(), Orig.Args.end(), std::back_inserter(Args));
627   }
628 
629   /// Legacy interface.
630   /// \p PassName is the name of the pass emitting this diagnostic.
631   /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
632   /// the location information to use in the diagnostic. If line table
633   /// information is available, the diagnostic will include the source code
634   /// location. \p Msg is the message to show. Note that this class does not
635   /// copy this message, so this reference must be valid for the whole life time
636   /// of the diagnostic.
637   DiagnosticInfoIROptimization(enum DiagnosticKind Kind,
638                                enum DiagnosticSeverity Severity,
639                                const char *PassName, const Function &Fn,
640                                const DiagnosticLocation &Loc, const Twine &Msg)
641       : DiagnosticInfoOptimizationBase(Kind, Severity, PassName, "", Fn, Loc) {
642     *this << Msg.str();
643   }
644 
645   const Value *getCodeRegion() const { return CodeRegion; }
646 
647   static bool classof(const DiagnosticInfo *DI) {
648     return DI->getKind() >= DK_FirstRemark && DI->getKind() <= DK_LastRemark;
649   }
650 
651 private:
652   /// The IR value (currently basic block) that the optimization operates on.
653   /// This is currently used to provide run-time hotness information with PGO.
654   const Value *CodeRegion;
655 };
656 
657 /// Diagnostic information for applied optimization remarks.
658 class OptimizationRemark : public DiagnosticInfoIROptimization {
659 public:
660   /// \p PassName is the name of the pass emitting this diagnostic. If this name
661   /// matches the regular expression given in -Rpass=, then the diagnostic will
662   /// be emitted. \p RemarkName is a textual identifier for the remark (single-
663   /// word, camel-case). \p Loc is the debug location and \p CodeRegion is the
664   /// region that the optimization operates on (currently only block is
665   /// supported).
666   OptimizationRemark(const char *PassName, StringRef RemarkName,
667                      const DiagnosticLocation &Loc, const Value *CodeRegion);
668 
669   /// Same as above, but the debug location and code region are derived from \p
670   /// Instr.
671   OptimizationRemark(const char *PassName, StringRef RemarkName,
672                      const Instruction *Inst);
673 
674   /// Same as above, but the debug location and code region are derived from \p
675   /// Func.
676   OptimizationRemark(const char *PassName, StringRef RemarkName,
677                      const Function *Func);
678 
679   static bool classof(const DiagnosticInfo *DI) {
680     return DI->getKind() == DK_OptimizationRemark;
681   }
682 
683   /// \see DiagnosticInfoOptimizationBase::isEnabled.
684   bool isEnabled() const override;
685 
686 private:
687   /// This is deprecated now and only used by the function API below.
688   /// \p PassName is the name of the pass emitting this diagnostic. If
689   /// this name matches the regular expression given in -Rpass=, then the
690   /// diagnostic will be emitted. \p Fn is the function where the diagnostic
691   /// is being emitted. \p Loc is the location information to use in the
692   /// diagnostic. If line table information is available, the diagnostic
693   /// will include the source code location. \p Msg is the message to show.
694   /// Note that this class does not copy this message, so this reference
695   /// must be valid for the whole life time of the diagnostic.
696   OptimizationRemark(const char *PassName, const Function &Fn,
697                      const DiagnosticLocation &Loc, const Twine &Msg)
698       : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,
699                                      Fn, Loc, Msg) {}
700 };
701 
702 /// Diagnostic information for missed-optimization remarks.
703 class OptimizationRemarkMissed : public DiagnosticInfoIROptimization {
704 public:
705   /// \p PassName is the name of the pass emitting this diagnostic. If this name
706   /// matches the regular expression given in -Rpass-missed=, then the
707   /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
708   /// remark (single-word, camel-case). \p Loc is the debug location and \p
709   /// CodeRegion is the region that the optimization operates on (currently only
710   /// block is supported).
711   OptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
712                            const DiagnosticLocation &Loc,
713                            const Value *CodeRegion);
714 
715   /// Same as above but \p Inst is used to derive code region and debug
716   /// location.
717   OptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
718                            const Instruction *Inst);
719 
720   static bool classof(const DiagnosticInfo *DI) {
721     return DI->getKind() == DK_OptimizationRemarkMissed;
722   }
723 
724   /// \see DiagnosticInfoOptimizationBase::isEnabled.
725   bool isEnabled() const override;
726 
727 private:
728   /// This is deprecated now and only used by the function API below.
729   /// \p PassName is the name of the pass emitting this diagnostic. If
730   /// this name matches the regular expression given in -Rpass-missed=, then the
731   /// diagnostic will be emitted. \p Fn is the function where the diagnostic
732   /// is being emitted. \p Loc is the location information to use in the
733   /// diagnostic. If line table information is available, the diagnostic
734   /// will include the source code location. \p Msg is the message to show.
735   /// Note that this class does not copy this message, so this reference
736   /// must be valid for the whole life time of the diagnostic.
737   OptimizationRemarkMissed(const char *PassName, const Function &Fn,
738                            const DiagnosticLocation &Loc, const Twine &Msg)
739       : DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark,
740                                      PassName, Fn, Loc, Msg) {}
741 };
742 
743 /// Diagnostic information for optimization analysis remarks.
744 class OptimizationRemarkAnalysis : public DiagnosticInfoIROptimization {
745 public:
746   /// \p PassName is the name of the pass emitting this diagnostic. If this name
747   /// matches the regular expression given in -Rpass-analysis=, then the
748   /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
749   /// remark (single-word, camel-case). \p Loc is the debug location and \p
750   /// CodeRegion is the region that the optimization operates on (currently only
751   /// block is supported).
752   OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
753                              const DiagnosticLocation &Loc,
754                              const Value *CodeRegion);
755 
756   /// This is ctor variant allows a pass to build an optimization remark
757   /// from an existing remark.
758   ///
759   /// This is useful when a transformation pass (e.g LV) wants to emit a remark
760   /// (\p Orig) generated by one of its analyses (e.g. LAA) as its own analysis
761   /// remark.  The string \p Prepend will be emitted before the original
762   /// message.
763   OptimizationRemarkAnalysis(const char *PassName, StringRef Prepend,
764                              const OptimizationRemarkAnalysis &Orig)
765       : DiagnosticInfoIROptimization(PassName, Prepend, Orig) {}
766 
767   /// Same as above but \p Inst is used to derive code region and debug
768   /// location.
769   OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
770                              const Instruction *Inst);
771 
772   static bool classof(const DiagnosticInfo *DI) {
773     return DI->getKind() == DK_OptimizationRemarkAnalysis;
774   }
775 
776   /// \see DiagnosticInfoOptimizationBase::isEnabled.
777   bool isEnabled() const override;
778 
779   static const char *AlwaysPrint;
780 
781   bool shouldAlwaysPrint() const { return getPassName() == AlwaysPrint; }
782 
783 protected:
784   OptimizationRemarkAnalysis(enum DiagnosticKind Kind, const char *PassName,
785                              const Function &Fn, const DiagnosticLocation &Loc,
786                              const Twine &Msg)
787       : DiagnosticInfoIROptimization(Kind, DS_Remark, PassName, Fn, Loc, Msg) {}
788 
789   OptimizationRemarkAnalysis(enum DiagnosticKind Kind, const char *PassName,
790                              StringRef RemarkName,
791                              const DiagnosticLocation &Loc,
792                              const Value *CodeRegion);
793 
794 private:
795   /// This is deprecated now and only used by the function API below.
796   /// \p PassName is the name of the pass emitting this diagnostic. If
797   /// this name matches the regular expression given in -Rpass-analysis=, then
798   /// the diagnostic will be emitted. \p Fn is the function where the diagnostic
799   /// is being emitted. \p Loc is the location information to use in the
800   /// diagnostic. If line table information is available, the diagnostic will
801   /// include the source code location. \p Msg is the message to show. Note that
802   /// this class does not copy this message, so this reference must be valid for
803   /// the whole life time of the diagnostic.
804   OptimizationRemarkAnalysis(const char *PassName, const Function &Fn,
805                              const DiagnosticLocation &Loc, const Twine &Msg)
806       : DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark,
807                                      PassName, Fn, Loc, Msg) {}
808 };
809 
810 /// Diagnostic information for optimization analysis remarks related to
811 /// floating-point non-commutativity.
812 class OptimizationRemarkAnalysisFPCommute : public OptimizationRemarkAnalysis {
813 public:
814   /// \p PassName is the name of the pass emitting this diagnostic. If this name
815   /// matches the regular expression given in -Rpass-analysis=, then the
816   /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
817   /// remark (single-word, camel-case). \p Loc is the debug location and \p
818   /// CodeRegion is the region that the optimization operates on (currently only
819   /// block is supported). The front-end will append its own message related to
820   /// options that address floating-point non-commutativity.
821   OptimizationRemarkAnalysisFPCommute(const char *PassName,
822                                       StringRef RemarkName,
823                                       const DiagnosticLocation &Loc,
824                                       const Value *CodeRegion)
825       : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute,
826                                    PassName, RemarkName, Loc, CodeRegion) {}
827 
828   static bool classof(const DiagnosticInfo *DI) {
829     return DI->getKind() == DK_OptimizationRemarkAnalysisFPCommute;
830   }
831 
832 private:
833   /// This is deprecated now and only used by the function API below.
834   /// \p PassName is the name of the pass emitting this diagnostic. If
835   /// this name matches the regular expression given in -Rpass-analysis=, then
836   /// the diagnostic will be emitted. \p Fn is the function where the diagnostic
837   /// is being emitted. \p Loc is the location information to use in the
838   /// diagnostic. If line table information is available, the diagnostic will
839   /// include the source code location. \p Msg is the message to show. The
840   /// front-end will append its own message related to options that address
841   /// floating-point non-commutativity. Note that this class does not copy this
842   /// message, so this reference must be valid for the whole life time of the
843   /// diagnostic.
844   OptimizationRemarkAnalysisFPCommute(const char *PassName, const Function &Fn,
845                                       const DiagnosticLocation &Loc,
846                                       const Twine &Msg)
847       : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute,
848                                    PassName, Fn, Loc, Msg) {}
849 };
850 
851 /// Diagnostic information for optimization analysis remarks related to
852 /// pointer aliasing.
853 class OptimizationRemarkAnalysisAliasing : public OptimizationRemarkAnalysis {
854 public:
855   /// \p PassName is the name of the pass emitting this diagnostic. If this name
856   /// matches the regular expression given in -Rpass-analysis=, then the
857   /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
858   /// remark (single-word, camel-case). \p Loc is the debug location and \p
859   /// CodeRegion is the region that the optimization operates on (currently only
860   /// block is supported). The front-end will append its own message related to
861   /// options that address pointer aliasing legality.
862   OptimizationRemarkAnalysisAliasing(const char *PassName, StringRef RemarkName,
863                                      const DiagnosticLocation &Loc,
864                                      const Value *CodeRegion)
865       : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing,
866                                    PassName, RemarkName, Loc, CodeRegion) {}
867 
868   static bool classof(const DiagnosticInfo *DI) {
869     return DI->getKind() == DK_OptimizationRemarkAnalysisAliasing;
870   }
871 
872 private:
873   /// This is deprecated now and only used by the function API below.
874   /// \p PassName is the name of the pass emitting this diagnostic. If
875   /// this name matches the regular expression given in -Rpass-analysis=, then
876   /// the diagnostic will be emitted. \p Fn is the function where the diagnostic
877   /// is being emitted. \p Loc is the location information to use in the
878   /// diagnostic. If line table information is available, the diagnostic will
879   /// include the source code location. \p Msg is the message to show. The
880   /// front-end will append its own message related to options that address
881   /// pointer aliasing legality. Note that this class does not copy this
882   /// message, so this reference must be valid for the whole life time of the
883   /// diagnostic.
884   OptimizationRemarkAnalysisAliasing(const char *PassName, const Function &Fn,
885                                      const DiagnosticLocation &Loc,
886                                      const Twine &Msg)
887       : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing,
888                                    PassName, Fn, Loc, Msg) {}
889 };
890 
891 /// Diagnostic information for machine IR parser.
892 class DiagnosticInfoMIRParser : public DiagnosticInfo {
893   const SMDiagnostic &Diagnostic;
894 
895 public:
896   DiagnosticInfoMIRParser(DiagnosticSeverity Severity,
897                           const SMDiagnostic &Diagnostic)
898       : DiagnosticInfo(DK_MIRParser, Severity), Diagnostic(Diagnostic) {}
899 
900   const SMDiagnostic &getDiagnostic() const { return Diagnostic; }
901 
902   void print(DiagnosticPrinter &DP) const override;
903 
904   static bool classof(const DiagnosticInfo *DI) {
905     return DI->getKind() == DK_MIRParser;
906   }
907 };
908 
909 /// Diagnostic information for ISel fallback path.
910 class DiagnosticInfoISelFallback : public DiagnosticInfo {
911   /// The function that is concerned by this diagnostic.
912   const Function &Fn;
913 
914 public:
915   DiagnosticInfoISelFallback(const Function &Fn,
916                              DiagnosticSeverity Severity = DS_Warning)
917       : DiagnosticInfo(DK_ISelFallback, Severity), Fn(Fn) {}
918 
919   const Function &getFunction() const { return Fn; }
920 
921   void print(DiagnosticPrinter &DP) const override;
922 
923   static bool classof(const DiagnosticInfo *DI) {
924     return DI->getKind() == DK_ISelFallback;
925   }
926 };
927 
928 // Create wrappers for C Binding types (see CBindingWrapping.h).
929 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DiagnosticInfo, LLVMDiagnosticInfoRef)
930 
931 /// Diagnostic information for optimization failures.
932 class DiagnosticInfoOptimizationFailure : public DiagnosticInfoIROptimization {
933 public:
934   /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
935   /// the location information to use in the diagnostic. If line table
936   /// information is available, the diagnostic will include the source code
937   /// location. \p Msg is the message to show. Note that this class does not
938   /// copy this message, so this reference must be valid for the whole life time
939   /// of the diagnostic.
940   DiagnosticInfoOptimizationFailure(const Function &Fn,
941                                     const DiagnosticLocation &Loc,
942                                     const Twine &Msg)
943       : DiagnosticInfoIROptimization(DK_OptimizationFailure, DS_Warning,
944                                      nullptr, Fn, Loc, Msg) {}
945 
946   /// \p PassName is the name of the pass emitting this diagnostic.  \p
947   /// RemarkName is a textual identifier for the remark (single-word,
948   /// camel-case).  \p Loc is the debug location and \p CodeRegion is the
949   /// region that the optimization operates on (currently basic block is
950   /// supported).
951   DiagnosticInfoOptimizationFailure(const char *PassName, StringRef RemarkName,
952                                     const DiagnosticLocation &Loc,
953                                     const Value *CodeRegion);
954 
955   static bool classof(const DiagnosticInfo *DI) {
956     return DI->getKind() == DK_OptimizationFailure;
957   }
958 
959   /// \see DiagnosticInfoOptimizationBase::isEnabled.
960   bool isEnabled() const override;
961 };
962 
963 /// Diagnostic information for unsupported feature in backend.
964 class DiagnosticInfoUnsupported : public DiagnosticInfoWithLocationBase {
965 private:
966   Twine Msg;
967 
968 public:
969   /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
970   /// the location information to use in the diagnostic. If line table
971   /// information is available, the diagnostic will include the source code
972   /// location. \p Msg is the message to show. Note that this class does not
973   /// copy this message, so this reference must be valid for the whole life time
974   /// of the diagnostic.
975   DiagnosticInfoUnsupported(
976       const Function &Fn, const Twine &Msg,
977       const DiagnosticLocation &Loc = DiagnosticLocation(),
978       DiagnosticSeverity Severity = DS_Error)
979       : DiagnosticInfoWithLocationBase(DK_Unsupported, Severity, Fn, Loc),
980         Msg(Msg) {}
981 
982   static bool classof(const DiagnosticInfo *DI) {
983     return DI->getKind() == DK_Unsupported;
984   }
985 
986   const Twine &getMessage() const { return Msg; }
987 
988   void print(DiagnosticPrinter &DP) const override;
989 };
990 
991 namespace yaml {
992 template <> struct MappingTraits<DiagnosticInfoOptimizationBase *> {
993   static void mapping(IO &io, DiagnosticInfoOptimizationBase *&OptDiag);
994 };
995 } // namespace yaml
996 
997 } // end namespace llvm
998 
999 #endif // LLVM_IR_DIAGNOSTICINFO_H
1000