1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===- llvm/IR/DiagnosticInfo.h - Diagnostic Declaration --------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This file declares the different classes involved in low level diagnostics.
- //
- // Diagnostics reporting is still done as part of the LLVMContext.
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_IR_DIAGNOSTICINFO_H
- #define LLVM_IR_DIAGNOSTICINFO_H
- #include "llvm-c/Types.h"
- #include "llvm/ADT/ArrayRef.h"
- #include "llvm/ADT/Optional.h"
- #include "llvm/ADT/SmallVector.h"
- #include "llvm/ADT/StringRef.h"
- #include "llvm/ADT/Twine.h"
- #include "llvm/IR/DebugLoc.h"
- #include "llvm/Support/CBindingWrapping.h"
- #include "llvm/Support/ErrorHandling.h"
- #include "llvm/Support/SourceMgr.h"
- #include "llvm/Support/TypeSize.h"
- #include <algorithm>
- #include <cstdint>
- #include <functional>
- #include <iterator>
- #include <string>
- namespace llvm {
- // Forward declarations.
- class DiagnosticPrinter;
- class DIFile;
- class DISubprogram;
- class CallInst;
- class Function;
- class Instruction;
- class InstructionCost;
- class Module;
- class Type;
- class Value;
- /// Defines the different supported severity of a diagnostic.
- enum DiagnosticSeverity : char {
- DS_Error,
- DS_Warning,
- DS_Remark,
- // A note attaches additional information to one of the previous diagnostic
- // types.
- DS_Note
- };
- /// Defines the different supported kind of a diagnostic.
- /// This enum should be extended with a new ID for each added concrete subclass.
- enum DiagnosticKind {
- DK_InlineAsm,
- DK_ResourceLimit,
- DK_StackSize,
- DK_Linker,
- DK_Lowering,
- DK_DebugMetadataVersion,
- DK_DebugMetadataInvalid,
- DK_ISelFallback,
- DK_SampleProfile,
- DK_OptimizationRemark,
- DK_OptimizationRemarkMissed,
- DK_OptimizationRemarkAnalysis,
- DK_OptimizationRemarkAnalysisFPCommute,
- DK_OptimizationRemarkAnalysisAliasing,
- DK_OptimizationFailure,
- DK_FirstRemark = DK_OptimizationRemark,
- DK_LastRemark = DK_OptimizationFailure,
- DK_MachineOptimizationRemark,
- DK_MachineOptimizationRemarkMissed,
- DK_MachineOptimizationRemarkAnalysis,
- DK_FirstMachineRemark = DK_MachineOptimizationRemark,
- DK_LastMachineRemark = DK_MachineOptimizationRemarkAnalysis,
- DK_MIRParser,
- DK_PGOProfile,
- DK_Unsupported,
- DK_SrcMgr,
- DK_DontCall,
- DK_FirstPluginKind // Must be last value to work with
- // getNextAvailablePluginDiagnosticKind
- };
- /// Get the next available kind ID for a plugin diagnostic.
- /// Each time this function is called, it returns a different number.
- /// Therefore, a plugin that wants to "identify" its own classes
- /// with a dynamic identifier, just have to use this method to get a new ID
- /// and assign it to each of its classes.
- /// The returned ID will be greater than or equal to DK_FirstPluginKind.
- /// Thus, the plugin identifiers will not conflict with the
- /// DiagnosticKind values.
- int getNextAvailablePluginDiagnosticKind();
- /// This is the base abstract class for diagnostic reporting in
- /// the backend.
- /// The print method must be overloaded by the subclasses to print a
- /// user-friendly message in the client of the backend (let us call it a
- /// frontend).
- class DiagnosticInfo {
- private:
- /// Kind defines the kind of report this is about.
- const /* DiagnosticKind */ int Kind;
- /// Severity gives the severity of the diagnostic.
- const DiagnosticSeverity Severity;
- virtual void anchor();
- public:
- DiagnosticInfo(/* DiagnosticKind */ int Kind, DiagnosticSeverity Severity)
- : Kind(Kind), Severity(Severity) {}
- virtual ~DiagnosticInfo() = default;
- /* DiagnosticKind */ int getKind() const { return Kind; }
- DiagnosticSeverity getSeverity() const { return Severity; }
- /// Print using the given \p DP a user-friendly message.
- /// This is the default message that will be printed to the user.
- /// It is used when the frontend does not directly take advantage
- /// of the information contained in fields of the subclasses.
- /// The printed message must not end with '.' nor start with a severity
- /// keyword.
- virtual void print(DiagnosticPrinter &DP) const = 0;
- };
- using DiagnosticHandlerFunction = std::function<void(const DiagnosticInfo &)>;
- /// Diagnostic information for inline asm reporting.
- /// This is basically a message and an optional location.
- class DiagnosticInfoInlineAsm : public DiagnosticInfo {
- private:
- /// Optional line information. 0 if not set.
- uint64_t LocCookie = 0;
- /// Message to be reported.
- const Twine &MsgStr;
- /// Optional origin of the problem.
- const Instruction *Instr = nullptr;
- public:
- /// \p MsgStr is the message to be reported to the frontend.
- /// This class does not copy \p MsgStr, therefore the reference must be valid
- /// for the whole life time of the Diagnostic.
- DiagnosticInfoInlineAsm(const Twine &MsgStr,
- DiagnosticSeverity Severity = DS_Error)
- : DiagnosticInfo(DK_InlineAsm, Severity), MsgStr(MsgStr) {}
- /// \p LocCookie if non-zero gives the line number for this report.
- /// \p MsgStr gives the message.
- /// This class does not copy \p MsgStr, therefore the reference must be valid
- /// for the whole life time of the Diagnostic.
- DiagnosticInfoInlineAsm(uint64_t LocCookie, const Twine &MsgStr,
- DiagnosticSeverity Severity = DS_Error)
- : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(LocCookie),
- MsgStr(MsgStr) {}
- /// \p Instr gives the original instruction that triggered the diagnostic.
- /// \p MsgStr gives the message.
- /// This class does not copy \p MsgStr, therefore the reference must be valid
- /// for the whole life time of the Diagnostic.
- /// Same for \p I.
- DiagnosticInfoInlineAsm(const Instruction &I, const Twine &MsgStr,
- DiagnosticSeverity Severity = DS_Error);
- uint64_t getLocCookie() const { return LocCookie; }
- const Twine &getMsgStr() const { return MsgStr; }
- const Instruction *getInstruction() const { return Instr; }
- /// \see DiagnosticInfo::print.
- void print(DiagnosticPrinter &DP) const override;
- static bool classof(const DiagnosticInfo *DI) {
- return DI->getKind() == DK_InlineAsm;
- }
- };
- /// Diagnostic information for stack size etc. reporting.
- /// This is basically a function and a size.
- class DiagnosticInfoResourceLimit : public DiagnosticInfo {
- private:
- /// The function that is concerned by this resource limit diagnostic.
- const Function &Fn;
- /// Description of the resource type (e.g. stack size)
- const char *ResourceName;
- /// The computed size usage
- uint64_t ResourceSize;
- // Threshould passed
- uint64_t ResourceLimit;
- public:
- /// \p The function that is concerned by this stack size diagnostic.
- /// \p The computed stack size.
- DiagnosticInfoResourceLimit(const Function &Fn, const char *ResourceName,
- uint64_t ResourceSize, uint64_t ResourceLimit,
- DiagnosticSeverity Severity = DS_Warning,
- DiagnosticKind Kind = DK_ResourceLimit)
- : DiagnosticInfo(Kind, Severity), Fn(Fn), ResourceName(ResourceName),
- ResourceSize(ResourceSize), ResourceLimit(ResourceLimit) {}
- const Function &getFunction() const { return Fn; }
- const char *getResourceName() const { return ResourceName; }
- uint64_t getResourceSize() const { return ResourceSize; }
- uint64_t getResourceLimit() const { return ResourceLimit; }
- /// \see DiagnosticInfo::print.
- void print(DiagnosticPrinter &DP) const override;
- static bool classof(const DiagnosticInfo *DI) {
- return DI->getKind() == DK_ResourceLimit || DI->getKind() == DK_StackSize;
- }
- };
- class DiagnosticInfoStackSize : public DiagnosticInfoResourceLimit {
- void anchor() override;
- public:
- DiagnosticInfoStackSize(const Function &Fn, uint64_t StackSize,
- uint64_t StackLimit,
- DiagnosticSeverity Severity = DS_Warning)
- : DiagnosticInfoResourceLimit(Fn, "stack frame size", StackSize,
- StackLimit, Severity, DK_StackSize) {}
- uint64_t getStackSize() const { return getResourceSize(); }
- uint64_t getStackLimit() const { return getResourceLimit(); }
- static bool classof(const DiagnosticInfo *DI) {
- return DI->getKind() == DK_StackSize;
- }
- };
- /// Diagnostic information for debug metadata version reporting.
- /// This is basically a module and a version.
- class DiagnosticInfoDebugMetadataVersion : public DiagnosticInfo {
- private:
- /// The module that is concerned by this debug metadata version diagnostic.
- const Module &M;
- /// The actual metadata version.
- unsigned MetadataVersion;
- public:
- /// \p The module that is concerned by this debug metadata version diagnostic.
- /// \p The actual metadata version.
- DiagnosticInfoDebugMetadataVersion(const Module &M, unsigned MetadataVersion,
- DiagnosticSeverity Severity = DS_Warning)
- : DiagnosticInfo(DK_DebugMetadataVersion, Severity), M(M),
- MetadataVersion(MetadataVersion) {}
- const Module &getModule() const { return M; }
- unsigned getMetadataVersion() const { return MetadataVersion; }
- /// \see DiagnosticInfo::print.
- void print(DiagnosticPrinter &DP) const override;
- static bool classof(const DiagnosticInfo *DI) {
- return DI->getKind() == DK_DebugMetadataVersion;
- }
- };
- /// Diagnostic information for stripping invalid debug metadata.
- class DiagnosticInfoIgnoringInvalidDebugMetadata : public DiagnosticInfo {
- private:
- /// The module that is concerned by this debug metadata version diagnostic.
- const Module &M;
- public:
- /// \p The module that is concerned by this debug metadata version diagnostic.
- DiagnosticInfoIgnoringInvalidDebugMetadata(
- const Module &M, DiagnosticSeverity Severity = DS_Warning)
- : DiagnosticInfo(DK_DebugMetadataVersion, Severity), M(M) {}
- const Module &getModule() const { return M; }
- /// \see DiagnosticInfo::print.
- void print(DiagnosticPrinter &DP) const override;
- static bool classof(const DiagnosticInfo *DI) {
- return DI->getKind() == DK_DebugMetadataInvalid;
- }
- };
- /// Diagnostic information for the sample profiler.
- class DiagnosticInfoSampleProfile : public DiagnosticInfo {
- public:
- DiagnosticInfoSampleProfile(StringRef FileName, unsigned LineNum,
- const Twine &Msg,
- DiagnosticSeverity Severity = DS_Error)
- : DiagnosticInfo(DK_SampleProfile, Severity), FileName(FileName),
- LineNum(LineNum), Msg(Msg) {}
- DiagnosticInfoSampleProfile(StringRef FileName, const Twine &Msg,
- DiagnosticSeverity Severity = DS_Error)
- : DiagnosticInfo(DK_SampleProfile, Severity), FileName(FileName),
- Msg(Msg) {}
- DiagnosticInfoSampleProfile(const Twine &Msg,
- DiagnosticSeverity Severity = DS_Error)
- : DiagnosticInfo(DK_SampleProfile, Severity), Msg(Msg) {}
- /// \see DiagnosticInfo::print.
- void print(DiagnosticPrinter &DP) const override;
- static bool classof(const DiagnosticInfo *DI) {
- return DI->getKind() == DK_SampleProfile;
- }
- StringRef getFileName() const { return FileName; }
- unsigned getLineNum() const { return LineNum; }
- const Twine &getMsg() const { return Msg; }
- private:
- /// Name of the input file associated with this diagnostic.
- StringRef FileName;
- /// Line number where the diagnostic occurred. If 0, no line number will
- /// be emitted in the message.
- unsigned LineNum = 0;
- /// Message to report.
- const Twine &Msg;
- };
- /// Diagnostic information for the PGO profiler.
- class DiagnosticInfoPGOProfile : public DiagnosticInfo {
- public:
- DiagnosticInfoPGOProfile(const char *FileName, const Twine &Msg,
- DiagnosticSeverity Severity = DS_Error)
- : DiagnosticInfo(DK_PGOProfile, Severity), FileName(FileName), Msg(Msg) {}
- /// \see DiagnosticInfo::print.
- void print(DiagnosticPrinter &DP) const override;
- static bool classof(const DiagnosticInfo *DI) {
- return DI->getKind() == DK_PGOProfile;
- }
- const char *getFileName() const { return FileName; }
- const Twine &getMsg() const { return Msg; }
- private:
- /// Name of the input file associated with this diagnostic.
- const char *FileName;
- /// Message to report.
- const Twine &Msg;
- };
- class DiagnosticLocation {
- DIFile *File = nullptr;
- unsigned Line = 0;
- unsigned Column = 0;
- public:
- DiagnosticLocation() = default;
- DiagnosticLocation(const DebugLoc &DL);
- DiagnosticLocation(const DISubprogram *SP);
- bool isValid() const { return File; }
- /// Return the full path to the file.
- std::string getAbsolutePath() const;
- /// Return the file name relative to the compilation directory.
- StringRef getRelativePath() const;
- unsigned getLine() const { return Line; }
- unsigned getColumn() const { return Column; }
- };
- /// Common features for diagnostics with an associated location.
- class DiagnosticInfoWithLocationBase : public DiagnosticInfo {
- void anchor() override;
- public:
- /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
- /// the location information to use in the diagnostic.
- DiagnosticInfoWithLocationBase(enum DiagnosticKind Kind,
- enum DiagnosticSeverity Severity,
- const Function &Fn,
- const DiagnosticLocation &Loc)
- : DiagnosticInfo(Kind, Severity), Fn(Fn), Loc(Loc) {}
- /// Return true if location information is available for this diagnostic.
- bool isLocationAvailable() const { return Loc.isValid(); }
- /// Return a string with the location information for this diagnostic
- /// in the format "file:line:col". If location information is not available,
- /// it returns "<unknown>:0:0".
- std::string getLocationStr() const;
- /// Return location information for this diagnostic in three parts:
- /// the relative source file path, line number and column.
- void getLocation(StringRef &RelativePath, unsigned &Line,
- unsigned &Column) const;
- /// Return the absolute path tot the file.
- std::string getAbsolutePath() const;
-
- const Function &getFunction() const { return Fn; }
- DiagnosticLocation getLocation() const { return Loc; }
- private:
- /// Function where this diagnostic is triggered.
- const Function &Fn;
- /// Debug location where this diagnostic is triggered.
- DiagnosticLocation Loc;
- };
- /// Common features for diagnostics dealing with optimization remarks
- /// that are used by both IR and MIR passes.
- class DiagnosticInfoOptimizationBase : public DiagnosticInfoWithLocationBase {
- public:
- /// Used to set IsVerbose via the stream interface.
- struct setIsVerbose {};
- /// When an instance of this is inserted into the stream, the arguments
- /// following will not appear in the remark printed in the compiler output
- /// (-Rpass) but only in the optimization record file
- /// (-fsave-optimization-record).
- struct setExtraArgs {};
- /// Used in the streaming interface as the general argument type. It
- /// internally converts everything into a key-value pair.
- struct Argument {
- std::string Key;
- std::string Val;
- // If set, the debug location corresponding to the value.
- DiagnosticLocation Loc;
- explicit Argument(StringRef Str = "") : Key("String"), Val(Str) {}
- Argument(StringRef Key, const Value *V);
- Argument(StringRef Key, const Type *T);
- Argument(StringRef Key, StringRef S);
- Argument(StringRef Key, const char *S) : Argument(Key, StringRef(S)) {};
- Argument(StringRef Key, int N);
- Argument(StringRef Key, float N);
- Argument(StringRef Key, long N);
- Argument(StringRef Key, long long N);
- Argument(StringRef Key, unsigned N);
- Argument(StringRef Key, unsigned long N);
- Argument(StringRef Key, unsigned long long N);
- Argument(StringRef Key, ElementCount EC);
- Argument(StringRef Key, bool B) : Key(Key), Val(B ? "true" : "false") {}
- Argument(StringRef Key, DebugLoc dl);
- Argument(StringRef Key, InstructionCost C);
- };
- /// \p PassName is the name of the pass emitting this diagnostic. \p
- /// RemarkName is a textual identifier for the remark (single-word,
- /// camel-case). \p Fn is the function where the diagnostic is being emitted.
- /// \p Loc is the location information to use in the diagnostic. If line table
- /// information is available, the diagnostic will include the source code
- /// location.
- DiagnosticInfoOptimizationBase(enum DiagnosticKind Kind,
- enum DiagnosticSeverity Severity,
- const char *PassName, StringRef RemarkName,
- const Function &Fn,
- const DiagnosticLocation &Loc)
- : DiagnosticInfoWithLocationBase(Kind, Severity, Fn, Loc),
- PassName(PassName), RemarkName(RemarkName) {}
- void insert(StringRef S);
- void insert(Argument A);
- void insert(setIsVerbose V);
- void insert(setExtraArgs EA);
- /// \see DiagnosticInfo::print.
- void print(DiagnosticPrinter &DP) const override;
- /// Return true if this optimization remark is enabled by one of
- /// of the LLVM command line flags (-pass-remarks, -pass-remarks-missed,
- /// or -pass-remarks-analysis). Note that this only handles the LLVM
- /// flags. We cannot access Clang flags from here (they are handled
- /// in BackendConsumer::OptimizationRemarkHandler).
- virtual bool isEnabled() const = 0;
- StringRef getPassName() const { return PassName; }
- StringRef getRemarkName() const { return RemarkName; }
- std::string getMsg() const;
- Optional<uint64_t> getHotness() const { return Hotness; }
- void setHotness(Optional<uint64_t> H) { Hotness = H; }
- bool isVerbose() const { return IsVerbose; }
- ArrayRef<Argument> getArgs() const { return Args; }
- static bool classof(const DiagnosticInfo *DI) {
- return (DI->getKind() >= DK_FirstRemark &&
- DI->getKind() <= DK_LastRemark) ||
- (DI->getKind() >= DK_FirstMachineRemark &&
- DI->getKind() <= DK_LastMachineRemark);
- }
- bool isPassed() const {
- return (getKind() == DK_OptimizationRemark ||
- getKind() == DK_MachineOptimizationRemark);
- }
- bool isMissed() const {
- return (getKind() == DK_OptimizationRemarkMissed ||
- getKind() == DK_MachineOptimizationRemarkMissed);
- }
- bool isAnalysis() const {
- return (getKind() == DK_OptimizationRemarkAnalysis ||
- getKind() == DK_MachineOptimizationRemarkAnalysis);
- }
- protected:
- /// Name of the pass that triggers this report. If this matches the
- /// regular expression given in -Rpass=regexp, then the remark will
- /// be emitted.
- const char *PassName;
- /// Textual identifier for the remark (single-word, camel-case). Can be used
- /// by external tools reading the output file for optimization remarks to
- /// identify the remark.
- StringRef RemarkName;
- /// If profile information is available, this is the number of times the
- /// corresponding code was executed in a profile instrumentation run.
- Optional<uint64_t> Hotness;
- /// Arguments collected via the streaming interface.
- SmallVector<Argument, 4> Args;
- /// The remark is expected to be noisy.
- bool IsVerbose = false;
- /// If positive, the index of the first argument that only appear in
- /// the optimization records and not in the remark printed in the compiler
- /// output.
- int FirstExtraArgIndex = -1;
- };
- /// Allow the insertion operator to return the actual remark type rather than a
- /// common base class. This allows returning the result of the insertion
- /// directly by value, e.g. return OptimizationRemarkAnalysis(...) << "blah".
- template <class RemarkT>
- RemarkT &
- operator<<(RemarkT &R,
- std::enable_if_t<
- std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
- StringRef>
- S) {
- R.insert(S);
- return R;
- }
- /// Also allow r-value for the remark to allow insertion into a
- /// temporarily-constructed remark.
- template <class RemarkT>
- RemarkT &
- operator<<(RemarkT &&R,
- std::enable_if_t<
- std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
- StringRef>
- S) {
- R.insert(S);
- return R;
- }
- template <class RemarkT>
- RemarkT &
- operator<<(RemarkT &R,
- std::enable_if_t<
- std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
- DiagnosticInfoOptimizationBase::Argument>
- A) {
- R.insert(A);
- return R;
- }
- template <class RemarkT>
- RemarkT &
- operator<<(RemarkT &&R,
- std::enable_if_t<
- std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
- DiagnosticInfoOptimizationBase::Argument>
- A) {
- R.insert(A);
- return R;
- }
- template <class RemarkT>
- RemarkT &
- operator<<(RemarkT &R,
- std::enable_if_t<
- std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
- DiagnosticInfoOptimizationBase::setIsVerbose>
- V) {
- R.insert(V);
- return R;
- }
- template <class RemarkT>
- RemarkT &
- operator<<(RemarkT &&R,
- std::enable_if_t<
- std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
- DiagnosticInfoOptimizationBase::setIsVerbose>
- V) {
- R.insert(V);
- return R;
- }
- template <class RemarkT>
- RemarkT &
- operator<<(RemarkT &R,
- std::enable_if_t<
- std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
- DiagnosticInfoOptimizationBase::setExtraArgs>
- EA) {
- R.insert(EA);
- return R;
- }
- /// Common features for diagnostics dealing with optimization remarks
- /// that are used by IR passes.
- class DiagnosticInfoIROptimization : public DiagnosticInfoOptimizationBase {
- void anchor() override;
- public:
- /// \p PassName is the name of the pass emitting this diagnostic. \p
- /// RemarkName is a textual identifier for the remark (single-word,
- /// camel-case). \p Fn is the function where the diagnostic is being emitted.
- /// \p Loc is the location information to use in the diagnostic. If line table
- /// information is available, the diagnostic will include the source code
- /// location. \p CodeRegion is IR value (currently basic block) that the
- /// optimization operates on. This is currently used to provide run-time
- /// hotness information with PGO.
- DiagnosticInfoIROptimization(enum DiagnosticKind Kind,
- enum DiagnosticSeverity Severity,
- const char *PassName, StringRef RemarkName,
- const Function &Fn,
- const DiagnosticLocation &Loc,
- const Value *CodeRegion = nullptr)
- : DiagnosticInfoOptimizationBase(Kind, Severity, PassName, RemarkName, Fn,
- Loc),
- CodeRegion(CodeRegion) {}
- /// This is ctor variant allows a pass to build an optimization remark
- /// from an existing remark.
- ///
- /// This is useful when a transformation pass (e.g LV) wants to emit a remark
- /// (\p Orig) generated by one of its analyses (e.g. LAA) as its own analysis
- /// remark. The string \p Prepend will be emitted before the original
- /// message.
- DiagnosticInfoIROptimization(const char *PassName, StringRef Prepend,
- const DiagnosticInfoIROptimization &Orig)
- : DiagnosticInfoOptimizationBase(
- (DiagnosticKind)Orig.getKind(), Orig.getSeverity(), PassName,
- Orig.RemarkName, Orig.getFunction(), Orig.getLocation()),
- CodeRegion(Orig.getCodeRegion()) {
- *this << Prepend;
- std::copy(Orig.Args.begin(), Orig.Args.end(), std::back_inserter(Args));
- }
- /// Legacy interface.
- /// \p PassName is the name of the pass emitting this diagnostic.
- /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
- /// the location information to use in the diagnostic. If line table
- /// information is available, the diagnostic will include the source code
- /// location. \p Msg is the message to show. Note that this class does not
- /// copy this message, so this reference must be valid for the whole life time
- /// of the diagnostic.
- DiagnosticInfoIROptimization(enum DiagnosticKind Kind,
- enum DiagnosticSeverity Severity,
- const char *PassName, const Function &Fn,
- const DiagnosticLocation &Loc, const Twine &Msg)
- : DiagnosticInfoOptimizationBase(Kind, Severity, PassName, "", Fn, Loc) {
- *this << Msg.str();
- }
- const Value *getCodeRegion() const { return CodeRegion; }
- static bool classof(const DiagnosticInfo *DI) {
- return DI->getKind() >= DK_FirstRemark && DI->getKind() <= DK_LastRemark;
- }
- private:
- /// The IR value (currently basic block) that the optimization operates on.
- /// This is currently used to provide run-time hotness information with PGO.
- const Value *CodeRegion = nullptr;
- };
- /// Diagnostic information for applied optimization remarks.
- class OptimizationRemark : public DiagnosticInfoIROptimization {
- public:
- /// \p PassName is the name of the pass emitting this diagnostic. If this name
- /// matches the regular expression given in -Rpass=, then the diagnostic will
- /// be emitted. \p RemarkName is a textual identifier for the remark (single-
- /// word, camel-case). \p Loc is the debug location and \p CodeRegion is the
- /// region that the optimization operates on (currently only block is
- /// supported).
- OptimizationRemark(const char *PassName, StringRef RemarkName,
- const DiagnosticLocation &Loc, const Value *CodeRegion);
- /// Same as above, but the debug location and code region are derived from \p
- /// Instr.
- OptimizationRemark(const char *PassName, StringRef RemarkName,
- const Instruction *Inst);
- /// Same as above, but the debug location and code region are derived from \p
- /// Func.
- OptimizationRemark(const char *PassName, StringRef RemarkName,
- const Function *Func);
- static bool classof(const DiagnosticInfo *DI) {
- return DI->getKind() == DK_OptimizationRemark;
- }
- /// \see DiagnosticInfoOptimizationBase::isEnabled.
- bool isEnabled() const override;
- private:
- /// This is deprecated now and only used by the function API below.
- /// \p PassName is the name of the pass emitting this diagnostic. If
- /// this name matches the regular expression given in -Rpass=, then the
- /// diagnostic will be emitted. \p Fn is the function where the diagnostic
- /// is being emitted. \p Loc is the location information to use in the
- /// diagnostic. If line table information is available, the diagnostic
- /// will include the source code location. \p Msg is the message to show.
- /// Note that this class does not copy this message, so this reference
- /// must be valid for the whole life time of the diagnostic.
- OptimizationRemark(const char *PassName, const Function &Fn,
- const DiagnosticLocation &Loc, const Twine &Msg)
- : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,
- Fn, Loc, Msg) {}
- };
- /// Diagnostic information for missed-optimization remarks.
- class OptimizationRemarkMissed : public DiagnosticInfoIROptimization {
- public:
- /// \p PassName is the name of the pass emitting this diagnostic. If this name
- /// matches the regular expression given in -Rpass-missed=, then the
- /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
- /// remark (single-word, camel-case). \p Loc is the debug location and \p
- /// CodeRegion is the region that the optimization operates on (currently only
- /// block is supported).
- OptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
- const DiagnosticLocation &Loc,
- const Value *CodeRegion);
- /// Same as above but \p Inst is used to derive code region and debug
- /// location.
- OptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
- const Instruction *Inst);
- /// Same as above but \p F is used to derive code region and debug
- /// location.
- OptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
- const Function *F);
- static bool classof(const DiagnosticInfo *DI) {
- return DI->getKind() == DK_OptimizationRemarkMissed;
- }
- /// \see DiagnosticInfoOptimizationBase::isEnabled.
- bool isEnabled() const override;
- private:
- /// This is deprecated now and only used by the function API below.
- /// \p PassName is the name of the pass emitting this diagnostic. If
- /// this name matches the regular expression given in -Rpass-missed=, then the
- /// diagnostic will be emitted. \p Fn is the function where the diagnostic
- /// is being emitted. \p Loc is the location information to use in the
- /// diagnostic. If line table information is available, the diagnostic
- /// will include the source code location. \p Msg is the message to show.
- /// Note that this class does not copy this message, so this reference
- /// must be valid for the whole life time of the diagnostic.
- OptimizationRemarkMissed(const char *PassName, const Function &Fn,
- const DiagnosticLocation &Loc, const Twine &Msg)
- : DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark,
- PassName, Fn, Loc, Msg) {}
- };
- /// Diagnostic information for optimization analysis remarks.
- class OptimizationRemarkAnalysis : public DiagnosticInfoIROptimization {
- public:
- /// \p PassName is the name of the pass emitting this diagnostic. If this name
- /// matches the regular expression given in -Rpass-analysis=, then the
- /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
- /// remark (single-word, camel-case). \p Loc is the debug location and \p
- /// CodeRegion is the region that the optimization operates on (currently only
- /// block is supported).
- OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
- const DiagnosticLocation &Loc,
- const Value *CodeRegion);
- /// This is ctor variant allows a pass to build an optimization remark
- /// from an existing remark.
- ///
- /// This is useful when a transformation pass (e.g LV) wants to emit a remark
- /// (\p Orig) generated by one of its analyses (e.g. LAA) as its own analysis
- /// remark. The string \p Prepend will be emitted before the original
- /// message.
- OptimizationRemarkAnalysis(const char *PassName, StringRef Prepend,
- const OptimizationRemarkAnalysis &Orig)
- : DiagnosticInfoIROptimization(PassName, Prepend, Orig) {}
- /// Same as above but \p Inst is used to derive code region and debug
- /// location.
- OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
- const Instruction *Inst);
- /// Same as above but \p F is used to derive code region and debug
- /// location.
- OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
- const Function *F);
- static bool classof(const DiagnosticInfo *DI) {
- return DI->getKind() == DK_OptimizationRemarkAnalysis;
- }
- /// \see DiagnosticInfoOptimizationBase::isEnabled.
- bool isEnabled() const override;
- static const char *AlwaysPrint;
- bool shouldAlwaysPrint() const { return getPassName() == AlwaysPrint; }
- protected:
- OptimizationRemarkAnalysis(enum DiagnosticKind Kind, const char *PassName,
- const Function &Fn, const DiagnosticLocation &Loc,
- const Twine &Msg)
- : DiagnosticInfoIROptimization(Kind, DS_Remark, PassName, Fn, Loc, Msg) {}
- OptimizationRemarkAnalysis(enum DiagnosticKind Kind, const char *PassName,
- StringRef RemarkName,
- const DiagnosticLocation &Loc,
- const Value *CodeRegion);
- private:
- /// This is deprecated now and only used by the function API below.
- /// \p PassName is the name of the pass emitting this diagnostic. If
- /// this name matches the regular expression given in -Rpass-analysis=, then
- /// the diagnostic will be emitted. \p Fn is the function where the diagnostic
- /// is being emitted. \p Loc is the location information to use in the
- /// diagnostic. If line table information is available, the diagnostic will
- /// include the source code location. \p Msg is the message to show. Note that
- /// this class does not copy this message, so this reference must be valid for
- /// the whole life time of the diagnostic.
- OptimizationRemarkAnalysis(const char *PassName, const Function &Fn,
- const DiagnosticLocation &Loc, const Twine &Msg)
- : DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark,
- PassName, Fn, Loc, Msg) {}
- };
- /// Diagnostic information for optimization analysis remarks related to
- /// floating-point non-commutativity.
- class OptimizationRemarkAnalysisFPCommute : public OptimizationRemarkAnalysis {
- void anchor() override;
- public:
- /// \p PassName is the name of the pass emitting this diagnostic. If this name
- /// matches the regular expression given in -Rpass-analysis=, then the
- /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
- /// remark (single-word, camel-case). \p Loc is the debug location and \p
- /// CodeRegion is the region that the optimization operates on (currently only
- /// block is supported). The front-end will append its own message related to
- /// options that address floating-point non-commutativity.
- OptimizationRemarkAnalysisFPCommute(const char *PassName,
- StringRef RemarkName,
- const DiagnosticLocation &Loc,
- const Value *CodeRegion)
- : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute,
- PassName, RemarkName, Loc, CodeRegion) {}
- static bool classof(const DiagnosticInfo *DI) {
- return DI->getKind() == DK_OptimizationRemarkAnalysisFPCommute;
- }
- private:
- /// This is deprecated now and only used by the function API below.
- /// \p PassName is the name of the pass emitting this diagnostic. If
- /// this name matches the regular expression given in -Rpass-analysis=, then
- /// the diagnostic will be emitted. \p Fn is the function where the diagnostic
- /// is being emitted. \p Loc is the location information to use in the
- /// diagnostic. If line table information is available, the diagnostic will
- /// include the source code location. \p Msg is the message to show. The
- /// front-end will append its own message related to options that address
- /// floating-point non-commutativity. Note that this class does not copy this
- /// message, so this reference must be valid for the whole life time of the
- /// diagnostic.
- OptimizationRemarkAnalysisFPCommute(const char *PassName, const Function &Fn,
- const DiagnosticLocation &Loc,
- const Twine &Msg)
- : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute,
- PassName, Fn, Loc, Msg) {}
- };
- /// Diagnostic information for optimization analysis remarks related to
- /// pointer aliasing.
- class OptimizationRemarkAnalysisAliasing : public OptimizationRemarkAnalysis {
- void anchor() override;
- public:
- /// \p PassName is the name of the pass emitting this diagnostic. If this name
- /// matches the regular expression given in -Rpass-analysis=, then the
- /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
- /// remark (single-word, camel-case). \p Loc is the debug location and \p
- /// CodeRegion is the region that the optimization operates on (currently only
- /// block is supported). The front-end will append its own message related to
- /// options that address pointer aliasing legality.
- OptimizationRemarkAnalysisAliasing(const char *PassName, StringRef RemarkName,
- const DiagnosticLocation &Loc,
- const Value *CodeRegion)
- : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing,
- PassName, RemarkName, Loc, CodeRegion) {}
- static bool classof(const DiagnosticInfo *DI) {
- return DI->getKind() == DK_OptimizationRemarkAnalysisAliasing;
- }
- private:
- /// This is deprecated now and only used by the function API below.
- /// \p PassName is the name of the pass emitting this diagnostic. If
- /// this name matches the regular expression given in -Rpass-analysis=, then
- /// the diagnostic will be emitted. \p Fn is the function where the diagnostic
- /// is being emitted. \p Loc is the location information to use in the
- /// diagnostic. If line table information is available, the diagnostic will
- /// include the source code location. \p Msg is the message to show. The
- /// front-end will append its own message related to options that address
- /// pointer aliasing legality. Note that this class does not copy this
- /// message, so this reference must be valid for the whole life time of the
- /// diagnostic.
- OptimizationRemarkAnalysisAliasing(const char *PassName, const Function &Fn,
- const DiagnosticLocation &Loc,
- const Twine &Msg)
- : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing,
- PassName, Fn, Loc, Msg) {}
- };
- /// Diagnostic information for machine IR parser.
- // FIXME: Remove this, use DiagnosticInfoSrcMgr instead.
- class DiagnosticInfoMIRParser : public DiagnosticInfo {
- const SMDiagnostic &Diagnostic;
- public:
- DiagnosticInfoMIRParser(DiagnosticSeverity Severity,
- const SMDiagnostic &Diagnostic)
- : DiagnosticInfo(DK_MIRParser, Severity), Diagnostic(Diagnostic) {}
- const SMDiagnostic &getDiagnostic() const { return Diagnostic; }
- void print(DiagnosticPrinter &DP) const override;
- static bool classof(const DiagnosticInfo *DI) {
- return DI->getKind() == DK_MIRParser;
- }
- };
- /// Diagnostic information for ISel fallback path.
- class DiagnosticInfoISelFallback : public DiagnosticInfo {
- /// The function that is concerned by this diagnostic.
- const Function &Fn;
- public:
- DiagnosticInfoISelFallback(const Function &Fn,
- DiagnosticSeverity Severity = DS_Warning)
- : DiagnosticInfo(DK_ISelFallback, Severity), Fn(Fn) {}
- const Function &getFunction() const { return Fn; }
- void print(DiagnosticPrinter &DP) const override;
- static bool classof(const DiagnosticInfo *DI) {
- return DI->getKind() == DK_ISelFallback;
- }
- };
- // Create wrappers for C Binding types (see CBindingWrapping.h).
- DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DiagnosticInfo, LLVMDiagnosticInfoRef)
- /// Diagnostic information for optimization failures.
- class DiagnosticInfoOptimizationFailure : public DiagnosticInfoIROptimization {
- public:
- /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
- /// the location information to use in the diagnostic. If line table
- /// information is available, the diagnostic will include the source code
- /// location. \p Msg is the message to show. Note that this class does not
- /// copy this message, so this reference must be valid for the whole life time
- /// of the diagnostic.
- DiagnosticInfoOptimizationFailure(const Function &Fn,
- const DiagnosticLocation &Loc,
- const Twine &Msg)
- : DiagnosticInfoIROptimization(DK_OptimizationFailure, DS_Warning,
- nullptr, Fn, Loc, Msg) {}
- /// \p PassName is the name of the pass emitting this diagnostic. \p
- /// RemarkName is a textual identifier for the remark (single-word,
- /// camel-case). \p Loc is the debug location and \p CodeRegion is the
- /// region that the optimization operates on (currently basic block is
- /// supported).
- DiagnosticInfoOptimizationFailure(const char *PassName, StringRef RemarkName,
- const DiagnosticLocation &Loc,
- const Value *CodeRegion);
- static bool classof(const DiagnosticInfo *DI) {
- return DI->getKind() == DK_OptimizationFailure;
- }
- /// \see DiagnosticInfoOptimizationBase::isEnabled.
- bool isEnabled() const override;
- };
- /// Diagnostic information for unsupported feature in backend.
- class DiagnosticInfoUnsupported : public DiagnosticInfoWithLocationBase {
- private:
- Twine Msg;
- public:
- /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
- /// the location information to use in the diagnostic. If line table
- /// information is available, the diagnostic will include the source code
- /// location. \p Msg is the message to show. Note that this class does not
- /// copy this message, so this reference must be valid for the whole life time
- /// of the diagnostic.
- DiagnosticInfoUnsupported(
- const Function &Fn, const Twine &Msg,
- const DiagnosticLocation &Loc = DiagnosticLocation(),
- DiagnosticSeverity Severity = DS_Error)
- : DiagnosticInfoWithLocationBase(DK_Unsupported, Severity, Fn, Loc),
- Msg(Msg) {}
- static bool classof(const DiagnosticInfo *DI) {
- return DI->getKind() == DK_Unsupported;
- }
- const Twine &getMessage() const { return Msg; }
- void print(DiagnosticPrinter &DP) const override;
- };
- static DiagnosticSeverity getDiagnosticSeverity(SourceMgr::DiagKind DK) {
- switch (DK) {
- case llvm::SourceMgr::DK_Error:
- return DS_Error;
- break;
- case llvm::SourceMgr::DK_Warning:
- return DS_Warning;
- break;
- case llvm::SourceMgr::DK_Note:
- return DS_Note;
- break;
- case llvm::SourceMgr::DK_Remark:
- return DS_Remark;
- break;
- }
- llvm_unreachable("unknown SourceMgr::DiagKind");
- }
- /// Diagnostic information for SMDiagnostic reporting.
- class DiagnosticInfoSrcMgr : public DiagnosticInfo {
- const SMDiagnostic &Diagnostic;
- StringRef ModName;
- // For inlineasm !srcloc translation.
- bool InlineAsmDiag;
- unsigned LocCookie;
- public:
- DiagnosticInfoSrcMgr(const SMDiagnostic &Diagnostic, StringRef ModName,
- bool InlineAsmDiag = true, unsigned LocCookie = 0)
- : DiagnosticInfo(DK_SrcMgr, getDiagnosticSeverity(Diagnostic.getKind())),
- Diagnostic(Diagnostic), ModName(ModName), InlineAsmDiag(InlineAsmDiag),
- LocCookie(LocCookie) {}
- StringRef getModuleName() const { return ModName; }
- bool isInlineAsmDiag() const { return InlineAsmDiag; }
- const SMDiagnostic &getSMDiag() const { return Diagnostic; }
- unsigned getLocCookie() const { return LocCookie; }
- void print(DiagnosticPrinter &DP) const override;
- static bool classof(const DiagnosticInfo *DI) {
- return DI->getKind() == DK_SrcMgr;
- }
- };
- void diagnoseDontCall(const CallInst &CI);
- class DiagnosticInfoDontCall : public DiagnosticInfo {
- StringRef CalleeName;
- StringRef Note;
- unsigned LocCookie;
- public:
- DiagnosticInfoDontCall(StringRef CalleeName, StringRef Note,
- DiagnosticSeverity DS, unsigned LocCookie)
- : DiagnosticInfo(DK_DontCall, DS), CalleeName(CalleeName), Note(Note),
- LocCookie(LocCookie) {}
- StringRef getFunctionName() const { return CalleeName; }
- StringRef getNote() const { return Note; }
- unsigned getLocCookie() const { return LocCookie; }
- void print(DiagnosticPrinter &DP) const override;
- static bool classof(const DiagnosticInfo *DI) {
- return DI->getKind() == DK_DontCall;
- }
- };
- } // end namespace llvm
- #endif // LLVM_IR_DIAGNOSTICINFO_H
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|