1 | //===--- IRPrintingPasses.cpp - Module and Function printing passes -------===// |
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 | // PrintModulePass and PrintFunctionPass implementations for the legacy pass |
10 | // manager. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "llvm/IR/IRPrintingPasses.h" |
15 | #include "llvm/ADT/StringRef.h" |
16 | #include "llvm/IR/Function.h" |
17 | #include "llvm/IR/Module.h" |
18 | #include "llvm/IR/PrintPasses.h" |
19 | #include "llvm/InitializePasses.h" |
20 | #include "llvm/Pass.h" |
21 | #include "llvm/Support/Debug.h" |
22 | #include "llvm/Support/raw_ostream.h" |
23 | |
24 | using namespace llvm; |
25 | |
26 | cl::opt<bool> WriteNewDbgInfoFormat( |
27 | "write-experimental-debuginfo" , |
28 | cl::desc("Write debug info in the new non-intrinsic format. Has no effect " |
29 | "if --preserve-input-debuginfo-format=true." ), |
30 | cl::init(Val: true)); |
31 | |
32 | namespace { |
33 | |
34 | class PrintModulePassWrapper : public ModulePass { |
35 | raw_ostream &OS; |
36 | std::string Banner; |
37 | bool ShouldPreserveUseListOrder; |
38 | |
39 | public: |
40 | static char ID; |
41 | PrintModulePassWrapper() : ModulePass(ID), OS(dbgs()) {} |
42 | PrintModulePassWrapper(raw_ostream &OS, const std::string &Banner, |
43 | bool ShouldPreserveUseListOrder) |
44 | : ModulePass(ID), OS(OS), Banner(Banner), |
45 | ShouldPreserveUseListOrder(ShouldPreserveUseListOrder) {} |
46 | |
47 | bool runOnModule(Module &M) override { |
48 | // RemoveDIs: Regardless of the format we've processed this module in, use |
49 | // `WriteNewDbgInfoFormat` to determine which format we use to write it. |
50 | ScopedDbgInfoFormatSetter FormatSetter(M, WriteNewDbgInfoFormat); |
51 | // Remove intrinsic declarations when printing in the new format. |
52 | // TODO: Move this into Module::setIsNewDbgInfoFormat when we're ready to |
53 | // update test output. |
54 | if (WriteNewDbgInfoFormat) |
55 | M.removeDebugIntrinsicDeclarations(); |
56 | |
57 | if (llvm::isFunctionInPrintList(FunctionName: "*" )) { |
58 | if (!Banner.empty()) |
59 | OS << Banner << "\n" ; |
60 | M.print(OS, AAW: nullptr, ShouldPreserveUseListOrder); |
61 | } else { |
62 | bool BannerPrinted = false; |
63 | for (const auto &F : M.functions()) { |
64 | if (llvm::isFunctionInPrintList(FunctionName: F.getName())) { |
65 | if (!BannerPrinted && !Banner.empty()) { |
66 | OS << Banner << "\n" ; |
67 | BannerPrinted = true; |
68 | } |
69 | F.print(OS); |
70 | } |
71 | } |
72 | } |
73 | |
74 | return false; |
75 | } |
76 | |
77 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
78 | AU.setPreservesAll(); |
79 | } |
80 | |
81 | StringRef getPassName() const override { return "Print Module IR" ; } |
82 | }; |
83 | |
84 | class PrintFunctionPassWrapper : public FunctionPass { |
85 | raw_ostream &OS; |
86 | std::string Banner; |
87 | |
88 | public: |
89 | static char ID; |
90 | PrintFunctionPassWrapper() : FunctionPass(ID), OS(dbgs()) {} |
91 | PrintFunctionPassWrapper(raw_ostream &OS, const std::string &Banner) |
92 | : FunctionPass(ID), OS(OS), Banner(Banner) {} |
93 | |
94 | // This pass just prints a banner followed by the function as it's processed. |
95 | bool runOnFunction(Function &F) override { |
96 | // RemoveDIs: Regardless of the format we've processed this function in, use |
97 | // `WriteNewDbgInfoFormat` to determine which format we use to write it. |
98 | ScopedDbgInfoFormatSetter FormatSetter(F, WriteNewDbgInfoFormat); |
99 | |
100 | if (isFunctionInPrintList(FunctionName: F.getName())) { |
101 | if (forcePrintModuleIR()) |
102 | OS << Banner << " (function: " << F.getName() << ")\n" |
103 | << *F.getParent(); |
104 | else |
105 | OS << Banner << '\n' << static_cast<Value &>(F); |
106 | } |
107 | |
108 | return false; |
109 | } |
110 | |
111 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
112 | AU.setPreservesAll(); |
113 | } |
114 | |
115 | StringRef getPassName() const override { return "Print Function IR" ; } |
116 | }; |
117 | |
118 | } // namespace |
119 | |
120 | char PrintModulePassWrapper::ID = 0; |
121 | INITIALIZE_PASS(PrintModulePassWrapper, "print-module" , |
122 | "Print module to stderr" , false, true) |
123 | char PrintFunctionPassWrapper::ID = 0; |
124 | INITIALIZE_PASS(PrintFunctionPassWrapper, "print-function" , |
125 | "Print function to stderr" , false, true) |
126 | |
127 | ModulePass *llvm::createPrintModulePass(llvm::raw_ostream &OS, |
128 | const std::string &Banner, |
129 | bool ShouldPreserveUseListOrder) { |
130 | return new PrintModulePassWrapper(OS, Banner, ShouldPreserveUseListOrder); |
131 | } |
132 | |
133 | FunctionPass *llvm::createPrintFunctionPass(llvm::raw_ostream &OS, |
134 | const std::string &Banner) { |
135 | return new PrintFunctionPassWrapper(OS, Banner); |
136 | } |
137 | |
138 | bool llvm::isIRPrintingPass(Pass *P) { |
139 | const char *PID = (const char *)P->getPassID(); |
140 | |
141 | return (PID == &PrintModulePassWrapper::ID) || |
142 | (PID == &PrintFunctionPassWrapper::ID); |
143 | } |
144 | |