LLVM  10.0.0svn
RemoteObjectLayer.h
Go to the documentation of this file.
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 
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.
27 public:
28 
30 
31 protected:
32 
34  using RemoteSymbol = std::pair<RemoteSymbolId, JITSymbolFlags>;
35 
36 public:
37 
40 
41 protected:
42 
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 
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 
66  : public rpc::Function<FindSymbolIn,
67  Expected<RemoteSymbol>(ObjHandleT, std::string,
68  bool)> {
69  public:
70  static const char *getName() { return "FindSymbolIn"; }
71  };
72 
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 
88  : public rpc::Function<LookupInLogicalDylib,
89  Expected<RemoteSymbol>(ObjHandleT, std::string)> {
90  public:
91  static const char *getName() { return "LookupInLogicalDylib"; }
92  };
93 
95  : public rpc::Function<ReleaseRemoteSymbol, Error(RemoteSymbolId)> {
96  public:
97  static const char *getName() { return "ReleaseRemoteSymbol"; }
98  };
99 
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>
112 public:
113 
114  RemoteObjectLayer(RPCEndpoint &Remote,
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.
132  public:
133 
134  /// Construct a RemoteSymbolMaterializer for the given RemoteObjectLayer
135  /// with the given Id.
138  : C(C), Id(Id) {}
139 
141  : C(Other.C), Id(Other.Id) {
142  Other.Id = 0;
143  }
144 
145  RemoteSymbolMaterializer &operator=(RemoteSymbolMaterializer &&) = delete;
146 
147  /// Release the remote symbol.
149  if (Id)
150  C.releaseRemoteSymbol(Id);
151  }
152 
153  /// Materialize the symbol on the remote and get its address.
155  auto Addr = C.materializeRemoteSymbol(Id);
156  Id = 0;
157  return Addr;
158  }
159 
160  private:
163  };
164 
165  /// Convenience function for getting a null remote symbol value.
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.
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 
186  return make_error<BadSymbolHandleError>(Id, "Remote JIT Symbol");
187  }
188 
190  return make_error<RemoteObjectLayerAPI::BadObjectHandleError>(
191  H, "Bad object handle");
192  }
193 
194  /// Create a RemoteSymbol wrapping the given JITSymbol.
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.
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.
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.
237  Expected<JITTargetAddress> materializeRemoteSymbol(RemoteSymbolId Id) {
238  return Remote.template callB<MaterializeRemoteSymbol>(Id);
239  }
240 
241  /// Release the JITSymbol with the given 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.
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 
294 
298 
299 public:
300 
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
312  RemoteObjectClientLayer(RPCEndpoint &Remote,
314  "ORCv1 layers (including RemoteObjectClientLayer) are deprecated. Please "
315  "use "
316  "ORCv2 (see docs/ORCv2.rst)");
317 
320  : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)) {
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.).
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.
347  return this->Remote.template callB<RemoveObject>(H);
348  }
349 
350  /// Search for the given named symbol.
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.
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.
366  return this->Remote.template callB<EmitAndFinalize>(H);
367  }
368 
369 private:
370 
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 
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 
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 
406 
414 
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.
424  RemoteObjectServerLayer(BaseLayerT &BaseLayer, RPCEndpoint &Remote,
426  "ORCv1 layers (including RemoteObjectServerLayer) are deprecated. Please "
427  "use "
428  "ORCv2 (see docs/ORCv2.rst)");
429 
431  BaseLayerT &BaseLayer, RPCEndpoint &Remote,
433  : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)),
434  BaseLayer(BaseLayer), HandleIdMgr(1) {
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:
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 
454  BufferKind getBufferKind() const override { return MemoryBuffer_Malloc; }
455  private:
456  std::string Buffer;
457  };
458 
459  JITSymbol lookup(ObjHandleT Id, const std::string &Name) {
460  return remoteToJITSymbol(
461  this->Remote.template callB<Lookup>(Id, Name));
462  }
463 
464  JITSymbol lookupInLogicalDylib(ObjHandleT Id, const std::string &Name) {
465  return remoteToJITSymbol(
466  this->Remote.template callB<LookupInLogicalDylib>(Id, Name));
467  }
468 
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 
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 
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 
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 
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 
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>
538  RPCEndpoint &Remote, std::function<void(Error)> ReportError)
539  : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)) {
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>
548  BaseLayerT &BaseLayer, RPCEndpoint &Remote,
550  : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)),
551  BaseLayer(BaseLayer), HandleIdMgr(1) {
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
uint64_t CallInst * C
RemoteObjectClientLayer(ORCv1DeprecationAcknowledgement, RPCEndpoint &Remote, std::function< void(Error)> ReportError)
Represents a symbol in the JIT.
Definition: JITSymbol.h:219
This class represents lattice values for constants.
Definition: AllocatorList.h:23
RemoteSymbol nullRemoteSymbol()
Convenience function for getting a null remote symbol value.
amdgpu Simplify well known AMD library false FunctionCallee Value const Twine & Name
RemoteObjectServerLayer(ORCv1DeprecationAcknowledgement, BaseLayerT &BaseLayer, RPCEndpoint &Remote, std::function< void(Error)> ReportError)
Error badObjectHandleError(ObjHandleT H)
Optional< std::vector< StOtherPiece > > Other
Definition: ELFYAML.cpp:953
Error takeError()
Take ownership of the stored error.
Definition: Error.h:552
remote::ResourceIdMgr::ResourceId ObjHandleT
JITSymbolFlags getFlags() const
Definition: JITSymbol.h:308
std::unique_ptr< MemoryBuffer > ObjectPtr
Definition: BitVector.h:937
RemoteObjectLayer(RPCEndpoint &Remote, std::function< void(Error)> ReportError)
static int Lookup(ArrayRef< TableEntry > Table, unsigned Opcode)
Tagged union holding either a T or a Error.
Definition: yaml2obj.h:21
Error emitAndFinalize(ObjHandleT H)
Immediately emit and finalize the object with the given handle.
static const uint16_t * lookup(unsigned opcode, unsigned domain, ArrayRef< uint16_t[3]> Table)
ORCv1DeprecationAcknowledgement
JITSymbol remoteToJITSymbol(Expected< RemoteSymbol > RemoteSymOrErr)
Convert an Expected<RemoteSymbol> to a JITSymbol.
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:432
Expected< RemoteSymbol > jitSymbolToRemote(JITSymbol Sym)
Create a RemoteSymbol wrapping the given JITSymbol.
static void LLVM_ATTRIBUTE_NORETURN ReportError(uint64_t StartOffset, const char *ErrorMsg)
#define H(x, y, z)
Definition: MD5.cpp:57
Interface for looking up the initializer for a variable name, used by Init::resolveReferences.
Definition: Record.h:1863
This class is used as the symbol materializer for JITSymbols returned by RemoteObjectLayerClient/Remo...
RemoteSymbolMaterializer(RemoteObjectLayer &C, RemoteSymbolId Id)
Construct a RemoteSymbolMaterializer for the given RemoteObjectLayer with the given Id...
Error badRemoteSymbolIdError(RemoteSymbolId Id)
static const RemoteSymbolId NullSymbolId
Flags for symbols in the JIT.
Definition: JITSymbol.h:56
remote::ResourceIdMgr::ResourceId RemoteSymbolId
JITSymbol findSymbolIn(ObjHandleT H, StringRef Name, bool ExportedSymbolsOnly)
Search for the given named symbol within the given context.
RPC API needed by RemoteObjectClientLayer and RemoteObjectServerLayer.
std::function< void(Error)> ReportError
Expected< ObjHandleT > addObject(ObjectPtr ObjBuffer, std::shared_ptr< LegacyJITSymbolResolver > Resolver)
Add an object to the JIT.
Template error for missing resources.
JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly)
Search for the given named symbol.
#define LLVM_ATTRIBUTE_DEPRECATED(decl, message)
Definition: Compiler.h:296
static ErrorSuccess success()
Create a success value.
Definition: Error.h:326
std::pair< RemoteSymbolId, JITSymbolFlags > RemoteSymbol
Base class containing common utilities for RemoteObjectClientLayer and RemoteObjectServerLayer.
RemoteSymbolMaterializer(RemoteSymbolMaterializer &&Other)
RemoteObjectServerLayer acts as a server and handling RPC calls for the object layer API from the giv...
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition: MemoryBuffer.h:41
Error teeLog(Error Err)
Creates a StringError that contains a copy of Err&#39;s log message, then sends that StringError to Repor...
static const ObjHandleT InvalidObjectHandleId
RemoteObjectClientLayer forwards the ORC Object Layer API over an RPC connection. ...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Error removeObject(ObjHandleT H)
Remove the given object from the JIT.
std::shared_ptr< LambdaResolver< DylibLookupFtorT, ExternalLookupFtorT > > createLambdaResolver(DylibLookupFtorT DylibLookupFtor, ExternalLookupFtorT ExternalLookupFtor)
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
Error handleErrors(Error E, HandlerTs &&... Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
Definition: Error.h:881
Error takeError()
Move the error field value out of this JITSymbol.
Definition: JITSymbol.h:287
print Print MemDeps of function
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
Expected< JITTargetAddress > materialize()
Materialize the symbol on the remote and get its address.