diff --git a/llvm/include/llvm/Support/DynamicLibrary.h b/llvm/include/llvm/Support/DynamicLibrary.h --- a/llvm/include/llvm/Support/DynamicLibrary.h +++ b/llvm/include/llvm/Support/DynamicLibrary.h @@ -123,6 +123,10 @@ /// Add searchable symbol/value pair. static void AddSymbol(StringRef symbolName, void *symbolValue); + /// Ensure the underlying library registry is properly constructed. + /// This is only useful to force ManagedStatic registration ordering. + static void ensureConstructed(); + class HandleSet; }; diff --git a/llvm/lib/Support/DynamicLibrary.cpp b/llvm/lib/Support/DynamicLibrary.cpp --- a/llvm/lib/Support/DynamicLibrary.cpp +++ b/llvm/lib/Support/DynamicLibrary.cpp @@ -145,6 +145,8 @@ (*ExplicitSymbols)[SymbolName] = SymbolValue; } +void DynamicLibrary::ensureConstructed() { (void)*OpenedHandles; } + DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *FileName, std::string *Err) { // Force OpenedHandles to be added into the ManagedStatic list before any diff --git a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp --- a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp +++ b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp @@ -27,6 +27,7 @@ #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Verifier.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h" #include "llvm/Transforms/IPO.h" @@ -194,12 +195,20 @@ /// Since GlobalExtensions is a managed static, calling 'empty()' will trigger /// the construction of the object. static bool GlobalExtensionsNotEmpty() { + // Dynamic library static registry **must** be initialized before global + // extension registry, because global extension may reference functions from + // dynamically opened libraries. Failing to ensure that order (randomly) + // triggers a segfault upon destruction, if the dynamically loaded library is + // closed before the global extensions are destroyed. + sys::DynamicLibrary::ensureConstructed(); return GlobalExtensions.isConstructed() && !GlobalExtensions->empty(); } void PassManagerBuilder::addGlobalExtension( PassManagerBuilder::ExtensionPointTy Ty, PassManagerBuilder::ExtensionFn Fn) { + // See comment in GlobalExtensionsNotEmpty + sys::DynamicLibrary::ensureConstructed(); GlobalExtensions->push_back(std::make_pair(Ty, std::move(Fn))); } diff --git a/llvm/test/Feature/load_extension.ll b/llvm/test/Feature/load_extension.ll --- a/llvm/test/Feature/load_extension.ll +++ b/llvm/test/Feature/load_extension.ll @@ -1,8 +1,5 @@ -; This is currently failing on multiple platforms. Disable while investigation occurs. -; XFAIL: * - ; RUN: opt %s %loadbye -goodbye -wave-goodbye -disable-output 2>&1 | FileCheck %s -; REQUIRES: plugins, examples +; REQUIRES: plugins ; CHECK: Bye @junk = global i32 0