xref: /minix3/external/bsd/llvm/dist/llvm/tools/opt/Passes.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc //===- Passes.cpp - Parsing, selection, and running of passes -------------===//
2*0a6a1f1dSLionel Sambuc //
3*0a6a1f1dSLionel Sambuc //                     The LLVM Compiler Infrastructure
4*0a6a1f1dSLionel Sambuc //
5*0a6a1f1dSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6*0a6a1f1dSLionel Sambuc // License. See LICENSE.TXT for details.
7*0a6a1f1dSLionel Sambuc //
8*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
9*0a6a1f1dSLionel Sambuc /// \file
10*0a6a1f1dSLionel Sambuc ///
11*0a6a1f1dSLionel Sambuc /// This file provides the infrastructure to parse and build a custom pass
12*0a6a1f1dSLionel Sambuc /// manager based on a commandline flag. It also provides helpers to aid in
13*0a6a1f1dSLionel Sambuc /// analyzing, debugging, and testing pass structures.
14*0a6a1f1dSLionel Sambuc ///
15*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
16*0a6a1f1dSLionel Sambuc 
17*0a6a1f1dSLionel Sambuc #include "Passes.h"
18*0a6a1f1dSLionel Sambuc #include "llvm/Analysis/CGSCCPassManager.h"
19*0a6a1f1dSLionel Sambuc #include "llvm/Analysis/LazyCallGraph.h"
20*0a6a1f1dSLionel Sambuc #include "llvm/IR/Dominators.h"
21*0a6a1f1dSLionel Sambuc #include "llvm/IR/IRPrintingPasses.h"
22*0a6a1f1dSLionel Sambuc #include "llvm/IR/PassManager.h"
23*0a6a1f1dSLionel Sambuc #include "llvm/IR/Verifier.h"
24*0a6a1f1dSLionel Sambuc #include "llvm/Support/Debug.h"
25*0a6a1f1dSLionel Sambuc 
26*0a6a1f1dSLionel Sambuc using namespace llvm;
27*0a6a1f1dSLionel Sambuc 
28*0a6a1f1dSLionel Sambuc namespace {
29*0a6a1f1dSLionel Sambuc 
30*0a6a1f1dSLionel Sambuc /// \brief No-op module pass which does nothing.
31*0a6a1f1dSLionel Sambuc struct NoOpModulePass {
run__anonbd3c17ae0111::NoOpModulePass32*0a6a1f1dSLionel Sambuc   PreservedAnalyses run(Module &M) { return PreservedAnalyses::all(); }
name__anonbd3c17ae0111::NoOpModulePass33*0a6a1f1dSLionel Sambuc   static StringRef name() { return "NoOpModulePass"; }
34*0a6a1f1dSLionel Sambuc };
35*0a6a1f1dSLionel Sambuc 
36*0a6a1f1dSLionel Sambuc /// \brief No-op module analysis.
37*0a6a1f1dSLionel Sambuc struct NoOpModuleAnalysis {
38*0a6a1f1dSLionel Sambuc   struct Result {};
run__anonbd3c17ae0111::NoOpModuleAnalysis39*0a6a1f1dSLionel Sambuc   Result run(Module &) { return Result(); }
name__anonbd3c17ae0111::NoOpModuleAnalysis40*0a6a1f1dSLionel Sambuc   static StringRef name() { return "NoOpModuleAnalysis"; }
ID__anonbd3c17ae0111::NoOpModuleAnalysis41*0a6a1f1dSLionel Sambuc   static void *ID() { return (void *)&PassID; }
42*0a6a1f1dSLionel Sambuc private:
43*0a6a1f1dSLionel Sambuc   static char PassID;
44*0a6a1f1dSLionel Sambuc };
45*0a6a1f1dSLionel Sambuc 
46*0a6a1f1dSLionel Sambuc char NoOpModuleAnalysis::PassID;
47*0a6a1f1dSLionel Sambuc 
48*0a6a1f1dSLionel Sambuc /// \brief No-op CGSCC pass which does nothing.
49*0a6a1f1dSLionel Sambuc struct NoOpCGSCCPass {
run__anonbd3c17ae0111::NoOpCGSCCPass50*0a6a1f1dSLionel Sambuc   PreservedAnalyses run(LazyCallGraph::SCC &C) {
51*0a6a1f1dSLionel Sambuc     return PreservedAnalyses::all();
52*0a6a1f1dSLionel Sambuc   }
name__anonbd3c17ae0111::NoOpCGSCCPass53*0a6a1f1dSLionel Sambuc   static StringRef name() { return "NoOpCGSCCPass"; }
54*0a6a1f1dSLionel Sambuc };
55*0a6a1f1dSLionel Sambuc 
56*0a6a1f1dSLionel Sambuc /// \brief No-op CGSCC analysis.
57*0a6a1f1dSLionel Sambuc struct NoOpCGSCCAnalysis {
58*0a6a1f1dSLionel Sambuc   struct Result {};
run__anonbd3c17ae0111::NoOpCGSCCAnalysis59*0a6a1f1dSLionel Sambuc   Result run(LazyCallGraph::SCC &) { return Result(); }
name__anonbd3c17ae0111::NoOpCGSCCAnalysis60*0a6a1f1dSLionel Sambuc   static StringRef name() { return "NoOpCGSCCAnalysis"; }
ID__anonbd3c17ae0111::NoOpCGSCCAnalysis61*0a6a1f1dSLionel Sambuc   static void *ID() { return (void *)&PassID; }
62*0a6a1f1dSLionel Sambuc private:
63*0a6a1f1dSLionel Sambuc   static char PassID;
64*0a6a1f1dSLionel Sambuc };
65*0a6a1f1dSLionel Sambuc 
66*0a6a1f1dSLionel Sambuc char NoOpCGSCCAnalysis::PassID;
67*0a6a1f1dSLionel Sambuc 
68*0a6a1f1dSLionel Sambuc /// \brief No-op function pass which does nothing.
69*0a6a1f1dSLionel Sambuc struct NoOpFunctionPass {
run__anonbd3c17ae0111::NoOpFunctionPass70*0a6a1f1dSLionel Sambuc   PreservedAnalyses run(Function &F) { return PreservedAnalyses::all(); }
name__anonbd3c17ae0111::NoOpFunctionPass71*0a6a1f1dSLionel Sambuc   static StringRef name() { return "NoOpFunctionPass"; }
72*0a6a1f1dSLionel Sambuc };
73*0a6a1f1dSLionel Sambuc 
74*0a6a1f1dSLionel Sambuc /// \brief No-op function analysis.
75*0a6a1f1dSLionel Sambuc struct NoOpFunctionAnalysis {
76*0a6a1f1dSLionel Sambuc   struct Result {};
run__anonbd3c17ae0111::NoOpFunctionAnalysis77*0a6a1f1dSLionel Sambuc   Result run(Function &) { return Result(); }
name__anonbd3c17ae0111::NoOpFunctionAnalysis78*0a6a1f1dSLionel Sambuc   static StringRef name() { return "NoOpFunctionAnalysis"; }
ID__anonbd3c17ae0111::NoOpFunctionAnalysis79*0a6a1f1dSLionel Sambuc   static void *ID() { return (void *)&PassID; }
80*0a6a1f1dSLionel Sambuc private:
81*0a6a1f1dSLionel Sambuc   static char PassID;
82*0a6a1f1dSLionel Sambuc };
83*0a6a1f1dSLionel Sambuc 
84*0a6a1f1dSLionel Sambuc char NoOpFunctionAnalysis::PassID;
85*0a6a1f1dSLionel Sambuc 
86*0a6a1f1dSLionel Sambuc } // End anonymous namespace.
87*0a6a1f1dSLionel Sambuc 
registerModuleAnalyses(ModuleAnalysisManager & MAM)88*0a6a1f1dSLionel Sambuc void llvm::registerModuleAnalyses(ModuleAnalysisManager &MAM) {
89*0a6a1f1dSLionel Sambuc #define MODULE_ANALYSIS(NAME, CREATE_PASS) \
90*0a6a1f1dSLionel Sambuc   MAM.registerPass(CREATE_PASS);
91*0a6a1f1dSLionel Sambuc #include "PassRegistry.def"
92*0a6a1f1dSLionel Sambuc }
93*0a6a1f1dSLionel Sambuc 
registerCGSCCAnalyses(CGSCCAnalysisManager & CGAM)94*0a6a1f1dSLionel Sambuc void llvm::registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM) {
95*0a6a1f1dSLionel Sambuc #define CGSCC_ANALYSIS(NAME, CREATE_PASS) \
96*0a6a1f1dSLionel Sambuc   CGAM.registerPass(CREATE_PASS);
97*0a6a1f1dSLionel Sambuc #include "PassRegistry.def"
98*0a6a1f1dSLionel Sambuc }
99*0a6a1f1dSLionel Sambuc 
registerFunctionAnalyses(FunctionAnalysisManager & FAM)100*0a6a1f1dSLionel Sambuc void llvm::registerFunctionAnalyses(FunctionAnalysisManager &FAM) {
101*0a6a1f1dSLionel Sambuc #define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
102*0a6a1f1dSLionel Sambuc   FAM.registerPass(CREATE_PASS);
103*0a6a1f1dSLionel Sambuc #include "PassRegistry.def"
104*0a6a1f1dSLionel Sambuc }
105*0a6a1f1dSLionel Sambuc 
106*0a6a1f1dSLionel Sambuc #ifndef NDEBUG
isModulePassName(StringRef Name)107*0a6a1f1dSLionel Sambuc static bool isModulePassName(StringRef Name) {
108*0a6a1f1dSLionel Sambuc #define MODULE_PASS(NAME, CREATE_PASS) if (Name == NAME) return true;
109*0a6a1f1dSLionel Sambuc #define MODULE_ANALYSIS(NAME, CREATE_PASS)                                     \
110*0a6a1f1dSLionel Sambuc   if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">")           \
111*0a6a1f1dSLionel Sambuc     return true;
112*0a6a1f1dSLionel Sambuc #include "PassRegistry.def"
113*0a6a1f1dSLionel Sambuc 
114*0a6a1f1dSLionel Sambuc   return false;
115*0a6a1f1dSLionel Sambuc }
116*0a6a1f1dSLionel Sambuc #endif
117*0a6a1f1dSLionel Sambuc 
isCGSCCPassName(StringRef Name)118*0a6a1f1dSLionel Sambuc static bool isCGSCCPassName(StringRef Name) {
119*0a6a1f1dSLionel Sambuc #define CGSCC_PASS(NAME, CREATE_PASS) if (Name == NAME) return true;
120*0a6a1f1dSLionel Sambuc #define CGSCC_ANALYSIS(NAME, CREATE_PASS)                                      \
121*0a6a1f1dSLionel Sambuc   if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">")           \
122*0a6a1f1dSLionel Sambuc     return true;
123*0a6a1f1dSLionel Sambuc #include "PassRegistry.def"
124*0a6a1f1dSLionel Sambuc 
125*0a6a1f1dSLionel Sambuc   return false;
126*0a6a1f1dSLionel Sambuc }
127*0a6a1f1dSLionel Sambuc 
isFunctionPassName(StringRef Name)128*0a6a1f1dSLionel Sambuc static bool isFunctionPassName(StringRef Name) {
129*0a6a1f1dSLionel Sambuc #define FUNCTION_PASS(NAME, CREATE_PASS) if (Name == NAME) return true;
130*0a6a1f1dSLionel Sambuc #define FUNCTION_ANALYSIS(NAME, CREATE_PASS)                                   \
131*0a6a1f1dSLionel Sambuc   if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">")           \
132*0a6a1f1dSLionel Sambuc     return true;
133*0a6a1f1dSLionel Sambuc #include "PassRegistry.def"
134*0a6a1f1dSLionel Sambuc 
135*0a6a1f1dSLionel Sambuc   return false;
136*0a6a1f1dSLionel Sambuc }
137*0a6a1f1dSLionel Sambuc 
parseModulePassName(ModulePassManager & MPM,StringRef Name)138*0a6a1f1dSLionel Sambuc static bool parseModulePassName(ModulePassManager &MPM, StringRef Name) {
139*0a6a1f1dSLionel Sambuc #define MODULE_PASS(NAME, CREATE_PASS)                                         \
140*0a6a1f1dSLionel Sambuc   if (Name == NAME) {                                                          \
141*0a6a1f1dSLionel Sambuc     MPM.addPass(CREATE_PASS);                                                  \
142*0a6a1f1dSLionel Sambuc     return true;                                                               \
143*0a6a1f1dSLionel Sambuc   }
144*0a6a1f1dSLionel Sambuc #define MODULE_ANALYSIS(NAME, CREATE_PASS)                                     \
145*0a6a1f1dSLionel Sambuc   if (Name == "require<" NAME ">") {                                           \
146*0a6a1f1dSLionel Sambuc     MPM.addPass(RequireAnalysisPass<decltype(CREATE_PASS)>());                 \
147*0a6a1f1dSLionel Sambuc     return true;                                                               \
148*0a6a1f1dSLionel Sambuc   }                                                                            \
149*0a6a1f1dSLionel Sambuc   if (Name == "invalidate<" NAME ">") {                                        \
150*0a6a1f1dSLionel Sambuc     MPM.addPass(InvalidateAnalysisPass<decltype(CREATE_PASS)>());              \
151*0a6a1f1dSLionel Sambuc     return true;                                                               \
152*0a6a1f1dSLionel Sambuc   }
153*0a6a1f1dSLionel Sambuc #include "PassRegistry.def"
154*0a6a1f1dSLionel Sambuc 
155*0a6a1f1dSLionel Sambuc   return false;
156*0a6a1f1dSLionel Sambuc }
157*0a6a1f1dSLionel Sambuc 
parseCGSCCPassName(CGSCCPassManager & CGPM,StringRef Name)158*0a6a1f1dSLionel Sambuc static bool parseCGSCCPassName(CGSCCPassManager &CGPM, StringRef Name) {
159*0a6a1f1dSLionel Sambuc #define CGSCC_PASS(NAME, CREATE_PASS)                                          \
160*0a6a1f1dSLionel Sambuc   if (Name == NAME) {                                                          \
161*0a6a1f1dSLionel Sambuc     CGPM.addPass(CREATE_PASS);                                                 \
162*0a6a1f1dSLionel Sambuc     return true;                                                               \
163*0a6a1f1dSLionel Sambuc   }
164*0a6a1f1dSLionel Sambuc #define CGSCC_ANALYSIS(NAME, CREATE_PASS)                                      \
165*0a6a1f1dSLionel Sambuc   if (Name == "require<" NAME ">") {                                           \
166*0a6a1f1dSLionel Sambuc     CGPM.addPass(RequireAnalysisPass<decltype(CREATE_PASS)>());                \
167*0a6a1f1dSLionel Sambuc     return true;                                                               \
168*0a6a1f1dSLionel Sambuc   }                                                                            \
169*0a6a1f1dSLionel Sambuc   if (Name == "invalidate<" NAME ">") {                                        \
170*0a6a1f1dSLionel Sambuc     CGPM.addPass(InvalidateAnalysisPass<decltype(CREATE_PASS)>());             \
171*0a6a1f1dSLionel Sambuc     return true;                                                               \
172*0a6a1f1dSLionel Sambuc   }
173*0a6a1f1dSLionel Sambuc #include "PassRegistry.def"
174*0a6a1f1dSLionel Sambuc 
175*0a6a1f1dSLionel Sambuc   return false;
176*0a6a1f1dSLionel Sambuc }
177*0a6a1f1dSLionel Sambuc 
parseFunctionPassName(FunctionPassManager & FPM,StringRef Name)178*0a6a1f1dSLionel Sambuc static bool parseFunctionPassName(FunctionPassManager &FPM, StringRef Name) {
179*0a6a1f1dSLionel Sambuc #define FUNCTION_PASS(NAME, CREATE_PASS)                                       \
180*0a6a1f1dSLionel Sambuc   if (Name == NAME) {                                                          \
181*0a6a1f1dSLionel Sambuc     FPM.addPass(CREATE_PASS);                                                  \
182*0a6a1f1dSLionel Sambuc     return true;                                                               \
183*0a6a1f1dSLionel Sambuc   }
184*0a6a1f1dSLionel Sambuc #define FUNCTION_ANALYSIS(NAME, CREATE_PASS)                                   \
185*0a6a1f1dSLionel Sambuc   if (Name == "require<" NAME ">") {                                           \
186*0a6a1f1dSLionel Sambuc     FPM.addPass(RequireAnalysisPass<decltype(CREATE_PASS)>());                 \
187*0a6a1f1dSLionel Sambuc     return true;                                                               \
188*0a6a1f1dSLionel Sambuc   }                                                                            \
189*0a6a1f1dSLionel Sambuc   if (Name == "invalidate<" NAME ">") {                                        \
190*0a6a1f1dSLionel Sambuc     FPM.addPass(InvalidateAnalysisPass<decltype(CREATE_PASS)>());              \
191*0a6a1f1dSLionel Sambuc     return true;                                                               \
192*0a6a1f1dSLionel Sambuc   }
193*0a6a1f1dSLionel Sambuc #include "PassRegistry.def"
194*0a6a1f1dSLionel Sambuc 
195*0a6a1f1dSLionel Sambuc   return false;
196*0a6a1f1dSLionel Sambuc }
197*0a6a1f1dSLionel Sambuc 
parseFunctionPassPipeline(FunctionPassManager & FPM,StringRef & PipelineText,bool VerifyEachPass,bool DebugLogging)198*0a6a1f1dSLionel Sambuc static bool parseFunctionPassPipeline(FunctionPassManager &FPM,
199*0a6a1f1dSLionel Sambuc                                       StringRef &PipelineText,
200*0a6a1f1dSLionel Sambuc                                       bool VerifyEachPass, bool DebugLogging) {
201*0a6a1f1dSLionel Sambuc   for (;;) {
202*0a6a1f1dSLionel Sambuc     // Parse nested pass managers by recursing.
203*0a6a1f1dSLionel Sambuc     if (PipelineText.startswith("function(")) {
204*0a6a1f1dSLionel Sambuc       FunctionPassManager NestedFPM(DebugLogging);
205*0a6a1f1dSLionel Sambuc 
206*0a6a1f1dSLionel Sambuc       // Parse the inner pipeline inte the nested manager.
207*0a6a1f1dSLionel Sambuc       PipelineText = PipelineText.substr(strlen("function("));
208*0a6a1f1dSLionel Sambuc       if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass,
209*0a6a1f1dSLionel Sambuc                                      DebugLogging) ||
210*0a6a1f1dSLionel Sambuc           PipelineText.empty())
211*0a6a1f1dSLionel Sambuc         return false;
212*0a6a1f1dSLionel Sambuc       assert(PipelineText[0] == ')');
213*0a6a1f1dSLionel Sambuc       PipelineText = PipelineText.substr(1);
214*0a6a1f1dSLionel Sambuc 
215*0a6a1f1dSLionel Sambuc       // Add the nested pass manager with the appropriate adaptor.
216*0a6a1f1dSLionel Sambuc       FPM.addPass(std::move(NestedFPM));
217*0a6a1f1dSLionel Sambuc     } else {
218*0a6a1f1dSLionel Sambuc       // Otherwise try to parse a pass name.
219*0a6a1f1dSLionel Sambuc       size_t End = PipelineText.find_first_of(",)");
220*0a6a1f1dSLionel Sambuc       if (!parseFunctionPassName(FPM, PipelineText.substr(0, End)))
221*0a6a1f1dSLionel Sambuc         return false;
222*0a6a1f1dSLionel Sambuc       if (VerifyEachPass)
223*0a6a1f1dSLionel Sambuc         FPM.addPass(VerifierPass());
224*0a6a1f1dSLionel Sambuc 
225*0a6a1f1dSLionel Sambuc       PipelineText = PipelineText.substr(End);
226*0a6a1f1dSLionel Sambuc     }
227*0a6a1f1dSLionel Sambuc 
228*0a6a1f1dSLionel Sambuc     if (PipelineText.empty() || PipelineText[0] == ')')
229*0a6a1f1dSLionel Sambuc       return true;
230*0a6a1f1dSLionel Sambuc 
231*0a6a1f1dSLionel Sambuc     assert(PipelineText[0] == ',');
232*0a6a1f1dSLionel Sambuc     PipelineText = PipelineText.substr(1);
233*0a6a1f1dSLionel Sambuc   }
234*0a6a1f1dSLionel Sambuc }
235*0a6a1f1dSLionel Sambuc 
parseCGSCCPassPipeline(CGSCCPassManager & CGPM,StringRef & PipelineText,bool VerifyEachPass,bool DebugLogging)236*0a6a1f1dSLionel Sambuc static bool parseCGSCCPassPipeline(CGSCCPassManager &CGPM,
237*0a6a1f1dSLionel Sambuc                                    StringRef &PipelineText, bool VerifyEachPass,
238*0a6a1f1dSLionel Sambuc                                    bool DebugLogging) {
239*0a6a1f1dSLionel Sambuc   for (;;) {
240*0a6a1f1dSLionel Sambuc     // Parse nested pass managers by recursing.
241*0a6a1f1dSLionel Sambuc     if (PipelineText.startswith("cgscc(")) {
242*0a6a1f1dSLionel Sambuc       CGSCCPassManager NestedCGPM(DebugLogging);
243*0a6a1f1dSLionel Sambuc 
244*0a6a1f1dSLionel Sambuc       // Parse the inner pipeline into the nested manager.
245*0a6a1f1dSLionel Sambuc       PipelineText = PipelineText.substr(strlen("cgscc("));
246*0a6a1f1dSLionel Sambuc       if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass,
247*0a6a1f1dSLionel Sambuc                                   DebugLogging) ||
248*0a6a1f1dSLionel Sambuc           PipelineText.empty())
249*0a6a1f1dSLionel Sambuc         return false;
250*0a6a1f1dSLionel Sambuc       assert(PipelineText[0] == ')');
251*0a6a1f1dSLionel Sambuc       PipelineText = PipelineText.substr(1);
252*0a6a1f1dSLionel Sambuc 
253*0a6a1f1dSLionel Sambuc       // Add the nested pass manager with the appropriate adaptor.
254*0a6a1f1dSLionel Sambuc       CGPM.addPass(std::move(NestedCGPM));
255*0a6a1f1dSLionel Sambuc     } else if (PipelineText.startswith("function(")) {
256*0a6a1f1dSLionel Sambuc       FunctionPassManager NestedFPM(DebugLogging);
257*0a6a1f1dSLionel Sambuc 
258*0a6a1f1dSLionel Sambuc       // Parse the inner pipeline inte the nested manager.
259*0a6a1f1dSLionel Sambuc       PipelineText = PipelineText.substr(strlen("function("));
260*0a6a1f1dSLionel Sambuc       if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass,
261*0a6a1f1dSLionel Sambuc                                      DebugLogging) ||
262*0a6a1f1dSLionel Sambuc           PipelineText.empty())
263*0a6a1f1dSLionel Sambuc         return false;
264*0a6a1f1dSLionel Sambuc       assert(PipelineText[0] == ')');
265*0a6a1f1dSLionel Sambuc       PipelineText = PipelineText.substr(1);
266*0a6a1f1dSLionel Sambuc 
267*0a6a1f1dSLionel Sambuc       // Add the nested pass manager with the appropriate adaptor.
268*0a6a1f1dSLionel Sambuc       CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(NestedFPM)));
269*0a6a1f1dSLionel Sambuc     } else {
270*0a6a1f1dSLionel Sambuc       // Otherwise try to parse a pass name.
271*0a6a1f1dSLionel Sambuc       size_t End = PipelineText.find_first_of(",)");
272*0a6a1f1dSLionel Sambuc       if (!parseCGSCCPassName(CGPM, PipelineText.substr(0, End)))
273*0a6a1f1dSLionel Sambuc         return false;
274*0a6a1f1dSLionel Sambuc       // FIXME: No verifier support for CGSCC passes!
275*0a6a1f1dSLionel Sambuc 
276*0a6a1f1dSLionel Sambuc       PipelineText = PipelineText.substr(End);
277*0a6a1f1dSLionel Sambuc     }
278*0a6a1f1dSLionel Sambuc 
279*0a6a1f1dSLionel Sambuc     if (PipelineText.empty() || PipelineText[0] == ')')
280*0a6a1f1dSLionel Sambuc       return true;
281*0a6a1f1dSLionel Sambuc 
282*0a6a1f1dSLionel Sambuc     assert(PipelineText[0] == ',');
283*0a6a1f1dSLionel Sambuc     PipelineText = PipelineText.substr(1);
284*0a6a1f1dSLionel Sambuc   }
285*0a6a1f1dSLionel Sambuc }
286*0a6a1f1dSLionel Sambuc 
parseModulePassPipeline(ModulePassManager & MPM,StringRef & PipelineText,bool VerifyEachPass,bool DebugLogging)287*0a6a1f1dSLionel Sambuc static bool parseModulePassPipeline(ModulePassManager &MPM,
288*0a6a1f1dSLionel Sambuc                                     StringRef &PipelineText,
289*0a6a1f1dSLionel Sambuc                                     bool VerifyEachPass, bool DebugLogging) {
290*0a6a1f1dSLionel Sambuc   for (;;) {
291*0a6a1f1dSLionel Sambuc     // Parse nested pass managers by recursing.
292*0a6a1f1dSLionel Sambuc     if (PipelineText.startswith("module(")) {
293*0a6a1f1dSLionel Sambuc       ModulePassManager NestedMPM(DebugLogging);
294*0a6a1f1dSLionel Sambuc 
295*0a6a1f1dSLionel Sambuc       // Parse the inner pipeline into the nested manager.
296*0a6a1f1dSLionel Sambuc       PipelineText = PipelineText.substr(strlen("module("));
297*0a6a1f1dSLionel Sambuc       if (!parseModulePassPipeline(NestedMPM, PipelineText, VerifyEachPass,
298*0a6a1f1dSLionel Sambuc                                    DebugLogging) ||
299*0a6a1f1dSLionel Sambuc           PipelineText.empty())
300*0a6a1f1dSLionel Sambuc         return false;
301*0a6a1f1dSLionel Sambuc       assert(PipelineText[0] == ')');
302*0a6a1f1dSLionel Sambuc       PipelineText = PipelineText.substr(1);
303*0a6a1f1dSLionel Sambuc 
304*0a6a1f1dSLionel Sambuc       // Now add the nested manager as a module pass.
305*0a6a1f1dSLionel Sambuc       MPM.addPass(std::move(NestedMPM));
306*0a6a1f1dSLionel Sambuc     } else if (PipelineText.startswith("cgscc(")) {
307*0a6a1f1dSLionel Sambuc       CGSCCPassManager NestedCGPM(DebugLogging);
308*0a6a1f1dSLionel Sambuc 
309*0a6a1f1dSLionel Sambuc       // Parse the inner pipeline inte the nested manager.
310*0a6a1f1dSLionel Sambuc       PipelineText = PipelineText.substr(strlen("cgscc("));
311*0a6a1f1dSLionel Sambuc       if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass,
312*0a6a1f1dSLionel Sambuc                                   DebugLogging) ||
313*0a6a1f1dSLionel Sambuc           PipelineText.empty())
314*0a6a1f1dSLionel Sambuc         return false;
315*0a6a1f1dSLionel Sambuc       assert(PipelineText[0] == ')');
316*0a6a1f1dSLionel Sambuc       PipelineText = PipelineText.substr(1);
317*0a6a1f1dSLionel Sambuc 
318*0a6a1f1dSLionel Sambuc       // Add the nested pass manager with the appropriate adaptor.
319*0a6a1f1dSLionel Sambuc       MPM.addPass(
320*0a6a1f1dSLionel Sambuc           createModuleToPostOrderCGSCCPassAdaptor(std::move(NestedCGPM)));
321*0a6a1f1dSLionel Sambuc     } else if (PipelineText.startswith("function(")) {
322*0a6a1f1dSLionel Sambuc       FunctionPassManager NestedFPM(DebugLogging);
323*0a6a1f1dSLionel Sambuc 
324*0a6a1f1dSLionel Sambuc       // Parse the inner pipeline inte the nested manager.
325*0a6a1f1dSLionel Sambuc       PipelineText = PipelineText.substr(strlen("function("));
326*0a6a1f1dSLionel Sambuc       if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass,
327*0a6a1f1dSLionel Sambuc                                      DebugLogging) ||
328*0a6a1f1dSLionel Sambuc           PipelineText.empty())
329*0a6a1f1dSLionel Sambuc         return false;
330*0a6a1f1dSLionel Sambuc       assert(PipelineText[0] == ')');
331*0a6a1f1dSLionel Sambuc       PipelineText = PipelineText.substr(1);
332*0a6a1f1dSLionel Sambuc 
333*0a6a1f1dSLionel Sambuc       // Add the nested pass manager with the appropriate adaptor.
334*0a6a1f1dSLionel Sambuc       MPM.addPass(createModuleToFunctionPassAdaptor(std::move(NestedFPM)));
335*0a6a1f1dSLionel Sambuc     } else {
336*0a6a1f1dSLionel Sambuc       // Otherwise try to parse a pass name.
337*0a6a1f1dSLionel Sambuc       size_t End = PipelineText.find_first_of(",)");
338*0a6a1f1dSLionel Sambuc       if (!parseModulePassName(MPM, PipelineText.substr(0, End)))
339*0a6a1f1dSLionel Sambuc         return false;
340*0a6a1f1dSLionel Sambuc       if (VerifyEachPass)
341*0a6a1f1dSLionel Sambuc         MPM.addPass(VerifierPass());
342*0a6a1f1dSLionel Sambuc 
343*0a6a1f1dSLionel Sambuc       PipelineText = PipelineText.substr(End);
344*0a6a1f1dSLionel Sambuc     }
345*0a6a1f1dSLionel Sambuc 
346*0a6a1f1dSLionel Sambuc     if (PipelineText.empty() || PipelineText[0] == ')')
347*0a6a1f1dSLionel Sambuc       return true;
348*0a6a1f1dSLionel Sambuc 
349*0a6a1f1dSLionel Sambuc     assert(PipelineText[0] == ',');
350*0a6a1f1dSLionel Sambuc     PipelineText = PipelineText.substr(1);
351*0a6a1f1dSLionel Sambuc   }
352*0a6a1f1dSLionel Sambuc }
353*0a6a1f1dSLionel Sambuc 
354*0a6a1f1dSLionel Sambuc // Primary pass pipeline description parsing routine.
355*0a6a1f1dSLionel Sambuc // FIXME: Should this routine accept a TargetMachine or require the caller to
356*0a6a1f1dSLionel Sambuc // pre-populate the analysis managers with target-specific stuff?
parsePassPipeline(ModulePassManager & MPM,StringRef PipelineText,bool VerifyEachPass,bool DebugLogging)357*0a6a1f1dSLionel Sambuc bool llvm::parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText,
358*0a6a1f1dSLionel Sambuc                              bool VerifyEachPass, bool DebugLogging) {
359*0a6a1f1dSLionel Sambuc   // By default, try to parse the pipeline as-if it were within an implicit
360*0a6a1f1dSLionel Sambuc   // 'module(...)' pass pipeline. If this will parse at all, it needs to
361*0a6a1f1dSLionel Sambuc   // consume the entire string.
362*0a6a1f1dSLionel Sambuc   if (parseModulePassPipeline(MPM, PipelineText, VerifyEachPass, DebugLogging))
363*0a6a1f1dSLionel Sambuc     return PipelineText.empty();
364*0a6a1f1dSLionel Sambuc 
365*0a6a1f1dSLionel Sambuc   // This isn't parsable as a module pipeline, look for the end of a pass name
366*0a6a1f1dSLionel Sambuc   // and directly drop down to that layer.
367*0a6a1f1dSLionel Sambuc   StringRef FirstName =
368*0a6a1f1dSLionel Sambuc       PipelineText.substr(0, PipelineText.find_first_of(",)"));
369*0a6a1f1dSLionel Sambuc   assert(!isModulePassName(FirstName) &&
370*0a6a1f1dSLionel Sambuc          "Already handled all module pipeline options.");
371*0a6a1f1dSLionel Sambuc 
372*0a6a1f1dSLionel Sambuc   // If this looks like a CGSCC pass, parse the whole thing as a CGSCC
373*0a6a1f1dSLionel Sambuc   // pipeline.
374*0a6a1f1dSLionel Sambuc   if (isCGSCCPassName(FirstName)) {
375*0a6a1f1dSLionel Sambuc     CGSCCPassManager CGPM(DebugLogging);
376*0a6a1f1dSLionel Sambuc     if (!parseCGSCCPassPipeline(CGPM, PipelineText, VerifyEachPass,
377*0a6a1f1dSLionel Sambuc                                 DebugLogging) ||
378*0a6a1f1dSLionel Sambuc         !PipelineText.empty())
379*0a6a1f1dSLionel Sambuc       return false;
380*0a6a1f1dSLionel Sambuc     MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
381*0a6a1f1dSLionel Sambuc     return true;
382*0a6a1f1dSLionel Sambuc   }
383*0a6a1f1dSLionel Sambuc 
384*0a6a1f1dSLionel Sambuc   // Similarly, if this looks like a Function pass, parse the whole thing as
385*0a6a1f1dSLionel Sambuc   // a Function pipelien.
386*0a6a1f1dSLionel Sambuc   if (isFunctionPassName(FirstName)) {
387*0a6a1f1dSLionel Sambuc     FunctionPassManager FPM(DebugLogging);
388*0a6a1f1dSLionel Sambuc     if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass,
389*0a6a1f1dSLionel Sambuc                                    DebugLogging) ||
390*0a6a1f1dSLionel Sambuc         !PipelineText.empty())
391*0a6a1f1dSLionel Sambuc       return false;
392*0a6a1f1dSLionel Sambuc     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
393*0a6a1f1dSLionel Sambuc     return true;
394*0a6a1f1dSLionel Sambuc   }
395*0a6a1f1dSLionel Sambuc 
396*0a6a1f1dSLionel Sambuc   return false;
397*0a6a1f1dSLionel Sambuc }
398