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 /// Defines the different supported severity of a diagnostic.
     43 enum DiagnosticSeverity : char {
     44   DS_Error,
     45   DS_Warning,
     46   DS_Remark,
     47   // A note attaches additional information to one of the previous diagnostic
     48   // types.
     49   DS_Note
     50 };
     51 
     52 /// Defines the different supported kind of a diagnostic.
     53 /// This enum should be extended with a new ID for each added concrete subclass.
     54 enum DiagnosticKind {
     55   DK_InlineAsm,
     56   DK_ResourceLimit,
     57   DK_StackSize,
     58   DK_Linker,
     59   DK_DebugMetadataVersion,
     60   DK_DebugMetadataInvalid,
     61   DK_ISelFallback,
     62   DK_SampleProfile,
     63   DK_OptimizationRemark,
     64   DK_OptimizationRemarkMissed,
     65   DK_OptimizationRemarkAnalysis,
     66   DK_OptimizationRemarkAnalysisFPCommute,
     67   DK_OptimizationRemarkAnalysisAliasing,
     68   DK_OptimizationFailure,
     69   DK_FirstRemark = DK_OptimizationRemark,
     70   DK_LastRemark = DK_OptimizationFailure,
     71   DK_MachineOptimizationRemark,
     72   DK_MachineOptimizationRemarkMissed,
     73   DK_MachineOptimizationRemarkAnalysis,
     74   DK_FirstMachineRemark = DK_MachineOptimizationRemark,
     75   DK_LastMachineRemark = DK_MachineOptimizationRemarkAnalysis,
     76   DK_MIRParser,
     77   DK_PGOProfile,
     78   DK_Unsupported,
     79   DK_FirstPluginKind
     80 };
     81 
     82 /// Get the next available kind ID for a plugin diagnostic.
     83 /// Each time this function is called, it returns a different number.
     84 /// Therefore, a plugin that wants to "identify" its own classes
     85 /// with a dynamic identifier, just have to use this method to get a new ID
     86 /// and assign it to each of its classes.
     87 /// The returned ID will be greater than or equal to DK_FirstPluginKind.
     88 /// Thus, the plugin identifiers will not conflict with the
     89 /// DiagnosticKind values.
     90 int getNextAvailablePluginDiagnosticKind();
     91 
     92 /// This is the base abstract class for diagnostic reporting in
     93 /// the backend.
     94 /// The print method must be overloaded by the subclasses to print a
     95 /// user-friendly message in the client of the backend (let us call it a
     96 /// frontend).
     97 class DiagnosticInfo {
     98 private:
     99   /// Kind defines the kind of report this is about.
    100   const /* DiagnosticKind */ int Kind;
    101   /// Severity gives the severity of the diagnostic.
    102   const DiagnosticSeverity Severity;
    103 
    104 public:
    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 /// Common features for diagnostics dealing with optimization remarks
    393 /// that are used by both IR and MIR passes.
    394 class DiagnosticInfoOptimizationBase : public DiagnosticInfoWithLocationBase {
    395 public:
    396   /// Used to set IsVerbose via the stream interface.
    397   struct setIsVerbose {};
    398 
    399   /// When an instance of this is inserted into the stream, the arguments
    400   /// following will not appear in the remark printed in the compiler output
    401   /// (-Rpass) but only in the optimization record file
    402   /// (-fsave-optimization-record).
    403   struct setExtraArgs {};
    404 
    405   /// Used in the streaming interface as the general argument type.  It
    406   /// internally converts everything into a key-value pair.
    407   struct Argument {
    408     std::string Key;
    409     std::string Val;
    410     // If set, the debug location corresponding to the value.
    411     DiagnosticLocation Loc;
    412 
    413     explicit Argument(StringRef Str = "") : Key("String"), Val(Str) {}
    414     Argument(StringRef Key, const Value *V);
    415     Argument(StringRef Key, const Type *T);
    416     Argument(StringRef Key, StringRef S);
    417     Argument(StringRef Key, int N);
    418     Argument(StringRef Key, float N);
    419     Argument(StringRef Key, long N);
    420     Argument(StringRef Key, long long N);
    421     Argument(StringRef Key, unsigned N);
    422     Argument(StringRef Key, unsigned long N);
    423     Argument(StringRef Key, unsigned long long N);
    424     Argument(StringRef Key, bool B) : Key(Key), Val(B ? "true" : "false") {}
    425     Argument(StringRef Key, DebugLoc dl);
    426   };
    427 
    428   /// \p PassName is the name of the pass emitting this diagnostic. \p
    429   /// RemarkName is a textual identifier for the remark (single-word,
    430   /// camel-case). \p Fn is the function where the diagnostic is being emitted.
    431   /// \p Loc is the location information to use in the diagnostic. If line table
    432   /// information is available, the diagnostic will include the source code
    433   /// location.
    434   DiagnosticInfoOptimizationBase(enum DiagnosticKind Kind,
    435                                  enum DiagnosticSeverity Severity,
    436                                  const char *PassName, StringRef RemarkName,
    437                                  const Function &Fn,
    438                                  const DiagnosticLocation &Loc)
    439       : DiagnosticInfoWithLocationBase(Kind, Severity, Fn, Loc),
    440         PassName(PassName), RemarkName(RemarkName) {}
    441 
    442   void insert(StringRef S);
    443   void insert(Argument A);
    444   void insert(setIsVerbose V);
    445   void insert(setExtraArgs EA);
    446 
    447   /// \see DiagnosticInfo::print.
    448   void print(DiagnosticPrinter &DP) const override;
    449 
    450   /// Return true if this optimization remark is enabled by one of
    451   /// of the LLVM command line flags (-pass-remarks, -pass-remarks-missed,
    452   /// or -pass-remarks-analysis). Note that this only handles the LLVM
    453   /// flags. We cannot access Clang flags from here (they are handled
    454   /// in BackendConsumer::OptimizationRemarkHandler).
    455   virtual bool isEnabled() const = 0;
    456 
    457   StringRef getPassName() const { return PassName; }
    458   std::string getMsg() const;
    459   Optional<uint64_t> getHotness() const { return Hotness; }
    460   void setHotness(Optional<uint64_t> H) { Hotness = H; }
    461 
    462   bool isVerbose() const { return IsVerbose; }
    463 
    464   static bool classof(const DiagnosticInfo *DI) {
    465     return (DI->getKind() >= DK_FirstRemark &&
    466             DI->getKind() <= DK_LastRemark) ||
    467            (DI->getKind() >= DK_FirstMachineRemark &&
    468             DI->getKind() <= DK_LastMachineRemark);
    469   }
    470 
    471   bool isPassed() const {
    472     return (getKind() == DK_OptimizationRemark ||
    473             getKind() == DK_MachineOptimizationRemark);
    474   }
    475 
    476   bool isMissed() const {
    477     return (getKind() == DK_OptimizationRemarkMissed ||
    478             getKind() == DK_MachineOptimizationRemarkMissed);
    479   }
    480 
    481   bool isAnalysis() const {
    482     return (getKind() == DK_OptimizationRemarkAnalysis ||
    483             getKind() == DK_MachineOptimizationRemarkAnalysis);
    484   }
    485 
    486 protected:
    487   /// Name of the pass that triggers this report. If this matches the
    488   /// regular expression given in -Rpass=regexp, then the remark will
    489   /// be emitted.
    490   const char *PassName;
    491 
    492   /// Textual identifier for the remark (single-word, camel-case). Can be used
    493   /// by external tools reading the YAML output file for optimization remarks to
    494   /// identify the remark.
    495   StringRef RemarkName;
    496 
    497   /// If profile information is available, this is the number of times the
    498   /// corresponding code was executed in a profile instrumentation run.
    499   Optional<uint64_t> Hotness;
    500 
    501   /// Arguments collected via the streaming interface.
    502   SmallVector<Argument, 4> Args;
    503 
    504   /// The remark is expected to be noisy.
    505   bool IsVerbose = false;
    506 
    507   /// If positive, the index of the first argument that only appear in
    508   /// the optimization records and not in the remark printed in the compiler
    509   /// output.
    510   int FirstExtraArgIndex = -1;
    511 
    512   friend struct yaml::MappingTraits<DiagnosticInfoOptimizationBase *>;
    513 };
    514 
    515 /// Allow the insertion operator to return the actual remark type rather than a
    516 /// common base class.  This allows returning the result of the insertion
    517 /// directly by value, e.g. return OptimizationRemarkAnalysis(...) << "blah".
    518 template <class RemarkT>
    519 RemarkT &
    520 operator<<(RemarkT &R,
    521            typename std::enable_if<
    522                std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
    523                StringRef>::type S) {
    524   R.insert(S);
    525   return R;
    526 }
    527 
    528 /// Also allow r-value for the remark to allow insertion into a
    529 /// temporarily-constructed remark.
    530 template <class RemarkT>
    531 RemarkT &
    532 operator<<(RemarkT &&R,
    533            typename std::enable_if<
    534                std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
    535                StringRef>::type S) {
    536   R.insert(S);
    537   return R;
    538 }
    539 
    540 template <class RemarkT>
    541 RemarkT &
    542 operator<<(RemarkT &R,
    543            typename std::enable_if<
    544                std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
    545                DiagnosticInfoOptimizationBase::Argument>::type A) {
    546   R.insert(A);
    547   return R;
    548 }
    549 
    550 template <class RemarkT>
    551 RemarkT &
    552 operator<<(RemarkT &&R,
    553            typename std::enable_if<
    554                std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
    555                DiagnosticInfoOptimizationBase::Argument>::type A) {
    556   R.insert(A);
    557   return R;
    558 }
    559 
    560 template <class RemarkT>
    561 RemarkT &
    562 operator<<(RemarkT &R,
    563            typename std::enable_if<
    564                std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
    565                DiagnosticInfoOptimizationBase::setIsVerbose>::type V) {
    566   R.insert(V);
    567   return R;
    568 }
    569 
    570 template <class RemarkT>
    571 RemarkT &
    572 operator<<(RemarkT &&R,
    573            typename std::enable_if<
    574                std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
    575                DiagnosticInfoOptimizationBase::setIsVerbose>::type V) {
    576   R.insert(V);
    577   return R;
    578 }
    579 
    580 template <class RemarkT>
    581 RemarkT &
    582 operator<<(RemarkT &R,
    583            typename std::enable_if<
    584                std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
    585                DiagnosticInfoOptimizationBase::setExtraArgs>::type EA) {
    586   R.insert(EA);
    587   return R;
    588 }
    589 
    590 /// Common features for diagnostics dealing with optimization remarks
    591 /// that are used by IR passes.
    592 class DiagnosticInfoIROptimization : public DiagnosticInfoOptimizationBase {
    593 public:
    594   /// \p PassName is the name of the pass emitting this diagnostic. \p
    595   /// RemarkName is a textual identifier for the remark (single-word,
    596   /// camel-case). \p Fn is the function where the diagnostic is being emitted.
    597   /// \p Loc is the location information to use in the diagnostic. If line table
    598   /// information is available, the diagnostic will include the source code
    599   /// location. \p CodeRegion is IR value (currently basic block) that the
    600   /// optimization operates on. This is currently used to provide run-time
    601   /// hotness information with PGO.
    602   DiagnosticInfoIROptimization(enum DiagnosticKind Kind,
    603                                enum DiagnosticSeverity Severity,
    604                                const char *PassName, StringRef RemarkName,
    605                                const Function &Fn,
    606                                const DiagnosticLocation &Loc,
    607                                const Value *CodeRegion = nullptr)
    608       : DiagnosticInfoOptimizationBase(Kind, Severity, PassName, RemarkName, Fn,
    609                                        Loc),
    610         CodeRegion(CodeRegion) {}
    611 
    612   /// This is ctor variant allows a pass to build an optimization remark
    613   /// from an existing remark.
    614   ///
    615   /// This is useful when a transformation pass (e.g LV) wants to emit a remark
    616   /// (\p Orig) generated by one of its analyses (e.g. LAA) as its own analysis
    617   /// remark.  The string \p Prepend will be emitted before the original
    618   /// message.
    619   DiagnosticInfoIROptimization(const char *PassName, StringRef Prepend,
    620                                const DiagnosticInfoIROptimization &Orig)
    621       : DiagnosticInfoOptimizationBase(
    622             (DiagnosticKind)Orig.getKind(), Orig.getSeverity(), PassName,
    623             Orig.RemarkName, Orig.getFunction(), Orig.getLocation()),
    624         CodeRegion(Orig.getCodeRegion()) {
    625     *this << Prepend;
    626     std::copy(Orig.Args.begin(), Orig.Args.end(), std::back_inserter(Args));
    627   }
    628 
    629   /// Legacy interface.
    630   /// \p PassName is the name of the pass emitting this diagnostic.
    631   /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
    632   /// the location information to use in the diagnostic. If line table
    633   /// information is available, the diagnostic will include the source code
    634   /// location. \p Msg is the message to show. Note that this class does not
    635   /// copy this message, so this reference must be valid for the whole life time
    636   /// of the diagnostic.
    637   DiagnosticInfoIROptimization(enum DiagnosticKind Kind,
    638                                enum DiagnosticSeverity Severity,
    639                                const char *PassName, const Function &Fn,
    640                                const DiagnosticLocation &Loc, const Twine &Msg)
    641       : DiagnosticInfoOptimizationBase(Kind, Severity, PassName, "", Fn, Loc) {
    642     *this << Msg.str();
    643   }
    644 
    645   const Value *getCodeRegion() const { return CodeRegion; }
    646 
    647   static bool classof(const DiagnosticInfo *DI) {
    648     return DI->getKind() >= DK_FirstRemark && DI->getKind() <= DK_LastRemark;
    649   }
    650 
    651 private:
    652   /// The IR value (currently basic block) that the optimization operates on.
    653   /// This is currently used to provide run-time hotness information with PGO.
    654   const Value *CodeRegion;
    655 };
    656 
    657 /// Diagnostic information for applied optimization remarks.
    658 class OptimizationRemark : public DiagnosticInfoIROptimization {
    659 public:
    660   /// \p PassName is the name of the pass emitting this diagnostic. If this name
    661   /// matches the regular expression given in -Rpass=, then the diagnostic will
    662   /// be emitted. \p RemarkName is a textual identifier for the remark (single-
    663   /// word, camel-case). \p Loc is the debug location and \p CodeRegion is the
    664   /// region that the optimization operates on (currently only block is
    665   /// supported).
    666   OptimizationRemark(const char *PassName, StringRef RemarkName,
    667                      const DiagnosticLocation &Loc, const Value *CodeRegion);
    668 
    669   /// Same as above, but the debug location and code region are derived from \p
    670   /// Instr.
    671   OptimizationRemark(const char *PassName, StringRef RemarkName,
    672                      const Instruction *Inst);
    673 
    674   /// Same as above, but the debug location and code region are derived from \p
    675   /// Func.
    676   OptimizationRemark(const char *PassName, StringRef RemarkName,
    677                      const Function *Func);
    678 
    679   static bool classof(const DiagnosticInfo *DI) {
    680     return DI->getKind() == DK_OptimizationRemark;
    681   }
    682 
    683   /// \see DiagnosticInfoOptimizationBase::isEnabled.
    684   bool isEnabled() const override;
    685 
    686 private:
    687   /// This is deprecated now and only used by the function API below.
    688   /// \p PassName is the name of the pass emitting this diagnostic. If
    689   /// this name matches the regular expression given in -Rpass=, then the
    690   /// diagnostic will be emitted. \p Fn is the function where the diagnostic
    691   /// is being emitted. \p Loc is the location information to use in the
    692   /// diagnostic. If line table information is available, the diagnostic
    693   /// will include the source code location. \p Msg is the message to show.
    694   /// Note that this class does not copy this message, so this reference
    695   /// must be valid for the whole life time of the diagnostic.
    696   OptimizationRemark(const char *PassName, const Function &Fn,
    697                      const DiagnosticLocation &Loc, const Twine &Msg)
    698       : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,
    699                                      Fn, Loc, Msg) {}
    700 };
    701 
    702 /// Diagnostic information for missed-optimization remarks.
    703 class OptimizationRemarkMissed : public DiagnosticInfoIROptimization {
    704 public:
    705   /// \p PassName is the name of the pass emitting this diagnostic. If this name
    706   /// matches the regular expression given in -Rpass-missed=, then the
    707   /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
    708   /// remark (single-word, camel-case). \p Loc is the debug location and \p
    709   /// CodeRegion is the region that the optimization operates on (currently only
    710   /// block is supported).
    711   OptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
    712                            const DiagnosticLocation &Loc,
    713                            const Value *CodeRegion);
    714 
    715   /// Same as above but \p Inst is used to derive code region and debug
    716   /// location.
    717   OptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
    718                            const Instruction *Inst);
    719 
    720   static bool classof(const DiagnosticInfo *DI) {
    721     return DI->getKind() == DK_OptimizationRemarkMissed;
    722   }
    723 
    724   /// \see DiagnosticInfoOptimizationBase::isEnabled.
    725   bool isEnabled() const override;
    726 
    727 private:
    728   /// This is deprecated now and only used by the function API below.
    729   /// \p PassName is the name of the pass emitting this diagnostic. If
    730   /// this name matches the regular expression given in -Rpass-missed=, then the
    731   /// diagnostic will be emitted. \p Fn is the function where the diagnostic
    732   /// is being emitted. \p Loc is the location information to use in the
    733   /// diagnostic. If line table information is available, the diagnostic
    734   /// will include the source code location. \p Msg is the message to show.
    735   /// Note that this class does not copy this message, so this reference
    736   /// must be valid for the whole life time of the diagnostic.
    737   OptimizationRemarkMissed(const char *PassName, const Function &Fn,
    738                            const DiagnosticLocation &Loc, const Twine &Msg)
    739       : DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark,
    740                                      PassName, Fn, Loc, Msg) {}
    741 };
    742 
    743 /// Diagnostic information for optimization analysis remarks.
    744 class OptimizationRemarkAnalysis : public DiagnosticInfoIROptimization {
    745 public:
    746   /// \p PassName is the name of the pass emitting this diagnostic. If this name
    747   /// matches the regular expression given in -Rpass-analysis=, then the
    748   /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
    749   /// remark (single-word, camel-case). \p Loc is the debug location and \p
    750   /// CodeRegion is the region that the optimization operates on (currently only
    751   /// block is supported).
    752   OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
    753                              const DiagnosticLocation &Loc,
    754                              const Value *CodeRegion);
    755 
    756   /// This is ctor variant allows a pass to build an optimization remark
    757   /// from an existing remark.
    758   ///
    759   /// This is useful when a transformation pass (e.g LV) wants to emit a remark
    760   /// (\p Orig) generated by one of its analyses (e.g. LAA) as its own analysis
    761   /// remark.  The string \p Prepend will be emitted before the original
    762   /// message.
    763   OptimizationRemarkAnalysis(const char *PassName, StringRef Prepend,
    764                              const OptimizationRemarkAnalysis &Orig)
    765       : DiagnosticInfoIROptimization(PassName, Prepend, Orig) {}
    766 
    767   /// Same as above but \p Inst is used to derive code region and debug
    768   /// location.
    769   OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
    770                              const Instruction *Inst);
    771 
    772   static bool classof(const DiagnosticInfo *DI) {
    773     return DI->getKind() == DK_OptimizationRemarkAnalysis;
    774   }
    775 
    776   /// \see DiagnosticInfoOptimizationBase::isEnabled.
    777   bool isEnabled() const override;
    778 
    779   static const char *AlwaysPrint;
    780 
    781   bool shouldAlwaysPrint() const { return getPassName() == AlwaysPrint; }
    782 
    783 protected:
    784   OptimizationRemarkAnalysis(enum DiagnosticKind Kind, const char *PassName,
    785                              const Function &Fn, const DiagnosticLocation &Loc,
    786                              const Twine &Msg)
    787       : DiagnosticInfoIROptimization(Kind, DS_Remark, PassName, Fn, Loc, Msg) {}
    788 
    789   OptimizationRemarkAnalysis(enum DiagnosticKind Kind, const char *PassName,
    790                              StringRef RemarkName,
    791                              const DiagnosticLocation &Loc,
    792                              const Value *CodeRegion);
    793 
    794 private:
    795   /// This is deprecated now and only used by the function API below.
    796   /// \p PassName is the name of the pass emitting this diagnostic. If
    797   /// this name matches the regular expression given in -Rpass-analysis=, then
    798   /// the diagnostic will be emitted. \p Fn is the function where the diagnostic
    799   /// is being emitted. \p Loc is the location information to use in the
    800   /// diagnostic. If line table information is available, the diagnostic will
    801   /// include the source code location. \p Msg is the message to show. Note that
    802   /// this class does not copy this message, so this reference must be valid for
    803   /// the whole life time of the diagnostic.
    804   OptimizationRemarkAnalysis(const char *PassName, const Function &Fn,
    805                              const DiagnosticLocation &Loc, const Twine &Msg)
    806       : DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark,
    807                                      PassName, Fn, Loc, Msg) {}
    808 };
    809 
    810 /// Diagnostic information for optimization analysis remarks related to
    811 /// floating-point non-commutativity.
    812 class OptimizationRemarkAnalysisFPCommute : public OptimizationRemarkAnalysis {
    813 public:
    814   /// \p PassName is the name of the pass emitting this diagnostic. If this name
    815   /// matches the regular expression given in -Rpass-analysis=, then the
    816   /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
    817   /// remark (single-word, camel-case). \p Loc is the debug location and \p
    818   /// CodeRegion is the region that the optimization operates on (currently only
    819   /// block is supported). The front-end will append its own message related to
    820   /// options that address floating-point non-commutativity.
    821   OptimizationRemarkAnalysisFPCommute(const char *PassName,
    822                                       StringRef RemarkName,
    823                                       const DiagnosticLocation &Loc,
    824                                       const Value *CodeRegion)
    825       : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute,
    826                                    PassName, RemarkName, Loc, CodeRegion) {}
    827 
    828   static bool classof(const DiagnosticInfo *DI) {
    829     return DI->getKind() == DK_OptimizationRemarkAnalysisFPCommute;
    830   }
    831 
    832 private:
    833   /// This is deprecated now and only used by the function API below.
    834   /// \p PassName is the name of the pass emitting this diagnostic. If
    835   /// this name matches the regular expression given in -Rpass-analysis=, then
    836   /// the diagnostic will be emitted. \p Fn is the function where the diagnostic
    837   /// is being emitted. \p Loc is the location information to use in the
    838   /// diagnostic. If line table information is available, the diagnostic will
    839   /// include the source code location. \p Msg is the message to show. The
    840   /// front-end will append its own message related to options that address
    841   /// floating-point non-commutativity. Note that this class does not copy this
    842   /// message, so this reference must be valid for the whole life time of the
    843   /// diagnostic.
    844   OptimizationRemarkAnalysisFPCommute(const char *PassName, const Function &Fn,
    845                                       const DiagnosticLocation &Loc,
    846                                       const Twine &Msg)
    847       : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute,
    848                                    PassName, Fn, Loc, Msg) {}
    849 };
    850 
    851 /// Diagnostic information for optimization analysis remarks related to
    852 /// pointer aliasing.
    853 class OptimizationRemarkAnalysisAliasing : public OptimizationRemarkAnalysis {
    854 public:
    855   /// \p PassName is the name of the pass emitting this diagnostic. If this name
    856   /// matches the regular expression given in -Rpass-analysis=, then the
    857   /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
    858   /// remark (single-word, camel-case). \p Loc is the debug location and \p
    859   /// CodeRegion is the region that the optimization operates on (currently only
    860   /// block is supported). The front-end will append its own message related to
    861   /// options that address pointer aliasing legality.
    862   OptimizationRemarkAnalysisAliasing(const char *PassName, StringRef RemarkName,
    863                                      const DiagnosticLocation &Loc,
    864                                      const Value *CodeRegion)
    865       : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing,
    866                                    PassName, RemarkName, Loc, CodeRegion) {}
    867 
    868   static bool classof(const DiagnosticInfo *DI) {
    869     return DI->getKind() == DK_OptimizationRemarkAnalysisAliasing;
    870   }
    871 
    872 private:
    873   /// This is deprecated now and only used by the function API below.
    874   /// \p PassName is the name of the pass emitting this diagnostic. If
    875   /// this name matches the regular expression given in -Rpass-analysis=, then
    876   /// the diagnostic will be emitted. \p Fn is the function where the diagnostic
    877   /// is being emitted. \p Loc is the location information to use in the
    878   /// diagnostic. If line table information is available, the diagnostic will
    879   /// include the source code location. \p Msg is the message to show. The
    880   /// front-end will append its own message related to options that address
    881   /// pointer aliasing legality. Note that this class does not copy this
    882   /// message, so this reference must be valid for the whole life time of the
    883   /// diagnostic.
    884   OptimizationRemarkAnalysisAliasing(const char *PassName, const Function &Fn,
    885                                      const DiagnosticLocation &Loc,
    886                                      const Twine &Msg)
    887       : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing,
    888                                    PassName, Fn, Loc, Msg) {}
    889 };
    890 
    891 /// Diagnostic information for machine IR parser.
    892 class DiagnosticInfoMIRParser : public DiagnosticInfo {
    893   const SMDiagnostic &Diagnostic;
    894 
    895 public:
    896   DiagnosticInfoMIRParser(DiagnosticSeverity Severity,
    897                           const SMDiagnostic &Diagnostic)
    898       : DiagnosticInfo(DK_MIRParser, Severity), Diagnostic(Diagnostic) {}
    899 
    900   const SMDiagnostic &getDiagnostic() const { return Diagnostic; }
    901 
    902   void print(DiagnosticPrinter &DP) const override;
    903 
    904   static bool classof(const DiagnosticInfo *DI) {
    905     return DI->getKind() == DK_MIRParser;
    906   }
    907 };
    908 
    909 /// Diagnostic information for ISel fallback path.
    910 class DiagnosticInfoISelFallback : public DiagnosticInfo {
    911   /// The function that is concerned by this diagnostic.
    912   const Function &Fn;
    913 
    914 public:
    915   DiagnosticInfoISelFallback(const Function &Fn,
    916                              DiagnosticSeverity Severity = DS_Warning)
    917       : DiagnosticInfo(DK_ISelFallback, Severity), Fn(Fn) {}
    918 
    919   const Function &getFunction() const { return Fn; }
    920 
    921   void print(DiagnosticPrinter &DP) const override;
    922 
    923   static bool classof(const DiagnosticInfo *DI) {
    924     return DI->getKind() == DK_ISelFallback;
    925   }
    926 };
    927 
    928 // Create wrappers for C Binding types (see CBindingWrapping.h).
    929 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DiagnosticInfo, LLVMDiagnosticInfoRef)
    930 
    931 /// Diagnostic information for optimization failures.
    932 class DiagnosticInfoOptimizationFailure : public DiagnosticInfoIROptimization {
    933 public:
    934   /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
    935   /// the location information to use in the diagnostic. If line table
    936   /// information is available, the diagnostic will include the source code
    937   /// location. \p Msg is the message to show. Note that this class does not
    938   /// copy this message, so this reference must be valid for the whole life time
    939   /// of the diagnostic.
    940   DiagnosticInfoOptimizationFailure(const Function &Fn,
    941                                     const DiagnosticLocation &Loc,
    942                                     const Twine &Msg)
    943       : DiagnosticInfoIROptimization(DK_OptimizationFailure, DS_Warning,
    944                                      nullptr, Fn, Loc, Msg) {}
    945 
    946   /// \p PassName is the name of the pass emitting this diagnostic.  \p
    947   /// RemarkName is a textual identifier for the remark (single-word,
    948   /// camel-case).  \p Loc is the debug location and \p CodeRegion is the
    949   /// region that the optimization operates on (currently basic block is
    950   /// supported).
    951   DiagnosticInfoOptimizationFailure(const char *PassName, StringRef RemarkName,
    952                                     const DiagnosticLocation &Loc,
    953                                     const Value *CodeRegion);
    954 
    955   static bool classof(const DiagnosticInfo *DI) {
    956     return DI->getKind() == DK_OptimizationFailure;
    957   }
    958 
    959   /// \see DiagnosticInfoOptimizationBase::isEnabled.
    960   bool isEnabled() const override;
    961 };
    962 
    963 /// Diagnostic information for unsupported feature in backend.
    964 class DiagnosticInfoUnsupported : public DiagnosticInfoWithLocationBase {
    965 private:
    966   Twine Msg;
    967 
    968 public:
    969   /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
    970   /// the location information to use in the diagnostic. If line table
    971   /// information is available, the diagnostic will include the source code
    972   /// location. \p Msg is the message to show. Note that this class does not
    973   /// copy this message, so this reference must be valid for the whole life time
    974   /// of the diagnostic.
    975   DiagnosticInfoUnsupported(
    976       const Function &Fn, const Twine &Msg,
    977       const DiagnosticLocation &Loc = DiagnosticLocation(),
    978       DiagnosticSeverity Severity = DS_Error)
    979       : DiagnosticInfoWithLocationBase(DK_Unsupported, Severity, Fn, Loc),
    980         Msg(Msg) {}
    981 
    982   static bool classof(const DiagnosticInfo *DI) {
    983     return DI->getKind() == DK_Unsupported;
    984   }
    985 
    986   const Twine &getMessage() const { return Msg; }
    987 
    988   void print(DiagnosticPrinter &DP) const override;
    989 };
    990 
    991 namespace yaml {
    992 template <> struct MappingTraits<DiagnosticInfoOptimizationBase *> {
    993   static void mapping(IO &io, DiagnosticInfoOptimizationBase *&OptDiag);
    994 };
    995 } // namespace yaml
    996 
    997 } // end namespace llvm
    998 
    999 #endif // LLVM_IR_DIAGNOSTICINFO_H
   1000