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