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