diff options
Diffstat (limited to 'include/llvm/ExecutionEngine/Orc')
-rw-r--r-- | include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h | 96 | ||||
-rw-r--r-- | include/llvm/ExecutionEngine/Orc/ExecutionUtils.h | 182 | ||||
-rw-r--r-- | include/llvm/ExecutionEngine/Orc/IRCompileLayer.h | 14 | ||||
-rw-r--r-- | include/llvm/ExecutionEngine/Orc/IRTransformLayer.h | 101 | ||||
-rw-r--r-- | include/llvm/ExecutionEngine/Orc/IndirectionUtils.h | 54 | ||||
-rw-r--r-- | include/llvm/ExecutionEngine/Orc/JITSymbol.h | 2 | ||||
-rw-r--r-- | include/llvm/ExecutionEngine/Orc/LambdaResolver.h | 62 | ||||
-rw-r--r-- | include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h | 45 | ||||
-rw-r--r-- | include/llvm/ExecutionEngine/Orc/LookasideRTDyldMM.h | 92 | ||||
-rw-r--r-- | include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h | 105 |
10 files changed, 540 insertions, 213 deletions
diff --git a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h index 77b0c48..30f7f1c 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 <list> @@ -36,7 +36,7 @@ namespace orc { /// compiled only when it is first called. template <typename BaseLayerT, typename CompileCallbackMgrT> class CompileOnDemandLayer { -public: +private: /// @brief Lookup helper that provides compatibility with the classic /// static-compilation symbol resolution process. /// @@ -64,6 +64,8 @@ public: /// @brief Construct a scoped lookup. CODScopedLookup(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {} + virtual ~CODScopedLookup() {} + /// @brief Start a new context for a single logical module. LMHandle createLogicalModule() { Handles.push_back(SiblingHandlesList()); @@ -92,6 +94,10 @@ public: return nullptr; } + /// @brief Find an external symbol (via the user supplied SymbolResolver). + virtual RuntimeDyld::SymbolInfo + externalLookup(const std::string &Name) const = 0; + private: JITSymbol findSymbolIn(LMHandle LMH, const std::string &Name) { @@ -105,7 +111,29 @@ public: PseudoDylibModuleSetHandlesList Handles; }; -private: + template <typename ResolverPtrT> + class CODScopedLookupImpl : public CODScopedLookup { + public: + CODScopedLookupImpl(BaseLayerT &BaseLayer, ResolverPtrT Resolver) + : CODScopedLookup(BaseLayer), Resolver(std::move(Resolver)) {} + + RuntimeDyld::SymbolInfo + externalLookup(const std::string &Name) const override { + return Resolver->findSymbol(Name); + } + + private: + ResolverPtrT Resolver; + }; + + template <typename ResolverPtrT> + static std::shared_ptr<CODScopedLookup> + createCODScopedLookup(BaseLayerT &BaseLayer, + ResolverPtrT Resolver) { + typedef CODScopedLookupImpl<ResolverPtrT> Impl; + return std::make_shared<Impl>(BaseLayer, std::move(Resolver)); + } + typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT; typedef std::vector<BaseLayerModuleSetHandleT> BaseLayerModuleSetHandleListT; @@ -138,36 +166,31 @@ public: /// @brief Handle to a set of loaded modules. typedef typename ModuleSetInfoListT::iterator ModuleSetHandleT; - // @brief Fallback lookup functor. - typedef std::function<uint64_t(const std::string &)> LookupFtor; - /// @brief Construct a compile-on-demand layer instance. CompileOnDemandLayer(BaseLayerT &BaseLayer, CompileCallbackMgrT &CallbackMgr) : BaseLayer(BaseLayer), CompileCallbackMgr(CallbackMgr) {} /// @brief Add a module to the compile-on-demand layer. - template <typename ModuleSetT> + template <typename ModuleSetT, typename MemoryManagerPtrT, + typename SymbolResolverPtrT> ModuleSetHandleT addModuleSet(ModuleSetT Ms, - LookupFtor FallbackLookup = nullptr) { + MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) { - // 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(); - }; + assert(MemMgr == nullptr && + "User supplied memory managers not supported with COD yet."); // Create a lookup context and ModuleSetInfo for this module set. // For the purposes of symbol resolution the set Ms will be treated as if // the modules it contained had been linked together as a dylib. - auto DylibLookup = std::make_shared<CODScopedLookup>(BaseLayer); + auto DylibLookup = createCODScopedLookup(BaseLayer, std::move(Resolver)); ModuleSetHandleT H = ModuleSetInfos.insert(ModuleSetInfos.end(), ModuleSetInfo(DylibLookup)); ModuleSetInfo &MSI = ModuleSetInfos.back(); // Process each of the modules in this module set. for (auto &M : Ms) - partitionAndAdd(*M, MSI, FallbackLookup); + partitionAndAdd(*M, MSI); return H; } @@ -203,8 +226,7 @@ public: private: - void partitionAndAdd(Module &M, ModuleSetInfo &MSI, - LookupFtor FallbackLookup) { + void partitionAndAdd(Module &M, ModuleSetInfo &MSI) { const char *AddrSuffix = "$orc_addr"; const char *BodySuffix = "$orc_body"; @@ -224,8 +246,7 @@ private: auto FunctionModules = std::move(PartitionedModule.Functions); // Emit the commons stright away. - auto CommonHandle = addModule(std::move(CommonsModule), MSI, LogicalModule, - FallbackLookup); + auto CommonHandle = addModule(std::move(CommonsModule), MSI, LogicalModule); BaseLayer.emitAndFinalize(CommonHandle); // Map of definition names to callback-info data structures. We'll use @@ -255,10 +276,12 @@ 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, - CallbackInfo.getAddress()); + createImplPointer(*Proto->getType(), *Proto->getParent(), + Name + AddrSuffix, + createIRTypedAddress(*Proto->getFunctionType(), + CallbackInfo.getAddress())); makeStub(*Proto, *FunctionBodyPointer); F.setName(Name + BodySuffix); @@ -268,7 +291,7 @@ private: NewStubInfos.push_back(StubInfos.insert(StubInfos.begin(), KV)); } - auto H = addModule(std::move(SubM), MSI, LogicalModule, FallbackLookup); + auto H = addModule(std::move(SubM), MSI, LogicalModule); // Set the compile actions for this module: for (auto &KVPair : NewStubInfos) { @@ -286,7 +309,7 @@ private: // Ok - we've processed all the partitioned modules. Now add the // stubs/globals module and set the update actions. auto StubsH = - addModule(std::move(StubsModule), MSI, LogicalModule, FallbackLookup); + addModule(std::move(StubsModule), MSI, LogicalModule); for (auto &KVPair : StubInfos) { std::string AddrName = Mangle(KVPair.first + AddrSuffix, @@ -304,8 +327,7 @@ private: BaseLayerModuleSetHandleT addModule( std::unique_ptr<Module> M, ModuleSetInfo &MSI, - typename CODScopedLookup::LMHandle LogicalModule, - LookupFtor FallbackLookup) { + typename CODScopedLookup::LMHandle LogicalModule) { // Add this module to the JIT with a memory manager that uses the // DylibLookup to resolve symbols. @@ -313,19 +335,25 @@ private: MSet.push_back(std::move(M)); auto DylibLookup = MSI.Lookup; - auto MM = - createLookasideRTDyldMM<SectionMemoryManager>( + auto Resolver = + createLambdaResolver( [=](const std::string &Name) { if (auto Symbol = DylibLookup->findSymbol(LogicalModule, Name)) - return Symbol.getAddress(); - return FallbackLookup(Name); + return RuntimeDyld::SymbolInfo(Symbol.getAddress(), + Symbol.getFlags()); + return DylibLookup->externalLookup(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<SectionMemoryManager>(), + 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/ExecutionUtils.h b/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h new file mode 100644 index 0000000..c10508c --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h @@ -0,0 +1,182 @@ +//===-- ExecutionUtils.h - Utilities for executing code in Orc --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains utilities for executing code in Orc. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H +#define LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H + +#include "JITSymbol.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" +#include <vector> + +namespace llvm { + +class ConstantArray; +class GlobalVariable; +class Function; +class Module; +class Value; + +namespace orc { + +/// @brief This iterator provides a convenient way to iterate over the elements +/// of an llvm.global_ctors/llvm.global_dtors instance. +/// +/// The easiest way to get hold of instances of this class is to use the +/// getConstructors/getDestructors functions. +class CtorDtorIterator { +public: + + /// @brief Accessor for an element of the global_ctors/global_dtors array. + /// + /// This class provides a read-only view of the element with any casts on + /// the function stripped away. + struct Element { + Element(unsigned Priority, const Function *Func, const Value *Data) + : Priority(Priority), Func(Func), Data(Data) {} + + unsigned Priority; + const Function *Func; + const Value *Data; + }; + + /// @brief Construct an iterator instance. If End is true then this iterator + /// acts as the end of the range, otherwise it is the beginning. + CtorDtorIterator(const GlobalVariable *GV, bool End); + + /// @brief Test iterators for equality. + bool operator==(const CtorDtorIterator &Other) const; + + /// @brief Test iterators for inequality. + bool operator!=(const CtorDtorIterator &Other) const; + + /// @brief Pre-increment iterator. + CtorDtorIterator& operator++(); + + /// @brief Post-increment iterator. + CtorDtorIterator operator++(int); + + /// @brief Dereference iterator. The resulting value provides a read-only view + /// of this element of the global_ctors/global_dtors list. + Element operator*() const; + +private: + const ConstantArray *InitList; + unsigned I; +}; + +/// @brief Create an iterator range over the entries of the llvm.global_ctors +/// array. +iterator_range<CtorDtorIterator> getConstructors(const Module &M); + +/// @brief Create an iterator range over the entries of the llvm.global_ctors +/// array. +iterator_range<CtorDtorIterator> getDestructors(const Module &M); + +/// @brief Convenience class for recording constructor/destructor names for +/// later execution. +template <typename JITLayerT> +class CtorDtorRunner { +public: + + /// @brief Construct a CtorDtorRunner for the given range using the given + /// name mangling function. + CtorDtorRunner(std::vector<std::string> CtorDtorNames, + typename JITLayerT::ModuleSetHandleT H) + : CtorDtorNames(std::move(CtorDtorNames)), H(H) {} + + /// @brief Run the recorded constructors/destructors through the given JIT + /// layer. + bool runViaLayer(JITLayerT &JITLayer) const { + typedef void (*CtorDtorTy)(); + + bool Error = false; + for (const auto &CtorDtorName : CtorDtorNames) + if (auto CtorDtorSym = JITLayer.findSymbolIn(H, CtorDtorName, false)) { + CtorDtorTy CtorDtor = + reinterpret_cast<CtorDtorTy>( + static_cast<uintptr_t>(CtorDtorSym.getAddress())); + CtorDtor(); + } else + Error = true; + return !Error; + } + +private: + std::vector<std::string> CtorDtorNames; + typename JITLayerT::ModuleSetHandleT H; +}; + +/// @brief Support class for static dtor execution. For hosted (in-process) JITs +/// only! +/// +/// If a __cxa_atexit function isn't found C++ programs that use static +/// destructors will fail to link. However, we don't want to use the host +/// process's __cxa_atexit, because it will schedule JIT'd destructors to run +/// after the JIT has been torn down, which is no good. This class makes it easy +/// to override __cxa_atexit (and the related __dso_handle). +/// +/// To use, clients should manually call searchOverrides from their symbol +/// resolver. This should generally be done after attempting symbol resolution +/// inside the JIT, but before searching the host process's symbol table. When +/// the client determines that destructors should be run (generally at JIT +/// teardown or after a return from main), the runDestructors method should be +/// called. +class LocalCXXRuntimeOverrides { +public: + + /// Create a runtime-overrides class. + template <typename MangleFtorT> + LocalCXXRuntimeOverrides(const MangleFtorT &Mangle) { + addOverride(Mangle("__dso_handle"), toTargetAddress(&DSOHandleOverride)); + addOverride(Mangle("__cxa_atexit"), toTargetAddress(&CXAAtExitOverride)); + } + + /// Search overrided symbols. + RuntimeDyld::SymbolInfo searchOverrides(const std::string &Name) { + auto I = CXXRuntimeOverrides.find(Name); + if (I != CXXRuntimeOverrides.end()) + return RuntimeDyld::SymbolInfo(I->second, JITSymbolFlags::Exported); + return nullptr; + } + + /// Run any destructors recorded by the overriden __cxa_atexit function + /// (CXAAtExitOverride). + void runDestructors(); + +private: + + template <typename PtrTy> + TargetAddress toTargetAddress(PtrTy* P) { + return static_cast<TargetAddress>(reinterpret_cast<uintptr_t>(P)); + } + + void addOverride(const std::string &Name, TargetAddress Addr) { + CXXRuntimeOverrides.insert(std::make_pair(Name, Addr)); + } + + StringMap<TargetAddress> CXXRuntimeOverrides; + + typedef void (*DestructorPtr)(void*); + typedef std::pair<DestructorPtr, void*> CXXDestructorDataPair; + typedef std::vector<CXXDestructorDataPair> CXXDestructorDataPairList; + CXXDestructorDataPairList DSOHandleOverride; + static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg, + void *DSOHandle); +}; + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H diff --git a/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h b/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h index 6a47622..6379022 100644 --- a/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h +++ b/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h @@ -52,14 +52,16 @@ public: /// @brief Set an ObjectCache to query before compiling. void setObjectCache(ObjectCache *NewCache) { ObjCache = NewCache; } - /// @brief Compile each module in the given module set, then then add the - /// resulting set of objects to the base layer, along with the memory - // manager MM. + /// @brief Compile each module in the given module set, then add the resulting + /// set of objects to the base layer along with the memory manager and + /// symbol resolver. /// /// @return A handle for the added modules. - template <typename ModuleSetT> + template <typename ModuleSetT, typename MemoryManagerPtrT, + typename SymbolResolverPtrT> ModuleSetHandleT addModuleSet(ModuleSetT Ms, - std::unique_ptr<RTDyldMemoryManager> 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/IRTransformLayer.h b/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h new file mode 100644 index 0000000..4dabb9a --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h @@ -0,0 +1,101 @@ +//===----- IRTransformLayer.h - Run all IR through a functor ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Run all IR passed in through a user supplied functor. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H +#define LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H + +#include "JITSymbol.h" + +namespace llvm { +namespace orc { + +/// @brief IR mutating layer. +/// +/// This layer accepts sets of LLVM IR Modules (via addModuleSet). It +/// immediately applies the user supplied functor to each module, then adds +/// the set of transformed modules to the layer below. +template <typename BaseLayerT, typename TransformFtor> +class IRTransformLayer { +public: + /// @brief Handle to a set of added modules. + typedef typename BaseLayerT::ModuleSetHandleT ModuleSetHandleT; + + /// @brief Construct an IRTransformLayer with the given BaseLayer + IRTransformLayer(BaseLayerT &BaseLayer, + TransformFtor Transform = TransformFtor()) + : BaseLayer(BaseLayer), Transform(std::move(Transform)) {} + + /// @brief Apply the transform functor to each module in the module set, then + /// add the resulting set of modules to the base layer, along with the + /// memory manager and symbol resolver. + /// + /// @return A handle for the added modules. + template <typename ModuleSetT, typename MemoryManagerPtrT, + typename SymbolResolverPtrT> + ModuleSetHandleT addModuleSet(ModuleSetT Ms, + MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) { + + for (auto I = Ms.begin(), E = Ms.end(); I != E; ++I) + *I = Transform(std::move(*I)); + + return BaseLayer.addModuleSet(std::move(Ms), std::move(MemMgr), + std::move(Resolver)); + } + + /// @brief Remove the module set associated with the handle H. + void removeModuleSet(ModuleSetHandleT H) { BaseLayer.removeModuleSet(H); } + + /// @brief Search for the given named symbol. + /// @param Name The name of the symbol to search for. + /// @param ExportedSymbolsOnly If true, search only for exported symbols. + /// @return A handle for the given named symbol, if it exists. + JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { + return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); + } + + /// @brief Get the address of the given symbol in the context of the set of + /// modules represented by the handle H. This call is forwarded to the + /// base layer's implementation. + /// @param H The handle for the module set to search in. + /// @param Name The name of the symbol to search for. + /// @param ExportedSymbolsOnly If true, search only for exported symbols. + /// @return A handle for the given named symbol, if it is found in the + /// given module set. + JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name, + bool ExportedSymbolsOnly) { + return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly); + } + + /// @brief Immediately emit and finalize the module set represented by the + /// given handle. + /// @param H Handle for module set to emit/finalize. + void emitAndFinalize(ModuleSetHandleT H) { + BaseLayer.emitAndFinalize(H); + } + + /// @brief Access the transform functor directly. + TransformFtor& getTransform() { return Transform; } + + /// @brief Access the mumate functor directly. + const TransformFtor& getTransform() const { return Transform; } + +private: + BaseLayerT &BaseLayer; + TransformFtor Transform; +}; + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H diff --git a/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h index 8ce1d4d..7b4f611 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" @@ -37,11 +38,11 @@ public: /// the compile and update actions for the callback. class CompileCallbackInfo { public: - CompileCallbackInfo(Constant *Addr, CompileFtor &Compile, + CompileCallbackInfo(TargetAddress Addr, CompileFtor &Compile, UpdateFtor &Update) : Addr(Addr), Compile(Compile), Update(Update) {} - Constant* getAddress() const { return Addr; } + TargetAddress getAddress() const { return Addr; } void setCompileAction(CompileFtor Compile) { this->Compile = std::move(Compile); } @@ -49,7 +50,7 @@ public: this->Update = std::move(Update); } private: - Constant *Addr; + TargetAddress Addr; CompileFtor &Compile; UpdateFtor &Update; }; @@ -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,27 +126,23 @@ 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]; - Constant *AddrIntVal = - ConstantInt::get(Type::getInt64Ty(FT.getContext()), TrampolineAddr); - Constant *AddrPtrVal = - ConstantExpr::getCast(Instruction::IntToPtr, AddrIntVal, - PointerType::get(&FT, 0)); - return CompileCallbackInfo(AddrPtrVal, CallbackHandler.Compile, + return CompileCallbackInfo(TrampolineAddr, CallbackHandler.Compile, CallbackHandler.Update); } @@ -162,7 +159,9 @@ private: std::unique_ptr<Module> 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<RuntimeDyld::SymbolResolver*>( + nullptr)); JIT.emitAndFinalize(H); auto ResolverBlockSymbol = JIT.findSymbolIn(H, TargetT::ResolverBlockName, false); @@ -187,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<RuntimeDyld::SymbolResolver*>( + nullptr)); JIT.emitAndFinalize(H); for (unsigned I = 0; I < this->NumTrampolinesPerBlock; ++I) { std::string Name = GetLabelName(I); @@ -198,10 +199,11 @@ private: } JITLayerT &JIT; + RuntimeDyld::MemoryManager &MemMgr; TargetAddress ResolverBlockAddr; }; -/// @brief Get an update functor for updating the value of a named function +/// @brief Get an update functor that updates the value of a named function /// pointer. template <typename JITLayerT> JITCompileCallbackManagerBase::UpdateFtor @@ -217,13 +219,26 @@ getLocalFPUpdater(JITLayerT &JIT, typename JITLayerT::ModuleSetHandleT H, }; } -GlobalVariable* createImplPointer(Function &F, const Twine &Name, - Constant *Initializer); +/// @brief Build a function pointer of FunctionType with the given constant +/// address. +/// +/// Usage example: Turn a trampoline address into a function pointer constant +/// for use in a stub. +Constant* createIRTypedAddress(FunctionType &FT, TargetAddress Addr); +/// @brief Create a function pointer with the given type, name, and initializer +/// in the given Module. +GlobalVariable* createImplPointer(PointerType &PT, Module &M, + const Twine &Name, Constant *Initializer); + +/// @brief Turn a function declaration into a stub function that makes an +/// indirect call using the given function pointer. void makeStub(Function &F, GlobalVariable &ImplPointer); typedef std::map<Module*, DenseSet<const GlobalValue*>> ModulePartitionMap; +/// @brief Extract subsections of a Module into the given Module according to +/// the given ModulePartitionMap. void partition(Module &M, const ModulePartitionMap &PMap); /// @brief Struct for trivial "complete" partitioning of a module. @@ -239,6 +254,7 @@ public: Functions(std::move(S.Functions)) {} }; +/// @brief Extract every function in M into a separate module. FullyPartitionedModule fullyPartition(Module &M); } // End namespace orc. diff --git a/include/llvm/ExecutionEngine/Orc/JITSymbol.h b/include/llvm/ExecutionEngine/Orc/JITSymbol.h index 7c3ad56..422a376 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<TargetAddress()> GetAddressFtor; diff --git a/include/llvm/ExecutionEngine/Orc/LambdaResolver.h b/include/llvm/ExecutionEngine/Orc/LambdaResolver.h new file mode 100644 index 0000000..faa2365 --- /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 <memory> +#include <vector> + +namespace llvm { +namespace orc { + +template <typename ExternalLookupFtorT, typename DylibLookupFtorT> +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 <typename ExternalLookupFtorT, + typename DylibLookupFtorT> +std::unique_ptr<LambdaResolver<ExternalLookupFtorT, DylibLookupFtorT>> +createLambdaResolver(ExternalLookupFtorT ExternalLookupFtor, + DylibLookupFtorT DylibLookupFtor) { + typedef LambdaResolver<ExternalLookupFtorT, DylibLookupFtorT> LR; + return make_unique<LR>(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 ac5fccf..71c83f7 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 <list> @@ -94,10 +94,11 @@ private: BaseLayer.emitAndFinalize(Handle); } - template <typename ModuleSetT> + template <typename ModuleSetT, typename MemoryManagerPtrT, + typename SymbolResolverPtrT> static std::unique_ptr<EmissionDeferredSet> - create(BaseLayerT &B, ModuleSetT Ms, - std::unique_ptr<RTDyldMemoryManager> 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 <typename ModuleSetT> + template <typename ModuleSetT, typename MemoryManagerPtrT, + typename SymbolResolverPtrT> class EmissionDeferredSetImpl : public EmissionDeferredSet { public: EmissionDeferredSetImpl(ModuleSetT Ms, - std::unique_ptr<RTDyldMemoryManager> 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<RTDyldMemoryManager> MM; + MemoryManagerPtrT MemMgr; + SymbolResolverPtrT Resolver; mutable std::unique_ptr<StringMap<const GlobalValue*>> MangledSymbols; }; @@ -223,12 +229,15 @@ public: LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {} /// @brief Add the given set of modules to the lazy emitting layer. - template <typename ModuleSetT> + template <typename ModuleSetT, typename MemoryManagerPtrT, + typename SymbolResolverPtrT> ModuleSetHandleT addModuleSet(ModuleSetT Ms, - std::unique_ptr<RTDyldMemoryManager> 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 <typename BaseLayerT> -template <typename ModuleSetT> +template <typename ModuleSetT, typename MemoryManagerPtrT, + typename SymbolResolverPtrT> std::unique_ptr<typename LazyEmittingLayer<BaseLayerT>::EmissionDeferredSet> LazyEmittingLayer<BaseLayerT>::EmissionDeferredSet::create( - BaseLayerT &B, ModuleSetT Ms, std::unique_ptr<RTDyldMemoryManager> MM) { - return llvm::make_unique<EmissionDeferredSetImpl<ModuleSetT>>(std::move(Ms), - std::move(MM)); + BaseLayerT &B, ModuleSetT Ms, MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) { + typedef EmissionDeferredSetImpl<ModuleSetT, MemoryManagerPtrT, SymbolResolverPtrT> + EDS; + return llvm::make_unique<EDS>(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 4456404..0000000 --- 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 <memory> -#include <vector> - -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 <typename BaseRTDyldMM, typename ExternalLookupFtor, - typename DylibLookupFtor> -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 <typename BaseRTDyldMM, typename ExternalLookupFtor, - typename DylibLookupFtor> -std::unique_ptr< - LookasideRTDyldMM<BaseRTDyldMM, ExternalLookupFtor, DylibLookupFtor>> -createLookasideRTDyldMM(ExternalLookupFtor &&ExternalLookup, - DylibLookupFtor &&DylibLookup) { - typedef LookasideRTDyldMM<BaseRTDyldMM, ExternalLookupFtor, DylibLookupFtor> - ThisLookasideMM; - return llvm::make_unique<ThisLookasideMM>( - std::forward<ExternalLookupFtor>(ExternalLookup), - std::forward<DylibLookupFtor>(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 9838991..f3094da 100644 --- a/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h +++ b/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h @@ -15,7 +15,7 @@ #define LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H #include "JITSymbol.h" -#include "LookasideRTDyldMM.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" #include <list> @@ -38,13 +38,12 @@ protected: LinkedObjectSet(const LinkedObjectSet&) = delete; void operator=(const LinkedObjectSet&) = delete; public: - LinkedObjectSet(std::unique_ptr<RTDyldMemoryManager> MM) - : MM(std::move(MM)), RTDyld(llvm::make_unique<RuntimeDyld>(&*this->MM)), + LinkedObjectSet(RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) + : RTDyld(llvm::make_unique<RuntimeDyld>(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<RuntimeDyld::LoadedObjectInfo> addObject(const object::ObjectFile &Obj) { @@ -57,14 +56,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 +68,7 @@ protected: OwnedBuffers.push_back(std::move(B)); } - private: - std::unique_ptr<RTDyldMemoryManager> MM; + protected: std::unique_ptr<RuntimeDyld> RTDyld; enum { Raw, Finalizing, Finalized } State; @@ -87,7 +78,7 @@ protected: std::vector<std::unique_ptr<MemoryBuffer>> OwnedBuffers; }; - typedef std::list<LinkedObjectSet> LinkedObjectSetListT; + typedef std::list<std::unique_ptr<LinkedObjectSet>> LinkedObjectSetListT; public: /// @brief Handle to a set of loaded objects. @@ -99,7 +90,7 @@ public: template <typename OwningMBSet> void takeOwnershipOfBuffers(ObjSetHandleT H, OwningMBSet MBs) { for (auto &MB : MBs) - H->takeOwnershipOfBuffer(std::move(MB)); + (*H)->takeOwnershipOfBuffer(std::move(MB)); } }; @@ -120,6 +111,37 @@ public: /// symbols. template <typename NotifyLoadedFtor = DoNothingOnNotifyLoaded> class ObjectLinkingLayer : public ObjectLinkingLayerBase { +private: + + template <typename MemoryManagerPtrT, typename SymbolResolverPtrT> + 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 <typename MemoryManagerPtrT, typename SymbolResolverPtrT> + std::unique_ptr<LinkedObjectSet> + createLinkedObjectSet(MemoryManagerPtrT MemMgr, SymbolResolverPtrT Resolver) { + typedef ConcreteLinkedObjectSet<MemoryManagerPtrT, SymbolResolverPtrT> LOS; + return llvm::make_unique<LOS>(std::move(MemMgr), std::move(Resolver)); + } + public: /// @brief LoadedObjectInfo list. Contains a list of owning pointers to @@ -127,21 +149,16 @@ public: typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>> LoadedObjInfoList; - /// @brief Functor to create RTDyldMemoryManager instances. - typedef std::function<std::unique_ptr<RTDyldMemoryManager>()> CreateRTDyldMMFtor; - /// @brief Functor for receiving finalization notifications. typedef std::function<void(ObjSetHandleT)> 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 +171,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 <typename ObjSetT> + template <typename ObjSetT, + typename MemoryManagerPtrT, + typename SymbolResolverPtrT> ObjSetHandleT addObjectSet(const ObjSetT &Objects, - std::unique_ptr<RTDyldMemoryManager> 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 +228,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 +241,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 +260,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 +276,6 @@ private: LinkedObjectSetListT LinkedObjSetList; NotifyLoadedFtor NotifyLoaded; NotifyFinalizedFtor NotifyFinalized; - CreateRTDyldMMFtor CreateMemoryManager; }; } // End namespace orc. |