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