1 //===- Standard pass instrumentations handling ----------------*- C++ -*--===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 ///
11 /// This file defines IR-printing pass instrumentation callbacks as well as
12 /// StandardInstrumentations class that manages standard pass instrumentations.
13 ///
14 //===----------------------------------------------------------------------===//
15 
16 #include "llvm/Passes/StandardInstrumentations.h"
17 #include "llvm/Analysis/CallGraphSCCPass.h"
18 #include "llvm/Analysis/LazyCallGraph.h"
19 #include "llvm/Analysis/LoopInfo.h"
20 #include "llvm/IR/Function.h"
21 #include "llvm/IR/IRPrintingPasses.h"
22 #include "llvm/IR/Module.h"
23 #include "llvm/IR/PassInstrumentation.h"
24 #include "llvm/Support/Debug.h"
25 #include "llvm/Support/FormatVariadic.h"
26 #include "llvm/Support/raw_ostream.h"
27 
28 using namespace llvm;
29 
30 namespace {
31 namespace PrintIR {
32 
33 //===----------------------------------------------------------------------===//
34 // IR-printing instrumentation
35 //===----------------------------------------------------------------------===//
36 
37 /// Generic IR-printing helper that unpacks a pointer to IRUnit wrapped into
38 /// llvm::Any and does actual print job.
39 void unwrapAndPrint(StringRef Banner, Any IR) {
40   SmallString<40> Extra{"\n"};
41   const Module *M = nullptr;
42   if (any_isa<const Module *>(IR)) {
43     M = any_cast<const Module *>(IR);
44   } else if (any_isa<const Function *>(IR)) {
45     const Function *F = any_cast<const Function *>(IR);
46     if (!llvm::isFunctionInPrintList(F->getName()))
47       return;
48     if (!llvm::forcePrintModuleIR()) {
49       dbgs() << Banner << Extra << static_cast<const Value &>(*F);
50       return;
51     }
52     M = F->getParent();
53     Extra = formatv(" (function: {0})\n", F->getName());
54   } else if (any_isa<const LazyCallGraph::SCC *>(IR)) {
55     const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR);
56     if (!llvm::forcePrintModuleIR()) {
57       Extra = formatv(" (scc: {0})\n", C->getName());
58       bool BannerPrinted = false;
59       for (const LazyCallGraph::Node &N : *C) {
60         const Function &F = N.getFunction();
61         if (!F.isDeclaration() && isFunctionInPrintList(F.getName())) {
62           if (!BannerPrinted) {
63             dbgs() << Banner << Extra;
64             BannerPrinted = true;
65           }
66           F.print(dbgs());
67         }
68       }
69       return;
70     }
71     for (const LazyCallGraph::Node &N : *C) {
72       const Function &F = N.getFunction();
73       if (!F.isDeclaration() && isFunctionInPrintList(F.getName())) {
74         M = F.getParent();
75         break;
76       }
77     }
78     if (!M)
79       return;
80     Extra = formatv(" (for scc: {0})\n", C->getName());
81   } else if (any_isa<const Loop *>(IR)) {
82     const Loop *L = any_cast<const Loop *>(IR);
83     const Function *F = L->getHeader()->getParent();
84     if (!isFunctionInPrintList(F->getName()))
85       return;
86     if (!llvm::forcePrintModuleIR()) {
87       llvm::printLoop(const_cast<Loop &>(*L), dbgs(), Banner);
88       return;
89     }
90     M = F->getParent();
91     {
92       std::string LoopName;
93       raw_string_ostream ss(LoopName);
94       L->getHeader()->printAsOperand(ss, false);
95       Extra = formatv(" (loop: {0})\n", ss.str());
96     }
97   }
98   if (M) {
99     dbgs() << Banner << Extra;
100     M->print(dbgs(), nullptr, false);
101   } else {
102     llvm_unreachable("Unknown wrapped IR type");
103   }
104 }
105 
106 bool printBeforePass(StringRef PassID, Any IR) {
107   if (!llvm::shouldPrintBeforePass(PassID))
108     return true;
109 
110   if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<"))
111     return true;
112 
113   SmallString<20> Banner = formatv("*** IR Dump Before {0} ***", PassID);
114   unwrapAndPrint(Banner, IR);
115   return true;
116 }
117 
118 void printAfterPass(StringRef PassID, Any IR) {
119   if (!llvm::shouldPrintAfterPass(PassID))
120     return;
121 
122   if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<"))
123     return;
124 
125   SmallString<20> Banner = formatv("*** IR Dump After {0} ***", PassID);
126   unwrapAndPrint(Banner, IR);
127   return;
128 }
129 } // namespace PrintIR
130 } // namespace
131 
132 void StandardInstrumentations::registerCallbacks(
133     PassInstrumentationCallbacks &PIC) {
134   if (llvm::shouldPrintBeforePass())
135     PIC.registerBeforePassCallback(PrintIR::printBeforePass);
136   if (llvm::shouldPrintAfterPass())
137     PIC.registerAfterPassCallback(PrintIR::printAfterPass);
138   TimePasses.registerCallbacks(PIC);
139 }
140