File indexing completed on 2026-05-10 08:44:26
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #ifndef LLVM_SANDBOXIR_PASSMANAGER_H
0019 #define LLVM_SANDBOXIR_PASSMANAGER_H
0020
0021 #include <memory>
0022
0023 #include "llvm/ADT/DenseMap.h"
0024 #include "llvm/ADT/STLExtras.h"
0025 #include "llvm/SandboxIR/Pass.h"
0026 #include "llvm/Support/Debug.h"
0027
0028 namespace llvm::sandboxir {
0029
0030 class Value;
0031
0032
0033 template <typename ParentPass, typename ContainedPass>
0034 class PassManager : public ParentPass {
0035 public:
0036
0037 using CreatePassFunc =
0038 std::function<std::unique_ptr<ContainedPass>(StringRef, StringRef)>;
0039
0040 protected:
0041
0042 SmallVector<std::unique_ptr<ContainedPass>> Passes;
0043
0044 PassManager(StringRef Name) : ParentPass(Name) {}
0045 PassManager(StringRef Name, StringRef Pipeline, CreatePassFunc CreatePass)
0046 : ParentPass(Name) {
0047 setPassPipeline(Pipeline, CreatePass);
0048 }
0049 PassManager(const PassManager &) = delete;
0050 PassManager(PassManager &&) = default;
0051 virtual ~PassManager() = default;
0052 PassManager &operator=(const PassManager &) = delete;
0053
0054 public:
0055
0056 void addPass(std::unique_ptr<ContainedPass> Pass) {
0057
0058 Passes.push_back(std::move(Pass));
0059 }
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076 void setPassPipeline(StringRef Pipeline, CreatePassFunc CreatePass) {
0077 static constexpr const char EndToken = '\0';
0078 static constexpr const char BeginArgsToken = '<';
0079 static constexpr const char EndArgsToken = '>';
0080 static constexpr const char PassDelimToken = ',';
0081
0082 assert(Passes.empty() &&
0083 "setPassPipeline called on a non-empty sandboxir::PassManager");
0084
0085
0086
0087
0088 if (Pipeline.empty())
0089 return;
0090
0091
0092 std::string PipelineStr = std::string(Pipeline) + EndToken;
0093 Pipeline = StringRef(PipelineStr);
0094
0095 auto AddPass = [this, CreatePass](StringRef PassName, StringRef PassArgs) {
0096 if (PassName.empty()) {
0097 errs() << "Found empty pass name.\n";
0098 exit(1);
0099 }
0100
0101
0102 auto Pass = CreatePass(PassName, PassArgs);
0103 if (Pass == nullptr) {
0104 errs() << "Pass '" << PassName << "' not registered!\n";
0105 exit(1);
0106 }
0107 addPass(std::move(Pass));
0108 };
0109
0110 enum class State {
0111 ScanName,
0112 ScanArgs,
0113 ArgsEnded,
0114 } CurrentState = State::ScanName;
0115 int PassBeginIdx = 0;
0116 int ArgsBeginIdx;
0117 StringRef PassName;
0118 int NestedArgs = 0;
0119 for (auto [Idx, C] : enumerate(Pipeline)) {
0120 switch (CurrentState) {
0121 case State::ScanName:
0122 if (C == BeginArgsToken) {
0123
0124 PassName = Pipeline.slice(PassBeginIdx, Idx);
0125 ArgsBeginIdx = Idx + 1;
0126 ++NestedArgs;
0127 CurrentState = State::ScanArgs;
0128 break;
0129 }
0130 if (C == EndArgsToken) {
0131 errs() << "Unexpected '>' in pass pipeline.\n";
0132 exit(1);
0133 }
0134 if (C == EndToken || C == PassDelimToken) {
0135
0136
0137 AddPass(Pipeline.slice(PassBeginIdx, Idx), StringRef());
0138 PassBeginIdx = Idx + 1;
0139 }
0140 break;
0141 case State::ScanArgs:
0142
0143
0144 if (C == BeginArgsToken) {
0145 ++NestedArgs;
0146 break;
0147 }
0148 if (C == EndArgsToken) {
0149 --NestedArgs;
0150 if (NestedArgs == 0) {
0151
0152 AddPass(PassName, Pipeline.slice(ArgsBeginIdx, Idx));
0153 CurrentState = State::ArgsEnded;
0154 } else if (NestedArgs < 0) {
0155 errs() << "Unexpected '>' in pass pipeline.\n";
0156 exit(1);
0157 }
0158 break;
0159 }
0160 if (C == EndToken) {
0161 errs() << "Missing '>' in pass pipeline. End-of-string reached while "
0162 "reading arguments for pass '"
0163 << PassName << "'.\n";
0164 exit(1);
0165 }
0166 break;
0167 case State::ArgsEnded:
0168
0169
0170 if (C == EndToken || C == PassDelimToken) {
0171 PassBeginIdx = Idx + 1;
0172 CurrentState = State::ScanName;
0173 } else {
0174 errs() << "Expected delimiter or end-of-string after pass "
0175 "arguments.\n";
0176 exit(1);
0177 }
0178 break;
0179 }
0180 }
0181 }
0182
0183 #ifndef NDEBUG
0184 void print(raw_ostream &OS) const override {
0185 OS << this->getName();
0186 OS << "(";
0187
0188 interleave(Passes, OS, [&OS](auto &Pass) { OS << Pass->getName(); }, ",");
0189 OS << ")";
0190 }
0191 LLVM_DUMP_METHOD void dump() const override {
0192 print(dbgs());
0193 dbgs() << "\n";
0194 }
0195 #endif
0196
0197 void printPipeline(raw_ostream &OS) const override {
0198 OS << this->getName() << "\n";
0199 for (const auto &PassPtr : Passes)
0200 PassPtr->printPipeline(OS);
0201 }
0202 };
0203
0204 class FunctionPassManager final
0205 : public PassManager<FunctionPass, FunctionPass> {
0206 public:
0207 FunctionPassManager(StringRef Name) : PassManager(Name) {}
0208 FunctionPassManager(StringRef Name, StringRef Pipeline,
0209 CreatePassFunc CreatePass)
0210 : PassManager(Name, Pipeline, CreatePass) {}
0211 bool runOnFunction(Function &F, const Analyses &A) final;
0212 };
0213
0214 class RegionPassManager final : public PassManager<RegionPass, RegionPass> {
0215 public:
0216 RegionPassManager(StringRef Name) : PassManager(Name) {}
0217 RegionPassManager(StringRef Name, StringRef Pipeline,
0218 CreatePassFunc CreatePass)
0219 : PassManager(Name, Pipeline, CreatePass) {}
0220 bool runOnRegion(Region &R, const Analyses &A) final;
0221 };
0222
0223 }
0224
0225 #endif