From ec30063ff313c9dffbfdc65243a87a80833d0c5b Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Sun, 17 Sep 2017 03:25:03 +0000 Subject: [PATCH] [ORC] Hook up the LLVMOrcAddObjectFile function in the Orc C Bindings. This can be used to add a relocatable object to the JIT session. llvm-svn: 313474 --- llvm/include/llvm-c/OrcBindings.h | 20 ++-- llvm/lib/ExecutionEngine/Orc/OrcCBindings.cpp | 22 ++-- .../ExecutionEngine/Orc/OrcCBindingsStack.h | 102 ++++++++++++++---- .../ExecutionEngine/Orc/OrcCAPITest.cpp | 40 +++++++ 4 files changed, 138 insertions(+), 46 deletions(-) diff --git a/llvm/include/llvm-c/OrcBindings.h b/llvm/include/llvm-c/OrcBindings.h index 7ee395431358..abb3ac6a7f03 100644 --- a/llvm/include/llvm-c/OrcBindings.h +++ b/llvm/include/llvm-c/OrcBindings.h @@ -30,7 +30,6 @@ extern "C" { #endif typedef struct LLVMOpaqueSharedModule *LLVMSharedModuleRef; -typedef struct LLVMOpaqueSharedObjectBuffer *LLVMSharedObjectBufferRef; typedef struct LLVMOrcOpaqueJITStack *LLVMOrcJITStackRef; typedef uint32_t LLVMOrcModuleHandle; typedef uint64_t LLVMOrcTargetAddress; @@ -67,18 +66,6 @@ LLVMSharedModuleRef LLVMOrcMakeSharedModule(LLVMModuleRef Mod); void LLVMOrcDisposeSharedModuleRef(LLVMSharedModuleRef SharedMod); -/** - * Get an LLVMSharedObjectBufferRef from an LLVMMemoryBufferRef. - */ -LLVMSharedObjectBufferRef -LLVMOrcMakeSharedObjectBuffer(LLVMMemoryBufferRef ObjBuffer); - -/** - * Dispose of a shared object buffer. - */ -void -LLVMOrcDisposeSharedObjectBufferRef(LLVMSharedObjectBufferRef SharedObjBuffer); - /** * Create an ORC JIT stack. * @@ -155,10 +142,15 @@ LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack, /** * Add an object file. + * + * This method takes ownership of the given memory buffer and attempts to add + * it to the JIT as an object file. + * Clients should *not* dispose of the 'Obj' argument: the JIT will manage it + * from this call onwards. */ LLVMOrcErrorCode LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack, LLVMOrcModuleHandle *RetHandle, - LLVMSharedObjectBufferRef Obj, + LLVMMemoryBufferRef Obj, LLVMOrcSymbolResolverFn SymbolResolver, void *SymbolResolverCtx); diff --git a/llvm/lib/ExecutionEngine/Orc/OrcCBindings.cpp b/llvm/lib/ExecutionEngine/Orc/OrcCBindings.cpp index de80cb1d0dd4..f945acaf95ee 100644 --- a/llvm/lib/ExecutionEngine/Orc/OrcCBindings.cpp +++ b/llvm/lib/ExecutionEngine/Orc/OrcCBindings.cpp @@ -20,16 +20,6 @@ void LLVMOrcDisposeSharedModuleRef(LLVMSharedModuleRef SharedMod) { delete unwrap(SharedMod); } -LLVMSharedObjectBufferRef -LLVMOrcMakeSharedObjectBuffer(LLVMMemoryBufferRef ObjBuffer) { - return wrap(new std::shared_ptr(unwrap(ObjBuffer))); -} - -void -LLVMOrcDisposeSharedObjectBufferRef(LLVMSharedObjectBufferRef SharedObjBuffer) { - delete unwrap(SharedObjBuffer); -} - LLVMOrcJITStackRef LLVMOrcCreateInstance(LLVMTargetMachineRef TM) { TargetMachine *TM2(unwrap(TM)); @@ -105,6 +95,18 @@ LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack, return J.addIRModuleLazy(*RetHandle, *M, SymbolResolver, SymbolResolverCtx); } +LLVMOrcErrorCode +LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack, + LLVMOrcModuleHandle *RetHandle, + LLVMMemoryBufferRef Obj, + LLVMOrcSymbolResolverFn SymbolResolver, + void *SymbolResolverCtx) { + OrcCBindingsStack &J = *unwrap(JITStack); + std::unique_ptr O(unwrap(Obj)); + return J.addObject(*RetHandle, std::move(O), SymbolResolver, + SymbolResolverCtx); +} + LLVMOrcErrorCode LLVMOrcRemoveModule(LLVMOrcJITStackRef JITStack, LLVMOrcModuleHandle H) { OrcCBindingsStack &J = *unwrap(JITStack); diff --git a/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h b/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h index ecb4c207b5df..405970e063d8 100644 --- a/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h +++ b/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h @@ -44,26 +44,12 @@ class OrcCBindingsStack; DEFINE_SIMPLE_CONVERSION_FUNCTIONS(std::shared_ptr, LLVMSharedModuleRef) -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(std::shared_ptr, - LLVMSharedObjectBufferRef) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OrcCBindingsStack, LLVMOrcJITStackRef) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef) -class OrcCBindingsStack { -public: +namespace detail { - using CompileCallbackMgr = orc::JITCompileCallbackManager; - using ObjLayerT = orc::RTDyldObjectLinkingLayer; - using CompileLayerT = orc::IRCompileLayer; - using CODLayerT = - orc::CompileOnDemandLayer; - using CallbackManagerBuilder = - std::function()>; - - using IndirectStubsManagerBuilder = CODLayerT::IndirectStubsManagerBuilderT; - -private: class GenericHandle { public: virtual ~GenericHandle() = default; @@ -90,13 +76,56 @@ private: typename LayerT::ModuleHandleT Handle; }; - template + template <> + class GenericHandleImpl + : public GenericHandle { + private: + using LayerT = orc::RTDyldObjectLinkingLayer; + public: + + GenericHandleImpl(LayerT &Layer, typename LayerT::ObjHandleT Handle) + : Layer(Layer), Handle(std::move(Handle)) {} + + JITSymbol findSymbolIn(const std::string &Name, + bool ExportedSymbolsOnly) override { + return Layer.findSymbolIn(Handle, Name, ExportedSymbolsOnly); + } + + Error removeModule() override { return Layer.removeObject(Handle); } + + private: + LayerT &Layer; + typename LayerT::ObjHandleT Handle; + }; + + + template std::unique_ptr> - createGenericHandle(LayerT &Layer, typename LayerT::ModuleHandleT Handle) { + createGenericHandle(LayerT &Layer, HandleT Handle) { return llvm::make_unique>(Layer, std::move(Handle)); } +} // end namespace detail + +class OrcCBindingsStack { +public: + + using CompileCallbackMgr = orc::JITCompileCallbackManager; + using ObjLayerT = orc::RTDyldObjectLinkingLayer; + using CompileLayerT = orc::IRCompileLayer; + using CODLayerT = + orc::CompileOnDemandLayer; + + using CallbackManagerBuilder = + std::function()>; + + using IndirectStubsManagerBuilder = CODLayerT::IndirectStubsManagerBuilderT; + +private: + + using OwningObject = object::OwningBinary; + public: using ModuleHandleT = unsigned; @@ -266,6 +295,33 @@ public: return LLVMOrcErrSuccess; } + LLVMOrcErrorCode addObject(ModuleHandleT &RetHandle, + std::unique_ptr ObjBuffer, + LLVMOrcSymbolResolverFn ExternalResolver, + void *ExternalResolverCtx) { + if (auto ObjOrErr = + object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef())) { + auto &Obj = *ObjOrErr; + auto OwningObj = + std::make_shared(std::move(Obj), std::move(ObjBuffer)); + + // Create the resolver. + auto Resolver = createResolver(ExternalResolver, ExternalResolverCtx); + + ModuleHandleT H; + if (auto HOrErr = ObjectLayer.addObject(std::move(OwningObj), + std::move(Resolver))) + H = createHandle(ObjectLayer, *HOrErr); + else + return mapError(HOrErr.takeError()); + + RetHandle = H; + + return LLVMOrcErrSuccess; + } else + return mapError(ObjOrErr.takeError()); + } + JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { if (auto Sym = IndirectStubsMgr->findStub(Name, ExportedSymbolsOnly)) @@ -301,17 +357,19 @@ public: const std::string &getErrorMessage() const { return ErrMsg; } private: - template - unsigned createHandle(LayerT &Layer, typename LayerT::ModuleHandleT Handle) { + template + unsigned createHandle(LayerT &Layer, HandleT Handle) { unsigned NewHandle; if (!FreeHandleIndexes.empty()) { NewHandle = FreeHandleIndexes.back(); FreeHandleIndexes.pop_back(); - GenericHandles[NewHandle] = createGenericHandle(Layer, std::move(Handle)); + GenericHandles[NewHandle] = + detail::createGenericHandle(Layer, std::move(Handle)); return NewHandle; } else { NewHandle = GenericHandles.size(); - GenericHandles.push_back(createGenericHandle(Layer, std::move(Handle))); + GenericHandles.push_back( + detail::createGenericHandle(Layer, std::move(Handle))); } return NewHandle; } @@ -338,7 +396,7 @@ private: CompileLayerT CompileLayer; CODLayerT CODLayer; - std::vector> GenericHandles; + std::vector> GenericHandles; std::vector FreeHandleIndexes; orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides; diff --git a/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp b/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp index 5a4d6b4a2252..d9448d47667f 100644 --- a/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "OrcTestCommon.h" +#include "llvm/ExecutionEngine/Orc/CompileUtils.h" #include "llvm-c/Core.h" #include "llvm-c/OrcBindings.h" #include "llvm-c/Target.h" @@ -37,6 +38,15 @@ protected: return MB.takeModule(); } + std::shared_ptr> + createTestObject() { + orc::SimpleCompiler IRCompiler(*TM); + auto M = createTestModule(TM->getTargetTriple()); + M->setDataLayout(TM->createDataLayout()); + return std::make_shared>( + IRCompiler(*M)); + } + typedef int (*MainFnTy)(); static int myTestFuncImpl() { @@ -134,6 +144,36 @@ TEST_F(OrcCAPIExecutionTest, TestLazyIRCompilation) { LLVMOrcDisposeInstance(JIT); } +TEST_F(OrcCAPIExecutionTest, TestAddObjectFile) { + if (!TM) + return; + + std::unique_ptr ObjBuffer; + { + auto OwningObj = createTestObject(); + auto ObjAndBuffer = OwningObj->takeBinary(); + ObjBuffer = std::move(ObjAndBuffer.second); + } + + LLVMOrcJITStackRef JIT = + LLVMOrcCreateInstance(wrap(TM.get())); + LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc"); + + LLVMOrcModuleHandle H; + LLVMOrcAddObjectFile(JIT, &H, wrap(ObjBuffer.release()), myResolver, nullptr); + LLVMOrcTargetAddress MainAddr; + LLVMOrcGetSymbolAddress(JIT, &MainAddr, "main"); + MainFnTy MainFn = (MainFnTy)MainAddr; + int Result = MainFn(); + EXPECT_EQ(Result, 42) + << "Lazily JIT'd code did not return expected result"; + + LLVMOrcRemoveModule(JIT, H); + + LLVMOrcDisposeMangledSymbol(testFuncName); + LLVMOrcDisposeInstance(JIT); +} + TEST_F(OrcCAPIExecutionTest, TestDirectCallbacksAPI) { if (!TM) return;