summaryrefslogtreecommitdiff
path: root/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h')
-rw-r--r--llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h534
1 files changed, 534 insertions, 0 deletions
diff --git a/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h b/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h
new file mode 100644
index 000000000000..e0af3df9d010
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h
@@ -0,0 +1,534 @@
+//===- OrcCBindingsStack.h - Orc JIT stack for C bindings -----*- C++ -*---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
+#define LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
+
+#include "llvm-c/OrcBindings.h"
+#include "llvm-c/TargetMachine.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/ExecutionEngine/JITEventListener.h"
+#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
+#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
+#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
+#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
+#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
+#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
+#include "llvm/ExecutionEngine/RuntimeDyld.h"
+#include "llvm/ExecutionEngine/SectionMemoryManager.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Mangler.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/CBindingWrapping.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetMachine.h"
+#include <algorithm>
+#include <cstdint>
+#include <functional>
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+namespace llvm {
+
+class OrcCBindingsStack;
+
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OrcCBindingsStack, LLVMOrcJITStackRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
+
+namespace detail {
+
+// FIXME: Kill this off once the Layer concept becomes an interface.
+class GenericLayer {
+public:
+ virtual ~GenericLayer() = default;
+
+ virtual JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
+ bool ExportedSymbolsOnly) = 0;
+ virtual Error removeModule(orc::VModuleKey K) = 0;
+ };
+
+ template <typename LayerT> class GenericLayerImpl : public GenericLayer {
+ public:
+ GenericLayerImpl(LayerT &Layer) : Layer(Layer) {}
+
+ JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
+ bool ExportedSymbolsOnly) override {
+ return Layer.findSymbolIn(K, Name, ExportedSymbolsOnly);
+ }
+
+ Error removeModule(orc::VModuleKey K) override {
+ return Layer.removeModule(K);
+ }
+
+ private:
+ LayerT &Layer;
+ };
+
+ template <>
+ class GenericLayerImpl<orc::LegacyRTDyldObjectLinkingLayer> : public GenericLayer {
+ private:
+ using LayerT = orc::LegacyRTDyldObjectLinkingLayer;
+ public:
+ GenericLayerImpl(LayerT &Layer) : Layer(Layer) {}
+
+ JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
+ bool ExportedSymbolsOnly) override {
+ return Layer.findSymbolIn(K, Name, ExportedSymbolsOnly);
+ }
+
+ Error removeModule(orc::VModuleKey K) override {
+ return Layer.removeObject(K);
+ }
+
+ private:
+ LayerT &Layer;
+ };
+
+ template <typename LayerT>
+ std::unique_ptr<GenericLayerImpl<LayerT>> createGenericLayer(LayerT &Layer) {
+ return std::make_unique<GenericLayerImpl<LayerT>>(Layer);
+ }
+
+} // end namespace detail
+
+class OrcCBindingsStack {
+public:
+
+ using CompileCallbackMgr = orc::JITCompileCallbackManager;
+ using ObjLayerT = orc::LegacyRTDyldObjectLinkingLayer;
+ using CompileLayerT = orc::LegacyIRCompileLayer<ObjLayerT, orc::SimpleCompiler>;
+ using CODLayerT =
+ orc::LegacyCompileOnDemandLayer<CompileLayerT, CompileCallbackMgr>;
+
+ using CallbackManagerBuilder =
+ std::function<std::unique_ptr<CompileCallbackMgr>()>;
+
+ using IndirectStubsManagerBuilder = CODLayerT::IndirectStubsManagerBuilderT;
+
+private:
+
+ using OwningObject = object::OwningBinary<object::ObjectFile>;
+
+ class CBindingsResolver : public orc::SymbolResolver {
+ public:
+ CBindingsResolver(OrcCBindingsStack &Stack,
+ LLVMOrcSymbolResolverFn ExternalResolver,
+ void *ExternalResolverCtx)
+ : Stack(Stack), ExternalResolver(std::move(ExternalResolver)),
+ ExternalResolverCtx(std::move(ExternalResolverCtx)) {}
+
+ orc::SymbolNameSet
+ getResponsibilitySet(const orc::SymbolNameSet &Symbols) override {
+ orc::SymbolNameSet Result;
+
+ for (auto &S : Symbols) {
+ if (auto Sym = findSymbol(*S)) {
+ if (!Sym.getFlags().isStrong())
+ Result.insert(S);
+ } else if (auto Err = Sym.takeError()) {
+ Stack.reportError(std::move(Err));
+ return orc::SymbolNameSet();
+ }
+ }
+
+ return Result;
+ }
+
+ orc::SymbolNameSet
+ lookup(std::shared_ptr<orc::AsynchronousSymbolQuery> Query,
+ orc::SymbolNameSet Symbols) override {
+ orc::SymbolNameSet UnresolvedSymbols;
+
+ for (auto &S : Symbols) {
+ if (auto Sym = findSymbol(*S)) {
+ if (auto Addr = Sym.getAddress()) {
+ Query->notifySymbolMetRequiredState(
+ S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
+ } else {
+ Stack.ES.legacyFailQuery(*Query, Addr.takeError());
+ return orc::SymbolNameSet();
+ }
+ } else if (auto Err = Sym.takeError()) {
+ Stack.ES.legacyFailQuery(*Query, std::move(Err));
+ return orc::SymbolNameSet();
+ } else
+ UnresolvedSymbols.insert(S);
+ }
+
+ if (Query->isComplete())
+ Query->handleComplete();
+
+ return UnresolvedSymbols;
+ }
+
+ private:
+ JITSymbol findSymbol(const std::string &Name) {
+ // Search order:
+ // 1. JIT'd symbols.
+ // 2. Runtime overrides.
+ // 3. External resolver (if present).
+
+ if (Stack.CODLayer) {
+ if (auto Sym = Stack.CODLayer->findSymbol(Name, true))
+ return Sym;
+ else if (auto Err = Sym.takeError())
+ return Sym.takeError();
+ } else {
+ if (auto Sym = Stack.CompileLayer.findSymbol(Name, true))
+ return Sym;
+ else if (auto Err = Sym.takeError())
+ return Sym.takeError();
+ }
+
+ if (auto Sym = Stack.CXXRuntimeOverrides.searchOverrides(Name))
+ return Sym;
+
+ if (ExternalResolver)
+ return JITSymbol(ExternalResolver(Name.c_str(), ExternalResolverCtx),
+ JITSymbolFlags::Exported);
+
+ return JITSymbol(nullptr);
+ }
+
+ OrcCBindingsStack &Stack;
+ LLVMOrcSymbolResolverFn ExternalResolver;
+ void *ExternalResolverCtx = nullptr;
+ };
+
+public:
+ OrcCBindingsStack(TargetMachine &TM,
+ IndirectStubsManagerBuilder IndirectStubsMgrBuilder)
+ : CCMgr(createCompileCallbackManager(TM, ES)), DL(TM.createDataLayout()),
+ IndirectStubsMgr(IndirectStubsMgrBuilder()),
+ ObjectLayer(
+ AcknowledgeORCv1Deprecation, ES,
+ [this](orc::VModuleKey K) {
+ auto ResolverI = Resolvers.find(K);
+ assert(ResolverI != Resolvers.end() &&
+ "No resolver for module K");
+ auto Resolver = std::move(ResolverI->second);
+ Resolvers.erase(ResolverI);
+ return ObjLayerT::Resources{
+ std::make_shared<SectionMemoryManager>(), Resolver};
+ },
+ nullptr,
+ [this](orc::VModuleKey K, const object::ObjectFile &Obj,
+ const RuntimeDyld::LoadedObjectInfo &LoadedObjInfo) {
+ this->notifyFinalized(K, Obj, LoadedObjInfo);
+ },
+ [this](orc::VModuleKey K, const object::ObjectFile &Obj) {
+ this->notifyFreed(K, Obj);
+ }),
+ CompileLayer(AcknowledgeORCv1Deprecation, ObjectLayer,
+ orc::SimpleCompiler(TM)),
+ CODLayer(createCODLayer(ES, CompileLayer, CCMgr.get(),
+ std::move(IndirectStubsMgrBuilder), Resolvers)),
+ CXXRuntimeOverrides(
+ AcknowledgeORCv1Deprecation,
+ [this](const std::string &S) { return mangle(S); }) {}
+
+ Error shutdown() {
+ // Run any destructors registered with __cxa_atexit.
+ CXXRuntimeOverrides.runDestructors();
+ // Run any IR destructors.
+ for (auto &DtorRunner : IRStaticDestructorRunners)
+ if (auto Err = DtorRunner.runViaLayer(*this))
+ return Err;
+ return Error::success();
+ }
+
+ std::string mangle(StringRef Name) {
+ std::string MangledName;
+ {
+ raw_string_ostream MangledNameStream(MangledName);
+ Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
+ }
+ return MangledName;
+ }
+
+ template <typename PtrTy>
+ static PtrTy fromTargetAddress(JITTargetAddress Addr) {
+ return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr));
+ }
+
+ Expected<JITTargetAddress>
+ createLazyCompileCallback(LLVMOrcLazyCompileCallbackFn Callback,
+ void *CallbackCtx) {
+ auto WrappedCallback = [=]() -> JITTargetAddress {
+ return Callback(wrap(this), CallbackCtx);
+ };
+
+ return CCMgr->getCompileCallback(std::move(WrappedCallback));
+ }
+
+ Error createIndirectStub(StringRef StubName, JITTargetAddress Addr) {
+ return IndirectStubsMgr->createStub(StubName, Addr,
+ JITSymbolFlags::Exported);
+ }
+
+ Error setIndirectStubPointer(StringRef Name, JITTargetAddress Addr) {
+ return IndirectStubsMgr->updatePointer(Name, Addr);
+ }
+
+ template <typename LayerT>
+ Expected<orc::VModuleKey>
+ addIRModule(LayerT &Layer, std::unique_ptr<Module> M,
+ std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr,
+ LLVMOrcSymbolResolverFn ExternalResolver,
+ void *ExternalResolverCtx) {
+
+ // Attach a data-layout if one isn't already present.
+ if (M->getDataLayout().isDefault())
+ M->setDataLayout(DL);
+
+ // Record the static constructors and destructors. We have to do this before
+ // we hand over ownership of the module to the JIT.
+ std::vector<std::string> CtorNames, DtorNames;
+ for (auto Ctor : orc::getConstructors(*M))
+ CtorNames.push_back(mangle(Ctor.Func->getName()));
+ for (auto Dtor : orc::getDestructors(*M))
+ DtorNames.push_back(mangle(Dtor.Func->getName()));
+
+ // Add the module to the JIT.
+ auto K = ES.allocateVModule();
+ Resolvers[K] = std::make_shared<CBindingsResolver>(*this, ExternalResolver,
+ ExternalResolverCtx);
+ if (auto Err = Layer.addModule(K, std::move(M)))
+ return std::move(Err);
+
+ KeyLayers[K] = detail::createGenericLayer(Layer);
+
+ // Run the static constructors, and save the static destructor runner for
+ // execution when the JIT is torn down.
+ orc::LegacyCtorDtorRunner<OrcCBindingsStack> CtorRunner(
+ AcknowledgeORCv1Deprecation, std::move(CtorNames), K);
+ if (auto Err = CtorRunner.runViaLayer(*this))
+ return std::move(Err);
+
+ IRStaticDestructorRunners.emplace_back(AcknowledgeORCv1Deprecation,
+ std::move(DtorNames), K);
+
+ return K;
+ }
+
+ Expected<orc::VModuleKey>
+ addIRModuleEager(std::unique_ptr<Module> M,
+ LLVMOrcSymbolResolverFn ExternalResolver,
+ void *ExternalResolverCtx) {
+ return addIRModule(CompileLayer, std::move(M),
+ std::make_unique<SectionMemoryManager>(),
+ std::move(ExternalResolver), ExternalResolverCtx);
+ }
+
+ Expected<orc::VModuleKey>
+ addIRModuleLazy(std::unique_ptr<Module> M,
+ LLVMOrcSymbolResolverFn ExternalResolver,
+ void *ExternalResolverCtx) {
+ if (!CODLayer)
+ return make_error<StringError>("Can not add lazy module: No compile "
+ "callback manager available",
+ inconvertibleErrorCode());
+
+ return addIRModule(*CODLayer, std::move(M),
+ std::make_unique<SectionMemoryManager>(),
+ std::move(ExternalResolver), ExternalResolverCtx);
+ }
+
+ Error removeModule(orc::VModuleKey K) {
+ // FIXME: Should error release the module key?
+ if (auto Err = KeyLayers[K]->removeModule(K))
+ return Err;
+ ES.releaseVModule(K);
+ KeyLayers.erase(K);
+ return Error::success();
+ }
+
+ Expected<orc::VModuleKey> addObject(std::unique_ptr<MemoryBuffer> ObjBuffer,
+ LLVMOrcSymbolResolverFn ExternalResolver,
+ void *ExternalResolverCtx) {
+ if (auto Obj = object::ObjectFile::createObjectFile(
+ ObjBuffer->getMemBufferRef())) {
+
+ auto K = ES.allocateVModule();
+ Resolvers[K] = std::make_shared<CBindingsResolver>(
+ *this, ExternalResolver, ExternalResolverCtx);
+
+ if (auto Err = ObjectLayer.addObject(K, std::move(ObjBuffer)))
+ return std::move(Err);
+
+ KeyLayers[K] = detail::createGenericLayer(ObjectLayer);
+
+ return K;
+ } else
+ return Obj.takeError();
+ }
+
+ JITSymbol findSymbol(const std::string &Name,
+ bool ExportedSymbolsOnly) {
+ if (auto Sym = IndirectStubsMgr->findStub(Name, ExportedSymbolsOnly))
+ return Sym;
+ if (CODLayer)
+ return CODLayer->findSymbol(mangle(Name), ExportedSymbolsOnly);
+ return CompileLayer.findSymbol(mangle(Name), ExportedSymbolsOnly);
+ }
+
+ JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
+ bool ExportedSymbolsOnly) {
+ assert(KeyLayers.count(K) && "looking up symbol in unknown module");
+ return KeyLayers[K]->findSymbolIn(K, mangle(Name), ExportedSymbolsOnly);
+ }
+
+ Expected<JITTargetAddress> findSymbolAddress(const std::string &Name,
+ bool ExportedSymbolsOnly) {
+ if (auto Sym = findSymbol(Name, ExportedSymbolsOnly)) {
+ // Successful lookup, non-null symbol:
+ if (auto AddrOrErr = Sym.getAddress())
+ return *AddrOrErr;
+ else
+ return AddrOrErr.takeError();
+ } else if (auto Err = Sym.takeError()) {
+ // Lookup failure - report error.
+ return std::move(Err);
+ }
+
+ // No symbol not found. Return 0.
+ return 0;
+ }
+
+ Expected<JITTargetAddress> findSymbolAddressIn(orc::VModuleKey K,
+ const std::string &Name,
+ bool ExportedSymbolsOnly) {
+ if (auto Sym = findSymbolIn(K, Name, ExportedSymbolsOnly)) {
+ // Successful lookup, non-null symbol:
+ if (auto AddrOrErr = Sym.getAddress())
+ return *AddrOrErr;
+ else
+ return AddrOrErr.takeError();
+ } else if (auto Err = Sym.takeError()) {
+ // Lookup failure - report error.
+ return std::move(Err);
+ }
+
+ // Symbol not found. Return 0.
+ return 0;
+ }
+
+ const std::string &getErrorMessage() const { return ErrMsg; }
+
+ void RegisterJITEventListener(JITEventListener *L) {
+ if (!L)
+ return;
+ EventListeners.push_back(L);
+ }
+
+ void UnregisterJITEventListener(JITEventListener *L) {
+ if (!L)
+ return;
+
+ auto I = find(reverse(EventListeners), L);
+ if (I != EventListeners.rend()) {
+ std::swap(*I, EventListeners.back());
+ EventListeners.pop_back();
+ }
+ }
+
+private:
+ using ResolverMap =
+ std::map<orc::VModuleKey, std::shared_ptr<orc::SymbolResolver>>;
+
+ static std::unique_ptr<CompileCallbackMgr>
+ createCompileCallbackManager(TargetMachine &TM, orc::ExecutionSession &ES) {
+ auto CCMgr = createLocalCompileCallbackManager(TM.getTargetTriple(), ES, 0);
+ if (!CCMgr) {
+ // FIXME: It would be good if we could report this somewhere, but we do
+ // have an instance yet.
+ logAllUnhandledErrors(CCMgr.takeError(), errs(), "ORC error: ");
+ return nullptr;
+ }
+ return std::move(*CCMgr);
+ }
+
+ static std::unique_ptr<CODLayerT>
+ createCODLayer(orc::ExecutionSession &ES, CompileLayerT &CompileLayer,
+ CompileCallbackMgr *CCMgr,
+ IndirectStubsManagerBuilder IndirectStubsMgrBuilder,
+ ResolverMap &Resolvers) {
+ // If there is no compile callback manager available we can not create a
+ // compile on demand layer.
+ if (!CCMgr)
+ return nullptr;
+
+ return std::make_unique<CODLayerT>(
+ AcknowledgeORCv1Deprecation, ES, CompileLayer,
+ [&Resolvers](orc::VModuleKey K) {
+ auto ResolverI = Resolvers.find(K);
+ assert(ResolverI != Resolvers.end() && "No resolver for module K");
+ return ResolverI->second;
+ },
+ [&Resolvers](orc::VModuleKey K,
+ std::shared_ptr<orc::SymbolResolver> Resolver) {
+ assert(!Resolvers.count(K) && "Resolver already present");
+ Resolvers[K] = std::move(Resolver);
+ },
+ [](Function &F) { return std::set<Function *>({&F}); }, *CCMgr,
+ std::move(IndirectStubsMgrBuilder), false);
+ }
+
+ void reportError(Error Err) {
+ // FIXME: Report errors on the execution session.
+ logAllUnhandledErrors(std::move(Err), errs(), "ORC error: ");
+ };
+
+ void notifyFinalized(orc::VModuleKey K,
+ const object::ObjectFile &Obj,
+ const RuntimeDyld::LoadedObjectInfo &LoadedObjInfo) {
+ uint64_t Key = static_cast<uint64_t>(
+ reinterpret_cast<uintptr_t>(Obj.getData().data()));
+ for (auto &Listener : EventListeners)
+ Listener->notifyObjectLoaded(Key, Obj, LoadedObjInfo);
+ }
+
+ void notifyFreed(orc::VModuleKey K, const object::ObjectFile &Obj) {
+ uint64_t Key = static_cast<uint64_t>(
+ reinterpret_cast<uintptr_t>(Obj.getData().data()));
+ for (auto &Listener : EventListeners)
+ Listener->notifyFreeingObject(Key);
+ }
+
+ orc::ExecutionSession ES;
+ std::unique_ptr<CompileCallbackMgr> CCMgr;
+
+ std::vector<JITEventListener *> EventListeners;
+
+ DataLayout DL;
+ SectionMemoryManager CCMgrMemMgr;
+
+ std::unique_ptr<orc::IndirectStubsManager> IndirectStubsMgr;
+
+ ObjLayerT ObjectLayer;
+ CompileLayerT CompileLayer;
+ std::unique_ptr<CODLayerT> CODLayer;
+
+ std::map<orc::VModuleKey, std::unique_ptr<detail::GenericLayer>> KeyLayers;
+
+ orc::LegacyLocalCXXRuntimeOverrides CXXRuntimeOverrides;
+ std::vector<orc::LegacyCtorDtorRunner<OrcCBindingsStack>> IRStaticDestructorRunners;
+ std::string ErrMsg;
+
+ ResolverMap Resolvers;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H