]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h
Merge lld trunk r351319, resolve conflicts, and update FREEBSD-Xlist.
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / ExecutionEngine / Orc / RemoteObjectLayer.h
1 //===------ RemoteObjectLayer.h - Forwards objs to a remote -----*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Forwards objects to a remote object layer via RPC.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_EXECUTIONENGINE_ORC_REMOTEOBJECTLAYER_H
15 #define LLVM_EXECUTIONENGINE_ORC_REMOTEOBJECTLAYER_H
16
17 #include "llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h"
18 #include "llvm/Object/ObjectFile.h"
19 #include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
20 #include <map>
21
22 namespace llvm {
23 namespace orc {
24
25 /// RPC API needed by RemoteObjectClientLayer and RemoteObjectServerLayer.
26 class RemoteObjectLayerAPI {
27 public:
28
29   using ObjHandleT = remote::ResourceIdMgr::ResourceId;
30
31 protected:
32
33   using RemoteSymbolId = remote::ResourceIdMgr::ResourceId;
34   using RemoteSymbol = std::pair<RemoteSymbolId, JITSymbolFlags>;
35
36 public:
37
38   using BadSymbolHandleError = remote::ResourceNotFound<RemoteSymbolId>;
39   using BadObjectHandleError = remote::ResourceNotFound<ObjHandleT>;
40
41 protected:
42
43   static const ObjHandleT InvalidObjectHandleId = 0;
44   static const RemoteSymbolId NullSymbolId = 0;
45
46   class AddObject
47     : public rpc::Function<AddObject, Expected<ObjHandleT>(std::string)> {
48   public:
49     static const char *getName() { return "AddObject"; }
50   };
51
52   class RemoveObject
53     : public rpc::Function<RemoveObject, Error(ObjHandleT)> {
54   public:
55     static const char *getName() { return "RemoveObject"; }
56   };
57
58   class FindSymbol
59     : public rpc::Function<FindSymbol, Expected<RemoteSymbol>(std::string,
60                                                               bool)> {
61   public:
62     static const char *getName() { return "FindSymbol"; }
63   };
64
65   class FindSymbolIn
66     : public rpc::Function<FindSymbolIn,
67                            Expected<RemoteSymbol>(ObjHandleT, std::string,
68                                                   bool)> {
69   public:
70     static const char *getName() { return "FindSymbolIn"; }
71   };
72
73   class EmitAndFinalize
74     : public rpc::Function<EmitAndFinalize,
75                            Error(ObjHandleT)> {
76   public:
77     static const char *getName() { return "EmitAndFinalize"; }
78   };
79
80   class Lookup
81     : public rpc::Function<Lookup,
82                            Expected<RemoteSymbol>(ObjHandleT, std::string)> {
83   public:
84     static const char *getName() { return "Lookup"; }
85   };
86
87   class LookupInLogicalDylib
88     : public rpc::Function<LookupInLogicalDylib,
89                            Expected<RemoteSymbol>(ObjHandleT, std::string)> {
90   public:
91     static const char *getName() { return "LookupInLogicalDylib"; }
92   };
93
94   class ReleaseRemoteSymbol
95     : public rpc::Function<ReleaseRemoteSymbol, Error(RemoteSymbolId)> {
96   public:
97     static const char *getName() { return "ReleaseRemoteSymbol"; }
98   };
99
100   class MaterializeRemoteSymbol
101     : public rpc::Function<MaterializeRemoteSymbol,
102                            Expected<JITTargetAddress>(RemoteSymbolId)> {
103   public:
104     static const char *getName() { return "MaterializeRemoteSymbol"; }
105   };
106 };
107
108 /// Base class containing common utilities for RemoteObjectClientLayer and
109 /// RemoteObjectServerLayer.
110 template <typename RPCEndpoint>
111 class RemoteObjectLayer : public RemoteObjectLayerAPI {
112 public:
113
114   RemoteObjectLayer(RPCEndpoint &Remote,
115                     std::function<void(Error)> ReportError)
116       : Remote(Remote), ReportError(std::move(ReportError)),
117         SymbolIdMgr(NullSymbolId + 1) {
118     using ThisT = RemoteObjectLayer<RPCEndpoint>;
119     Remote.template addHandler<ReleaseRemoteSymbol>(
120              *this, &ThisT::handleReleaseRemoteSymbol);
121     Remote.template addHandler<MaterializeRemoteSymbol>(
122              *this, &ThisT::handleMaterializeRemoteSymbol);
123   }
124
125 protected:
126
127   /// This class is used as the symbol materializer for JITSymbols returned by
128   /// RemoteObjectLayerClient/RemoteObjectLayerServer -- the materializer knows
129   /// how to call back to the other RPC endpoint to get the address when
130   /// requested.
131   class RemoteSymbolMaterializer {
132   public:
133
134     /// Construct a RemoteSymbolMaterializer for the given RemoteObjectLayer
135     /// with the given Id.
136     RemoteSymbolMaterializer(RemoteObjectLayer &C,
137                              RemoteSymbolId Id)
138       : C(C), Id(Id) {}
139
140     RemoteSymbolMaterializer(const RemoteSymbolMaterializer &Other)
141       : C(Other.C), Id(Other.Id) {
142       // FIXME: This is a horrible, auto_ptr-style, copy-as-move operation.
143       //        It should be removed as soon as LLVM has C++14's generalized
144       //        lambda capture (at which point the materializer can be moved
145       //        into the lambda in remoteToJITSymbol below).
146       const_cast<RemoteSymbolMaterializer&>(Other).Id = 0;
147     }
148
149     RemoteSymbolMaterializer&
150     operator=(const RemoteSymbolMaterializer&) = delete;
151
152     /// Release the remote symbol.
153     ~RemoteSymbolMaterializer() {
154       if (Id)
155         C.releaseRemoteSymbol(Id);
156     }
157
158     /// Materialize the symbol on the remote and get its address.
159     Expected<JITTargetAddress> materialize() {
160       auto Addr = C.materializeRemoteSymbol(Id);
161       Id = 0;
162       return Addr;
163     }
164
165   private:
166     RemoteObjectLayer &C;
167     RemoteSymbolId Id;
168   };
169
170   /// Convenience function for getting a null remote symbol value.
171   RemoteSymbol nullRemoteSymbol() {
172     return RemoteSymbol(0, JITSymbolFlags());
173   }
174
175   /// Creates a StringError that contains a copy of Err's log message, then
176   /// sends that StringError to ReportError.
177   ///
178   /// This allows us to locally log error messages for errors that will actually
179   /// be delivered to the remote.
180   Error teeLog(Error Err) {
181     return handleErrors(std::move(Err),
182                         [this](std::unique_ptr<ErrorInfoBase> EIB) {
183                           ReportError(make_error<StringError>(
184                                         EIB->message(),
185                                         EIB->convertToErrorCode()));
186                           return Error(std::move(EIB));
187                         });
188   }
189
190   Error badRemoteSymbolIdError(RemoteSymbolId Id) {
191     return make_error<BadSymbolHandleError>(Id, "Remote JIT Symbol");
192   }
193
194   Error badObjectHandleError(ObjHandleT H) {
195     return make_error<RemoteObjectLayerAPI::BadObjectHandleError>(
196              H, "Bad object handle");
197   }
198
199   /// Create a RemoteSymbol wrapping the given JITSymbol.
200   Expected<RemoteSymbol> jitSymbolToRemote(JITSymbol Sym) {
201     if (Sym) {
202       auto Id = SymbolIdMgr.getNext();
203       auto Flags = Sym.getFlags();
204       assert(!InUseSymbols.count(Id) && "Symbol id already in use");
205       InUseSymbols.insert(std::make_pair(Id, std::move(Sym)));
206       return RemoteSymbol(Id, Flags);
207     } else if (auto Err = Sym.takeError())
208       return teeLog(std::move(Err));
209     // else...
210     return nullRemoteSymbol();
211   }
212
213   /// Convert an Expected<RemoteSymbol> to a JITSymbol.
214   JITSymbol remoteToJITSymbol(Expected<RemoteSymbol> RemoteSymOrErr) {
215     if (RemoteSymOrErr) {
216       auto &RemoteSym = *RemoteSymOrErr;
217       if (RemoteSym == nullRemoteSymbol())
218         return nullptr;
219       // else...
220       RemoteSymbolMaterializer RSM(*this, RemoteSym.first);
221       auto Sym =
222         JITSymbol([RSM]() mutable { return RSM.materialize(); },
223                   RemoteSym.second);
224       return Sym;
225     } else
226       return RemoteSymOrErr.takeError();
227   }
228
229   RPCEndpoint &Remote;
230   std::function<void(Error)> ReportError;
231
232 private:
233
234   /// Notify the remote to release the given JITSymbol.
235   void releaseRemoteSymbol(RemoteSymbolId Id) {
236     if (auto Err = Remote.template callB<ReleaseRemoteSymbol>(Id))
237       ReportError(std::move(Err));
238   }
239
240   /// Notify the remote to materialize the JITSymbol with the given Id and
241   /// return its address.
242   Expected<JITTargetAddress> materializeRemoteSymbol(RemoteSymbolId Id) {
243     return Remote.template callB<MaterializeRemoteSymbol>(Id);
244   }
245
246   /// Release the JITSymbol with the given Id.
247   Error handleReleaseRemoteSymbol(RemoteSymbolId Id) {
248     auto SI = InUseSymbols.find(Id);
249     if (SI != InUseSymbols.end()) {
250       InUseSymbols.erase(SI);
251       return Error::success();
252     } else
253       return teeLog(badRemoteSymbolIdError(Id));
254   }
255
256   /// Run the materializer for the JITSymbol with the given Id and return its
257   /// address.
258   Expected<JITTargetAddress> handleMaterializeRemoteSymbol(RemoteSymbolId Id) {
259     auto SI = InUseSymbols.find(Id);
260     if (SI != InUseSymbols.end()) {
261       auto AddrOrErr = SI->second.getAddress();
262       InUseSymbols.erase(SI);
263       SymbolIdMgr.release(Id);
264       if (AddrOrErr)
265         return *AddrOrErr;
266       else
267         return teeLog(AddrOrErr.takeError());
268     } else {
269       return teeLog(badRemoteSymbolIdError(Id));
270     }
271   }
272
273   remote::ResourceIdMgr SymbolIdMgr;
274   std::map<RemoteSymbolId, JITSymbol> InUseSymbols;
275 };
276
277 /// RemoteObjectClientLayer forwards the ORC Object Layer API over an RPC
278 /// connection.
279 ///
280 /// This class can be used as the base layer of a JIT stack on the client and
281 /// will forward operations to a corresponding RemoteObjectServerLayer on the
282 /// server (which can be composed on top of a "real" object layer like
283 /// RTDyldObjectLinkingLayer to actually carry out the operations).
284 ///
285 /// Sending relocatable objects to the server (rather than fully relocated
286 /// bits) allows JIT'd code to be cached on the server side and re-used in
287 /// subsequent JIT sessions.
288 template <typename RPCEndpoint>
289 class RemoteObjectClientLayer : public RemoteObjectLayer<RPCEndpoint> {
290 private:
291
292   using AddObject = RemoteObjectLayerAPI::AddObject;
293   using RemoveObject = RemoteObjectLayerAPI::RemoveObject;
294   using FindSymbol = RemoteObjectLayerAPI::FindSymbol;
295   using FindSymbolIn = RemoteObjectLayerAPI::FindSymbolIn;
296   using EmitAndFinalize = RemoteObjectLayerAPI::EmitAndFinalize;
297   using Lookup = RemoteObjectLayerAPI::Lookup;
298   using LookupInLogicalDylib = RemoteObjectLayerAPI::LookupInLogicalDylib;
299
300   using RemoteObjectLayer<RPCEndpoint>::teeLog;
301   using RemoteObjectLayer<RPCEndpoint>::badObjectHandleError;
302   using RemoteObjectLayer<RPCEndpoint>::remoteToJITSymbol;
303
304 public:
305
306   using ObjHandleT = RemoteObjectLayerAPI::ObjHandleT;
307   using RemoteSymbol = RemoteObjectLayerAPI::RemoteSymbol;
308
309   using ObjectPtr = std::unique_ptr<MemoryBuffer>;
310
311   /// Create a RemoteObjectClientLayer that communicates with a
312   /// RemoteObjectServerLayer instance via the given RPCEndpoint.
313   ///
314   /// The ReportError functor can be used locally log errors that are intended
315   /// to be sent  sent
316   RemoteObjectClientLayer(RPCEndpoint &Remote,
317                           std::function<void(Error)> ReportError)
318       : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)) {
319     using ThisT = RemoteObjectClientLayer<RPCEndpoint>;
320     Remote.template addHandler<Lookup>(*this, &ThisT::lookup);
321     Remote.template addHandler<LookupInLogicalDylib>(
322             *this, &ThisT::lookupInLogicalDylib);
323   }
324
325   /// Add an object to the JIT.
326   ///
327   /// @return A handle that can be used to refer to the loaded object (for
328   ///         symbol searching, finalization, freeing memory, etc.).
329   Expected<ObjHandleT>
330   addObject(ObjectPtr ObjBuffer,
331             std::shared_ptr<LegacyJITSymbolResolver> Resolver) {
332     if (auto HandleOrErr =
333             this->Remote.template callB<AddObject>(ObjBuffer->getBuffer())) {
334       auto &Handle = *HandleOrErr;
335       // FIXME: Return an error for this:
336       assert(!Resolvers.count(Handle) && "Handle already in use?");
337       Resolvers[Handle] = std::move(Resolver);
338       return Handle;
339     } else
340       return HandleOrErr.takeError();
341   }
342
343   /// Remove the given object from the JIT.
344   Error removeObject(ObjHandleT H) {
345     return this->Remote.template callB<RemoveObject>(H);
346   }
347
348   /// Search for the given named symbol.
349   JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
350     return remoteToJITSymbol(
351              this->Remote.template callB<FindSymbol>(Name,
352                                                      ExportedSymbolsOnly));
353   }
354
355   /// Search for the given named symbol within the given context.
356   JITSymbol findSymbolIn(ObjHandleT H, StringRef Name, bool ExportedSymbolsOnly) {
357     return remoteToJITSymbol(
358              this->Remote.template callB<FindSymbolIn>(H, Name,
359                                                        ExportedSymbolsOnly));
360   }
361
362   /// Immediately emit and finalize the object with the given handle.
363   Error emitAndFinalize(ObjHandleT H) {
364     return this->Remote.template callB<EmitAndFinalize>(H);
365   }
366
367 private:
368
369   Expected<RemoteSymbol> lookup(ObjHandleT H, const std::string &Name) {
370     auto RI = Resolvers.find(H);
371     if (RI != Resolvers.end()) {
372       return this->jitSymbolToRemote(RI->second->findSymbol(Name));
373     } else
374       return teeLog(badObjectHandleError(H));
375   }
376
377   Expected<RemoteSymbol> lookupInLogicalDylib(ObjHandleT H,
378                                               const std::string &Name) {
379     auto RI = Resolvers.find(H);
380     if (RI != Resolvers.end())
381       return this->jitSymbolToRemote(
382                RI->second->findSymbolInLogicalDylib(Name));
383     else
384       return teeLog(badObjectHandleError(H));
385   }
386
387   std::map<remote::ResourceIdMgr::ResourceId,
388            std::shared_ptr<LegacyJITSymbolResolver>>
389       Resolvers;
390 };
391
392 /// RemoteObjectServerLayer acts as a server and handling RPC calls for the
393 /// object layer API from the given RPC connection.
394 ///
395 /// This class can be composed on top of a 'real' object layer (e.g.
396 /// RTDyldObjectLinkingLayer) to do the actual work of relocating objects
397 /// and making them executable.
398 template <typename BaseLayerT, typename RPCEndpoint>
399 class RemoteObjectServerLayer : public RemoteObjectLayer<RPCEndpoint> {
400 private:
401
402   using ObjHandleT = RemoteObjectLayerAPI::ObjHandleT;
403   using RemoteSymbol = RemoteObjectLayerAPI::RemoteSymbol;
404
405   using AddObject = RemoteObjectLayerAPI::AddObject;
406   using RemoveObject = RemoteObjectLayerAPI::RemoveObject;
407   using FindSymbol = RemoteObjectLayerAPI::FindSymbol;
408   using FindSymbolIn = RemoteObjectLayerAPI::FindSymbolIn;
409   using EmitAndFinalize = RemoteObjectLayerAPI::EmitAndFinalize;
410   using Lookup = RemoteObjectLayerAPI::Lookup;
411   using LookupInLogicalDylib = RemoteObjectLayerAPI::LookupInLogicalDylib;
412
413   using RemoteObjectLayer<RPCEndpoint>::teeLog;
414   using RemoteObjectLayer<RPCEndpoint>::badObjectHandleError;
415   using RemoteObjectLayer<RPCEndpoint>::remoteToJITSymbol;
416
417 public:
418
419   /// Create a RemoteObjectServerLayer with the given base layer (which must be
420   /// an object layer), RPC endpoint, and error reporter function.
421   RemoteObjectServerLayer(BaseLayerT &BaseLayer,
422                           RPCEndpoint &Remote,
423                           std::function<void(Error)> ReportError)
424     : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)),
425       BaseLayer(BaseLayer), HandleIdMgr(1) {
426     using ThisT = RemoteObjectServerLayer<BaseLayerT, RPCEndpoint>;
427
428     Remote.template addHandler<AddObject>(*this, &ThisT::addObject);
429     Remote.template addHandler<RemoveObject>(*this, &ThisT::removeObject);
430     Remote.template addHandler<FindSymbol>(*this, &ThisT::findSymbol);
431     Remote.template addHandler<FindSymbolIn>(*this, &ThisT::findSymbolIn);
432     Remote.template addHandler<EmitAndFinalize>(*this, &ThisT::emitAndFinalize);
433   }
434
435 private:
436
437   class StringMemoryBuffer : public MemoryBuffer {
438   public:
439     StringMemoryBuffer(std::string Buffer)
440       : Buffer(std::move(Buffer)) {
441       init(this->Buffer.data(), this->Buffer.data() + this->Buffer.size(),
442            false);
443     }
444
445     BufferKind getBufferKind() const override { return MemoryBuffer_Malloc; }
446   private:
447     std::string Buffer;
448   };
449
450   JITSymbol lookup(ObjHandleT Id, const std::string &Name) {
451     return remoteToJITSymbol(
452              this->Remote.template callB<Lookup>(Id, Name));
453   }
454
455   JITSymbol lookupInLogicalDylib(ObjHandleT Id, const std::string &Name) {
456     return remoteToJITSymbol(
457              this->Remote.template callB<LookupInLogicalDylib>(Id, Name));
458   }
459
460   Expected<ObjHandleT> addObject(std::string ObjBuffer) {
461     auto Buffer = llvm::make_unique<StringMemoryBuffer>(std::move(ObjBuffer));
462     auto Id = HandleIdMgr.getNext();
463     assert(!BaseLayerHandles.count(Id) && "Id already in use?");
464
465     auto Resolver = createLambdaResolver(
466         [this, Id](const std::string &Name) { return lookup(Id, Name); },
467         [this, Id](const std::string &Name) {
468           return lookupInLogicalDylib(Id, Name);
469         });
470
471     if (auto HandleOrErr =
472             BaseLayer.addObject(std::move(Buffer), std::move(Resolver))) {
473       BaseLayerHandles[Id] = std::move(*HandleOrErr);
474       return Id;
475     } else
476       return teeLog(HandleOrErr.takeError());
477   }
478
479   Error removeObject(ObjHandleT H) {
480     auto HI = BaseLayerHandles.find(H);
481     if (HI != BaseLayerHandles.end()) {
482       if (auto Err = BaseLayer.removeObject(HI->second))
483         return teeLog(std::move(Err));
484       return Error::success();
485     } else
486       return teeLog(badObjectHandleError(H));
487   }
488
489   Expected<RemoteSymbol> findSymbol(const std::string &Name,
490                                     bool ExportedSymbolsOnly) {
491     if (auto Sym = BaseLayer.findSymbol(Name, ExportedSymbolsOnly))
492       return this->jitSymbolToRemote(std::move(Sym));
493     else if (auto Err = Sym.takeError())
494       return teeLog(std::move(Err));
495     return this->nullRemoteSymbol();
496   }
497
498   Expected<RemoteSymbol> findSymbolIn(ObjHandleT H, const std::string &Name,
499                                       bool ExportedSymbolsOnly) {
500     auto HI = BaseLayerHandles.find(H);
501     if (HI != BaseLayerHandles.end()) {
502       if (auto Sym = BaseLayer.findSymbolIn(HI->second, Name, ExportedSymbolsOnly))
503         return this->jitSymbolToRemote(std::move(Sym));
504       else if (auto Err = Sym.takeError())
505         return teeLog(std::move(Err));
506       return this->nullRemoteSymbol();
507     } else
508       return teeLog(badObjectHandleError(H));
509   }
510
511   Error emitAndFinalize(ObjHandleT H) {
512     auto HI = BaseLayerHandles.find(H);
513     if (HI != BaseLayerHandles.end()) {
514       if (auto Err = BaseLayer.emitAndFinalize(HI->second))
515         return teeLog(std::move(Err));
516       return Error::success();
517     } else
518       return teeLog(badObjectHandleError(H));
519   }
520
521   BaseLayerT &BaseLayer;
522   remote::ResourceIdMgr HandleIdMgr;
523   std::map<ObjHandleT, typename BaseLayerT::ObjHandleT> BaseLayerHandles;
524 };
525
526 } // end namespace orc
527 } // end namespace llvm
528
529 #endif // LLVM_EXECUTIONENGINE_ORC_REMOTEOBJECTLAYER_H