diff options
| author | vvvv <[email protected]> | 2024-02-06 20:01:22 +0300 |
|---|---|---|
| committer | vvvv <[email protected]> | 2024-02-06 20:22:16 +0300 |
| commit | 0203b7a9a40828bb2bd4c32029b79ff0ea3d1f8f (patch) | |
| tree | e630d0d5bd0bd29fc8c2d2842ed2cfde781b993a /contrib/libs/llvm16/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h | |
| parent | ba27db76d99d12a4f1c06960b5449423218614c4 (diff) | |
llvm16 targets
Diffstat (limited to 'contrib/libs/llvm16/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h')
| -rw-r--r-- | contrib/libs/llvm16/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/contrib/libs/llvm16/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h b/contrib/libs/llvm16/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h new file mode 100644 index 00000000000..8ecdc3140db --- /dev/null +++ b/contrib/libs/llvm16/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h @@ -0,0 +1,192 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===----------- ThreadSafeModule.h -- Layer interfaces ---------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Thread safe wrappers and utilities for Module and LLVMContext. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_THREADSAFEMODULE_H +#define LLVM_EXECUTIONENGINE_ORC_THREADSAFEMODULE_H + +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/Compiler.h" + +#include <functional> +#include <memory> +#include <mutex> + +namespace llvm { +namespace orc { + +/// An LLVMContext together with an associated mutex that can be used to lock +/// the context to prevent concurrent access by other threads. +class ThreadSafeContext { +private: + struct State { + State(std::unique_ptr<LLVMContext> Ctx) : Ctx(std::move(Ctx)) {} + + std::unique_ptr<LLVMContext> Ctx; + std::recursive_mutex Mutex; + }; + +public: + // RAII based lock for ThreadSafeContext. + class [[nodiscard]] Lock { + public: + Lock(std::shared_ptr<State> S) : S(std::move(S)), L(this->S->Mutex) {} + + private: + std::shared_ptr<State> S; + std::unique_lock<std::recursive_mutex> L; + }; + + /// Construct a null context. + ThreadSafeContext() = default; + + /// Construct a ThreadSafeContext from the given LLVMContext. + ThreadSafeContext(std::unique_ptr<LLVMContext> NewCtx) + : S(std::make_shared<State>(std::move(NewCtx))) { + assert(S->Ctx != nullptr && + "Can not construct a ThreadSafeContext from a nullptr"); + } + + /// Returns a pointer to the LLVMContext that was used to construct this + /// instance, or null if the instance was default constructed. + LLVMContext *getContext() { return S ? S->Ctx.get() : nullptr; } + + /// Returns a pointer to the LLVMContext that was used to construct this + /// instance, or null if the instance was default constructed. + const LLVMContext *getContext() const { return S ? S->Ctx.get() : nullptr; } + + Lock getLock() const { + assert(S && "Can not lock an empty ThreadSafeContext"); + return Lock(S); + } + +private: + std::shared_ptr<State> S; +}; + +/// An LLVM Module together with a shared ThreadSafeContext. +class ThreadSafeModule { +public: + /// Default construct a ThreadSafeModule. This results in a null module and + /// null context. + ThreadSafeModule() = default; + + ThreadSafeModule(ThreadSafeModule &&Other) = default; + + ThreadSafeModule &operator=(ThreadSafeModule &&Other) { + // We have to explicitly define this move operator to copy the fields in + // reverse order (i.e. module first) to ensure the dependencies are + // protected: The old module that is being overwritten must be destroyed + // *before* the context that it depends on. + // We also need to lock the context to make sure the module tear-down + // does not overlap any other work on the context. + if (M) { + auto L = TSCtx.getLock(); + M = nullptr; + } + M = std::move(Other.M); + TSCtx = std::move(Other.TSCtx); + return *this; + } + + /// Construct a ThreadSafeModule from a unique_ptr<Module> and a + /// unique_ptr<LLVMContext>. This creates a new ThreadSafeContext from the + /// given context. + ThreadSafeModule(std::unique_ptr<Module> M, std::unique_ptr<LLVMContext> Ctx) + : M(std::move(M)), TSCtx(std::move(Ctx)) {} + + /// Construct a ThreadSafeModule from a unique_ptr<Module> and an + /// existing ThreadSafeContext. + ThreadSafeModule(std::unique_ptr<Module> M, ThreadSafeContext TSCtx) + : M(std::move(M)), TSCtx(std::move(TSCtx)) {} + + ~ThreadSafeModule() { + // We need to lock the context while we destruct the module. + if (M) { + auto L = TSCtx.getLock(); + M = nullptr; + } + } + + /// Boolean conversion: This ThreadSafeModule will evaluate to true if it + /// wraps a non-null module. + explicit operator bool() const { + if (M) { + assert(TSCtx.getContext() && + "Non-null module must have non-null context"); + return true; + } + return false; + } + + /// Locks the associated ThreadSafeContext and calls the given function + /// on the contained Module. + template <typename Func> decltype(auto) withModuleDo(Func &&F) { + assert(M && "Can not call on null module"); + auto Lock = TSCtx.getLock(); + return F(*M); + } + + /// Locks the associated ThreadSafeContext and calls the given function + /// on the contained Module. + template <typename Func> decltype(auto) withModuleDo(Func &&F) const { + assert(M && "Can not call on null module"); + auto Lock = TSCtx.getLock(); + return F(*M); + } + + /// Locks the associated ThreadSafeContext and calls the given function, + /// passing the contained std::unique_ptr<Module>. The given function should + /// consume the Module. + template <typename Func> decltype(auto) consumingModuleDo(Func &&F) { + auto Lock = TSCtx.getLock(); + return F(std::move(M)); + } + + /// Get a raw pointer to the contained module without locking the context. + Module *getModuleUnlocked() { return M.get(); } + + /// Get a raw pointer to the contained module without locking the context. + const Module *getModuleUnlocked() const { return M.get(); } + + /// Returns the context for this ThreadSafeModule. + ThreadSafeContext getContext() const { return TSCtx; } + +private: + std::unique_ptr<Module> M; + ThreadSafeContext TSCtx; +}; + +using GVPredicate = std::function<bool(const GlobalValue &)>; +using GVModifier = std::function<void(GlobalValue &)>; + +/// Clones the given module on to a new context. +ThreadSafeModule +cloneToNewContext(const ThreadSafeModule &TSMW, + GVPredicate ShouldCloneDef = GVPredicate(), + GVModifier UpdateClonedDefSource = GVModifier()); + +} // End namespace orc +} // End namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_THREADSAFEMODULE_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif |
