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