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