Index: include/llvm/Support/DynamicLibrary.h =================================================================== --- include/llvm/Support/DynamicLibrary.h +++ include/llvm/Support/DynamicLibrary.h @@ -108,7 +108,9 @@ /// @brief Add searchable symbol/value pair. static void AddSymbol(StringRef symbolName, void *symbolValue); + // Force any ManagedStatics DynamicLibrary requires to be constructed. class HandleSet; + static HandleSet& init(); }; } // End sys namespace Index: lib/Support/DynamicLibrary.cpp =================================================================== --- lib/Support/DynamicLibrary.cpp +++ lib/Support/DynamicLibrary.cpp @@ -125,12 +125,21 @@ (*ExplicitSymbols)[SymbolName] = SymbolValue; } +DynamicLibrary::HandleSet& DynamicLibrary::init() { + return *OpenedHandles; +} + DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *FileName, std::string *Err) { - SmartScopedLock Lock(*SymbolsMutex); + // Force OpenedHandles to be added into the ManagedStatic list before any + // ManagedStatic can be added from static constructors in HandleSet::DLOpen. + HandleSet& HS = init(); + void *Handle = HandleSet::DLOpen(FileName, Err); - if (Handle != &Invalid) - OpenedHandles->AddLibrary(Handle, /*IsProcess*/ FileName == nullptr); + if (Handle != &Invalid) { + SmartScopedLock Lock(*SymbolsMutex); + HS.AddLibrary(Handle, /*IsProcess*/ FileName == nullptr); + } return DynamicLibrary(Handle); } Index: lib/Transforms/IPO/PassManagerBuilder.cpp =================================================================== --- lib/Transforms/IPO/PassManagerBuilder.cpp +++ lib/Transforms/IPO/PassManagerBuilder.cpp @@ -29,6 +29,7 @@ #include "llvm/IR/ModuleSummaryIndex.h" #include "llvm/IR/Verifier.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/IPO.h" @@ -197,6 +198,7 @@ void PassManagerBuilder::addGlobalExtension( PassManagerBuilder::ExtensionPointTy Ty, PassManagerBuilder::ExtensionFn Fn) { + sys::DynamicLibrary::init(); GlobalExtensions->push_back(std::make_pair(Ty, std::move(Fn))); } Index: unittests/Support/DynamicLibrary/CMakeLists.txt =================================================================== --- unittests/Support/DynamicLibrary/CMakeLists.txt +++ unittests/Support/DynamicLibrary/CMakeLists.txt @@ -1,4 +1,4 @@ -set(LLVM_LINK_COMPONENTS Support) +set(LLVM_LINK_COMPONENTS Support IPO) add_llvm_unittest(DynamicLibraryTests DynamicLibraryTest.cpp) Index: unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp =================================================================== --- unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp +++ unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp @@ -12,6 +12,7 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Path.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "gtest/gtest.h" #include "PipSqueak.h" @@ -54,6 +55,28 @@ return Tmp.P; } +static void +NoPassRegistration(const PassManagerBuilder &, legacy::PassManagerBase &) { +} + +static RegisterStandardPasses TestOrder(PassManagerBuilder::EP_LoopOptimizerEnd, + NoPassRegistration); + +typedef void (*TestPassReg)(void (*)(PassManagerBuilder::ExtensionPointTy, + PassManagerBuilder::ExtensionFn)); + +TEST(DynamicLibrary, PassRegistration) { + std::string Err; + llvm_shutdown_obj Shutdown; + DynamicLibrary DL = + DynamicLibrary::getPermanentLibrary(LibPath().c_str(), &Err); + EXPECT_TRUE(DL.isValid()); + EXPECT_TRUE(Err.empty()); + + TestPassReg RP = FuncPtr(DL.getAddressOfSymbol("TestPassReg")); + RP(&PassManagerBuilder::addGlobalExtension); +} + static const char *OverloadTestA() { return "OverloadCall"; } std::string StdString(const char *Ptr) { return Ptr ? Ptr : ""; } Index: unittests/Support/DynamicLibrary/PipSqueak.cxx =================================================================== --- unittests/Support/DynamicLibrary/PipSqueak.cxx +++ unittests/Support/DynamicLibrary/PipSqueak.cxx @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "PipSqueak.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" #if defined(_WIN32) && !defined(__GNUC__) // Disable warnings from inclusion of xlocale & exception @@ -44,3 +45,13 @@ } extern "C" PIPSQUEAK_EXPORT const char *TestA() { return "LibCall"; } + +static void LibPassRegistration(const llvm::PassManagerBuilder &, + llvm::legacy::PassManagerBase &) {} + +extern "C" PIPSQUEAK_EXPORT void TestPassReg( + void (*addGlobalExtension)(llvm::PassManagerBuilder::ExtensionPointTy, + llvm::PassManagerBuilder::ExtensionFn)) { + addGlobalExtension(llvm::PassManagerBuilder::EP_EarlyAsPossible, + LibPassRegistration); +}