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