X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FExecutionEngine%2FOrc%2FIndirectionUtils.h;h=13ba125e80b4b627b84350451e89b673238b148d;hb=af4016443146134fc73e5fe8af4094f8a2313cf3;hp=50e9a4352dd7f50089626b2b945da5d4ad2cd0fe;hpb=884236fa72399b1785b82f93b537771a801dc3c5;p=oota-llvm.git diff --git a/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h index 50e9a4352dd..13ba125e80b 100644 --- a/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h +++ b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h @@ -15,20 +15,47 @@ #define LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H #include "JITSymbol.h" +#include "LambdaResolver.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" #include namespace llvm { +namespace orc { /// @brief Base class for JITLayer independent aspects of /// JITCompileCallbackManager. -template class JITCompileCallbackManagerBase { public: + typedef std::function CompileFtor; + typedef std::function UpdateFtor; + + /// @brief Handle to a newly created compile callback. Can be used to get an + /// IR constant representing the address of the trampoline, and to set + /// the compile and update actions for the callback. + class CompileCallbackInfo { + public: + CompileCallbackInfo(TargetAddress Addr, CompileFtor &Compile, + UpdateFtor &Update) + : Addr(Addr), Compile(Compile), Update(Update) {} + + TargetAddress getAddress() const { return Addr; } + void setCompileAction(CompileFtor Compile) { + this->Compile = std::move(Compile); + } + void setUpdateAction(UpdateFtor Update) { + this->Update = std::move(Update); + } + private: + TargetAddress Addr; + CompileFtor &Compile; + UpdateFtor &Update; + }; + /// @brief Construct a JITCompileCallbackManagerBase. /// @param ErrorHandlerAddress The address of an error handler in the target /// process to be used if a compile callback fails. @@ -40,10 +67,12 @@ public: : ErrorHandlerAddress(ErrorHandlerAddress), NumTrampolinesPerBlock(NumTrampolinesPerBlock) {} + virtual ~JITCompileCallbackManagerBase() {} + /// @brief Execute the callback for the given trampoline id. Called by the JIT /// to compile functions on demand. TargetAddress executeCompileCallback(TargetAddress TrampolineID) { - typename TrampolineMapT::iterator I = ActiveTrampolines.find(TrampolineID); + TrampolineMapT::iterator I = ActiveTrampolines.find(TrampolineID); // FIXME: Also raise an error in the Orc error-handler when we finally have // one. if (I == ActiveTrampolines.end()) @@ -55,7 +84,7 @@ public: // Moving the trampoline ID back to the available list first means there's at // least one available trampoline if the compile action triggers a request for // a new one. - AvailableTrampolines.push_back(I->first - TargetT::CallSize); + AvailableTrampolines.push_back(I->first); auto CallbackHandler = std::move(I->second); ActiveTrampolines.erase(I); @@ -66,14 +95,14 @@ public: return ErrorHandlerAddress; } -protected: + /// @brief Get/create a compile callback with the given signature. + virtual CompileCallbackInfo getCompileCallback(LLVMContext &Context) = 0; - typedef std::function CompileFtorT; - typedef std::function UpdateFtorT; +protected: struct CallbackHandler { - CompileFtorT Compile; - UpdateFtorT Update; + CompileFtor Compile; + UpdateFtor Update; }; TargetAddress ErrorHandlerAddress; @@ -86,15 +115,9 @@ protected: /// @brief Manage compile callbacks. template -class JITCompileCallbackManager : - public JITCompileCallbackManagerBase { +class JITCompileCallbackManager : public JITCompileCallbackManagerBase { public: - typedef typename JITCompileCallbackManagerBase::CompileFtorT - CompileFtorT; - typedef typename JITCompileCallbackManagerBase::UpdateFtorT - UpdateFtorT; - /// @brief Construct a JITCompileCallbackManager. /// @param JIT JIT layer to emit callback trampolines, etc. into. /// @param Context LLVMContext to use for trampoline & resolve block modules. @@ -104,63 +127,24 @@ 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) { + : JITCompileCallbackManagerBase(ErrorHandlerAddress, + NumTrampolinesPerBlock), + JIT(JIT), MemMgr(MemMgr) { emitResolverBlock(Context); } - /// @brief Handle to a newly created compile callback. Can be used to get an - /// IR constant representing the address of the trampoline, and to set - /// the compile and update actions for the callback. - class CompileCallbackInfo { - public: - CompileCallbackInfo(Constant *Addr, CompileFtorT &Compile, - UpdateFtorT &Update) - : Addr(Addr), Compile(Compile), Update(Update) {} - - Constant* getAddress() const { return Addr; } - void setCompileAction(CompileFtorT Compile) { - this->Compile = std::move(Compile); - } - void setUpdateAction(UpdateFtorT Update) { - this->Update = std::move(Update); - } - private: - Constant *Addr; - CompileFtorT &Compile; - UpdateFtorT &Update; - }; - /// @brief Get/create a compile callback with the given signature. - CompileCallbackInfo getCompileCallback(FunctionType &FT) { - TargetAddress TrampolineAddr = getAvailableTrampolineAddr(FT.getContext()); + CompileCallbackInfo getCompileCallback(LLVMContext &Context) final { + TargetAddress TrampolineAddr = getAvailableTrampolineAddr(Context); auto &CallbackHandler = - this->ActiveTrampolines[TrampolineAddr + TargetT::CallSize]; - 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, - CallbackHandler.Update); - } + this->ActiveTrampolines[TrampolineAddr]; - /// @brief Get a functor for updating the value of a named function pointer. - UpdateFtorT getLocalFPUpdater(typename JITLayerT::ModuleSetHandleT H, - std::string Name) { - // FIXME: Move-capture Name once we can use C++14. - return [=](TargetAddress Addr) { - auto FPSym = JIT.findSymbolIn(H, Name, true); - assert(FPSym && "Cannot find function pointer to update."); - void *FPAddr = reinterpret_cast( - static_cast(FPSym.getAddress())); - memcpy(FPAddr, &Addr, sizeof(uintptr_t)); - }; + return CompileCallbackInfo(TrampolineAddr, CallbackHandler.Compile, + CallbackHandler.Update); } private: @@ -176,7 +160,16 @@ 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 NonResolver = + createLambdaResolver( + [](const std::string &Name) -> RuntimeDyld::SymbolInfo { + llvm_unreachable("External symbols in resolver block?"); + }, + [](const std::string &Name) -> RuntimeDyld::SymbolInfo { + llvm_unreachable("Dylib symbols in resolver block?"); + }); + auto H = JIT.addModuleSet(SingletonSet(std::move(M)), &MemMgr, + std::move(NonResolver)); JIT.emitAndFinalize(H); auto ResolverBlockSymbol = JIT.findSymbolIn(H, TargetT::ResolverBlockName, false); @@ -201,7 +194,16 @@ private: TargetT::insertCompileCallbackTrampolines(*M, ResolverBlockAddr, this->NumTrampolinesPerBlock, this->ActiveTrampolines.size()); - auto H = JIT.addModuleSet(SingletonSet(std::move(M)), nullptr); + auto NonResolver = + createLambdaResolver( + [](const std::string &Name) -> RuntimeDyld::SymbolInfo { + llvm_unreachable("External symbols in trampoline block?"); + }, + [](const std::string &Name) -> RuntimeDyld::SymbolInfo { + llvm_unreachable("Dylib symbols in trampoline block?"); + }); + auto H = JIT.addModuleSet(SingletonSet(std::move(M)), &MemMgr, + std::move(NonResolver)); JIT.emitAndFinalize(H); for (unsigned I = 0; I < this->NumTrampolinesPerBlock; ++I) { std::string Name = GetLabelName(I); @@ -212,16 +214,46 @@ private: } JITLayerT &JIT; + RuntimeDyld::MemoryManager &MemMgr; TargetAddress ResolverBlockAddr; }; -GlobalVariable* createImplPointer(Function &F, const Twine &Name, - Constant *Initializer); +/// @brief Get an update functor that updates the value of a named function +/// pointer. +template +JITCompileCallbackManagerBase::UpdateFtor +getLocalFPUpdater(JITLayerT &JIT, typename JITLayerT::ModuleSetHandleT H, + std::string Name) { + // FIXME: Move-capture Name once we can use C++14. + return [=,&JIT](TargetAddress Addr) { + auto FPSym = JIT.findSymbolIn(H, Name, true); + assert(FPSym && "Cannot find function pointer to update."); + void *FPAddr = reinterpret_cast( + static_cast(FPSym.getAddress())); + memcpy(FPAddr, &Addr, sizeof(uintptr_t)); + }; + } + +/// @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> 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. @@ -237,8 +269,10 @@ public: Functions(std::move(S.Functions)) {} }; +/// @brief Extract every function in M into a separate module. FullyPartitionedModule fullyPartition(Module &M); -} +} // End namespace orc. +} // End namespace llvm. #endif // LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H