1 //===------ RemoteObjectLayer.h - Forwards objs to a remote -----*- 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 // Forwards objects to a remote object layer via RPC.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_EXECUTIONENGINE_ORC_REMOTEOBJECTLAYER_H
14 #define LLVM_EXECUTIONENGINE_ORC_REMOTEOBJECTLAYER_H
15 
16 #include "llvm/ExecutionEngine/Orc/Core.h"
17 #include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
18 #include "llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h"
19 #include "llvm/Object/ObjectFile.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:
getName()49     static const char *getName() { return "AddObject"; }
50   };
51 
52   class RemoveObject
53     : public rpc::Function<RemoveObject, Error(ObjHandleT)> {
54   public:
getName()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:
getName()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:
getName()70     static const char *getName() { return "FindSymbolIn"; }
71   };
72 
73   class EmitAndFinalize
74     : public rpc::Function<EmitAndFinalize,
75                            Error(ObjHandleT)> {
76   public:
getName()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:
getName()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:
getName()91     static const char *getName() { return "LookupInLogicalDylib"; }
92   };
93 
94   class ReleaseRemoteSymbol
95     : public rpc::Function<ReleaseRemoteSymbol, Error(RemoteSymbolId)> {
96   public:
getName()97     static const char *getName() { return "ReleaseRemoteSymbol"; }
98   };
99 
100   class MaterializeRemoteSymbol
101     : public rpc::Function<MaterializeRemoteSymbol,
102                            Expected<JITTargetAddress>(RemoteSymbolId)> {
103   public:
getName()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 
RemoteObjectLayer(RPCEndpoint & Remote,std::function<void (Error)> ReportError)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.
RemoteSymbolMaterializer(RemoteObjectLayer & C,RemoteSymbolId Id)136     RemoteSymbolMaterializer(RemoteObjectLayer &C,
137                              RemoteSymbolId Id)
138       : C(C), Id(Id) {}
139 
RemoteSymbolMaterializer(RemoteSymbolMaterializer && Other)140     RemoteSymbolMaterializer(RemoteSymbolMaterializer &&Other)
141         : C(Other.C), Id(Other.Id) {
142       Other.Id = 0;
143     }
144 
145     RemoteSymbolMaterializer &operator=(RemoteSymbolMaterializer &&) = delete;
146 
147     /// Release the remote symbol.
~RemoteSymbolMaterializer()148     ~RemoteSymbolMaterializer() {
149       if (Id)
150         C.releaseRemoteSymbol(Id);
151     }
152 
153     /// Materialize the symbol on the remote and get its address.
materialize()154     Expected<JITTargetAddress> materialize() {
155       auto Addr = C.materializeRemoteSymbol(Id);
156       Id = 0;
157       return Addr;
158     }
159 
160   private:
161     RemoteObjectLayer &C;
162     RemoteSymbolId Id;
163   };
164 
165   /// Convenience function for getting a null remote symbol value.
nullRemoteSymbol()166   RemoteSymbol nullRemoteSymbol() {
167     return RemoteSymbol(0, JITSymbolFlags());
168   }
169 
170   /// Creates a StringError that contains a copy of Err's log message, then
171   /// sends that StringError to ReportError.
172   ///
173   /// This allows us to locally log error messages for errors that will actually
174   /// be delivered to the remote.
teeLog(Error Err)175   Error teeLog(Error Err) {
176     return handleErrors(std::move(Err),
177                         [this](std::unique_ptr<ErrorInfoBase> EIB) {
178                           ReportError(make_error<StringError>(
179                                         EIB->message(),
180                                         EIB->convertToErrorCode()));
181                           return Error(std::move(EIB));
182                         });
183   }
184 
badRemoteSymbolIdError(RemoteSymbolId Id)185   Error badRemoteSymbolIdError(RemoteSymbolId Id) {
186     return make_error<BadSymbolHandleError>(Id, "Remote JIT Symbol");
187   }
188 
badObjectHandleError(ObjHandleT H)189   Error badObjectHandleError(ObjHandleT H) {
190     return make_error<RemoteObjectLayerAPI::BadObjectHandleError>(
191              H, "Bad object handle");
192   }
193 
194   /// Create a RemoteSymbol wrapping the given JITSymbol.
jitSymbolToRemote(JITSymbol Sym)195   Expected<RemoteSymbol> jitSymbolToRemote(JITSymbol Sym) {
196     if (Sym) {
197       auto Id = SymbolIdMgr.getNext();
198       auto Flags = Sym.getFlags();
199       assert(!InUseSymbols.count(Id) && "Symbol id already in use");
200       InUseSymbols.insert(std::make_pair(Id, std::move(Sym)));
201       return RemoteSymbol(Id, Flags);
202     } else if (auto Err = Sym.takeError())
203       return teeLog(std::move(Err));
204     // else...
205     return nullRemoteSymbol();
206   }
207 
208   /// Convert an Expected<RemoteSymbol> to a JITSymbol.
remoteToJITSymbol(Expected<RemoteSymbol> RemoteSymOrErr)209   JITSymbol remoteToJITSymbol(Expected<RemoteSymbol> RemoteSymOrErr) {
210     if (RemoteSymOrErr) {
211       auto &RemoteSym = *RemoteSymOrErr;
212       if (RemoteSym == nullRemoteSymbol())
213         return nullptr;
214       // else...
215       RemoteSymbolMaterializer RSM(*this, RemoteSym.first);
216       auto Sym = JITSymbol(
217           [RSM = std::move(RSM)]() mutable { return RSM.materialize(); },
218           RemoteSym.second);
219       return Sym;
220     } else
221       return RemoteSymOrErr.takeError();
222   }
223 
224   RPCEndpoint &Remote;
225   std::function<void(Error)> ReportError;
226 
227 private:
228 
229   /// Notify the remote to release the given JITSymbol.
releaseRemoteSymbol(RemoteSymbolId Id)230   void releaseRemoteSymbol(RemoteSymbolId Id) {
231     if (auto Err = Remote.template callB<ReleaseRemoteSymbol>(Id))
232       ReportError(std::move(Err));
233   }
234 
235   /// Notify the remote to materialize the JITSymbol with the given Id and
236   /// return its address.
materializeRemoteSymbol(RemoteSymbolId Id)237   Expected<JITTargetAddress> materializeRemoteSymbol(RemoteSymbolId Id) {
238     return Remote.template callB<MaterializeRemoteSymbol>(Id);
239   }
240 
241   /// Release the JITSymbol with the given Id.
handleReleaseRemoteSymbol(RemoteSymbolId Id)242   Error handleReleaseRemoteSymbol(RemoteSymbolId Id) {
243     auto SI = InUseSymbols.find(Id);
244     if (SI != InUseSymbols.end()) {
245       InUseSymbols.erase(SI);
246       return Error::success();
247     } else
248       return teeLog(badRemoteSymbolIdError(Id));
249   }
250 
251   /// Run the materializer for the JITSymbol with the given Id and return its
252   /// address.
handleMaterializeRemoteSymbol(RemoteSymbolId Id)253   Expected<JITTargetAddress> handleMaterializeRemoteSymbol(RemoteSymbolId Id) {
254     auto SI = InUseSymbols.find(Id);
255     if (SI != InUseSymbols.end()) {
256       auto AddrOrErr = SI->second.getAddress();
257       InUseSymbols.erase(SI);
258       SymbolIdMgr.release(Id);
259       if (AddrOrErr)
260         return *AddrOrErr;
261       else
262         return teeLog(AddrOrErr.takeError());
263     } else {
264       return teeLog(badRemoteSymbolIdError(Id));
265     }
266   }
267 
268   remote::ResourceIdMgr SymbolIdMgr;
269   std::map<RemoteSymbolId, JITSymbol> InUseSymbols;
270 };
271 
272 /// RemoteObjectClientLayer forwards the ORC Object Layer API over an RPC
273 /// connection.
274 ///
275 /// This class can be used as the base layer of a JIT stack on the client and
276 /// will forward operations to a corresponding RemoteObjectServerLayer on the
277 /// server (which can be composed on top of a "real" object layer like
278 /// RTDyldObjectLinkingLayer to actually carry out the operations).
279 ///
280 /// Sending relocatable objects to the server (rather than fully relocated
281 /// bits) allows JIT'd code to be cached on the server side and re-used in
282 /// subsequent JIT sessions.
283 template <typename RPCEndpoint>
284 class RemoteObjectClientLayer : public RemoteObjectLayer<RPCEndpoint> {
285 private:
286 
287   using AddObject = RemoteObjectLayerAPI::AddObject;
288   using RemoveObject = RemoteObjectLayerAPI::RemoveObject;
289   using FindSymbol = RemoteObjectLayerAPI::FindSymbol;
290   using FindSymbolIn = RemoteObjectLayerAPI::FindSymbolIn;
291   using EmitAndFinalize = RemoteObjectLayerAPI::EmitAndFinalize;
292   using Lookup = RemoteObjectLayerAPI::Lookup;
293   using LookupInLogicalDylib = RemoteObjectLayerAPI::LookupInLogicalDylib;
294 
295   using RemoteObjectLayer<RPCEndpoint>::teeLog;
296   using RemoteObjectLayer<RPCEndpoint>::badObjectHandleError;
297   using RemoteObjectLayer<RPCEndpoint>::remoteToJITSymbol;
298 
299 public:
300 
301   using ObjHandleT = RemoteObjectLayerAPI::ObjHandleT;
302   using RemoteSymbol = RemoteObjectLayerAPI::RemoteSymbol;
303 
304   using ObjectPtr = std::unique_ptr<MemoryBuffer>;
305 
306   /// Create a RemoteObjectClientLayer that communicates with a
307   /// RemoteObjectServerLayer instance via the given RPCEndpoint.
308   ///
309   /// The ReportError functor can be used locally log errors that are intended
310   /// to be sent  sent
311   LLVM_ATTRIBUTE_DEPRECATED(
312       RemoteObjectClientLayer(RPCEndpoint &Remote,
313                               std::function<void(Error)> ReportError),
314       "ORCv1 layers (including RemoteObjectClientLayer) are deprecated. Please "
315       "use "
316       "ORCv2 (see docs/ORCv2.rst)");
317 
RemoteObjectClientLayer(ORCv1DeprecationAcknowledgement,RPCEndpoint & Remote,std::function<void (Error)> ReportError)318   RemoteObjectClientLayer(ORCv1DeprecationAcknowledgement, RPCEndpoint &Remote,
319                           std::function<void(Error)> ReportError)
320       : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)) {
321     using ThisT = RemoteObjectClientLayer<RPCEndpoint>;
322     Remote.template addHandler<Lookup>(*this, &ThisT::lookup);
323     Remote.template addHandler<LookupInLogicalDylib>(
324             *this, &ThisT::lookupInLogicalDylib);
325   }
326 
327   /// Add an object to the JIT.
328   ///
329   /// @return A handle that can be used to refer to the loaded object (for
330   ///         symbol searching, finalization, freeing memory, etc.).
331   Expected<ObjHandleT>
addObject(ObjectPtr ObjBuffer,std::shared_ptr<LegacyJITSymbolResolver> Resolver)332   addObject(ObjectPtr ObjBuffer,
333             std::shared_ptr<LegacyJITSymbolResolver> Resolver) {
334     if (auto HandleOrErr =
335             this->Remote.template callB<AddObject>(ObjBuffer->getBuffer())) {
336       auto &Handle = *HandleOrErr;
337       // FIXME: Return an error for this:
338       assert(!Resolvers.count(Handle) && "Handle already in use?");
339       Resolvers[Handle] = std::move(Resolver);
340       return Handle;
341     } else
342       return HandleOrErr.takeError();
343   }
344 
345   /// Remove the given object from the JIT.
removeObject(ObjHandleT H)346   Error removeObject(ObjHandleT H) {
347     return this->Remote.template callB<RemoveObject>(H);
348   }
349 
350   /// Search for the given named symbol.
findSymbol(StringRef Name,bool ExportedSymbolsOnly)351   JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
352     return remoteToJITSymbol(
353              this->Remote.template callB<FindSymbol>(Name,
354                                                      ExportedSymbolsOnly));
355   }
356 
357   /// Search for the given named symbol within the given context.
findSymbolIn(ObjHandleT H,StringRef Name,bool ExportedSymbolsOnly)358   JITSymbol findSymbolIn(ObjHandleT H, StringRef Name, bool ExportedSymbolsOnly) {
359     return remoteToJITSymbol(
360              this->Remote.template callB<FindSymbolIn>(H, Name,
361                                                        ExportedSymbolsOnly));
362   }
363 
364   /// Immediately emit and finalize the object with the given handle.
emitAndFinalize(ObjHandleT H)365   Error emitAndFinalize(ObjHandleT H) {
366     return this->Remote.template callB<EmitAndFinalize>(H);
367   }
368 
369 private:
370 
lookup(ObjHandleT H,const std::string & Name)371   Expected<RemoteSymbol> lookup(ObjHandleT H, const std::string &Name) {
372     auto RI = Resolvers.find(H);
373     if (RI != Resolvers.end()) {
374       return this->jitSymbolToRemote(RI->second->findSymbol(Name));
375     } else
376       return teeLog(badObjectHandleError(H));
377   }
378 
lookupInLogicalDylib(ObjHandleT H,const std::string & Name)379   Expected<RemoteSymbol> lookupInLogicalDylib(ObjHandleT H,
380                                               const std::string &Name) {
381     auto RI = Resolvers.find(H);
382     if (RI != Resolvers.end())
383       return this->jitSymbolToRemote(
384                RI->second->findSymbolInLogicalDylib(Name));
385     else
386       return teeLog(badObjectHandleError(H));
387   }
388 
389   std::map<remote::ResourceIdMgr::ResourceId,
390            std::shared_ptr<LegacyJITSymbolResolver>>
391       Resolvers;
392 };
393 
394 /// RemoteObjectServerLayer acts as a server and handling RPC calls for the
395 /// object layer API from the given RPC connection.
396 ///
397 /// This class can be composed on top of a 'real' object layer (e.g.
398 /// RTDyldObjectLinkingLayer) to do the actual work of relocating objects
399 /// and making them executable.
400 template <typename BaseLayerT, typename RPCEndpoint>
401 class RemoteObjectServerLayer : public RemoteObjectLayer<RPCEndpoint> {
402 private:
403 
404   using ObjHandleT = RemoteObjectLayerAPI::ObjHandleT;
405   using RemoteSymbol = RemoteObjectLayerAPI::RemoteSymbol;
406 
407   using AddObject = RemoteObjectLayerAPI::AddObject;
408   using RemoveObject = RemoteObjectLayerAPI::RemoveObject;
409   using FindSymbol = RemoteObjectLayerAPI::FindSymbol;
410   using FindSymbolIn = RemoteObjectLayerAPI::FindSymbolIn;
411   using EmitAndFinalize = RemoteObjectLayerAPI::EmitAndFinalize;
412   using Lookup = RemoteObjectLayerAPI::Lookup;
413   using LookupInLogicalDylib = RemoteObjectLayerAPI::LookupInLogicalDylib;
414 
415   using RemoteObjectLayer<RPCEndpoint>::teeLog;
416   using RemoteObjectLayer<RPCEndpoint>::badObjectHandleError;
417   using RemoteObjectLayer<RPCEndpoint>::remoteToJITSymbol;
418 
419 public:
420 
421   /// Create a RemoteObjectServerLayer with the given base layer (which must be
422   /// an object layer), RPC endpoint, and error reporter function.
423   LLVM_ATTRIBUTE_DEPRECATED(
424       RemoteObjectServerLayer(BaseLayerT &BaseLayer, RPCEndpoint &Remote,
425                               std::function<void(Error)> ReportError),
426       "ORCv1 layers (including RemoteObjectServerLayer) are deprecated. Please "
427       "use "
428       "ORCv2 (see docs/ORCv2.rst)");
429 
RemoteObjectServerLayer(ORCv1DeprecationAcknowledgement,BaseLayerT & BaseLayer,RPCEndpoint & Remote,std::function<void (Error)> ReportError)430   RemoteObjectServerLayer(ORCv1DeprecationAcknowledgement,
431                           BaseLayerT &BaseLayer, RPCEndpoint &Remote,
432                           std::function<void(Error)> ReportError)
433       : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)),
434         BaseLayer(BaseLayer), HandleIdMgr(1) {
435     using ThisT = RemoteObjectServerLayer<BaseLayerT, RPCEndpoint>;
436 
437     Remote.template addHandler<AddObject>(*this, &ThisT::addObject);
438     Remote.template addHandler<RemoveObject>(*this, &ThisT::removeObject);
439     Remote.template addHandler<FindSymbol>(*this, &ThisT::findSymbol);
440     Remote.template addHandler<FindSymbolIn>(*this, &ThisT::findSymbolIn);
441     Remote.template addHandler<EmitAndFinalize>(*this, &ThisT::emitAndFinalize);
442   }
443 
444 private:
445 
446   class StringMemoryBuffer : public MemoryBuffer {
447   public:
StringMemoryBuffer(std::string Buffer)448     StringMemoryBuffer(std::string Buffer)
449       : Buffer(std::move(Buffer)) {
450       init(this->Buffer.data(), this->Buffer.data() + this->Buffer.size(),
451            false);
452     }
453 
getBufferKind()454     BufferKind getBufferKind() const override { return MemoryBuffer_Malloc; }
455   private:
456     std::string Buffer;
457   };
458 
lookup(ObjHandleT Id,const std::string & Name)459   JITSymbol lookup(ObjHandleT Id, const std::string &Name) {
460     return remoteToJITSymbol(
461              this->Remote.template callB<Lookup>(Id, Name));
462   }
463 
lookupInLogicalDylib(ObjHandleT Id,const std::string & Name)464   JITSymbol lookupInLogicalDylib(ObjHandleT Id, const std::string &Name) {
465     return remoteToJITSymbol(
466              this->Remote.template callB<LookupInLogicalDylib>(Id, Name));
467   }
468 
addObject(std::string ObjBuffer)469   Expected<ObjHandleT> addObject(std::string ObjBuffer) {
470     auto Buffer = std::make_unique<StringMemoryBuffer>(std::move(ObjBuffer));
471     auto Id = HandleIdMgr.getNext();
472     assert(!BaseLayerHandles.count(Id) && "Id already in use?");
473 
474     auto Resolver = createLambdaResolver(
475         AcknowledgeORCv1Deprecation,
476         [this, Id](const std::string &Name) { return lookup(Id, Name); },
477         [this, Id](const std::string &Name) {
478           return lookupInLogicalDylib(Id, Name);
479         });
480 
481     if (auto HandleOrErr =
482             BaseLayer.addObject(std::move(Buffer), std::move(Resolver))) {
483       BaseLayerHandles[Id] = std::move(*HandleOrErr);
484       return Id;
485     } else
486       return teeLog(HandleOrErr.takeError());
487   }
488 
removeObject(ObjHandleT H)489   Error removeObject(ObjHandleT H) {
490     auto HI = BaseLayerHandles.find(H);
491     if (HI != BaseLayerHandles.end()) {
492       if (auto Err = BaseLayer.removeObject(HI->second))
493         return teeLog(std::move(Err));
494       return Error::success();
495     } else
496       return teeLog(badObjectHandleError(H));
497   }
498 
findSymbol(const std::string & Name,bool ExportedSymbolsOnly)499   Expected<RemoteSymbol> findSymbol(const std::string &Name,
500                                     bool ExportedSymbolsOnly) {
501     if (auto Sym = BaseLayer.findSymbol(Name, ExportedSymbolsOnly))
502       return this->jitSymbolToRemote(std::move(Sym));
503     else if (auto Err = Sym.takeError())
504       return teeLog(std::move(Err));
505     return this->nullRemoteSymbol();
506   }
507 
findSymbolIn(ObjHandleT H,const std::string & Name,bool ExportedSymbolsOnly)508   Expected<RemoteSymbol> findSymbolIn(ObjHandleT H, const std::string &Name,
509                                       bool ExportedSymbolsOnly) {
510     auto HI = BaseLayerHandles.find(H);
511     if (HI != BaseLayerHandles.end()) {
512       if (auto Sym = BaseLayer.findSymbolIn(HI->second, Name, ExportedSymbolsOnly))
513         return this->jitSymbolToRemote(std::move(Sym));
514       else if (auto Err = Sym.takeError())
515         return teeLog(std::move(Err));
516       return this->nullRemoteSymbol();
517     } else
518       return teeLog(badObjectHandleError(H));
519   }
520 
emitAndFinalize(ObjHandleT H)521   Error emitAndFinalize(ObjHandleT H) {
522     auto HI = BaseLayerHandles.find(H);
523     if (HI != BaseLayerHandles.end()) {
524       if (auto Err = BaseLayer.emitAndFinalize(HI->second))
525         return teeLog(std::move(Err));
526       return Error::success();
527     } else
528       return teeLog(badObjectHandleError(H));
529   }
530 
531   BaseLayerT &BaseLayer;
532   remote::ResourceIdMgr HandleIdMgr;
533   std::map<ObjHandleT, typename BaseLayerT::ObjHandleT> BaseLayerHandles;
534 };
535 
536 template <typename RPCEndpoint>
RemoteObjectClientLayer(RPCEndpoint & Remote,std::function<void (Error)> ReportError)537 RemoteObjectClientLayer<RPCEndpoint>::RemoteObjectClientLayer(
538     RPCEndpoint &Remote, std::function<void(Error)> ReportError)
539     : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)) {
540   using ThisT = RemoteObjectClientLayer<RPCEndpoint>;
541   Remote.template addHandler<Lookup>(*this, &ThisT::lookup);
542   Remote.template addHandler<LookupInLogicalDylib>(
543       *this, &ThisT::lookupInLogicalDylib);
544 }
545 
546 template <typename BaseLayerT, typename RPCEndpoint>
RemoteObjectServerLayer(BaseLayerT & BaseLayer,RPCEndpoint & Remote,std::function<void (Error)> ReportError)547 RemoteObjectServerLayer<BaseLayerT, RPCEndpoint>::RemoteObjectServerLayer(
548     BaseLayerT &BaseLayer, RPCEndpoint &Remote,
549     std::function<void(Error)> ReportError)
550     : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)),
551       BaseLayer(BaseLayer), HandleIdMgr(1) {
552   using ThisT = RemoteObjectServerLayer<BaseLayerT, RPCEndpoint>;
553 
554   Remote.template addHandler<AddObject>(*this, &ThisT::addObject);
555   Remote.template addHandler<RemoveObject>(*this, &ThisT::removeObject);
556   Remote.template addHandler<FindSymbol>(*this, &ThisT::findSymbol);
557   Remote.template addHandler<FindSymbolIn>(*this, &ThisT::findSymbolIn);
558   Remote.template addHandler<EmitAndFinalize>(*this, &ThisT::emitAndFinalize);
559 }
560 
561 } // end namespace orc
562 } // end namespace llvm
563 
564 #endif // LLVM_EXECUTIONENGINE_ORC_REMOTEOBJECTLAYER_H
565