Index: include/llvm/IR/LegacyPassNameParser.h =================================================================== --- include/llvm/IR/LegacyPassNameParser.h +++ include/llvm/IR/LegacyPassNameParser.h @@ -44,14 +44,11 @@ cl::Option *Opt; public: PassNameParser() : Opt(nullptr) {} - virtual ~PassNameParser(); + virtual ~PassNameParser() {} void initialize(cl::Option &O) { Opt = &O; cl::parser::initialize(O); - - // Add all of the passes to the map that got initialized before 'this' did. - enumeratePasses(); } // ignorablePassImpl - Can be overriden in subclasses to refine the list of Index: include/llvm/PassRegistry.h =================================================================== --- include/llvm/PassRegistry.h +++ include/llvm/PassRegistry.h @@ -40,9 +40,14 @@ PassRegistry() : pImpl(nullptr) { } ~PassRegistry(); - /// getPassRegistry - Access the global registry object, which is - /// automatically initialized at application launch and destroyed by - /// llvm_shutdown. + /// initializePassRegistry - Creates the global pass registry object. This + /// is typically called very early in main, and must be called before any call + /// to getPassRegistry. + static void initializePassRegistry(); + + /// getPassRegistry - Access the global registry object, which is + /// automatically initialized when you call initializePassRegistry(), and + /// destroyed by llvm_shutdown. static PassRegistry *getPassRegistry(); /// getPassInfo - Look up a pass' corresponding PassInfo, indexed by the pass' Index: include/llvm/PassSupport.h =================================================================== --- include/llvm/PassSupport.h +++ include/llvm/PassSupport.h @@ -24,7 +24,9 @@ #include "Pass.h" #include "llvm/InitializePasses.h" #include "llvm/PassRegistry.h" +#include "llvm/StaticPassRegistry.h" #include "llvm/Support/Atomic.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Valgrind.h" #include @@ -228,48 +230,7 @@ : PassInfo(Name, PassArg, &passName::ID, PassInfo::NormalCtor_t(callDefaultCtor), CFGOnly, is_analysis) { - PassRegistry::getPassRegistry()->registerPass(*this); - } -}; - - -/// RegisterAnalysisGroup - Register a Pass as a member of an analysis _group_. -/// Analysis groups are used to define an interface (which need not derive from -/// Pass) that is required by passes to do their job. Analysis Groups differ -/// from normal analyses because any available implementation of the group will -/// be used if it is available. -/// -/// If no analysis implementing the interface is available, a default -/// implementation is created and added. A pass registers itself as the default -/// implementation by specifying 'true' as the second template argument of this -/// class. -/// -/// In addition to registering itself as an analysis group member, a pass must -/// register itself normally as well. Passes may be members of multiple groups -/// and may still be "required" specifically by name. -/// -/// The actual interface may also be registered as well (by not specifying the -/// second template argument). The interface should be registered to associate -/// a nice name with the interface. -/// -class RegisterAGBase : public PassInfo { -public: - RegisterAGBase(const char *Name, - const void *InterfaceID, - const void *PassID = nullptr, - bool isDefault = false); -}; - -template -struct RegisterAnalysisGroup : public RegisterAGBase { - explicit RegisterAnalysisGroup(PassInfo &RPB) - : RegisterAGBase(RPB.getPassName(), - &Interface::ID, RPB.getTypeInfo(), - Default) { - } - - explicit RegisterAnalysisGroup(const char *Name) - : RegisterAGBase(Name, &Interface::ID) { + StaticPassRegistry::getStaticPassRegistry()->registerPass(*this); } }; @@ -323,39 +284,23 @@ //===--------------------------------------------------------------------------- /// PassRegistrationListener class - This class is meant to be derived from by /// clients that are interested in which passes get registered and unregistered -/// at runtime (which can be because of the RegisterPass constructors being run -/// as the program starts up, or may be because a shared object just got -/// loaded). Deriving from the PassRegistrationListener class automatically -/// registers your object to receive callbacks indicating when passes are loaded -/// and removed. +/// at runtime due to a a shared object just having been loaded. Deriving from +/// PassRegistrationListener doesn't automatically register your object to +/// receive callbacks indicating when passes are loaded and removed. /// struct PassRegistrationListener { - - /// PassRegistrationListener ctor - Add the current object to the list of - /// PassRegistrationListeners... - PassRegistrationListener(); - - /// dtor - Remove object from list of listeners... - /// - virtual ~PassRegistrationListener(); + virtual ~PassRegistrationListener() { } /// Callback functions - These functions are invoked whenever a pass is loaded /// or removed from the current executable. /// virtual void passRegistered(const PassInfo *) {} - /// enumeratePasses - Iterate over the registered passes, calling the - /// passEnumerate callback on each PassInfo object. - /// - void enumeratePasses(); + virtual void passUnregistered(const PassInfo *) {} - /// passEnumerate - Callback function invoked when someone calls - /// enumeratePasses on this PassRegistrationListener object. - /// virtual void passEnumerate(const PassInfo *) {} }; - } // End llvm namespace #endif Index: include/llvm/StaticPassRegistry.h =================================================================== --- /dev/null +++ include/llvm/StaticPassRegistry.h @@ -0,0 +1,48 @@ +//===- llvm/StaticPassRegistry.h - Pass Information Registry ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines StaticPassRegistry, a class that is used in the +// initialization and registration of passes. During static program +// initialization, passes are registered with the StaticPassRegistry by +// declaring instances of the RegisterPass<> template. Once main() begins, the +// application must call PassRegistry::initializePassRegistry() to load the +// statically initialized passes. Note that StaticPassRegistry is intended to +// be immutable after main() is entered. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_STATIC_PASSREGISTRY_H +#define LLVM_STATIC_PASSREGISTRY_H + +#include + +namespace llvm { + +class PassInfo; + +class StaticPassRegistry { + friend class PassRegistry; +private: + /// PassInfoMap - Keep track of the PassInfo object for each registered pass. + typedef std::list ListType; + ListType PassInfoList; + +public: + /// registerPass - Register a pass (by means of its PassInfo) with the + /// registry. + void registerPass(const PassInfo &PI); + + /// getStaticPassRegistry - Access the global registry object, which is + /// automatically initialized at application launch. + static StaticPassRegistry *getStaticPassRegistry(); +}; + +} + +#endif \ No newline at end of file Index: lib/IR/CMakeLists.txt =================================================================== --- lib/IR/CMakeLists.txt +++ lib/IR/CMakeLists.txt @@ -35,6 +35,7 @@ Pass.cpp PassManager.cpp PassRegistry.cpp + StaticPassRegistry.cpp Type.cpp TypeFinder.cpp Use.cpp Index: lib/IR/Pass.cpp =================================================================== --- lib/IR/Pass.cpp +++ lib/IR/Pass.cpp @@ -208,43 +208,6 @@ } //===----------------------------------------------------------------------===// -// Analysis Group Implementation Code -//===----------------------------------------------------------------------===// - -// RegisterAGBase implementation -// -RegisterAGBase::RegisterAGBase(const char *Name, const void *InterfaceID, - const void *PassID, bool isDefault) - : PassInfo(Name, InterfaceID) { - PassRegistry::getPassRegistry()->registerAnalysisGroup(InterfaceID, PassID, - *this, isDefault); -} - -//===----------------------------------------------------------------------===// -// PassRegistrationListener implementation -// - -// PassRegistrationListener ctor - Add the current object to the list of -// PassRegistrationListeners... -PassRegistrationListener::PassRegistrationListener() { - PassRegistry::getPassRegistry()->addRegistrationListener(this); -} - -// dtor - Remove object from list of listeners... -PassRegistrationListener::~PassRegistrationListener() { - PassRegistry::getPassRegistry()->removeRegistrationListener(this); -} - -// enumeratePasses - Iterate over the registered passes, calling the -// passEnumerate callback on each PassInfo object. -// -void PassRegistrationListener::enumeratePasses() { - PassRegistry::getPassRegistry()->enumerateWith(this); -} - -PassNameParser::~PassNameParser() {} - -//===----------------------------------------------------------------------===// // AnalysisUsage Class Implementation // @@ -273,7 +236,8 @@ void AnalysisUsage::setPreservesCFG() { // Since this transformation doesn't modify the CFG, it preserves all analyses // that only depend on the CFG (like dominators, loop info, etc...) - GetCFGOnlyPasses(Preserved).enumeratePasses(); + GetCFGOnlyPasses callback(Preserved); + PassRegistry::getPassRegistry()->enumerateWith(&callback); } AnalysisUsage &AnalysisUsage::addPreserved(StringRef Arg) { Index: lib/IR/PassRegistry.cpp =================================================================== --- lib/IR/PassRegistry.cpp +++ lib/IR/PassRegistry.cpp @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// // -// This file implements the PassRegistry, with which passes are registered on -// initialization, and supports the PassManager in dependency resolution. +// This file implements the PassRegistry, with which passes are registered at +// runtime, and supports the PassManager in dependency resolution. // //===----------------------------------------------------------------------===// @@ -18,6 +18,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/IR/Function.h" #include "llvm/PassSupport.h" +#include "llvm/StaticPassRegistry.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Mutex.h" @@ -26,17 +27,23 @@ using namespace llvm; -// FIXME: We use ManagedStatic to erase the pass registrar on shutdown. -// Unfortunately, passes are registered with static ctors, and having -// llvm_shutdown clear this map prevents successful resurrection after -// llvm_shutdown is run. Ideally we should find a solution so that we don't -// leak the map, AND can still resurrect after shutdown. +static sys::SmartRWMutex Lock; static ManagedStatic PassRegistryObj; PassRegistry *PassRegistry::getPassRegistry() { + assert(PassRegistryObj.isConstructed() && "initializePassRegistry not called!"); return &*PassRegistryObj; } -static ManagedStatic > Lock; +void PassRegistry::initializePassRegistry() { + assert(!PassRegistryObj.isConstructed() && "initializePassRegistry called twice!"); + + // Manually construct the ManagedStatic here. + PassRegistry ®istry = *PassRegistryObj; + + StaticPassRegistry *staticRegistry = StaticPassRegistry::getStaticPassRegistry(); + for (auto it=staticRegistry->PassInfoList.begin(); it!=staticRegistry->PassInfoList.end(); ++it) + registry.registerPass(**it); +} //===----------------------------------------------------------------------===// // PassRegistryImpl @@ -58,7 +65,7 @@ DenseMap AnalysisGroupInfoMap; std::vector> ToFree; - std::vector Listeners; + std::vector RegistrationListeners; }; } // end anonymous namespace @@ -73,21 +80,21 @@ // PassRegistry::~PassRegistry() { - sys::SmartScopedWriter Guard(*Lock); + sys::SmartScopedWriter Guard(Lock); PassRegistryImpl *Impl = static_cast(pImpl); delete Impl; pImpl = nullptr; } const PassInfo *PassRegistry::getPassInfo(const void *TI) const { - sys::SmartScopedReader Guard(*Lock); + sys::SmartScopedReader Guard(Lock); PassRegistryImpl *Impl = static_cast(getImpl()); PassRegistryImpl::MapType::const_iterator I = Impl->PassInfoMap.find(TI); return I != Impl->PassInfoMap.end() ? I->second : nullptr; } const PassInfo *PassRegistry::getPassInfo(StringRef Arg) const { - sys::SmartScopedReader Guard(*Lock); + sys::SmartScopedReader Guard(Lock); PassRegistryImpl *Impl = static_cast(getImpl()); PassRegistryImpl::StringMapType::const_iterator I = Impl->PassInfoStringMap.find(Arg); @@ -99,7 +106,7 @@ // void PassRegistry::registerPass(const PassInfo &PI, bool ShouldFree) { - sys::SmartScopedWriter Guard(*Lock); + sys::SmartScopedWriter Guard(Lock); PassRegistryImpl *Impl = static_cast(getImpl()); bool Inserted = Impl->PassInfoMap.insert(std::make_pair(PI.getTypeInfo(),&PI)).second; @@ -109,14 +116,14 @@ // Notify any listeners. for (std::vector::iterator - I = Impl->Listeners.begin(), E = Impl->Listeners.end(); I != E; ++I) + I = Impl->RegistrationListeners.begin(), E = Impl->RegistrationListeners.end(); I != E; ++I) (*I)->passRegistered(&PI); if (ShouldFree) Impl->ToFree.push_back(std::unique_ptr(&PI)); } void PassRegistry::unregisterPass(const PassInfo &PI) { - sys::SmartScopedWriter Guard(*Lock); + sys::SmartScopedWriter Guard(Lock); PassRegistryImpl *Impl = static_cast(getImpl()); PassRegistryImpl::MapType::iterator I = Impl->PassInfoMap.find(PI.getTypeInfo()); @@ -128,7 +135,7 @@ } void PassRegistry::enumerateWith(PassRegistrationListener *L) { - sys::SmartScopedReader Guard(*Lock); + sys::SmartScopedReader Guard(Lock); PassRegistryImpl *Impl = static_cast(getImpl()); for (PassRegistryImpl::MapType::const_iterator I = Impl->PassInfoMap.begin(), E = Impl->PassInfoMap.end(); I != E; ++I) @@ -156,7 +163,7 @@ assert(ImplementationInfo && "Must register pass before adding to AnalysisGroup!"); - sys::SmartScopedWriter Guard(*Lock); + sys::SmartScopedWriter Guard(Lock); // Make sure we keep track of the fact that the implementation implements // the interface. @@ -185,13 +192,13 @@ } void PassRegistry::addRegistrationListener(PassRegistrationListener *L) { - sys::SmartScopedWriter Guard(*Lock); + sys::SmartScopedWriter Guard(Lock); PassRegistryImpl *Impl = static_cast(getImpl()); - Impl->Listeners.push_back(L); + Impl->RegistrationListeners.push_back(L); } void PassRegistry::removeRegistrationListener(PassRegistrationListener *L) { - sys::SmartScopedWriter Guard(*Lock); + sys::SmartScopedWriter Guard(Lock); // NOTE: This is necessary, because removeRegistrationListener() can be called // as part of the llvm_shutdown sequence. Since we have no control over the @@ -201,8 +208,8 @@ PassRegistryImpl *Impl = static_cast(getImpl()); std::vector::iterator I = - std::find(Impl->Listeners.begin(), Impl->Listeners.end(), L); - assert(I != Impl->Listeners.end() && - "PassRegistrationListener not registered!"); - Impl->Listeners.erase(I); + std::find(Impl->RegistrationListeners.begin(), Impl->RegistrationListeners.end(), L); + assert(I != Impl->RegistrationListeners.end() && + "Pass registration listener not registered!"); + Impl->RegistrationListeners.erase(I); } Index: lib/IR/StaticPassRegistry.cpp =================================================================== --- /dev/null +++ lib/IR/StaticPassRegistry.cpp @@ -0,0 +1,31 @@ +//===- StaticPassRegistry.cpp - Pass Registration Implementation ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the StaticPassRegistry, with which static passes are +// registered during program initialization. +// +//===----------------------------------------------------------------------===// + +#include "llvm/StaticPassRegistry.h" +#include "llvm/PassSupport.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/ManagedStatic.h" +#include + +using namespace llvm; + +static ManagedStatic PassRegistryObj; + +StaticPassRegistry *StaticPassRegistry::getStaticPassRegistry() { + return &*PassRegistryObj; +} + +void StaticPassRegistry::registerPass(const PassInfo &PI) { + PassInfoList.push_back(&PI); +} \ No newline at end of file Index: tools/bugpoint/bugpoint.cpp =================================================================== --- tools/bugpoint/bugpoint.cpp +++ tools/bugpoint/bugpoint.cpp @@ -123,7 +123,14 @@ #endif // Initialize passes + PassRegistry::initializePassRegistry(); PassRegistry &Registry = *PassRegistry::getPassRegistry(); + // Add a registration listener to catch dynamically loaded pass registrations, + // and do an enumeration to catch existing pass registrations done during + // static program initialization. + Registry.addRegistrationListener(&PassList.getParser()); + Registry.enumerateWith(&PassList.getParser()); + initializeCore(Registry); initializeScalarOpts(Registry); initializeObjCARCOpts(Registry); Index: tools/llc/llc.cpp =================================================================== --- tools/llc/llc.cpp +++ tools/llc/llc.cpp @@ -181,6 +181,7 @@ // Enable debug stream buffering. EnableDebugBuffering = true; + PassRegistry::initializePassRegistry(); LLVMContext &Context = getGlobalContext(); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. Index: tools/opt/opt.cpp =================================================================== --- tools/opt/opt.cpp +++ tools/opt/opt.cpp @@ -34,6 +34,7 @@ #include "llvm/LinkAllPasses.h" #include "llvm/MC/SubtargetFeature.h" #include "llvm/PassManager.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/ManagedStatic.h" @@ -328,6 +329,14 @@ sys::PrintStackTraceOnErrorSignal(); llvm::PrettyStackTraceProgram X(argc, argv); + PassRegistry::initializePassRegistry(); + PassRegistry &Registry = *PassRegistry::getPassRegistry(); + // Add a registration listener to catch dynamically loaded pass registrations, + // and do an enumeration to catch existing pass registrations done during + // static program initialization. + Registry.addRegistrationListener(&PassList.getParser()); + Registry.enumerateWith(&PassList.getParser()); + // Enable debug stream buffering. EnableDebugBuffering = true; @@ -338,7 +347,6 @@ InitializeAllTargetMCs(); // Initialize passes - PassRegistry &Registry = *PassRegistry::getPassRegistry(); initializeCore(Registry); initializeDebugIRPass(Registry); initializeScalarOpts(Registry);