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