xref: /netbsd-src/external/apache2/llvm/dist/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h (revision 82d56013d7b633d116a93943de88e08335357a7c)
1 //===-- ObjectLinkingLayer.h - JITLink-based jit linking layer --*- 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 // Contains the definition for an JITLink-based, in-process object linking
10 // layer.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
15 #define LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
16 
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/ADT/StringMap.h"
19 #include "llvm/ADT/StringRef.h"
20 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
21 #include "llvm/ExecutionEngine/JITSymbol.h"
22 #include "llvm/ExecutionEngine/Orc/Core.h"
23 #include "llvm/ExecutionEngine/Orc/Layer.h"
24 #include "llvm/Support/Error.h"
25 #include <algorithm>
26 #include <cassert>
27 #include <functional>
28 #include <list>
29 #include <memory>
30 #include <string>
31 #include <utility>
32 #include <vector>
33 
34 namespace llvm {
35 
36 namespace jitlink {
37 class EHFrameRegistrar;
38 class LinkGraph;
39 class Symbol;
40 } // namespace jitlink
41 
42 namespace object {
43 class ObjectFile;
44 } // namespace object
45 
46 namespace orc {
47 
48 class ObjectLinkingLayerJITLinkContext;
49 
50 /// An ObjectLayer implementation built on JITLink.
51 ///
52 /// Clients can use this class to add relocatable object files to an
53 /// ExecutionSession, and it typically serves as the base layer (underneath
54 /// a compiling layer like IRCompileLayer) for the rest of the JIT.
55 class ObjectLinkingLayer : public RTTIExtends<ObjectLinkingLayer, ObjectLayer>,
56                            private ResourceManager {
57   friend class ObjectLinkingLayerJITLinkContext;
58 
59 public:
60   static char ID;
61 
62   /// Plugin instances can be added to the ObjectLinkingLayer to receive
63   /// callbacks when code is loaded or emitted, and when JITLink is being
64   /// configured.
65   class Plugin {
66   public:
67     using JITLinkSymbolVector = std::vector<const jitlink::Symbol *>;
68     using LocalDependenciesMap = DenseMap<SymbolStringPtr, JITLinkSymbolVector>;
69 
70     virtual ~Plugin();
modifyPassConfig(MaterializationResponsibility & MR,jitlink::LinkGraph & G,jitlink::PassConfiguration & Config)71     virtual void modifyPassConfig(MaterializationResponsibility &MR,
72                                   jitlink::LinkGraph &G,
73                                   jitlink::PassConfiguration &Config) {}
74 
75     // Deprecated. Don't use this in new code. There will be a proper mechanism
76     // for capturing object buffers.
notifyMaterializing(MaterializationResponsibility & MR,jitlink::LinkGraph & G,jitlink::JITLinkContext & Ctx,MemoryBufferRef InputObject)77     virtual void notifyMaterializing(MaterializationResponsibility &MR,
78                                      jitlink::LinkGraph &G,
79                                      jitlink::JITLinkContext &Ctx,
80                                      MemoryBufferRef InputObject) {}
81 
notifyLoaded(MaterializationResponsibility & MR)82     virtual void notifyLoaded(MaterializationResponsibility &MR) {}
notifyEmitted(MaterializationResponsibility & MR)83     virtual Error notifyEmitted(MaterializationResponsibility &MR) {
84       return Error::success();
85     }
86     virtual Error notifyFailed(MaterializationResponsibility &MR) = 0;
87     virtual Error notifyRemovingResources(ResourceKey K) = 0;
88     virtual void notifyTransferringResources(ResourceKey DstKey,
89                                              ResourceKey SrcKey) = 0;
90 
91     /// Return any dependencies that synthetic symbols (e.g. init symbols)
92     /// have on locally scoped jitlink::Symbols. This is used by the
93     /// ObjectLinkingLayer to update the dependencies for the synthetic
94     /// symbols.
95     virtual LocalDependenciesMap
getSyntheticSymbolLocalDependencies(MaterializationResponsibility & MR)96     getSyntheticSymbolLocalDependencies(MaterializationResponsibility &MR) {
97       return LocalDependenciesMap();
98     }
99   };
100 
101   using ReturnObjectBufferFunction =
102       std::function<void(std::unique_ptr<MemoryBuffer>)>;
103 
104   /// Construct an ObjectLinkingLayer.
105   ObjectLinkingLayer(ExecutionSession &ES,
106                      jitlink::JITLinkMemoryManager &MemMgr);
107 
108   /// Construct an ObjectLinkingLayer. Takes ownership of the given
109   /// JITLinkMemoryManager. This method is a temporary hack to simplify
110   /// co-existence with RTDyldObjectLinkingLayer (which also owns its
111   /// allocators).
112   ObjectLinkingLayer(ExecutionSession &ES,
113                      std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr);
114 
115   /// Destruct an ObjectLinkingLayer.
116   ~ObjectLinkingLayer();
117 
118   /// Set an object buffer return function. By default object buffers are
119   /// deleted once the JIT has linked them. If a return function is set then
120   /// it will be called to transfer ownership of the buffer instead.
setReturnObjectBuffer(ReturnObjectBufferFunction ReturnObjectBuffer)121   void setReturnObjectBuffer(ReturnObjectBufferFunction ReturnObjectBuffer) {
122     this->ReturnObjectBuffer = std::move(ReturnObjectBuffer);
123   }
124 
125   /// Add a pass-config modifier.
addPlugin(std::unique_ptr<Plugin> P)126   ObjectLinkingLayer &addPlugin(std::unique_ptr<Plugin> P) {
127     std::lock_guard<std::mutex> Lock(LayerMutex);
128     Plugins.push_back(std::move(P));
129     return *this;
130   }
131 
132   /// Add a LinkGraph to the JITDylib targeted by the given tracker.
133   Error add(ResourceTrackerSP, std::unique_ptr<jitlink::LinkGraph> G);
134 
135   /// Add a LinkGraph to the given JITDylib.
add(JITDylib & JD,std::unique_ptr<jitlink::LinkGraph> G)136   Error add(JITDylib &JD, std::unique_ptr<jitlink::LinkGraph> G) {
137     return add(JD.getDefaultResourceTracker(), std::move(G));
138   }
139 
140   // Un-hide ObjectLayer add methods.
141   using ObjectLayer::add;
142 
143   /// Emit an object file.
144   void emit(std::unique_ptr<MaterializationResponsibility> R,
145             std::unique_ptr<MemoryBuffer> O) override;
146 
147   /// Emit a LinkGraph.
148   void emit(std::unique_ptr<MaterializationResponsibility> R,
149             std::unique_ptr<jitlink::LinkGraph> G);
150 
151   /// Instructs this ObjectLinkingLayer instance to override the symbol flags
152   /// found in the AtomGraph with the flags supplied by the
153   /// MaterializationResponsibility instance. This is a workaround to support
154   /// symbol visibility in COFF, which does not use the libObject's
155   /// SF_Exported flag. Use only when generating / adding COFF object files.
156   ///
157   /// FIXME: We should be able to remove this if/when COFF properly tracks
158   /// exported symbols.
159   ObjectLinkingLayer &
setOverrideObjectFlagsWithResponsibilityFlags(bool OverrideObjectFlags)160   setOverrideObjectFlagsWithResponsibilityFlags(bool OverrideObjectFlags) {
161     this->OverrideObjectFlags = OverrideObjectFlags;
162     return *this;
163   }
164 
165   /// If set, this ObjectLinkingLayer instance will claim responsibility
166   /// for any symbols provided by a given object file that were not already in
167   /// the MaterializationResponsibility instance. Setting this flag allows
168   /// higher-level program representations (e.g. LLVM IR) to be added based on
169   /// only a subset of the symbols they provide, without having to write
170   /// intervening layers to scan and add the additional symbols. This trades
171   /// diagnostic quality for convenience however: If all symbols are enumerated
172   /// up-front then clashes can be detected and reported early (and usually
173   /// deterministically). If this option is set, clashes for the additional
174   /// symbols may not be detected until late, and detection may depend on
175   /// the flow of control through JIT'd code. Use with care.
176   ObjectLinkingLayer &
setAutoClaimResponsibilityForObjectSymbols(bool AutoClaimObjectSymbols)177   setAutoClaimResponsibilityForObjectSymbols(bool AutoClaimObjectSymbols) {
178     this->AutoClaimObjectSymbols = AutoClaimObjectSymbols;
179     return *this;
180   }
181 
182 private:
183   using AllocPtr = std::unique_ptr<jitlink::JITLinkMemoryManager::Allocation>;
184 
185   void modifyPassConfig(MaterializationResponsibility &MR,
186                         jitlink::LinkGraph &G,
187                         jitlink::PassConfiguration &PassConfig);
188   void notifyLoaded(MaterializationResponsibility &MR);
189   Error notifyEmitted(MaterializationResponsibility &MR, AllocPtr Alloc);
190 
191   Error handleRemoveResources(ResourceKey K) override;
192   void handleTransferResources(ResourceKey DstKey, ResourceKey SrcKey) override;
193 
194   mutable std::mutex LayerMutex;
195   jitlink::JITLinkMemoryManager &MemMgr;
196   std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgrOwnership;
197   bool OverrideObjectFlags = false;
198   bool AutoClaimObjectSymbols = false;
199   ReturnObjectBufferFunction ReturnObjectBuffer;
200   DenseMap<ResourceKey, std::vector<AllocPtr>> Allocs;
201   std::vector<std::unique_ptr<Plugin>> Plugins;
202 };
203 
204 class EHFrameRegistrationPlugin : public ObjectLinkingLayer::Plugin {
205 public:
206   EHFrameRegistrationPlugin(
207       ExecutionSession &ES,
208       std::unique_ptr<jitlink::EHFrameRegistrar> Registrar);
209   void modifyPassConfig(MaterializationResponsibility &MR,
210                         jitlink::LinkGraph &G,
211                         jitlink::PassConfiguration &PassConfig) override;
212   Error notifyEmitted(MaterializationResponsibility &MR) override;
213   Error notifyFailed(MaterializationResponsibility &MR) override;
214   Error notifyRemovingResources(ResourceKey K) override;
215   void notifyTransferringResources(ResourceKey DstKey,
216                                    ResourceKey SrcKey) override;
217 
218 private:
219 
220   struct EHFrameRange {
221     JITTargetAddress Addr = 0;
222     size_t Size;
223   };
224 
225   std::mutex EHFramePluginMutex;
226   ExecutionSession &ES;
227   std::unique_ptr<jitlink::EHFrameRegistrar> Registrar;
228   DenseMap<MaterializationResponsibility *, EHFrameRange> InProcessLinks;
229   DenseMap<ResourceKey, std::vector<EHFrameRange>> EHFrameRanges;
230 };
231 
232 } // end namespace orc
233 } // end namespace llvm
234 
235 #endif // LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
236