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