diff options
Diffstat (limited to 'tools/opt/Passes.cpp')
-rw-r--r-- | tools/opt/Passes.cpp | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/tools/opt/Passes.cpp b/tools/opt/Passes.cpp new file mode 100644 index 0000000..ffdf9bf --- /dev/null +++ b/tools/opt/Passes.cpp @@ -0,0 +1,209 @@ +//===- Passes.cpp - Parsing, selection, and running of passes -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file provides the infrastructure to parse and build a custom pass +/// manager based on a commandline flag. It also provides helpers to aid in +/// analyzing, debugging, and testing pass structures. +/// +//===----------------------------------------------------------------------===// + +#include "Passes.h" +#include "llvm/Analysis/LazyCallGraph.h" +#include "llvm/IR/IRPrintingPasses.h" +#include "llvm/IR/PassManager.h" +#include "llvm/IR/Verifier.h" +#include "llvm/Support/Debug.h" + +using namespace llvm; + +namespace { + +/// \brief No-op module pass which does nothing. +struct NoOpModulePass { + PreservedAnalyses run(Module *M) { return PreservedAnalyses::all(); } + static StringRef name() { return "NoOpModulePass"; } +}; + +/// \brief No-op function pass which does nothing. +struct NoOpFunctionPass { + PreservedAnalyses run(Function *F) { return PreservedAnalyses::all(); } + static StringRef name() { return "NoOpFunctionPass"; } +}; + +} // End anonymous namespace. + +// FIXME: Factor all of the parsing logic into a .def file that we include +// under different macros. +static bool isModulePassName(StringRef Name) { + if (Name == "no-op-module") return true; + if (Name == "print") return true; + if (Name == "print-cg") return true; + + return false; +} + +static bool isFunctionPassName(StringRef Name) { + if (Name == "no-op-function") return true; + if (Name == "print") return true; + + return false; +} + +static bool parseModulePassName(ModulePassManager &MPM, StringRef Name) { + if (Name == "no-op-module") { + MPM.addPass(NoOpModulePass()); + return true; + } + if (Name == "print") { + MPM.addPass(PrintModulePass(dbgs())); + return true; + } + if (Name == "print-cg") { + MPM.addPass(LazyCallGraphPrinterPass(dbgs())); + return true; + } + return false; +} + +static bool parseFunctionPassName(FunctionPassManager &FPM, StringRef Name) { + if (Name == "no-op-function") { + FPM.addPass(NoOpFunctionPass()); + return true; + } + if (Name == "print") { + FPM.addPass(PrintFunctionPass(dbgs())); + return true; + } + return false; +} + +static bool parseFunctionPassPipeline(FunctionPassManager &FPM, + StringRef &PipelineText, + bool VerifyEachPass) { + for (;;) { + // Parse nested pass managers by recursing. + if (PipelineText.startswith("function(")) { + FunctionPassManager NestedFPM; + + // Parse the inner pipeline inte the nested manager. + PipelineText = PipelineText.substr(strlen("function(")); + if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass) || + PipelineText.empty()) + return false; + assert(PipelineText[0] == ')'); + PipelineText = PipelineText.substr(1); + + // Add the nested pass manager with the appropriate adaptor. + FPM.addPass(std::move(NestedFPM)); + } else { + // Otherwise try to parse a pass name. + size_t End = PipelineText.find_first_of(",)"); + if (!parseFunctionPassName(FPM, PipelineText.substr(0, End))) + return false; + if (VerifyEachPass) + FPM.addPass(VerifierPass()); + + PipelineText = PipelineText.substr(End); + } + + if (PipelineText.empty() || PipelineText[0] == ')') + return true; + + assert(PipelineText[0] == ','); + PipelineText = PipelineText.substr(1); + } +} + +static bool parseModulePassPipeline(ModulePassManager &MPM, + StringRef &PipelineText, + bool VerifyEachPass) { + for (;;) { + // Parse nested pass managers by recursing. + if (PipelineText.startswith("module(")) { + ModulePassManager NestedMPM; + + // Parse the inner pipeline into the nested manager. + PipelineText = PipelineText.substr(strlen("module(")); + if (!parseModulePassPipeline(NestedMPM, PipelineText, VerifyEachPass) || + PipelineText.empty()) + return false; + assert(PipelineText[0] == ')'); + PipelineText = PipelineText.substr(1); + + // Now add the nested manager as a module pass. + MPM.addPass(std::move(NestedMPM)); + } else if (PipelineText.startswith("function(")) { + FunctionPassManager NestedFPM; + + // Parse the inner pipeline inte the nested manager. + PipelineText = PipelineText.substr(strlen("function(")); + if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass) || + PipelineText.empty()) + return false; + assert(PipelineText[0] == ')'); + PipelineText = PipelineText.substr(1); + + // Add the nested pass manager with the appropriate adaptor. + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(NestedFPM))); + } else { + // Otherwise try to parse a pass name. + size_t End = PipelineText.find_first_of(",)"); + if (!parseModulePassName(MPM, PipelineText.substr(0, End))) + return false; + if (VerifyEachPass) + MPM.addPass(VerifierPass()); + + PipelineText = PipelineText.substr(End); + } + + if (PipelineText.empty() || PipelineText[0] == ')') + return true; + + assert(PipelineText[0] == ','); + PipelineText = PipelineText.substr(1); + } +} + +// Primary pass pipeline description parsing routine. +// FIXME: Should this routine accept a TargetMachine or require the caller to +// pre-populate the analysis managers with target-specific stuff? +bool llvm::parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText, + bool VerifyEachPass) { + // Look at the first entry to figure out which layer to start parsing at. + if (PipelineText.startswith("module(")) + return parseModulePassPipeline(MPM, PipelineText, VerifyEachPass) && + PipelineText.empty(); + if (PipelineText.startswith("function(")) { + FunctionPassManager FPM; + if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass) || + !PipelineText.empty()) + return false; + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + return true; + } + + // This isn't a direct pass manager name, look for the end of a pass name. + StringRef FirstName = + PipelineText.substr(0, PipelineText.find_first_of(",)")); + if (isModulePassName(FirstName)) + return parseModulePassPipeline(MPM, PipelineText, VerifyEachPass) && + PipelineText.empty(); + + if (isFunctionPassName(FirstName)) { + FunctionPassManager FPM; + if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass) || + !PipelineText.empty()) + return false; + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + return true; + } + + return false; +} |