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