Index: include/llvm/Transforms/IPO/PassManagerBuilder.h =================================================================== --- include/llvm/Transforms/IPO/PassManagerBuilder.h +++ include/llvm/Transforms/IPO/PassManagerBuilder.h @@ -60,9 +60,10 @@ public: /// Extensions are passed the builder itself (so they can see how it is /// configured) as well as the pass manager to add stuff to. - typedef std::function - ExtensionFn; + typedef void ExtensionProc(const PassManagerBuilder &Builder, + legacy::PassManagerBase &PM); + typedef std::function ExtensionFn; + enum ExtensionPointTy { /// EP_EarlyAsPossible - This extension point allows adding passes before /// any other transformations, allowing them to see the code as it is coming @@ -179,7 +180,7 @@ /// Adds an extension that will be used by all PassManagerBuilder instances. /// This is intended to be used by plugins, to register a set of /// optimisations to run automatically. - static void addGlobalExtension(ExtensionPointTy Ty, ExtensionFn Fn); + static void addGlobalExtension(ExtensionPointTy Ty, ExtensionProc Fn); void addExtension(ExtensionPointTy Ty, ExtensionFn Fn); private: @@ -208,10 +209,12 @@ /// used by optimizer plugins to allow all front ends to transparently use /// them. Create a static instance of this class in your plugin, providing a /// private function that the PassManagerBuilder can use to add your passes. +/// Currently limited to real functions to avoid crashes when used within the +/// main executable before a loaded plugin has a chance to use this. struct RegisterStandardPasses { RegisterStandardPasses(PassManagerBuilder::ExtensionPointTy Ty, - PassManagerBuilder::ExtensionFn Fn) { - PassManagerBuilder::addGlobalExtension(Ty, std::move(Fn)); + PassManagerBuilder::ExtensionProc Fn) { + PassManagerBuilder::addGlobalExtension(Ty, Fn); } }; Index: lib/Transforms/IPO/PassManagerBuilder.cpp =================================================================== --- lib/Transforms/IPO/PassManagerBuilder.cpp +++ lib/Transforms/IPO/PassManagerBuilder.cpp @@ -198,10 +198,9 @@ static ManagedStatic, 8> > GlobalExtensions; -void PassManagerBuilder::addGlobalExtension( - PassManagerBuilder::ExtensionPointTy Ty, - PassManagerBuilder::ExtensionFn Fn) { - GlobalExtensions->push_back(std::make_pair(Ty, std::move(Fn))); +void PassManagerBuilder::addGlobalExtension(ExtensionPointTy Ty, + ExtensionProc Fn) { + GlobalExtensions->push_back(std::make_pair(Ty, Fn)); } void PassManagerBuilder::addExtension(ExtensionPointTy Ty, ExtensionFn 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_library(DynamicLibraryLib STATIC ExportedFuncs.cxx) @@ -6,21 +6,37 @@ target_link_libraries(DynamicLibraryTests DynamicLibraryLib) export_executable_symbols(DynamicLibraryTests) -function(dynlib_add_module NAME) - add_library(${NAME} SHARED PipSqueak.cxx) +if ( LLVM_INCLUDE_TESTS ) - set_output_directory(${NAME} - BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} - LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} - ) + function(dynlib_add_module NAME) + add_library(${NAME} SHARED PipSqueak.cxx) - set_target_properties(${NAME} - PROPERTIES PREFIX "" - SUFFIX ".so" - ) + set_output_directory(${NAME} + BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} + LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} + ) - add_dependencies(DynamicLibraryTests ${NAME}) -endfunction(dynlib_add_module) + set_target_properties(${NAME} + PROPERTIES PREFIX "" + SUFFIX ".so" + ) -dynlib_add_module(PipSqueak) -dynlib_add_module(SecondLib) + add_dependencies(DynamicLibraryTests ${NAME}) + endfunction(dynlib_add_module) + + dynlib_add_module(PipSqueak) + target_compile_definitions(PipSqueak PRIVATE LLVM_DYLIB_PASSREG_TEST) + add_dependencies(PipSqueak LLVMipo) + if ( BUILD_SHARED_LIBS ) + # Broken in Debug mode when building static libraries + target_compile_definitions(PipSqueak PRIVATE LLVM_DYLIB_PASSREG_TEST_2) + if ( LLVM_LINK_LLVM_DYLIB ) + target_link_libraries(PipSqueak LLVM) + else () + target_link_libraries(PipSqueak LLVMipo) + endif () + endif ( BUILD_SHARED_LIBS ) + + dynlib_add_module(SecondLib) + +endif( LLVM_INCLUDE_TESTS ) 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" @@ -52,6 +53,28 @@ return Tmp.P; } +static void +NoPassRegistration(const PassManagerBuilder &, legacy::PassManagerBase &) { +} + +static RegisterStandardPasses LocalPass(PassManagerBuilder::EP_LoopOptimizerEnd, + NoPassRegistration); + +typedef void (*TestPassReg)(void (*)(PassManagerBuilder::ExtensionPointTy, + PassManagerBuilder::ExtensionProc)); + +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 @@ -9,6 +9,30 @@ #include "PipSqueak.h" +#define PIPSQUEAK_TESTA_RETURN "LibCall" +#include "ExportedFuncs.cxx" + +#ifdef LLVM_DYLIB_PASSREG_TEST +#include "llvm/Transforms/IPO/PassManagerBuilder.h" +using namespace llvm; + +static void LibPassRegistration(const PassManagerBuilder &, + legacy::PassManagerBase &) {} + +extern "C" PIPSQUEAK_EXPORT void TestPassReg( + void (*addGlobalExtension)(PassManagerBuilder::ExtensionPointTy, + PassManagerBuilder::ExtensionProc)) { + addGlobalExtension(PassManagerBuilder::EP_EarlyAsPossible, + LibPassRegistration); +} + +#ifdef LLVM_DYLIB_PASSREG_TEST_2 +// FIXME: Broken in Debug mode when building static libraries +static RegisterStandardPasses sLocalPass(PassManagerBuilder::EP_EarlyAsPossible, + LibPassRegistration); +#endif // LLVM_DYLIB_PASSREG_TEST_2 +#endif // LLVM_DYLIB_PASSREG_TEST + struct Global { std::string *Str; std::vector *Vec; @@ -44,6 +68,3 @@ extern "C" PIPSQUEAK_EXPORT void TestOrder(std::vector &V) { Glb.Vec = &V; } - -#define PIPSQUEAK_TESTA_RETURN "LibCall" -#include "ExportedFuncs.cxx"