LLVM  3.7.0
lib/ExecutionEngine/Orc/OrcMCJITReplacement.h
Go to the documentation of this file.
1 //===---- OrcMCJITReplacement.h - Orc based MCJIT replacement ---*- 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 // Orc based MCJIT replacement.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_LIB_EXECUTIONENGINE_ORC_ORCMCJITREPLACEMENT_H
15 #define LLVM_LIB_EXECUTIONENGINE_ORC_ORCMCJITREPLACEMENT_H
16 
22 #include "llvm/Object/Archive.h"
23 
24 namespace llvm {
25 namespace orc {
26 
28 
29  // OrcMCJITReplacement needs to do a little extra book-keeping to ensure that
30  // Orc's automatic finalization doesn't kick in earlier than MCJIT clients are
31  // expecting - see finalizeMemory.
32  class MCJITReplacementMemMgr : public MCJITMemoryManager {
33  public:
34  MCJITReplacementMemMgr(OrcMCJITReplacement &M,
35  std::shared_ptr<MCJITMemoryManager> ClientMM)
36  : M(M), ClientMM(std::move(ClientMM)) {}
37 
38  uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
39  unsigned SectionID,
40  StringRef SectionName) override {
41  uint8_t *Addr =
42  ClientMM->allocateCodeSection(Size, Alignment, SectionID,
43  SectionName);
44  M.SectionsAllocatedSinceLastLoad.insert(Addr);
45  return Addr;
46  }
47 
48  uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
49  unsigned SectionID, StringRef SectionName,
50  bool IsReadOnly) override {
51  uint8_t *Addr = ClientMM->allocateDataSection(Size, Alignment, SectionID,
52  SectionName, IsReadOnly);
53  M.SectionsAllocatedSinceLastLoad.insert(Addr);
54  return Addr;
55  }
56 
57  void reserveAllocationSpace(uintptr_t CodeSize, uintptr_t DataSizeRO,
58  uintptr_t DataSizeRW) override {
59  return ClientMM->reserveAllocationSpace(CodeSize, DataSizeRO,
60  DataSizeRW);
61  }
62 
63  bool needsToReserveAllocationSpace() override {
64  return ClientMM->needsToReserveAllocationSpace();
65  }
66 
67  void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
68  size_t Size) override {
69  return ClientMM->registerEHFrames(Addr, LoadAddr, Size);
70  }
71 
72  void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr,
73  size_t Size) override {
74  return ClientMM->deregisterEHFrames(Addr, LoadAddr, Size);
75  }
76 
77  void notifyObjectLoaded(ExecutionEngine *EE,
78  const object::ObjectFile &O) override {
79  return ClientMM->notifyObjectLoaded(EE, O);
80  }
81 
82  bool finalizeMemory(std::string *ErrMsg = nullptr) override {
83  // Each set of objects loaded will be finalized exactly once, but since
84  // symbol lookup during relocation may recursively trigger the
85  // loading/relocation of other modules, and since we're forwarding all
86  // finalizeMemory calls to a single underlying memory manager, we need to
87  // defer forwarding the call on until all necessary objects have been
88  // loaded. Otherwise, during the relocation of a leaf object, we will end
89  // up finalizing memory, causing a crash further up the stack when we
90  // attempt to apply relocations to finalized memory.
91  // To avoid finalizing too early, look at how many objects have been
92  // loaded but not yet finalized. This is a bit of a hack that relies on
93  // the fact that we're lazily emitting object files: The only way you can
94  // get more than one set of objects loaded but not yet finalized is if
95  // they were loaded during relocation of another set.
96  if (M.UnfinalizedSections.size() == 1)
97  return ClientMM->finalizeMemory(ErrMsg);
98  return false;
99  }
100 
101  private:
103  std::shared_ptr<MCJITMemoryManager> ClientMM;
104  };
105 
106  class LinkingResolver : public RuntimeDyld::SymbolResolver {
107  public:
108  LinkingResolver(OrcMCJITReplacement &M) : M(M) {}
109 
110  RuntimeDyld::SymbolInfo findSymbol(const std::string &Name) override {
111  return M.findMangledSymbol(Name);
112  }
113 
115  findSymbolInLogicalDylib(const std::string &Name) override {
116  return M.ClientResolver->findSymbolInLogicalDylib(Name);
117  }
118 
119  private:
121  };
122 
123 private:
124 
125  static ExecutionEngine *
126  createOrcMCJITReplacement(std::string *ErrorMsg,
127  std::shared_ptr<MCJITMemoryManager> MemMgr,
128  std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver,
129  std::unique_ptr<TargetMachine> TM) {
130  return new OrcMCJITReplacement(std::move(MemMgr), std::move(Resolver),
131  std::move(TM));
132  }
133 
134 public:
135  static void Register() {
136  OrcMCJITReplacementCtor = createOrcMCJITReplacement;
137  }
138 
140  std::shared_ptr<MCJITMemoryManager> MemMgr,
141  std::shared_ptr<RuntimeDyld::SymbolResolver> ClientResolver,
142  std::unique_ptr<TargetMachine> TM)
143  : TM(std::move(TM)), MemMgr(*this, std::move(MemMgr)),
144  Resolver(*this), ClientResolver(std::move(ClientResolver)),
145  NotifyObjectLoaded(*this), NotifyFinalized(*this),
146  ObjectLayer(NotifyObjectLoaded, NotifyFinalized),
147  CompileLayer(ObjectLayer, SimpleCompiler(*this->TM)),
148  LazyEmitLayer(CompileLayer) {
149  setDataLayout(this->TM->getDataLayout());
150  }
151 
152  void addModule(std::unique_ptr<Module> M) override {
153 
154  // If this module doesn't have a DataLayout attached then attach the
155  // default.
156  if (M->getDataLayout().isDefault())
157  M->setDataLayout(*getDataLayout());
158 
159  Modules.push_back(std::move(M));
160  std::vector<Module *> Ms;
161  Ms.push_back(&*Modules.back());
162  LazyEmitLayer.addModuleSet(std::move(Ms), &MemMgr, &Resolver);
163  }
164 
165  void addObjectFile(std::unique_ptr<object::ObjectFile> O) override {
166  std::vector<std::unique_ptr<object::ObjectFile>> Objs;
167  Objs.push_back(std::move(O));
168  ObjectLayer.addObjectSet(std::move(Objs), &MemMgr, &Resolver);
169  }
170 
172  std::unique_ptr<object::ObjectFile> Obj;
173  std::unique_ptr<MemoryBuffer> Buf;
174  std::tie(Obj, Buf) = O.takeBinary();
175  std::vector<std::unique_ptr<object::ObjectFile>> Objs;
176  Objs.push_back(std::move(Obj));
177  auto H =
178  ObjectLayer.addObjectSet(std::move(Objs), &MemMgr, &Resolver);
179 
180  std::vector<std::unique_ptr<MemoryBuffer>> Bufs;
181  Bufs.push_back(std::move(Buf));
182  ObjectLayer.takeOwnershipOfBuffers(H, std::move(Bufs));
183  }
184 
186  Archives.push_back(std::move(A));
187  }
188 
190  return findSymbol(Name).getAddress();
191  }
192 
194  return findMangledSymbol(Mangle(Name));
195  }
196 
197  void finalizeObject() override {
198  // This is deprecated - Aim to remove in ExecutionEngine.
199  // REMOVE IF POSSIBLE - Doesn't make sense for New JIT.
200  }
201 
202  void mapSectionAddress(const void *LocalAddress,
203  uint64_t TargetAddress) override {
204  for (auto &P : UnfinalizedSections)
205  if (P.second.count(LocalAddress))
206  ObjectLayer.mapSectionAddress(P.first, LocalAddress, TargetAddress);
207  }
208 
209  uint64_t getGlobalValueAddress(const std::string &Name) override {
210  return getSymbolAddress(Name);
211  }
212 
213  uint64_t getFunctionAddress(const std::string &Name) override {
214  return getSymbolAddress(Name);
215  }
216 
217  void *getPointerToFunction(Function *F) override {
218  uint64_t FAddr = getSymbolAddress(F->getName());
219  return reinterpret_cast<void *>(static_cast<uintptr_t>(FAddr));
220  }
221 
223  bool AbortOnFailure = true) override {
224  uint64_t Addr = getSymbolAddress(Name);
225  if (!Addr && AbortOnFailure)
226  llvm_unreachable("Missing symbol!");
227  return reinterpret_cast<void *>(static_cast<uintptr_t>(Addr));
228  }
229 
231  ArrayRef<GenericValue> ArgValues) override;
232 
233  void setObjectCache(ObjectCache *NewCache) override {
234  CompileLayer.setObjectCache(NewCache);
235  }
236 
237 private:
238 
239  RuntimeDyld::SymbolInfo findMangledSymbol(StringRef Name) {
240  if (auto Sym = LazyEmitLayer.findSymbol(Name, false))
241  return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags());
242  if (auto Sym = ClientResolver->findSymbol(Name))
243  return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags());
244  if (auto Sym = scanArchives(Name))
245  return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags());
246 
247  return nullptr;
248  }
249 
250  JITSymbol scanArchives(StringRef Name) {
251  for (object::OwningBinary<object::Archive> &OB : Archives) {
252  object::Archive *A = OB.getBinary();
253  // Look for our symbols in each Archive
254  object::Archive::child_iterator ChildIt = A->findSym(Name);
255  if (ChildIt != A->child_end()) {
256  // FIXME: Support nested archives?
258  ChildIt->getAsBinary();
259  if (ChildBinOrErr.getError())
260  continue;
261  std::unique_ptr<object::Binary> &ChildBin = ChildBinOrErr.get();
262  if (ChildBin->isObject()) {
263  std::vector<std::unique_ptr<object::ObjectFile>> ObjSet;
264  ObjSet.push_back(std::unique_ptr<object::ObjectFile>(
265  static_cast<object::ObjectFile *>(ChildBin.release())));
266  ObjectLayer.addObjectSet(std::move(ObjSet), &MemMgr, &Resolver);
267  if (auto Sym = ObjectLayer.findSymbol(Name, true))
268  return Sym;
269  }
270  }
271  }
272  return nullptr;
273  }
274 
275  class NotifyObjectLoadedT {
276  public:
277  typedef std::vector<std::unique_ptr<object::ObjectFile>> ObjListT;
278  typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>
279  LoadedObjInfoListT;
280 
281  NotifyObjectLoadedT(OrcMCJITReplacement &M) : M(M) {}
282 
284  const ObjListT &Objects,
285  const LoadedObjInfoListT &Infos) const {
286  M.UnfinalizedSections[H] = std::move(M.SectionsAllocatedSinceLastLoad);
287  M.SectionsAllocatedSinceLastLoad = SectionAddrSet();
288  assert(Objects.size() == Infos.size() &&
289  "Incorrect number of Infos for Objects.");
290  for (unsigned I = 0; I < Objects.size(); ++I)
291  M.MemMgr.notifyObjectLoaded(&M, *Objects[I]);
292  };
293 
294  private:
296  };
297 
298  class NotifyFinalizedT {
299  public:
300  NotifyFinalizedT(OrcMCJITReplacement &M) : M(M) {}
301  void operator()(ObjectLinkingLayerBase::ObjSetHandleT H) {
302  M.UnfinalizedSections.erase(H);
303  }
304 
305  private:
307  };
308 
309  std::string Mangle(StringRef Name) {
310  std::string MangledName;
311  {
312  raw_string_ostream MangledNameStream(MangledName);
313  Mang.getNameWithPrefix(MangledNameStream, Name, *TM->getDataLayout());
314  }
315  return MangledName;
316  }
317 
318  typedef ObjectLinkingLayer<NotifyObjectLoadedT> ObjectLayerT;
319  typedef IRCompileLayer<ObjectLayerT> CompileLayerT;
320  typedef LazyEmittingLayer<CompileLayerT> LazyEmitLayerT;
321 
322  std::unique_ptr<TargetMachine> TM;
323  MCJITReplacementMemMgr MemMgr;
324  LinkingResolver Resolver;
325  std::shared_ptr<RuntimeDyld::SymbolResolver> ClientResolver;
326  Mangler Mang;
327 
328  NotifyObjectLoadedT NotifyObjectLoaded;
329  NotifyFinalizedT NotifyFinalized;
330 
331  ObjectLayerT ObjectLayer;
332  CompileLayerT CompileLayer;
333  LazyEmitLayerT LazyEmitLayer;
334 
335  // We need to store ObjLayerT::ObjSetHandles for each of the object sets
336  // that have been emitted but not yet finalized so that we can forward the
337  // mapSectionAddress calls appropriately.
338  typedef std::set<const void *> SectionAddrSet;
339  struct ObjSetHandleCompare {
340  bool operator()(ObjectLayerT::ObjSetHandleT H1,
341  ObjectLayerT::ObjSetHandleT H2) const {
342  return &*H1 < &*H2;
343  }
344  };
345  SectionAddrSet SectionsAllocatedSinceLastLoad;
346  std::map<ObjectLayerT::ObjSetHandleT, SectionAddrSet, ObjSetHandleCompare>
347  UnfinalizedSections;
348 
349  std::vector<object::OwningBinary<object::Archive>> Archives;
350 };
351 
352 } // End namespace orc.
353 } // End namespace llvm.
354 
355 #endif // LLVM_LIB_EXECUTIONENGINE_ORC_MCJITREPLACEMENT_H
void addObjectFile(std::unique_ptr< object::ObjectFile > O) override
addObjectFile - Add an ObjectFile to the execution engine.
std::error_code getError() const
Definition: ErrorOr.h:178
Represents either an error or a value T.
Definition: ErrorOr.h:82
static ExecutionEngine *(* OrcMCJITReplacementCtor)(std::string *ErrorStr, std::shared_ptr< MCJITMemoryManager > MM, std::shared_ptr< RuntimeDyld::SymbolResolver > SR, std::unique_ptr< TargetMachine > TM)
JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly)
Search for the given named symbol.
ModuleSetHandleT addModuleSet(ModuleSetT Ms, MemoryManagerPtrT MemMgr, SymbolResolverPtrT Resolver)
Add the given set of modules to the lazy emitting layer.
ErrorOr< std::unique_ptr< Binary > > getAsBinary(LLVMContext *Context=nullptr) const
Definition: Archive.cpp:214
void finalizeObject() override
finalizeObject - ensure the module is fully processed and is usable.
uint64_t getAddress() const
Definition: RuntimeDyld.h:53
This class is the base class for all object file types.
Definition: ObjectFile.h:176
ObjSetHandleT addObjectSet(const ObjSetT &Objects, MemoryManagerPtrT MemMgr, SymbolResolverPtrT Resolver)
Add a set of objects (or archives) that will be treated as a unit for the purposes of symbol lookup a...
F(f)
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:188
uint64_t getFunctionAddress(const std::string &Name) override
getFunctionAddress - Return the address of the specified function.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:98
void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress, TargetAddress TargetAddr)
Map section addresses for the objects associated with the handle H.
Simple compile functor: Takes a single IR module and returns an ObjectFile.
Definition: CompileUtils.h:28
OrcMCJITReplacement(std::shared_ptr< MCJITMemoryManager > MemMgr, std::shared_ptr< RuntimeDyld::SymbolResolver > ClientResolver, std::unique_ptr< TargetMachine > TM)
void setObjectCache(ObjectCache *NewCache)
Set an ObjectCache to query before compiling.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: ArrayRef.h:31
GenericValue runFunction(Function *F, ArrayRef< GenericValue > ArgValues) override
runFunction - Execute the specified function with the specified arguments, and return the result...
uint64_t getGlobalValueAddress(const std::string &Name) override
getGlobalValueAddress - Return the address of the specified global value.
#define P(N)
child_iterator child_end() const
Definition: Archive.cpp:372
void addObjectFile(object::OwningBinary< object::ObjectFile > O) override
#define H(x, y, z)
Definition: MD5.cpp:53
void setObjectCache(ObjectCache *NewCache) override
Sets the pre-compiled object cache.
void setDataLayout(const DataLayout *Val)
void * getPointerToFunction(Function *F) override
getPointerToFunction - The different EE's represent function bodies in different ways.
Abstract interface for implementation execution of LLVM modules, designed to support both interpreter...
child_iterator findSym(StringRef name) const
Definition: Archive.cpp:528
std::pair< std::unique_ptr< T >, std::unique_ptr< MemoryBuffer > > takeBinary()
Definition: Binary.h:168
void takeOwnershipOfBuffers(ObjSetHandleT H, OwningMBSet MBs)
JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly)
Search for the given named symbol.
uint64_t TargetAddress
Represents an address in the target process's address space.
Definition: JITSymbol.h:26
SmallVector< std::unique_ptr< Module >, 1 > Modules
The list of Modules that we are JIT'ing from.
const DataLayout * getDataLayout() const
void getNameWithPrefix(raw_ostream &OS, const GlobalValue *GV, bool CannotUsePrivateLabel) const
Print the appropriate prefix and the specified global variable's name.
Definition: Mangler.cpp:108
#define I(x, y, z)
Definition: MD5.cpp:54
Information about a named symbol.
Definition: RuntimeDyld.h:47
This is the base ObjectCache type which can be provided to an ExecutionEngine for the purpose of avoi...
Definition: ObjectCache.h:22
void addModule(std::unique_ptr< Module > M) override
Add a Module to the list of modules that we can JIT from.
void * getPointerToNamedFunction(StringRef Name, bool AbortOnFailure=true) override
getPointerToNamedFunction - This method returns the address of the specified function by using the dl...
void addArchive(object::OwningBinary< object::Archive > A) override
addArchive - Add an Archive to the execution engine.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:40
RuntimeDyld::SymbolInfo findSymbol(StringRef Name)
void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress) override
mapSectionAddress - map a section to its target address space value.
LinkedObjectSetListT::iterator ObjSetHandleT
Handle to a set of loaded objects.
reference get()
Definition: ErrorOr.h:175