1 //===- StandardInstrumentations.h ------------------------------*- 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 /// \file 9 /// 10 /// This header defines a class that provides bookkeeping for all standard 11 /// (i.e in-tree) pass instrumentations. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_PASSES_STANDARDINSTRUMENTATIONS_H 16 #define LLVM_PASSES_STANDARDINSTRUMENTATIONS_H 17 18 #include "llvm/ADT/STLExtras.h" 19 #include "llvm/ADT/SmallVector.h" 20 #include "llvm/ADT/StringRef.h" 21 #include "llvm/ADT/StringSet.h" 22 #include "llvm/CodeGen/MachineBasicBlock.h" 23 #include "llvm/IR/BasicBlock.h" 24 #include "llvm/IR/OptBisect.h" 25 #include "llvm/IR/PassTimingInfo.h" 26 #include "llvm/IR/ValueHandle.h" 27 #include "llvm/Support/CommandLine.h" 28 #include "llvm/Support/TimeProfiler.h" 29 #include "llvm/Transforms/IPO/SampleProfileProbe.h" 30 31 #include <string> 32 #include <utility> 33 34 namespace llvm { 35 36 class Module; 37 class Function; 38 class MachineFunction; 39 class PassInstrumentationCallbacks; 40 41 /// Instrumentation to print IR before/after passes. 42 /// 43 /// Needs state to be able to print module after pass that invalidates IR unit 44 /// (typically Loop or SCC). 45 class PrintIRInstrumentation { 46 public: 47 ~PrintIRInstrumentation(); 48 49 void registerCallbacks(PassInstrumentationCallbacks &PIC); 50 51 private: 52 struct PassRunDescriptor { 53 const Module *M; 54 const std::string DumpIRFilename; 55 const std::string IRName; 56 const StringRef PassID; 57 PassRunDescriptorPassRunDescriptor58 PassRunDescriptor(const Module *M, std::string DumpIRFilename, 59 std::string IRName, const StringRef PassID) 60 : M{M}, DumpIRFilename{DumpIRFilename}, IRName{IRName}, PassID(PassID) { 61 } 62 }; 63 64 void printBeforePass(StringRef PassID, Any IR); 65 void printAfterPass(StringRef PassID, Any IR); 66 void printAfterPassInvalidated(StringRef PassID); 67 68 bool shouldPrintBeforePass(StringRef PassID); 69 bool shouldPrintAfterPass(StringRef PassID); 70 bool shouldPrintBeforeCurrentPassNumber(); 71 bool shouldPrintAfterCurrentPassNumber(); 72 bool shouldPrintPassNumbers(); 73 bool shouldPrintBeforeSomePassNumber(); 74 bool shouldPrintAfterSomePassNumber(); 75 76 void pushPassRunDescriptor(StringRef PassID, Any IR, 77 std::string &DumpIRFilename); 78 PassRunDescriptor popPassRunDescriptor(StringRef PassID); 79 std::string fetchDumpFilename(StringRef PassId, Any IR); 80 81 PassInstrumentationCallbacks *PIC; 82 /// Stack of Pass Run descriptions, enough to print the IR unit after a given 83 /// pass. 84 SmallVector<PassRunDescriptor, 2> PassRunDescriptorStack; 85 86 /// Used for print-at-pass-number 87 unsigned CurrentPassNumber = 0; 88 }; 89 90 class OptNoneInstrumentation { 91 public: OptNoneInstrumentation(bool DebugLogging)92 OptNoneInstrumentation(bool DebugLogging) : DebugLogging(DebugLogging) {} 93 void registerCallbacks(PassInstrumentationCallbacks &PIC); 94 95 private: 96 bool DebugLogging; 97 bool shouldRun(StringRef PassID, Any IR); 98 }; 99 100 class OptPassGateInstrumentation { 101 LLVMContext &Context; 102 bool HasWrittenIR = false; 103 public: OptPassGateInstrumentation(LLVMContext & Context)104 OptPassGateInstrumentation(LLVMContext &Context) : Context(Context) {} 105 bool shouldRun(StringRef PassName, Any IR); 106 void registerCallbacks(PassInstrumentationCallbacks &PIC); 107 }; 108 109 struct PrintPassOptions { 110 /// Print adaptors and pass managers. 111 bool Verbose = false; 112 /// Don't print information for analyses. 113 bool SkipAnalyses = false; 114 /// Indent based on hierarchy. 115 bool Indent = false; 116 }; 117 118 // Debug logging for transformation and analysis passes. 119 class PrintPassInstrumentation { 120 raw_ostream &print(); 121 122 public: PrintPassInstrumentation(bool Enabled,PrintPassOptions Opts)123 PrintPassInstrumentation(bool Enabled, PrintPassOptions Opts) 124 : Enabled(Enabled), Opts(Opts) {} 125 void registerCallbacks(PassInstrumentationCallbacks &PIC); 126 127 private: 128 bool Enabled; 129 PrintPassOptions Opts; 130 int Indent = 0; 131 }; 132 133 class PreservedCFGCheckerInstrumentation { 134 public: 135 // Keeps sticky poisoned flag for the given basic block once it has been 136 // deleted or RAUWed. 137 struct BBGuard final : public CallbackVH { BBGuardfinal138 BBGuard(const BasicBlock *BB) : CallbackVH(BB) {} deletedfinal139 void deleted() override { CallbackVH::deleted(); } allUsesReplacedWithfinal140 void allUsesReplacedWith(Value *) override { CallbackVH::deleted(); } isPoisonedfinal141 bool isPoisoned() const { return !getValPtr(); } 142 }; 143 144 // CFG is a map BB -> {(Succ, Multiplicity)}, where BB is a non-leaf basic 145 // block, {(Succ, Multiplicity)} set of all pairs of the block's successors 146 // and the multiplicity of the edge (BB->Succ). As the mapped sets are 147 // unordered the order of successors is not tracked by the CFG. In other words 148 // this allows basic block successors to be swapped by a pass without 149 // reporting a CFG change. CFG can be guarded by basic block tracking pointers 150 // in the Graph (BBGuard). That is if any of the block is deleted or RAUWed 151 // then the CFG is treated poisoned and no block pointer of the Graph is used. 152 struct CFG { 153 std::optional<DenseMap<intptr_t, BBGuard>> BBGuards; 154 DenseMap<const BasicBlock *, DenseMap<const BasicBlock *, unsigned>> Graph; 155 156 CFG(const Function *F, bool TrackBBLifetime); 157 158 bool operator==(const CFG &G) const { 159 return !isPoisoned() && !G.isPoisoned() && Graph == G.Graph; 160 } 161 isPoisonedCFG162 bool isPoisoned() const { 163 return BBGuards && llvm::any_of(*BBGuards, [](const auto &BB) { 164 return BB.second.isPoisoned(); 165 }); 166 } 167 168 static void printDiff(raw_ostream &out, const CFG &Before, 169 const CFG &After); 170 bool invalidate(Function &F, const PreservedAnalyses &PA, 171 FunctionAnalysisManager::Invalidator &); 172 }; 173 174 #ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS 175 SmallVector<StringRef, 8> PassStack; 176 #endif 177 178 void registerCallbacks(PassInstrumentationCallbacks &PIC, 179 ModuleAnalysisManager &MAM); 180 }; 181 182 // Base class for classes that report changes to the IR. 183 // It presents an interface for such classes and provides calls 184 // on various events as the new pass manager transforms the IR. 185 // It also provides filtering of information based on hidden options 186 // specifying which functions are interesting. 187 // Calls are made for the following events/queries: 188 // 1. The initial IR processed. 189 // 2. To get the representation of the IR (of type \p T). 190 // 3. When a pass does not change the IR. 191 // 4. When a pass changes the IR (given both before and after representations 192 // of type \p T). 193 // 5. When an IR is invalidated. 194 // 6. When a pass is run on an IR that is not interesting (based on options). 195 // 7. When a pass is ignored (pass manager or adapter pass). 196 // 8. To compare two IR representations (of type \p T). 197 template <typename IRUnitT> class ChangeReporter { 198 protected: ChangeReporter(bool RunInVerboseMode)199 ChangeReporter(bool RunInVerboseMode) : VerboseMode(RunInVerboseMode) {} 200 201 public: 202 virtual ~ChangeReporter(); 203 204 // Determine if this pass/IR is interesting and if so, save the IR 205 // otherwise it is left on the stack without data. 206 void saveIRBeforePass(Any IR, StringRef PassID, StringRef PassName); 207 // Compare the IR from before the pass after the pass. 208 void handleIRAfterPass(Any IR, StringRef PassID, StringRef PassName); 209 // Handle the situation where a pass is invalidated. 210 void handleInvalidatedPass(StringRef PassID); 211 212 protected: 213 // Register required callbacks. 214 void registerRequiredCallbacks(PassInstrumentationCallbacks &PIC); 215 216 // Called on the first IR processed. 217 virtual void handleInitialIR(Any IR) = 0; 218 // Called before and after a pass to get the representation of the IR. 219 virtual void generateIRRepresentation(Any IR, StringRef PassID, 220 IRUnitT &Output) = 0; 221 // Called when the pass is not iteresting. 222 virtual void omitAfter(StringRef PassID, std::string &Name) = 0; 223 // Called when an interesting IR has changed. 224 virtual void handleAfter(StringRef PassID, std::string &Name, 225 const IRUnitT &Before, const IRUnitT &After, 226 Any) = 0; 227 // Called when an interesting pass is invalidated. 228 virtual void handleInvalidated(StringRef PassID) = 0; 229 // Called when the IR or pass is not interesting. 230 virtual void handleFiltered(StringRef PassID, std::string &Name) = 0; 231 // Called when an ignored pass is encountered. 232 virtual void handleIgnored(StringRef PassID, std::string &Name) = 0; 233 234 // Stack of IRs before passes. 235 std::vector<IRUnitT> BeforeStack; 236 // Is this the first IR seen? 237 bool InitialIR = true; 238 239 // Run in verbose mode, printing everything? 240 const bool VerboseMode; 241 }; 242 243 // An abstract template base class that handles printing banners and 244 // reporting when things have not changed or are filtered out. 245 template <typename IRUnitT> 246 class TextChangeReporter : public ChangeReporter<IRUnitT> { 247 protected: 248 TextChangeReporter(bool Verbose); 249 250 // Print a module dump of the first IR that is changed. 251 void handleInitialIR(Any IR) override; 252 // Report that the IR was omitted because it did not change. 253 void omitAfter(StringRef PassID, std::string &Name) override; 254 // Report that the pass was invalidated. 255 void handleInvalidated(StringRef PassID) override; 256 // Report that the IR was filtered out. 257 void handleFiltered(StringRef PassID, std::string &Name) override; 258 // Report that the pass was ignored. 259 void handleIgnored(StringRef PassID, std::string &Name) override; 260 // Make substitutions in \p S suitable for reporting changes 261 // after the pass and then print it. 262 263 raw_ostream &Out; 264 }; 265 266 // A change printer based on the string representation of the IR as created 267 // by unwrapAndPrint. The string representation is stored in a std::string 268 // to preserve it as the IR changes in each pass. Note that the banner is 269 // included in this representation but it is massaged before reporting. 270 class IRChangedPrinter : public TextChangeReporter<std::string> { 271 public: IRChangedPrinter(bool VerboseMode)272 IRChangedPrinter(bool VerboseMode) 273 : TextChangeReporter<std::string>(VerboseMode) {} 274 ~IRChangedPrinter() override; 275 void registerCallbacks(PassInstrumentationCallbacks &PIC); 276 277 protected: 278 // Called before and after a pass to get the representation of the IR. 279 void generateIRRepresentation(Any IR, StringRef PassID, 280 std::string &Output) override; 281 // Called when an interesting IR has changed. 282 void handleAfter(StringRef PassID, std::string &Name, 283 const std::string &Before, const std::string &After, 284 Any) override; 285 }; 286 287 class IRChangedTester : public IRChangedPrinter { 288 public: IRChangedTester()289 IRChangedTester() : IRChangedPrinter(true) {} 290 ~IRChangedTester() override; 291 void registerCallbacks(PassInstrumentationCallbacks &PIC); 292 293 protected: 294 void handleIR(const std::string &IR, StringRef PassID); 295 296 // Check initial IR 297 void handleInitialIR(Any IR) override; 298 // Do nothing. 299 void omitAfter(StringRef PassID, std::string &Name) override; 300 // Do nothing. 301 void handleInvalidated(StringRef PassID) override; 302 // Do nothing. 303 void handleFiltered(StringRef PassID, std::string &Name) override; 304 // Do nothing. 305 void handleIgnored(StringRef PassID, std::string &Name) override; 306 307 // Call test as interesting IR has changed. 308 void handleAfter(StringRef PassID, std::string &Name, 309 const std::string &Before, const std::string &After, 310 Any) override; 311 }; 312 313 // Information that needs to be saved for a basic block in order to compare 314 // before and after the pass to determine if it was changed by a pass. 315 template <typename T> class BlockDataT { 316 public: BlockDataT(const BasicBlock & B)317 BlockDataT(const BasicBlock &B) : Label(B.getName().str()), Data(B) { 318 raw_string_ostream SS(Body); 319 B.print(SS, nullptr, true, true); 320 } 321 BlockDataT(const MachineBasicBlock & B)322 BlockDataT(const MachineBasicBlock &B) : Label(B.getName().str()), Data(B) { 323 raw_string_ostream SS(Body); 324 B.print(SS); 325 } 326 327 bool operator==(const BlockDataT &That) const { return Body == That.Body; } 328 bool operator!=(const BlockDataT &That) const { return Body != That.Body; } 329 330 // Return the label of the represented basic block. getLabel()331 StringRef getLabel() const { return Label; } 332 // Return the string representation of the basic block. getBody()333 StringRef getBody() const { return Body; } 334 335 // Return the associated data getData()336 const T &getData() const { return Data; } 337 338 protected: 339 std::string Label; 340 std::string Body; 341 342 // Extra data associated with a basic block 343 T Data; 344 }; 345 346 template <typename T> class OrderedChangedData { 347 public: 348 // Return the names in the order they were saved getOrder()349 std::vector<std::string> &getOrder() { return Order; } getOrder()350 const std::vector<std::string> &getOrder() const { return Order; } 351 352 // Return a map of names to saved representations getData()353 StringMap<T> &getData() { return Data; } getData()354 const StringMap<T> &getData() const { return Data; } 355 356 bool operator==(const OrderedChangedData<T> &That) const { 357 return Data == That.getData(); 358 } 359 360 // Call the lambda \p HandlePair on each corresponding pair of data from 361 // \p Before and \p After. The order is based on the order in \p After 362 // with ones that are only in \p Before interspersed based on where they 363 // occur in \p Before. This is used to present the output in an order 364 // based on how the data is ordered in LLVM. 365 static void report(const OrderedChangedData &Before, 366 const OrderedChangedData &After, 367 function_ref<void(const T *, const T *)> HandlePair); 368 369 protected: 370 std::vector<std::string> Order; 371 StringMap<T> Data; 372 }; 373 374 // Do not need extra information for patch-style change reporter. 375 class EmptyData { 376 public: EmptyData(const BasicBlock &)377 EmptyData(const BasicBlock &) {} EmptyData(const MachineBasicBlock &)378 EmptyData(const MachineBasicBlock &) {} 379 }; 380 381 // The data saved for comparing functions. 382 template <typename T> 383 class FuncDataT : public OrderedChangedData<BlockDataT<T>> { 384 public: FuncDataT(std::string S)385 FuncDataT(std::string S) : EntryBlockName(S) {} 386 387 // Return the name of the entry block getEntryBlockName()388 std::string getEntryBlockName() const { return EntryBlockName; } 389 390 protected: 391 std::string EntryBlockName; 392 }; 393 394 // The data saved for comparing IRs. 395 template <typename T> 396 class IRDataT : public OrderedChangedData<FuncDataT<T>> {}; 397 398 // Abstract template base class for a class that compares two IRs. The 399 // class is created with the 2 IRs to compare and then compare is called. 400 // The static function analyzeIR is used to build up the IR representation. 401 template <typename T> class IRComparer { 402 public: IRComparer(const IRDataT<T> & Before,const IRDataT<T> & After)403 IRComparer(const IRDataT<T> &Before, const IRDataT<T> &After) 404 : Before(Before), After(After) {} 405 406 // Compare the 2 IRs. \p handleFunctionCompare is called to handle the 407 // compare of a function. When \p InModule is set, 408 // this function is being handled as part of comparing a module. 409 void compare( 410 bool CompareModule, 411 std::function<void(bool InModule, unsigned Minor, 412 const FuncDataT<T> &Before, const FuncDataT<T> &After)> 413 CompareFunc); 414 415 // Analyze \p IR and build the IR representation in \p Data. 416 static void analyzeIR(Any IR, IRDataT<T> &Data); 417 418 protected: 419 // Generate the data for \p F into \p Data. 420 template <typename FunctionT> 421 static bool generateFunctionData(IRDataT<T> &Data, const FunctionT &F); 422 423 const IRDataT<T> &Before; 424 const IRDataT<T> &After; 425 }; 426 427 // A change printer that prints out in-line differences in the basic 428 // blocks. It uses an InlineComparer to do the comparison so it shows 429 // the differences prefixed with '-' and '+' for code that is removed 430 // and added, respectively. Changes to the IR that do not affect basic 431 // blocks are not reported as having changed the IR. The option 432 // -print-module-scope does not affect this change reporter. 433 class InLineChangePrinter : public TextChangeReporter<IRDataT<EmptyData>> { 434 public: InLineChangePrinter(bool VerboseMode,bool ColourMode)435 InLineChangePrinter(bool VerboseMode, bool ColourMode) 436 : TextChangeReporter<IRDataT<EmptyData>>(VerboseMode), 437 UseColour(ColourMode) {} 438 ~InLineChangePrinter() override; 439 void registerCallbacks(PassInstrumentationCallbacks &PIC); 440 441 protected: 442 // Create a representation of the IR. 443 void generateIRRepresentation(Any IR, StringRef PassID, 444 IRDataT<EmptyData> &Output) override; 445 446 // Called when an interesting IR has changed. 447 void handleAfter(StringRef PassID, std::string &Name, 448 const IRDataT<EmptyData> &Before, 449 const IRDataT<EmptyData> &After, Any) override; 450 451 void handleFunctionCompare(StringRef Name, StringRef Prefix, StringRef PassID, 452 StringRef Divider, bool InModule, unsigned Minor, 453 const FuncDataT<EmptyData> &Before, 454 const FuncDataT<EmptyData> &After); 455 456 bool UseColour; 457 }; 458 459 class VerifyInstrumentation { 460 bool DebugLogging; 461 462 public: VerifyInstrumentation(bool DebugLogging)463 VerifyInstrumentation(bool DebugLogging) : DebugLogging(DebugLogging) {} 464 void registerCallbacks(PassInstrumentationCallbacks &PIC, 465 ModuleAnalysisManager *MAM); 466 }; 467 468 /// This class implements --time-trace functionality for new pass manager. 469 /// It provides the pass-instrumentation callbacks that measure the pass 470 /// execution time. They collect time tracing info by TimeProfiler. 471 class TimeProfilingPassesHandler { 472 public: 473 TimeProfilingPassesHandler(); 474 // We intend this to be unique per-compilation, thus no copies. 475 TimeProfilingPassesHandler(const TimeProfilingPassesHandler &) = delete; 476 void operator=(const TimeProfilingPassesHandler &) = delete; 477 478 void registerCallbacks(PassInstrumentationCallbacks &PIC); 479 480 private: 481 // Implementation of pass instrumentation callbacks. 482 void runBeforePass(StringRef PassID, Any IR); 483 void runAfterPass(); 484 }; 485 486 // Class that holds transitions between basic blocks. The transitions 487 // are contained in a map of values to names of basic blocks. 488 class DCData { 489 public: 490 // Fill the map with the transitions from basic block \p B. 491 DCData(const BasicBlock &B); 492 DCData(const MachineBasicBlock &B); 493 494 // Return an iterator to the names of the successor blocks. begin()495 StringMap<std::string>::const_iterator begin() const { 496 return Successors.begin(); 497 } end()498 StringMap<std::string>::const_iterator end() const { 499 return Successors.end(); 500 } 501 502 // Return the label of the basic block reached on a transition on \p S. getSuccessorLabel(StringRef S)503 StringRef getSuccessorLabel(StringRef S) const { 504 assert(Successors.count(S) == 1 && "Expected to find successor."); 505 return Successors.find(S)->getValue(); 506 } 507 508 protected: 509 // Add a transition to \p Succ on \p Label addSuccessorLabel(StringRef Succ,StringRef Label)510 void addSuccessorLabel(StringRef Succ, StringRef Label) { 511 std::pair<std::string, std::string> SS{Succ.str(), Label.str()}; 512 Successors.insert(SS); 513 } 514 515 StringMap<std::string> Successors; 516 }; 517 518 // A change reporter that builds a website with links to pdf files showing 519 // dot control flow graphs with changed instructions shown in colour. 520 class DotCfgChangeReporter : public ChangeReporter<IRDataT<DCData>> { 521 public: 522 DotCfgChangeReporter(bool Verbose); 523 ~DotCfgChangeReporter() override; 524 void registerCallbacks(PassInstrumentationCallbacks &PIC); 525 526 protected: 527 // Initialize the HTML file and output the header. 528 bool initializeHTML(); 529 530 // Called on the first IR processed. 531 void handleInitialIR(Any IR) override; 532 // Called before and after a pass to get the representation of the IR. 533 void generateIRRepresentation(Any IR, StringRef PassID, 534 IRDataT<DCData> &Output) override; 535 // Called when the pass is not iteresting. 536 void omitAfter(StringRef PassID, std::string &Name) override; 537 // Called when an interesting IR has changed. 538 void handleAfter(StringRef PassID, std::string &Name, 539 const IRDataT<DCData> &Before, const IRDataT<DCData> &After, 540 Any) override; 541 // Called when an interesting pass is invalidated. 542 void handleInvalidated(StringRef PassID) override; 543 // Called when the IR or pass is not interesting. 544 void handleFiltered(StringRef PassID, std::string &Name) override; 545 // Called when an ignored pass is encountered. 546 void handleIgnored(StringRef PassID, std::string &Name) override; 547 548 // Generate the pdf file into \p Dir / \p PDFFileName using \p DotFile as 549 // input and return the html <a> tag with \Text as the content. 550 static std::string genHTML(StringRef Text, StringRef DotFile, 551 StringRef PDFFileName); 552 553 void handleFunctionCompare(StringRef Name, StringRef Prefix, StringRef PassID, 554 StringRef Divider, bool InModule, unsigned Minor, 555 const FuncDataT<DCData> &Before, 556 const FuncDataT<DCData> &After); 557 558 unsigned N = 0; 559 std::unique_ptr<raw_fd_ostream> HTML; 560 }; 561 562 // Print IR on crash. 563 class PrintCrashIRInstrumentation { 564 public: PrintCrashIRInstrumentation()565 PrintCrashIRInstrumentation() 566 : SavedIR("*** Dump of IR Before Last Pass Unknown ***") {} 567 ~PrintCrashIRInstrumentation(); 568 void registerCallbacks(PassInstrumentationCallbacks &PIC); 569 void reportCrashIR(); 570 571 protected: 572 std::string SavedIR; 573 574 private: 575 // The crash reporter that will report on a crash. 576 static PrintCrashIRInstrumentation *CrashReporter; 577 // Crash handler registered when print-on-crash is specified. 578 static void SignalHandler(void *); 579 }; 580 581 /// This class provides an interface to register all the standard pass 582 /// instrumentations and manages their state (if any). 583 class StandardInstrumentations { 584 PrintIRInstrumentation PrintIR; 585 PrintPassInstrumentation PrintPass; 586 TimePassesHandler TimePasses; 587 TimeProfilingPassesHandler TimeProfilingPasses; 588 OptNoneInstrumentation OptNone; 589 OptPassGateInstrumentation OptPassGate; 590 PreservedCFGCheckerInstrumentation PreservedCFGChecker; 591 IRChangedPrinter PrintChangedIR; 592 PseudoProbeVerifier PseudoProbeVerification; 593 InLineChangePrinter PrintChangedDiff; 594 DotCfgChangeReporter WebsiteChangeReporter; 595 PrintCrashIRInstrumentation PrintCrashIR; 596 IRChangedTester ChangeTester; 597 VerifyInstrumentation Verify; 598 599 bool VerifyEach; 600 601 public: 602 StandardInstrumentations(LLVMContext &Context, bool DebugLogging, 603 bool VerifyEach = false, 604 PrintPassOptions PrintPassOpts = PrintPassOptions()); 605 606 // Register all the standard instrumentation callbacks. If \p FAM is nullptr 607 // then PreservedCFGChecker is not enabled. 608 void registerCallbacks(PassInstrumentationCallbacks &PIC, 609 ModuleAnalysisManager *MAM = nullptr); 610 getTimePasses()611 TimePassesHandler &getTimePasses() { return TimePasses; } 612 }; 613 614 extern template class ChangeReporter<std::string>; 615 extern template class TextChangeReporter<std::string>; 616 617 extern template class BlockDataT<EmptyData>; 618 extern template class FuncDataT<EmptyData>; 619 extern template class IRDataT<EmptyData>; 620 extern template class ChangeReporter<IRDataT<EmptyData>>; 621 extern template class TextChangeReporter<IRDataT<EmptyData>>; 622 extern template class IRComparer<EmptyData>; 623 624 } // namespace llvm 625 626 #endif 627