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