Author: Joseph Huber Date: 2024-05-09T07:05:23-05:00 New Revision: e5e66073c3d404f4dedf1b0be160b7815ccf8903
URL: https://github.com/llvm/llvm-project/commit/e5e66073c3d404f4dedf1b0be160b7815ccf8903 DIFF: https://github.com/llvm/llvm-project/commit/e5e66073c3d404f4dedf1b0be160b7815ccf8903.diff LOG: Revert "[Libomptarget] Statically link all plugin runtimes (#87009)" Caused failures on build-bots, reverting to investigate. This reverts commit 80f9e814ec896fdc57ee84afad8ac4cb1f8e4627. Added: Modified: clang/test/Driver/linker-wrapper-image.c llvm/lib/Frontend/Offloading/OffloadWrapper.cpp offload/include/PluginManager.h offload/include/device.h offload/plugins-nextgen/CMakeLists.txt offload/plugins-nextgen/amdgpu/CMakeLists.txt offload/plugins-nextgen/amdgpu/src/rtl.cpp offload/plugins-nextgen/common/CMakeLists.txt offload/plugins-nextgen/common/include/PluginInterface.h offload/plugins-nextgen/common/include/Utils/ELF.h offload/plugins-nextgen/common/src/JIT.cpp offload/plugins-nextgen/common/src/PluginInterface.cpp offload/plugins-nextgen/cuda/CMakeLists.txt offload/plugins-nextgen/cuda/src/rtl.cpp offload/plugins-nextgen/host/CMakeLists.txt offload/plugins-nextgen/host/src/rtl.cpp offload/src/CMakeLists.txt offload/src/OffloadRTL.cpp offload/src/OpenMP/InteropAPI.cpp offload/src/PluginManager.cpp offload/src/device.cpp offload/src/interface.cpp offload/tools/kernelreplay/llvm-omp-kernel-replay.cpp offload/unittests/Plugins/NextgenPluginsTest.cpp Removed: ################################################################################ diff --git a/clang/test/Driver/linker-wrapper-image.c b/clang/test/Driver/linker-wrapper-image.c index 5d5d62805e174..d01445e3aed04 100644 --- a/clang/test/Driver/linker-wrapper-image.c +++ b/clang/test/Driver/linker-wrapper-image.c @@ -30,8 +30,8 @@ // OPENMP: define internal void @.omp_offloading.descriptor_reg() section ".text.startup" { // OPENMP-NEXT: entry: -// OPENMP-NEXT: call void @__tgt_register_lib(ptr @.omp_offloading.descriptor) // OPENMP-NEXT: %0 = call i32 @atexit(ptr @.omp_offloading.descriptor_unreg) +// OPENMP-NEXT: call void @__tgt_register_lib(ptr @.omp_offloading.descriptor) // OPENMP-NEXT: ret void // OPENMP-NEXT: } diff --git a/llvm/lib/Frontend/Offloading/OffloadWrapper.cpp b/llvm/lib/Frontend/Offloading/OffloadWrapper.cpp index 8b6f9ea1f4cca..7241d15ed1c67 100644 --- a/llvm/lib/Frontend/Offloading/OffloadWrapper.cpp +++ b/llvm/lib/Frontend/Offloading/OffloadWrapper.cpp @@ -232,13 +232,12 @@ void createRegisterFunction(Module &M, GlobalVariable *BinDesc, // Construct function body IRBuilder<> Builder(BasicBlock::Create(C, "entry", Func)); - Builder.CreateCall(RegFuncC, BinDesc); - // Register the destructors with 'atexit'. This is expected by the CUDA // runtime and ensures that we clean up before dynamic objects are destroyed. - // This needs to be done after plugin initialization to ensure that it is - // called before the plugin runtime is destroyed. + // This needs to be done before the runtime is called and registers its own. Builder.CreateCall(AtExit, UnregFunc); + + Builder.CreateCall(RegFuncC, BinDesc); Builder.CreateRetVoid(); // Add this function to constructors. diff --git a/offload/include/PluginManager.h b/offload/include/PluginManager.h index 1d6804da75d92..eece7525e25e7 100644 --- a/offload/include/PluginManager.h +++ b/offload/include/PluginManager.h @@ -13,11 +13,10 @@ #ifndef OMPTARGET_PLUGIN_MANAGER_H #define OMPTARGET_PLUGIN_MANAGER_H -#include "PluginInterface.h" - #include "DeviceImage.h" #include "ExclusiveAccess.h" #include "Shared/APITypes.h" +#include "Shared/PluginAPI.h" #include "Shared/Requirements.h" #include "device.h" @@ -35,7 +34,38 @@ #include <mutex> #include <string> -using GenericPluginTy = llvm::omp::target::plugin::GenericPluginTy; +struct PluginManager; + +/// Plugin adaptors should be created via `PluginAdaptorTy::create` which will +/// invoke the constructor and call `PluginAdaptorTy::init`. Eventual errors are +/// reported back to the caller, otherwise a valid and initialized adaptor is +/// returned. +struct PluginAdaptorTy { + /// Try to create a plugin adaptor from a filename. + static llvm::Expected<std::unique_ptr<PluginAdaptorTy>> + create(const std::string &Name); + + /// Name of the shared object file representing the plugin. + std::string Name; + + /// Access to the shared object file representing the plugin. + std::unique_ptr<llvm::sys::DynamicLibrary> LibraryHandler; + +#define PLUGIN_API_HANDLE(NAME) \ + using NAME##_ty = decltype(__tgt_rtl_##NAME); \ + NAME##_ty *NAME = nullptr; + +#include "Shared/PluginAPI.inc" +#undef PLUGIN_API_HANDLE + + /// Create a plugin adaptor for filename \p Name with a dynamic library \p DL. + PluginAdaptorTy(const std::string &Name, + std::unique_ptr<llvm::sys::DynamicLibrary> DL); + + /// Initialize the plugin adaptor, this can fail in which case the adaptor is + /// useless. + llvm::Error init(); +}; /// Struct for the data required to handle plugins struct PluginManager { @@ -50,8 +80,6 @@ struct PluginManager { void init(); - void deinit(); - // Register a shared library with all (compatible) RTLs. void registerLib(__tgt_bin_desc *Desc); @@ -64,9 +92,10 @@ struct PluginManager { std::make_unique<DeviceImageTy>(TgtBinDesc, TgtDeviceImage)); } - /// Initialize as many devices as possible for this plugin. Devices that fail - /// to initialize are ignored. - void initDevices(GenericPluginTy &RTL); + /// Initialize as many devices as possible for this plugin adaptor. Devices + /// that fail to initialize are ignored. Returns the offset the devices were + /// registered at. + void initDevices(PluginAdaptorTy &RTL); /// Return the device presented to the user as device \p DeviceNo if it is /// initialized and ready. Otherwise return an error explaining the problem. @@ -122,8 +151,8 @@ struct PluginManager { // Initialize all plugins. void initAllPlugins(); - /// Iterator range for all plugins (in use or not, but always valid). - auto plugins() { return llvm::make_pointee_range(Plugins); } + /// Iterator range for all plugin adaptors (in use or not, but always valid). + auto pluginAdaptors() { return llvm::make_pointee_range(PluginAdaptors); } /// Return the user provided requirements. int64_t getRequirements() const { return Requirements.getRequirements(); } @@ -135,14 +164,14 @@ struct PluginManager { bool RTLsLoaded = false; llvm::SmallVector<__tgt_bin_desc *> DelayedBinDesc; - // List of all plugins, in use or not. - llvm::SmallVector<std::unique_ptr<GenericPluginTy>> Plugins; + // List of all plugin adaptors, in use or not. + llvm::SmallVector<std::unique_ptr<PluginAdaptorTy>> PluginAdaptors; - // Mapping of plugins to offsets in the device table. - llvm::DenseMap<const GenericPluginTy *, int32_t> DeviceOffsets; + // Mapping of plugin adaptors to offsets in the device table. + llvm::DenseMap<const PluginAdaptorTy *, int32_t> DeviceOffsets; - // Mapping of plugins to the number of used devices. - llvm::DenseMap<const GenericPluginTy *, int32_t> DeviceUsed; + // Mapping of plugin adaptors to the number of used devices. + llvm::DenseMap<const PluginAdaptorTy *, int32_t> DeviceUsed; // Set of all device images currently in use. llvm::DenseSet<const __tgt_device_image *> UsedImages; diff --git a/offload/include/device.h b/offload/include/device.h index fd6e5fba5fc53..bd2829722bb32 100644 --- a/offload/include/device.h +++ b/offload/include/device.h @@ -33,19 +33,17 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" -#include "PluginInterface.h" -using GenericPluginTy = llvm::omp::target::plugin::GenericPluginTy; - // Forward declarations. +struct PluginAdaptorTy; struct __tgt_bin_desc; struct __tgt_target_table; struct DeviceTy { int32_t DeviceID; - GenericPluginTy *RTL; + PluginAdaptorTy *RTL; int32_t RTLDeviceID; - DeviceTy(GenericPluginTy *RTL, int32_t DeviceID, int32_t RTLDeviceID); + DeviceTy(PluginAdaptorTy *RTL, int32_t DeviceID, int32_t RTLDeviceID); // DeviceTy is not copyable DeviceTy(const DeviceTy &D) = delete; DeviceTy &operator=(const DeviceTy &D) = delete; diff --git a/offload/plugins-nextgen/CMakeLists.txt b/offload/plugins-nextgen/CMakeLists.txt index d1079f8a3e9cc..df625e97c7ebf 100644 --- a/offload/plugins-nextgen/CMakeLists.txt +++ b/offload/plugins-nextgen/CMakeLists.txt @@ -14,7 +14,7 @@ set(common_dir ${CMAKE_CURRENT_SOURCE_DIR}/common) add_subdirectory(common) function(add_target_library target_name lib_name) - add_llvm_library(${target_name} STATIC + add_llvm_library(${target_name} SHARED LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} AggressiveInstCombine @@ -46,14 +46,27 @@ function(add_target_library target_name lib_name) ) llvm_update_compile_flags(${target_name}) - target_include_directories(${target_name} PUBLIC ${common_dir}/include) target_link_libraries(${target_name} PRIVATE PluginCommon ${OPENMP_PTHREAD_LIB}) target_compile_definitions(${target_name} PRIVATE TARGET_NAME=${lib_name}) target_compile_definitions(${target_name} PRIVATE DEBUG_PREFIX="TARGET ${lib_name} RTL") - set_target_properties(${target_name} PROPERTIES POSITION_INDEPENDENT_CODE ON) + + if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + # On FreeBSD, the 'environ' symbol is undefined at link time, but resolved by + # the dynamic linker at runtime. Therefore, allow the symbol to be undefined + # when creating a shared library. + target_link_libraries(${target_name} PRIVATE "-Wl,--allow-shlib-undefined") + else() + target_link_libraries(${target_name} PRIVATE "-Wl,-z,defs") + endif() + + if(LIBOMP_HAVE_VERSION_SCRIPT_FLAG) + target_link_libraries(${target_name} PRIVATE + "-Wl,--version-script=${common_dir}/../exports") + endif() + set_target_properties(${target_name} PROPERTIES CXX_VISIBILITY_PRESET protected) endfunction() foreach(plugin IN LISTS LIBOMPTARGET_PLUGINS_TO_BUILD) diff --git a/offload/plugins-nextgen/amdgpu/CMakeLists.txt b/offload/plugins-nextgen/amdgpu/CMakeLists.txt index 738183f8945ed..f5f7096137c20 100644 --- a/offload/plugins-nextgen/amdgpu/CMakeLists.txt +++ b/offload/plugins-nextgen/amdgpu/CMakeLists.txt @@ -57,3 +57,8 @@ else() libomptarget_say("Not generating AMDGPU tests, no supported devices detected." " Use 'LIBOMPTARGET_FORCE_AMDGPU_TESTS' to override.") endif() + +# Install plugin under the lib destination folder. +install(TARGETS omptarget.rtl.amdgpu LIBRARY DESTINATION "${OFFLOAD_INSTALL_LIBDIR}") +set_target_properties(omptarget.rtl.amdgpu PROPERTIES + INSTALL_RPATH "$ORIGIN" BUILD_RPATH "$ORIGIN:${CMAKE_CURRENT_BINARY_DIR}/..") diff --git a/offload/plugins-nextgen/amdgpu/src/rtl.cpp b/offload/plugins-nextgen/amdgpu/src/rtl.cpp index 295685fceaa43..00650b801b420 100644 --- a/offload/plugins-nextgen/amdgpu/src/rtl.cpp +++ b/offload/plugins-nextgen/amdgpu/src/rtl.cpp @@ -3064,6 +3064,10 @@ struct AMDGPUPluginTy final : public GenericPluginTy { // HSA functions from now on, e.g., hsa_shut_down. Initialized = true; +#ifdef OMPT_SUPPORT + ompt::connectLibrary(); +#endif + // Register event handler to detect memory errors on the devices. Status = hsa_amd_register_system_event_handler(eventHandler, nullptr); if (auto Err = Plugin::check( @@ -3151,8 +3155,6 @@ struct AMDGPUPluginTy final : public GenericPluginTy { Triple::ArchType getTripleArch() const override { return Triple::amdgcn; } - const char *getName() const override { return GETNAME(TARGET_NAME); } - /// Get the ELF code for recognizing the compatible image binary. uint16_t getMagicElfBits() const override { return ELF::EM_AMDGPU; } @@ -3385,6 +3387,8 @@ Error AMDGPUKernelTy::printLaunchInfoDetails(GenericDeviceTy &GenericDevice, return Plugin::success(); } +GenericPluginTy *PluginTy::createPlugin() { return new AMDGPUPluginTy(); } + template <typename... ArgsTy> static Error Plugin::check(int32_t Code, const char *ErrFmt, ArgsTy... Args) { hsa_status_t ResultCode = static_cast<hsa_status_t>(Code); @@ -3472,9 +3476,3 @@ void *AMDGPUDeviceTy::allocate(size_t Size, void *, TargetAllocTy Kind) { } // namespace target } // namespace omp } // namespace llvm - -extern "C" { -llvm::omp::target::plugin::GenericPluginTy *createPlugin_amdgpu() { - return new llvm::omp::target::plugin::AMDGPUPluginTy(); -} -} diff --git a/offload/plugins-nextgen/common/CMakeLists.txt b/offload/plugins-nextgen/common/CMakeLists.txt index a6bbb7e9454bd..acf0af63f0508 100644 --- a/offload/plugins-nextgen/common/CMakeLists.txt +++ b/offload/plugins-nextgen/common/CMakeLists.txt @@ -46,6 +46,7 @@ endif() # If we have OMPT enabled include it in the list of sources. if (OMPT_TARGET_DEFAULT AND LIBOMPTARGET_OMPT_SUPPORT) + target_sources(PluginCommon PRIVATE OMPT/OmptCallback.cpp) target_include_directories(PluginCommon PRIVATE OMPT) endif() @@ -65,4 +66,6 @@ target_include_directories(PluginCommon PUBLIC ${LIBOMPTARGET_INCLUDE_DIR} ) -set_target_properties(PluginCommon PROPERTIES POSITION_INDEPENDENT_CODE ON) +set_target_properties(PluginCommon PROPERTIES + POSITION_INDEPENDENT_CODE ON + CXX_VISIBILITY_PRESET protected) diff --git a/offload/plugins-nextgen/common/include/PluginInterface.h b/offload/plugins-nextgen/common/include/PluginInterface.h index e7a008f3a8573..79e8464bfda5c 100644 --- a/offload/plugins-nextgen/common/include/PluginInterface.h +++ b/offload/plugins-nextgen/common/include/PluginInterface.h @@ -1010,9 +1010,6 @@ struct GenericPluginTy { /// Get the target triple of this plugin. virtual Triple::ArchType getTripleArch() const = 0; - /// Get the constant name identifier for this plugin. - virtual const char *getName() const = 0; - /// Allocate a structure using the internal allocator. template <typename Ty> Ty *allocate() { return reinterpret_cast<Ty *>(Allocator.Allocate(sizeof(Ty), alignof(Ty))); @@ -1229,7 +1226,7 @@ namespace Plugin { /// Create a success error. This is the same as calling Error::success(), but /// it is recommended to use this one for consistency with Plugin::error() and /// Plugin::check(). -static inline Error success() { return Error::success(); } +static Error success() { return Error::success(); } /// Create a string error. template <typename... ArgsTy> @@ -1249,6 +1246,95 @@ template <typename... ArgsTy> static Error check(int32_t ErrorCode, const char *ErrFmt, ArgsTy... Args); } // namespace Plugin +/// Class for simplifying the getter operation of the plugin. Anywhere on the +/// code, the current plugin can be retrieved by Plugin::get(). The class also +/// declares functions to create plugin-specific object instances. The check(), +/// createPlugin(), createDevice() and createGlobalHandler() functions should be +/// defined by each plugin implementation. +class PluginTy { + // Reference to the plugin instance. + static GenericPluginTy *SpecificPlugin; + + PluginTy() { + if (auto Err = init()) + REPORT("Failed to initialize plugin: %s\n", + toString(std::move(Err)).data()); + } + + ~PluginTy() { + if (auto Err = deinit()) + REPORT("Failed to deinitialize plugin: %s\n", + toString(std::move(Err)).data()); + } + + PluginTy(const PluginTy &) = delete; + void operator=(const PluginTy &) = delete; + + /// Create and intialize the plugin instance. + static Error init() { + assert(!SpecificPlugin && "Plugin already created"); + + // Create the specific plugin. + SpecificPlugin = createPlugin(); + assert(SpecificPlugin && "Plugin was not created"); + + // Initialize the plugin. + return SpecificPlugin->init(); + } + + // Deinitialize and destroy the plugin instance. + static Error deinit() { + assert(SpecificPlugin && "Plugin no longer valid"); + + for (int32_t DevNo = 0, NumDev = SpecificPlugin->getNumDevices(); + DevNo < NumDev; ++DevNo) + if (auto Err = SpecificPlugin->deinitDevice(DevNo)) + return Err; + + // Deinitialize the plugin. + if (auto Err = SpecificPlugin->deinit()) + return Err; + + // Delete the plugin instance. + delete SpecificPlugin; + + // Invalidate the plugin reference. + SpecificPlugin = nullptr; + + return Plugin::success(); + } + +public: + /// Initialize the plugin if needed. The plugin could have been initialized by + /// a previous call to Plugin::get(). + static Error initIfNeeded() { + // Trigger the initialization if needed. + get(); + + return Error::success(); + } + + /// Get a reference (or create if it was not created) to the plugin instance. + static GenericPluginTy &get() { + // This static variable will initialize the underlying plugin instance in + // case there was no previous explicit initialization. The initialization is + // thread safe. + static PluginTy Plugin; + + assert(SpecificPlugin && "Plugin is not active"); + return *SpecificPlugin; + } + + /// Get a reference to the plugin with a specific plugin-specific type. + template <typename Ty> static Ty &get() { return static_cast<Ty &>(get()); } + + /// Indicate whether the plugin is active. + static bool isActive() { return SpecificPlugin != nullptr; } + + /// Create a plugin instance. + static GenericPluginTy *createPlugin(); +}; + /// Auxiliary interface class for GenericDeviceResourceManagerTy. This class /// acts as a reference to a device resource, such as a stream, and requires /// some basic functions to be implemented. The derived class should define an diff --git a/offload/plugins-nextgen/common/include/Utils/ELF.h b/offload/plugins-nextgen/common/include/Utils/ELF.h index dcfdb5bd7b035..f87e0a5ed02b4 100644 --- a/offload/plugins-nextgen/common/include/Utils/ELF.h +++ b/offload/plugins-nextgen/common/include/Utils/ELF.h @@ -13,6 +13,8 @@ #ifndef LLVM_OPENMP_LIBOMPTARGET_PLUGINS_ELF_UTILS_H #define LLVM_OPENMP_LIBOMPTARGET_PLUGINS_ELF_UTILS_H +#include "Shared/PluginAPI.h" + #include "llvm/Object/ELF.h" #include "llvm/Object/ELFObjectFile.h" diff --git a/offload/plugins-nextgen/common/src/JIT.cpp b/offload/plugins-nextgen/common/src/JIT.cpp index 9d58e6060646b..9eb610cab4de6 100644 --- a/offload/plugins-nextgen/common/src/JIT.cpp +++ b/offload/plugins-nextgen/common/src/JIT.cpp @@ -56,6 +56,28 @@ bool isImageBitcode(const __tgt_device_image &Image) { return identify_magic(Binary) == file_magic::bitcode; } +std::once_flag InitFlag; + +void init(Triple TT) { + codegen::RegisterCodeGenFlags(); +#ifdef LIBOMPTARGET_JIT_NVPTX + if (TT.isNVPTX()) { + LLVMInitializeNVPTXTargetInfo(); + LLVMInitializeNVPTXTarget(); + LLVMInitializeNVPTXTargetMC(); + LLVMInitializeNVPTXAsmPrinter(); + } +#endif +#ifdef LIBOMPTARGET_JIT_AMDGPU + if (TT.isAMDGPU()) { + LLVMInitializeAMDGPUTargetInfo(); + LLVMInitializeAMDGPUTarget(); + LLVMInitializeAMDGPUTargetMC(); + LLVMInitializeAMDGPUAsmPrinter(); + } +#endif +} + Expected<std::unique_ptr<Module>> createModuleFromMemoryBuffer(std::unique_ptr<MemoryBuffer> &MB, LLVMContext &Context) { @@ -126,23 +148,7 @@ createTargetMachine(Module &M, std::string CPU, unsigned OptLevel) { } // namespace JITEngine::JITEngine(Triple::ArchType TA) : TT(Triple::getArchTypeName(TA)) { - codegen::RegisterCodeGenFlags(); -#ifdef LIBOMPTARGET_JIT_NVPTX - if (TT.isNVPTX()) { - LLVMInitializeNVPTXTargetInfo(); - LLVMInitializeNVPTXTarget(); - LLVMInitializeNVPTXTargetMC(); - LLVMInitializeNVPTXAsmPrinter(); - } -#endif -#ifdef LIBOMPTARGET_JIT_AMDGPU - if (TT.isAMDGPU()) { - LLVMInitializeAMDGPUTargetInfo(); - LLVMInitializeAMDGPUTarget(); - LLVMInitializeAMDGPUTargetMC(); - LLVMInitializeAMDGPUAsmPrinter(); - } -#endif + std::call_once(InitFlag, init, TT); } void JITEngine::opt(TargetMachine *TM, TargetLibraryInfoImpl *TLII, Module &M, diff --git a/offload/plugins-nextgen/common/src/PluginInterface.cpp b/offload/plugins-nextgen/common/src/PluginInterface.cpp index fae197527850a..8de93ba17a560 100644 --- a/offload/plugins-nextgen/common/src/PluginInterface.cpp +++ b/offload/plugins-nextgen/common/src/PluginInterface.cpp @@ -13,6 +13,7 @@ #include "Shared/APITypes.h" #include "Shared/Debug.h" #include "Shared/Environment.h" +#include "Shared/PluginAPI.h" #include "GlobalHandler.h" #include "JIT.h" @@ -38,6 +39,8 @@ using namespace omp; using namespace target; using namespace plugin; +GenericPluginTy *PluginTy::SpecificPlugin = nullptr; + // TODO: Fix any thread safety issues for multi-threaded kernel recording. struct RecordReplayTy { @@ -2032,3 +2035,205 @@ bool llvm::omp::target::plugin::libomptargetSupportsRPC() { return false; #endif } + +/// Exposed library API function, basically wrappers around the GenericDeviceTy +/// functionality with the same name. All non-async functions are redirected +/// to the async versions right away with a NULL AsyncInfoPtr. +#ifdef __cplusplus +extern "C" { +#endif + +int32_t __tgt_rtl_init_plugin() { + auto Err = PluginTy::initIfNeeded(); + if (Err) { + [[maybe_unused]] std::string ErrStr = toString(std::move(Err)); + DP("Failed to init plugin: %s", ErrStr.c_str()); + return OFFLOAD_FAIL; + } + + return OFFLOAD_SUCCESS; +} + +int32_t __tgt_rtl_is_valid_binary(__tgt_device_image *Image) { + if (!PluginTy::isActive()) + return false; + + return PluginTy::get().is_valid_binary(Image); +} + +int32_t __tgt_rtl_init_device(int32_t DeviceId) { + return PluginTy::get().init_device(DeviceId); +} + +int32_t __tgt_rtl_number_of_devices() { + return PluginTy::get().number_of_devices(); +} + +int64_t __tgt_rtl_init_requires(int64_t RequiresFlags) { + return PluginTy::get().init_requires(RequiresFlags); +} + +int32_t __tgt_rtl_is_data_exchangable(int32_t SrcDeviceId, + int32_t DstDeviceId) { + return PluginTy::get().is_data_exchangable(SrcDeviceId, DstDeviceId); +} + +int32_t __tgt_rtl_initialize_record_replay(int32_t DeviceId, int64_t MemorySize, + void *VAddr, bool isRecord, + bool SaveOutput, + uint64_t &ReqPtrArgOffset) { + return PluginTy::get().initialize_record_replay( + DeviceId, MemorySize, VAddr, isRecord, SaveOutput, ReqPtrArgOffset); +} + +int32_t __tgt_rtl_load_binary(int32_t DeviceId, __tgt_device_image *TgtImage, + __tgt_device_binary *Binary) { + return PluginTy::get().load_binary(DeviceId, TgtImage, Binary); +} + +void *__tgt_rtl_data_alloc(int32_t DeviceId, int64_t Size, void *HostPtr, + int32_t Kind) { + return PluginTy::get().data_alloc(DeviceId, Size, HostPtr, Kind); +} + +int32_t __tgt_rtl_data_delete(int32_t DeviceId, void *TgtPtr, int32_t Kind) { + return PluginTy::get().data_delete(DeviceId, TgtPtr, Kind); +} + +int32_t __tgt_rtl_data_lock(int32_t DeviceId, void *Ptr, int64_t Size, + void **LockedPtr) { + return PluginTy::get().data_lock(DeviceId, Ptr, Size, LockedPtr); +} + +int32_t __tgt_rtl_data_unlock(int32_t DeviceId, void *Ptr) { + return PluginTy::get().data_unlock(DeviceId, Ptr); +} + +int32_t __tgt_rtl_data_notify_mapped(int32_t DeviceId, void *HstPtr, + int64_t Size) { + return PluginTy::get().data_notify_mapped(DeviceId, HstPtr, Size); +} + +int32_t __tgt_rtl_data_notify_unmapped(int32_t DeviceId, void *HstPtr) { + return PluginTy::get().data_notify_unmapped(DeviceId, HstPtr); +} + +int32_t __tgt_rtl_data_submit(int32_t DeviceId, void *TgtPtr, void *HstPtr, + int64_t Size) { + return PluginTy::get().data_submit(DeviceId, TgtPtr, HstPtr, Size); +} + +int32_t __tgt_rtl_data_submit_async(int32_t DeviceId, void *TgtPtr, + void *HstPtr, int64_t Size, + __tgt_async_info *AsyncInfoPtr) { + return PluginTy::get().data_submit_async(DeviceId, TgtPtr, HstPtr, Size, + AsyncInfoPtr); +} + +int32_t __tgt_rtl_data_retrieve(int32_t DeviceId, void *HstPtr, void *TgtPtr, + int64_t Size) { + return PluginTy::get().data_retrieve(DeviceId, HstPtr, TgtPtr, Size); +} + +int32_t __tgt_rtl_data_retrieve_async(int32_t DeviceId, void *HstPtr, + void *TgtPtr, int64_t Size, + __tgt_async_info *AsyncInfoPtr) { + return PluginTy::get().data_retrieve_async(DeviceId, HstPtr, TgtPtr, Size, + AsyncInfoPtr); +} + +int32_t __tgt_rtl_data_exchange(int32_t SrcDeviceId, void *SrcPtr, + int32_t DstDeviceId, void *DstPtr, + int64_t Size) { + return PluginTy::get().data_exchange(SrcDeviceId, SrcPtr, DstDeviceId, DstPtr, + Size); +} + +int32_t __tgt_rtl_data_exchange_async(int32_t SrcDeviceId, void *SrcPtr, + int DstDeviceId, void *DstPtr, + int64_t Size, + __tgt_async_info *AsyncInfo) { + return PluginTy::get().data_exchange_async(SrcDeviceId, SrcPtr, DstDeviceId, + DstPtr, Size, AsyncInfo); +} + +int32_t __tgt_rtl_launch_kernel(int32_t DeviceId, void *TgtEntryPtr, + void **TgtArgs, ptr diff _t *TgtOffsets, + KernelArgsTy *KernelArgs, + __tgt_async_info *AsyncInfoPtr) { + return PluginTy::get().launch_kernel(DeviceId, TgtEntryPtr, TgtArgs, + TgtOffsets, KernelArgs, AsyncInfoPtr); +} + +int32_t __tgt_rtl_synchronize(int32_t DeviceId, + __tgt_async_info *AsyncInfoPtr) { + return PluginTy::get().synchronize(DeviceId, AsyncInfoPtr); +} + +int32_t __tgt_rtl_query_async(int32_t DeviceId, + __tgt_async_info *AsyncInfoPtr) { + return PluginTy::get().query_async(DeviceId, AsyncInfoPtr); +} + +void __tgt_rtl_print_device_info(int32_t DeviceId) { + PluginTy::get().print_device_info(DeviceId); +} + +int32_t __tgt_rtl_create_event(int32_t DeviceId, void **EventPtr) { + return PluginTy::get().create_event(DeviceId, EventPtr); +} + +int32_t __tgt_rtl_record_event(int32_t DeviceId, void *EventPtr, + __tgt_async_info *AsyncInfoPtr) { + return PluginTy::get().record_event(DeviceId, EventPtr, AsyncInfoPtr); +} + +int32_t __tgt_rtl_wait_event(int32_t DeviceId, void *EventPtr, + __tgt_async_info *AsyncInfoPtr) { + return PluginTy::get().wait_event(DeviceId, EventPtr, AsyncInfoPtr); +} + +int32_t __tgt_rtl_sync_event(int32_t DeviceId, void *EventPtr) { + return PluginTy::get().sync_event(DeviceId, EventPtr); +} + +int32_t __tgt_rtl_destroy_event(int32_t DeviceId, void *EventPtr) { + return PluginTy::get().destroy_event(DeviceId, EventPtr); +} + +void __tgt_rtl_set_info_flag(uint32_t NewInfoLevel) { + return PluginTy::get().set_info_flag(NewInfoLevel); +} + +int32_t __tgt_rtl_init_async_info(int32_t DeviceId, + __tgt_async_info **AsyncInfoPtr) { + return PluginTy::get().init_async_info(DeviceId, AsyncInfoPtr); +} + +int32_t __tgt_rtl_init_device_info(int32_t DeviceId, + __tgt_device_info *DeviceInfo, + const char **ErrStr) { + return PluginTy::get().init_device_info(DeviceId, DeviceInfo, ErrStr); +} + +int32_t __tgt_rtl_set_device_offset(int32_t DeviceIdOffset) { + return PluginTy::get().set_device_offset(DeviceIdOffset); +} + +int32_t __tgt_rtl_use_auto_zero_copy(int32_t DeviceId) { + return PluginTy::get().use_auto_zero_copy(DeviceId); +} + +int32_t __tgt_rtl_get_global(__tgt_device_binary Binary, uint64_t Size, + const char *Name, void **DevicePtr) { + return PluginTy::get().get_global(Binary, Size, Name, DevicePtr); +} + +int32_t __tgt_rtl_get_function(__tgt_device_binary Binary, const char *Name, + void **KernelPtr) { + return PluginTy::get().get_function(Binary, Name, KernelPtr); +} + +#ifdef __cplusplus +} +#endif diff --git a/offload/plugins-nextgen/cuda/CMakeLists.txt b/offload/plugins-nextgen/cuda/CMakeLists.txt index dd684bb223431..0284bd22d2a4d 100644 --- a/offload/plugins-nextgen/cuda/CMakeLists.txt +++ b/offload/plugins-nextgen/cuda/CMakeLists.txt @@ -51,3 +51,8 @@ else() libomptarget_say("Not generating NVIDIA tests, no supported devices detected." " Use 'LIBOMPTARGET_FORCE_NVIDIA_TESTS' to override.") endif() + +# Install plugin under the lib destination folder. +install(TARGETS omptarget.rtl.cuda LIBRARY DESTINATION "${OFFLOAD_INSTALL_LIBDIR}") +set_target_properties(omptarget.rtl.cuda PROPERTIES + INSTALL_RPATH "$ORIGIN" BUILD_RPATH "$ORIGIN:${CMAKE_CURRENT_BINARY_DIR}/..") diff --git a/offload/plugins-nextgen/cuda/src/rtl.cpp b/offload/plugins-nextgen/cuda/src/rtl.cpp index b260334baa18b..fc74c6aa23fdd 100644 --- a/offload/plugins-nextgen/cuda/src/rtl.cpp +++ b/offload/plugins-nextgen/cuda/src/rtl.cpp @@ -1342,6 +1342,10 @@ struct CUDAPluginTy final : public GenericPluginTy { return 0; } +#ifdef OMPT_SUPPORT + ompt::connectLibrary(); +#endif + if (Res == CUDA_ERROR_NO_DEVICE) { // Do not initialize if there are no devices. DP("There are no devices supporting CUDA.\n"); @@ -1386,8 +1390,6 @@ struct CUDAPluginTy final : public GenericPluginTy { return Triple::nvptx64; } - const char *getName() const override { return GETNAME(TARGET_NAME); } - /// Check whether the image is compatible with the available CUDA devices. Expected<bool> isELFCompatible(StringRef Image) const override { auto ElfOrErr = @@ -1493,6 +1495,8 @@ Error CUDADeviceTy::dataExchangeImpl(const void *SrcPtr, return Plugin::check(Res, "Error in cuMemcpyDtoDAsync: %s"); } +GenericPluginTy *PluginTy::createPlugin() { return new CUDAPluginTy(); } + template <typename... ArgsTy> static Error Plugin::check(int32_t Code, const char *ErrFmt, ArgsTy... Args) { CUresult ResultCode = static_cast<CUresult>(Code); @@ -1512,9 +1516,3 @@ static Error Plugin::check(int32_t Code, const char *ErrFmt, ArgsTy... Args) { } // namespace target } // namespace omp } // namespace llvm - -extern "C" { -llvm::omp::target::plugin::GenericPluginTy *createPlugin_cuda() { - return new llvm::omp::target::plugin::CUDAPluginTy(); -} -} diff --git a/offload/plugins-nextgen/host/CMakeLists.txt b/offload/plugins-nextgen/host/CMakeLists.txt index 72b5681283fe2..1d000442c84d4 100644 --- a/offload/plugins-nextgen/host/CMakeLists.txt +++ b/offload/plugins-nextgen/host/CMakeLists.txt @@ -31,6 +31,14 @@ else() target_include_directories(omptarget.rtl.host PRIVATE dynamic_ffi) endif() +# Install plugin under the lib destination folder. +install(TARGETS omptarget.rtl.host + LIBRARY DESTINATION "${OFFLOAD_INSTALL_LIBDIR}") +set_target_properties(omptarget.rtl.host PROPERTIES + INSTALL_RPATH "$ORIGIN" BUILD_RPATH "$ORIGIN:${CMAKE_CURRENT_BINARY_DIR}/.." + POSITION_INDEPENDENT_CODE ON + CXX_VISIBILITY_PRESET protected) + target_include_directories(omptarget.rtl.host PRIVATE ${LIBOMPTARGET_INCLUDE_DIR}) diff --git a/offload/plugins-nextgen/host/src/rtl.cpp b/offload/plugins-nextgen/host/src/rtl.cpp index 409b44b1640ad..4bdcae3dd6a1b 100644 --- a/offload/plugins-nextgen/host/src/rtl.cpp +++ b/offload/plugins-nextgen/host/src/rtl.cpp @@ -385,6 +385,10 @@ struct GenELF64PluginTy final : public GenericPluginTy { /// Initialize the plugin and return the number of devices. Expected<int32_t> initImpl() override { +#ifdef OMPT_SUPPORT + ompt::connectLibrary(); +#endif + #ifdef USES_DYNAMIC_FFI if (auto Err = Plugin::check(ffi_init(), "Failed to initialize libffi")) return std::move(Err); @@ -441,10 +445,10 @@ struct GenELF64PluginTy final : public GenericPluginTy { return llvm::Triple::UnknownArch; #endif } - - const char *getName() const override { return GETNAME(TARGET_NAME); } }; +GenericPluginTy *PluginTy::createPlugin() { return new GenELF64PluginTy(); } + template <typename... ArgsTy> static Error Plugin::check(int32_t Code, const char *ErrMsg, ArgsTy... Args) { if (Code == 0) @@ -458,9 +462,3 @@ static Error Plugin::check(int32_t Code, const char *ErrMsg, ArgsTy... Args) { } // namespace target } // namespace omp } // namespace llvm - -extern "C" { -llvm::omp::target::plugin::GenericPluginTy *createPlugin_host() { - return new llvm::omp::target::plugin::GenELF64PluginTy(); -} -} diff --git a/offload/src/CMakeLists.txt b/offload/src/CMakeLists.txt index 8fe6d19d83eb3..eda5a85ff1ab8 100644 --- a/offload/src/CMakeLists.txt +++ b/offload/src/CMakeLists.txt @@ -65,10 +65,6 @@ target_compile_definitions(omptarget PRIVATE DEBUG_PREFIX="omptarget" ) -foreach(plugin IN LISTS LIBOMPTARGET_PLUGINS_TO_BUILD) - target_link_libraries(omptarget PRIVATE omptarget.rtl.${plugin}) -endforeach() - target_compile_options(omptarget PUBLIC ${offload_compile_flags}) target_link_options(omptarget PUBLIC ${offload_link_flags}) diff --git a/offload/src/OffloadRTL.cpp b/offload/src/OffloadRTL.cpp index 29b573a27d087..dd75b1b181505 100644 --- a/offload/src/OffloadRTL.cpp +++ b/offload/src/OffloadRTL.cpp @@ -50,7 +50,6 @@ void deinitRuntime() { if (RefCount == 1) { DP("Deinit offload library!\n"); - PM->deinit(); delete PM; PM = nullptr; } diff --git a/offload/src/OpenMP/InteropAPI.cpp b/offload/src/OpenMP/InteropAPI.cpp index bdbc440c64a2c..1a995cde7816e 100644 --- a/offload/src/OpenMP/InteropAPI.cpp +++ b/offload/src/OpenMP/InteropAPI.cpp @@ -230,14 +230,14 @@ void __tgt_interop_init(ident_t *LocRef, int32_t Gtid, } DeviceTy &Device = *DeviceOrErr; - if (!Device.RTL || + if (!Device.RTL || !Device.RTL->init_device_info || Device.RTL->init_device_info(DeviceId, &(InteropPtr)->device_info, &(InteropPtr)->err_str)) { delete InteropPtr; InteropPtr = omp_interop_none; } if (InteropType == kmp_interop_type_tasksync) { - if (!Device.RTL || + if (!Device.RTL || !Device.RTL->init_async_info || Device.RTL->init_async_info(DeviceId, &(InteropPtr)->async_info)) { delete InteropPtr; InteropPtr = omp_interop_none; diff --git a/offload/src/PluginManager.cpp b/offload/src/PluginManager.cpp index 191afa345641a..dbb556c179e58 100644 --- a/offload/src/PluginManager.cpp +++ b/offload/src/PluginManager.cpp @@ -23,25 +23,85 @@ using namespace llvm::sys; PluginManager *PM = nullptr; -// Every plugin exports this method to create an instance of the plugin type. -#define PLUGIN_TARGET(Name) extern "C" GenericPluginTy *createPlugin_##Name(); -#include "Shared/Targets.def" +Expected<std::unique_ptr<PluginAdaptorTy>> +PluginAdaptorTy::create(const std::string &Name) { + DP("Attempting to load library '%s'...\n", Name.c_str()); + TIMESCOPE_WITH_NAME_AND_IDENT(Name, (const ident_t *)nullptr); + + std::string ErrMsg; + auto LibraryHandler = std::make_unique<DynamicLibrary>( + DynamicLibrary::getPermanentLibrary(Name.c_str(), &ErrMsg)); + + if (!LibraryHandler->isValid()) { + // Library does not exist or cannot be found. + return createStringError(inconvertibleErrorCode(), + "Unable to load library '%s': %s!\n", Name.c_str(), + ErrMsg.c_str()); + } + + DP("Successfully loaded library '%s'!\n", Name.c_str()); + auto PluginAdaptor = std::unique_ptr<PluginAdaptorTy>( + new PluginAdaptorTy(Name, std::move(LibraryHandler))); + if (auto Err = PluginAdaptor->init()) + return Err; + return std::move(PluginAdaptor); +} + +PluginAdaptorTy::PluginAdaptorTy(const std::string &Name, + std::unique_ptr<llvm::sys::DynamicLibrary> DL) + : Name(Name), LibraryHandler(std::move(DL)) {} + +Error PluginAdaptorTy::init() { + +#define PLUGIN_API_HANDLE(NAME) \ + NAME = reinterpret_cast<decltype(NAME)>( \ + LibraryHandler->getAddressOfSymbol(GETNAME(__tgt_rtl_##NAME))); \ + if (!NAME) { \ + return createStringError(inconvertibleErrorCode(), \ + "Invalid plugin as necessary interface function " \ + "(%s) was not found.\n", \ + std::string(#NAME).c_str()); \ + } + +#include "Shared/PluginAPI.inc" +#undef PLUGIN_API_HANDLE + + // Remove plugin on failure to call optional init_plugin + int32_t Rc = init_plugin(); + if (Rc != OFFLOAD_SUCCESS) { + return createStringError(inconvertibleErrorCode(), + "Unable to initialize library '%s': %u!\n", + Name.c_str(), Rc); + } + + // No devices are supported by this RTL? + int32_t NumberOfPluginDevices = number_of_devices(); + if (!NumberOfPluginDevices) { + return createStringError(inconvertibleErrorCode(), + "No devices supported in this RTL\n"); + } + + DP("Registered '%s' with %d plugin visible devices!\n", Name.c_str(), + NumberOfPluginDevices); + return Error::success(); +} void PluginManager::init() { TIMESCOPE(); DP("Loading RTLs...\n"); - // Attempt to create an instance of each supported plugin. + // Attempt to open all the plugins and, if they exist, check if the interface + // is correct and if they are supporting any devices. #define PLUGIN_TARGET(Name) \ do { \ - auto Plugin = std::unique_ptr<GenericPluginTy>(createPlugin_##Name()); \ - if (auto Err = Plugin->init()) { \ - [[maybe_unused]] std::string InfoMsg = toString(std::move(Err)); \ - DP("Failed to init plugin: %s\n", InfoMsg.c_str()); \ + auto PluginAdaptorOrErr = \ + PluginAdaptorTy::create("libomptarget.rtl." #Name ".so"); \ + if (!PluginAdaptorOrErr) { \ + [[maybe_unused]] std::string InfoMsg = \ + toString(PluginAdaptorOrErr.takeError()); \ + DP("%s", InfoMsg.c_str()); \ } else { \ - DP("Registered plugin %s with %d visible device(s)\n", \ - Plugin->getName(), Plugin->number_of_devices()); \ - Plugins.emplace_back(std::move(Plugin)); \ + PluginAdaptors.push_back(std::move(*PluginAdaptorOrErr)); \ } \ } while (false); #include "Shared/Targets.def" @@ -49,29 +109,15 @@ void PluginManager::init() { DP("RTLs loaded!\n"); } -void PluginManager::deinit() { - TIMESCOPE(); - DP("Unloading RTLs...\n"); - - for (auto &Plugin : Plugins) { - if (auto Err = Plugin->deinit()) { - [[maybe_unused]] std::string InfoMsg = toString(std::move(Err)); - DP("Failed to deinit plugin: %s\n", InfoMsg.c_str()); - } - Plugin.release(); - } - - DP("RTLs unloaded!\n"); -} - -void PluginManager::initDevices(GenericPluginTy &RTL) { +void PluginManager::initDevices(PluginAdaptorTy &RTL) { // If this RTL has already been initialized. if (PM->DeviceOffsets.contains(&RTL)) return; TIMESCOPE(); // If this RTL is not already in use, initialize it. - assert(RTL.number_of_devices() > 0 && "Tried to initialize useless plugin!"); + assert(RTL.number_of_devices() > 0 && + "Tried to initialize useless plugin adaptor"); // Initialize the device information for the RTL we are about to use. auto ExclusiveDevicesAccessor = getExclusiveDevicesAccessor(); @@ -111,12 +157,13 @@ void PluginManager::initDevices(GenericPluginTy &RTL) { DeviceOffsets[&RTL] = DeviceOffset; DeviceUsed[&RTL] = NumberOfUserDevices; - DP("Plugin has index %d, exposes %d out of %d devices!\n", DeviceOffset, - NumberOfUserDevices, RTL.number_of_devices()); + DP("Plugin adaptor " DPxMOD " has index %d, exposes %d out of %d devices!\n", + DPxPTR(RTL.LibraryHandler.get()), DeviceOffset, NumberOfUserDevices, + RTL.number_of_devices()); } void PluginManager::initAllPlugins() { - for (auto &R : Plugins) + for (auto &R : PluginAdaptors) initDevices(*R); } @@ -169,22 +216,19 @@ void PluginManager::registerLib(__tgt_bin_desc *Desc) { // Obtain the image and information that was previously extracted. __tgt_device_image *Img = &DI.getExecutableImage(); - GenericPluginTy *FoundRTL = nullptr; + PluginAdaptorTy *FoundRTL = nullptr; // Scan the RTLs that have associated images until we find one that supports // the current image. - for (auto &R : PM->plugins()) { - if (!R.number_of_devices()) - continue; - + for (auto &R : PM->pluginAdaptors()) { if (!R.is_valid_binary(Img)) { DP("Image " DPxMOD " is NOT compatible with RTL %s!\n", - DPxPTR(Img->ImageStart), R.getName()); + DPxPTR(Img->ImageStart), R.Name.c_str()); continue; } DP("Image " DPxMOD " is compatible with RTL %s!\n", - DPxPTR(Img->ImageStart), R.getName()); + DPxPTR(Img->ImageStart), R.Name.c_str()); PM->initDevices(R); @@ -203,7 +247,7 @@ void PluginManager::registerLib(__tgt_bin_desc *Desc) { (PM->HostEntriesBeginToTransTable)[Desc->HostEntriesBegin]; DP("Registering image " DPxMOD " with RTL %s!\n", DPxPTR(Img->ImageStart), - R.getName()); + R.Name.c_str()); registerImageIntoTranslationTable(TransTable, PM->DeviceOffsets[&R], PM->DeviceUsed[&R], Img); @@ -238,11 +282,11 @@ void PluginManager::unregisterLib(__tgt_bin_desc *Desc) { // Obtain the image and information that was previously extracted. __tgt_device_image *Img = &DI.getExecutableImage(); - GenericPluginTy *FoundRTL = NULL; + PluginAdaptorTy *FoundRTL = NULL; // Scan the RTLs that have associated images until we find one that supports // the current image. We only need to scan RTLs that are already being used. - for (auto &R : PM->plugins()) { + for (auto &R : PM->pluginAdaptors()) { if (!DeviceOffsets.contains(&R)) continue; @@ -252,7 +296,8 @@ void PluginManager::unregisterLib(__tgt_bin_desc *Desc) { FoundRTL = &R; - DP("Unregistered image " DPxMOD " from RTL\n", DPxPTR(Img->ImageStart)); + DP("Unregistered image " DPxMOD " from RTL " DPxMOD "!\n", + DPxPTR(Img->ImageStart), DPxPTR(R.LibraryHandler.get())); break; } diff --git a/offload/src/device.cpp b/offload/src/device.cpp index 749b4c567f8e4..44a2facc8d3dd 100644 --- a/offload/src/device.cpp +++ b/offload/src/device.cpp @@ -64,7 +64,7 @@ int HostDataToTargetTy::addEventIfNecessary(DeviceTy &Device, return OFFLOAD_SUCCESS; } -DeviceTy::DeviceTy(GenericPluginTy *RTL, int32_t DeviceID, int32_t RTLDeviceID) +DeviceTy::DeviceTy(PluginAdaptorTy *RTL, int32_t DeviceID, int32_t RTLDeviceID) : DeviceID(DeviceID), RTL(RTL), RTLDeviceID(RTLDeviceID), MappingInfo(*this) {} @@ -192,6 +192,7 @@ int32_t DeviceTy::dataExchange(void *SrcPtr, DeviceTy &DstDev, void *DstPtr, RTLDeviceID, SrcPtr, DstDev.RTLDeviceID, DstPtr, Size, /*CodePtr=*/OMPT_GET_RETURN_ADDRESS);) if (!AsyncInfo) { + assert(RTL->data_exchange && "RTL->data_exchange is nullptr"); return RTL->data_exchange(RTLDeviceID, SrcPtr, DstDev.RTLDeviceID, DstPtr, Size); } diff --git a/offload/src/interface.cpp b/offload/src/interface.cpp index 763b051cc6d77..557703632c625 100644 --- a/offload/src/interface.cpp +++ b/offload/src/interface.cpp @@ -456,6 +456,8 @@ EXTERN void __tgt_set_info_flag(uint32_t NewInfoLevel) { assert(PM && "Runtime not initialized"); std::atomic<uint32_t> &InfoLevel = getInfoLevelInternal(); InfoLevel.store(NewInfoLevel); + for (auto &R : PM->pluginAdaptors()) + R.set_info_flag(NewInfoLevel); } EXTERN int __tgt_print_device_info(int64_t DeviceId) { diff --git a/offload/tools/kernelreplay/llvm-omp-kernel-replay.cpp b/offload/tools/kernelreplay/llvm-omp-kernel-replay.cpp index 1e9a6a84d8058..761e04e4c7bbd 100644 --- a/offload/tools/kernelreplay/llvm-omp-kernel-replay.cpp +++ b/offload/tools/kernelreplay/llvm-omp-kernel-replay.cpp @@ -13,6 +13,8 @@ #include "omptarget.h" +#include "Shared/PluginAPI.h" + #include "llvm/Support/CommandLine.h" #include "llvm/Support/JSON.h" #include "llvm/Support/MemoryBuffer.h" diff --git a/offload/unittests/Plugins/NextgenPluginsTest.cpp b/offload/unittests/Plugins/NextgenPluginsTest.cpp index 479b3f614aed2..635bd1637c903 100644 --- a/offload/unittests/Plugins/NextgenPluginsTest.cpp +++ b/offload/unittests/Plugins/NextgenPluginsTest.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "Shared/PluginAPI.h" #include "omptarget.h" #include "gtest/gtest.h" _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits