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 {
72
72
DenseMap<StringRef, Pass *> NameToPassMap;
73
73
74
74
public:
75
+ static constexpr const char PassDelimToken = ' ,' ;
75
76
PassRegistry () = default ;
76
77
// / Registers \p PassPtr and takes ownership.
77
78
Pass ®isterPass (std::unique_ptr<Pass> &&PassPtr) {
@@ -85,6 +86,9 @@ class PassRegistry {
85
86
auto It = NameToPassMap.find (Name);
86
87
return It != NameToPassMap.end () ? It->second : nullptr ;
87
88
}
89
+ // / Creates a pass pipeline and returns the first pass manager.
90
+ FunctionPassManager &parseAndCreatePassPipeline (StringRef Pipeline);
91
+
88
92
#ifndef NDEBUG
89
93
void print (raw_ostream &OS) const {
90
94
for (const auto &PassPtr : Passes)
Original file line number Diff line number Diff line change @@ -20,6 +20,38 @@ bool FunctionPassManager::runOnFunction(Function &F) {
20
20
// TODO: Check ChangeAll against hashes before/after.
21
21
return Change;
22
22
}
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
+ }
23
55
#ifndef NDEBUG
24
56
void PassRegistry::dump () const {
25
57
print (dbgs ());
Original file line number Diff line number Diff line change @@ -162,3 +162,34 @@ TEST_F(PassTest, PassRegistry) {
162
162
EXPECT_EQ (Buff, " test-pass1\n test-pass2\n " );
163
163
#endif // NDEBUG
164
164
}
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