diff --git a/llvm/tools/llvm-shlib/CMakeLists.txt b/llvm/tools/llvm-shlib/CMakeLists.txt --- a/llvm/tools/llvm-shlib/CMakeLists.txt +++ b/llvm/tools/llvm-shlib/CMakeLists.txt @@ -15,6 +15,10 @@ message(FATAL_ERROR "Generating libLLVM is not supported on MSVC") endif() + if (LLVM_LINK_LLVM_DYLIB) + set(INSTALL_WITH_TOOLCHAIN INSTALL_WITH_TOOLCHAIN) + endif() + llvm_map_components_to_libnames(LIB_NAMES ${LLVM_DYLIB_COMPONENTS}) # Exclude libLLVMTableGen for the following reasons: @@ -22,16 +26,30 @@ # - it pollutes the global options space. list(REMOVE_ITEM LIB_NAMES "LLVMTableGen") + foreach(target ${LLVM_TARGETS_TO_BUILD}) + get_property(target_link_components TARGET ${target} PROPERTY LLVM_LINK_COMPONENTS) + set(objects "") + foreach(component ${target_link_components}) + list(REMOVE_ITEM LIB_NAMES "LLVM${component}") + list(APPEND objects "$") + endforeach() + add_llvm_library("LLVM${target}Backend" + MODULE + DISABLE_LLVM_LINK_LLVM_DYLIB + ${INSTALL_WITH_TOOLCHAIN} + OBJLIBS ${objects}) + + endforeach() + if(LLVM_DYLIB_EXPORTED_SYMBOL_FILE) set(LLVM_EXPORTED_SYMBOL_FILE ${LLVM_DYLIB_EXPORTED_SYMBOL_FILE}) add_custom_target(libLLVMExports DEPENDS ${LLVM_EXPORTED_SYMBOL_FILE}) endif() - if (LLVM_LINK_LLVM_DYLIB) - set(INSTALL_WITH_TOOLCHAIN INSTALL_WITH_TOOLCHAIN) - endif() add_llvm_library(LLVM SHARED DISABLE_LLVM_LINK_LLVM_DYLIB SONAME ${INSTALL_WITH_TOOLCHAIN} ${SOURCES}) + target_compile_definitions(LLVM PRIVATE "LLVM_BUILD_BACKEND_MODULE") + list(REMOVE_DUPLICATES LIB_NAMES) if(("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") OR (MINGW) OR (HAIKU) OR ("${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD") @@ -55,6 +73,9 @@ endif() target_link_libraries(LLVM PRIVATE ${LIB_NAMES}) + foreach(target ${LLVM_TARGETS_TO_BUILD}) + add_dependencies(LLVM LLVM${target}Backend) + endforeach() if (APPLE) set_property(TARGET LLVM APPEND_STRING PROPERTY diff --git a/llvm/tools/llvm-shlib/libllvm.cpp b/llvm/tools/llvm-shlib/libllvm.cpp --- a/llvm/tools/llvm-shlib/libllvm.cpp +++ b/llvm/tools/llvm-shlib/libllvm.cpp @@ -6,7 +6,53 @@ // //===----------------------------------------------------------------------===// // -// This file is empty and serves only the purpose of making CMake happy because -// you can't define a target with no sources. // //===----------------------------------------------------------------------===// + +#ifdef LLVM_BUILD_BACKEND_MODULE + +#include +#include + +static void * LoadBackendModule(const char *Target) { + char SharedObjectName[100]; + void *Handle; + + snprintf(SharedObjectName, 100, "LLVM%sBackend.so", Target); + Handle = dlopen(SharedObjectName, RTLD_LAZY | RTLD_NOLOAD); + if (!Handle) { + Handle = dlopen(SharedObjectName, RTLD_LAZY); + } + + return Handle; +} + +extern "C" { + +// FIXME: Can we do some error handling here? +#define LLVM_INIT_FUNC(TargetName, Component) \ + void LLVMInitialize##TargetName##Component(void) { \ + void *Handle = LoadBackendModule(#TargetName); \ + if (!Handle) \ + return; \ + void (*InitFunc)(void) = (void (*)())(dlsym(Handle, "LLVMInitialize"#TargetName #Component)); \ + if (!InitFunc) { \ + return; \ + } \ + InitFunc(); \ + } + + +#define LLVM_TARGET(TargetName) \ + LLVM_INIT_FUNC(TargetName, Target) \ + LLVM_INIT_FUNC(TargetName, TargetInfo) \ + LLVM_INIT_FUNC(TargetName, TargetMC) \ + LLVM_INIT_FUNC(TargetName, AsmParser) \ + LLVM_INIT_FUNC(TargetName, AsmPrinter) \ + LLVM_INIT_FUNC(TargetName, Disassembler) +#include "llvm/Config/Targets.def" +#undef LLVM_TARGET + +} + +#endif