1 //===- llvm/IR/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/Types.h" 19 #include "llvm/ADT/Optional.h" 20 #include "llvm/ADT/SmallVector.h" 21 #include "llvm/ADT/StringRef.h" 22 #include "llvm/ADT/Twine.h" 23 #include "llvm/IR/DebugLoc.h" 24 #include "llvm/Support/CBindingWrapping.h" 25 #include "llvm/Support/YAMLTraits.h" 26 #include <algorithm> 27 #include <cstdint> 28 #include <functional> 29 #include <iterator> 30 #include <string> 31 32 namespace llvm { 33 34 // Forward declarations. 35 class DiagnosticPrinter; 36 class Function; 37 class Instruction; 38 class LLVMContext; 39 class Module; 40 class SMDiagnostic; 41 42 /// Defines the different supported severity of a diagnostic. 43 enum DiagnosticSeverity : char { 44 DS_Error, 45 DS_Warning, 46 DS_Remark, 47 // A note attaches additional information to one of the previous diagnostic 48 // types. 49 DS_Note 50 }; 51 52 /// Defines the different supported kind of a diagnostic. 53 /// This enum should be extended with a new ID for each added concrete subclass. 54 enum DiagnosticKind { 55 DK_InlineAsm, 56 DK_ResourceLimit, 57 DK_StackSize, 58 DK_Linker, 59 DK_DebugMetadataVersion, 60 DK_DebugMetadataInvalid, 61 DK_ISelFallback, 62 DK_SampleProfile, 63 DK_OptimizationRemark, 64 DK_OptimizationRemarkMissed, 65 DK_OptimizationRemarkAnalysis, 66 DK_OptimizationRemarkAnalysisFPCommute, 67 DK_OptimizationRemarkAnalysisAliasing, 68 DK_OptimizationFailure, 69 DK_FirstRemark = DK_OptimizationRemark, 70 DK_LastRemark = DK_OptimizationFailure, 71 DK_MachineOptimizationRemark, 72 DK_MachineOptimizationRemarkMissed, 73 DK_MachineOptimizationRemarkAnalysis, 74 DK_FirstMachineRemark = DK_MachineOptimizationRemark, 75 DK_LastMachineRemark = DK_MachineOptimizationRemarkAnalysis, 76 DK_MIRParser, 77 DK_PGOProfile, 78 DK_Unsupported, 79 DK_FirstPluginKind 80 }; 81 82 /// Get the next available kind ID for a plugin diagnostic. 83 /// Each time this function is called, it returns a different number. 84 /// Therefore, a plugin that wants to "identify" its own classes 85 /// with a dynamic identifier, just have to use this method to get a new ID 86 /// and assign it to each of its classes. 87 /// The returned ID will be greater than or equal to DK_FirstPluginKind. 88 /// Thus, the plugin identifiers will not conflict with the 89 /// DiagnosticKind values. 90 int getNextAvailablePluginDiagnosticKind(); 91 92 /// This is the base abstract class for diagnostic reporting in 93 /// the backend. 94 /// The print method must be overloaded by the subclasses to print a 95 /// user-friendly message in the client of the backend (let us call it a 96 /// frontend). 97 class DiagnosticInfo { 98 private: 99 /// Kind defines the kind of report this is about. 100 const /* DiagnosticKind */ int Kind; 101 /// Severity gives the severity of the diagnostic. 102 const DiagnosticSeverity Severity; 103 104 virtual void anchor(); 105 public: DiagnosticInfo(int Kind,DiagnosticSeverity Severity)106 DiagnosticInfo(/* DiagnosticKind */ int Kind, DiagnosticSeverity Severity) 107 : Kind(Kind), Severity(Severity) {} 108 109 virtual ~DiagnosticInfo() = default; 110 getKind()111 /* DiagnosticKind */ int getKind() const { return Kind; } getSeverity()112 DiagnosticSeverity getSeverity() const { return Severity; } 113 114 /// Print using the given \p DP a user-friendly message. 115 /// This is the default message that will be printed to the user. 116 /// It is used when the frontend does not directly take advantage 117 /// of the information contained in fields of the subclasses. 118 /// The printed message must not end with '.' nor start with a severity 119 /// keyword. 120 virtual void print(DiagnosticPrinter &DP) const = 0; 121 }; 122 123 using DiagnosticHandlerFunction = std::function<void(const DiagnosticInfo &)>; 124 125 /// Diagnostic information for inline asm reporting. 126 /// This is basically a message and an optional location. 127 class DiagnosticInfoInlineAsm : public DiagnosticInfo { 128 private: 129 /// Optional line information. 0 if not set. 130 unsigned LocCookie = 0; 131 /// Message to be reported. 132 const Twine &MsgStr; 133 /// Optional origin of the problem. 134 const Instruction *Instr = nullptr; 135 136 public: 137 /// \p MsgStr is the message to be reported to the frontend. 138 /// This class does not copy \p MsgStr, therefore the reference must be valid 139 /// for the whole life time of the Diagnostic. 140 DiagnosticInfoInlineAsm(const Twine &MsgStr, 141 DiagnosticSeverity Severity = DS_Error) DiagnosticInfo(DK_InlineAsm,Severity)142 : DiagnosticInfo(DK_InlineAsm, Severity), MsgStr(MsgStr) {} 143 144 /// \p LocCookie if non-zero gives the line number for this report. 145 /// \p MsgStr gives the message. 146 /// This class does not copy \p MsgStr, therefore the reference must be valid 147 /// for the whole life time of the Diagnostic. 148 DiagnosticInfoInlineAsm(unsigned LocCookie, const Twine &MsgStr, 149 DiagnosticSeverity Severity = DS_Error) DiagnosticInfo(DK_InlineAsm,Severity)150 : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(LocCookie), 151 MsgStr(MsgStr) {} 152 153 /// \p Instr gives the original instruction that triggered the diagnostic. 154 /// \p MsgStr gives the message. 155 /// This class does not copy \p MsgStr, therefore the reference must be valid 156 /// for the whole life time of the Diagnostic. 157 /// Same for \p I. 158 DiagnosticInfoInlineAsm(const Instruction &I, const Twine &MsgStr, 159 DiagnosticSeverity Severity = DS_Error); 160 getLocCookie()161 unsigned getLocCookie() const { return LocCookie; } getMsgStr()162 const Twine &getMsgStr() const { return MsgStr; } getInstruction()163 const Instruction *getInstruction() const { return Instr; } 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_InlineAsm; 170 } 171 }; 172 173 /// Diagnostic information for stack size etc. reporting. 174 /// This is basically a function and a size. 175 class DiagnosticInfoResourceLimit : public DiagnosticInfo { 176 private: 177 /// The function that is concerned by this resource limit diagnostic. 178 const Function &Fn; 179 180 /// Description of the resource type (e.g. stack size) 181 const char *ResourceName; 182 183 /// The computed size usage 184 uint64_t ResourceSize; 185 186 // Threshould passed 187 uint64_t ResourceLimit; 188 189 public: 190 /// \p The function that is concerned by this stack size diagnostic. 191 /// \p The computed stack size. 192 DiagnosticInfoResourceLimit(const Function &Fn, const char *ResourceName, 193 uint64_t ResourceSize, 194 DiagnosticSeverity Severity = DS_Warning, 195 DiagnosticKind Kind = DK_ResourceLimit, 196 uint64_t ResourceLimit = 0) DiagnosticInfo(Kind,Severity)197 : DiagnosticInfo(Kind, Severity), Fn(Fn), ResourceName(ResourceName), 198 ResourceSize(ResourceSize), ResourceLimit(ResourceLimit) {} 199 getFunction()200 const Function &getFunction() const { return Fn; } getResourceName()201 const char *getResourceName() const { return ResourceName; } getResourceSize()202 uint64_t getResourceSize() const { return ResourceSize; } getResourceLimit()203 uint64_t getResourceLimit() const { return ResourceLimit; } 204 205 /// \see DiagnosticInfo::print. 206 void print(DiagnosticPrinter &DP) const override; 207 classof(const DiagnosticInfo * DI)208 static bool classof(const DiagnosticInfo *DI) { 209 return DI->getKind() == DK_ResourceLimit || DI->getKind() == DK_StackSize; 210 } 211 }; 212 213 class DiagnosticInfoStackSize : public DiagnosticInfoResourceLimit { 214 virtual void anchor() override; 215 public: 216 DiagnosticInfoStackSize(const Function &Fn, uint64_t StackSize, 217 DiagnosticSeverity Severity = DS_Warning, 218 uint64_t StackLimit = 0) 219 : DiagnosticInfoResourceLimit(Fn, "stack size", StackSize, Severity, 220 DK_StackSize, StackLimit) {} 221 getStackSize()222 uint64_t getStackSize() const { return getResourceSize(); } getStackLimit()223 uint64_t getStackLimit() const { return getResourceLimit(); } 224 classof(const DiagnosticInfo * DI)225 static bool classof(const DiagnosticInfo *DI) { 226 return DI->getKind() == DK_StackSize; 227 } 228 }; 229 230 /// Diagnostic information for debug metadata version reporting. 231 /// This is basically a module and a version. 232 class DiagnosticInfoDebugMetadataVersion : public DiagnosticInfo { 233 private: 234 /// The module that is concerned by this debug metadata version diagnostic. 235 const Module &M; 236 /// The actual metadata version. 237 unsigned MetadataVersion; 238 239 public: 240 /// \p The module that is concerned by this debug metadata version diagnostic. 241 /// \p The actual metadata version. 242 DiagnosticInfoDebugMetadataVersion(const Module &M, unsigned MetadataVersion, 243 DiagnosticSeverity Severity = DS_Warning) DiagnosticInfo(DK_DebugMetadataVersion,Severity)244 : DiagnosticInfo(DK_DebugMetadataVersion, Severity), M(M), 245 MetadataVersion(MetadataVersion) {} 246 getModule()247 const Module &getModule() const { return M; } getMetadataVersion()248 unsigned getMetadataVersion() const { return MetadataVersion; } 249 250 /// \see DiagnosticInfo::print. 251 void print(DiagnosticPrinter &DP) const override; 252 classof(const DiagnosticInfo * DI)253 static bool classof(const DiagnosticInfo *DI) { 254 return DI->getKind() == DK_DebugMetadataVersion; 255 } 256 }; 257 258 /// Diagnostic information for stripping invalid debug metadata. 259 class DiagnosticInfoIgnoringInvalidDebugMetadata : public DiagnosticInfo { 260 private: 261 /// The module that is concerned by this debug metadata version diagnostic. 262 const Module &M; 263 264 public: 265 /// \p The module that is concerned by this debug metadata version diagnostic. 266 DiagnosticInfoIgnoringInvalidDebugMetadata( 267 const Module &M, DiagnosticSeverity Severity = DS_Warning) DiagnosticInfo(DK_DebugMetadataVersion,Severity)268 : DiagnosticInfo(DK_DebugMetadataVersion, Severity), M(M) {} 269 getModule()270 const Module &getModule() const { return M; } 271 272 /// \see DiagnosticInfo::print. 273 void print(DiagnosticPrinter &DP) const override; 274 classof(const DiagnosticInfo * DI)275 static bool classof(const DiagnosticInfo *DI) { 276 return DI->getKind() == DK_DebugMetadataInvalid; 277 } 278 }; 279 280 /// Diagnostic information for the sample profiler. 281 class DiagnosticInfoSampleProfile : public DiagnosticInfo { 282 public: 283 DiagnosticInfoSampleProfile(StringRef FileName, unsigned LineNum, 284 const Twine &Msg, 285 DiagnosticSeverity Severity = DS_Error) DiagnosticInfo(DK_SampleProfile,Severity)286 : DiagnosticInfo(DK_SampleProfile, Severity), FileName(FileName), 287 LineNum(LineNum), Msg(Msg) {} 288 DiagnosticInfoSampleProfile(StringRef FileName, const Twine &Msg, 289 DiagnosticSeverity Severity = DS_Error) DiagnosticInfo(DK_SampleProfile,Severity)290 : DiagnosticInfo(DK_SampleProfile, Severity), FileName(FileName), 291 Msg(Msg) {} 292 DiagnosticInfoSampleProfile(const Twine &Msg, 293 DiagnosticSeverity Severity = DS_Error) DiagnosticInfo(DK_SampleProfile,Severity)294 : DiagnosticInfo(DK_SampleProfile, Severity), Msg(Msg) {} 295 296 /// \see DiagnosticInfo::print. 297 void print(DiagnosticPrinter &DP) const override; 298 classof(const DiagnosticInfo * DI)299 static bool classof(const DiagnosticInfo *DI) { 300 return DI->getKind() == DK_SampleProfile; 301 } 302 getFileName()303 StringRef getFileName() const { return FileName; } getLineNum()304 unsigned getLineNum() const { return LineNum; } getMsg()305 const Twine &getMsg() const { return Msg; } 306 307 private: 308 /// Name of the input file associated with this diagnostic. 309 StringRef FileName; 310 311 /// Line number where the diagnostic occurred. If 0, no line number will 312 /// be emitted in the message. 313 unsigned LineNum = 0; 314 315 /// Message to report. 316 const Twine &Msg; 317 }; 318 319 /// Diagnostic information for the PGO profiler. 320 class DiagnosticInfoPGOProfile : public DiagnosticInfo { 321 public: 322 DiagnosticInfoPGOProfile(const char *FileName, const Twine &Msg, 323 DiagnosticSeverity Severity = DS_Error) DiagnosticInfo(DK_PGOProfile,Severity)324 : DiagnosticInfo(DK_PGOProfile, Severity), FileName(FileName), Msg(Msg) {} 325 326 /// \see DiagnosticInfo::print. 327 void print(DiagnosticPrinter &DP) const override; 328 classof(const DiagnosticInfo * DI)329 static bool classof(const DiagnosticInfo *DI) { 330 return DI->getKind() == DK_PGOProfile; 331 } 332 getFileName()333 const char *getFileName() const { return FileName; } getMsg()334 const Twine &getMsg() const { return Msg; } 335 336 private: 337 /// Name of the input file associated with this diagnostic. 338 const char *FileName; 339 340 /// Message to report. 341 const Twine &Msg; 342 }; 343 344 class DiagnosticLocation { 345 DIFile *File = nullptr; 346 unsigned Line = 0; 347 unsigned Column = 0; 348 349 public: 350 DiagnosticLocation() = default; 351 DiagnosticLocation(const DebugLoc &DL); 352 DiagnosticLocation(const DISubprogram *SP); 353 isValid()354 bool isValid() const { return File; } 355 /// Return the full path to the file. 356 std::string getAbsolutePath() const; 357 /// Return the file name relative to the compilation directory. 358 StringRef getRelativePath() const; getLine()359 unsigned getLine() const { return Line; } getColumn()360 unsigned getColumn() const { return Column; } 361 }; 362 363 /// Common features for diagnostics with an associated location. 364 class DiagnosticInfoWithLocationBase : public DiagnosticInfo { 365 virtual void anchor() override; 366 public: 367 /// \p Fn is the function where the diagnostic is being emitted. \p Loc is 368 /// the location information to use in the diagnostic. DiagnosticInfoWithLocationBase(enum DiagnosticKind Kind,enum DiagnosticSeverity Severity,const Function & Fn,const DiagnosticLocation & Loc)369 DiagnosticInfoWithLocationBase(enum DiagnosticKind Kind, 370 enum DiagnosticSeverity Severity, 371 const Function &Fn, 372 const DiagnosticLocation &Loc) 373 : DiagnosticInfo(Kind, Severity), Fn(Fn), Loc(Loc) {} 374 375 /// Return true if location information is available for this diagnostic. isLocationAvailable()376 bool isLocationAvailable() const { return Loc.isValid(); } 377 378 /// Return a string with the location information for this diagnostic 379 /// in the format "file:line:col". If location information is not available, 380 /// it returns "<unknown>:0:0". 381 const std::string getLocationStr() const; 382 383 /// Return location information for this diagnostic in three parts: 384 /// the relative source file path, line number and column. 385 void getLocation(StringRef &RelativePath, unsigned &Line, 386 unsigned &Column) const; 387 388 /// Return the absolute path tot the file. 389 std::string getAbsolutePath() const; 390 getFunction()391 const Function &getFunction() const { return Fn; } getLocation()392 DiagnosticLocation getLocation() const { return Loc; } 393 394 private: 395 /// Function where this diagnostic is triggered. 396 const Function &Fn; 397 398 /// Debug location where this diagnostic is triggered. 399 DiagnosticLocation Loc; 400 }; 401 402 /// Common features for diagnostics dealing with optimization remarks 403 /// that are used by both IR and MIR passes. 404 class DiagnosticInfoOptimizationBase : public DiagnosticInfoWithLocationBase { 405 public: 406 /// Used to set IsVerbose via the stream interface. 407 struct setIsVerbose {}; 408 409 /// When an instance of this is inserted into the stream, the arguments 410 /// following will not appear in the remark printed in the compiler output 411 /// (-Rpass) but only in the optimization record file 412 /// (-fsave-optimization-record). 413 struct setExtraArgs {}; 414 415 /// Used in the streaming interface as the general argument type. It 416 /// internally converts everything into a key-value pair. 417 struct Argument { 418 std::string Key; 419 std::string Val; 420 // If set, the debug location corresponding to the value. 421 DiagnosticLocation Loc; 422 423 explicit Argument(StringRef Str = "") : Key("String"), Val(Str) {} 424 Argument(StringRef Key, const Value *V); 425 Argument(StringRef Key, const Type *T); 426 Argument(StringRef Key, StringRef S); ArgumentArgument427 Argument(StringRef Key, const char *S) : Argument(Key, StringRef(S)) {}; 428 Argument(StringRef Key, int N); 429 Argument(StringRef Key, float N); 430 Argument(StringRef Key, long N); 431 Argument(StringRef Key, long long N); 432 Argument(StringRef Key, unsigned N); 433 Argument(StringRef Key, unsigned long N); 434 Argument(StringRef Key, unsigned long long N); ArgumentArgument435 Argument(StringRef Key, bool B) : Key(Key), Val(B ? "true" : "false") {} 436 Argument(StringRef Key, DebugLoc dl); 437 }; 438 439 /// \p PassName is the name of the pass emitting this diagnostic. \p 440 /// RemarkName is a textual identifier for the remark (single-word, 441 /// camel-case). \p Fn is the function where the diagnostic is being emitted. 442 /// \p Loc is the location information to use in the diagnostic. If line table 443 /// information is available, the diagnostic will include the source code 444 /// location. DiagnosticInfoOptimizationBase(enum DiagnosticKind Kind,enum DiagnosticSeverity Severity,const char * PassName,StringRef RemarkName,const Function & Fn,const DiagnosticLocation & Loc)445 DiagnosticInfoOptimizationBase(enum DiagnosticKind Kind, 446 enum DiagnosticSeverity Severity, 447 const char *PassName, StringRef RemarkName, 448 const Function &Fn, 449 const DiagnosticLocation &Loc) 450 : DiagnosticInfoWithLocationBase(Kind, Severity, Fn, Loc), 451 PassName(PassName), RemarkName(RemarkName) {} 452 453 void insert(StringRef S); 454 void insert(Argument A); 455 void insert(setIsVerbose V); 456 void insert(setExtraArgs EA); 457 458 /// \see DiagnosticInfo::print. 459 void print(DiagnosticPrinter &DP) const override; 460 461 /// Return true if this optimization remark is enabled by one of 462 /// of the LLVM command line flags (-pass-remarks, -pass-remarks-missed, 463 /// or -pass-remarks-analysis). Note that this only handles the LLVM 464 /// flags. We cannot access Clang flags from here (they are handled 465 /// in BackendConsumer::OptimizationRemarkHandler). 466 virtual bool isEnabled() const = 0; 467 getPassName()468 StringRef getPassName() const { return PassName; } 469 std::string getMsg() const; getHotness()470 Optional<uint64_t> getHotness() const { return Hotness; } setHotness(Optional<uint64_t> H)471 void setHotness(Optional<uint64_t> H) { Hotness = H; } 472 isVerbose()473 bool isVerbose() const { return IsVerbose; } 474 classof(const DiagnosticInfo * DI)475 static bool classof(const DiagnosticInfo *DI) { 476 return (DI->getKind() >= DK_FirstRemark && 477 DI->getKind() <= DK_LastRemark) || 478 (DI->getKind() >= DK_FirstMachineRemark && 479 DI->getKind() <= DK_LastMachineRemark); 480 } 481 isPassed()482 bool isPassed() const { 483 return (getKind() == DK_OptimizationRemark || 484 getKind() == DK_MachineOptimizationRemark); 485 } 486 isMissed()487 bool isMissed() const { 488 return (getKind() == DK_OptimizationRemarkMissed || 489 getKind() == DK_MachineOptimizationRemarkMissed); 490 } 491 isAnalysis()492 bool isAnalysis() const { 493 return (getKind() == DK_OptimizationRemarkAnalysis || 494 getKind() == DK_MachineOptimizationRemarkAnalysis); 495 } 496 497 protected: 498 /// Name of the pass that triggers this report. If this matches the 499 /// regular expression given in -Rpass=regexp, then the remark will 500 /// be emitted. 501 const char *PassName; 502 503 /// Textual identifier for the remark (single-word, camel-case). Can be used 504 /// by external tools reading the YAML output file for optimization remarks to 505 /// identify the remark. 506 StringRef RemarkName; 507 508 /// If profile information is available, this is the number of times the 509 /// corresponding code was executed in a profile instrumentation run. 510 Optional<uint64_t> Hotness; 511 512 /// Arguments collected via the streaming interface. 513 SmallVector<Argument, 4> Args; 514 515 /// The remark is expected to be noisy. 516 bool IsVerbose = false; 517 518 /// If positive, the index of the first argument that only appear in 519 /// the optimization records and not in the remark printed in the compiler 520 /// output. 521 int FirstExtraArgIndex = -1; 522 523 friend struct yaml::MappingTraits<DiagnosticInfoOptimizationBase *>; 524 }; 525 526 /// Allow the insertion operator to return the actual remark type rather than a 527 /// common base class. This allows returning the result of the insertion 528 /// directly by value, e.g. return OptimizationRemarkAnalysis(...) << "blah". 529 template <class RemarkT> 530 RemarkT & 531 operator<<(RemarkT &R, 532 typename std::enable_if< 533 std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value, 534 StringRef>::type S) { 535 R.insert(S); 536 return R; 537 } 538 539 /// Also allow r-value for the remark to allow insertion into a 540 /// temporarily-constructed remark. 541 template <class RemarkT> 542 RemarkT & 543 operator<<(RemarkT &&R, 544 typename std::enable_if< 545 std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value, 546 StringRef>::type S) { 547 R.insert(S); 548 return R; 549 } 550 551 template <class RemarkT> 552 RemarkT & 553 operator<<(RemarkT &R, 554 typename std::enable_if< 555 std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value, 556 DiagnosticInfoOptimizationBase::Argument>::type A) { 557 R.insert(A); 558 return R; 559 } 560 561 template <class RemarkT> 562 RemarkT & 563 operator<<(RemarkT &&R, 564 typename std::enable_if< 565 std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value, 566 DiagnosticInfoOptimizationBase::Argument>::type A) { 567 R.insert(A); 568 return R; 569 } 570 571 template <class RemarkT> 572 RemarkT & 573 operator<<(RemarkT &R, 574 typename std::enable_if< 575 std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value, 576 DiagnosticInfoOptimizationBase::setIsVerbose>::type V) { 577 R.insert(V); 578 return R; 579 } 580 581 template <class RemarkT> 582 RemarkT & 583 operator<<(RemarkT &&R, 584 typename std::enable_if< 585 std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value, 586 DiagnosticInfoOptimizationBase::setIsVerbose>::type V) { 587 R.insert(V); 588 return R; 589 } 590 591 template <class RemarkT> 592 RemarkT & 593 operator<<(RemarkT &R, 594 typename std::enable_if< 595 std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value, 596 DiagnosticInfoOptimizationBase::setExtraArgs>::type EA) { 597 R.insert(EA); 598 return R; 599 } 600 601 /// Common features for diagnostics dealing with optimization remarks 602 /// that are used by IR passes. 603 class DiagnosticInfoIROptimization : public DiagnosticInfoOptimizationBase { 604 virtual void anchor() override; 605 public: 606 /// \p PassName is the name of the pass emitting this diagnostic. \p 607 /// RemarkName is a textual identifier for the remark (single-word, 608 /// camel-case). \p Fn is the function where the diagnostic is being emitted. 609 /// \p Loc is the location information to use in the diagnostic. If line table 610 /// information is available, the diagnostic will include the source code 611 /// location. \p CodeRegion is IR value (currently basic block) that the 612 /// optimization operates on. This is currently used to provide run-time 613 /// hotness information with PGO. 614 DiagnosticInfoIROptimization(enum DiagnosticKind Kind, 615 enum DiagnosticSeverity Severity, 616 const char *PassName, StringRef RemarkName, 617 const Function &Fn, 618 const DiagnosticLocation &Loc, 619 const Value *CodeRegion = nullptr) 620 : DiagnosticInfoOptimizationBase(Kind, Severity, PassName, RemarkName, Fn, 621 Loc), 622 CodeRegion(CodeRegion) {} 623 624 /// This is ctor variant allows a pass to build an optimization remark 625 /// from an existing remark. 626 /// 627 /// This is useful when a transformation pass (e.g LV) wants to emit a remark 628 /// (\p Orig) generated by one of its analyses (e.g. LAA) as its own analysis 629 /// remark. The string \p Prepend will be emitted before the original 630 /// message. 631 DiagnosticInfoIROptimization(const char *PassName, StringRef Prepend, 632 const DiagnosticInfoIROptimization &Orig) 633 : DiagnosticInfoOptimizationBase( 634 (DiagnosticKind)Orig.getKind(), Orig.getSeverity(), PassName, 635 Orig.RemarkName, Orig.getFunction(), Orig.getLocation()), 636 CodeRegion(Orig.getCodeRegion()) { 637 *this << Prepend; 638 std::copy(Orig.Args.begin(), Orig.Args.end(), std::back_inserter(Args)); 639 } 640 641 /// Legacy interface. 642 /// \p PassName is the name of the pass emitting this diagnostic. 643 /// \p Fn is the function where the diagnostic is being emitted. \p Loc is 644 /// the location information to use in the diagnostic. If line table 645 /// information is available, the diagnostic will include the source code 646 /// location. \p Msg is the message to show. Note that this class does not 647 /// copy this message, so this reference must be valid for the whole life time 648 /// of the diagnostic. 649 DiagnosticInfoIROptimization(enum DiagnosticKind Kind, 650 enum DiagnosticSeverity Severity, 651 const char *PassName, const Function &Fn, 652 const DiagnosticLocation &Loc, const Twine &Msg) 653 : DiagnosticInfoOptimizationBase(Kind, Severity, PassName, "", Fn, Loc) { 654 *this << Msg.str(); 655 } 656 657 const Value *getCodeRegion() const { return CodeRegion; } 658 659 static bool classof(const DiagnosticInfo *DI) { 660 return DI->getKind() >= DK_FirstRemark && DI->getKind() <= DK_LastRemark; 661 } 662 663 private: 664 /// The IR value (currently basic block) that the optimization operates on. 665 /// This is currently used to provide run-time hotness information with PGO. 666 const Value *CodeRegion; 667 }; 668 669 /// Diagnostic information for applied optimization remarks. 670 class OptimizationRemark : public DiagnosticInfoIROptimization { 671 public: 672 /// \p PassName is the name of the pass emitting this diagnostic. If this name 673 /// matches the regular expression given in -Rpass=, then the diagnostic will 674 /// be emitted. \p RemarkName is a textual identifier for the remark (single- 675 /// word, camel-case). \p Loc is the debug location and \p CodeRegion is the 676 /// region that the optimization operates on (currently only block is 677 /// supported). 678 OptimizationRemark(const char *PassName, StringRef RemarkName, 679 const DiagnosticLocation &Loc, const Value *CodeRegion); 680 681 /// Same as above, but the debug location and code region are derived from \p 682 /// Instr. 683 OptimizationRemark(const char *PassName, StringRef RemarkName, 684 const Instruction *Inst); 685 686 /// Same as above, but the debug location and code region are derived from \p 687 /// Func. 688 OptimizationRemark(const char *PassName, StringRef RemarkName, 689 const Function *Func); 690 691 static bool classof(const DiagnosticInfo *DI) { 692 return DI->getKind() == DK_OptimizationRemark; 693 } 694 695 /// \see DiagnosticInfoOptimizationBase::isEnabled. 696 bool isEnabled() const override; 697 698 private: 699 /// This is deprecated now and only used by the function API below. 700 /// \p PassName is the name of the pass emitting this diagnostic. If 701 /// this name matches the regular expression given in -Rpass=, then the 702 /// diagnostic will be emitted. \p Fn is the function where the diagnostic 703 /// is being emitted. \p Loc is the location information to use in the 704 /// diagnostic. If line table information is available, the diagnostic 705 /// will include the source code location. \p Msg is the message to show. 706 /// Note that this class does not copy this message, so this reference 707 /// must be valid for the whole life time of the diagnostic. 708 OptimizationRemark(const char *PassName, const Function &Fn, 709 const DiagnosticLocation &Loc, const Twine &Msg) 710 : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName, 711 Fn, Loc, Msg) {} 712 }; 713 714 /// Diagnostic information for missed-optimization remarks. 715 class OptimizationRemarkMissed : public DiagnosticInfoIROptimization { 716 public: 717 /// \p PassName is the name of the pass emitting this diagnostic. If this name 718 /// matches the regular expression given in -Rpass-missed=, then the 719 /// diagnostic will be emitted. \p RemarkName is a textual identifier for the 720 /// remark (single-word, camel-case). \p Loc is the debug location and \p 721 /// CodeRegion is the region that the optimization operates on (currently only 722 /// block is supported). 723 OptimizationRemarkMissed(const char *PassName, StringRef RemarkName, 724 const DiagnosticLocation &Loc, 725 const Value *CodeRegion); 726 727 /// Same as above but \p Inst is used to derive code region and debug 728 /// location. 729 OptimizationRemarkMissed(const char *PassName, StringRef RemarkName, 730 const Instruction *Inst); 731 732 static bool classof(const DiagnosticInfo *DI) { 733 return DI->getKind() == DK_OptimizationRemarkMissed; 734 } 735 736 /// \see DiagnosticInfoOptimizationBase::isEnabled. 737 bool isEnabled() const override; 738 739 private: 740 /// This is deprecated now and only used by the function API below. 741 /// \p PassName is the name of the pass emitting this diagnostic. If 742 /// this name matches the regular expression given in -Rpass-missed=, then the 743 /// diagnostic will be emitted. \p Fn is the function where the diagnostic 744 /// is being emitted. \p Loc is the location information to use in the 745 /// diagnostic. If line table information is available, the diagnostic 746 /// will include the source code location. \p Msg is the message to show. 747 /// Note that this class does not copy this message, so this reference 748 /// must be valid for the whole life time of the diagnostic. 749 OptimizationRemarkMissed(const char *PassName, const Function &Fn, 750 const DiagnosticLocation &Loc, const Twine &Msg) 751 : DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark, 752 PassName, Fn, Loc, Msg) {} 753 }; 754 755 /// Diagnostic information for optimization analysis remarks. 756 class OptimizationRemarkAnalysis : public DiagnosticInfoIROptimization { 757 public: 758 /// \p PassName is the name of the pass emitting this diagnostic. If this name 759 /// matches the regular expression given in -Rpass-analysis=, then the 760 /// diagnostic will be emitted. \p RemarkName is a textual identifier for the 761 /// remark (single-word, camel-case). \p Loc is the debug location and \p 762 /// CodeRegion is the region that the optimization operates on (currently only 763 /// block is supported). 764 OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName, 765 const DiagnosticLocation &Loc, 766 const Value *CodeRegion); 767 768 /// This is ctor variant allows a pass to build an optimization remark 769 /// from an existing remark. 770 /// 771 /// This is useful when a transformation pass (e.g LV) wants to emit a remark 772 /// (\p Orig) generated by one of its analyses (e.g. LAA) as its own analysis 773 /// remark. The string \p Prepend will be emitted before the original 774 /// message. 775 OptimizationRemarkAnalysis(const char *PassName, StringRef Prepend, 776 const OptimizationRemarkAnalysis &Orig) 777 : DiagnosticInfoIROptimization(PassName, Prepend, Orig) {} 778 779 /// Same as above but \p Inst is used to derive code region and debug 780 /// location. 781 OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName, 782 const Instruction *Inst); 783 784 static bool classof(const DiagnosticInfo *DI) { 785 return DI->getKind() == DK_OptimizationRemarkAnalysis; 786 } 787 788 /// \see DiagnosticInfoOptimizationBase::isEnabled. 789 bool isEnabled() const override; 790 791 static const char *AlwaysPrint; 792 793 bool shouldAlwaysPrint() const { return getPassName() == AlwaysPrint; } 794 795 protected: 796 OptimizationRemarkAnalysis(enum DiagnosticKind Kind, const char *PassName, 797 const Function &Fn, const DiagnosticLocation &Loc, 798 const Twine &Msg) 799 : DiagnosticInfoIROptimization(Kind, DS_Remark, PassName, Fn, Loc, Msg) {} 800 801 OptimizationRemarkAnalysis(enum DiagnosticKind Kind, const char *PassName, 802 StringRef RemarkName, 803 const DiagnosticLocation &Loc, 804 const Value *CodeRegion); 805 806 private: 807 /// This is deprecated now and only used by the function API below. 808 /// \p PassName is the name of the pass emitting this diagnostic. If 809 /// this name matches the regular expression given in -Rpass-analysis=, then 810 /// the diagnostic will be emitted. \p Fn is the function where the diagnostic 811 /// is being emitted. \p Loc is the location information to use in the 812 /// diagnostic. If line table information is available, the diagnostic will 813 /// include the source code location. \p Msg is the message to show. Note that 814 /// this class does not copy this message, so this reference must be valid for 815 /// the whole life time of the diagnostic. 816 OptimizationRemarkAnalysis(const char *PassName, const Function &Fn, 817 const DiagnosticLocation &Loc, const Twine &Msg) 818 : DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark, 819 PassName, Fn, Loc, Msg) {} 820 }; 821 822 /// Diagnostic information for optimization analysis remarks related to 823 /// floating-point non-commutativity. 824 class OptimizationRemarkAnalysisFPCommute : public OptimizationRemarkAnalysis { 825 virtual void anchor(); 826 public: 827 /// \p PassName is the name of the pass emitting this diagnostic. If this name 828 /// matches the regular expression given in -Rpass-analysis=, then the 829 /// diagnostic will be emitted. \p RemarkName is a textual identifier for the 830 /// remark (single-word, camel-case). \p Loc is the debug location and \p 831 /// CodeRegion is the region that the optimization operates on (currently only 832 /// block is supported). The front-end will append its own message related to 833 /// options that address floating-point non-commutativity. 834 OptimizationRemarkAnalysisFPCommute(const char *PassName, 835 StringRef RemarkName, 836 const DiagnosticLocation &Loc, 837 const Value *CodeRegion) 838 : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute, 839 PassName, RemarkName, Loc, CodeRegion) {} 840 841 static bool classof(const DiagnosticInfo *DI) { 842 return DI->getKind() == DK_OptimizationRemarkAnalysisFPCommute; 843 } 844 845 private: 846 /// This is deprecated now and only used by the function API below. 847 /// \p PassName is the name of the pass emitting this diagnostic. If 848 /// this name matches the regular expression given in -Rpass-analysis=, then 849 /// the diagnostic will be emitted. \p Fn is the function where the diagnostic 850 /// is being emitted. \p Loc is the location information to use in the 851 /// diagnostic. If line table information is available, the diagnostic will 852 /// include the source code location. \p Msg is the message to show. The 853 /// front-end will append its own message related to options that address 854 /// floating-point non-commutativity. Note that this class does not copy this 855 /// message, so this reference must be valid for the whole life time of the 856 /// diagnostic. 857 OptimizationRemarkAnalysisFPCommute(const char *PassName, const Function &Fn, 858 const DiagnosticLocation &Loc, 859 const Twine &Msg) 860 : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute, 861 PassName, Fn, Loc, Msg) {} 862 }; 863 864 /// Diagnostic information for optimization analysis remarks related to 865 /// pointer aliasing. 866 class OptimizationRemarkAnalysisAliasing : public OptimizationRemarkAnalysis { 867 virtual void anchor(); 868 public: 869 /// \p PassName is the name of the pass emitting this diagnostic. If this name 870 /// matches the regular expression given in -Rpass-analysis=, then the 871 /// diagnostic will be emitted. \p RemarkName is a textual identifier for the 872 /// remark (single-word, camel-case). \p Loc is the debug location and \p 873 /// CodeRegion is the region that the optimization operates on (currently only 874 /// block is supported). The front-end will append its own message related to 875 /// options that address pointer aliasing legality. 876 OptimizationRemarkAnalysisAliasing(const char *PassName, StringRef RemarkName, 877 const DiagnosticLocation &Loc, 878 const Value *CodeRegion) 879 : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing, 880 PassName, RemarkName, Loc, CodeRegion) {} 881 882 static bool classof(const DiagnosticInfo *DI) { 883 return DI->getKind() == DK_OptimizationRemarkAnalysisAliasing; 884 } 885 886 private: 887 /// This is deprecated now and only used by the function API below. 888 /// \p PassName is the name of the pass emitting this diagnostic. If 889 /// this name matches the regular expression given in -Rpass-analysis=, then 890 /// the diagnostic will be emitted. \p Fn is the function where the diagnostic 891 /// is being emitted. \p Loc is the location information to use in the 892 /// diagnostic. If line table information is available, the diagnostic will 893 /// include the source code location. \p Msg is the message to show. The 894 /// front-end will append its own message related to options that address 895 /// pointer aliasing legality. Note that this class does not copy this 896 /// message, so this reference must be valid for the whole life time of the 897 /// diagnostic. 898 OptimizationRemarkAnalysisAliasing(const char *PassName, const Function &Fn, 899 const DiagnosticLocation &Loc, 900 const Twine &Msg) 901 : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing, 902 PassName, Fn, Loc, Msg) {} 903 }; 904 905 /// Diagnostic information for machine IR parser. 906 class DiagnosticInfoMIRParser : public DiagnosticInfo { 907 const SMDiagnostic &Diagnostic; 908 909 public: 910 DiagnosticInfoMIRParser(DiagnosticSeverity Severity, 911 const SMDiagnostic &Diagnostic) 912 : DiagnosticInfo(DK_MIRParser, Severity), Diagnostic(Diagnostic) {} 913 914 const SMDiagnostic &getDiagnostic() const { return Diagnostic; } 915 916 void print(DiagnosticPrinter &DP) const override; 917 918 static bool classof(const DiagnosticInfo *DI) { 919 return DI->getKind() == DK_MIRParser; 920 } 921 }; 922 923 /// Diagnostic information for ISel fallback path. 924 class DiagnosticInfoISelFallback : public DiagnosticInfo { 925 /// The function that is concerned by this diagnostic. 926 const Function &Fn; 927 928 public: 929 DiagnosticInfoISelFallback(const Function &Fn, 930 DiagnosticSeverity Severity = DS_Warning) 931 : DiagnosticInfo(DK_ISelFallback, Severity), Fn(Fn) {} 932 933 const Function &getFunction() const { return Fn; } 934 935 void print(DiagnosticPrinter &DP) const override; 936 937 static bool classof(const DiagnosticInfo *DI) { 938 return DI->getKind() == DK_ISelFallback; 939 } 940 }; 941 942 // Create wrappers for C Binding types (see CBindingWrapping.h). 943 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DiagnosticInfo, LLVMDiagnosticInfoRef) 944 945 /// Diagnostic information for optimization failures. 946 class DiagnosticInfoOptimizationFailure : public DiagnosticInfoIROptimization { 947 public: 948 /// \p Fn is the function where the diagnostic is being emitted. \p Loc is 949 /// the location information to use in the diagnostic. If line table 950 /// information is available, the diagnostic will include the source code 951 /// location. \p Msg is the message to show. Note that this class does not 952 /// copy this message, so this reference must be valid for the whole life time 953 /// of the diagnostic. 954 DiagnosticInfoOptimizationFailure(const Function &Fn, 955 const DiagnosticLocation &Loc, 956 const Twine &Msg) 957 : DiagnosticInfoIROptimization(DK_OptimizationFailure, DS_Warning, 958 nullptr, Fn, Loc, Msg) {} 959 960 /// \p PassName is the name of the pass emitting this diagnostic. \p 961 /// RemarkName is a textual identifier for the remark (single-word, 962 /// camel-case). \p Loc is the debug location and \p CodeRegion is the 963 /// region that the optimization operates on (currently basic block is 964 /// supported). 965 DiagnosticInfoOptimizationFailure(const char *PassName, StringRef RemarkName, 966 const DiagnosticLocation &Loc, 967 const Value *CodeRegion); 968 969 static bool classof(const DiagnosticInfo *DI) { 970 return DI->getKind() == DK_OptimizationFailure; 971 } 972 973 /// \see DiagnosticInfoOptimizationBase::isEnabled. 974 bool isEnabled() const override; 975 }; 976 977 /// Diagnostic information for unsupported feature in backend. 978 class DiagnosticInfoUnsupported : public DiagnosticInfoWithLocationBase { 979 private: 980 Twine Msg; 981 982 public: 983 /// \p Fn is the function where the diagnostic is being emitted. \p Loc is 984 /// the location information to use in the diagnostic. If line table 985 /// information is available, the diagnostic will include the source code 986 /// location. \p Msg is the message to show. Note that this class does not 987 /// copy this message, so this reference must be valid for the whole life time 988 /// of the diagnostic. 989 DiagnosticInfoUnsupported( 990 const Function &Fn, const Twine &Msg, 991 const DiagnosticLocation &Loc = DiagnosticLocation(), 992 DiagnosticSeverity Severity = DS_Error) 993 : DiagnosticInfoWithLocationBase(DK_Unsupported, Severity, Fn, Loc), 994 Msg(Msg) {} 995 996 static bool classof(const DiagnosticInfo *DI) { 997 return DI->getKind() == DK_Unsupported; 998 } 999 1000 const Twine &getMessage() const { return Msg; } 1001 1002 void print(DiagnosticPrinter &DP) const override; 1003 }; 1004 1005 namespace yaml { 1006 template <> struct MappingTraits<DiagnosticInfoOptimizationBase *> { 1007 static void mapping(IO &io, DiagnosticInfoOptimizationBase *&OptDiag); 1008 }; 1009 } // namespace yaml 1010 1011 } // end namespace llvm 1012 1013 #endif // LLVM_IR_DIAGNOSTICINFO_H 1014