From da62155c112f508b1de986835912917c53fbc073 Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Mon, 30 Mar 2015 03:37:06 +0000 Subject: [PATCH] [MCJIT][Orc] Refactor RTDyldMemoryManager, weave RuntimeDyld::SymbolInfo through MCJIT. This patch decouples the two responsibilities of the RTDyldMemoryManager class, memory management and symbol resolution, into two new classes: RuntimeDyld::MemoryManager and RuntimeDyld::SymbolResolver. The symbol resolution interface is modified slightly, from: uint64_t getSymbolAddress(const std::string &Name); to: RuntimeDyld::SymbolInfo findSymbol(const std::string &Name); The latter passes symbol flags along with symbol addresses, allowing RuntimeDyld and others to reason about non-strong/non-exported symbols. The memory management interface removes the following method: void notifyObjectLoaded(ExecutionEngine *EE, const object::ObjectFile &) {} as it is not related to memory management. (Note: Backwards compatibility *is* maintained for this method in MCJIT and OrcMCJITReplacement, see below). The RTDyldMemoryManager class remains in-tree for backwards compatibility. It inherits directly from RuntimeDyld::SymbolResolver, and indirectly from RuntimeDyld::MemoryManager via the new MCJITMemoryManager class, which just subclasses RuntimeDyld::MemoryManager and reintroduces the notifyObjectLoaded method for backwards compatibility). The EngineBuilder class retains the existing method: EngineBuilder& setMCJITMemoryManager(std::unique_ptr mcjmm); and includes two new methods: EngineBuilder& setMemoryManager(std::unique_ptr MM); EngineBuilder& setSymbolResolver(std::unique_ptr SR); Clients should use EITHER: A single call to setMCJITMemoryManager with an RTDyldMemoryManager. OR (exclusive) One call each to each of setMemoryManager and setSymbolResolver. This patch should be fully compatible with existing uses of RTDyldMemoryManager. If it is not it should be considered a bug, and the patch either fixed or reverted. If clients find the new API to be an improvement the goal will be to deprecate and eventually remove the RTDyldMemoryManager class in favor of the new classes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@233509 91177308-0d34-0410-b5e6-96231b3b80d8 --- examples/Kaleidoscope/Orc/fully_lazy/toy.cpp | 43 +++--- examples/Kaleidoscope/Orc/initial/toy.cpp | 20 ++- .../Kaleidoscope/Orc/lazy_codegen/toy.cpp | 17 ++- examples/Kaleidoscope/Orc/lazy_irgen/toy.cpp | 32 +++-- .../llvm/ExecutionEngine/ExecutionEngine.h | 27 ++-- .../Orc/CompileOnDemandLayer.h | 34 +++-- .../llvm/ExecutionEngine/Orc/IRCompileLayer.h | 8 +- .../ExecutionEngine/Orc/IndirectionUtils.h | 21 ++- include/llvm/ExecutionEngine/Orc/JITSymbol.h | 2 +- .../llvm/ExecutionEngine/Orc/LambdaResolver.h | 62 ++++++++ .../ExecutionEngine/Orc/LazyEmittingLayer.h | 45 +++--- .../ExecutionEngine/Orc/LookasideRTDyldMM.h | 92 ------------ .../ExecutionEngine/Orc/ObjectLinkingLayer.h | 104 ++++++++------ .../ExecutionEngine/RTDyldMemoryManager.h | 136 ++++++++---------- include/llvm/ExecutionEngine/RuntimeDyld.h | 114 +++++++++++++-- .../ExecutionEngine/SectionMemoryManager.h | 2 +- lib/ExecutionEngine/ExecutionEngine.cpp | 37 +++-- lib/ExecutionEngine/MCJIT/MCJIT.cpp | 84 ++++++----- lib/ExecutionEngine/MCJIT/MCJIT.h | 82 ++++------- lib/ExecutionEngine/Orc/OrcMCJITReplacement.h | 123 +++++++++------- .../RuntimeDyld/RuntimeDyld.cpp | 60 ++++---- .../RuntimeDyld/RuntimeDyldCOFF.cpp | 6 +- .../RuntimeDyld/RuntimeDyldCOFF.h | 10 +- .../RuntimeDyld/RuntimeDyldChecker.cpp | 2 +- .../RuntimeDyld/RuntimeDyldELF.cpp | 47 +++--- .../RuntimeDyld/RuntimeDyldELF.h | 3 +- .../RuntimeDyld/RuntimeDyldImpl.h | 12 +- .../RuntimeDyld/RuntimeDyldMachO.cpp | 22 +-- .../RuntimeDyld/RuntimeDyldMachO.h | 14 +- .../Targets/RuntimeDyldCOFFX86_64.h | 8 +- .../Targets/RuntimeDyldMachOAArch64.h | 5 +- .../RuntimeDyld/Targets/RuntimeDyldMachOARM.h | 4 +- .../Targets/RuntimeDyldMachOI386.h | 5 +- .../Targets/RuntimeDyldMachOX86_64.h | 5 +- tools/lli/OrcLazyJIT.cpp | 2 +- tools/lli/OrcLazyJIT.h | 3 +- tools/llvm-rtdyld/llvm-rtdyld.cpp | 7 +- .../Orc/LazyEmittingLayerTest.cpp | 10 +- 38 files changed, 750 insertions(+), 560 deletions(-) create mode 100644 include/llvm/ExecutionEngine/Orc/LambdaResolver.h delete mode 100644 include/llvm/ExecutionEngine/Orc/LookasideRTDyldMM.h diff --git a/examples/Kaleidoscope/Orc/fully_lazy/toy.cpp b/examples/Kaleidoscope/Orc/fully_lazy/toy.cpp index 3b5dcd0b3e0..e3359dd0e47 100644 --- a/examples/Kaleidoscope/Orc/fully_lazy/toy.cpp +++ b/examples/Kaleidoscope/Orc/fully_lazy/toy.cpp @@ -1,6 +1,7 @@ #include "llvm/Analysis/Passes.h" #include "llvm/ExecutionEngine/Orc/CompileUtils.h" #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" +#include "llvm/ExecutionEngine/Orc/LambdaResolver.h" #include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" #include "llvm/ExecutionEngine/Orc/OrcTargetSupport.h" @@ -1168,11 +1169,9 @@ public: KaleidoscopeJIT(SessionContext &Session) : Session(Session), Mang(Session.getTarget().getDataLayout()), - ObjectLayer( - [](){ return llvm::make_unique(); }), CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())), LazyEmitLayer(CompileLayer), - CompileCallbacks(LazyEmitLayer, Session.getLLVMContext(), + CompileCallbacks(LazyEmitLayer, CCMgrMemMgr, Session.getLLVMContext(), reinterpret_cast(EarthShatteringKaboom), 64) {} @@ -1194,20 +1193,22 @@ public: // We need a memory manager to allocate memory and resolve symbols for this // new module. Create one that resolves symbols by looking back into the // JIT. - auto MM = createLookasideRTDyldMM( - [&](const std::string &Name) { - // First try to find 'Name' within the JIT. - if (auto Symbol = findSymbol(Name)) - return Symbol.getAddress(); - - // If we don't already have a definition of 'Name' then search - // the ASTs. - return searchFunctionASTs(Name); - }, - [](const std::string &S) { return 0; } ); + auto Resolver = createLambdaResolver( + [&](const std::string &Name) { + // First try to find 'Name' within the JIT. + if (auto Symbol = findSymbol(Name)) + return RuntimeDyld::SymbolInfo(Symbol.getAddress(), + Symbol.getFlags()); + + // If we don't already have a definition of 'Name' then search + // the ASTs. + return searchFunctionASTs(Name); + }, + [](const std::string &S) { return nullptr; } ); return LazyEmitLayer.addModuleSet(singletonSet(std::move(M)), - std::move(MM)); + make_unique(), + std::move(Resolver)); } void removeModule(ModuleHandleT H) { LazyEmitLayer.removeModuleSet(H); } @@ -1232,7 +1233,7 @@ private: // This method searches the FunctionDefs map for a definition of 'Name'. If it // finds one it generates a stub for it and returns the address of the stub. - TargetAddress searchFunctionASTs(const std::string &Name) { + RuntimeDyld::SymbolInfo searchFunctionASTs(const std::string &Name) { auto DefI = FunctionDefs.find(Name); if (DefI == FunctionDefs.end()) return 0; @@ -1244,7 +1245,8 @@ private: // IRGen the AST, add it to the JIT, and return the address for it. auto H = irGenStub(std::move(FnAST)); - return findSymbolIn(H, Name).getAddress(); + auto Sym = findSymbolIn(H, Name); + return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags()); } // This method will take the AST for a function definition and IR-gen a stub @@ -1261,14 +1263,16 @@ private: // compile and update actions for the callback, and get a pointer to // the jit trampoline that we need to call to trigger those actions. auto CallbackInfo = - CompileCallbacks.getCompileCallback(*F->getFunctionType()); + CompileCallbacks.getCompileCallback(F->getContext()); // Step 3) Create a stub that will indirectly call the body of this // function once it is compiled. Initially, set the function // pointer for the indirection to point at the trampoline. std::string BodyPtrName = (F->getName() + "$address").str(); GlobalVariable *FunctionBodyPointer = - createImplPointer(*F, BodyPtrName, CallbackInfo.getAddress()); + createImplPointer(*F, BodyPtrName, + createIRTypedAddress(*F->getFunctionType(), + CallbackInfo.getAddress())); makeStub(*F, *FunctionBodyPointer); // Step 4) Add the module containing the stub to the JIT. @@ -1297,6 +1301,7 @@ private: SessionContext &Session; Mangler Mang; + SectionMemoryManager CCMgrMemMgr; ObjLayerT ObjectLayer; CompileLayerT CompileLayer; LazyEmitLayerT LazyEmitLayer; diff --git a/examples/Kaleidoscope/Orc/initial/toy.cpp b/examples/Kaleidoscope/Orc/initial/toy.cpp index cc6fb8e0a01..bf43f2952c7 100644 --- a/examples/Kaleidoscope/Orc/initial/toy.cpp +++ b/examples/Kaleidoscope/Orc/initial/toy.cpp @@ -1,6 +1,7 @@ #include "llvm/Analysis/Passes.h" #include "llvm/ExecutionEngine/Orc/CompileUtils.h" #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" +#include "llvm/ExecutionEngine/Orc/LambdaResolver.h" #include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" #include "llvm/IR/DataLayout.h" @@ -1175,13 +1176,18 @@ public: // We need a memory manager to allocate memory and resolve symbols for this // new module. Create one that resolves symbols by looking back into the // JIT. - auto MM = createLookasideRTDyldMM( - [&](const std::string &Name) { - return findSymbol(Name).getAddress(); - }, - [](const std::string &S) { return 0; } ); - - return CompileLayer.addModuleSet(singletonSet(std::move(M)), std::move(MM)); + auto Resolver = createLambdaResolver( + [&](const std::string &Name) { + if (auto Sym = findSymbol(Name)) + return RuntimeDyld::SymbolInfo(Sym.getAddress(), + Sym.getFlags()); + return RuntimeDyld::SymbolInfo(nullptr); + }, + [](const std::string &S) { return nullptr; } + ); + return CompileLayer.addModuleSet(singletonSet(std::move(M)), + make_unique(), + std::move(Resolver)); } void removeModule(ModuleHandleT H) { CompileLayer.removeModuleSet(H); } diff --git a/examples/Kaleidoscope/Orc/lazy_codegen/toy.cpp b/examples/Kaleidoscope/Orc/lazy_codegen/toy.cpp index 6e2ec2723a4..1369ba6f5ee 100644 --- a/examples/Kaleidoscope/Orc/lazy_codegen/toy.cpp +++ b/examples/Kaleidoscope/Orc/lazy_codegen/toy.cpp @@ -1,6 +1,7 @@ #include "llvm/Analysis/Passes.h" #include "llvm/ExecutionEngine/Orc/CompileUtils.h" #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" +#include "llvm/ExecutionEngine/Orc/LambdaResolver.h" #include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" #include "llvm/IR/DataLayout.h" @@ -1178,14 +1179,18 @@ public: // We need a memory manager to allocate memory and resolve symbols for this // new module. Create one that resolves symbols by looking back into the // JIT. - auto MM = createLookasideRTDyldMM( - [&](const std::string &Name) { - return findSymbol(Name).getAddress(); - }, - [](const std::string &S) { return 0; } ); + auto Resolver = createLambdaResolver( + [&](const std::string &Name) { + if (auto Sym = findSymbol(Name)) + return RuntimeDyld::SymbolInfo(Sym.getAddress(), + Sym.getFlags()); + return RuntimeDyld::SymbolInfo(nullptr); + }, + [](const std::string &S) { return nullptr; } ); return LazyEmitLayer.addModuleSet(singletonSet(std::move(M)), - std::move(MM)); + make_unique(), + std::move(Resolver)); } void removeModule(ModuleHandleT H) { LazyEmitLayer.removeModuleSet(H); } diff --git a/examples/Kaleidoscope/Orc/lazy_irgen/toy.cpp b/examples/Kaleidoscope/Orc/lazy_irgen/toy.cpp index 19801e12030..c489a450d79 100644 --- a/examples/Kaleidoscope/Orc/lazy_irgen/toy.cpp +++ b/examples/Kaleidoscope/Orc/lazy_irgen/toy.cpp @@ -1,6 +1,7 @@ #include "llvm/Analysis/Passes.h" #include "llvm/ExecutionEngine/Orc/CompileUtils.h" #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" +#include "llvm/ExecutionEngine/Orc/LambdaResolver.h" #include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" #include "llvm/IR/DataLayout.h" @@ -1183,20 +1184,22 @@ public: // We need a memory manager to allocate memory and resolve symbols for this // new module. Create one that resolves symbols by looking back into the // JIT. - auto MM = createLookasideRTDyldMM( - [&](const std::string &Name) { - // First try to find 'Name' within the JIT. - if (auto Symbol = findSymbol(Name)) - return Symbol.getAddress(); - - // If we don't already have a definition of 'Name' then search - // the ASTs. - return searchFunctionASTs(Name); - }, - [](const std::string &S) { return 0; } ); + auto Resolver = createLambdaResolver( + [&](const std::string &Name) { + // First try to find 'Name' within the JIT. + if (auto Symbol = findSymbol(Name)) + return RuntimeDyld::SymbolInfo(Symbol.getAddress(), + Symbol.getFlags()); + + // If we don't already have a definition of 'Name' then search + // the ASTs. + return searchFunctionASTs(Name); + }, + [](const std::string &S) { return nullptr; } ); return LazyEmitLayer.addModuleSet(singletonSet(std::move(M)), - std::move(MM)); + make_unique(), + std::move(Resolver)); } void removeModule(ModuleHandleT H) { LazyEmitLayer.removeModuleSet(H); } @@ -1217,7 +1220,7 @@ private: // This method searches the FunctionDefs map for a definition of 'Name'. If it // finds one it generates a stub for it and returns the address of the stub. - TargetAddress searchFunctionASTs(const std::string &Name) { + RuntimeDyld::SymbolInfo searchFunctionASTs(const std::string &Name) { auto DefI = FunctionDefs.find(Name); if (DefI == FunctionDefs.end()) return 0; @@ -1228,7 +1231,8 @@ private: // IRGen the AST, add it to the JIT, and return the address for it. auto H = addModule(IRGen(Session, *FnAST)); - return findSymbolIn(H, Name).getAddress(); + auto Sym = findSymbolIn(H, Name); + return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags()); } SessionContext &Session; diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index abdaa0ce54c..6e022afae5f 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -15,6 +15,7 @@ #ifndef LLVM_EXECUTIONENGINE_EXECUTIONENGINE_H #define LLVM_EXECUTIONENGINE_EXECUTIONENGINE_H +#include "RuntimeDyld.h" #include "llvm-c/ExecutionEngine.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -42,6 +43,7 @@ class GlobalVariable; class GlobalValue; class JITEventListener; class MachineCodeInfo; +class MCJITMemoryManager; class MutexGuard; class ObjectCache; class RTDyldMemoryManager; @@ -139,15 +141,17 @@ protected: virtual char *getMemoryForGV(const GlobalVariable *GV); static ExecutionEngine *(*MCJITCtor)( - std::unique_ptr M, - std::string *ErrorStr, - std::unique_ptr MCJMM, - std::unique_ptr TM); + std::unique_ptr M, + std::string *ErrorStr, + std::shared_ptr MM, + std::shared_ptr SR, + std::unique_ptr TM); static ExecutionEngine *(*OrcMCJITReplacementCtor)( - std::string *ErrorStr, - std::unique_ptr OrcJMM, - std::unique_ptr TM); + std::string *ErrorStr, + std::shared_ptr MM, + std::shared_ptr SR, + std::unique_ptr TM); static ExecutionEngine *(*InterpCtor)(std::unique_ptr M, std::string *ErrorStr); @@ -500,7 +504,8 @@ private: EngineKind::Kind WhichEngine; std::string *ErrorStr; CodeGenOpt::Level OptLevel; - std::unique_ptr MCJMM; + std::shared_ptr MemMgr; + std::shared_ptr Resolver; TargetOptions Options; Reloc::Model RelocModel; CodeModel::Model CMModel; @@ -535,6 +540,12 @@ public: /// memory manager. This option defaults to NULL. EngineBuilder &setMCJITMemoryManager(std::unique_ptr mcjmm); + EngineBuilder& + setMemoryManager(std::unique_ptr MM); + + EngineBuilder& + setSymbolResolver(std::unique_ptr SR); + /// setErrorStr - Set the error string to write to on error. This option /// defaults to NULL. EngineBuilder &setErrorStr(std::string *e) { diff --git a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h index 15b74f53255..7c1398a51c8 100644 --- a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h +++ b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h @@ -16,7 +16,7 @@ #define LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H #include "IndirectionUtils.h" -#include "LookasideRTDyldMM.h" +#include "LambdaResolver.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" #include @@ -139,7 +139,7 @@ public: typedef typename ModuleSetInfoListT::iterator ModuleSetHandleT; // @brief Fallback lookup functor. - typedef std::function LookupFtor; + typedef std::function LookupFtor; /// @brief Construct a compile-on-demand layer instance. CompileOnDemandLayer(BaseLayerT &BaseLayer, CompileCallbackMgrT &CallbackMgr) @@ -153,9 +153,13 @@ public: // If the user didn't supply a fallback lookup then just use // getSymbolAddress. if (!FallbackLookup) - FallbackLookup = [=](const std::string &Name) { - return findSymbol(Name, true).getAddress(); - }; + FallbackLookup = + [=](const std::string &Name) -> RuntimeDyld::SymbolInfo { + if (auto Symbol = findSymbol(Name, true)) + return RuntimeDyld::SymbolInfo(Symbol.getAddress(), + Symbol.getFlags()); + return nullptr; + }; // Create a lookup context and ModuleSetInfo for this module set. // For the purposes of symbol resolution the set Ms will be treated as if @@ -255,7 +259,7 @@ private: Function *Proto = StubsModule->getFunction(Name); assert(Proto && "Failed to clone function decl into stubs module."); auto CallbackInfo = - CompileCallbackMgr.getCompileCallback(*Proto->getFunctionType()); + CompileCallbackMgr.getCompileCallback(Proto->getContext()); GlobalVariable *FunctionBodyPointer = createImplPointer(*Proto, Name + AddrSuffix, createIRTypedAddress(*Proto->getFunctionType(), @@ -314,19 +318,25 @@ private: MSet.push_back(std::move(M)); auto DylibLookup = MSI.Lookup; - auto MM = - createLookasideRTDyldMM( + auto Resolver = + createLambdaResolver( [=](const std::string &Name) { if (auto Symbol = DylibLookup->findSymbol(LogicalModule, Name)) - return Symbol.getAddress(); + return RuntimeDyld::SymbolInfo(Symbol.getAddress(), + Symbol.getFlags()); return FallbackLookup(Name); }, - [=](const std::string &Name) { - return DylibLookup->findSymbol(LogicalModule, Name).getAddress(); + [=](const std::string &Name) -> RuntimeDyld::SymbolInfo { + if (auto Symbol = DylibLookup->findSymbol(LogicalModule, Name)) + return RuntimeDyld::SymbolInfo(Symbol.getAddress(), + Symbol.getFlags()); + return nullptr; }); BaseLayerModuleSetHandleT H = - BaseLayer.addModuleSet(std::move(MSet), std::move(MM)); + BaseLayer.addModuleSet(std::move(MSet), + make_unique(), + std::move(Resolver)); // Add this module to the logical module lookup. DylibLookup->addToLogicalModule(LogicalModule, H); MSI.BaseLayerModuleSetHandles.push_back(H); diff --git a/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h b/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h index 6a476221739..edbb32f5344 100644 --- a/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h +++ b/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h @@ -57,9 +57,11 @@ public: // manager MM. /// /// @return A handle for the added modules. - template + template ModuleSetHandleT addModuleSet(ModuleSetT Ms, - std::unique_ptr MM) { + MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) { OwningObjectVec Objects; OwningBufferVec Buffers; @@ -81,7 +83,7 @@ public: } ModuleSetHandleT H = - BaseLayer.addObjectSet(Objects, std::move(MM)); + BaseLayer.addObjectSet(Objects, std::move(MemMgr), std::move(Resolver)); BaseLayer.takeOwnershipOfBuffers(H, std::move(Buffers)); diff --git a/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h index f39fcab1f0a..94032910a2b 100644 --- a/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h +++ b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h @@ -16,6 +16,7 @@ #include "JITSymbol.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" @@ -94,7 +95,7 @@ public: } /// @brief Get/create a compile callback with the given signature. - virtual CompileCallbackInfo getCompileCallback(FunctionType &FT) = 0; + virtual CompileCallbackInfo getCompileCallback(LLVMContext &Context) = 0; protected: @@ -125,18 +126,19 @@ public: /// there is no existing callback trampoline. /// (Trampolines are allocated in blocks for /// efficiency.) - JITCompileCallbackManager(JITLayerT &JIT, LLVMContext &Context, + JITCompileCallbackManager(JITLayerT &JIT, RuntimeDyld::MemoryManager &MemMgr, + LLVMContext &Context, TargetAddress ErrorHandlerAddress, unsigned NumTrampolinesPerBlock) : JITCompileCallbackManagerBase(ErrorHandlerAddress, NumTrampolinesPerBlock), - JIT(JIT) { + JIT(JIT), MemMgr(MemMgr) { emitResolverBlock(Context); } /// @brief Get/create a compile callback with the given signature. - CompileCallbackInfo getCompileCallback(FunctionType &FT) final { - TargetAddress TrampolineAddr = getAvailableTrampolineAddr(FT.getContext()); + CompileCallbackInfo getCompileCallback(LLVMContext &Context) final { + TargetAddress TrampolineAddr = getAvailableTrampolineAddr(Context); auto &CallbackHandler = this->ActiveTrampolines[TrampolineAddr]; @@ -157,7 +159,9 @@ private: std::unique_ptr M(new Module("resolver_block_module", Context)); TargetT::insertResolverBlock(*M, *this); - auto H = JIT.addModuleSet(SingletonSet(std::move(M)), nullptr); + auto H = JIT.addModuleSet(SingletonSet(std::move(M)), &MemMgr, + static_cast( + nullptr)); JIT.emitAndFinalize(H); auto ResolverBlockSymbol = JIT.findSymbolIn(H, TargetT::ResolverBlockName, false); @@ -182,7 +186,9 @@ private: TargetT::insertCompileCallbackTrampolines(*M, ResolverBlockAddr, this->NumTrampolinesPerBlock, this->ActiveTrampolines.size()); - auto H = JIT.addModuleSet(SingletonSet(std::move(M)), nullptr); + auto H = JIT.addModuleSet(SingletonSet(std::move(M)), &MemMgr, + static_cast( + nullptr)); JIT.emitAndFinalize(H); for (unsigned I = 0; I < this->NumTrampolinesPerBlock; ++I) { std::string Name = GetLabelName(I); @@ -193,6 +199,7 @@ private: } JITLayerT &JIT; + RuntimeDyld::MemoryManager &MemMgr; TargetAddress ResolverBlockAddr; }; diff --git a/include/llvm/ExecutionEngine/Orc/JITSymbol.h b/include/llvm/ExecutionEngine/Orc/JITSymbol.h index 7c3ad56ab2d..422a3761837 100644 --- a/include/llvm/ExecutionEngine/Orc/JITSymbol.h +++ b/include/llvm/ExecutionEngine/Orc/JITSymbol.h @@ -27,7 +27,7 @@ typedef uint64_t TargetAddress; /// @brief Represents a symbol in the JIT. class JITSymbol : public JITSymbolBase { -public: +public: typedef std::function GetAddressFtor; diff --git a/include/llvm/ExecutionEngine/Orc/LambdaResolver.h b/include/llvm/ExecutionEngine/Orc/LambdaResolver.h new file mode 100644 index 00000000000..faa23658524 --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/LambdaResolver.h @@ -0,0 +1,62 @@ +//===-- LambdaResolverMM - Redirect symbol lookup via a functor -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines a RuntimeDyld::SymbolResolver subclass that uses a user-supplied +// functor for symbol resolution. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H +#define LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" +#include +#include + +namespace llvm { +namespace orc { + +template +class LambdaResolver : public RuntimeDyld::SymbolResolver { +public: + + LambdaResolver(ExternalLookupFtorT ExternalLookupFtor, + DylibLookupFtorT DylibLookupFtor) + : ExternalLookupFtor(ExternalLookupFtor), + DylibLookupFtor(DylibLookupFtor) {} + + RuntimeDyld::SymbolInfo findSymbol(const std::string &Name) final { + return ExternalLookupFtor(Name); + } + + RuntimeDyld::SymbolInfo + findSymbolInLogicalDylib(const std::string &Name) final { + return DylibLookupFtor(Name); + } + +private: + ExternalLookupFtorT ExternalLookupFtor; + DylibLookupFtorT DylibLookupFtor; +}; + +template +std::unique_ptr> +createLambdaResolver(ExternalLookupFtorT ExternalLookupFtor, + DylibLookupFtorT DylibLookupFtor) { + typedef LambdaResolver LR; + return make_unique(std::move(ExternalLookupFtor), + std::move(DylibLookupFtor)); +} + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H diff --git a/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h b/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h index ac5fccfcd4d..71c83f7e05f 100644 --- a/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h +++ b/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h @@ -15,11 +15,11 @@ #define LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H #include "JITSymbol.h" -#include "LookasideRTDyldMM.h" #include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringMap.h" #include @@ -94,10 +94,11 @@ private: BaseLayer.emitAndFinalize(Handle); } - template + template static std::unique_ptr - create(BaseLayerT &B, ModuleSetT Ms, - std::unique_ptr MM); + create(BaseLayerT &B, ModuleSetT Ms, MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver); protected: virtual const GlobalValue* searchGVs(StringRef Name, @@ -109,12 +110,15 @@ private: BaseLayerHandleT Handle; }; - template + template class EmissionDeferredSetImpl : public EmissionDeferredSet { public: EmissionDeferredSetImpl(ModuleSetT Ms, - std::unique_ptr MM) - : Ms(std::move(Ms)), MM(std::move(MM)) {} + MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) + : Ms(std::move(Ms)), MemMgr(std::move(MemMgr)), + Resolver(std::move(Resolver)) {} protected: @@ -145,7 +149,8 @@ private: // We don't need the mangled names set any more: Once we've emitted this // to the base layer we'll just look for symbols there. MangledSymbols.reset(); - return BaseLayer.addModuleSet(std::move(Ms), std::move(MM)); + return BaseLayer.addModuleSet(std::move(Ms), std::move(MemMgr), + std::move(Resolver)); } private: @@ -206,7 +211,8 @@ private: } ModuleSetT Ms; - std::unique_ptr MM; + MemoryManagerPtrT MemMgr; + SymbolResolverPtrT Resolver; mutable std::unique_ptr> MangledSymbols; }; @@ -223,12 +229,15 @@ public: LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {} /// @brief Add the given set of modules to the lazy emitting layer. - template + template ModuleSetHandleT addModuleSet(ModuleSetT Ms, - std::unique_ptr MM) { + MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) { return ModuleSetList.insert( ModuleSetList.end(), - EmissionDeferredSet::create(BaseLayer, std::move(Ms), std::move(MM))); + EmissionDeferredSet::create(BaseLayer, std::move(Ms), std::move(MemMgr), + std::move(Resolver))); } /// @brief Remove the module set represented by the given handle. @@ -277,12 +286,16 @@ public: }; template -template +template std::unique_ptr::EmissionDeferredSet> LazyEmittingLayer::EmissionDeferredSet::create( - BaseLayerT &B, ModuleSetT Ms, std::unique_ptr MM) { - return llvm::make_unique>(std::move(Ms), - std::move(MM)); + BaseLayerT &B, ModuleSetT Ms, MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) { + typedef EmissionDeferredSetImpl + EDS; + return llvm::make_unique(std::move(Ms), std::move(MemMgr), + std::move(Resolver)); } } // End namespace orc. diff --git a/include/llvm/ExecutionEngine/Orc/LookasideRTDyldMM.h b/include/llvm/ExecutionEngine/Orc/LookasideRTDyldMM.h deleted file mode 100644 index 44564045656..00000000000 --- a/include/llvm/ExecutionEngine/Orc/LookasideRTDyldMM.h +++ /dev/null @@ -1,92 +0,0 @@ -//===- LookasideRTDyldMM - Redirect symbol lookup via a functor -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Defines an adapter for RuntimeDyldMM that allows lookups for external -// symbols to go via a functor. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_ORC_LOOKASIDERTDYLDMM_H -#define LLVM_EXECUTIONENGINE_ORC_LOOKASIDERTDYLDMM_H - -#include "llvm/ADT/STLExtras.h" -#include -#include - -namespace llvm { -namespace orc { - -/// @brief Defines an adapter for RuntimeDyldMM that allows lookups for external -/// symbols to go via a functor, before falling back to the lookup logic -/// provided by the underlying RuntimeDyldMM instance. -/// -/// This class is useful for redirecting symbol lookup back to various layers -/// of a JIT component stack, e.g. to enable lazy module emission. -/// -template -class LookasideRTDyldMM : public BaseRTDyldMM { -public: - /// @brief Create a LookasideRTDyldMM intance. - LookasideRTDyldMM(ExternalLookupFtor ExternalLookup, - DylibLookupFtor DylibLookup) - : ExternalLookup(std::move(ExternalLookup)), - DylibLookup(std::move(DylibLookup)) {} - - /// @brief Look up the given symbol address, first via the functor this - /// instance was created with, then (if the symbol isn't found) - /// via the underlying RuntimeDyldMM. - uint64_t getSymbolAddress(const std::string &Name) override { - if (uint64_t Addr = ExternalLookup(Name)) - return Addr; - return BaseRTDyldMM::getSymbolAddress(Name); - } - - uint64_t getSymbolAddressInLogicalDylib(const std::string &Name) override { - if (uint64_t Addr = DylibLookup(Name)) - return Addr; - return BaseRTDyldMM::getSymbolAddressInLogicalDylib(Name); - }; - - /// @brief Get a reference to the ExternalLookup functor. - ExternalLookupFtor &getExternalLookup() { return ExternalLookup; } - - /// @brief Get a const-reference to the ExternalLookup functor. - const ExternalLookupFtor &getExternalLookup() const { return ExternalLookup; } - - /// @brief Get a reference to the DylibLookup functor. - DylibLookupFtor &getDylibLookup() { return DylibLookup; } - - /// @brief Get a const-reference to the DylibLookup functor. - const DylibLookupFtor &getDylibLookup() const { return DylibLookup; } - -private: - ExternalLookupFtor ExternalLookup; - DylibLookupFtor DylibLookup; -}; - -/// @brief Create a LookasideRTDyldMM from a base memory manager type, an -/// external lookup functor, and a dylib lookup functor. -template -std::unique_ptr< - LookasideRTDyldMM> -createLookasideRTDyldMM(ExternalLookupFtor &&ExternalLookup, - DylibLookupFtor &&DylibLookup) { - typedef LookasideRTDyldMM - ThisLookasideMM; - return llvm::make_unique( - std::forward(ExternalLookup), - std::forward(DylibLookup)); -} - -} // End namespace orc. -} // End namespace llvm. - -#endif // LLVM_EXECUTIONENGINE_ORC_LOOKASIDERTDYLDMM_H diff --git a/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h b/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h index 9838991d6f4..9401efe4377 100644 --- a/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h +++ b/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h @@ -15,7 +15,6 @@ #define LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H #include "JITSymbol.h" -#include "LookasideRTDyldMM.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" #include @@ -38,13 +37,12 @@ protected: LinkedObjectSet(const LinkedObjectSet&) = delete; void operator=(const LinkedObjectSet&) = delete; public: - LinkedObjectSet(std::unique_ptr MM) - : MM(std::move(MM)), RTDyld(llvm::make_unique(&*this->MM)), + LinkedObjectSet(RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) + : RTDyld(llvm::make_unique(MemMgr, Resolver)), State(Raw) {} - // MSVC 2012 cannot infer a move constructor, so write it out longhand. - LinkedObjectSet(LinkedObjectSet &&O) - : MM(std::move(O.MM)), RTDyld(std::move(O.RTDyld)), State(O.State) {} + virtual ~LinkedObjectSet() {} std::unique_ptr addObject(const object::ObjectFile &Obj) { @@ -57,14 +55,7 @@ protected: bool NeedsFinalization() const { return (State == Raw); } - void Finalize() { - State = Finalizing; - RTDyld->resolveRelocations(); - RTDyld->registerEHFrames(); - MM->finalizeMemory(); - OwnedBuffers.clear(); - State = Finalized; - } + virtual void Finalize() = 0; void mapSectionAddress(const void *LocalAddress, TargetAddress TargetAddr) { assert((State != Finalized) && @@ -76,8 +67,7 @@ protected: OwnedBuffers.push_back(std::move(B)); } - private: - std::unique_ptr MM; + protected: std::unique_ptr RTDyld; enum { Raw, Finalizing, Finalized } State; @@ -87,7 +77,7 @@ protected: std::vector> OwnedBuffers; }; - typedef std::list LinkedObjectSetListT; + typedef std::list> LinkedObjectSetListT; public: /// @brief Handle to a set of loaded objects. @@ -99,7 +89,7 @@ public: template void takeOwnershipOfBuffers(ObjSetHandleT H, OwningMBSet MBs) { for (auto &MB : MBs) - H->takeOwnershipOfBuffer(std::move(MB)); + (*H)->takeOwnershipOfBuffer(std::move(MB)); } }; @@ -120,6 +110,37 @@ public: /// symbols. template class ObjectLinkingLayer : public ObjectLinkingLayerBase { +private: + + template + class ConcreteLinkedObjectSet : public LinkedObjectSet { + public: + ConcreteLinkedObjectSet(MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) + : LinkedObjectSet(*MemMgr, *Resolver), MemMgr(std::move(MemMgr)), + Resolver(std::move(Resolver)) { } + + void Finalize() override { + State = Finalizing; + RTDyld->resolveRelocations(); + RTDyld->registerEHFrames(); + MemMgr->finalizeMemory(); + OwnedBuffers.clear(); + State = Finalized; + } + + private: + MemoryManagerPtrT MemMgr; + SymbolResolverPtrT Resolver; + }; + + template + std::unique_ptr + createLinkedObjectSet(MemoryManagerPtrT MemMgr, SymbolResolverPtrT Resolver) { + typedef ConcreteLinkedObjectSet LOS; + return llvm::make_unique(std::move(MemMgr), std::move(Resolver)); + } + public: /// @brief LoadedObjectInfo list. Contains a list of owning pointers to @@ -127,21 +148,16 @@ public: typedef std::vector> LoadedObjInfoList; - /// @brief Functor to create RTDyldMemoryManager instances. - typedef std::function()> CreateRTDyldMMFtor; - /// @brief Functor for receiving finalization notifications. typedef std::function NotifyFinalizedFtor; /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded, - /// NotifyFinalized and CreateMemoryManager functors. + /// and NotifyFinalized functors. ObjectLinkingLayer( - CreateRTDyldMMFtor CreateMemoryManager = CreateRTDyldMMFtor(), NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(), NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor()) : NotifyLoaded(std::move(NotifyLoaded)), - NotifyFinalized(std::move(NotifyFinalized)), - CreateMemoryManager(std::move(CreateMemoryManager)) {} + NotifyFinalized(std::move(NotifyFinalized)) {} /// @brief Add a set of objects (or archives) that will be treated as a unit /// for the purposes of symbol lookup and memory management. @@ -154,19 +170,18 @@ public: /// This version of this method allows the client to pass in an /// RTDyldMemoryManager instance that will be used to allocate memory and look /// up external symbol addresses for the given objects. - template + template ObjSetHandleT addObjectSet(const ObjSetT &Objects, - std::unique_ptr MM) { - - if (!MM) { - assert(CreateMemoryManager && - "No memory manager or memory manager creator provided."); - MM = CreateMemoryManager(); - } - - ObjSetHandleT Handle = LinkedObjSetList.insert( - LinkedObjSetList.end(), LinkedObjectSet(std::move(MM))); - LinkedObjectSet &LOS = *Handle; + MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) { + ObjSetHandleT Handle = + LinkedObjSetList.insert( + LinkedObjSetList.end(), + createLinkedObjectSet(std::move(MemMgr), std::move(Resolver))); + + LinkedObjectSet &LOS = **Handle; LoadedObjInfoList LoadedObjInfos; for (auto &Obj : Objects) @@ -212,11 +227,11 @@ public: /// given object set. JITSymbol findSymbolIn(ObjSetHandleT H, StringRef Name, bool ExportedSymbolsOnly) { - if (auto Sym = H->getSymbol(Name)) { + if (auto Sym = (*H)->getSymbol(Name)) { if (Sym.isExported() || !ExportedSymbolsOnly) { auto Addr = Sym.getAddress(); auto Flags = Sym.getFlags(); - if (!H->NeedsFinalization()) { + if (!(*H)->NeedsFinalization()) { // If this instance has already been finalized then we can just return // the address. return JITSymbol(Addr, Flags); @@ -225,10 +240,10 @@ public: // it. The functor still needs to double-check whether finalization is // required, in case someone else finalizes this set before the // functor is called. - auto GetAddress = + auto GetAddress = [this, Addr, H]() { - if (H->NeedsFinalization()) { - H->Finalize(); + if ((*H)->NeedsFinalization()) { + (*H)->Finalize(); if (NotifyFinalized) NotifyFinalized(H); } @@ -244,14 +259,14 @@ public: /// @brief Map section addresses for the objects associated with the handle H. void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress, TargetAddress TargetAddr) { - H->mapSectionAddress(LocalAddress, TargetAddr); + (*H)->mapSectionAddress(LocalAddress, TargetAddr); } /// @brief Immediately emit and finalize the object set represented by the /// given handle. /// @param H Handle for object set to emit/finalize. void emitAndFinalize(ObjSetHandleT H) { - H->Finalize(); + (*H)->Finalize(); if (NotifyFinalized) NotifyFinalized(H); } @@ -260,7 +275,6 @@ private: LinkedObjectSetListT LinkedObjSetList; NotifyLoadedFtor NotifyLoaded; NotifyFinalizedFtor NotifyFinalized; - CreateRTDyldMMFtor CreateMemoryManager; }; } // End namespace orc. diff --git a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h index 792a4999bc8..098009a9f92 100644 --- a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h +++ b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h @@ -14,6 +14,7 @@ #ifndef LLVM_EXECUTIONENGINE_RTDYLDMEMORYMANAGER_H #define LLVM_EXECUTIONENGINE_RTDYLDMEMORYMANAGER_H +#include "RuntimeDyld.h" #include "llvm-c/ExecutionEngine.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/CBindingWrapping.h" @@ -27,89 +28,91 @@ class ExecutionEngine; class ObjectFile; } +class MCJITMemoryManager : public RuntimeDyld::MemoryManager { +public: + /// This method is called after an object has been loaded into memory but + /// before relocations are applied to the loaded sections. The object load + /// may have been initiated by MCJIT to resolve an external symbol for another + /// object that is being finalized. In that case, the object about which + /// the memory manager is being notified will be finalized immediately after + /// the memory manager returns from this call. + /// + /// Memory managers which are preparing code for execution in an external + /// address space can use this call to remap the section addresses for the + /// newly loaded object. + virtual void notifyObjectLoaded(ExecutionEngine *EE, + const object::ObjectFile &) {} +}; + // RuntimeDyld clients often want to handle the memory management of // what gets placed where. For JIT clients, this is the subset of // JITMemoryManager required for dynamic loading of binaries. // // FIXME: As the RuntimeDyld fills out, additional routines will be needed // for the varying types of objects to be allocated. -class RTDyldMemoryManager { +class RTDyldMemoryManager : public MCJITMemoryManager, + public RuntimeDyld::SymbolResolver { RTDyldMemoryManager(const RTDyldMemoryManager&) = delete; void operator=(const RTDyldMemoryManager&) = delete; public: RTDyldMemoryManager() {} virtual ~RTDyldMemoryManager(); - /// Allocate a memory block of (at least) the given size suitable for - /// executable code. The SectionID is a unique identifier assigned by the JIT - /// engine, and optionally recorded by the memory manager to access a loaded - /// section. - virtual uint8_t *allocateCodeSection( - uintptr_t Size, unsigned Alignment, unsigned SectionID, - StringRef SectionName) = 0; - - /// Allocate a memory block of (at least) the given size suitable for data. - /// The SectionID is a unique identifier assigned by the JIT engine, and - /// optionally recorded by the memory manager to access a loaded section. - virtual uint8_t *allocateDataSection( - uintptr_t Size, unsigned Alignment, unsigned SectionID, - StringRef SectionName, bool IsReadOnly) = 0; - - /// Inform the memory manager about the total amount of memory required to - /// allocate all sections to be loaded: - /// \p CodeSize - the total size of all code sections - /// \p DataSizeRO - the total size of all read-only data sections - /// \p DataSizeRW - the total size of all read-write data sections - /// - /// Note that by default the callback is disabled. To enable it - /// redefine the method needsToReserveAllocationSpace to return true. - virtual void reserveAllocationSpace( - uintptr_t CodeSize, uintptr_t DataSizeRO, uintptr_t DataSizeRW) { } - - /// Override to return true to enable the reserveAllocationSpace callback. - virtual bool needsToReserveAllocationSpace() { return false; } - - /// Register the EH frames with the runtime so that c++ exceptions work. - /// - /// \p Addr parameter provides the local address of the EH frame section - /// data, while \p LoadAddr provides the address of the data in the target - /// address space. If the section has not been remapped (which will usually - /// be the case for local execution) these two values will be the same. - virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size); - - virtual void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size); + void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override; + void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override; /// This method returns the address of the specified function or variable in /// the current process. static uint64_t getSymbolAddressInProcess(const std::string &Name); + /// Legacy symbol lookup - DEPRECATED! Please override findSymbol instead. + /// /// This method returns the address of the specified function or variable. /// It is used to resolve symbols during module linking. virtual uint64_t getSymbolAddress(const std::string &Name) { return getSymbolAddressInProcess(Name); } - /// This method returns the address of the specified symbol if it exists - /// within the logical dynamic library represented by this - /// RTDyldMemoryManager. Unlike getSymbolAddress, queries through this - /// interface should return addresses for hidden symbols. + /// This method returns a RuntimeDyld::SymbolInfo for the specified function + /// or variable. It is used to resolve symbols during module linking. + /// + /// By default this falls back on the legacy lookup method: + /// 'getSymbolAddress'. The address returned by getSymbolAddress is treated as + /// a strong, exported symbol, consistent with historical treatment by + /// RuntimeDyld. /// - /// This is of particular importance for the Orc JIT APIs, which support lazy - /// compilation by breaking up modules: Each of those broken out modules - /// must be able to resolve hidden symbols provided by the others. Clients - /// writing memory managers for MCJIT can usually ignore this method. + /// Clients writing custom RTDyldMemoryManagers are encouraged to override + /// this method and return a SymbolInfo with the flags set correctly. This is + /// necessary for RuntimeDyld to correctly handle weak and non-exported symbols. + RuntimeDyld::SymbolInfo findSymbol(const std::string &Name) override { + return RuntimeDyld::SymbolInfo(getSymbolAddress(Name), + JITSymbolFlags::Exported); + } + + /// Legacy symbol lookup -- DEPRECATED! Please override + /// findSymbolInLogicalDylib instead. /// - /// This method will be queried by RuntimeDyld when checking for previous - /// definitions of common symbols. It will *not* be queried by default when - /// resolving external symbols (this minimises the link-time overhead for - /// MCJIT clients who don't care about Orc features). If you are writing a - /// RTDyldMemoryManager for Orc and want "external" symbol resolution to - /// search the logical dylib, you should override your getSymbolAddress - /// method call this method directly. + /// Default to treating all modules as separate. virtual uint64_t getSymbolAddressInLogicalDylib(const std::string &Name) { return 0; } + /// Default to treating all modules as separate. + /// + /// By default this falls back on the legacy lookup method: + /// 'getSymbolAddressInLogicalDylib'. The address returned by + /// getSymbolAddressInLogicalDylib is treated as a strong, exported symbol, + /// consistent with historical treatment by RuntimeDyld. + /// + /// Clients writing custom RTDyldMemoryManagers are encouraged to override + /// this method and return a SymbolInfo with the flags set correctly. This is + /// necessary for RuntimeDyld to correctly handle weak and non-exported symbols. + RuntimeDyld::SymbolInfo + findSymbolInLogicalDylib(const std::string &Name) override { + return RuntimeDyld::SymbolInfo(getSymbolAddressInLogicalDylib(Name), + JITSymbolFlags::Exported); + } + /// This method returns the address of the specified function. As such it is /// only useful for resolving library symbols, not code generated symbols. /// @@ -121,30 +124,6 @@ public: /// MCJIT or RuntimeDyld. Use getSymbolAddress instead. virtual void *getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure = true); - - /// This method is called after an object has been loaded into memory but - /// before relocations are applied to the loaded sections. The object load - /// may have been initiated by MCJIT to resolve an external symbol for another - /// object that is being finalized. In that case, the object about which - /// the memory manager is being notified will be finalized immediately after - /// the memory manager returns from this call. - /// - /// Memory managers which are preparing code for execution in an external - /// address space can use this call to remap the section addresses for the - /// newly loaded object. - virtual void notifyObjectLoaded(ExecutionEngine *EE, - const object::ObjectFile &) {} - - /// This method is called when object loading is complete and section page - /// permissions can be applied. It is up to the memory manager implementation - /// to decide whether or not to act on this method. The memory manager will - /// typically allocate all sections as read-write and then apply specific - /// permissions when this method is called. Code sections cannot be executed - /// until this function has been called. In addition, any cache coherency - /// operations needed to reliably use the memory are also performed. - /// - /// Returns true if an error occurred, false otherwise. - virtual bool finalizeMemory(std::string *ErrMsg = nullptr) = 0; }; // Create wrappers for C Binding types (see CBindingWrapping.h). @@ -153,4 +132,5 @@ DEFINE_SIMPLE_CONVERSION_FUNCTIONS( } // namespace llvm + #endif diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index fe0ccdaaa1a..5723f058f72 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -16,7 +16,6 @@ #include "JITSymbolFlags.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/Support/Memory.h" #include @@ -29,19 +28,13 @@ namespace object { class RuntimeDyldImpl; class RuntimeDyldCheckerImpl; - + class RuntimeDyld { friend class RuntimeDyldCheckerImpl; RuntimeDyld(const RuntimeDyld &) = delete; void operator=(const RuntimeDyld &) = delete; - // RuntimeDyldImpl is the actual class. RuntimeDyld is just the public - // interface. - std::unique_ptr Dyld; - RTDyldMemoryManager *MM; - bool ProcessAllSections; - RuntimeDyldCheckerImpl *Checker; protected: // Change the address associated with a section when resolving relocations. // Any relocations already associated with the symbol will be re-resolved. @@ -82,7 +75,101 @@ public: unsigned BeginIdx, EndIdx; }; - RuntimeDyld(RTDyldMemoryManager *); + /// \brief Memory Management. + class MemoryManager { + public: + virtual ~MemoryManager() {}; + + /// Allocate a memory block of (at least) the given size suitable for + /// executable code. The SectionID is a unique identifier assigned by the + /// RuntimeDyld instance, and optionally recorded by the memory manager to + /// access a loaded section. + virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, + StringRef SectionName) = 0; + + /// Allocate a memory block of (at least) the given size suitable for data. + /// The SectionID is a unique identifier assigned by the JIT engine, and + /// optionally recorded by the memory manager to access a loaded section. + virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, + StringRef SectionName, + bool IsReadOnly) = 0; + + /// Inform the memory manager about the total amount of memory required to + /// allocate all sections to be loaded: + /// \p CodeSize - the total size of all code sections + /// \p DataSizeRO - the total size of all read-only data sections + /// \p DataSizeRW - the total size of all read-write data sections + /// + /// Note that by default the callback is disabled. To enable it + /// redefine the method needsToReserveAllocationSpace to return true. + virtual void reserveAllocationSpace(uintptr_t CodeSize, + uintptr_t DataSizeRO, + uintptr_t DataSizeRW) {} + + /// Override to return true to enable the reserveAllocationSpace callback. + virtual bool needsToReserveAllocationSpace() { return false; } + + /// Register the EH frames with the runtime so that c++ exceptions work. + /// + /// \p Addr parameter provides the local address of the EH frame section + /// data, while \p LoadAddr provides the address of the data in the target + /// address space. If the section has not been remapped (which will usually + /// be the case for local execution) these two values will be the same. + virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, + size_t Size) = 0; + virtual void deregisterEHFrames(uint8_t *addr, uint64_t LoadAddr, + size_t Size) = 0; + + /// This method is called when object loading is complete and section page + /// permissions can be applied. It is up to the memory manager implementation + /// to decide whether or not to act on this method. The memory manager will + /// typically allocate all sections as read-write and then apply specific + /// permissions when this method is called. Code sections cannot be executed + /// until this function has been called. In addition, any cache coherency + /// operations needed to reliably use the memory are also performed. + /// + /// Returns true if an error occurred, false otherwise. + virtual bool finalizeMemory(std::string *ErrMsg = nullptr) = 0; + + private: + virtual void anchor(); + }; + + /// \brief Symbol resolution. + class SymbolResolver { + public: + virtual ~SymbolResolver() {}; + + /// This method returns the address of the specified function or variable. + /// It is used to resolve symbols during module linking. + virtual SymbolInfo findSymbol(const std::string &Name) = 0; + + /// This method returns the address of the specified symbol if it exists + /// within the logical dynamic library represented by this + /// RTDyldMemoryManager. Unlike getSymbolAddress, queries through this + /// interface should return addresses for hidden symbols. + /// + /// This is of particular importance for the Orc JIT APIs, which support lazy + /// compilation by breaking up modules: Each of those broken out modules + /// must be able to resolve hidden symbols provided by the others. Clients + /// writing memory managers for MCJIT can usually ignore this method. + /// + /// This method will be queried by RuntimeDyld when checking for previous + /// definitions of common symbols. It will *not* be queried by default when + /// resolving external symbols (this minimises the link-time overhead for + /// MCJIT clients who don't care about Orc features). If you are writing a + /// RTDyldMemoryManager for Orc and want "external" symbol resolution to + /// search the logical dylib, you should override your getSymbolAddress + /// method call this method directly. + virtual SymbolInfo findSymbolInLogicalDylib(const std::string &Name) = 0; + private: + virtual void anchor(); + }; + + /// \brief Construct a RuntimeDyld instance. + RuntimeDyld(MemoryManager &MemMgr, SymbolResolver &Resolver); ~RuntimeDyld(); /// Add the referenced object file to the list of objects to be loaded and @@ -131,6 +218,15 @@ public: assert(!Dyld && "setProcessAllSections must be called before loadObject."); this->ProcessAllSections = ProcessAllSections; } + +private: + // RuntimeDyldImpl is the actual class. RuntimeDyld is just the public + // interface. + std::unique_ptr Dyld; + MemoryManager &MemMgr; + SymbolResolver &Resolver; + bool ProcessAllSections; + RuntimeDyldCheckerImpl *Checker; }; } // end namespace llvm diff --git a/include/llvm/ExecutionEngine/SectionMemoryManager.h b/include/llvm/ExecutionEngine/SectionMemoryManager.h index b825afffc0c..b30934f8103 100644 --- a/include/llvm/ExecutionEngine/SectionMemoryManager.h +++ b/include/llvm/ExecutionEngine/SectionMemoryManager.h @@ -16,7 +16,7 @@ #define LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H #include "llvm/ADT/SmallVector.h" -#include "llvm/ExecutionEngine/RuntimeDyld.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Memory.h" diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index c586ba725c5..238663a16be 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/ExecutionEngine/JITEventListener.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" @@ -45,11 +46,13 @@ STATISTIC(NumGlobals , "Number of global vars initialized"); ExecutionEngine *(*ExecutionEngine::MCJITCtor)( std::unique_ptr M, std::string *ErrorStr, - std::unique_ptr MCJMM, + std::shared_ptr MemMgr, + std::shared_ptr Resolver, std::unique_ptr TM) = nullptr; ExecutionEngine *(*ExecutionEngine::OrcMCJITReplacementCtor)( - std::string *ErrorStr, std::unique_ptr OrcJMM, + std::string *ErrorStr, std::shared_ptr MemMgr, + std::shared_ptr Resolver, std::unique_ptr TM) = nullptr; ExecutionEngine *(*ExecutionEngine::InterpCtor)(std::unique_ptr M, @@ -404,8 +407,9 @@ EngineBuilder::EngineBuilder() : EngineBuilder(nullptr) {} EngineBuilder::EngineBuilder(std::unique_ptr M) : M(std::move(M)), WhichEngine(EngineKind::Either), ErrorStr(nullptr), - OptLevel(CodeGenOpt::Default), MCJMM(nullptr), RelocModel(Reloc::Default), - CMModel(CodeModel::JITDefault), UseOrcMCJITReplacement(false) { + OptLevel(CodeGenOpt::Default), MemMgr(nullptr), Resolver(nullptr), + RelocModel(Reloc::Default), CMModel(CodeModel::JITDefault), + UseOrcMCJITReplacement(false) { // IR module verification is enabled by default in debug builds, and disabled // by default in release builds. #ifndef NDEBUG @@ -419,7 +423,21 @@ EngineBuilder::~EngineBuilder() = default; EngineBuilder &EngineBuilder::setMCJITMemoryManager( std::unique_ptr mcjmm) { - MCJMM = std::move(mcjmm); + auto SharedMM = std::shared_ptr(std::move(mcjmm)); + MemMgr = SharedMM; + Resolver = SharedMM; + return *this; +} + +EngineBuilder& +EngineBuilder::setMemoryManager(std::unique_ptr MM) { + MemMgr = std::shared_ptr(std::move(MM)); + return *this; +} + +EngineBuilder& +EngineBuilder::setSymbolResolver(std::unique_ptr SR) { + Resolver = std::shared_ptr(std::move(SR)); return *this; } @@ -434,7 +452,7 @@ ExecutionEngine *EngineBuilder::create(TargetMachine *TM) { // If the user specified a memory manager but didn't specify which engine to // create, we assume they only want the JIT, and we fail if they only want // the interpreter. - if (MCJMM) { + if (MemMgr) { if (WhichEngine & EngineKind::JIT) WhichEngine = EngineKind::JIT; else { @@ -456,12 +474,13 @@ ExecutionEngine *EngineBuilder::create(TargetMachine *TM) { ExecutionEngine *EE = nullptr; if (ExecutionEngine::OrcMCJITReplacementCtor && UseOrcMCJITReplacement) { - EE = ExecutionEngine::OrcMCJITReplacementCtor(ErrorStr, std::move(MCJMM), + EE = ExecutionEngine::OrcMCJITReplacementCtor(ErrorStr, std::move(MemMgr), + std::move(Resolver), std::move(TheTM)); EE->addModule(std::move(M)); } else if (ExecutionEngine::MCJITCtor) - EE = ExecutionEngine::MCJITCtor(std::move(M), ErrorStr, std::move(MCJMM), - std::move(TheTM)); + EE = ExecutionEngine::MCJITCtor(std::move(M), ErrorStr, std::move(MemMgr), + std::move(Resolver), std::move(TheTM)); if (EE) { EE->setVerifyModules(VerifyModules); diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/lib/ExecutionEngine/MCJIT/MCJIT.cpp index 20b85532e0b..7e37afe2056 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "MCJIT.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/ExecutionEngine/JITEventListener.h" #include "llvm/ExecutionEngine/MCJIT.h" @@ -41,26 +42,35 @@ static struct RegisterJIT { extern "C" void LLVMLinkInMCJIT() { } -ExecutionEngine *MCJIT::createJIT(std::unique_ptr M, - std::string *ErrorStr, - std::unique_ptr MemMgr, - std::unique_ptr TM) { +ExecutionEngine* +MCJIT::createJIT(std::unique_ptr M, + std::string *ErrorStr, + std::shared_ptr MemMgr, + std::shared_ptr Resolver, + std::unique_ptr TM) { // Try to register the program as a source of symbols to resolve against. // // FIXME: Don't do this here. sys::DynamicLibrary::LoadLibraryPermanently(nullptr, nullptr); - std::unique_ptr MM = std::move(MemMgr); - if (!MM) - MM = std::unique_ptr(new SectionMemoryManager()); + if (!MemMgr || !Resolver) { + auto RTDyldMM = std::make_shared(); + if (!MemMgr) + MemMgr = RTDyldMM; + if (!Resolver) + Resolver = RTDyldMM; + } - return new MCJIT(std::move(M), std::move(TM), std::move(MM)); + return new MCJIT(std::move(M), std::move(TM), std::move(MemMgr), + std::move(Resolver)); } MCJIT::MCJIT(std::unique_ptr M, std::unique_ptr tm, - std::unique_ptr MM) + std::shared_ptr MemMgr, + std::shared_ptr Resolver) : ExecutionEngine(std::move(M)), TM(std::move(tm)), Ctx(nullptr), - MemMgr(this, std::move(MM)), Dyld(&MemMgr), ObjCache(nullptr) { + MemMgr(std::move(MemMgr)), Resolver(*this, std::move(Resolver)), + Dyld(*this->MemMgr, this->Resolver), ObjCache(nullptr) { // FIXME: We are managing our modules, so we do not want the base class // ExecutionEngine to manage them as well. To avoid double destruction // of the first (and only) module added in ExecutionEngine constructor @@ -221,7 +231,7 @@ void MCJIT::finalizeLoadedModules() { Dyld.registerEHFrames(); // Set page permissions. - MemMgr.finalizeMemory(); + MemMgr->finalizeMemory(); } // FIXME: Rename this. @@ -253,11 +263,11 @@ void MCJIT::finalizeModule(Module *M) { finalizeLoadedModules(); } -uint64_t MCJIT::getExistingSymbolAddress(const std::string &Name) { +RuntimeDyld::SymbolInfo MCJIT::findExistingSymbol(const std::string &Name) { Mangler Mang(TM->getDataLayout()); SmallString<128> FullName; Mang.getNameWithPrefix(FullName, Name); - return Dyld.getSymbol(FullName).getAddress(); + return Dyld.getSymbol(FullName); } Module *MCJIT::findModuleForSymbol(const std::string &Name, @@ -284,14 +294,17 @@ Module *MCJIT::findModuleForSymbol(const std::string &Name, } uint64_t MCJIT::getSymbolAddress(const std::string &Name, - bool CheckFunctionsOnly) -{ + bool CheckFunctionsOnly) { + return findSymbol(Name, CheckFunctionsOnly).getAddress(); +} + +RuntimeDyld::SymbolInfo MCJIT::findSymbol(const std::string &Name, + bool CheckFunctionsOnly) { MutexGuard locked(lock); // First, check to see if we already have this symbol. - uint64_t Addr = getExistingSymbolAddress(Name); - if (Addr) - return Addr; + if (auto Sym = findExistingSymbol(Name)) + return Sym; for (object::OwningBinary &OB : Archives) { object::Archive *A = OB.getBinary(); @@ -310,9 +323,8 @@ uint64_t MCJIT::getSymbolAddress(const std::string &Name, // This causes the object file to be loaded. addObjectFile(std::move(OF)); // The address should be here now. - Addr = getExistingSymbolAddress(Name); - if (Addr) - return Addr; + if (auto Sym = findExistingSymbol(Name)) + return Sym; } } } @@ -323,15 +335,18 @@ uint64_t MCJIT::getSymbolAddress(const std::string &Name, generateCodeForModule(M); // Check the RuntimeDyld table again, it should be there now. - return getExistingSymbolAddress(Name); + return findExistingSymbol(Name); } // If a LazyFunctionCreator is installed, use it to get/create the function. // FIXME: Should we instead have a LazySymbolCreator callback? - if (LazyFunctionCreator) - Addr = (uint64_t)LazyFunctionCreator(Name); + if (LazyFunctionCreator) { + auto Addr = static_cast( + reinterpret_cast(LazyFunctionCreator(Name))); + return RuntimeDyld::SymbolInfo(Addr, JITSymbolFlags::Exported); + } - return Addr; + return nullptr; } uint64_t MCJIT::getGlobalValueAddress(const std::string &Name) { @@ -528,7 +543,9 @@ GenericValue MCJIT::runFunction(Function *F, void *MCJIT::getPointerToNamedFunction(StringRef Name, bool AbortOnFailure) { if (!isSymbolSearchingDisabled()) { - void *ptr = MemMgr.getPointerToNamedFunction(Name, false); + void *ptr = + reinterpret_cast( + static_cast(Resolver.findSymbol(Name).getAddress())); if (ptr) return ptr; } @@ -566,7 +583,7 @@ void MCJIT::UnregisterJITEventListener(JITEventListener *L) { void MCJIT::NotifyObjectEmitted(const object::ObjectFile& Obj, const RuntimeDyld::LoadedObjectInfo &L) { MutexGuard locked(lock); - MemMgr.notifyObjectLoaded(this, Obj); + MemMgr->notifyObjectLoaded(this, Obj); for (unsigned I = 0, S = EventListeners.size(); I < S; ++I) { EventListeners[I]->NotifyObjectEmitted(Obj, L); } @@ -578,15 +595,16 @@ void MCJIT::NotifyFreeingObject(const object::ObjectFile& Obj) { L->NotifyFreeingObject(Obj); } -uint64_t LinkingMemoryManager::getSymbolAddress(const std::string &Name) { - uint64_t Result = ParentEngine->getSymbolAddress(Name, false); +RuntimeDyld::SymbolInfo +LinkingSymbolResolver::findSymbol(const std::string &Name) { + auto Result = ParentEngine.findSymbol(Name, false); // If the symbols wasn't found and it begins with an underscore, try again // without the underscore. if (!Result && Name[0] == '_') - Result = ParentEngine->getSymbolAddress(Name.substr(1), false); + Result = ParentEngine.findSymbol(Name.substr(1), false); if (Result) return Result; - if (ParentEngine->isSymbolSearchingDisabled()) - return 0; - return ClientMM->getSymbolAddress(Name); + if (ParentEngine.isSymbolSearchingDisabled()) + return nullptr; + return ClientResolver->findSymbol(Name); } diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.h b/lib/ExecutionEngine/MCJIT/MCJIT.h index de4a8f6a60d..cee1550d185 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.h +++ b/lib/ExecutionEngine/MCJIT/MCJIT.h @@ -16,6 +16,7 @@ #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/ObjectCache.h" #include "llvm/ExecutionEngine/ObjectMemoryBuffer.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/IR/Module.h" @@ -26,59 +27,23 @@ class MCJIT; // functions across modules that it owns. It aggregates the memory manager // that is passed in to the MCJIT constructor and defers most functionality // to that object. -class LinkingMemoryManager : public RTDyldMemoryManager { +class LinkingSymbolResolver : public RuntimeDyld::SymbolResolver { public: - LinkingMemoryManager(MCJIT *Parent, - std::unique_ptr MM) - : ParentEngine(Parent), ClientMM(std::move(MM)) {} + LinkingSymbolResolver(MCJIT &Parent, + std::shared_ptr Resolver) + : ParentEngine(Parent), ClientResolver(std::move(Resolver)) {} - uint64_t getSymbolAddress(const std::string &Name) override; + RuntimeDyld::SymbolInfo findSymbol(const std::string &Name) override; - // Functions deferred to client memory manager - uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID, - StringRef SectionName) override { - return ClientMM->allocateCodeSection(Size, Alignment, SectionID, SectionName); - } - - uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID, StringRef SectionName, - bool IsReadOnly) override { - return ClientMM->allocateDataSection(Size, Alignment, - SectionID, SectionName, IsReadOnly); - } - - void reserveAllocationSpace(uintptr_t CodeSize, uintptr_t DataSizeRO, - uintptr_t DataSizeRW) override { - return ClientMM->reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW); - } - - bool needsToReserveAllocationSpace() override { - return ClientMM->needsToReserveAllocationSpace(); - } - - void notifyObjectLoaded(ExecutionEngine *EE, - const object::ObjectFile &Obj) override { - ClientMM->notifyObjectLoaded(EE, Obj); - } - - void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, - size_t Size) override { - ClientMM->registerEHFrames(Addr, LoadAddr, Size); - } - - void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, - size_t Size) override { - ClientMM->deregisterEHFrames(Addr, LoadAddr, Size); - } - - bool finalizeMemory(std::string *ErrMsg = nullptr) override { - return ClientMM->finalizeMemory(ErrMsg); + // MCJIT doesn't support logical dylibs. + RuntimeDyld::SymbolInfo + findSymbolInLogicalDylib(const std::string &Name) override { + return nullptr; } private: - MCJIT *ParentEngine; - std::unique_ptr ClientMM; + MCJIT &ParentEngine; + std::shared_ptr ClientResolver; }; // About Module states: added->loaded->finalized. @@ -103,7 +68,8 @@ private: class MCJIT : public ExecutionEngine { MCJIT(std::unique_ptr M, std::unique_ptr tm, - std::unique_ptr MemMgr); + std::shared_ptr MemMgr, + std::shared_ptr Resolver); typedef llvm::SmallPtrSet ModulePtrSet; @@ -214,7 +180,8 @@ class MCJIT : public ExecutionEngine { std::unique_ptr TM; MCContext *Ctx; - LinkingMemoryManager MemMgr; + std::shared_ptr MemMgr; + LinkingSymbolResolver Resolver; RuntimeDyld Dyld; std::vector EventListeners; @@ -324,17 +291,22 @@ public: MCJITCtor = createJIT; } - static ExecutionEngine *createJIT(std::unique_ptr M, - std::string *ErrorStr, - std::unique_ptr MemMgr, - std::unique_ptr TM); + static ExecutionEngine* + createJIT(std::unique_ptr M, + std::string *ErrorStr, + std::shared_ptr MemMgr, + std::shared_ptr Resolver, + std::unique_ptr TM); // @} + RuntimeDyld::SymbolInfo findSymbol(const std::string &Name, + bool CheckFunctionsOnly); + // DEPRECATED - Please use findSymbol instead. // This is not directly exposed via the ExecutionEngine API, but it is // used by the LinkingMemoryManager. uint64_t getSymbolAddress(const std::string &Name, - bool CheckFunctionsOnly); + bool CheckFunctionsOnly); protected: /// emitObject -- Generate a JITed object in memory from the specified module @@ -348,7 +320,7 @@ protected: const RuntimeDyld::LoadedObjectInfo &L); void NotifyFreeingObject(const object::ObjectFile& Obj); - uint64_t getExistingSymbolAddress(const std::string &Name); + RuntimeDyld::SymbolInfo findExistingSymbol(const std::string &Name); Module *findModuleForSymbol(const std::string &Name, bool CheckFunctionsOnly); }; diff --git a/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h b/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h index 00e39bb73c1..32f5cdb1be9 100644 --- a/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h +++ b/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h @@ -26,15 +26,21 @@ namespace orc { class OrcMCJITReplacement : public ExecutionEngine { - class ForwardingRTDyldMM : public RTDyldMemoryManager { + // OrcMCJITReplacement needs to do a little extra book-keeping to ensure that + // Orc's automatic finalization doesn't kick in earlier than MCJIT clients are + // expecting - see finalizeMemory. + class MCJITReplacementMemMgr : public MCJITMemoryManager { public: - ForwardingRTDyldMM(OrcMCJITReplacement &M) : M(M) {} + MCJITReplacementMemMgr(OrcMCJITReplacement &M, + std::shared_ptr ClientMM) + : M(M), ClientMM(std::move(ClientMM)) {} uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName) override { uint8_t *Addr = - M.MM->allocateCodeSection(Size, Alignment, SectionID, SectionName); + ClientMM->allocateCodeSection(Size, Alignment, SectionID, + SectionName); M.SectionsAllocatedSinceLastLoad.insert(Addr); return Addr; } @@ -42,43 +48,35 @@ class OrcMCJITReplacement : public ExecutionEngine { uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName, bool IsReadOnly) override { - uint8_t *Addr = M.MM->allocateDataSection(Size, Alignment, SectionID, - SectionName, IsReadOnly); + uint8_t *Addr = ClientMM->allocateDataSection(Size, Alignment, SectionID, + SectionName, IsReadOnly); M.SectionsAllocatedSinceLastLoad.insert(Addr); return Addr; } void reserveAllocationSpace(uintptr_t CodeSize, uintptr_t DataSizeRO, uintptr_t DataSizeRW) override { - return M.MM->reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW); + return ClientMM->reserveAllocationSpace(CodeSize, DataSizeRO, + DataSizeRW); } bool needsToReserveAllocationSpace() override { - return M.MM->needsToReserveAllocationSpace(); + return ClientMM->needsToReserveAllocationSpace(); } void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override { - return M.MM->registerEHFrames(Addr, LoadAddr, Size); + return ClientMM->registerEHFrames(Addr, LoadAddr, Size); } void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override { - return M.MM->deregisterEHFrames(Addr, LoadAddr, Size); - } - - uint64_t getSymbolAddress(const std::string &Name) override { - return M.getSymbolAddressWithoutMangling(Name); - } - - void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true) override { - return M.MM->getPointerToNamedFunction(Name, AbortOnFailure); + return ClientMM->deregisterEHFrames(Addr, LoadAddr, Size); } void notifyObjectLoaded(ExecutionEngine *EE, const object::ObjectFile &O) override { - return M.MM->notifyObjectLoaded(EE, O); + return ClientMM->notifyObjectLoaded(EE, O); } bool finalizeMemory(std::string *ErrMsg = nullptr) override { @@ -96,10 +94,27 @@ class OrcMCJITReplacement : public ExecutionEngine { // get more than one set of objects loaded but not yet finalized is if // they were loaded during relocation of another set. if (M.UnfinalizedSections.size() == 1) - return M.MM->finalizeMemory(ErrMsg); + return ClientMM->finalizeMemory(ErrMsg); return false; } + private: + OrcMCJITReplacement &M; + std::shared_ptr ClientMM; + }; + + class LinkingResolver : public RuntimeDyld::SymbolResolver { + public: + LinkingResolver(OrcMCJITReplacement &M) : M(M) {} + + RuntimeDyld::SymbolInfo findSymbol(const std::string &Name) { + return M.findMangledSymbol(Name); + } + + RuntimeDyld::SymbolInfo findSymbolInLogicalDylib(const std::string &Name) { + return M.ClientResolver->findSymbolInLogicalDylib(Name); + } + private: OrcMCJITReplacement &M; }; @@ -108,9 +123,11 @@ private: static ExecutionEngine * createOrcMCJITReplacement(std::string *ErrorMsg, - std::unique_ptr OrcJMM, + std::shared_ptr MemMgr, + std::shared_ptr Resolver, std::unique_ptr TM) { - return new OrcMCJITReplacement(std::move(OrcJMM), std::move(TM)); + return new OrcMCJITReplacement(std::move(MemMgr), std::move(Resolver), + std::move(TM)); } public: @@ -118,12 +135,15 @@ public: OrcMCJITReplacementCtor = createOrcMCJITReplacement; } - OrcMCJITReplacement(std::unique_ptr MM, - std::unique_ptr TM) - : TM(std::move(TM)), MM(std::move(MM)), Mang(this->TM->getDataLayout()), + OrcMCJITReplacement( + std::shared_ptr MemMgr, + std::shared_ptr ClientResolver, + std::unique_ptr TM) + : TM(std::move(TM)), MemMgr(*this, std::move(MemMgr)), + Resolver(*this), ClientResolver(std::move(ClientResolver)), + Mang(this->TM->getDataLayout()), NotifyObjectLoaded(*this), NotifyFinalized(*this), - ObjectLayer(ObjectLayerT::CreateRTDyldMMFtor(), NotifyObjectLoaded, - NotifyFinalized), + ObjectLayer(NotifyObjectLoaded, NotifyFinalized), CompileLayer(ObjectLayer, SimpleCompiler(*this->TM)), LazyEmitLayer(CompileLayer) { setDataLayout(this->TM->getDataLayout()); @@ -139,15 +159,13 @@ public: Modules.push_back(std::move(M)); std::vector Ms; Ms.push_back(&*Modules.back()); - LazyEmitLayer.addModuleSet(std::move(Ms), - llvm::make_unique(*this)); + LazyEmitLayer.addModuleSet(std::move(Ms), &MemMgr, &Resolver); } void addObjectFile(std::unique_ptr O) override { std::vector> Objs; Objs.push_back(std::move(O)); - ObjectLayer.addObjectSet(std::move(Objs), - llvm::make_unique(*this)); + ObjectLayer.addObjectSet(std::move(Objs), &MemMgr, &Resolver); } void addObjectFile(object::OwningBinary O) override { @@ -157,8 +175,7 @@ public: std::vector> Objs; Objs.push_back(std::move(Obj)); auto H = - ObjectLayer.addObjectSet(std::move(Objs), - llvm::make_unique(*this)); + ObjectLayer.addObjectSet(std::move(Objs), &MemMgr, &Resolver); std::vector> Bufs; Bufs.push_back(std::move(Buf)); @@ -170,7 +187,11 @@ public: } uint64_t getSymbolAddress(StringRef Name) { - return getSymbolAddressWithoutMangling(Mangle(Name)); + return findSymbol(Name).getAddress(); + } + + RuntimeDyld::SymbolInfo findSymbol(StringRef Name) { + return findMangledSymbol(Mangle(Name)); } void finalizeObject() override { @@ -214,18 +235,19 @@ public: } private: - uint64_t getSymbolAddressWithoutMangling(StringRef Name) { - if (uint64_t Addr = LazyEmitLayer.findSymbol(Name, false).getAddress()) - return Addr; - if (uint64_t Addr = MM->getSymbolAddress(Name)) - return Addr; - if (uint64_t Addr = scanArchives(Name)) - return Addr; - return 0; + RuntimeDyld::SymbolInfo findMangledSymbol(StringRef Name) { + if (auto Sym = LazyEmitLayer.findSymbol(Name, false)) + return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags()); + if (auto Sym = ClientResolver->findSymbol(Name)) + return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags()); + if (auto Sym = scanArchives(Name)) + return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags()); + + return nullptr; } - uint64_t scanArchives(StringRef Name) { + JITSymbol scanArchives(StringRef Name) { for (object::OwningBinary &OB : Archives) { object::Archive *A = OB.getBinary(); // Look for our symbols in each Archive @@ -241,14 +263,13 @@ private: std::vector> ObjSet; ObjSet.push_back(std::unique_ptr( static_cast(ChildBin.release()))); - ObjectLayer.addObjectSet( - std::move(ObjSet), llvm::make_unique(*this)); - if (uint64_t Addr = ObjectLayer.findSymbol(Name, true).getAddress()) - return Addr; + ObjectLayer.addObjectSet(std::move(ObjSet), &MemMgr, &Resolver); + if (auto Sym = ObjectLayer.findSymbol(Name, true)) + return Sym; } } } - return 0; + return nullptr; } class NotifyObjectLoadedT { @@ -267,7 +288,7 @@ private: assert(Objects.size() == Infos.size() && "Incorrect number of Infos for Objects."); for (unsigned I = 0; I < Objects.size(); ++I) - M.MM->notifyObjectLoaded(&M, *Objects[I]); + M.MemMgr.notifyObjectLoaded(&M, *Objects[I]); }; private: @@ -299,7 +320,9 @@ private: typedef LazyEmittingLayer LazyEmitLayerT; std::unique_ptr TM; - std::unique_ptr MM; + MCJITReplacementMemMgr MemMgr; + LinkingResolver Resolver; + std::shared_ptr ClientResolver; Mangler Mang; NotifyObjectLoadedT NotifyObjectLoaded; diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index a0ed7cf8447..c8f35d1d3b6 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -151,10 +151,10 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { // Compute the memory size required to load all sections to be loaded // and pass this information to the memory manager - if (MemMgr->needsToReserveAllocationSpace()) { + if (MemMgr.needsToReserveAllocationSpace()) { uint64_t CodeSize = 0, DataSizeRO = 0, DataSizeRW = 0; computeTotalAllocSize(Obj, CodeSize, DataSizeRO, DataSizeRW); - MemMgr->reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW); + MemMgr.reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW); } // Used sections from the object file @@ -485,7 +485,7 @@ void RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj, // Skip common symbols already elsewhere. if (GlobalSymbolTable.count(Name) || - MemMgr->getSymbolAddressInLogicalDylib(Name)) { + Resolver.findSymbolInLogicalDylib(Name)) { DEBUG(dbgs() << "\tSkipping already emitted common symbol '" << Name << "'\n"); continue; @@ -502,8 +502,8 @@ void RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj, // Allocate memory for the section unsigned SectionID = Sections.size(); - uint8_t *Addr = MemMgr->allocateDataSection(CommonSize, sizeof(void *), - SectionID, StringRef(), false); + uint8_t *Addr = MemMgr.allocateDataSection(CommonSize, sizeof(void *), + SectionID, StringRef(), false); if (!Addr) report_fatal_error("Unable to allocate memory for common symbols!"); uint64_t Offset = 0; @@ -577,10 +577,10 @@ unsigned RuntimeDyldImpl::emitSection(const ObjectFile &Obj, if (IsRequired) { Check(Section.getContents(data)); Allocate = DataSize + PaddingSize + StubBufSize; - Addr = IsCode ? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID, - Name) - : MemMgr->allocateDataSection(Allocate, Alignment, SectionID, - Name, IsReadOnly); + Addr = IsCode ? MemMgr.allocateCodeSection(Allocate, Alignment, SectionID, + Name) + : MemMgr.allocateDataSection(Allocate, Alignment, SectionID, + Name, IsReadOnly); if (!Addr) report_fatal_error("Unable to allocate section memory!"); @@ -787,9 +787,9 @@ void RuntimeDyldImpl::resolveExternalSymbols() { uint64_t Addr = 0; RTDyldSymbolTable::const_iterator Loc = GlobalSymbolTable.find(Name); if (Loc == GlobalSymbolTable.end()) { - // This is an external symbol, try to get its address from - // MemoryManager. - Addr = MemMgr->getSymbolAddress(Name.data()); + // This is an external symbol, try to get its address from the symbol + // resolver. + Addr = Resolver.findSymbol(Name.data()).getAddress(); // The call to getSymbolAddress may have caused additional modules to // be loaded, which may have added new entries to the // ExternalSymbolRelocations map. Consquently, we need to update our @@ -835,7 +835,12 @@ uint64_t RuntimeDyld::LoadedObjectInfo::getSectionLoadAddress( return 0; } -RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) { +void RuntimeDyld::MemoryManager::anchor() {} +void RuntimeDyld::SymbolResolver::anchor() {} + +RuntimeDyld::RuntimeDyld(RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) + : MemMgr(MemMgr), Resolver(Resolver) { // FIXME: There's a potential issue lurking here if a single instance of // RuntimeDyld is used to load multiple objects. The current implementation // associates a single memory manager with a RuntimeDyld instance. Even @@ -843,7 +848,6 @@ RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) { // they share a single memory manager. This can become a problem when page // permissions are applied. Dyld = nullptr; - MM = mm; ProcessAllSections = false; Checker = nullptr; } @@ -851,27 +855,33 @@ RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) { RuntimeDyld::~RuntimeDyld() {} static std::unique_ptr -createRuntimeDyldCOFF(Triple::ArchType Arch, RTDyldMemoryManager *MM, +createRuntimeDyldCOFF(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MM, + RuntimeDyld::SymbolResolver &Resolver, bool ProcessAllSections, RuntimeDyldCheckerImpl *Checker) { - std::unique_ptr Dyld(RuntimeDyldCOFF::create(Arch, MM)); + std::unique_ptr Dyld = + RuntimeDyldCOFF::create(Arch, MM, Resolver); Dyld->setProcessAllSections(ProcessAllSections); Dyld->setRuntimeDyldChecker(Checker); return Dyld; } static std::unique_ptr -createRuntimeDyldELF(RTDyldMemoryManager *MM, bool ProcessAllSections, - RuntimeDyldCheckerImpl *Checker) { - std::unique_ptr Dyld(new RuntimeDyldELF(MM)); +createRuntimeDyldELF(RuntimeDyld::MemoryManager &MM, + RuntimeDyld::SymbolResolver &Resolver, + bool ProcessAllSections, RuntimeDyldCheckerImpl *Checker) { + std::unique_ptr Dyld(new RuntimeDyldELF(MM, Resolver)); Dyld->setProcessAllSections(ProcessAllSections); Dyld->setRuntimeDyldChecker(Checker); return Dyld; } static std::unique_ptr -createRuntimeDyldMachO(Triple::ArchType Arch, RTDyldMemoryManager *MM, - bool ProcessAllSections, RuntimeDyldCheckerImpl *Checker) { - std::unique_ptr Dyld(RuntimeDyldMachO::create(Arch, MM)); +createRuntimeDyldMachO(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MM, + RuntimeDyld::SymbolResolver &Resolver, + bool ProcessAllSections, + RuntimeDyldCheckerImpl *Checker) { + std::unique_ptr Dyld = + RuntimeDyldMachO::create(Arch, MM, Resolver); Dyld->setProcessAllSections(ProcessAllSections); Dyld->setRuntimeDyldChecker(Checker); return Dyld; @@ -881,14 +891,14 @@ std::unique_ptr RuntimeDyld::loadObject(const ObjectFile &Obj) { if (!Dyld) { if (Obj.isELF()) - Dyld = createRuntimeDyldELF(MM, ProcessAllSections, Checker); + Dyld = createRuntimeDyldELF(MemMgr, Resolver, ProcessAllSections, Checker); else if (Obj.isMachO()) Dyld = createRuntimeDyldMachO( - static_cast(Obj.getArch()), MM, + static_cast(Obj.getArch()), MemMgr, Resolver, ProcessAllSections, Checker); else if (Obj.isCOFF()) Dyld = createRuntimeDyldCOFF( - static_cast(Obj.getArch()), MM, + static_cast(Obj.getArch()), MemMgr, Resolver, ProcessAllSections, Checker); else report_fatal_error("Incompatible object format!"); diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp index 56bcb8ee674..8055d550006 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp @@ -40,13 +40,15 @@ public: namespace llvm { std::unique_ptr -llvm::RuntimeDyldCOFF::create(Triple::ArchType Arch, RTDyldMemoryManager *MM) { +llvm::RuntimeDyldCOFF::create(Triple::ArchType Arch, + RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) { switch (Arch) { default: llvm_unreachable("Unsupported target for RuntimeDyldCOFF."); break; case Triple::x86_64: - return make_unique(MM); + return make_unique(MemMgr, Resolver); } } diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h index 681a3e52d27..32b8fa269be 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.h @@ -31,11 +31,15 @@ public: std::unique_ptr loadObject(const object::ObjectFile &Obj) override; bool isCompatibleFile(const object::ObjectFile &Obj) const override; - static std::unique_ptr create(Triple::ArchType Arch, - RTDyldMemoryManager *MM); + + static std::unique_ptr + create(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver); protected: - RuntimeDyldCOFF(RTDyldMemoryManager *MM) : RuntimeDyldImpl(MM) {} + RuntimeDyldCOFF(RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldImpl(MemMgr, Resolver) {} uint64_t getSymbolOffset(const SymbolRef &Sym); }; diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp index c99140897f6..957571b092d 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp @@ -738,7 +738,7 @@ uint64_t RuntimeDyldCheckerImpl::getSymbolLocalAddr(StringRef Symbol) const { uint64_t RuntimeDyldCheckerImpl::getSymbolRemoteAddr(StringRef Symbol) const { if (auto InternalSymbol = getRTDyld().getSymbol(Symbol)) return InternalSymbol.getAddress(); - return getRTDyld().MemMgr->getSymbolAddress(Symbol); + return getRTDyld().Resolver.findSymbol(Symbol).getAddress(); } uint64_t RuntimeDyldCheckerImpl::readMemoryAtAddr(uint64_t SrcAddr, diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index 6278170cd88..6381c0495c3 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -183,32 +183,30 @@ LoadedELFObjectInfo::getObjectForDebug(const ObjectFile &Obj) const { namespace llvm { -RuntimeDyldELF::RuntimeDyldELF(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {} +RuntimeDyldELF::RuntimeDyldELF(RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldImpl(MemMgr, Resolver) {} RuntimeDyldELF::~RuntimeDyldELF() {} void RuntimeDyldELF::registerEHFrames() { - if (!MemMgr) - return; for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) { SID EHFrameSID = UnregisteredEHFrameSections[i]; uint8_t *EHFrameAddr = Sections[EHFrameSID].Address; uint64_t EHFrameLoadAddr = Sections[EHFrameSID].LoadAddress; size_t EHFrameSize = Sections[EHFrameSID].Size; - MemMgr->registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize); + MemMgr.registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize); RegisteredEHFrameSections.push_back(EHFrameSID); } UnregisteredEHFrameSections.clear(); } void RuntimeDyldELF::deregisterEHFrames() { - if (!MemMgr) - return; for (int i = 0, e = RegisteredEHFrameSections.size(); i != e; ++i) { SID EHFrameSID = RegisteredEHFrameSections[i]; uint8_t *EHFrameAddr = Sections[EHFrameSID].Address; uint64_t EHFrameLoadAddr = Sections[EHFrameSID].LoadAddress; size_t EHFrameSize = Sections[EHFrameSID].Size; - MemMgr->deregisterEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize); + MemMgr.deregisterEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize); } RegisteredEHFrameSections.clear(); } @@ -1457,26 +1455,21 @@ uint64_t RuntimeDyldELF::findGOTEntry(uint64_t LoadAddress, uint64_t Offset) { void RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj, ObjSectionToIDMap &SectionMap) { // If necessary, allocate the global offset table - if (MemMgr) { - // Allocate the GOT if necessary - size_t numGOTEntries = GOTEntries.size(); - if (numGOTEntries != 0) { - // Allocate memory for the section - unsigned SectionID = Sections.size(); - size_t TotalSize = numGOTEntries * getGOTEntrySize(); - uint8_t *Addr = MemMgr->allocateDataSection(TotalSize, getGOTEntrySize(), - SectionID, ".got", false); - if (!Addr) - report_fatal_error("Unable to allocate memory for GOT!"); - - GOTs.push_back(std::make_pair(SectionID, GOTEntries)); - Sections.push_back(SectionEntry(".got", Addr, TotalSize, 0)); - // For now, initialize all GOT entries to zero. We'll fill them in as - // needed when GOT-based relocations are applied. - memset(Addr, 0, TotalSize); - } - } else { - report_fatal_error("Unable to allocate memory for GOT!"); + size_t numGOTEntries = GOTEntries.size(); + if (numGOTEntries != 0) { + // Allocate memory for the section + unsigned SectionID = Sections.size(); + size_t TotalSize = numGOTEntries * getGOTEntrySize(); + uint8_t *Addr = MemMgr.allocateDataSection(TotalSize, getGOTEntrySize(), + SectionID, ".got", false); + if (!Addr) + report_fatal_error("Unable to allocate memory for GOT!"); + + GOTs.push_back(std::make_pair(SectionID, GOTEntries)); + Sections.push_back(SectionEntry(".got", Addr, TotalSize, 0)); + // For now, initialize all GOT entries to zero. We'll fill them in as + // needed when GOT-based relocations are applied. + memset(Addr, 0, TotalSize); } // Look for and record the EH frame section. diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h index 71260d02f95..a15e38141da 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h @@ -98,7 +98,8 @@ class RuntimeDyldELF : public RuntimeDyldImpl { SmallVector RegisteredEHFrameSections; public: - RuntimeDyldELF(RTDyldMemoryManager *mm); + RuntimeDyldELF(RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver); virtual ~RuntimeDyldELF(); std::unique_ptr diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index 05060dd2a5c..e79e2edb317 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -18,6 +18,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Triple.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/ExecutionEngine/RuntimeDyldChecker.h" #include "llvm/Object/ObjectFile.h" @@ -188,7 +189,10 @@ class RuntimeDyldImpl { friend class RuntimeDyldCheckerImpl; protected: // The MemoryManager to load objects into. - RTDyldMemoryManager *MemMgr; + RuntimeDyld::MemoryManager &MemMgr; + + // The symbol resolver to use for external symbols. + RuntimeDyld::SymbolResolver &Resolver; // Attached RuntimeDyldChecker instance. Null if no instance attached. RuntimeDyldCheckerImpl *Checker; @@ -374,8 +378,10 @@ protected: std::pair loadObjectImpl(const object::ObjectFile &Obj); public: - RuntimeDyldImpl(RTDyldMemoryManager *mm) - : MemMgr(mm), Checker(nullptr), ProcessAllSections(false), HasError(false) { + RuntimeDyldImpl(RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) + : MemMgr(MemMgr), Resolver(Resolver), Checker(nullptr), + ProcessAllSections(false), HasError(false) { } virtual ~RuntimeDyldImpl(); diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp index 2d3966270fc..54932547453 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp @@ -247,8 +247,6 @@ static int64_t computeDelta(SectionEntry *A, SectionEntry *B) { template void RuntimeDyldMachOCRTPBase::registerEHFrames() { - if (!MemMgr) - return; for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) { EHFrameRelatedSections &SectionInfo = UnregisteredEHFrameSections[i]; if (SectionInfo.EHFrameSID == RTDYLD_INVALID_SECTION_ID || @@ -271,22 +269,28 @@ void RuntimeDyldMachOCRTPBase::registerEHFrames() { P = processFDE(P, DeltaForText, DeltaForEH); } while (P != End); - MemMgr->registerEHFrames(EHFrame->Address, EHFrame->LoadAddress, - EHFrame->Size); + MemMgr.registerEHFrames(EHFrame->Address, EHFrame->LoadAddress, + EHFrame->Size); } UnregisteredEHFrameSections.clear(); } std::unique_ptr -RuntimeDyldMachO::create(Triple::ArchType Arch, RTDyldMemoryManager *MM) { +RuntimeDyldMachO::create(Triple::ArchType Arch, + RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) { switch (Arch) { default: llvm_unreachable("Unsupported target for RuntimeDyldMachO."); break; - case Triple::arm: return make_unique(MM); - case Triple::aarch64: return make_unique(MM); - case Triple::x86: return make_unique(MM); - case Triple::x86_64: return make_unique(MM); + case Triple::arm: + return make_unique(MemMgr, Resolver); + case Triple::aarch64: + return make_unique(MemMgr, Resolver); + case Triple::x86: + return make_unique(MemMgr, Resolver); + case Triple::x86_64: + return make_unique(MemMgr, Resolver); } } diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h index f8bfc03b6d2..45a94ba928f 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h @@ -49,7 +49,9 @@ protected: // EH frame sections with the memory manager. SmallVector UnregisteredEHFrameSections; - RuntimeDyldMachO(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {} + RuntimeDyldMachO(RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldImpl(MemMgr, Resolver) {} /// This convenience method uses memcpy to extract a contiguous addend (the /// addend size and offset are taken from the corresponding fields of the RE). @@ -114,8 +116,10 @@ protected: public: /// Create a RuntimeDyldMachO instance for the given target architecture. - static std::unique_ptr create(Triple::ArchType Arch, - RTDyldMemoryManager *mm); + static std::unique_ptr + create(Triple::ArchType Arch, + RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver); std::unique_ptr loadObject(const object::ObjectFile &O) override; @@ -142,7 +146,9 @@ private: int64_t DeltaForEH); public: - RuntimeDyldMachOCRTPBase(RTDyldMemoryManager *mm) : RuntimeDyldMachO(mm) {} + RuntimeDyldMachOCRTPBase(RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldMachO(MemMgr, Resolver) {} void finalizeLoad(const ObjectFile &Obj, ObjSectionToIDMap &SectionMap) override; diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h index ce2f4a2ae46..cd534a12549 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h @@ -32,7 +32,9 @@ private: SmallVector RegisteredEHFrameSections; public: - RuntimeDyldCOFFX86_64(RTDyldMemoryManager *MM) : RuntimeDyldCOFF(MM) {} + RuntimeDyldCOFFX86_64(RuntimeDyld::MemoryManager &MM, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldCOFF(MM, Resolver) {} unsigned getMaxStubSize() override { return 6; // 2-byte jmp instruction + 32-bit relative address @@ -177,13 +179,11 @@ public: unsigned getStubAlignment() override { return 1; } void registerEHFrames() override { - if (!MemMgr) - return; for (auto const &EHFrameSID : UnregisteredEHFrameSections) { uint8_t *EHFrameAddr = Sections[EHFrameSID].Address; uint64_t EHFrameLoadAddr = Sections[EHFrameSID].LoadAddress; size_t EHFrameSize = Sections[EHFrameSID].Size; - MemMgr->registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize); + MemMgr.registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize); RegisteredEHFrameSections.push_back(EHFrameSID); } UnregisteredEHFrameSections.clear(); diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h index 196fa62a0a0..99fd6e333b4 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h @@ -23,8 +23,9 @@ public: typedef uint64_t TargetPtrT; - RuntimeDyldMachOAArch64(RTDyldMemoryManager *MM) - : RuntimeDyldMachOCRTPBase(MM) {} + RuntimeDyldMachOAArch64(RuntimeDyld::MemoryManager &MM, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldMachOCRTPBase(MM, Resolver) {} unsigned getMaxStubSize() override { return 8; } diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h index 09e430e2261..09e51f27da4 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h @@ -25,7 +25,9 @@ public: typedef uint32_t TargetPtrT; - RuntimeDyldMachOARM(RTDyldMemoryManager *MM) : RuntimeDyldMachOCRTPBase(MM) {} + RuntimeDyldMachOARM(RuntimeDyld::MemoryManager &MM, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldMachOCRTPBase(MM, Resolver) {} unsigned getMaxStubSize() override { return 8; } diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h index 67d7027c185..053f90ce05a 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h @@ -22,8 +22,9 @@ public: typedef uint32_t TargetPtrT; - RuntimeDyldMachOI386(RTDyldMemoryManager *MM) - : RuntimeDyldMachOCRTPBase(MM) {} + RuntimeDyldMachOI386(RuntimeDyld::MemoryManager &MM, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldMachOCRTPBase(MM, Resolver) {} unsigned getMaxStubSize() override { return 0; } diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h index 0734017e220..4b3b01ba3c9 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h @@ -22,8 +22,9 @@ public: typedef uint64_t TargetPtrT; - RuntimeDyldMachOX86_64(RTDyldMemoryManager *MM) - : RuntimeDyldMachOCRTPBase(MM) {} + RuntimeDyldMachOX86_64(RuntimeDyld::MemoryManager &MM, + RuntimeDyld::SymbolResolver &Resolver) + : RuntimeDyldMachOCRTPBase(MM, Resolver) {} unsigned getMaxStubSize() override { return 8; } diff --git a/tools/lli/OrcLazyJIT.cpp b/tools/lli/OrcLazyJIT.cpp index 4a8d3b9e3ed..d17672c1445 100644 --- a/tools/lli/OrcLazyJIT.cpp +++ b/tools/lli/OrcLazyJIT.cpp @@ -23,7 +23,7 @@ OrcLazyJIT::createCallbackMgr(Triple T, LLVMContext &Context) { case Triple::x86_64: { typedef orc::JITCompileCallbackManager CCMgrT; - return make_unique(CompileLayer, Context, 0, 64); + return make_unique(CompileLayer, CCMgrMemMgr, Context, 0, 64); } } } diff --git a/tools/lli/OrcLazyJIT.h b/tools/lli/OrcLazyJIT.h index 76e1ac63bd2..fc1d0827cbc 100644 --- a/tools/lli/OrcLazyJIT.h +++ b/tools/lli/OrcLazyJIT.h @@ -39,7 +39,7 @@ public: OrcLazyJIT(std::unique_ptr TM, LLVMContext &Context) : Error(false), TM(std::move(TM)), Mang(this->TM->getDataLayout()), - ObjectLayer([](){ return llvm::make_unique(); }), + ObjectLayer(), CompileLayer(ObjectLayer, orc::SimpleCompiler(*this->TM)), LazyEmitLayer(CompileLayer), CCMgr(createCallbackMgr(Triple(this->TM->getTargetTriple()), Context)), @@ -82,6 +82,7 @@ private: bool Error; std::unique_ptr TM; Mangler Mang; + SectionMemoryManager CCMgrMemMgr; ObjLayerT ObjectLayer; CompileLayerT CompileLayer; diff --git a/tools/llvm-rtdyld/llvm-rtdyld.cpp b/tools/llvm-rtdyld/llvm-rtdyld.cpp index 946201521ba..c2c3498c9b8 100644 --- a/tools/llvm-rtdyld/llvm-rtdyld.cpp +++ b/tools/llvm-rtdyld/llvm-rtdyld.cpp @@ -13,6 +13,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/DebugInfo/DWARF/DIContext.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/ExecutionEngine/RuntimeDyldChecker.h" #include "llvm/MC/MCAsmInfo.h" @@ -196,7 +197,7 @@ static int printLineInfoForInput() { for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) { // Instantiate a dynamic linker. TrivialMemoryManager MemMgr; - RuntimeDyld Dyld(&MemMgr); + RuntimeDyld Dyld(MemMgr, MemMgr); // Load the input memory buffer. @@ -264,7 +265,7 @@ static int executeInput() { // Instantiate a dynamic linker. TrivialMemoryManager MemMgr; - RuntimeDyld Dyld(&MemMgr); + RuntimeDyld Dyld(MemMgr, MemMgr); // If we don't have any input files, read from stdin. if (!InputFileList.size()) @@ -513,7 +514,7 @@ static int linkAndVerify() { // Instantiate a dynamic linker. TrivialMemoryManager MemMgr; - RuntimeDyld Dyld(&MemMgr); + RuntimeDyld Dyld(MemMgr, MemMgr); Dyld.setProcessAllSections(true); RuntimeDyldChecker Checker(Dyld, Disassembler.get(), InstPrinter.get(), llvm::dbgs()); diff --git a/unittests/ExecutionEngine/Orc/LazyEmittingLayerTest.cpp b/unittests/ExecutionEngine/Orc/LazyEmittingLayerTest.cpp index b0ff1276c5c..a495766db91 100644 --- a/unittests/ExecutionEngine/Orc/LazyEmittingLayerTest.cpp +++ b/unittests/ExecutionEngine/Orc/LazyEmittingLayerTest.cpp @@ -14,9 +14,11 @@ namespace { struct MockBaseLayer { typedef int ModuleSetHandleT; - ModuleSetHandleT addModuleSet(std::list>, - std::unique_ptr x) { - EXPECT_FALSE(x); + ModuleSetHandleT addModuleSet( + std::list>, + std::unique_ptr MemMgr, + std::unique_ptr Resolver) { + EXPECT_FALSE(MemMgr); return 42; } }; @@ -24,7 +26,7 @@ struct MockBaseLayer { TEST(LazyEmittingLayerTest, Empty) { MockBaseLayer M; llvm::orc::LazyEmittingLayer L(M); - L.addModuleSet(std::list>(), nullptr); + L.addModuleSet(std::list>(), nullptr, nullptr); } } -- 2.34.1