//===- LegacyPassManager.cpp - LLVM Pass Infrastructure Implementation ----===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file implements the legacy LLVM Pass Manager infrastructure. // //===----------------------------------------------------------------------===// #include "llvm/IR/LegacyPassManager.h" #include "llvm/ADT/MapVector.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/LegacyPassManagers.h" #include "llvm/IR/Module.h" #include "llvm/IR/PassTimingInfo.h" #include "llvm/IR/PrintPasses.h" #include "llvm/Support/Chrono.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TimeProfiler.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> usingnamespacellvm; extern cl::opt<bool> UseNewDbgInfoFormat; // See PassManagers.h for Pass Manager infrastructure overview. //===----------------------------------------------------------------------===// // Pass debugging information. Often it is useful to find out what pass is // running when a crash occurs in a utility. When this library is compiled with // debugging on, a command line option (--debug-pass) is enabled that causes the // pass name to be printed before it executes. // namespace { // Different debug levels that can be enabled... enum PassDebugLevel { … }; } // namespace static cl::opt<enum PassDebugLevel> PassDebugging( "debug-pass", cl::Hidden, cl::desc("Print legacy PassManager debugging information"), cl::values(clEnumVal(Disabled, "disable debug output"), clEnumVal(Arguments, "print pass arguments to pass to 'opt'"), clEnumVal(Structure, "print pass structure before run()"), clEnumVal(Executions, "print pass name before it is executed"), clEnumVal(Details, "print pass details when it is executed"))); /// isPassDebuggingExecutionsOrMore - Return true if -debug-pass=Executions /// or higher is specified. bool PMDataManager::isPassDebuggingExecutionsOrMore() const { … } unsigned PMDataManager::initSizeRemarkInfo( Module &M, StringMap<std::pair<unsigned, unsigned>> &FunctionToInstrCount) { … } void PMDataManager::emitInstrCountChangedRemark( Pass *P, Module &M, int64_t Delta, unsigned CountBefore, StringMap<std::pair<unsigned, unsigned>> &FunctionToInstrCount, Function *F) { … } void PassManagerPrettyStackEntry::print(raw_ostream &OS) const { … } namespace llvm { namespace legacy { bool debugPassSpecified() { … } //===----------------------------------------------------------------------===// // FunctionPassManagerImpl // /// FunctionPassManagerImpl manages FPPassManagers class FunctionPassManagerImpl : public Pass, public PMDataManager, public PMTopLevelManager { … }; void FunctionPassManagerImpl::anchor() { … } char FunctionPassManagerImpl::ID = …; //===----------------------------------------------------------------------===// // FunctionPassManagerImpl implementation // bool FunctionPassManagerImpl::doInitialization(Module &M) { … } bool FunctionPassManagerImpl::doFinalization(Module &M) { … } void FunctionPassManagerImpl::releaseMemoryOnTheFly() { … } // Execute all the passes managed by this top level manager. // Return true if any function is modified by a pass. bool FunctionPassManagerImpl::run(Function &F) { … } } // namespace legacy } // namespace llvm namespace { //===----------------------------------------------------------------------===// // MPPassManager // /// MPPassManager manages ModulePasses and function pass managers. /// It batches all Module passes and function pass managers together and /// sequences them to process one module. class MPPassManager : public Pass, public PMDataManager { … }; char MPPassManager::ID = …; } // End anonymous namespace namespace llvm { namespace legacy { //===----------------------------------------------------------------------===// // PassManagerImpl // /// PassManagerImpl manages MPPassManagers class PassManagerImpl : public Pass, public PMDataManager, public PMTopLevelManager { … }; void PassManagerImpl::anchor() { … } char PassManagerImpl::ID = …; //===----------------------------------------------------------------------===// // PassManagerImpl implementation // /// run - Execute all of the passes scheduled for execution. Keep track of /// whether any of the passes modifies the module, and if so, return true. bool PassManagerImpl::run(Module &M) { … } } // namespace legacy } // namespace llvm //===----------------------------------------------------------------------===// // PMTopLevelManager implementation /// Initialize top level manager. Create first pass manager. PMTopLevelManager::PMTopLevelManager(PMDataManager *PMDM) { … } /// Set pass P as the last user of the given analysis passes. void PMTopLevelManager::setLastUser(ArrayRef<Pass*> AnalysisPasses, Pass *P) { … } /// Collect passes whose last user is P void PMTopLevelManager::collectLastUses(SmallVectorImpl<Pass *> &LastUses, Pass *P) { … } AnalysisUsage *PMTopLevelManager::findAnalysisUsage(Pass *P) { … } /// Schedule pass P for execution. Make sure that passes required by /// P are run before P is run. Update analysis info maintained by /// the manager. Remove dead passes. This is a recursive function. void PMTopLevelManager::schedulePass(Pass *P) { … } /// Find the pass that implements Analysis AID. Search immutable /// passes and all pass managers. If desired pass is not found /// then return NULL. Pass *PMTopLevelManager::findAnalysisPass(AnalysisID AID) { … } const PassInfo *PMTopLevelManager::findAnalysisPassInfo(AnalysisID AID) const { … } void PMTopLevelManager::addImmutablePass(ImmutablePass *P) { … } // Print passes managed by this top level manager. void PMTopLevelManager::dumpPasses() const { … } void PMTopLevelManager::dumpArguments() const { … } void PMTopLevelManager::initializeAllAnalysisInfo() { … } /// Destructor PMTopLevelManager::~PMTopLevelManager() { … } //===----------------------------------------------------------------------===// // PMDataManager implementation /// Augement AvailableAnalysis by adding analysis made available by pass P. void PMDataManager::recordAvailableAnalysis(Pass *P) { … } // Return true if P preserves high level analysis used by other // passes managed by this manager bool PMDataManager::preserveHigherLevelAnalysis(Pass *P) { … } /// verifyPreservedAnalysis -- Verify analysis preserved by pass P. void PMDataManager::verifyPreservedAnalysis(Pass *P) { … } /// Remove Analysis not preserved by Pass P void PMDataManager::removeNotPreservedAnalysis(Pass *P) { … } /// Remove analysis passes that are not used any longer void PMDataManager::removeDeadPasses(Pass *P, StringRef Msg, enum PassDebuggingString DBG_STR) { … } void PMDataManager::freePass(Pass *P, StringRef Msg, enum PassDebuggingString DBG_STR) { … } /// Add pass P into the PassVector. Update /// AvailableAnalysis appropriately if ProcessAnalysis is true. void PMDataManager::add(Pass *P, bool ProcessAnalysis) { … } /// Populate UP with analysis pass that are used or required by /// pass P and are available. Populate RP_NotAvail with analysis /// pass that are required by pass P but are not available. void PMDataManager::collectRequiredAndUsedAnalyses( SmallVectorImpl<Pass *> &UP, SmallVectorImpl<AnalysisID> &RP_NotAvail, Pass *P) { … } // All Required analyses should be available to the pass as it runs! Here // we fill in the AnalysisImpls member of the pass so that it can // successfully use the getAnalysis() method to retrieve the // implementations it needs. // void PMDataManager::initializeAnalysisImpl(Pass *P) { … } /// Find the pass that implements Analysis AID. If desired pass is not found /// then return NULL. Pass *PMDataManager::findAnalysisPass(AnalysisID AID, bool SearchParent) { … } // Print list of passes that are last used by P. void PMDataManager::dumpLastUses(Pass *P, unsigned Offset) const{ … } void PMDataManager::dumpPassArguments() const { … } void PMDataManager::dumpPassInfo(Pass *P, enum PassDebuggingString S1, enum PassDebuggingString S2, StringRef Msg) { … } void PMDataManager::dumpRequiredSet(const Pass *P) const { … } void PMDataManager::dumpPreservedSet(const Pass *P) const { … } void PMDataManager::dumpUsedSet(const Pass *P) const { … } void PMDataManager::dumpAnalysisUsage(StringRef Msg, const Pass *P, const AnalysisUsage::VectorType &Set) const { … } /// Add RequiredPass into list of lower level passes required by pass P. /// RequiredPass is run on the fly by Pass Manager when P requests it /// through getAnalysis interface. /// This should be handled by specific pass manager. void PMDataManager::addLowerLevelRequiredPass(Pass *P, Pass *RequiredPass) { … } std::tuple<Pass *, bool> PMDataManager::getOnTheFlyPass(Pass *P, AnalysisID PI, Function &F) { … } // Destructor PMDataManager::~PMDataManager() { … } //===----------------------------------------------------------------------===// // NOTE: Is this the right place to define this method ? // getAnalysisIfAvailable - Return analysis result or null if it doesn't exist. Pass *AnalysisResolver::getAnalysisIfAvailable(AnalysisID ID) const { … } std::tuple<Pass *, bool> AnalysisResolver::findImplPass(Pass *P, AnalysisID AnalysisPI, Function &F) { … } namespace llvm { namespace legacy { //===----------------------------------------------------------------------===// // FunctionPassManager implementation /// Create new Function pass manager FunctionPassManager::FunctionPassManager(Module *m) : … { … } FunctionPassManager::~FunctionPassManager() { … } void FunctionPassManager::add(Pass *P) { … } /// run - Execute all of the passes scheduled for execution. Keep /// track of whether any of the passes modifies the function, and if /// so, return true. /// bool FunctionPassManager::run(Function &F) { … } /// doInitialization - Run all of the initializers for the function passes. /// bool FunctionPassManager::doInitialization() { … } /// doFinalization - Run all of the finalizers for the function passes. /// bool FunctionPassManager::doFinalization() { … } } // namespace legacy } // namespace llvm /// cleanup - After running all passes, clean up pass manager cache. void FPPassManager::cleanup() { … } //===----------------------------------------------------------------------===// // FPPassManager implementation char FPPassManager::ID = …; /// Print passes managed by this manager void FPPassManager::dumpPassStructure(unsigned Offset) { … } /// Execute all of the passes scheduled for execution by invoking /// runOnFunction method. Keep track of whether any of the passes modifies /// the function, and if so, return true. bool FPPassManager::runOnFunction(Function &F) { … } bool FPPassManager::runOnModule(Module &M) { … } bool FPPassManager::doInitialization(Module &M) { … } bool FPPassManager::doFinalization(Module &M) { … } //===----------------------------------------------------------------------===// // MPPassManager implementation /// Execute all of the passes scheduled for execution by invoking /// runOnModule method. Keep track of whether any of the passes modifies /// the module, and if so, return true. bool MPPassManager::runOnModule(Module &M) { … } /// Add RequiredPass into list of lower level passes required by pass P. /// RequiredPass is run on the fly by Pass Manager when P requests it /// through getAnalysis interface. void MPPassManager::addLowerLevelRequiredPass(Pass *P, Pass *RequiredPass) { … } /// Return function pass corresponding to PassInfo PI, that is /// required by module pass MP. Instantiate analysis pass, by using /// its runOnFunction() for function F. std::tuple<Pass *, bool> MPPassManager::getOnTheFlyPass(Pass *MP, AnalysisID PI, Function &F) { … } namespace llvm { namespace legacy { //===----------------------------------------------------------------------===// // PassManager implementation /// Create new pass manager PassManager::PassManager() { … } PassManager::~PassManager() { … } void PassManager::add(Pass *P) { … } /// run - Execute all of the passes scheduled for execution. Keep track of /// whether any of the passes modifies the module, and if so, return true. bool PassManager::run(Module &M) { … } } // namespace legacy } // namespace llvm //===----------------------------------------------------------------------===// // PMStack implementation // // Pop Pass Manager from the stack and clear its analysis info. void PMStack::pop() { … } // Push PM on the stack and set its top level manager. void PMStack::push(PMDataManager *PM) { … } // Dump content of the pass manager stack. LLVM_DUMP_METHOD void PMStack::dump() const { … } /// Find appropriate Module Pass Manager in the PM Stack and /// add self into that manager. void ModulePass::assignPassManager(PMStack &PMS, PassManagerType PreferredType) { … } /// Find appropriate Function Pass Manager or Call Graph Pass Manager /// in the PM Stack and add self into that manager. void FunctionPass::assignPassManager(PMStack &PMS, PassManagerType /*PreferredType*/) { … } legacy::PassManagerBase::~PassManagerBase() = default;