File tree Expand file tree Collapse file tree 3 files changed +67
-0
lines changed Expand file tree Collapse file tree 3 files changed +67
-0
lines changed Original file line number Diff line number Diff line change @@ -72,6 +72,7 @@ class PassRegistry {
7272 DenseMap<StringRef, Pass *> NameToPassMap;
7373
7474public:
75+ static constexpr const char PassDelimToken = ' ,' ;
7576 PassRegistry () = default ;
7677 // / Registers \p PassPtr and takes ownership.
7778 Pass ®isterPass (std::unique_ptr<Pass> &&PassPtr) {
@@ -85,6 +86,9 @@ class PassRegistry {
8586 auto It = NameToPassMap.find (Name);
8687 return It != NameToPassMap.end () ? It->second : nullptr ;
8788 }
89+ // / Creates a pass pipeline and returns the first pass manager.
90+ FunctionPassManager &parseAndCreatePassPipeline (StringRef Pipeline);
91+
8892#ifndef NDEBUG
8993 void print (raw_ostream &OS) const {
9094 for (const auto &PassPtr : Passes)
Original file line number Diff line number Diff line change @@ -20,6 +20,38 @@ bool FunctionPassManager::runOnFunction(Function &F) {
2020 // TODO: Check ChangeAll against hashes before/after.
2121 return Change;
2222}
23+
24+ FunctionPassManager &
25+ PassRegistry::parseAndCreatePassPipeline (StringRef Pipeline) {
26+ static constexpr const char EndToken = ' \0 ' ;
27+ // Add EndToken to the end to ease parsing.
28+ std::string PipelineStr = std::string (Pipeline) + EndToken;
29+ int FlagBeginIdx = 0 ;
30+ // Start with a FunctionPassManager.
31+ auto &InitialPM = static_cast <FunctionPassManager &>(
32+ registerPass (std::make_unique<FunctionPassManager>(" init-fpm" )));
33+
34+ for (auto [Idx, C] : enumerate(PipelineStr)) {
35+ // Keep moving Idx until we find the end of the pass name.
36+ bool FoundDelim = C == EndToken || C == PassDelimToken;
37+ if (!FoundDelim)
38+ continue ;
39+ unsigned Sz = Idx - FlagBeginIdx;
40+ std::string PassName (&PipelineStr[FlagBeginIdx], Sz);
41+ FlagBeginIdx = Idx + 1 ;
42+
43+ // Get the pass that corresponds to PassName and add it to the pass manager.
44+ auto *Pass = getPassByName (PassName);
45+ if (Pass == nullptr ) {
46+ errs () << " Pass '" << PassName << " ' not registered!\n " ;
47+ exit (1 );
48+ }
49+ // TODO: This is safe for now, but would require proper upcasting once we
50+ // add more Pass sub-classes.
51+ InitialPM.addPass (static_cast <FunctionPass *>(Pass));
52+ }
53+ return InitialPM;
54+ }
2355#ifndef NDEBUG
2456void PassRegistry::dump () const {
2557 print (dbgs ());
Original file line number Diff line number Diff line change @@ -162,3 +162,34 @@ TEST_F(PassTest, PassRegistry) {
162162 EXPECT_EQ (Buff, " test-pass1\n test-pass2\n " );
163163#endif // NDEBUG
164164}
165+
166+ TEST_F (PassTest, ParsePassPipeline) {
167+ class TestPass1 final : public FunctionPass {
168+ public:
169+ TestPass1 () : FunctionPass(" test-pass1" ) {}
170+ bool runOnFunction (Function &F) final { return false ; }
171+ };
172+ class TestPass2 final : public FunctionPass {
173+ public:
174+ TestPass2 () : FunctionPass(" test-pass2" ) {}
175+ bool runOnFunction (Function &F) final { return false ; }
176+ };
177+
178+ PassRegistry Registry;
179+ Registry.registerPass (std::make_unique<TestPass1>());
180+ Registry.registerPass (std::make_unique<TestPass2>());
181+
182+ auto &FPM =
183+ Registry.parseAndCreatePassPipeline (" test-pass1,test-pass2,test-pass1" );
184+ #ifndef NDEBUG
185+ std::string Buff;
186+ llvm::raw_string_ostream SS (Buff);
187+ FPM.print (SS);
188+ EXPECT_EQ (Buff, " init-fpm(test-pass1,test-pass2,test-pass1)" );
189+ #endif // NDEBUG
190+
191+ EXPECT_DEATH (Registry.parseAndCreatePassPipeline (" bad-pass-name" ),
192+ " .*not registered.*" );
193+ EXPECT_DEATH (Registry.parseAndCreatePassPipeline (" " ), " .*not registered.*" );
194+ EXPECT_DEATH (Registry.parseAndCreatePassPipeline (" ," ), " .*not registered.*" );
195+ }
You can’t perform that action at this time.
0 commit comments