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