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