1 //===- llvm/Support/DiagnosticInfo.h - Diagnostic Declaration ---*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file declares the different classes involved in low level diagnostics. 11 // 12 // Diagnostics reporting is still done as part of the LLVMContext. 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_SUPPORT_DIAGNOSTICINFO_H 16 #define LLVM_SUPPORT_DIAGNOSTICINFO_H 17 18 #include "llvm-c/Core.h" 19 #include "llvm/ADT/ArrayRef.h" 20 #include "llvm/IR/DebugLoc.h" 21 #include "llvm/Support/Casting.h" 22 23 namespace llvm { 24 25 // Forward declarations. 26 class DiagnosticPrinter; 27 class Function; 28 class Instruction; 29 class LLVMContextImpl; 30 class Twine; 31 class Value; 32 class DebugLoc; 33 34 /// \brief Defines the different supported severity of a diagnostic. 35 enum DiagnosticSeverity { 36 DS_Error, 37 DS_Warning, 38 DS_Remark, 39 // A note attaches additional information to one of the previous diagnostic 40 // types. 41 DS_Note 42 }; 43 44 /// \brief Defines the different supported kind of a diagnostic. 45 /// This enum should be extended with a new ID for each added concrete subclass. 46 enum DiagnosticKind { 47 DK_InlineAsm, 48 DK_StackSize, 49 DK_DebugMetadataVersion, 50 DK_SampleProfile, 51 DK_OptimizationRemark, 52 DK_OptimizationRemarkMissed, 53 DK_OptimizationRemarkAnalysis, 54 DK_FirstPluginKind 55 }; 56 57 /// \brief Get the next available kind ID for a plugin diagnostic. 58 /// Each time this function is called, it returns a different number. 59 /// Therefore, a plugin that wants to "identify" its own classes 60 /// with a dynamic identifier, just have to use this method to get a new ID 61 /// and assign it to each of its classes. 62 /// The returned ID will be greater than or equal to DK_FirstPluginKind. 63 /// Thus, the plugin identifiers will not conflict with the 64 /// DiagnosticKind values. 65 int getNextAvailablePluginDiagnosticKind(); 66 67 /// \brief This is the base abstract class for diagnostic reporting in 68 /// the backend. 69 /// The print method must be overloaded by the subclasses to print a 70 /// user-friendly message in the client of the backend (let us call it a 71 /// frontend). 72 class DiagnosticInfo { 73 private: 74 /// Kind defines the kind of report this is about. 75 const /* DiagnosticKind */ int Kind; 76 /// Severity gives the severity of the diagnostic. 77 const DiagnosticSeverity Severity; 78 79 public: DiagnosticInfo(int Kind,DiagnosticSeverity Severity)80 DiagnosticInfo(/* DiagnosticKind */ int Kind, DiagnosticSeverity Severity) 81 : Kind(Kind), Severity(Severity) {} 82 ~DiagnosticInfo()83 virtual ~DiagnosticInfo() {} 84 getKind()85 /* DiagnosticKind */ int getKind() const { return Kind; } getSeverity()86 DiagnosticSeverity getSeverity() const { return Severity; } 87 88 /// Print using the given \p DP a user-friendly message. 89 /// This is the default message that will be printed to the user. 90 /// It is used when the frontend does not directly take advantage 91 /// of the information contained in fields of the subclasses. 92 /// The printed message must not end with '.' nor start with a severity 93 /// keyword. 94 virtual void print(DiagnosticPrinter &DP) const = 0; 95 }; 96 97 /// Diagnostic information for inline asm reporting. 98 /// This is basically a message and an optional location. 99 class DiagnosticInfoInlineAsm : public DiagnosticInfo { 100 private: 101 /// Optional line information. 0 if not set. 102 unsigned LocCookie; 103 /// Message to be reported. 104 const Twine &MsgStr; 105 /// Optional origin of the problem. 106 const Instruction *Instr; 107 108 public: 109 /// \p MsgStr is the message to be reported to the frontend. 110 /// This class does not copy \p MsgStr, therefore the reference must be valid 111 /// for the whole life time of the Diagnostic. 112 DiagnosticInfoInlineAsm(const Twine &MsgStr, 113 DiagnosticSeverity Severity = DS_Error) DiagnosticInfo(DK_InlineAsm,Severity)114 : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(0), MsgStr(MsgStr), 115 Instr(nullptr) {} 116 117 /// \p LocCookie if non-zero gives the line number for this report. 118 /// \p MsgStr gives the message. 119 /// This class does not copy \p MsgStr, therefore the reference must be valid 120 /// for the whole life time of the Diagnostic. 121 DiagnosticInfoInlineAsm(unsigned LocCookie, const Twine &MsgStr, 122 DiagnosticSeverity Severity = DS_Error) DiagnosticInfo(DK_InlineAsm,Severity)123 : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(LocCookie), 124 MsgStr(MsgStr), Instr(nullptr) {} 125 126 /// \p Instr gives the original instruction that triggered the diagnostic. 127 /// \p MsgStr gives the message. 128 /// This class does not copy \p MsgStr, therefore the reference must be valid 129 /// for the whole life time of the Diagnostic. 130 /// Same for \p I. 131 DiagnosticInfoInlineAsm(const Instruction &I, const Twine &MsgStr, 132 DiagnosticSeverity Severity = DS_Error); 133 getLocCookie()134 unsigned getLocCookie() const { return LocCookie; } getMsgStr()135 const Twine &getMsgStr() const { return MsgStr; } getInstruction()136 const Instruction *getInstruction() const { return Instr; } 137 138 /// \see DiagnosticInfo::print. 139 void print(DiagnosticPrinter &DP) const override; 140 classof(const DiagnosticInfo * DI)141 static bool classof(const DiagnosticInfo *DI) { 142 return DI->getKind() == DK_InlineAsm; 143 } 144 }; 145 146 /// Diagnostic information for stack size reporting. 147 /// This is basically a function and a size. 148 class DiagnosticInfoStackSize : public DiagnosticInfo { 149 private: 150 /// The function that is concerned by this stack size diagnostic. 151 const Function &Fn; 152 /// The computed stack size. 153 unsigned StackSize; 154 155 public: 156 /// \p The function that is concerned by this stack size diagnostic. 157 /// \p The computed stack size. 158 DiagnosticInfoStackSize(const Function &Fn, unsigned StackSize, 159 DiagnosticSeverity Severity = DS_Warning) DiagnosticInfo(DK_StackSize,Severity)160 : DiagnosticInfo(DK_StackSize, Severity), Fn(Fn), StackSize(StackSize) {} 161 getFunction()162 const Function &getFunction() const { return Fn; } getStackSize()163 unsigned getStackSize() const { return StackSize; } 164 165 /// \see DiagnosticInfo::print. 166 void print(DiagnosticPrinter &DP) const override; 167 classof(const DiagnosticInfo * DI)168 static bool classof(const DiagnosticInfo *DI) { 169 return DI->getKind() == DK_StackSize; 170 } 171 }; 172 173 /// Diagnostic information for debug metadata version reporting. 174 /// This is basically a module and a version. 175 class DiagnosticInfoDebugMetadataVersion : public DiagnosticInfo { 176 private: 177 /// The module that is concerned by this debug metadata version diagnostic. 178 const Module &M; 179 /// The actual metadata version. 180 unsigned MetadataVersion; 181 182 public: 183 /// \p The module that is concerned by this debug metadata version diagnostic. 184 /// \p The actual metadata version. 185 DiagnosticInfoDebugMetadataVersion(const Module &M, unsigned MetadataVersion, 186 DiagnosticSeverity Severity = DS_Warning) DiagnosticInfo(DK_DebugMetadataVersion,Severity)187 : DiagnosticInfo(DK_DebugMetadataVersion, Severity), M(M), 188 MetadataVersion(MetadataVersion) {} 189 getModule()190 const Module &getModule() const { return M; } getMetadataVersion()191 unsigned getMetadataVersion() const { return MetadataVersion; } 192 193 /// \see DiagnosticInfo::print. 194 void print(DiagnosticPrinter &DP) const override; 195 classof(const DiagnosticInfo * DI)196 static bool classof(const DiagnosticInfo *DI) { 197 return DI->getKind() == DK_DebugMetadataVersion; 198 } 199 }; 200 201 /// Diagnostic information for the sample profiler. 202 class DiagnosticInfoSampleProfile : public DiagnosticInfo { 203 public: 204 DiagnosticInfoSampleProfile(const char *FileName, unsigned LineNum, 205 const Twine &Msg, 206 DiagnosticSeverity Severity = DS_Error) DiagnosticInfo(DK_SampleProfile,Severity)207 : DiagnosticInfo(DK_SampleProfile, Severity), FileName(FileName), 208 LineNum(LineNum), Msg(Msg) {} 209 DiagnosticInfoSampleProfile(const char *FileName, const Twine &Msg, 210 DiagnosticSeverity Severity = DS_Error) DiagnosticInfo(DK_SampleProfile,Severity)211 : DiagnosticInfo(DK_SampleProfile, Severity), FileName(FileName), 212 LineNum(0), Msg(Msg) {} 213 DiagnosticInfoSampleProfile(const Twine &Msg, 214 DiagnosticSeverity Severity = DS_Error) DiagnosticInfo(DK_SampleProfile,Severity)215 : DiagnosticInfo(DK_SampleProfile, Severity), FileName(nullptr), 216 LineNum(0), Msg(Msg) {} 217 218 /// \see DiagnosticInfo::print. 219 void print(DiagnosticPrinter &DP) const override; 220 classof(const DiagnosticInfo * DI)221 static bool classof(const DiagnosticInfo *DI) { 222 return DI->getKind() == DK_SampleProfile; 223 } 224 getFileName()225 const char *getFileName() const { return FileName; } getLineNum()226 unsigned getLineNum() const { return LineNum; } getMsg()227 const Twine &getMsg() const { return Msg; } 228 229 private: 230 /// Name of the input file associated with this diagnostic. 231 const char *FileName; 232 233 /// Line number where the diagnostic occurred. If 0, no line number will 234 /// be emitted in the message. 235 unsigned LineNum; 236 237 /// Message to report. 238 const Twine &Msg; 239 }; 240 241 /// Common features for diagnostics dealing with optimization remarks. 242 class DiagnosticInfoOptimizationRemarkBase : public DiagnosticInfo { 243 public: 244 /// \p PassName is the name of the pass emitting this diagnostic. 245 /// \p Fn is the function where the diagnostic is being emitted. \p DLoc is 246 /// the location information to use in the diagnostic. If line table 247 /// information is available, the diagnostic will include the source code 248 /// location. \p Msg is the message to show. Note that this class does not 249 /// copy this message, so this reference must be valid for the whole life time 250 /// of the diagnostic. DiagnosticInfoOptimizationRemarkBase(enum DiagnosticKind Kind,const char * PassName,const Function & Fn,const DebugLoc & DLoc,const Twine & Msg)251 DiagnosticInfoOptimizationRemarkBase(enum DiagnosticKind Kind, 252 const char *PassName, const Function &Fn, 253 const DebugLoc &DLoc, const Twine &Msg) 254 : DiagnosticInfo(Kind, DS_Remark), PassName(PassName), Fn(Fn), DLoc(DLoc), 255 Msg(Msg) {} 256 257 /// \see DiagnosticInfo::print. 258 void print(DiagnosticPrinter &DP) const override; 259 classof(const DiagnosticInfo * DI)260 static bool classof(const DiagnosticInfo *DI) { 261 return DI->getKind() == DK_OptimizationRemark; 262 } 263 264 /// Return true if this optimization remark is enabled by one of 265 /// of the LLVM command line flags (-pass-remarks, -pass-remarks-missed, 266 /// or -pass-remarks-analysis). Note that this only handles the LLVM 267 /// flags. We cannot access Clang flags from here (they are handled 268 /// in BackendConsumer::OptimizationRemarkHandler). 269 virtual bool isEnabled() const = 0; 270 271 /// Return true if location information is available for this diagnostic. 272 bool isLocationAvailable() const; 273 274 /// Return a string with the location information for this diagnostic 275 /// in the format "file:line:col". If location information is not available, 276 /// it returns "<unknown>:0:0". 277 const std::string getLocationStr() const; 278 279 /// Return location information for this diagnostic in three parts: 280 /// the source file name, line number and column. 281 void getLocation(StringRef *Filename, unsigned *Line, unsigned *Column) const; 282 getPassName()283 const char *getPassName() const { return PassName; } getFunction()284 const Function &getFunction() const { return Fn; } getDebugLoc()285 const DebugLoc &getDebugLoc() const { return DLoc; } getMsg()286 const Twine &getMsg() const { return Msg; } 287 288 private: 289 /// Name of the pass that triggers this report. If this matches the 290 /// regular expression given in -Rpass=regexp, then the remark will 291 /// be emitted. 292 const char *PassName; 293 294 /// Function where this diagnostic is triggered. 295 const Function &Fn; 296 297 /// Debug location where this diagnostic is triggered. 298 DebugLoc DLoc; 299 300 /// Message to report. 301 const Twine &Msg; 302 }; 303 304 /// Diagnostic information for applied optimization remarks. 305 class DiagnosticInfoOptimizationRemark 306 : public DiagnosticInfoOptimizationRemarkBase { 307 public: 308 /// \p PassName is the name of the pass emitting this diagnostic. If 309 /// this name matches the regular expression given in -Rpass=, then the 310 /// diagnostic will be emitted. \p Fn is the function where the diagnostic 311 /// is being emitted. \p DLoc is the location information to use in the 312 /// diagnostic. If line table information is available, the diagnostic 313 /// will include the source code location. \p Msg is the message to show. 314 /// Note that this class does not copy this message, so this reference 315 /// must be valid for the whole life time of the diagnostic. DiagnosticInfoOptimizationRemark(const char * PassName,const Function & Fn,const DebugLoc & DLoc,const Twine & Msg)316 DiagnosticInfoOptimizationRemark(const char *PassName, const Function &Fn, 317 const DebugLoc &DLoc, const Twine &Msg) 318 : DiagnosticInfoOptimizationRemarkBase(DK_OptimizationRemark, PassName, 319 Fn, DLoc, Msg) {} 320 classof(const DiagnosticInfo * DI)321 static bool classof(const DiagnosticInfo *DI) { 322 return DI->getKind() == DK_OptimizationRemark; 323 } 324 325 /// \see DiagnosticInfoOptimizationRemarkBase::isEnabled. 326 virtual bool isEnabled() const override; 327 }; 328 329 /// Diagnostic information for missed-optimization remarks. 330 class DiagnosticInfoOptimizationRemarkMissed 331 : public DiagnosticInfoOptimizationRemarkBase { 332 public: 333 /// \p PassName is the name of the pass emitting this diagnostic. If 334 /// this name matches the regular expression given in -Rpass-missed=, then the 335 /// diagnostic will be emitted. \p Fn is the function where the diagnostic 336 /// is being emitted. \p DLoc is the location information to use in the 337 /// diagnostic. If line table information is available, the diagnostic 338 /// will include the source code location. \p Msg is the message to show. 339 /// Note that this class does not copy this message, so this reference 340 /// must be valid for the whole life time of the diagnostic. DiagnosticInfoOptimizationRemarkMissed(const char * PassName,const Function & Fn,const DebugLoc & DLoc,const Twine & Msg)341 DiagnosticInfoOptimizationRemarkMissed(const char *PassName, 342 const Function &Fn, 343 const DebugLoc &DLoc, const Twine &Msg) 344 : DiagnosticInfoOptimizationRemarkBase(DK_OptimizationRemarkMissed, 345 PassName, Fn, DLoc, Msg) {} 346 classof(const DiagnosticInfo * DI)347 static bool classof(const DiagnosticInfo *DI) { 348 return DI->getKind() == DK_OptimizationRemarkMissed; 349 } 350 351 /// \see DiagnosticInfoOptimizationRemarkBase::isEnabled. 352 virtual bool isEnabled() const override; 353 }; 354 355 /// Diagnostic information for optimization analysis remarks. 356 class DiagnosticInfoOptimizationRemarkAnalysis 357 : public DiagnosticInfoOptimizationRemarkBase { 358 public: 359 /// \p PassName is the name of the pass emitting this diagnostic. If 360 /// this name matches the regular expression given in -Rpass-analysis=, then 361 /// the diagnostic will be emitted. \p Fn is the function where the diagnostic 362 /// is being emitted. \p DLoc is the location information to use in the 363 /// diagnostic. If line table information is available, the diagnostic will 364 /// include the source code location. \p Msg is the message to show. Note that 365 /// this class does not copy this message, so this reference must be valid for 366 /// the whole life time of the diagnostic. DiagnosticInfoOptimizationRemarkAnalysis(const char * PassName,const Function & Fn,const DebugLoc & DLoc,const Twine & Msg)367 DiagnosticInfoOptimizationRemarkAnalysis(const char *PassName, 368 const Function &Fn, 369 const DebugLoc &DLoc, 370 const Twine &Msg) 371 : DiagnosticInfoOptimizationRemarkBase(DK_OptimizationRemarkAnalysis, 372 PassName, Fn, DLoc, Msg) {} 373 classof(const DiagnosticInfo * DI)374 static bool classof(const DiagnosticInfo *DI) { 375 return DI->getKind() == DK_OptimizationRemarkAnalysis; 376 } 377 378 /// \see DiagnosticInfoOptimizationRemarkBase::isEnabled. 379 virtual bool isEnabled() const override; 380 }; 381 382 // Create wrappers for C Binding types (see CBindingWrapping.h). 383 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DiagnosticInfo, LLVMDiagnosticInfoRef) 384 385 /// Emit an optimization-applied message. \p PassName is the name of the pass 386 /// emitting the message. If -Rpass= is given and \p PassName matches the 387 /// regular expression in -Rpass, then the remark will be emitted. \p Fn is 388 /// the function triggering the remark, \p DLoc is the debug location where 389 /// the diagnostic is generated. \p Msg is the message string to use. 390 void emitOptimizationRemark(LLVMContext &Ctx, const char *PassName, 391 const Function &Fn, const DebugLoc &DLoc, 392 const Twine &Msg); 393 394 /// Emit an optimization-missed message. \p PassName is the name of the 395 /// pass emitting the message. If -Rpass-missed= is given and \p PassName 396 /// matches the regular expression in -Rpass, then the remark will be 397 /// emitted. \p Fn is the function triggering the remark, \p DLoc is the 398 /// debug location where the diagnostic is generated. \p Msg is the 399 /// message string to use. 400 void emitOptimizationRemarkMissed(LLVMContext &Ctx, const char *PassName, 401 const Function &Fn, const DebugLoc &DLoc, 402 const Twine &Msg); 403 404 /// Emit an optimization analysis remark message. \p PassName is the name of 405 /// the pass emitting the message. If -Rpass-analysis= is given and \p 406 /// PassName matches the regular expression in -Rpass, then the remark will be 407 /// emitted. \p Fn is the function triggering the remark, \p DLoc is the debug 408 /// location where the diagnostic is generated. \p Msg is the message string 409 /// to use. 410 void emitOptimizationRemarkAnalysis(LLVMContext &Ctx, const char *PassName, 411 const Function &Fn, const DebugLoc &DLoc, 412 const Twine &Msg); 413 414 } // End namespace llvm 415 416 #endif 417