LLVM 22.0.0git
ThreadSafeModule.h
Go to the documentation of this file.
1//===----------- ThreadSafeModule.h -- Layer interfaces ---------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Thread safe wrappers and utilities for Module and LLVMContext.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_EXECUTIONENGINE_ORC_THREADSAFEMODULE_H
14#define LLVM_EXECUTIONENGINE_ORC_THREADSAFEMODULE_H
15
16#include "llvm/IR/LLVMContext.h"
17#include "llvm/IR/Module.h"
19
20#include <functional>
21#include <memory>
22#include <mutex>
23
24namespace llvm {
25namespace orc {
26
27/// An LLVMContext together with an associated mutex that can be used to lock
28/// the context to prevent concurrent access by other threads.
30private:
31 struct State {
32 State(std::unique_ptr<LLVMContext> Ctx) : Ctx(std::move(Ctx)) {}
33
34 std::unique_ptr<LLVMContext> Ctx;
35 std::recursive_mutex Mutex;
36 };
37
38public:
39 /// Construct a null context.
40 ThreadSafeContext() = default;
41
42 /// Construct a ThreadSafeContext from the given LLVMContext.
43 ThreadSafeContext(std::unique_ptr<LLVMContext> NewCtx)
44 : S(std::make_shared<State>(std::move(NewCtx))) {
45 assert(S->Ctx != nullptr &&
46 "Can not construct a ThreadSafeContext from a nullptr");
47 }
48
49 template <typename Func> decltype(auto) withContextDo(Func &&F) {
50 if (auto TmpS = S) {
51 std::lock_guard<std::recursive_mutex> Lock(TmpS->Mutex);
52 return F(TmpS->Ctx.get());
53 } else
54 return F((LLVMContext *)nullptr);
55 }
56
57 template <typename Func> decltype(auto) withContextDo(Func &&F) const {
58 if (auto TmpS = S) {
59 std::lock_guard<std::recursive_mutex> Lock(TmpS->Mutex);
60 return F(const_cast<const LLVMContext *>(TmpS->Ctx.get()));
61 } else
62 return F((const LLVMContext *)nullptr);
63 }
64
65private:
66 std::shared_ptr<State> S;
67};
68
69/// An LLVM Module together with a shared ThreadSafeContext.
71public:
72 /// Default construct a ThreadSafeModule. This results in a null module and
73 /// null context.
74 ThreadSafeModule() = default;
75
77
79 // We have to explicitly define this move operator to copy the fields in
80 // reverse order (i.e. module first) to ensure the dependencies are
81 // protected: The old module that is being overwritten must be destroyed
82 // *before* the context that it depends on.
83 // We also need to lock the context to make sure the module tear-down
84 // does not overlap any other work on the context.
85 TSCtx.withContextDo([this](LLVMContext *Ctx) { M = nullptr; });
86 M = std::move(Other.M);
87 TSCtx = std::move(Other.TSCtx);
88 return *this;
89 }
90
91 /// Construct a ThreadSafeModule from a unique_ptr<Module> and a
92 /// unique_ptr<LLVMContext>. This creates a new ThreadSafeContext from the
93 /// given context.
94 ThreadSafeModule(std::unique_ptr<Module> M, std::unique_ptr<LLVMContext> Ctx)
95 : M(std::move(M)), TSCtx(std::move(Ctx)) {}
96
97 /// Construct a ThreadSafeModule from a unique_ptr<Module> and an
98 /// existing ThreadSafeContext.
99 ThreadSafeModule(std::unique_ptr<Module> M, ThreadSafeContext TSCtx)
100 : M(std::move(M)), TSCtx(std::move(TSCtx)) {}
101
103 // We need to lock the context while we destruct the module.
104 TSCtx.withContextDo([this](LLVMContext *Ctx) { M = nullptr; });
105 }
106
107 /// Boolean conversion: This ThreadSafeModule will evaluate to true if it
108 /// wraps a non-null module.
109 explicit operator bool() const { return !!M; }
110
111 /// Locks the associated ThreadSafeContext and calls the given function
112 /// on the contained Module.
113 template <typename Func> decltype(auto) withModuleDo(Func &&F) {
114 return TSCtx.withContextDo([&](LLVMContext *) {
115 assert(M && "Can not call on null module");
116 return F(*M);
117 });
118 }
119
120 /// Locks the associated ThreadSafeContext and calls the given function
121 /// on the contained Module.
122 template <typename Func> decltype(auto) withModuleDo(Func &&F) const {
123 return TSCtx.withContextDo([&](const LLVMContext *) {
124 assert(M && "Can not call on null module");
125 return F(*M);
126 });
127 }
128
129 /// Locks the associated ThreadSafeContext and calls the given function,
130 /// passing the contained std::unique_ptr<Module>. The given function should
131 /// consume the Module.
132 template <typename Func> decltype(auto) consumingModuleDo(Func &&F) {
133 return TSCtx.withContextDo([&](LLVMContext *) {
134 assert(M && "Can not call on null module");
135 return F(std::move(M));
136 });
137 }
138
139 /// Get a raw pointer to the contained module without locking the context.
140 Module *getModuleUnlocked() { return M.get(); }
141
142 /// Get a raw pointer to the contained module without locking the context.
143 const Module *getModuleUnlocked() const { return M.get(); }
144
145 /// Returns the context for this ThreadSafeModule.
146 ThreadSafeContext getContext() const { return TSCtx; }
147
148private:
149 std::unique_ptr<Module> M;
150 ThreadSafeContext TSCtx;
151};
152
153using GVPredicate = std::function<bool(const GlobalValue &)>;
154using GVModifier = std::function<void(GlobalValue &)>;
155
156/// Clones the given module onto the given context.
159 GVPredicate ShouldCloneDef = GVPredicate(),
160 GVModifier UpdateClonedDefSource = GVModifier());
161
162/// Clone the given module onto the given context.
163/// The caller is responsible for ensuring that the source module and its
164/// LLVMContext will not be concurrently accessed during the clone.
167 GVPredicate ShouldCloneDef = GVPredicate(),
168 GVModifier UpdateClonedDefSource = GVModifier());
169
170/// Clones the given module on to a new context.
172 const ThreadSafeModule &TSMW, GVPredicate ShouldCloneDef = GVPredicate(),
173 GVModifier UpdateClonedDefSource = GVModifier());
174
175} // End namespace orc
176} // End namespace llvm
177
178#endif // LLVM_EXECUTIONENGINE_ORC_THREADSAFEMODULE_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_ABI
Definition: Compiler.h:213
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition: MD5.cpp:55
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:68
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
An LLVMContext together with an associated mutex that can be used to lock the context to prevent conc...
ThreadSafeContext()=default
Construct a null context.
ThreadSafeContext(std::unique_ptr< LLVMContext > NewCtx)
Construct a ThreadSafeContext from the given LLVMContext.
decltype(auto) withContextDo(Func &&F)
decltype(auto) withContextDo(Func &&F) const
An LLVM Module together with a shared ThreadSafeContext.
ThreadSafeContext getContext() const
Returns the context for this ThreadSafeModule.
decltype(auto) consumingModuleDo(Func &&F)
Locks the associated ThreadSafeContext and calls the given function, passing the contained std::uniqu...
ThreadSafeModule & operator=(ThreadSafeModule &&Other)
ThreadSafeModule()=default
Default construct a ThreadSafeModule.
Module * getModuleUnlocked()
Get a raw pointer to the contained module without locking the context.
ThreadSafeModule(std::unique_ptr< Module > M, std::unique_ptr< LLVMContext > Ctx)
Construct a ThreadSafeModule from a unique_ptr<Module> and a unique_ptr<LLVMContext>.
decltype(auto) withModuleDo(Func &&F)
Locks the associated ThreadSafeContext and calls the given function on the contained Module.
ThreadSafeModule(ThreadSafeModule &&Other)=default
decltype(auto) withModuleDo(Func &&F) const
Locks the associated ThreadSafeContext and calls the given function on the contained Module.
ThreadSafeModule(std::unique_ptr< Module > M, ThreadSafeContext TSCtx)
Construct a ThreadSafeModule from a unique_ptr<Module> and an existing ThreadSafeContext.
const Module * getModuleUnlocked() const
Get a raw pointer to the contained module without locking the context.
std::function< bool(const GlobalValue &)> GVPredicate
std::function< void(GlobalValue &)> GVModifier
LLVM_ABI ThreadSafeModule cloneToContext(const ThreadSafeModule &TSMW, ThreadSafeContext TSCtx, GVPredicate ShouldCloneDef=GVPredicate(), GVModifier UpdateClonedDefSource=GVModifier())
Clones the given module onto the given context.
LLVM_ABI ThreadSafeModule cloneExternalModuleToContext(const Module &M, ThreadSafeContext TSCtx, GVPredicate ShouldCloneDef=GVPredicate(), GVModifier UpdateClonedDefSource=GVModifier())
Clone the given module onto the given context.
LLVM_ABI ThreadSafeModule cloneToNewContext(const ThreadSafeModule &TSMW, GVPredicate ShouldCloneDef=GVPredicate(), GVModifier UpdateClonedDefSource=GVModifier())
Clones the given module on to a new context.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Other
Any other memory.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1886
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:856