]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r303197, and update
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / ExecutionEngine / Orc / OrcMCJITReplacement.h
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"
20 #include "llvm/ExecutionEngine/ExecutionEngine.h"
21 #include "llvm/ExecutionEngine/GenericValue.h"
22 #include "llvm/ExecutionEngine/JITSymbol.h"
23 #include "llvm/ExecutionEngine/RuntimeDyld.h"
24 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
25 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
26 #include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h"
27 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.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"
34 #include "llvm/Support/ErrorHandling.h"
35 #include "llvm/Support/raw_ostream.h"
36 #include "llvm/Target/TargetMachine.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
50 class OrcMCJITReplacement : public ExecutionEngine {
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() override {
98       return ClientMM->deregisterEHFrames();
99     }
100
101     void notifyObjectLoaded(RuntimeDyld &RTDyld,
102                             const object::ObjectFile &O) override {
103       return ClientMM->notifyObjectLoaded(RTDyld, O);
104     }
105
106     void notifyObjectLoaded(ExecutionEngine *EE,
107                             const object::ObjectFile &O) override {
108       return ClientMM->notifyObjectLoaded(EE, O);
109     }
110
111     bool finalizeMemory(std::string *ErrMsg = nullptr) override {
112       // Each set of objects loaded will be finalized exactly once, but since
113       // symbol lookup during relocation may recursively trigger the
114       // loading/relocation of other modules, and since we're forwarding all
115       // finalizeMemory calls to a single underlying memory manager, we need to
116       // defer forwarding the call on until all necessary objects have been
117       // loaded. Otherwise, during the relocation of a leaf object, we will end
118       // up finalizing memory, causing a crash further up the stack when we
119       // attempt to apply relocations to finalized memory.
120       // To avoid finalizing too early, look at how many objects have been
121       // loaded but not yet finalized. This is a bit of a hack that relies on
122       // the fact that we're lazily emitting object files: The only way you can
123       // get more than one set of objects loaded but not yet finalized is if
124       // they were loaded during relocation of another set.
125       if (M.UnfinalizedSections.size() == 1)
126         return ClientMM->finalizeMemory(ErrMsg);
127       return false;
128     }
129
130   private:
131     OrcMCJITReplacement &M;
132     std::shared_ptr<MCJITMemoryManager> ClientMM;
133   };
134
135   class LinkingResolver : public JITSymbolResolver {
136   public:
137     LinkingResolver(OrcMCJITReplacement &M) : M(M) {}
138
139     JITSymbol findSymbol(const std::string &Name) override {
140       return M.ClientResolver->findSymbol(Name);
141     }
142
143     JITSymbol findSymbolInLogicalDylib(const std::string &Name) override {
144       if (auto Sym = M.findMangledSymbol(Name))
145         return Sym;
146       return M.ClientResolver->findSymbolInLogicalDylib(Name);
147     }
148
149   private:
150     OrcMCJITReplacement &M;
151   };
152
153 private:
154
155   static ExecutionEngine *
156   createOrcMCJITReplacement(std::string *ErrorMsg,
157                             std::shared_ptr<MCJITMemoryManager> MemMgr,
158                             std::shared_ptr<JITSymbolResolver> Resolver,
159                             std::unique_ptr<TargetMachine> TM) {
160     return new OrcMCJITReplacement(std::move(MemMgr), std::move(Resolver),
161                                    std::move(TM));
162   }
163
164 public:
165   static void Register() {
166     OrcMCJITReplacementCtor = createOrcMCJITReplacement;
167   }
168
169   OrcMCJITReplacement(
170       std::shared_ptr<MCJITMemoryManager> MemMgr,
171       std::shared_ptr<JITSymbolResolver> ClientResolver,
172       std::unique_ptr<TargetMachine> TM)
173       : ExecutionEngine(TM->createDataLayout()), TM(std::move(TM)),
174         MemMgr(*this, std::move(MemMgr)), Resolver(*this),
175         ClientResolver(std::move(ClientResolver)), NotifyObjectLoaded(*this),
176         NotifyFinalized(*this),
177         ObjectLayer(NotifyObjectLoaded, NotifyFinalized),
178         CompileLayer(ObjectLayer, SimpleCompiler(*this->TM)),
179         LazyEmitLayer(CompileLayer) {}
180
181   void addModule(std::unique_ptr<Module> M) override {
182
183     // If this module doesn't have a DataLayout attached then attach the
184     // default.
185     if (M->getDataLayout().isDefault()) {
186       M->setDataLayout(getDataLayout());
187     } else {
188       assert(M->getDataLayout() == getDataLayout() && "DataLayout Mismatch");
189     }
190     Modules.push_back(std::move(M));
191     std::vector<Module *> Ms;
192     Ms.push_back(&*Modules.back());
193     LazyEmitLayer.addModuleSet(std::move(Ms), &MemMgr, &Resolver);
194   }
195
196   void addObjectFile(std::unique_ptr<object::ObjectFile> O) override {
197     std::vector<std::unique_ptr<object::ObjectFile>> Objs;
198     Objs.push_back(std::move(O));
199     ObjectLayer.addObjectSet(std::move(Objs), &MemMgr, &Resolver);
200   }
201
202   void addObjectFile(object::OwningBinary<object::ObjectFile> O) override {
203     std::vector<std::unique_ptr<object::OwningBinary<object::ObjectFile>>> Objs;
204     Objs.push_back(
205       llvm::make_unique<object::OwningBinary<object::ObjectFile>>(
206         std::move(O)));
207     ObjectLayer.addObjectSet(std::move(Objs), &MemMgr, &Resolver);
208   }
209
210   void addArchive(object::OwningBinary<object::Archive> A) override {
211     Archives.push_back(std::move(A));
212   }
213
214   uint64_t getSymbolAddress(StringRef Name) {
215     return findSymbol(Name).getAddress();
216   }
217
218   JITSymbol findSymbol(StringRef Name) {
219     return findMangledSymbol(Mangle(Name));
220   }
221
222   void finalizeObject() override {
223     // This is deprecated - Aim to remove in ExecutionEngine.
224     // REMOVE IF POSSIBLE - Doesn't make sense for New JIT.
225   }
226
227   void mapSectionAddress(const void *LocalAddress,
228                          uint64_t TargetAddress) override {
229     for (auto &P : UnfinalizedSections)
230       if (P.second.count(LocalAddress))
231         ObjectLayer.mapSectionAddress(P.first, LocalAddress, TargetAddress);
232   }
233
234   uint64_t getGlobalValueAddress(const std::string &Name) override {
235     return getSymbolAddress(Name);
236   }
237
238   uint64_t getFunctionAddress(const std::string &Name) override {
239     return getSymbolAddress(Name);
240   }
241
242   void *getPointerToFunction(Function *F) override {
243     uint64_t FAddr = getSymbolAddress(F->getName());
244     return reinterpret_cast<void *>(static_cast<uintptr_t>(FAddr));
245   }
246
247   void *getPointerToNamedFunction(StringRef Name,
248                                   bool AbortOnFailure = true) override {
249     uint64_t Addr = getSymbolAddress(Name);
250     if (!Addr && AbortOnFailure)
251       llvm_unreachable("Missing symbol!");
252     return reinterpret_cast<void *>(static_cast<uintptr_t>(Addr));
253   }
254
255   GenericValue runFunction(Function *F,
256                            ArrayRef<GenericValue> ArgValues) override;
257
258   void setObjectCache(ObjectCache *NewCache) override {
259     CompileLayer.setObjectCache(NewCache);
260   }
261
262   void setProcessAllSections(bool ProcessAllSections) override {
263     ObjectLayer.setProcessAllSections(ProcessAllSections);
264   }
265
266 private:
267   JITSymbol findMangledSymbol(StringRef Name) {
268     if (auto Sym = LazyEmitLayer.findSymbol(Name, false))
269       return Sym;
270     if (auto Sym = ClientResolver->findSymbol(Name))
271       return Sym;
272     if (auto Sym = scanArchives(Name))
273       return Sym;
274
275     return nullptr;
276   }
277
278   JITSymbol scanArchives(StringRef Name) {
279     for (object::OwningBinary<object::Archive> &OB : Archives) {
280       object::Archive *A = OB.getBinary();
281       // Look for our symbols in each Archive
282       auto OptionalChildOrErr = A->findSym(Name);
283       if (!OptionalChildOrErr)
284         report_fatal_error(OptionalChildOrErr.takeError());
285       auto &OptionalChild = *OptionalChildOrErr;
286       if (OptionalChild) {
287         // FIXME: Support nested archives?
288         Expected<std::unique_ptr<object::Binary>> ChildBinOrErr =
289             OptionalChild->getAsBinary();
290         if (!ChildBinOrErr) {
291           // TODO: Actually report errors helpfully.
292           consumeError(ChildBinOrErr.takeError());
293           continue;
294         }
295         std::unique_ptr<object::Binary> &ChildBin = ChildBinOrErr.get();
296         if (ChildBin->isObject()) {
297           std::vector<std::unique_ptr<object::ObjectFile>> ObjSet;
298           ObjSet.push_back(std::unique_ptr<object::ObjectFile>(
299               static_cast<object::ObjectFile *>(ChildBin.release())));
300           ObjectLayer.addObjectSet(std::move(ObjSet), &MemMgr, &Resolver);
301           if (auto Sym = ObjectLayer.findSymbol(Name, true))
302             return Sym;
303         }
304       }
305     }
306     return nullptr;
307   }
308
309   class NotifyObjectLoadedT {
310   public:
311     typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>
312         LoadedObjInfoListT;
313
314     NotifyObjectLoadedT(OrcMCJITReplacement &M) : M(M) {}
315
316     template <typename ObjListT>
317     void operator()(RTDyldObjectLinkingLayerBase::ObjSetHandleT H,
318                     const ObjListT &Objects,
319                     const LoadedObjInfoListT &Infos) const {
320       M.UnfinalizedSections[H] = std::move(M.SectionsAllocatedSinceLastLoad);
321       M.SectionsAllocatedSinceLastLoad = SectionAddrSet();
322       assert(Objects.size() == Infos.size() &&
323              "Incorrect number of Infos for Objects.");
324       for (unsigned I = 0; I < Objects.size(); ++I)
325         M.MemMgr.notifyObjectLoaded(&M, getObject(*Objects[I]));
326     }
327
328   private:
329     static const object::ObjectFile& getObject(const object::ObjectFile &Obj) {
330       return Obj;
331     }
332
333     template <typename ObjT>
334     static const object::ObjectFile&
335     getObject(const object::OwningBinary<ObjT> &Obj) {
336       return *Obj.getBinary();
337     }
338
339     OrcMCJITReplacement &M;
340   };
341
342   class NotifyFinalizedT {
343   public:
344     NotifyFinalizedT(OrcMCJITReplacement &M) : M(M) {}
345
346     void operator()(RTDyldObjectLinkingLayerBase::ObjSetHandleT H) {
347       M.UnfinalizedSections.erase(H);
348     }
349
350   private:
351     OrcMCJITReplacement &M;
352   };
353
354   std::string Mangle(StringRef Name) {
355     std::string MangledName;
356     {
357       raw_string_ostream MangledNameStream(MangledName);
358       Mang.getNameWithPrefix(MangledNameStream, Name, getDataLayout());
359     }
360     return MangledName;
361   }
362
363   typedef RTDyldObjectLinkingLayer<NotifyObjectLoadedT> ObjectLayerT;
364   typedef IRCompileLayer<ObjectLayerT> CompileLayerT;
365   typedef LazyEmittingLayer<CompileLayerT> LazyEmitLayerT;
366
367   std::unique_ptr<TargetMachine> TM;
368   MCJITReplacementMemMgr MemMgr;
369   LinkingResolver Resolver;
370   std::shared_ptr<JITSymbolResolver> ClientResolver;
371   Mangler Mang;
372
373   NotifyObjectLoadedT NotifyObjectLoaded;
374   NotifyFinalizedT NotifyFinalized;
375
376   ObjectLayerT ObjectLayer;
377   CompileLayerT CompileLayer;
378   LazyEmitLayerT LazyEmitLayer;
379
380   // We need to store ObjLayerT::ObjSetHandles for each of the object sets
381   // that have been emitted but not yet finalized so that we can forward the
382   // mapSectionAddress calls appropriately.
383   typedef std::set<const void *> SectionAddrSet;
384   struct ObjSetHandleCompare {
385     bool operator()(ObjectLayerT::ObjSetHandleT H1,
386                     ObjectLayerT::ObjSetHandleT H2) const {
387       return &*H1 < &*H2;
388     }
389   };
390   SectionAddrSet SectionsAllocatedSinceLastLoad;
391   std::map<ObjectLayerT::ObjSetHandleT, SectionAddrSet, ObjSetHandleCompare>
392       UnfinalizedSections;
393
394   std::vector<object::OwningBinary<object::Archive>> Archives;
395 };
396
397 } // end namespace orc
398 } // end namespace llvm
399
400 #endif // LLVM_LIB_EXECUTIONENGINE_ORC_MCJITREPLACEMENT_H