LLVM  4.0.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 
17 #include "llvm/ADT/ArrayRef.h"
18 #include "llvm/ADT/STLExtras.h"
19 #include "llvm/ADT/StringRef.h"
28 #include "llvm/IR/Function.h"
29 #include "llvm/IR/Mangler.h"
30 #include "llvm/Object/Archive.h"
31 #include "llvm/Object/Binary.h"
32 #include "llvm/Object/ObjectFile.h"
33 #include "llvm/Support/Error.h"
37 #include <cassert>
38 #include <cstddef>
39 #include <cstdint>
40 #include <algorithm>
41 #include <map>
42 #include <memory>
43 #include <set>
44 #include <string>
45 #include <vector>
46 
47 namespace llvm {
48 namespace orc {
49 
51  // OrcMCJITReplacement needs to do a little extra book-keeping to ensure that
52  // Orc's automatic finalization doesn't kick in earlier than MCJIT clients are
53  // expecting - see finalizeMemory.
54  class MCJITReplacementMemMgr : public MCJITMemoryManager {
55  public:
56  MCJITReplacementMemMgr(OrcMCJITReplacement &M,
57  std::shared_ptr<MCJITMemoryManager> ClientMM)
58  : M(M), ClientMM(std::move(ClientMM)) {}
59 
60  uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
61  unsigned SectionID,
62  StringRef SectionName) override {
63  uint8_t *Addr =
64  ClientMM->allocateCodeSection(Size, Alignment, SectionID,
65  SectionName);
66  M.SectionsAllocatedSinceLastLoad.insert(Addr);
67  return Addr;
68  }
69 
70  uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
71  unsigned SectionID, StringRef SectionName,
72  bool IsReadOnly) override {
73  uint8_t *Addr = ClientMM->allocateDataSection(Size, Alignment, SectionID,
74  SectionName, IsReadOnly);
75  M.SectionsAllocatedSinceLastLoad.insert(Addr);
76  return Addr;
77  }
78 
79  void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign,
80  uintptr_t RODataSize, uint32_t RODataAlign,
81  uintptr_t RWDataSize,
82  uint32_t RWDataAlign) override {
83  return ClientMM->reserveAllocationSpace(CodeSize, CodeAlign,
84  RODataSize, RODataAlign,
85  RWDataSize, RWDataAlign);
86  }
87 
88  bool needsToReserveAllocationSpace() override {
89  return ClientMM->needsToReserveAllocationSpace();
90  }
91 
92  void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
93  size_t Size) override {
94  return ClientMM->registerEHFrames(Addr, LoadAddr, Size);
95  }
96 
97  void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr,
98  size_t Size) override {
99  return ClientMM->deregisterEHFrames(Addr, LoadAddr, Size);
100  }
101 
102  void notifyObjectLoaded(RuntimeDyld &RTDyld,
103  const object::ObjectFile &O) override {
104  return ClientMM->notifyObjectLoaded(RTDyld, O);
105  }
106 
107  void notifyObjectLoaded(ExecutionEngine *EE,
108  const object::ObjectFile &O) override {
109  return ClientMM->notifyObjectLoaded(EE, O);
110  }
111 
112  bool finalizeMemory(std::string *ErrMsg = nullptr) override {
113  // Each set of objects loaded will be finalized exactly once, but since
114  // symbol lookup during relocation may recursively trigger the
115  // loading/relocation of other modules, and since we're forwarding all
116  // finalizeMemory calls to a single underlying memory manager, we need to
117  // defer forwarding the call on until all necessary objects have been
118  // loaded. Otherwise, during the relocation of a leaf object, we will end
119  // up finalizing memory, causing a crash further up the stack when we
120  // attempt to apply relocations to finalized memory.
121  // To avoid finalizing too early, look at how many objects have been
122  // loaded but not yet finalized. This is a bit of a hack that relies on
123  // the fact that we're lazily emitting object files: The only way you can
124  // get more than one set of objects loaded but not yet finalized is if
125  // they were loaded during relocation of another set.
126  if (M.UnfinalizedSections.size() == 1)
127  return ClientMM->finalizeMemory(ErrMsg);
128  return false;
129  }
130 
131  private:
133  std::shared_ptr<MCJITMemoryManager> ClientMM;
134  };
135 
136  class LinkingResolver : public JITSymbolResolver {
137  public:
138  LinkingResolver(OrcMCJITReplacement &M) : M(M) {}
139 
140  JITSymbol findSymbol(const std::string &Name) override {
141  return M.ClientResolver->findSymbol(Name);
142  }
143 
144  JITSymbol findSymbolInLogicalDylib(const std::string &Name) override {
145  if (auto Sym = M.findMangledSymbol(Name))
146  return Sym;
147  return M.ClientResolver->findSymbolInLogicalDylib(Name);
148  }
149 
150  private:
152  };
153 
154 private:
155 
156  static ExecutionEngine *
157  createOrcMCJITReplacement(std::string *ErrorMsg,
158  std::shared_ptr<MCJITMemoryManager> MemMgr,
159  std::shared_ptr<JITSymbolResolver> Resolver,
160  std::unique_ptr<TargetMachine> TM) {
161  return new OrcMCJITReplacement(std::move(MemMgr), std::move(Resolver),
162  std::move(TM));
163  }
164 
165 public:
166  static void Register() {
167  OrcMCJITReplacementCtor = createOrcMCJITReplacement;
168  }
169 
171  std::shared_ptr<MCJITMemoryManager> MemMgr,
172  std::shared_ptr<JITSymbolResolver> ClientResolver,
173  std::unique_ptr<TargetMachine> TM)
174  : ExecutionEngine(TM->createDataLayout()), TM(std::move(TM)),
175  MemMgr(*this, std::move(MemMgr)), Resolver(*this),
176  ClientResolver(std::move(ClientResolver)), NotifyObjectLoaded(*this),
177  NotifyFinalized(*this),
178  ObjectLayer(NotifyObjectLoaded, NotifyFinalized),
179  CompileLayer(ObjectLayer, SimpleCompiler(*this->TM)),
180  LazyEmitLayer(CompileLayer) {}
181 
182  void addModule(std::unique_ptr<Module> M) override {
183 
184  // If this module doesn't have a DataLayout attached then attach the
185  // default.
186  if (M->getDataLayout().isDefault()) {
187  M->setDataLayout(getDataLayout());
188  } else {
189  assert(M->getDataLayout() == getDataLayout() && "DataLayout Mismatch");
190  }
191  Modules.push_back(std::move(M));
192  std::vector<Module *> Ms;
193  Ms.push_back(&*Modules.back());
194  LazyEmitLayer.addModuleSet(std::move(Ms), &MemMgr, &Resolver);
195  }
196 
197  void addObjectFile(std::unique_ptr<object::ObjectFile> O) override {
198  std::vector<std::unique_ptr<object::ObjectFile>> Objs;
199  Objs.push_back(std::move(O));
200  ObjectLayer.addObjectSet(std::move(Objs), &MemMgr, &Resolver);
201  }
202 
204  std::vector<std::unique_ptr<object::OwningBinary<object::ObjectFile>>> Objs;
205  Objs.push_back(
207  std::move(O)));
208  ObjectLayer.addObjectSet(std::move(Objs), &MemMgr, &Resolver);
209  }
210 
212  Archives.push_back(std::move(A));
213  }
214 
216  return findSymbol(Name).getAddress();
217  }
218 
220  return findMangledSymbol(Mangle(Name));
221  }
222 
223  void finalizeObject() override {
224  // This is deprecated - Aim to remove in ExecutionEngine.
225  // REMOVE IF POSSIBLE - Doesn't make sense for New JIT.
226  }
227 
228  void mapSectionAddress(const void *LocalAddress,
229  uint64_t TargetAddress) override {
230  for (auto &P : UnfinalizedSections)
231  if (P.second.count(LocalAddress))
232  ObjectLayer.mapSectionAddress(P.first, LocalAddress, TargetAddress);
233  }
234 
235  uint64_t getGlobalValueAddress(const std::string &Name) override {
236  return getSymbolAddress(Name);
237  }
238 
239  uint64_t getFunctionAddress(const std::string &Name) override {
240  return getSymbolAddress(Name);
241  }
242 
243  void *getPointerToFunction(Function *F) override {
244  uint64_t FAddr = getSymbolAddress(F->getName());
245  return reinterpret_cast<void *>(static_cast<uintptr_t>(FAddr));
246  }
247 
249  bool AbortOnFailure = true) override {
250  uint64_t Addr = getSymbolAddress(Name);
251  if (!Addr && AbortOnFailure)
252  llvm_unreachable("Missing symbol!");
253  return reinterpret_cast<void *>(static_cast<uintptr_t>(Addr));
254  }
255 
257  ArrayRef<GenericValue> ArgValues) override;
258 
259  void setObjectCache(ObjectCache *NewCache) override {
260  CompileLayer.setObjectCache(NewCache);
261  }
262 
263  void setProcessAllSections(bool ProcessAllSections) override {
264  ObjectLayer.setProcessAllSections(ProcessAllSections);
265  }
266 
267 private:
268  JITSymbol findMangledSymbol(StringRef Name) {
269  if (auto Sym = LazyEmitLayer.findSymbol(Name, false))
270  return Sym;
271  if (auto Sym = ClientResolver->findSymbol(Name))
272  return Sym;
273  if (auto Sym = scanArchives(Name))
274  return Sym;
275 
276  return nullptr;
277  }
278 
279  JITSymbol scanArchives(StringRef Name) {
280  for (object::OwningBinary<object::Archive> &OB : Archives) {
281  object::Archive *A = OB.getBinary();
282  // Look for our symbols in each Archive
283  auto OptionalChildOrErr = A->findSym(Name);
284  if (!OptionalChildOrErr)
285  report_fatal_error(OptionalChildOrErr.takeError());
286  auto &OptionalChild = *OptionalChildOrErr;
287  if (OptionalChild) {
288  // FIXME: Support nested archives?
290  OptionalChild->getAsBinary();
291  if (!ChildBinOrErr) {
292  // TODO: Actually report errors helpfully.
293  consumeError(ChildBinOrErr.takeError());
294  continue;
295  }
296  std::unique_ptr<object::Binary> &ChildBin = ChildBinOrErr.get();
297  if (ChildBin->isObject()) {
298  std::vector<std::unique_ptr<object::ObjectFile>> ObjSet;
299  ObjSet.push_back(std::unique_ptr<object::ObjectFile>(
300  static_cast<object::ObjectFile *>(ChildBin.release())));
301  ObjectLayer.addObjectSet(std::move(ObjSet), &MemMgr, &Resolver);
302  if (auto Sym = ObjectLayer.findSymbol(Name, true))
303  return Sym;
304  }
305  }
306  }
307  return nullptr;
308  }
309 
310  class NotifyObjectLoadedT {
311  public:
312  typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>
313  LoadedObjInfoListT;
314 
315  NotifyObjectLoadedT(OrcMCJITReplacement &M) : M(M) {}
316 
317  template <typename ObjListT>
319  const ObjListT &Objects,
320  const LoadedObjInfoListT &Infos) const {
321  M.UnfinalizedSections[H] = std::move(M.SectionsAllocatedSinceLastLoad);
322  M.SectionsAllocatedSinceLastLoad = SectionAddrSet();
323  assert(Objects.size() == Infos.size() &&
324  "Incorrect number of Infos for Objects.");
325  for (unsigned I = 0; I < Objects.size(); ++I)
326  M.MemMgr.notifyObjectLoaded(&M, getObject(*Objects[I]));
327  }
328 
329  private:
330  static const object::ObjectFile& getObject(const object::ObjectFile &Obj) {
331  return Obj;
332  }
333 
334  template <typename ObjT>
335  static const object::ObjectFile&
336  getObject(const object::OwningBinary<ObjT> &Obj) {
337  return *Obj.getBinary();
338  }
339 
341  };
342 
343  class NotifyFinalizedT {
344  public:
345  NotifyFinalizedT(OrcMCJITReplacement &M) : M(M) {}
346 
347  void operator()(ObjectLinkingLayerBase::ObjSetHandleT H) {
348  M.UnfinalizedSections.erase(H);
349  }
350 
351  private:
353  };
354 
355  std::string Mangle(StringRef Name) {
356  std::string MangledName;
357  {
358  raw_string_ostream MangledNameStream(MangledName);
359  Mang.getNameWithPrefix(MangledNameStream, Name, getDataLayout());
360  }
361  return MangledName;
362  }
363 
364  typedef ObjectLinkingLayer<NotifyObjectLoadedT> ObjectLayerT;
365  typedef IRCompileLayer<ObjectLayerT> CompileLayerT;
366  typedef LazyEmittingLayer<CompileLayerT> LazyEmitLayerT;
367 
368  std::unique_ptr<TargetMachine> TM;
369  MCJITReplacementMemMgr MemMgr;
370  LinkingResolver Resolver;
371  std::shared_ptr<JITSymbolResolver> ClientResolver;
372  Mangler Mang;
373 
374  NotifyObjectLoadedT NotifyObjectLoaded;
375  NotifyFinalizedT NotifyFinalized;
376 
377  ObjectLayerT ObjectLayer;
378  CompileLayerT CompileLayer;
379  LazyEmitLayerT LazyEmitLayer;
380 
381  // We need to store ObjLayerT::ObjSetHandles for each of the object sets
382  // that have been emitted but not yet finalized so that we can forward the
383  // mapSectionAddress calls appropriately.
384  typedef std::set<const void *> SectionAddrSet;
385  struct ObjSetHandleCompare {
386  bool operator()(ObjectLayerT::ObjSetHandleT H1,
387  ObjectLayerT::ObjSetHandleT H2) const {
388  return &*H1 < &*H2;
389  }
390  };
391  SectionAddrSet SectionsAllocatedSinceLastLoad;
392  std::map<ObjectLayerT::ObjSetHandleT, SectionAddrSet, ObjSetHandleCompare>
393  UnfinalizedSections;
394 
395  std::vector<object::OwningBinary<object::Archive>> Archives;
396 };
397 
398 } // end namespace orc
399 } // end namespace llvm
400 
401 #endif // LLVM_LIB_EXECUTIONENGINE_ORC_MCJITREPLACEMENT_H
void addObjectFile(std::unique_ptr< object::ObjectFile > O) override
addObjectFile - Add an ObjectFile to the execution engine.
JITTargetAddress getAddress()
Get the address of the symbol in the target address space.
Definition: JITSymbol.h:147
Represents a symbol in the JIT.
Definition: JITSymbol.h:113
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
ObjSetHandleT addObjectSet(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...
Expected< Optional< Child > > findSym(StringRef name) const
Definition: Archive.cpp:957
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.
static std::error_code getObject(const T *&Obj, MemoryBufferRef M, const void *Ptr, const uint64_t Size=sizeof(T))
void finalizeObject() override
finalizeObject - ensure the module is fully processed and is usable.
This class is the base class for all object file types.
Definition: ObjectFile.h:178
Error takeError()
Take ownership of the stored error.
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:191
const DataLayout & getDataLayout() const
uint64_t getFunctionAddress(const std::string &Name) override
getFunctionAddress - Return the address of the specified function.
Tagged union holding either a T or a Error.
Simple compile functor: Takes a single IR module and returns an ObjectFile.
Definition: CompileUtils.h:28
#define F(x, y, z)
Definition: MD5.cpp:51
void setObjectCache(ObjectCache *NewCache)
Set an ObjectCache to query before compiling.
OrcMCJITReplacement(std::shared_ptr< MCJITMemoryManager > MemMgr, std::shared_ptr< JITSymbolResolver > ClientResolver, std::unique_ptr< TargetMachine > TM)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:33
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)
static ExecutionEngine *(* OrcMCJITReplacementCtor)(std::string *ErrorStr, std::shared_ptr< MCJITMemoryManager > MM, std::shared_ptr< JITSymbolResolver > SR, std::unique_ptr< TargetMachine > TM)
std::enable_if<!std::is_array< T >::value, std::unique_ptr< T > >::type make_unique(Args &&...args)
Constructs a new T() with the given args and returns a unique_ptr<T> which owns the object...
Definition: STLExtras.h:845
void addObjectFile(object::OwningBinary< object::ObjectFile > O) override
#define H(x, y, z)
Definition: MD5.cpp:53
void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress, JITTargetAddress TargetAddr)
Map section addresses for the objects associated with the handle H.
Symbol resolution.
Definition: JITSymbol.h:165
void setObjectCache(ObjectCache *NewCache) override
Sets the pre-compiled object cache.
void consumeError(Error Err)
Consume a Error without doing anything.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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...
JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly)
Search for the given named symbol.
reference get()
Returns a reference to the stored T value.
SmallVector< std::unique_ptr< Module >, 1 > Modules
The list of Modules that we are JIT'ing from.
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
void setProcessAllSections(bool ProcessAllSections) override
setProcessAllSections (MCJIT Only): By default, only sections that are "required for execution" are p...
This is the base ObjectCache type which can be provided to an ExecutionEngine for the purpose of avoi...
Definition: ObjectCache.h:23
const char SectionName[]
Definition: AMDGPUPTNote.h:24
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...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void addArchive(object::OwningBinary< object::Archive > A) override
addArchive - Add an Archive to the execution engine.
void setProcessAllSections(bool ProcessAllSections)
Set the 'ProcessAllSections' flag.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
static GCRegistry::Add< ErlangGC > A("erlang","erlang-compatible garbage collector")
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.