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