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