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