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