1 //===- OrcMCJITReplacement.h - Orc based MCJIT replacement ------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Orc based MCJIT replacement.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_LIB_EXECUTIONENGINE_ORC_ORCMCJITREPLACEMENT_H
15 #define LLVM_LIB_EXECUTIONENGINE_ORC_ORCMCJITREPLACEMENT_H
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/Orc/CompileUtils.h"
24 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
25 #include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h"
26 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
27 #include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
28 #include "llvm/ExecutionEngine/RuntimeDyld.h"
29 #include "llvm/IR/DataLayout.h"
30 #include "llvm/IR/Function.h"
31 #include "llvm/IR/Mangler.h"
32 #include "llvm/IR/Module.h"
33 #include "llvm/Object/Archive.h"
34 #include "llvm/Object/Binary.h"
35 #include "llvm/Object/ObjectFile.h"
36 #include "llvm/Support/Error.h"
37 #include "llvm/Support/ErrorHandling.h"
38 #include "llvm/Support/raw_ostream.h"
39 #include "llvm/Target/TargetMachine.h"
56 class OrcMCJITReplacement : public ExecutionEngine {
57 // OrcMCJITReplacement needs to do a little extra book-keeping to ensure that
58 // Orc's automatic finalization doesn't kick in earlier than MCJIT clients are
59 // expecting - see finalizeMemory.
60 class MCJITReplacementMemMgr : public MCJITMemoryManager {
62 MCJITReplacementMemMgr(OrcMCJITReplacement &M,
63 std::shared_ptr<MCJITMemoryManager> ClientMM)
64 : M(M), ClientMM(std::move(ClientMM)) {}
66 uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
68 StringRef SectionName) override {
70 ClientMM->allocateCodeSection(Size, Alignment, SectionID,
72 M.SectionsAllocatedSinceLastLoad.insert(Addr);
76 uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
77 unsigned SectionID, StringRef SectionName,
78 bool IsReadOnly) override {
79 uint8_t *Addr = ClientMM->allocateDataSection(Size, Alignment, SectionID,
80 SectionName, IsReadOnly);
81 M.SectionsAllocatedSinceLastLoad.insert(Addr);
85 void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign,
86 uintptr_t RODataSize, uint32_t RODataAlign,
88 uint32_t RWDataAlign) override {
89 return ClientMM->reserveAllocationSpace(CodeSize, CodeAlign,
90 RODataSize, RODataAlign,
91 RWDataSize, RWDataAlign);
94 bool needsToReserveAllocationSpace() override {
95 return ClientMM->needsToReserveAllocationSpace();
98 void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
99 size_t Size) override {
100 return ClientMM->registerEHFrames(Addr, LoadAddr, Size);
103 void deregisterEHFrames() override {
104 return ClientMM->deregisterEHFrames();
107 void notifyObjectLoaded(RuntimeDyld &RTDyld,
108 const object::ObjectFile &O) override {
109 return ClientMM->notifyObjectLoaded(RTDyld, O);
112 void notifyObjectLoaded(ExecutionEngine *EE,
113 const object::ObjectFile &O) override {
114 return ClientMM->notifyObjectLoaded(EE, O);
117 bool finalizeMemory(std::string *ErrMsg = nullptr) override {
118 // Each set of objects loaded will be finalized exactly once, but since
119 // symbol lookup during relocation may recursively trigger the
120 // loading/relocation of other modules, and since we're forwarding all
121 // finalizeMemory calls to a single underlying memory manager, we need to
122 // defer forwarding the call on until all necessary objects have been
123 // loaded. Otherwise, during the relocation of a leaf object, we will end
124 // up finalizing memory, causing a crash further up the stack when we
125 // attempt to apply relocations to finalized memory.
126 // To avoid finalizing too early, look at how many objects have been
127 // loaded but not yet finalized. This is a bit of a hack that relies on
128 // the fact that we're lazily emitting object files: The only way you can
129 // get more than one set of objects loaded but not yet finalized is if
130 // they were loaded during relocation of another set.
131 if (M.UnfinalizedSections.size() == 1)
132 return ClientMM->finalizeMemory(ErrMsg);
137 OrcMCJITReplacement &M;
138 std::shared_ptr<MCJITMemoryManager> ClientMM;
141 class LinkingResolver : public JITSymbolResolver {
143 LinkingResolver(OrcMCJITReplacement &M) : M(M) {}
145 JITSymbol findSymbol(const std::string &Name) override {
146 return M.ClientResolver->findSymbol(Name);
149 JITSymbol findSymbolInLogicalDylib(const std::string &Name) override {
150 if (auto Sym = M.findMangledSymbol(Name))
152 return M.ClientResolver->findSymbolInLogicalDylib(Name);
156 OrcMCJITReplacement &M;
160 static ExecutionEngine *
161 createOrcMCJITReplacement(std::string *ErrorMsg,
162 std::shared_ptr<MCJITMemoryManager> MemMgr,
163 std::shared_ptr<JITSymbolResolver> Resolver,
164 std::unique_ptr<TargetMachine> TM) {
165 return new OrcMCJITReplacement(std::move(MemMgr), std::move(Resolver),
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) {}
182 static void Register() {
183 OrcMCJITReplacementCtor = createOrcMCJITReplacement;
186 void addModule(std::unique_ptr<Module> M) override {
187 // If this module doesn't have a DataLayout attached then attach the
189 if (M->getDataLayout().isDefault()) {
190 M->setDataLayout(getDataLayout());
192 assert(M->getDataLayout() == getDataLayout() && "DataLayout Mismatch");
194 auto *MPtr = M.release();
195 ShouldDelete[MPtr] = true;
197 [this](Module *Mod) {
198 if (ShouldDelete[Mod])
201 LocalModules.push_back(std::shared_ptr<Module>(MPtr, std::move(Deleter)));
202 LazyEmitLayer.addModule(LocalModules.back(), &MemMgr, &Resolver);
205 void addObjectFile(std::unique_ptr<object::ObjectFile> O) override {
207 std::make_shared<object::OwningBinary<object::ObjectFile>>(std::move(O),
209 ObjectLayer.addObject(std::move(Obj), &MemMgr, &Resolver);
212 void addObjectFile(object::OwningBinary<object::ObjectFile> O) override {
214 std::make_shared<object::OwningBinary<object::ObjectFile>>(std::move(O));
215 ObjectLayer.addObject(std::move(Obj), &MemMgr, &Resolver);
218 void addArchive(object::OwningBinary<object::Archive> A) override {
219 Archives.push_back(std::move(A));
222 bool removeModule(Module *M) override {
223 for (auto I = LocalModules.begin(), E = LocalModules.end(); I != E; ++I) {
225 ShouldDelete[M] = false;
226 LocalModules.erase(I);
233 uint64_t getSymbolAddress(StringRef Name) {
234 return findSymbol(Name).getAddress();
237 JITSymbol findSymbol(StringRef Name) {
238 return findMangledSymbol(Mangle(Name));
241 void finalizeObject() override {
242 // This is deprecated - Aim to remove in ExecutionEngine.
243 // REMOVE IF POSSIBLE - Doesn't make sense for New JIT.
246 void mapSectionAddress(const void *LocalAddress,
247 uint64_t TargetAddress) override {
248 for (auto &P : UnfinalizedSections)
249 if (P.second.count(LocalAddress))
250 ObjectLayer.mapSectionAddress(P.first, LocalAddress, TargetAddress);
253 uint64_t getGlobalValueAddress(const std::string &Name) override {
254 return getSymbolAddress(Name);
257 uint64_t getFunctionAddress(const std::string &Name) override {
258 return getSymbolAddress(Name);
261 void *getPointerToFunction(Function *F) override {
262 uint64_t FAddr = getSymbolAddress(F->getName());
263 return reinterpret_cast<void *>(static_cast<uintptr_t>(FAddr));
266 void *getPointerToNamedFunction(StringRef Name,
267 bool AbortOnFailure = true) override {
268 uint64_t Addr = getSymbolAddress(Name);
269 if (!Addr && AbortOnFailure)
270 llvm_unreachable("Missing symbol!");
271 return reinterpret_cast<void *>(static_cast<uintptr_t>(Addr));
274 GenericValue runFunction(Function *F,
275 ArrayRef<GenericValue> ArgValues) override;
277 void setObjectCache(ObjectCache *NewCache) override {
278 CompileLayer.getCompiler().setObjectCache(NewCache);
281 void setProcessAllSections(bool ProcessAllSections) override {
282 ObjectLayer.setProcessAllSections(ProcessAllSections);
285 void runStaticConstructorsDestructors(bool isDtors) override;
288 JITSymbol findMangledSymbol(StringRef Name) {
289 if (auto Sym = LazyEmitLayer.findSymbol(Name, false))
291 if (auto Sym = ClientResolver->findSymbol(Name))
293 if (auto Sym = scanArchives(Name))
299 JITSymbol scanArchives(StringRef Name) {
300 for (object::OwningBinary<object::Archive> &OB : Archives) {
301 object::Archive *A = OB.getBinary();
302 // Look for our symbols in each Archive
303 auto OptionalChildOrErr = A->findSym(Name);
304 if (!OptionalChildOrErr)
305 report_fatal_error(OptionalChildOrErr.takeError());
306 auto &OptionalChild = *OptionalChildOrErr;
308 // FIXME: Support nested archives?
309 Expected<std::unique_ptr<object::Binary>> ChildBinOrErr =
310 OptionalChild->getAsBinary();
311 if (!ChildBinOrErr) {
312 // TODO: Actually report errors helpfully.
313 consumeError(ChildBinOrErr.takeError());
316 std::unique_ptr<object::Binary> &ChildBin = ChildBinOrErr.get();
317 if (ChildBin->isObject()) {
318 std::unique_ptr<object::ObjectFile> ChildObj(
319 static_cast<object::ObjectFile*>(ChildBinOrErr->release()));
321 std::make_shared<object::OwningBinary<object::ObjectFile>>(
322 std::move(ChildObj), nullptr);
323 ObjectLayer.addObject(std::move(Obj), &MemMgr, &Resolver);
324 if (auto Sym = ObjectLayer.findSymbol(Name, true))
332 class NotifyObjectLoadedT {
334 using LoadedObjInfoListT =
335 std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>;
337 NotifyObjectLoadedT(OrcMCJITReplacement &M) : M(M) {}
339 void operator()(RTDyldObjectLinkingLayerBase::ObjHandleT H,
340 const RTDyldObjectLinkingLayer::ObjectPtr &Obj,
341 const LoadedObjectInfo &Info) const {
342 M.UnfinalizedSections[H] = std::move(M.SectionsAllocatedSinceLastLoad);
343 M.SectionsAllocatedSinceLastLoad = SectionAddrSet();
344 M.MemMgr.notifyObjectLoaded(&M, *Obj->getBinary());
347 OrcMCJITReplacement &M;
350 class NotifyFinalizedT {
352 NotifyFinalizedT(OrcMCJITReplacement &M) : M(M) {}
354 void operator()(RTDyldObjectLinkingLayerBase::ObjHandleT H) {
355 M.UnfinalizedSections.erase(H);
359 OrcMCJITReplacement &M;
362 std::string Mangle(StringRef Name) {
363 std::string MangledName;
365 raw_string_ostream MangledNameStream(MangledName);
366 Mang.getNameWithPrefix(MangledNameStream, Name, getDataLayout());
371 using ObjectLayerT = RTDyldObjectLinkingLayer;
372 using CompileLayerT = IRCompileLayer<ObjectLayerT, orc::SimpleCompiler>;
373 using LazyEmitLayerT = LazyEmittingLayer<CompileLayerT>;
375 std::unique_ptr<TargetMachine> TM;
376 MCJITReplacementMemMgr MemMgr;
377 LinkingResolver Resolver;
378 std::shared_ptr<JITSymbolResolver> ClientResolver;
381 NotifyObjectLoadedT NotifyObjectLoaded;
382 NotifyFinalizedT NotifyFinalized;
384 ObjectLayerT ObjectLayer;
385 CompileLayerT CompileLayer;
386 LazyEmitLayerT LazyEmitLayer;
388 // We need to store ObjLayerT::ObjSetHandles for each of the object sets
389 // that have been emitted but not yet finalized so that we can forward the
390 // mapSectionAddress calls appropriately.
391 using SectionAddrSet = std::set<const void *>;
392 struct ObjHandleCompare {
393 bool operator()(ObjectLayerT::ObjHandleT H1,
394 ObjectLayerT::ObjHandleT H2) const {
398 SectionAddrSet SectionsAllocatedSinceLastLoad;
399 std::map<ObjectLayerT::ObjHandleT, SectionAddrSet, ObjHandleCompare>
402 std::map<Module*, bool> ShouldDelete;
403 std::vector<std::shared_ptr<Module>> LocalModules;
404 std::vector<object::OwningBinary<object::Archive>> Archives;
407 } // end namespace orc
409 } // end namespace llvm
411 #endif // LLVM_LIB_EXECUTIONENGINE_ORC_MCJITREPLACEMENT_H