Line data Source code
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/Orc/CompileUtils.h"
24 : #include "llvm/ExecutionEngine/Orc/ExecutionUtils.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/ExecutionEngine/RTDyldMemoryManager.h"
29 : #include "llvm/ExecutionEngine/RuntimeDyld.h"
30 : #include "llvm/IR/DataLayout.h"
31 : #include "llvm/IR/Function.h"
32 : #include "llvm/IR/Mangler.h"
33 : #include "llvm/IR/Module.h"
34 : #include "llvm/Object/Archive.h"
35 : #include "llvm/Object/Binary.h"
36 : #include "llvm/Object/ObjectFile.h"
37 : #include "llvm/Support/Error.h"
38 : #include "llvm/Support/ErrorHandling.h"
39 : #include "llvm/Support/raw_ostream.h"
40 : #include "llvm/Target/TargetMachine.h"
41 : #include <algorithm>
42 : #include <cassert>
43 : #include <cstddef>
44 : #include <cstdint>
45 : #include <map>
46 : #include <memory>
47 : #include <set>
48 : #include <string>
49 : #include <vector>
50 :
51 : namespace llvm {
52 :
53 : class ObjectCache;
54 :
55 : namespace orc {
56 :
57 : class OrcMCJITReplacement : public ExecutionEngine {
58 :
59 : // OrcMCJITReplacement needs to do a little extra book-keeping to ensure that
60 : // Orc's automatic finalization doesn't kick in earlier than MCJIT clients are
61 : // expecting - see finalizeMemory.
62 : class MCJITReplacementMemMgr : public MCJITMemoryManager {
63 : public:
64 : MCJITReplacementMemMgr(OrcMCJITReplacement &M,
65 : std::shared_ptr<MCJITMemoryManager> ClientMM)
66 154 : : M(M), ClientMM(std::move(ClientMM)) {}
67 :
68 94 : uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
69 : unsigned SectionID,
70 : StringRef SectionName) override {
71 : uint8_t *Addr =
72 188 : ClientMM->allocateCodeSection(Size, Alignment, SectionID,
73 94 : SectionName);
74 94 : M.SectionsAllocatedSinceLastLoad.insert(Addr);
75 94 : return Addr;
76 : }
77 :
78 135 : uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
79 : unsigned SectionID, StringRef SectionName,
80 : bool IsReadOnly) override {
81 270 : uint8_t *Addr = ClientMM->allocateDataSection(Size, Alignment, SectionID,
82 135 : SectionName, IsReadOnly);
83 135 : M.SectionsAllocatedSinceLastLoad.insert(Addr);
84 135 : return Addr;
85 : }
86 :
87 14 : void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign,
88 : uintptr_t RODataSize, uint32_t RODataAlign,
89 : uintptr_t RWDataSize,
90 : uint32_t RWDataAlign) override {
91 28 : return ClientMM->reserveAllocationSpace(CodeSize, CodeAlign,
92 : RODataSize, RODataAlign,
93 14 : RWDataSize, RWDataAlign);
94 : }
95 :
96 93 : bool needsToReserveAllocationSpace() override {
97 93 : return ClientMM->needsToReserveAllocationSpace();
98 : }
99 :
100 73 : void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
101 : size_t Size) override {
102 73 : return ClientMM->registerEHFrames(Addr, LoadAddr, Size);
103 : }
104 :
105 14 : void deregisterEHFrames() override {
106 14 : return ClientMM->deregisterEHFrames();
107 : }
108 :
109 93 : void notifyObjectLoaded(RuntimeDyld &RTDyld,
110 : const object::ObjectFile &O) override {
111 93 : return ClientMM->notifyObjectLoaded(RTDyld, O);
112 : }
113 :
114 93 : void notifyObjectLoaded(ExecutionEngine *EE,
115 : const object::ObjectFile &O) override {
116 93 : return ClientMM->notifyObjectLoaded(EE, O);
117 : }
118 :
119 76 : bool finalizeMemory(std::string *ErrMsg = nullptr) override {
120 : // Each set of objects loaded will be finalized exactly once, but since
121 : // symbol lookup during relocation may recursively trigger the
122 : // loading/relocation of other modules, and since we're forwarding all
123 : // finalizeMemory calls to a single underlying memory manager, we need to
124 : // defer forwarding the call on until all necessary objects have been
125 : // loaded. Otherwise, during the relocation of a leaf object, we will end
126 : // up finalizing memory, causing a crash further up the stack when we
127 : // attempt to apply relocations to finalized memory.
128 : // To avoid finalizing too early, look at how many objects have been
129 : // loaded but not yet finalized. This is a bit of a hack that relies on
130 : // the fact that we're lazily emitting object files: The only way you can
131 : // get more than one set of objects loaded but not yet finalized is if
132 : // they were loaded during relocation of another set.
133 152 : if (M.UnfinalizedSections.size() == 1)
134 76 : return ClientMM->finalizeMemory(ErrMsg);
135 : return false;
136 : }
137 :
138 : private:
139 : OrcMCJITReplacement &M;
140 : std::shared_ptr<MCJITMemoryManager> ClientMM;
141 : };
142 :
143 : class LinkingORCResolver : public orc::SymbolResolver {
144 : public:
145 77 : LinkingORCResolver(OrcMCJITReplacement &M) : M(M) {}
146 :
147 93 : SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) override {
148 : SymbolNameSet Result;
149 :
150 112 : for (auto &S : Symbols) {
151 57 : if (auto Sym = M.findMangledSymbol(*S)) {
152 : if (!Sym.getFlags().isStrong())
153 : Result.insert(S);
154 16 : } else if (auto Err = Sym.takeError()) {
155 0 : M.reportError(std::move(Err));
156 0 : return SymbolNameSet();
157 : } else {
158 80 : if (auto Sym2 = M.ClientResolver->findSymbolInLogicalDylib(*S)) {
159 : if (!Sym2.getFlags().isStrong())
160 : Result.insert(S);
161 16 : } else if (auto Err = Sym2.takeError()) {
162 0 : M.reportError(std::move(Err));
163 0 : return SymbolNameSet();
164 : } else
165 : Result.insert(S);
166 : }
167 : }
168 :
169 : return Result;
170 : }
171 :
172 35 : SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
173 : SymbolNameSet Symbols) override {
174 : SymbolNameSet UnresolvedSymbols;
175 : bool NewSymbolsResolved = false;
176 :
177 95 : for (auto &S : Symbols) {
178 180 : if (auto Sym = M.findMangledSymbol(*S)) {
179 60 : if (auto Addr = Sym.getAddress()) {
180 120 : Query->resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
181 60 : Query->notifySymbolReady();
182 : NewSymbolsResolved = true;
183 : } else {
184 0 : M.ES.legacyFailQuery(*Query, Addr.takeError());
185 0 : return SymbolNameSet();
186 : }
187 0 : } else if (auto Err = Sym.takeError()) {
188 0 : M.ES.legacyFailQuery(*Query, std::move(Err));
189 0 : return SymbolNameSet();
190 : } else {
191 0 : if (auto Sym2 = M.ClientResolver->findSymbol(*S)) {
192 0 : if (auto Addr = Sym2.getAddress()) {
193 0 : Query->resolve(S, JITEvaluatedSymbol(*Addr, Sym2.getFlags()));
194 0 : Query->notifySymbolReady();
195 : NewSymbolsResolved = true;
196 : } else {
197 0 : M.ES.legacyFailQuery(*Query, Addr.takeError());
198 0 : return SymbolNameSet();
199 : }
200 0 : } else if (auto Err = Sym2.takeError()) {
201 0 : M.ES.legacyFailQuery(*Query, std::move(Err));
202 0 : return SymbolNameSet();
203 : } else
204 : UnresolvedSymbols.insert(S);
205 : }
206 : }
207 :
208 35 : if (NewSymbolsResolved && Query->isFullyResolved())
209 35 : Query->handleFullyResolved();
210 :
211 35 : if (NewSymbolsResolved && Query->isFullyReady())
212 35 : Query->handleFullyReady();
213 :
214 : return UnresolvedSymbols;
215 : }
216 :
217 : private:
218 : OrcMCJITReplacement &M;
219 : };
220 :
221 : private:
222 : static ExecutionEngine *
223 77 : createOrcMCJITReplacement(std::string *ErrorMsg,
224 : std::shared_ptr<MCJITMemoryManager> MemMgr,
225 : std::shared_ptr<LegacyJITSymbolResolver> Resolver,
226 : std::unique_ptr<TargetMachine> TM) {
227 : return new OrcMCJITReplacement(std::move(MemMgr), std::move(Resolver),
228 154 : std::move(TM));
229 : }
230 :
231 0 : void reportError(Error Err) {
232 0 : logAllUnhandledErrors(std::move(Err), errs(), "MCJIT error: ");
233 0 : }
234 :
235 : public:
236 77 : OrcMCJITReplacement(std::shared_ptr<MCJITMemoryManager> MemMgr,
237 : std::shared_ptr<LegacyJITSymbolResolver> ClientResolver,
238 : std::unique_ptr<TargetMachine> TM)
239 77 : : ExecutionEngine(TM->createDataLayout()),
240 : TM(std::move(TM)),
241 : MemMgr(
242 : std::make_shared<MCJITReplacementMemMgr>(*this, std::move(MemMgr))),
243 : Resolver(std::make_shared<LinkingORCResolver>(*this)),
244 : ClientResolver(std::move(ClientResolver)), NotifyObjectLoaded(*this),
245 : NotifyFinalized(*this),
246 : ObjectLayer(
247 : ES,
248 93 : [this](VModuleKey K) {
249 : return ObjectLayerT::Resources{this->MemMgr, this->Resolver};
250 : },
251 : NotifyObjectLoaded, NotifyFinalized),
252 : CompileLayer(ObjectLayer, SimpleCompiler(*this->TM),
253 : [this](VModuleKey K, std::unique_ptr<Module> M) {
254 89 : Modules.push_back(std::move(M));
255 : }),
256 539 : LazyEmitLayer(CompileLayer) {}
257 :
258 : static void Register() {
259 0 : OrcMCJITReplacementCtor = createOrcMCJITReplacement;
260 : }
261 :
262 90 : void addModule(std::unique_ptr<Module> M) override {
263 : // If this module doesn't have a DataLayout attached then attach the
264 : // default.
265 90 : if (M->getDataLayout().isDefault()) {
266 90 : M->setDataLayout(getDataLayout());
267 : } else {
268 : assert(M->getDataLayout() == getDataLayout() && "DataLayout Mismatch");
269 : }
270 :
271 : // Rename, bump linkage and record static constructors and destructors.
272 : // We have to do this before we hand over ownership of the module to the
273 : // JIT.
274 90 : std::vector<std::string> CtorNames, DtorNames;
275 : {
276 : unsigned CtorId = 0, DtorId = 0;
277 91 : for (auto Ctor : orc::getConstructors(*M)) {
278 1 : std::string NewCtorName = ("__ORCstatic_ctor." + Twine(CtorId++)).str();
279 2 : Ctor.Func->setName(NewCtorName);
280 : Ctor.Func->setLinkage(GlobalValue::ExternalLinkage);
281 : Ctor.Func->setVisibility(GlobalValue::HiddenVisibility);
282 2 : CtorNames.push_back(mangle(NewCtorName));
283 : }
284 91 : for (auto Dtor : orc::getDestructors(*M)) {
285 1 : std::string NewDtorName = ("__ORCstatic_dtor." + Twine(DtorId++)).str();
286 2 : dbgs() << "Found dtor: " << NewDtorName << "\n";
287 2 : Dtor.Func->setName(NewDtorName);
288 : Dtor.Func->setLinkage(GlobalValue::ExternalLinkage);
289 : Dtor.Func->setVisibility(GlobalValue::HiddenVisibility);
290 2 : DtorNames.push_back(mangle(NewDtorName));
291 : }
292 : }
293 :
294 90 : auto K = ES.allocateVModule();
295 :
296 90 : UnexecutedConstructors[K] = std::move(CtorNames);
297 90 : UnexecutedDestructors[K] = std::move(DtorNames);
298 :
299 270 : cantFail(LazyEmitLayer.addModule(K, std::move(M)));
300 90 : }
301 :
302 0 : void addObjectFile(std::unique_ptr<object::ObjectFile> O) override {
303 0 : cantFail(ObjectLayer.addObject(
304 0 : ES.allocateVModule(), MemoryBuffer::getMemBufferCopy(O->getData())));
305 0 : }
306 :
307 2 : void addObjectFile(object::OwningBinary<object::ObjectFile> O) override {
308 2 : std::unique_ptr<object::ObjectFile> Obj;
309 2 : std::unique_ptr<MemoryBuffer> ObjBuffer;
310 2 : std::tie(Obj, ObjBuffer) = O.takeBinary();
311 6 : cantFail(ObjectLayer.addObject(ES.allocateVModule(), std::move(ObjBuffer)));
312 2 : }
313 :
314 1 : void addArchive(object::OwningBinary<object::Archive> A) override {
315 1 : Archives.push_back(std::move(A));
316 1 : }
317 :
318 0 : bool removeModule(Module *M) override {
319 : auto I = Modules.begin();
320 0 : for (auto E = Modules.end(); I != E; ++I)
321 0 : if (I->get() == M)
322 : break;
323 0 : if (I == Modules.end())
324 : return false;
325 0 : Modules.erase(I);
326 0 : return true;
327 : }
328 :
329 205 : uint64_t getSymbolAddress(StringRef Name) {
330 410 : return cantFail(findSymbol(Name).getAddress());
331 : }
332 :
333 205 : JITSymbol findSymbol(StringRef Name) {
334 205 : return findMangledSymbol(mangle(Name));
335 : }
336 :
337 76 : void finalizeObject() override {
338 : // This is deprecated - Aim to remove in ExecutionEngine.
339 : // REMOVE IF POSSIBLE - Doesn't make sense for New JIT.
340 76 : }
341 :
342 0 : void mapSectionAddress(const void *LocalAddress,
343 : uint64_t TargetAddress) override {
344 0 : for (auto &P : UnfinalizedSections)
345 : if (P.second.count(LocalAddress))
346 0 : ObjectLayer.mapSectionAddress(P.first, LocalAddress, TargetAddress);
347 0 : }
348 :
349 0 : uint64_t getGlobalValueAddress(const std::string &Name) override {
350 0 : return getSymbolAddress(Name);
351 : }
352 :
353 11 : uint64_t getFunctionAddress(const std::string &Name) override {
354 11 : return getSymbolAddress(Name);
355 : }
356 :
357 194 : void *getPointerToFunction(Function *F) override {
358 194 : uint64_t FAddr = getSymbolAddress(F->getName());
359 194 : return reinterpret_cast<void *>(static_cast<uintptr_t>(FAddr));
360 : }
361 :
362 0 : void *getPointerToNamedFunction(StringRef Name,
363 : bool AbortOnFailure = true) override {
364 0 : uint64_t Addr = getSymbolAddress(Name);
365 0 : if (!Addr && AbortOnFailure)
366 0 : llvm_unreachable("Missing symbol!");
367 0 : return reinterpret_cast<void *>(static_cast<uintptr_t>(Addr));
368 : }
369 :
370 : GenericValue runFunction(Function *F,
371 : ArrayRef<GenericValue> ArgValues) override;
372 :
373 1 : void setObjectCache(ObjectCache *NewCache) override {
374 : CompileLayer.getCompiler().setObjectCache(NewCache);
375 1 : }
376 :
377 0 : void setProcessAllSections(bool ProcessAllSections) override {
378 : ObjectLayer.setProcessAllSections(ProcessAllSections);
379 0 : }
380 :
381 : void runStaticConstructorsDestructors(bool isDtors) override;
382 :
383 : private:
384 284 : JITSymbol findMangledSymbol(StringRef Name) {
385 974 : if (auto Sym = LazyEmitLayer.findSymbol(Name, false))
386 162 : return Sym;
387 384 : if (auto Sym = ClientResolver->findSymbol(Name))
388 104 : return Sym;
389 34 : if (auto Sym = scanArchives(Name))
390 2 : return Sym;
391 :
392 : return nullptr;
393 : }
394 :
395 18 : JITSymbol scanArchives(StringRef Name) {
396 18 : for (object::OwningBinary<object::Archive> &OB : Archives) {
397 : object::Archive *A = OB.getBinary();
398 : // Look for our symbols in each Archive
399 2 : auto OptionalChildOrErr = A->findSym(Name);
400 2 : if (!OptionalChildOrErr)
401 0 : report_fatal_error(OptionalChildOrErr.takeError());
402 : auto &OptionalChild = *OptionalChildOrErr;
403 2 : if (OptionalChild) {
404 : // FIXME: Support nested archives?
405 : Expected<std::unique_ptr<object::Binary>> ChildBinOrErr =
406 2 : OptionalChild->getAsBinary();
407 2 : if (!ChildBinOrErr) {
408 : // TODO: Actually report errors helpfully.
409 0 : consumeError(ChildBinOrErr.takeError());
410 0 : continue;
411 : }
412 : std::unique_ptr<object::Binary> &ChildBin = ChildBinOrErr.get();
413 4 : if (ChildBin->isObject()) {
414 6 : cantFail(ObjectLayer.addObject(
415 : ES.allocateVModule(),
416 2 : MemoryBuffer::getMemBufferCopy(ChildBin->getData())));
417 2 : if (auto Sym = ObjectLayer.findSymbol(Name, true))
418 2 : return Sym;
419 : }
420 : }
421 : }
422 : return nullptr;
423 : }
424 :
425 : class NotifyObjectLoadedT {
426 : public:
427 : using LoadedObjInfoListT =
428 : std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>;
429 :
430 77 : NotifyObjectLoadedT(OrcMCJITReplacement &M) : M(M) {}
431 :
432 93 : void operator()(VModuleKey K, const object::ObjectFile &Obj,
433 : const RuntimeDyld::LoadedObjectInfo &Info) const {
434 93 : M.UnfinalizedSections[K] = std::move(M.SectionsAllocatedSinceLastLoad);
435 93 : M.SectionsAllocatedSinceLastLoad = SectionAddrSet();
436 186 : M.MemMgr->notifyObjectLoaded(&M, Obj);
437 93 : }
438 : private:
439 : OrcMCJITReplacement &M;
440 : };
441 :
442 : class NotifyFinalizedT {
443 : public:
444 77 : NotifyFinalizedT(OrcMCJITReplacement &M) : M(M) {}
445 :
446 0 : void operator()(VModuleKey K, const object::ObjectFile &Obj,
447 : const RuntimeDyld::LoadedObjectInfo &Info) {
448 0 : M.UnfinalizedSections.erase(K);
449 0 : }
450 :
451 : private:
452 : OrcMCJITReplacement &M;
453 : };
454 :
455 207 : std::string mangle(StringRef Name) {
456 : std::string MangledName;
457 : {
458 207 : raw_string_ostream MangledNameStream(MangledName);
459 207 : Mang.getNameWithPrefix(MangledNameStream, Name, getDataLayout());
460 : }
461 207 : return MangledName;
462 : }
463 :
464 : using ObjectLayerT = LegacyRTDyldObjectLinkingLayer;
465 : using CompileLayerT = LegacyIRCompileLayer<ObjectLayerT, orc::SimpleCompiler>;
466 : using LazyEmitLayerT = LazyEmittingLayer<CompileLayerT>;
467 :
468 : ExecutionSession ES;
469 :
470 : std::unique_ptr<TargetMachine> TM;
471 : std::shared_ptr<MCJITReplacementMemMgr> MemMgr;
472 : std::shared_ptr<LinkingORCResolver> Resolver;
473 : std::shared_ptr<LegacyJITSymbolResolver> ClientResolver;
474 : Mangler Mang;
475 :
476 : // IMPORTANT: ShouldDelete *must* come before LocalModules: The shared_ptr
477 : // delete blocks in LocalModules refer to the ShouldDelete map, so
478 : // LocalModules needs to be destructed before ShouldDelete.
479 : std::map<Module*, bool> ShouldDelete;
480 :
481 : NotifyObjectLoadedT NotifyObjectLoaded;
482 : NotifyFinalizedT NotifyFinalized;
483 :
484 : ObjectLayerT ObjectLayer;
485 : CompileLayerT CompileLayer;
486 : LazyEmitLayerT LazyEmitLayer;
487 :
488 : std::map<VModuleKey, std::vector<std::string>> UnexecutedConstructors;
489 : std::map<VModuleKey, std::vector<std::string>> UnexecutedDestructors;
490 :
491 : // We need to store ObjLayerT::ObjSetHandles for each of the object sets
492 : // that have been emitted but not yet finalized so that we can forward the
493 : // mapSectionAddress calls appropriately.
494 : using SectionAddrSet = std::set<const void *>;
495 : SectionAddrSet SectionsAllocatedSinceLastLoad;
496 : std::map<VModuleKey, SectionAddrSet> UnfinalizedSections;
497 :
498 : std::vector<object::OwningBinary<object::Archive>> Archives;
499 : };
500 :
501 : } // end namespace orc
502 :
503 : } // end namespace llvm
504 :
505 : #endif // LLVM_LIB_EXECUTIONENGINE_ORC_MCJITREPLACEMENT_H
|