Skip to content

Commit f0f1b70

Browse files
authored
[SandboxIR][PassRegistry] Parse pipeline string (#108103)
This patch implements a simple version of the pipeline parsing function. It currently only handles a single FPM and adds function passes to it.
1 parent 661382f commit f0f1b70

File tree

3 files changed

+67
-0
lines changed

3 files changed

+67
-0
lines changed

llvm/include/llvm/SandboxIR/PassManager.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ class PassRegistry {
7272
DenseMap<StringRef, Pass *> NameToPassMap;
7373

7474
public:
75+
static constexpr const char PassDelimToken = ',';
7576
PassRegistry() = default;
7677
/// Registers \p PassPtr and takes ownership.
7778
Pass &registerPass(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)

llvm/lib/SandboxIR/PassManager.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff 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
2456
void PassRegistry::dump() const {
2557
print(dbgs());

llvm/unittests/SandboxIR/PassTest.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,3 +162,34 @@ TEST_F(PassTest, PassRegistry) {
162162
EXPECT_EQ(Buff, "test-pass1\ntest-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+
}

0 commit comments

Comments
 (0)