LLVM  7.0.0svn
OrcCBindingsStack.h
Go to the documentation of this file.
1 //===- OrcCBindingsStack.h - Orc JIT stack for C bindings -----*- 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 #ifndef LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
11 #define LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
12 
13 #include "llvm-c/OrcBindings.h"
14 #include "llvm-c/TargetMachine.h"
15 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/ADT/StringRef.h"
26 #include "llvm/IR/DataLayout.h"
27 #include "llvm/IR/Mangler.h"
28 #include "llvm/IR/Module.h"
30 #include "llvm/Support/Error.h"
33 #include <algorithm>
34 #include <cstdint>
35 #include <functional>
36 #include <map>
37 #include <memory>
38 #include <set>
39 #include <string>
40 #include <vector>
41 
42 namespace llvm {
43 
44 class OrcCBindingsStack;
45 
46 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(std::shared_ptr<Module>,
50 
51 namespace detail {
52 
53 // FIXME: Kill this off once the Layer concept becomes an interface.
54 class GenericLayer {
55 public:
56  virtual ~GenericLayer() = default;
57 
58  virtual JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
59  bool ExportedSymbolsOnly) = 0;
60  virtual Error removeModule(orc::VModuleKey K) = 0;
61  };
62 
63  template <typename LayerT> class GenericLayerImpl : public GenericLayer {
64  public:
65  GenericLayerImpl(LayerT &Layer) : Layer(Layer) {}
66 
67  JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
68  bool ExportedSymbolsOnly) override {
69  return Layer.findSymbolIn(K, Name, ExportedSymbolsOnly);
70  }
71 
72  Error removeModule(orc::VModuleKey K) override {
73  return Layer.removeModule(K);
74  }
75 
76  private:
77  LayerT &Layer;
78  };
79 
80  template <>
81  class GenericLayerImpl<orc::RTDyldObjectLinkingLayer> : public GenericLayer {
82  private:
83  using LayerT = orc::RTDyldObjectLinkingLayer;
84  public:
85  GenericLayerImpl(LayerT &Layer) : Layer(Layer) {}
86 
87  JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
88  bool ExportedSymbolsOnly) override {
89  return Layer.findSymbolIn(K, Name, ExportedSymbolsOnly);
90  }
91 
92  Error removeModule(orc::VModuleKey K) override {
93  return Layer.removeObject(K);
94  }
95 
96  private:
97  LayerT &Layer;
98  };
99 
100  template <typename LayerT>
101  std::unique_ptr<GenericLayerImpl<LayerT>> createGenericLayer(LayerT &Layer) {
102  return llvm::make_unique<GenericLayerImpl<LayerT>>(Layer);
103  }
104 
105 } // end namespace detail
106 
108 public:
109 
113  using CODLayerT =
115 
116  using CallbackManagerBuilder =
117  std::function<std::unique_ptr<CompileCallbackMgr>()>;
118 
120 
121 private:
122 
124 
125  class CBindingsResolver : public orc::SymbolResolver {
126  public:
127  CBindingsResolver(OrcCBindingsStack &Stack,
128  LLVMOrcSymbolResolverFn ExternalResolver,
129  void *ExternalResolverCtx)
130  : Stack(Stack), ExternalResolver(std::move(ExternalResolver)),
131  ExternalResolverCtx(std::move(ExternalResolverCtx)) {}
132 
133  orc::SymbolNameSet lookupFlags(orc::SymbolFlagsMap &SymbolFlags,
134  const orc::SymbolNameSet &Symbols) override {
135  orc::SymbolNameSet SymbolsNotFound;
136 
137  for (auto &S : Symbols) {
138  if (auto Sym = findSymbol(*S))
139  SymbolFlags[S] = Sym.getFlags();
140  else if (auto Err = Sym.takeError()) {
141  Stack.reportError(std::move(Err));
142  return orc::SymbolNameSet();
143  } else
144  SymbolsNotFound.insert(S);
145  }
146 
147  return SymbolsNotFound;
148  }
149 
151  lookup(std::shared_ptr<orc::AsynchronousSymbolQuery> Query,
152  orc::SymbolNameSet Symbols) override {
153  orc::SymbolNameSet UnresolvedSymbols;
154 
155  for (auto &S : Symbols) {
156  if (auto Sym = findSymbol(*S)) {
157  if (auto Addr = Sym.getAddress())
158  Query->setDefinition(S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
159  else {
160  Query->setFailed(Addr.takeError());
161  return orc::SymbolNameSet();
162  }
163  } else if (auto Err = Sym.takeError()) {
164  Query->setFailed(std::move(Err));
165  return orc::SymbolNameSet();
166  } else
167  UnresolvedSymbols.insert(S);
168  }
169 
170  return UnresolvedSymbols;
171  }
172 
173  private:
174  JITSymbol findSymbol(const std::string &Name) {
175  // Search order:
176  // 1. JIT'd symbols.
177  // 2. Runtime overrides.
178  // 3. External resolver (if present).
179 
180  if (auto Sym = Stack.CODLayer.findSymbol(Name, true))
181  return Sym;
182  else if (auto Err = Sym.takeError())
183  return Sym.takeError();
184 
185  if (auto Sym = Stack.CXXRuntimeOverrides.searchOverrides(Name))
186  return Sym;
187 
188  if (ExternalResolver)
189  return JITSymbol(ExternalResolver(Name.c_str(), ExternalResolverCtx),
191 
192  return JITSymbol(nullptr);
193  }
194 
195  OrcCBindingsStack &Stack;
196  LLVMOrcSymbolResolverFn ExternalResolver;
197  void *ExternalResolverCtx = nullptr;
198  };
199 
200 public:
201 
203  std::unique_ptr<CompileCallbackMgr> CCMgr,
204  IndirectStubsManagerBuilder IndirectStubsMgrBuilder)
205  : ES(SSP), DL(TM.createDataLayout()),
206  IndirectStubsMgr(IndirectStubsMgrBuilder()), CCMgr(std::move(CCMgr)),
207  ObjectLayer(ES,
208  [this](orc::VModuleKey K) {
209  auto ResolverI = Resolvers.find(K);
210  assert(ResolverI != Resolvers.end() &&
211  "No resolver for module K");
212  auto Resolver = std::move(ResolverI->second);
213  Resolvers.erase(ResolverI);
214  return ObjLayerT::Resources{
215  std::make_shared<SectionMemoryManager>(), Resolver};
216  }),
217  CompileLayer(ObjectLayer, orc::SimpleCompiler(TM)),
218  CODLayer(ES, CompileLayer,
219  [this](orc::VModuleKey K) {
220  auto ResolverI = Resolvers.find(K);
221  assert(ResolverI != Resolvers.end() &&
222  "No resolver for module K");
223  return ResolverI->second;
224  },
225  [this](orc::VModuleKey K,
226  std::shared_ptr<orc::SymbolResolver> Resolver) {
227  assert(!Resolvers.count(K) && "Resolver already present");
228  Resolvers[K] = std::move(Resolver);
229  },
230  [](Function &F) { return std::set<Function *>({&F}); },
231  *this->CCMgr, std::move(IndirectStubsMgrBuilder), false),
232  CXXRuntimeOverrides(
233  [this](const std::string &S) { return mangle(S); }) {}
234 
236  // Run any destructors registered with __cxa_atexit.
237  CXXRuntimeOverrides.runDestructors();
238  // Run any IR destructors.
239  for (auto &DtorRunner : IRStaticDestructorRunners)
240  if (auto Err = DtorRunner.runViaLayer(*this))
241  return mapError(std::move(Err));
242  return LLVMOrcErrSuccess;
243  }
244 
245  std::string mangle(StringRef Name) {
246  std::string MangledName;
247  {
248  raw_string_ostream MangledNameStream(MangledName);
249  Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
250  }
251  return MangledName;
252  }
253 
254  template <typename PtrTy>
255  static PtrTy fromTargetAddress(JITTargetAddress Addr) {
256  return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr));
257  }
258 
259 
263  void *CallbackCtx) {
264  if (auto CCInfoOrErr = CCMgr->getCompileCallback()) {
265  auto &CCInfo = *CCInfoOrErr;
266  CCInfo.setCompileAction([=]() -> JITTargetAddress {
267  return Callback(wrap(this), CallbackCtx);
268  });
269  RetAddr = CCInfo.getAddress();
270  return LLVMOrcErrSuccess;
271  } else
272  return mapError(CCInfoOrErr.takeError());
273  }
274 
276  JITTargetAddress Addr) {
277  return mapError(
278  IndirectStubsMgr->createStub(StubName, Addr, JITSymbolFlags::Exported));
279  }
280 
282  JITTargetAddress Addr) {
283  return mapError(IndirectStubsMgr->updatePointer(Name, Addr));
284  }
285  template <typename LayerT>
287  addIRModule(orc::VModuleKey &RetKey, LayerT &Layer, std::shared_ptr<Module> M,
288  std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr,
289  LLVMOrcSymbolResolverFn ExternalResolver,
290  void *ExternalResolverCtx) {
291 
292  // Attach a data-layout if one isn't already present.
293  if (M->getDataLayout().isDefault())
294  M->setDataLayout(DL);
295 
296  // Record the static constructors and destructors. We have to do this before
297  // we hand over ownership of the module to the JIT.
298  std::vector<std::string> CtorNames, DtorNames;
299  for (auto Ctor : orc::getConstructors(*M))
300  CtorNames.push_back(mangle(Ctor.Func->getName()));
301  for (auto Dtor : orc::getDestructors(*M))
302  DtorNames.push_back(mangle(Dtor.Func->getName()));
303 
304  // Add the module to the JIT.
305  RetKey = ES.allocateVModule();
306  Resolvers[RetKey] = std::make_shared<CBindingsResolver>(
307  *this, ExternalResolver, ExternalResolverCtx);
308  if (auto Err = Layer.addModule(RetKey, std::move(M)))
309  return mapError(std::move(Err));
310 
311  KeyLayers[RetKey] = detail::createGenericLayer(Layer);
312 
313  // Run the static constructors, and save the static destructor runner for
314  // execution when the JIT is torn down.
315  orc::CtorDtorRunner<OrcCBindingsStack> CtorRunner(std::move(CtorNames),
316  RetKey);
317  if (auto Err = CtorRunner.runViaLayer(*this))
318  return mapError(std::move(Err));
319 
320  IRStaticDestructorRunners.emplace_back(std::move(DtorNames), RetKey);
321 
322  return LLVMOrcErrSuccess;
323  }
324 
326  std::shared_ptr<Module> M,
327  LLVMOrcSymbolResolverFn ExternalResolver,
328  void *ExternalResolverCtx) {
329  return addIRModule(RetKey, CompileLayer, std::move(M),
330  llvm::make_unique<SectionMemoryManager>(),
331  std::move(ExternalResolver), ExternalResolverCtx);
332  }
333 
335  std::shared_ptr<Module> M,
336  LLVMOrcSymbolResolverFn ExternalResolver,
337  void *ExternalResolverCtx) {
338  return addIRModule(RetKey, CODLayer, std::move(M),
339  llvm::make_unique<SectionMemoryManager>(),
340  std::move(ExternalResolver), ExternalResolverCtx);
341  }
342 
344  // FIXME: Should error release the module key?
345  if (auto Err = KeyLayers[K]->removeModule(K))
346  return mapError(std::move(Err));
347  ES.releaseVModule(K);
348  KeyLayers.erase(K);
349  return LLVMOrcErrSuccess;
350  }
351 
353  std::unique_ptr<MemoryBuffer> ObjBuffer,
354  LLVMOrcSymbolResolverFn ExternalResolver,
355  void *ExternalResolverCtx) {
356  if (auto ObjOrErr =
357  object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef())) {
358  auto &Obj = *ObjOrErr;
359  auto OwningObj =
360  std::make_shared<OwningObject>(std::move(Obj), std::move(ObjBuffer));
361 
362  RetKey = ES.allocateVModule();
363  Resolvers[RetKey] = std::make_shared<CBindingsResolver>(
364  *this, ExternalResolver, ExternalResolverCtx);
365 
366  if (auto Err = ObjectLayer.addObject(RetKey, std::move(OwningObj)))
367  return mapError(std::move(Err));
368 
369  KeyLayers[RetKey] = detail::createGenericLayer(ObjectLayer);
370 
371  return LLVMOrcErrSuccess;
372  } else
373  return mapError(ObjOrErr.takeError());
374  }
375 
376  JITSymbol findSymbol(const std::string &Name,
377  bool ExportedSymbolsOnly) {
378  if (auto Sym = IndirectStubsMgr->findStub(Name, ExportedSymbolsOnly))
379  return Sym;
380  return CODLayer.findSymbol(mangle(Name), ExportedSymbolsOnly);
381  }
382 
384  bool ExportedSymbolsOnly) {
385  return KeyLayers[K]->findSymbolIn(K, Name, ExportedSymbolsOnly);
386  }
387 
389  const std::string &Name,
390  bool ExportedSymbolsOnly) {
391  RetAddr = 0;
392  if (auto Sym = findSymbol(Name, ExportedSymbolsOnly)) {
393  // Successful lookup, non-null symbol:
394  if (auto AddrOrErr = Sym.getAddress()) {
395  RetAddr = *AddrOrErr;
396  return LLVMOrcErrSuccess;
397  } else
398  return mapError(AddrOrErr.takeError());
399  } else if (auto Err = Sym.takeError()) {
400  // Lookup failure - report error.
401  return mapError(std::move(Err));
402  }
403  // Otherwise we had a successful lookup but got a null result. We already
404  // set RetAddr to '0' above, so just return success.
405  return LLVMOrcErrSuccess;
406  }
407 
408  const std::string &getErrorMessage() const { return ErrMsg; }
409 
410 private:
411 
412  LLVMOrcErrorCode mapError(Error Err) {
414  handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
415  // Handler of last resort.
416  Result = LLVMOrcErrGeneric;
417  ErrMsg = "";
418  raw_string_ostream ErrStream(ErrMsg);
419  EIB.log(ErrStream);
420  });
421  return Result;
422  }
423 
424  void reportError(Error Err) {
425  // FIXME: Report errors on the execution session.
426  logAllUnhandledErrors(std::move(Err), errs(), "ORC error: ");
427  };
428 
431 
432  DataLayout DL;
433  SectionMemoryManager CCMgrMemMgr;
434 
435  std::unique_ptr<orc::IndirectStubsManager> IndirectStubsMgr;
436 
437  std::unique_ptr<CompileCallbackMgr> CCMgr;
438  ObjLayerT ObjectLayer;
439  CompileLayerT CompileLayer;
440  CODLayerT CODLayer;
441 
442  std::map<orc::VModuleKey, std::unique_ptr<detail::GenericLayer>> KeyLayers;
443 
444  orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides;
445  std::vector<orc::CtorDtorRunner<OrcCBindingsStack>> IRStaticDestructorRunners;
446  std::string ErrMsg;
447 
448  std::map<orc::VModuleKey, std::shared_ptr<orc::SymbolResolver>> Resolvers;
449 };
450 
451 } // end namespace llvm
452 
453 #endif // LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
static Expected< OwningBinary< ObjectFile > > createObjectFile(StringRef ObjectPath)
Create ObjectFile from path.
Definition: ObjectFile.cpp:152
A parsed version of the target data layout string in and methods for querying it. ...
Definition: DataLayout.h:111
LLVMOrcErrorCode addIRModuleEager(orc::VModuleKey &RetKey, std::shared_ptr< Module > M, LLVMOrcSymbolResolverFn ExternalResolver, void *ExternalResolverCtx)
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
CODLayerT::IndirectStubsManagerBuilderT IndirectStubsManagerBuilder
Represents a symbol in the JIT.
Definition: JITSymbol.h:180
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
String pool for symbol names used by the JIT.
void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner)
Log all errors (if any) in E to OS.
Definition: Error.cpp:57
std::function< std::unique_ptr< CompileCallbackMgr >()> CallbackManagerBuilder
LLVMOrcErrorCode setIndirectStubPointer(StringRef Name, JITTargetAddress Addr)
Bare bones object linking layer.
F(f)
LLVMOrcErrorCode addIRModule(orc::VModuleKey &RetKey, LayerT &Layer, std::shared_ptr< Module > M, std::unique_ptr< RuntimeDyld::MemoryManager > MemMgr, LLVMOrcSymbolResolverFn ExternalResolver, void *ExternalResolverCtx)
Base class for error info classes.
Definition: Error.h:47
uint64_t VModuleKey
VModuleKey provides a unique identifier (allocated and managed by ExecutionSessions) for a module add...
Definition: Core.h:30
Target-independent base class for compile callback management.
Definition: BitVector.h:920
struct LLVMOpaqueTargetMachine * LLVMTargetMachineRef
Definition: TargetMachine.h:28
std::map< SymbolStringPtr, JITSymbolFlags > SymbolFlagsMap
A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags.
Definition: Core.h:43
std::function< std::unique_ptr< IndirectStubsManager >()> IndirectStubsManagerBuilderT
Builder for IndirectStubsManagers.
virtual void log(raw_ostream &OS) const =0
Print an error message to an output stream.
LLVMOrcErrorCode shutdown()
Simple compile functor: Takes a single IR module and returns an ObjectFile.
Definition: CompileUtils.h:40
static const uint16_t * lookup(unsigned opcode, unsigned domain, ArrayRef< uint16_t[3]> Table)
JITEvaluatedSymbol searchOverrides(const std::string &Name)
Search overrided symbols.
Support class for static dtor execution.
struct LLVMOpaqueSharedModule * LLVMSharedModuleRef
Definition: OrcBindings.h:32
iterator_range< CtorDtorIterator > getDestructors(const Module &M)
Create an iterator range over the entries of the llvm.global_ctors array.
LLVMOrcErrorCode addIRModuleLazy(orc::VModuleKey &RetKey, std::shared_ptr< Module > M, LLVMOrcSymbolResolverFn ExternalResolver, void *ExternalResolverCtx)
LLVMOrcErrorCode addObject(orc::VModuleKey &RetKey, std::unique_ptr< MemoryBuffer > ObjBuffer, LLVMOrcSymbolResolverFn ExternalResolver, void *ExternalResolverCtx)
LLVMOrcErrorCode removeModule(orc::VModuleKey K)
OrcCBindingsStack(TargetMachine &TM, std::unique_ptr< CompileCallbackMgr > CCMgr, IndirectStubsManagerBuilder IndirectStubsMgrBuilder)
LLVMOrcErrorCode
Definition: OrcBindings.h:40
uint64_t JITTargetAddress
Represents an address in the target process&#39;s address space.
Definition: JITSymbol.h:40
Error runViaLayer(JITLayerT &JITLayer) const
Run the recorded constructors/destructors through the given JIT layer.
Convenience class for recording constructor/destructor names for later execution. ...
LLVMOrcErrorCode createIndirectStub(StringRef StubName, JITTargetAddress Addr)
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(std::shared_ptr< Module >, LLVMSharedModuleRef) namespace detail
std::string mangle(StringRef Name)
JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name, bool ExportedSymbolsOnly)
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that it requires that all errors be handled by the given han...
Definition: Error.h:889
Module.h This file contains the declarations for the Module class.
LLVMOrcErrorCode createLazyCompileCallback(JITTargetAddress &RetAddr, LLVMOrcLazyCompileCallbackFn Callback, void *CallbackCtx)
uint64_t(* LLVMOrcLazyCompileCallbackFn)(LLVMOrcJITStackRef JITStack, void *CallbackCtx)
Definition: OrcBindings.h:37
An ExecutionSession represents a running JIT program.
Definition: Core.h:310
SymbolResolver is a composable interface for looking up symbol flags and addresses using the Asynchro...
Definition: Core.h:99
Represents a symbol that has been evaluated to an address already.
Definition: JITSymbol.h:154
const std::string & getErrorMessage() const
static PtrTy fromTargetAddress(JITTargetAddress Addr)
static int reportError(const char *ProgName, Twine Msg)
Definition: Main.cpp:49
uint64_t(* LLVMOrcSymbolResolverFn)(const char *Name, void *LookupCtx)
Definition: OrcBindings.h:36
LLVMAttributeRef wrap(Attribute Attr)
Definition: Attributes.h:190
iterator_range< CtorDtorIterator > getConstructors(const Module &M)
Create an iterator range over the entries of the llvm.global_ctors array.
static void Query(const MachineInstr &MI, AliasAnalysis &AA, bool &Read, bool &Write, bool &Effects, bool &StackPointer)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This is a simple memory manager which implements the methods called by the RuntimeDyld class to alloc...
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:462
JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly)
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:59
void getNameWithPrefix(raw_ostream &OS, const GlobalValue *GV, bool CannotUsePrivateLabel) const
Print the appropriate prefix and the specified global variable&#39;s name.
Definition: Mangler.cpp:109
Error takeError()
Move the error field value out of this JITSymbol.
Definition: JITSymbol.h:248
JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly)
Search for the given named symbol.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
struct LLVMOrcOpaqueJITStack * LLVMOrcJITStackRef
Definition: OrcBindings.h:33
std::set< SymbolStringPtr > SymbolNameSet
A set of symbol names (represented by SymbolStringPtrs for.
Definition: Core.h:36
LLVMOrcErrorCode findSymbolAddress(JITTargetAddress &RetAddr, const std::string &Name, bool ExportedSymbolsOnly)