From 4b546c91452c5735ada1430f8a6943328e4dba4e Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Tue, 6 Feb 2018 21:25:11 +0000 Subject: [PATCH] [ORC] Start migrating ORC layers to use the new ORC Core.h APIs. In particular this patch switches RTDyldObjectLinkingLayer to use orc::SymbolResolver and threads the requried changse (ExecutionSession references and VModuleKeys) through the existing layer APIs. The purpose of the new resolver interface is to improve query performance and better support parallelism, both in JIT'd code and within the compiler itself. The most visibile change is switch of the ::addModule signatures from: Expected addModule(std::shared_ptr Mod, std::shared_ptr Resolver) to: Expected addModule(VModuleKey K, std::shared_ptr Mod); Typical usage of addModule will now look like: auto K = ES.allocateVModuleKey(); Resolvers[K] = createSymbolResolver(...); Layer.addModule(K, std::move(Mod)); See the BuildingAJIT tutorial code for example usage. llvm-svn: 324405 --- .../BuildingAJIT/Chapter1/CMakeLists.txt | 1 + .../BuildingAJIT/Chapter1/KaleidoscopeJIT.h | 46 ++-- .../BuildingAJIT/Chapter2/CMakeLists.txt | 1 + .../BuildingAJIT/Chapter2/KaleidoscopeJIT.h | 54 ++--- .../BuildingAJIT/Chapter3/KaleidoscopeJIT.h | 64 +++--- .../BuildingAJIT/Chapter4/KaleidoscopeJIT.h | 59 ++--- .../BuildingAJIT/Chapter5/KaleidoscopeJIT.h | 64 +++--- .../Kaleidoscope/Chapter4/CMakeLists.txt | 1 + .../Kaleidoscope/Chapter5/CMakeLists.txt | 1 + .../Kaleidoscope/Chapter6/CMakeLists.txt | 1 + .../Kaleidoscope/Chapter7/CMakeLists.txt | 1 + .../Kaleidoscope/include/KaleidoscopeJIT.h | 38 ++-- .../Orc/CompileOnDemandLayer.h | 126 +++++++--- .../llvm/ExecutionEngine/Orc/ExecutionUtils.h | 11 +- .../llvm/ExecutionEngine/Orc/IRCompileLayer.h | 7 +- .../ExecutionEngine/Orc/IRTransformLayer.h | 7 +- .../ExecutionEngine/Orc/LazyEmittingLayer.h | 17 +- .../include/llvm/ExecutionEngine/Orc/Legacy.h | 40 ++++ .../llvm/ExecutionEngine/Orc/NullResolver.h | 10 + .../Orc/ObjectTransformLayer.h | 6 +- .../Orc/RTDyldObjectLinkingLayer.h | 124 +++++----- llvm/lib/ExecutionEngine/Orc/Legacy.cpp | 19 +- llvm/lib/ExecutionEngine/Orc/NullResolver.cpp | 11 + .../ExecutionEngine/Orc/OrcCBindingsStack.h | 215 ++++++++++++------ .../ExecutionEngine/Orc/OrcMCJITReplacement.h | 92 ++++++-- llvm/tools/lli/OrcLazyJIT.h | 92 ++++++-- .../Orc/CompileOnDemandLayerTest.cpp | 17 +- .../Orc/LazyEmittingLayerTest.cpp | 10 +- .../Orc/ObjectTransformLayerTest.cpp | 43 ++-- .../Orc/RTDyldObjectLinkingLayerTest.cpp | 79 ++++--- 30 files changed, 818 insertions(+), 439 deletions(-) diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/CMakeLists.txt b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/CMakeLists.txt index 657a14be87d0..72c9668f7d3a 100644 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/CMakeLists.txt +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/CMakeLists.txt @@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS ExecutionEngine InstCombine Object + OrcJIT RuntimeDyld ScalarOpts Support diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h index ab675e3f7422..91709433d937 100644 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h @@ -38,6 +38,9 @@ namespace orc { class KaleidoscopeJIT { private: + SymbolStringPool SSP; + ExecutionSession ES; + std::shared_ptr Resolver; std::unique_ptr TM; const DataLayout DL; RTDyldObjectLinkingLayer ObjectLayer; @@ -47,8 +50,24 @@ public: using ModuleHandle = decltype(CompileLayer)::ModuleHandleT; KaleidoscopeJIT() - : TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()), - ObjectLayer([]() { return std::make_shared(); }), + : ES(SSP), + Resolver(createLegacyLookupResolver( + [this](const std::string &Name) -> JITSymbol { + if (auto Sym = CompileLayer.findSymbol(Name, false)) + return Sym; + else if (auto Err = Sym.takeError()) + return std::move(Err); + if (auto SymAddr = + RTDyldMemoryManager::getSymbolAddressInProcess(Name)) + return JITSymbol(SymAddr, JITSymbolFlags::Exported); + return nullptr; + }, + [](Error Err) { cantFail(std::move(Err), "lookupFlags failed"); })), + TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()), + ObjectLayer( + ES, + [](VModuleKey) { return std::make_shared(); }, + [this](VModuleKey K) { return Resolver; }), CompileLayer(ObjectLayer, SimpleCompiler(*TM)) { llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr); } @@ -56,27 +75,8 @@ public: TargetMachine &getTargetMachine() { return *TM; } ModuleHandle addModule(std::unique_ptr M) { - // Build our symbol resolver: - // Lambda 1: Look back into the JIT itself to find symbols that are part of - // the same "logical dylib". - // Lambda 2: Search for external symbols in the host process. - auto Resolver = createLambdaResolver( - [&](const std::string &Name) { - if (auto Sym = CompileLayer.findSymbol(Name, false)) - return Sym; - return JITSymbol(nullptr); - }, - [](const std::string &Name) { - if (auto SymAddr = - RTDyldMemoryManager::getSymbolAddressInProcess(Name)) - return JITSymbol(SymAddr, JITSymbolFlags::Exported); - return JITSymbol(nullptr); - }); - - // Add the set to the JIT with the resolver we created above and a newly - // created SectionMemoryManager. - return cantFail(CompileLayer.addModule(std::move(M), - std::move(Resolver))); + // Add the module to the JIT with a new VModuleKey. + return cantFail(CompileLayer.addModule(ES.allocateVModule(), std::move(M))); } JITSymbol findSymbol(const std::string Name) { diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/CMakeLists.txt b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/CMakeLists.txt index ea5bc05fa00a..ba6abd72d428 100644 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/CMakeLists.txt +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/CMakeLists.txt @@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS ExecutionEngine InstCombine Object + OrcJIT RuntimeDyld ScalarOpts Support diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h index 9a295f1566cb..4b7549391b9c 100644 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h @@ -42,6 +42,9 @@ namespace orc { class KaleidoscopeJIT { private: + SymbolStringPool SSP; + ExecutionSession ES; + std::shared_ptr Resolver; std::unique_ptr TM; const DataLayout DL; RTDyldObjectLinkingLayer ObjectLayer; @@ -56,40 +59,37 @@ public: using ModuleHandle = decltype(OptimizeLayer)::ModuleHandleT; KaleidoscopeJIT() - : TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()), - ObjectLayer([]() { return std::make_shared(); }), + : ES(SSP), + Resolver(createLegacyLookupResolver( + [this](const std::string &Name) -> JITSymbol { + if (auto Sym = OptimizeLayer.findSymbol(Name, false)) + return Sym; + else if (auto Err = Sym.takeError()) + return std::move(Err); + if (auto SymAddr = + RTDyldMemoryManager::getSymbolAddressInProcess(Name)) + return JITSymbol(SymAddr, JITSymbolFlags::Exported); + return nullptr; + }, + [](Error Err) { cantFail(std::move(Err), "lookupFlags failed"); })), + TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()), + ObjectLayer( + ES, + [](VModuleKey) { return std::make_shared(); }, + [this](VModuleKey K) { return Resolver; }), CompileLayer(ObjectLayer, SimpleCompiler(*TM)), - OptimizeLayer(CompileLayer, - [this](std::shared_ptr M) { - return optimizeModule(std::move(M)); - }) { + OptimizeLayer(CompileLayer, [this](std::shared_ptr M) { + return optimizeModule(std::move(M)); + }) { llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr); } TargetMachine &getTargetMachine() { return *TM; } ModuleHandle addModule(std::unique_ptr M) { - // Build our symbol resolver: - // Lambda 1: Look back into the JIT itself to find symbols that are part of - // the same "logical dylib". - // Lambda 2: Search for external symbols in the host process. - auto Resolver = createLambdaResolver( - [&](const std::string &Name) { - if (auto Sym = OptimizeLayer.findSymbol(Name, false)) - return Sym; - return JITSymbol(nullptr); - }, - [](const std::string &Name) { - if (auto SymAddr = - RTDyldMemoryManager::getSymbolAddressInProcess(Name)) - return JITSymbol(SymAddr, JITSymbolFlags::Exported); - return JITSymbol(nullptr); - }); - - // Add the set to the JIT with the resolver we created above and a newly - // created SectionMemoryManager. - return cantFail(OptimizeLayer.addModule(std::move(M), - std::move(Resolver))); + // Add the module to the JIT with a new VModuleKey. + return cantFail( + OptimizeLayer.addModule(ES.allocateVModule(), std::move(M))); } JITSymbol findSymbol(const std::string Name) { diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h index a03f5ce5e238..43de6d9ef567 100644 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h @@ -17,15 +17,15 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/JITSymbol.h" -#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" -#include "llvm/ExecutionEngine/RuntimeDyld.h" -#include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h" #include "llvm/ExecutionEngine/Orc/CompileUtils.h" #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" #include "llvm/ExecutionEngine/Orc/IRTransformLayer.h" #include "llvm/ExecutionEngine/Orc/LambdaResolver.h" #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Mangler.h" @@ -35,6 +35,7 @@ #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Scalar/GVN.h" #include +#include #include #include #include @@ -45,6 +46,9 @@ namespace orc { class KaleidoscopeJIT { private: + SymbolStringPool SSP; + ExecutionSession ES; + std::map> Resolvers; std::unique_ptr TM; const DataLayout DL; RTDyldObjectLinkingLayer ObjectLayer; @@ -62,8 +66,11 @@ public: using ModuleHandle = decltype(CODLayer)::ModuleHandleT; KaleidoscopeJIT() - : TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()), - ObjectLayer([]() { return std::make_shared(); }), + : ES(SSP), TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()), + ObjectLayer( + ES, + [](VModuleKey) { return std::make_shared(); }, + [&](orc::VModuleKey K) { return Resolvers[K]; }), CompileLayer(ObjectLayer, SimpleCompiler(*TM)), OptimizeLayer(CompileLayer, [this](std::shared_ptr M) { @@ -71,37 +78,40 @@ public: }), CompileCallbackManager( orc::createLocalCompileCallbackManager(TM->getTargetTriple(), 0)), - CODLayer(OptimizeLayer, - [](Function &F) { return std::set({&F}); }, + CODLayer(ES, OptimizeLayer, + [&](orc::VModuleKey K) { return Resolvers[K]; }, + [&](orc::VModuleKey K, std::shared_ptr R) { + Resolvers[K] = std::move(R); + }, + [](Function &F) { return std::set({&F}); }, *CompileCallbackManager, orc::createLocalIndirectStubsManagerBuilder( - TM->getTargetTriple())) { + TM->getTargetTriple())) { llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr); } TargetMachine &getTargetMachine() { return *TM; } ModuleHandle addModule(std::unique_ptr M) { - // Build our symbol resolver: - // Lambda 1: Look back into the JIT itself to find symbols that are part of - // the same "logical dylib". - // Lambda 2: Search for external symbols in the host process. - auto Resolver = createLambdaResolver( - [&](const std::string &Name) { - if (auto Sym = CODLayer.findSymbol(Name, false)) - return Sym; - return JITSymbol(nullptr); - }, - [](const std::string &Name) { - if (auto SymAddr = - RTDyldMemoryManager::getSymbolAddressInProcess(Name)) - return JITSymbol(SymAddr, JITSymbolFlags::Exported); - return JITSymbol(nullptr); - }); + // Create a new VModuleKey. + VModuleKey K = ES.allocateVModule(); - // Add the set to the JIT with the resolver we created above and a newly - // created SectionMemoryManager. - return cantFail(CODLayer.addModule(std::move(M), std::move(Resolver))); + // Build a resolver and associate it with the new key. + Resolvers[K] = createLegacyLookupResolver( + [this](const std::string &Name) -> JITSymbol { + if (auto Sym = CompileLayer.findSymbol(Name, false)) + return Sym; + else if (auto Err = Sym.takeError()) + return std::move(Err); + if (auto SymAddr = + RTDyldMemoryManager::getSymbolAddressInProcess(Name)) + return JITSymbol(SymAddr, JITSymbolFlags::Exported); + return nullptr; + }, + [](Error Err) { cantFail(std::move(Err), "lookupFlags failed"); }); + + // Add the module to the JIT with the new key. + return cantFail(CODLayer.addModule(K, std::move(M))); } JITSymbol findSymbol(const std::string Name) { diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h index 841ea74fb98a..a95efd4ba822 100644 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h @@ -17,14 +17,14 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/JITSymbol.h" -#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" -#include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/ExecutionEngine/Orc/CompileUtils.h" -#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" #include "llvm/ExecutionEngine/Orc/IRTransformLayer.h" +#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" #include "llvm/ExecutionEngine/Orc/LambdaResolver.h" #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Mangler.h" @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -71,6 +72,9 @@ namespace orc { class KaleidoscopeJIT { private: + SymbolStringPool SSP; + ExecutionSession ES; + std::shared_ptr Resolver; std::unique_ptr TM; const DataLayout DL; RTDyldObjectLinkingLayer ObjectLayer; @@ -88,9 +92,26 @@ public: using ModuleHandle = decltype(OptimizeLayer)::ModuleHandleT; KaleidoscopeJIT() - : TM(EngineBuilder().selectTarget()), - DL(TM->createDataLayout()), - ObjectLayer([]() { return std::make_shared(); }), + : ES(SSP), + Resolver(createLegacyLookupResolver( + [this](const std::string &Name) -> JITSymbol { + if (auto Sym = IndirectStubsMgr->findStub(Name, false)) + return Sym; + if (auto Sym = OptimizeLayer.findSymbol(Name, false)) + return Sym; + else if (auto Err = Sym.takeError()) + return std::move(Err); + if (auto SymAddr = + RTDyldMemoryManager::getSymbolAddressInProcess(Name)) + return JITSymbol(SymAddr, JITSymbolFlags::Exported); + return nullptr; + }, + [](Error Err) { cantFail(std::move(Err), "lookupFlags failed"); })), + TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()), + ObjectLayer( + ES, + [](VModuleKey) { return std::make_shared(); }, + [&](VModuleKey K) { return Resolver; }), CompileLayer(ObjectLayer, SimpleCompiler(*TM)), OptimizeLayer(CompileLayer, [this](std::shared_ptr M) { @@ -107,29 +128,9 @@ public: TargetMachine &getTargetMachine() { return *TM; } ModuleHandle addModule(std::unique_ptr M) { - // Build our symbol resolver: - // Lambda 1: Look back into the JIT itself to find symbols that are part of - // the same "logical dylib". - // Lambda 2: Search for external symbols in the host process. - auto Resolver = createLambdaResolver( - [&](const std::string &Name) { - if (auto Sym = IndirectStubsMgr->findStub(Name, false)) - return Sym; - if (auto Sym = OptimizeLayer.findSymbol(Name, false)) - return Sym; - return JITSymbol(nullptr); - }, - [](const std::string &Name) { - if (auto SymAddr = - RTDyldMemoryManager::getSymbolAddressInProcess(Name)) - return JITSymbol(SymAddr, JITSymbolFlags::Exported); - return JITSymbol(nullptr); - }); - - // Add the set to the JIT with the resolver we created above and a newly - // created SectionMemoryManager. - return cantFail(OptimizeLayer.addModule(std::move(M), - std::move(Resolver))); + // Add the module to the JIT with a new VModuleKey. + return cantFail( + OptimizeLayer.addModule(ES.allocateVModule(), std::move(M))); } Error addFunctionAST(std::unique_ptr FnAST) { diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h index 8990a67feb72..2e9f5c3b37f0 100644 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h @@ -15,18 +15,18 @@ #define LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H #include "RemoteJITUtils.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Triple.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/CompileUtils.h" -#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" #include "llvm/ExecutionEngine/Orc/IRTransformLayer.h" +#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" #include "llvm/ExecutionEngine/Orc/LambdaResolver.h" -#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" #include "llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h" +#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Mangler.h" @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -76,6 +77,9 @@ using MyRemote = remote::OrcRemoteTargetClient; class KaleidoscopeJIT { private: + SymbolStringPool SSP; + ExecutionSession ES; + std::shared_ptr Resolver; std::unique_ptr TM; const DataLayout DL; RTDyldObjectLinkingLayer ObjectLayer; @@ -94,12 +98,28 @@ public: using ModuleHandle = decltype(OptimizeLayer)::ModuleHandleT; KaleidoscopeJIT(MyRemote &Remote) - : TM(EngineBuilder().selectTarget(Triple(Remote.getTargetTriple()), "", + : ES(SSP), + Resolver(createLegacyLookupResolver( + [this](const std::string &Name) -> JITSymbol { + if (auto Sym = IndirectStubsMgr->findStub(Name, false)) + return Sym; + if (auto Sym = OptimizeLayer.findSymbol(Name, false)) + return Sym; + else if (auto Err = Sym.takeError()) + return std::move(Err); + if (auto Addr = cantFail(this->Remote.getSymbolAddress(Name))) + return JITSymbol(Addr, JITSymbolFlags::Exported); + return nullptr; + }, + [](Error Err) { cantFail(std::move(Err), "lookupFlags failed"); })), + TM(EngineBuilder().selectTarget(Triple(Remote.getTargetTriple()), "", "", SmallVector())), DL(TM->createDataLayout()), - ObjectLayer([&Remote]() { - return cantFail(Remote.createRemoteMemoryManager()); - }), + ObjectLayer(ES, + [&Remote](VModuleKey) { + return cantFail(Remote.createRemoteMemoryManager()); + }, + [this](VModuleKey) { return Resolver; }), CompileLayer(ObjectLayer, SimpleCompiler(*TM)), OptimizeLayer(CompileLayer, [this](std::shared_ptr M) { @@ -120,33 +140,9 @@ public: TargetMachine &getTargetMachine() { return *TM; } ModuleHandle addModule(std::unique_ptr M) { - // Build our symbol resolver: - // Lambda 1: Look back into the JIT itself to find symbols that are part of - // the same "logical dylib". - // Lambda 2: Search for external symbols in the host process. - auto Resolver = createLambdaResolver( - [&](const std::string &Name) { - if (auto Sym = IndirectStubsMgr->findStub(Name, false)) - return Sym; - if (auto Sym = OptimizeLayer.findSymbol(Name, false)) - return Sym; - return JITSymbol(nullptr); - }, - [&](const std::string &Name) { - if (auto AddrOrErr = Remote.getSymbolAddress(Name)) - return JITSymbol(*AddrOrErr, JITSymbolFlags::Exported); - else { - logAllUnhandledErrors(AddrOrErr.takeError(), errs(), - "Error resolving remote symbol:"); - exit(1); - } - return JITSymbol(nullptr); - }); - - // Add the set to the JIT with the resolver we created above and a newly - // created SectionMemoryManager. - return cantFail(OptimizeLayer.addModule(std::move(M), - std::move(Resolver))); + // Add the module with a new VModuleKey. + return cantFail( + OptimizeLayer.addModule(ES.allocateVModule(), std::move(M))); } Error addFunctionAST(std::unique_ptr FnAST) { diff --git a/llvm/examples/Kaleidoscope/Chapter4/CMakeLists.txt b/llvm/examples/Kaleidoscope/Chapter4/CMakeLists.txt index 89feed143adc..fdc083e07681 100644 --- a/llvm/examples/Kaleidoscope/Chapter4/CMakeLists.txt +++ b/llvm/examples/Kaleidoscope/Chapter4/CMakeLists.txt @@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS ExecutionEngine InstCombine Object + OrcJIT RuntimeDyld ScalarOpts Support diff --git a/llvm/examples/Kaleidoscope/Chapter5/CMakeLists.txt b/llvm/examples/Kaleidoscope/Chapter5/CMakeLists.txt index c0ae70654c36..757d901ef525 100644 --- a/llvm/examples/Kaleidoscope/Chapter5/CMakeLists.txt +++ b/llvm/examples/Kaleidoscope/Chapter5/CMakeLists.txt @@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS ExecutionEngine InstCombine Object + OrcJIT RuntimeDyld ScalarOpts Support diff --git a/llvm/examples/Kaleidoscope/Chapter6/CMakeLists.txt b/llvm/examples/Kaleidoscope/Chapter6/CMakeLists.txt index 49627f07ddf0..ad50928a346c 100644 --- a/llvm/examples/Kaleidoscope/Chapter6/CMakeLists.txt +++ b/llvm/examples/Kaleidoscope/Chapter6/CMakeLists.txt @@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS ExecutionEngine InstCombine Object + OrcJIT RuntimeDyld ScalarOpts Support diff --git a/llvm/examples/Kaleidoscope/Chapter7/CMakeLists.txt b/llvm/examples/Kaleidoscope/Chapter7/CMakeLists.txt index 69e78be6a620..03220358ab71 100644 --- a/llvm/examples/Kaleidoscope/Chapter7/CMakeLists.txt +++ b/llvm/examples/Kaleidoscope/Chapter7/CMakeLists.txt @@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS ExecutionEngine InstCombine Object + OrcJIT RuntimeDyld ScalarOpts Support diff --git a/llvm/examples/Kaleidoscope/include/KaleidoscopeJIT.h b/llvm/examples/Kaleidoscope/include/KaleidoscopeJIT.h index 215ce03af99b..a1cbe0267bab 100644 --- a/llvm/examples/Kaleidoscope/include/KaleidoscopeJIT.h +++ b/llvm/examples/Kaleidoscope/include/KaleidoscopeJIT.h @@ -14,22 +14,23 @@ #ifndef LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H #define LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/JITSymbol.h" -#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" -#include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/ExecutionEngine/Orc/CompileUtils.h" #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" #include "llvm/ExecutionEngine/Orc/LambdaResolver.h" #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Mangler.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetMachine.h" #include +#include #include #include #include @@ -44,8 +45,17 @@ public: using ModuleHandleT = CompileLayerT::ModuleHandleT; KaleidoscopeJIT() - : TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()), - ObjectLayer([]() { return std::make_shared(); }), + : ES(SSP), + Resolver(createLegacyLookupResolver( + [this](const std::string &Name) { + return ObjectLayer.findSymbol(Name, true); + }, + [](Error Err) { cantFail(std::move(Err), "lookupFlags failed"); })), + TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()), + ObjectLayer( + ES, + [](VModuleKey) { return std::make_shared(); }, + [this](VModuleKey) { return Resolver; }), CompileLayer(ObjectLayer, SimpleCompiler(*TM)) { llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr); } @@ -53,19 +63,8 @@ public: TargetMachine &getTargetMachine() { return *TM; } ModuleHandleT addModule(std::unique_ptr M) { - // 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 Resolver = createLambdaResolver( - [&](const std::string &Name) { - if (auto Sym = findMangledSymbol(Name)) - return Sym; - return JITSymbol(nullptr); - }, - [](const std::string &S) { return nullptr; }); - auto H = cantFail(CompileLayer.addModule(std::move(M), - std::move(Resolver))); - + auto H = + cantFail(CompileLayer.addModule(ES.allocateVModule(), std::move(M))); ModuleHandles.push_back(H); return H; } @@ -127,6 +126,9 @@ private: return nullptr; } + SymbolStringPool SSP; + ExecutionSession ES; + std::shared_ptr Resolver; std::unique_ptr TM; const DataLayout DL; ObjLayerT ObjectLayer; diff --git a/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h index 3281c354676c..1daff438b685 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h @@ -20,6 +20,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/Orc/Core.h" #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" #include "llvm/ExecutionEngine/Orc/LambdaResolver.h" #include "llvm/ExecutionEngine/Orc/OrcError.h" @@ -138,8 +139,6 @@ private: }; struct LogicalDylib { - using SymbolResolverFtor = std::function; - struct SourceModuleEntry { std::shared_ptr SourceMod; std::set StubsToClone; @@ -183,7 +182,8 @@ private: return Error::success(); } - std::shared_ptr ExternalSymbolResolver; + VModuleKey K; + std::shared_ptr BackingResolver; std::unique_ptr StubsMgr; StaticGlobalRenamer StaticRenamer; SourceModulesList SourceModules; @@ -204,13 +204,24 @@ public: using IndirectStubsManagerBuilderT = std::function()>; + using SymbolResolverGetter = + std::function(VModuleKey K)>; + + using SymbolResolverSetter = + std::function R)>; + /// @brief Construct a compile-on-demand layer instance. - CompileOnDemandLayer(BaseLayerT &BaseLayer, PartitioningFtor Partition, + CompileOnDemandLayer(ExecutionSession &ES, BaseLayerT &BaseLayer, + SymbolResolverGetter GetSymbolResolver, + SymbolResolverSetter SetSymbolResolver, + PartitioningFtor Partition, CompileCallbackMgrT &CallbackMgr, IndirectStubsManagerBuilderT CreateIndirectStubsManager, bool CloneStubsIntoPartitions = true) - : BaseLayer(BaseLayer), Partition(std::move(Partition)), - CompileCallbackMgr(CallbackMgr), + : ES(ES), BaseLayer(BaseLayer), + GetSymbolResolver(std::move(GetSymbolResolver)), + SetSymbolResolver(std::move(SetSymbolResolver)), + Partition(std::move(Partition)), CompileCallbackMgr(CallbackMgr), CreateIndirectStubsManager(std::move(CreateIndirectStubsManager)), CloneStubsIntoPartitions(CloneStubsIntoPartitions) {} @@ -221,16 +232,14 @@ public: } /// @brief Add a module to the compile-on-demand layer. - Expected - addModule(std::shared_ptr M, - std::shared_ptr Resolver) { + Expected addModule(VModuleKey K, std::shared_ptr M) { LogicalDylibs.push_back(LogicalDylib()); auto &LD = LogicalDylibs.back(); - LD.ExternalSymbolResolver = std::move(Resolver); + LD.K = std::move(K); LD.StubsMgr = CreateIndirectStubsManager(); + LD.BackingResolver = GetSymbolResolver(LD.K); - // Process each of the modules in this module set. if (auto Err = addLogicalModule(LD, std::move(M))) return std::move(Err); @@ -454,22 +463,46 @@ private: return MaterializerErrors; // Build a resolver for the globals module and add it to the base layer. - auto GVsResolver = createLambdaResolver( - [this, &LD](const std::string &Name) -> JITSymbol { - if (auto Sym = LD.StubsMgr->findStub(Name, false)) - return Sym; - if (auto Sym = LD.findSymbol(BaseLayer, Name, false)) - return Sym; - else if (auto Err = Sym.takeError()) - return std::move(Err); - return LD.ExternalSymbolResolver->findSymbolInLogicalDylib(Name); + auto LegacyLookup = [this, &LD](const std::string &Name) -> JITSymbol { + if (auto Sym = LD.StubsMgr->findStub(Name, false)) + return Sym; + else if (auto Err = Sym.takeError()) + return std::move(Err); + + if (auto Sym = LD.findSymbol(BaseLayer, Name, false)) + return Sym; + else if (auto Err = Sym.takeError()) + return std::move(Err); + + return nullptr; + }; + + auto GVsResolver = createSymbolResolver( + [this, &LD, LegacyLookup](SymbolFlagsMap &SymbolFlags, + const SymbolNameSet &Symbols) { + auto NotFoundViaLegacyLookup = + lookupFlagsWithLegacyFn(SymbolFlags, Symbols, LegacyLookup); + + if (!NotFoundViaLegacyLookup) { + logAllUnhandledErrors(NotFoundViaLegacyLookup.takeError(), errs(), + "CODLayer/GVsResolver flags lookup failed: "); + SymbolFlags.clear(); + return SymbolNameSet(); + } + + return LD.BackingResolver->lookupFlags(SymbolFlags, + *NotFoundViaLegacyLookup); }, - [&LD](const std::string &Name) { - return LD.ExternalSymbolResolver->findSymbol(Name); + [&LD, LegacyLookup](AsynchronousSymbolQuery &Query, + SymbolNameSet Symbols) { + auto NotFoundViaLegacyLookup = + lookupWithLegacyFn(Query, Symbols, LegacyLookup); + return LD.BackingResolver->lookup(Query, NotFoundViaLegacyLookup); }); - if (auto GVsHOrErr = - BaseLayer.addModule(std::move(GVsM), std::move(GVsResolver))) + SetSymbolResolver(LD.K, std::move(GVsResolver)); + + if (auto GVsHOrErr = BaseLayer.addModule(LD.K, std::move(GVsM))) LD.BaseLayerHandles.push_back(*GVsHOrErr); else return GVsHOrErr.takeError(); @@ -596,23 +629,42 @@ private: for (auto *F : Part) moveFunctionBody(*F, VMap, &Materializer); - // Create memory manager and symbol resolver. - auto Resolver = createLambdaResolver( - [this, &LD](const std::string &Name) -> JITSymbol { - if (auto Sym = LD.findSymbol(BaseLayer, Name, false)) - return Sym; - else if (auto Err = Sym.takeError()) - return std::move(Err); - return LD.ExternalSymbolResolver->findSymbolInLogicalDylib(Name); - }, - [&LD](const std::string &Name) { - return LD.ExternalSymbolResolver->findSymbol(Name); - }); + auto K = ES.allocateVModule(); - return BaseLayer.addModule(std::move(M), std::move(Resolver)); + auto LegacyLookup = [this, &LD](const std::string &Name) -> JITSymbol { + return LD.findSymbol(BaseLayer, Name, false); + }; + + // Create memory manager and symbol resolver. + auto Resolver = createSymbolResolver( + [this, &LD, LegacyLookup](SymbolFlagsMap &SymbolFlags, + const SymbolNameSet &Symbols) { + auto NotFoundViaLegacyLookup = + lookupFlagsWithLegacyFn(SymbolFlags, Symbols, LegacyLookup); + if (!NotFoundViaLegacyLookup) { + logAllUnhandledErrors(NotFoundViaLegacyLookup.takeError(), errs(), + "CODLayer/SubResolver flags lookup failed: "); + SymbolFlags.clear(); + return SymbolNameSet(); + } + return LD.BackingResolver->lookupFlags(SymbolFlags, + *NotFoundViaLegacyLookup); + }, + [&LD, LegacyLookup](AsynchronousSymbolQuery &Q, SymbolNameSet Symbols) { + auto NotFoundViaLegacyLookup = + lookupWithLegacyFn(Q, Symbols, LegacyLookup); + return LD.BackingResolver->lookup(Q, + std::move(NotFoundViaLegacyLookup)); + }); + SetSymbolResolver(K, std::move(Resolver)); + + return BaseLayer.addModule(std::move(K), std::move(M)); } + ExecutionSession &ES; BaseLayerT &BaseLayer; + SymbolResolverGetter GetSymbolResolver; + SymbolResolverSetter SetSymbolResolver; PartitioningFtor Partition; CompileCallbackMgrT &CompileCallbackMgr; IndirectStubsManagerBuilderT CreateIndirectStubsManager; diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h index d9b45c6a1e29..22071ff0cb04 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h @@ -104,20 +104,27 @@ public: Error runViaLayer(JITLayerT &JITLayer) const { using CtorDtorTy = void (*)(); - for (const auto &CtorDtorName : CtorDtorNames) + for (const auto &CtorDtorName : CtorDtorNames) { + dbgs() << "Searching for ctor/dtor: " << CtorDtorName << "..."; if (auto CtorDtorSym = JITLayer.findSymbolIn(H, CtorDtorName, false)) { + dbgs() << " found symbol..."; if (auto AddrOrErr = CtorDtorSym.getAddress()) { + dbgs() << " at addr " << format("0x%016x", *AddrOrErr) << "\n"; CtorDtorTy CtorDtor = reinterpret_cast(static_cast(*AddrOrErr)); CtorDtor(); - } else + } else { + dbgs() << " failed materialization!\n"; return AddrOrErr.takeError(); + } } else { + dbgs() << " failed to find symbol..."; if (auto Err = CtorDtorSym.takeError()) return Err; else return make_error(CtorDtorName); } + } return Error::success(); } diff --git a/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h index fadd334bed0f..94a3086a4eea 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h @@ -16,6 +16,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/Orc/Core.h" #include "llvm/Support/Error.h" #include #include @@ -50,12 +51,10 @@ public: /// along with the given memory manager and symbol resolver. /// /// @return A handle for the added module. - Expected - addModule(std::shared_ptr M, - std::shared_ptr Resolver) { + Expected addModule(VModuleKey K, std::shared_ptr M) { using CompileResult = decltype(Compile(*M)); auto Obj = std::make_shared(Compile(*M)); - return BaseLayer.addObject(std::move(Obj), std::move(Resolver)); + return BaseLayer.addObject(std::move(K), std::move(Obj)); } /// @brief Remove the module associated with the handle H. diff --git a/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h index 476061afda59..31de6f1cd5cb 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h @@ -15,6 +15,7 @@ #define LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H #include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/Orc/Core.h" #include #include @@ -42,10 +43,8 @@ public: /// the layer below, along with the memory manager and symbol resolver. /// /// @return A handle for the added modules. - Expected - addModule(std::shared_ptr M, - std::shared_ptr Resolver) { - return BaseLayer.addModule(Transform(std::move(M)), std::move(Resolver)); + Expected addModule(VModuleKey K, std::shared_ptr M) { + return BaseLayer.addModule(std::move(K), Transform(std::move(M))); } /// @brief Remove the module associated with the handle H. diff --git a/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h index b7e462e85d9d..0da6e0135b77 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h @@ -18,6 +18,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/Orc/Core.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" @@ -46,9 +47,8 @@ public: private: class EmissionDeferredModule { public: - EmissionDeferredModule(std::shared_ptr M, - std::shared_ptr Resolver) - : M(std::move(M)), Resolver(std::move(Resolver)) {} + EmissionDeferredModule(VModuleKey K, std::shared_ptr M) + : K(std::move(K)), M(std::move(M)) {} JITSymbol find(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) { switch (EmitState) { @@ -139,7 +139,7 @@ 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.addModule(std::move(M), std::move(Resolver)); + return BaseLayer.addModule(std::move(K), std::move(M)); } // If the mangled name of the given GlobalValue matches the given search @@ -193,8 +193,8 @@ private: enum { NotEmitted, Emitting, Emitted } EmitState = NotEmitted; BaseLayerHandleT Handle; + VModuleKey K; std::shared_ptr M; - std::shared_ptr Resolver; mutable std::unique_ptr> MangledSymbols; }; @@ -212,13 +212,10 @@ public: LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {} /// @brief Add the given module to the lazy emitting layer. - Expected - addModule(std::shared_ptr M, - std::shared_ptr Resolver) { + Expected addModule(VModuleKey K, std::shared_ptr M) { return ModuleList.insert( ModuleList.end(), - llvm::make_unique(std::move(M), - std::move(Resolver))); + llvm::make_unique(std::move(K), std::move(M))); } /// @brief Remove the module represented by the given handle. diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Legacy.h b/llvm/include/llvm/ExecutionEngine/Orc/Legacy.h index e04ef93a9629..ab495c6cebd3 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/Legacy.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/Legacy.h @@ -92,6 +92,46 @@ SymbolNameSet lookupWithLegacyFn(AsynchronousSymbolQuery &Query, return SymbolsNotFound; } +/// @brief An ORC SymbolResolver implementation that uses a legacy +/// findSymbol-like function to perform lookup; +template +class LegacyLookupFnResolver final : public SymbolResolver { +public: + using ErrorReporter = std::function; + + LegacyLookupFnResolver(LegacyLookupFn LegacyLookup, ErrorReporter ReportError) + : LegacyLookup(std::move(LegacyLookup)), + ReportError(std::move(ReportError)) {} + + SymbolNameSet lookupFlags(SymbolFlagsMap &Flags, + const SymbolNameSet &Symbols) final { + if (auto RemainingSymbols = + lookupFlagsWithLegacyFn(Flags, Symbols, LegacyLookup)) + return std::move(*RemainingSymbols); + else { + ReportError(RemainingSymbols.takeError()); + return Symbols; + } + } + + SymbolNameSet lookup(AsynchronousSymbolQuery &Query, + SymbolNameSet Symbols) final { + return lookupWithLegacyFn(Query, Symbols, LegacyLookup); + } + +private: + LegacyLookupFn LegacyLookup; + ErrorReporter ReportError; +}; + +template +std::shared_ptr> +createLegacyLookupResolver(LegacyLookupFn LegacyLookup, + std::function ErrorReporter) { + return std::make_shared>( + std::move(LegacyLookup), std::move(ErrorReporter)); +}; + } // End namespace orc } // End namespace llvm diff --git a/llvm/include/llvm/ExecutionEngine/Orc/NullResolver.h b/llvm/include/llvm/ExecutionEngine/Orc/NullResolver.h index e946b909eff3..982bd868e763 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/NullResolver.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/NullResolver.h @@ -15,11 +15,21 @@ #ifndef LLVM_EXECUTIONENGINE_ORC_NULLRESOLVER_H #define LLVM_EXECUTIONENGINE_ORC_NULLRESOLVER_H +#include "llvm/ExecutionEngine/Orc/Core.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" namespace llvm { namespace orc { +class NullResolver : public SymbolResolver { +public: + SymbolNameSet lookupFlags(SymbolFlagsMap &Flags, + const SymbolNameSet &Symbols) override; + + SymbolNameSet lookup(AsynchronousSymbolQuery &Query, + SymbolNameSet Symbols) override; +}; + /// SymbolResolver impliementation that rejects all resolution requests. /// Useful for clients that have no cross-object fixups. class NullLegacyResolver : public LegacyJITSymbolResolver { diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h index cb47e7520b1a..46bf21437c94 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h @@ -15,6 +15,7 @@ #define LLVM_EXECUTIONENGINE_ORC_OBJECTTRANSFORMLAYER_H #include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/Orc/Core.h" #include #include #include @@ -44,9 +45,8 @@ public: /// /// @return A handle for the added objects. template - Expected addObject(ObjectPtr Obj, - std::shared_ptr Resolver) { - return BaseLayer.addObject(Transform(std::move(Obj)), std::move(Resolver)); + Expected addObject(VModuleKey K, ObjectPtr Obj) { + return BaseLayer.addObject(std::move(K), Transform(std::move(Obj))); } /// @brief Remove the object set associated with the handle H. diff --git a/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h index 246c57341f35..073d48e09d5d 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h @@ -18,6 +18,8 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/Orc/Core.h" +#include "llvm/ExecutionEngine/Orc/Legacy.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Error.h" @@ -55,7 +57,7 @@ protected: void operator=(const LinkedObject&) = delete; virtual ~LinkedObject() = default; - virtual void finalize() = 0; + virtual Error finalize() = 0; virtual JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name) = 0; @@ -107,21 +109,17 @@ public: using NotifyFinalizedFtor = std::function; private: - - - template + template class ConcreteLinkedObject : public LinkedObject { public: - ConcreteLinkedObject(ObjectPtr Obj, MemoryManagerPtrT MemMgr, - SymbolResolverPtrT Resolver, - FinalizerFtor Finalizer, - bool ProcessAllSections) - : MemMgr(std::move(MemMgr)), - PFC(llvm::make_unique(std::move(Obj), - std::move(Resolver), - std::move(Finalizer), - ProcessAllSections)) { + ConcreteLinkedObject(ExecutionSession &ES, ObjectPtr Obj, + MemoryManagerPtrT MemMgr, + std::shared_ptr Resolver, + FinalizerFtor Finalizer, bool ProcessAllSections) + : MemMgr(std::move(MemMgr)), + PFC(llvm::make_unique( + ES, std::move(Obj), std::move(Resolver), std::move(Finalizer), + ProcessAllSections)) { buildInitialSymbolTable(PFC->Obj); } @@ -133,32 +131,32 @@ private: PFC->Handle = H; } - void finalize() override { + Error finalize() override { assert(PFC && "mapSectionAddress called on finalized LinkedObject"); - RuntimeDyld RTDyld(*MemMgr, *PFC->Resolver); + JITSymbolResolverAdapter ResolverAdapter(PFC->ES, *PFC->Resolver); + RuntimeDyld RTDyld(*MemMgr, ResolverAdapter); RTDyld.setProcessAllSections(PFC->ProcessAllSections); PFC->RTDyld = &RTDyld; this->Finalized = true; - PFC->Finalizer(PFC->Handle, RTDyld, std::move(PFC->Obj), - [&]() { - this->updateSymbolTable(RTDyld); - }); + auto Err = PFC->Finalizer(PFC->Handle, RTDyld, std::move(PFC->Obj), + [&]() { this->updateSymbolTable(RTDyld); }); // Release resources. PFC = nullptr; + return Err; } JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name) override { - return - [this, Name]() { - // The symbol may be materialized between the creation of this lambda - // and its execution, so we need to double check. - if (!this->Finalized) - this->finalize(); - return this->getSymbol(Name, false).getAddress(); - }; + return [this, Name]() -> Expected { + // The symbol may be materialized between the creation of this lambda + // and its execution, so we need to double check. + if (!this->Finalized) + if (auto Err = this->finalize()) + return std::move(Err); + return this->getSymbol(Name, false).getAddress(); + }; } void mapSectionAddress(const void *LocalAddress, @@ -194,14 +192,16 @@ private: // Contains the information needed prior to finalization: the object files, // memory manager, resolver, and flags needed for RuntimeDyld. struct PreFinalizeContents { - PreFinalizeContents(ObjectPtr Obj, SymbolResolverPtrT Resolver, + PreFinalizeContents(ExecutionSession &ES, ObjectPtr Obj, + std::shared_ptr Resolver, FinalizerFtor Finalizer, bool ProcessAllSections) - : Obj(std::move(Obj)), Resolver(std::move(Resolver)), - Finalizer(std::move(Finalizer)), - ProcessAllSections(ProcessAllSections) {} + : ES(ES), Obj(std::move(Obj)), Resolver(std::move(Resolver)), + Finalizer(std::move(Finalizer)), + ProcessAllSections(ProcessAllSections) {} + ExecutionSession &ES; ObjectPtr Obj; - SymbolResolverPtrT Resolver; + std::shared_ptr Resolver; FinalizerFtor Finalizer; bool ProcessAllSections; ObjHandleT Handle; @@ -212,17 +212,14 @@ private: std::unique_ptr PFC; }; - template - std::unique_ptr< - ConcreteLinkedObject> - createLinkedObject(ObjectPtr Obj, MemoryManagerPtrT MemMgr, - SymbolResolverPtrT Resolver, - FinalizerFtor Finalizer, - bool ProcessAllSections) { - using LOS = ConcreteLinkedObject; - return llvm::make_unique(std::move(Obj), std::move(MemMgr), + template + std::unique_ptr> + createLinkedObject(ExecutionSession &ES, ObjectPtr Obj, + MemoryManagerPtrT MemMgr, + std::shared_ptr Resolver, + FinalizerFtor Finalizer, bool ProcessAllSections) { + using LOS = ConcreteLinkedObject; + return llvm::make_unique(ES, std::move(Obj), std::move(MemMgr), std::move(Resolver), std::move(Finalizer), ProcessAllSections); } @@ -231,18 +228,23 @@ public: /// @brief Functor for creating memory managers. using MemoryManagerGetter = - std::function()>; + std::function(VModuleKey)>; + + using ResolverGetter = + std::function(VModuleKey)>; /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded, /// and NotifyFinalized functors. RTDyldObjectLinkingLayer( - MemoryManagerGetter GetMemMgr, + ExecutionSession &ES, MemoryManagerGetter GetMemMgr, + ResolverGetter GetResolver, NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(), NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor()) - : GetMemMgr(GetMemMgr), + : ES(ES), GetMemMgr(std::move(GetMemMgr)), + GetResolver(std::move(GetResolver)), NotifyLoaded(std::move(NotifyLoaded)), - NotifyFinalized(std::move(NotifyFinalized)), - ProcessAllSections(false) {} + NotifyFinalized(std::move(NotifyFinalized)), ProcessAllSections(false) { + } /// @brief Set the 'ProcessAllSections' flag. /// @@ -258,11 +260,10 @@ public: /// /// @return A handle that can be used to refer to the loaded object (for /// symbol searching, finalization, freeing memory, etc.). - Expected addObject(ObjectPtr Obj, - std::shared_ptr Resolver) { + Expected addObject(VModuleKey K, ObjectPtr Obj) { auto Finalizer = [&](ObjHandleT H, RuntimeDyld &RTDyld, const ObjectPtr &ObjToLoad, - std::function LOSHandleLoad) { + std::function LOSHandleLoad) -> Error { std::unique_ptr Info = RTDyld.loadObject(*ObjToLoad->getBinary()); @@ -273,14 +274,19 @@ public: RTDyld.finalizeWithMemoryManagerLocking(); + if (RTDyld.hasError()) + return make_error(RTDyld.getErrorString(), + inconvertibleErrorCode()); + if (this->NotifyFinalized) this->NotifyFinalized(H); + + return Error::success(); }; auto LO = - createLinkedObject(std::move(Obj), GetMemMgr(), - std::move(Resolver), std::move(Finalizer), - ProcessAllSections); + createLinkedObject(ES, std::move(Obj), GetMemMgr(K), GetResolver(K), + std::move(Finalizer), ProcessAllSections); // LOS is an owning-ptr. Keep a non-owning one so that we can set the handle // below. auto *LOPtr = LO.get(); @@ -339,15 +345,13 @@ public: /// @brief Immediately emit and finalize the object represented by the given /// handle. /// @param H Handle for object to emit/finalize. - Error emitAndFinalize(ObjHandleT H) { - (*H)->finalize(); - return Error::success(); - } + Error emitAndFinalize(ObjHandleT H) { return (*H)->finalize(); } private: - + ExecutionSession &ES; LinkedObjectListT LinkedObjList; MemoryManagerGetter GetMemMgr; + ResolverGetter GetResolver; NotifyLoadedFtor NotifyLoaded; NotifyFinalizedFtor NotifyFinalized; bool ProcessAllSections = false; diff --git a/llvm/lib/ExecutionEngine/Orc/Legacy.cpp b/llvm/lib/ExecutionEngine/Orc/Legacy.cpp index 7a11b94c7cf0..240e0f8ba1dd 100644 --- a/llvm/lib/ExecutionEngine/Orc/Legacy.cpp +++ b/llvm/lib/ExecutionEngine/Orc/Legacy.cpp @@ -45,10 +45,21 @@ JITSymbolResolverAdapter::lookup(const LookupSet &Symbols) { auto UnresolvedSymbols = R.lookup(Query, InternedSymbols); - if (!UnresolvedSymbols.empty()) - Err = joinErrors(std::move(Err), - make_error("Unresolved symbols", - inconvertibleErrorCode())); + if (!UnresolvedSymbols.empty()) { + std::string ErrorMsg = "Unresolved symbols: "; + + ErrorMsg += **UnresolvedSymbols.begin(); + for (auto I = std::next(UnresolvedSymbols.begin()), + E = UnresolvedSymbols.end(); + I != E; ++I) { + ErrorMsg += ", "; + ErrorMsg += **I; + } + + Err = + joinErrors(std::move(Err), + make_error(ErrorMsg, inconvertibleErrorCode())); + } if (Err) return std::move(Err); diff --git a/llvm/lib/ExecutionEngine/Orc/NullResolver.cpp b/llvm/lib/ExecutionEngine/Orc/NullResolver.cpp index 6bb94f788416..59f7414df71d 100644 --- a/llvm/lib/ExecutionEngine/Orc/NullResolver.cpp +++ b/llvm/lib/ExecutionEngine/Orc/NullResolver.cpp @@ -14,6 +14,17 @@ namespace llvm { namespace orc { +SymbolNameSet NullResolver::lookupFlags(SymbolFlagsMap &Flags, + const SymbolNameSet &Symbols) { + return Symbols; +} + +SymbolNameSet NullResolver::lookup(AsynchronousSymbolQuery &Query, + SymbolNameSet Symbols) { + assert(Symbols.empty() && "Null resolver: Symbols must be empty"); + return Symbols; +} + JITSymbol NullLegacyResolver::findSymbol(const std::string &Name) { llvm_unreachable("Unexpected cross-object symbol reference"); } diff --git a/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h b/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h index 05b1f47eb5bb..7128bd343809 100644 --- a/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h +++ b/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h @@ -52,24 +52,34 @@ namespace detail { class GenericHandle { public: + GenericHandle(orc::VModuleKey K) : K(K) {} + virtual ~GenericHandle() = default; virtual JITSymbol findSymbolIn(const std::string &Name, bool ExportedSymbolsOnly) = 0; - virtual Error removeModule() = 0; + virtual Error removeModule(orc::ExecutionSession &ES) = 0; + + orc::VModuleKey K; }; template class GenericHandleImpl : public GenericHandle { public: - GenericHandleImpl(LayerT &Layer, typename LayerT::ModuleHandleT Handle) - : Layer(Layer), Handle(std::move(Handle)) {} + GenericHandleImpl(LayerT &Layer, typename LayerT::ModuleHandleT Handle, + orc::VModuleKey K) + : GenericHandle(std::move(K)), 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.removeModule(Handle); } + Error removeModule(orc::ExecutionSession &ES) override { + auto Err = Layer.removeModule(Handle); + ES.releaseVModule(K); + return Err; + } private: LayerT &Layer; @@ -82,28 +92,32 @@ namespace detail { private: using LayerT = orc::RTDyldObjectLinkingLayer; public: - - GenericHandleImpl(LayerT &Layer, typename LayerT::ObjHandleT Handle) - : Layer(Layer), Handle(std::move(Handle)) {} + GenericHandleImpl(LayerT &Layer, typename LayerT::ObjHandleT Handle, + orc::VModuleKey K) + : GenericHandle(std::move(K)), 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); } + Error removeModule(orc::ExecutionSession &ES) override { + auto Err = Layer.removeObject(Handle); + ES.releaseVModule(K); + return Err; + } private: LayerT &Layer; typename LayerT::ObjHandleT Handle; }; - template std::unique_ptr> - createGenericHandle(LayerT &Layer, HandleT Handle) { - return llvm::make_unique>(Layer, - std::move(Handle)); + createGenericHandle(LayerT &Layer, HandleT Handle, orc::VModuleKey K) { + return llvm::make_unique>( + Layer, std::move(Handle), std::move(K)); } } // end namespace detail @@ -126,20 +140,113 @@ private: using OwningObject = object::OwningBinary; + 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 lookupFlags(orc::SymbolFlagsMap &SymbolFlags, + const orc::SymbolNameSet &Symbols) override { + orc::SymbolNameSet SymbolsNotFound; + + for (auto &S : Symbols) { + if (auto Sym = findSymbol(*S)) + SymbolFlags[S] = Sym.getFlags(); + else if (auto Err = Sym.takeError()) { + Stack.reportError(std::move(Err)); + return {}; + } else + SymbolsNotFound.insert(S); + } + + return SymbolsNotFound; + } + + orc::SymbolNameSet lookup(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.setDefinition(S, JITEvaluatedSymbol(*Addr, Sym.getFlags())); + else { + Query.setFailed(Addr.takeError()); + return {}; + } + } else if (auto Err = Sym.takeError()) { + Query.setFailed(std::move(Err)); + return {}; + } else + UnresolvedSymbols.insert(S); + } + + return UnresolvedSymbols; + } + + private: + JITSymbol findSymbol(const std::string &Name) { + // Search order: + // 1. JIT'd symbols. + // 2. Runtime overrides. + // 3. External resolver (if present). + + if (auto Sym = Stack.CODLayer.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: using ModuleHandleT = unsigned; OrcCBindingsStack(TargetMachine &TM, std::unique_ptr CCMgr, IndirectStubsManagerBuilder IndirectStubsMgrBuilder) - : DL(TM.createDataLayout()), IndirectStubsMgr(IndirectStubsMgrBuilder()), - CCMgr(std::move(CCMgr)), - ObjectLayer( - []() { - return std::make_shared(); - }), + : ES(SSP), DL(TM.createDataLayout()), + IndirectStubsMgr(IndirectStubsMgrBuilder()), CCMgr(std::move(CCMgr)), + ObjectLayer(ES, + [](orc::VModuleKey K) { + return std::make_shared(); + }, + [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 Resolver; + }), CompileLayer(ObjectLayer, orc::SimpleCompiler(TM)), - CODLayer(CompileLayer, + CODLayer(ES, CompileLayer, + [this](orc::VModuleKey K) { + auto ResolverI = Resolvers.find(K); + assert(ResolverI != Resolvers.end() && + "No resolver for module K"); + return ResolverI->second; + }, + [this](orc::VModuleKey K, + std::shared_ptr Resolver) { + assert(!Resolvers.count(K) && "Resolver already present"); + Resolvers[K] = std::move(Resolver); + }, [](Function &F) { return std::set({&F}); }, *this->CCMgr, std::move(IndirectStubsMgrBuilder), false), CXXRuntimeOverrides( @@ -195,38 +302,6 @@ public: JITTargetAddress Addr) { return mapError(IndirectStubsMgr->updatePointer(Name, Addr)); } - - std::shared_ptr - createResolver(LLVMOrcSymbolResolverFn ExternalResolver, - void *ExternalResolverCtx) { - return orc::createLambdaResolver( - [this, ExternalResolver, ExternalResolverCtx](const std::string &Name) - -> JITSymbol { - // Search order: - // 1. JIT'd symbols. - // 2. Runtime overrides. - // 3. External resolver (if present). - - if (auto Sym = CODLayer.findSymbol(Name, true)) - return Sym; - else if (auto Err = Sym.takeError()) - return Sym.takeError(); - - if (auto Sym = CXXRuntimeOverrides.searchOverrides(Name)) - return Sym; - - if (ExternalResolver) - return JITSymbol( - ExternalResolver(Name.c_str(), ExternalResolverCtx), - JITSymbolFlags::Exported); - - return JITSymbol(nullptr); - }, - [](const std::string &Name) -> JITSymbol { - return JITSymbol(nullptr); - }); - } - template LLVMOrcErrorCode addIRModule(ModuleHandleT &RetHandle, LayerT &Layer, @@ -247,13 +322,13 @@ public: for (auto Dtor : orc::getDestructors(*M)) DtorNames.push_back(mangle(Dtor.Func->getName())); - // Create the resolver. - auto Resolver = createResolver(ExternalResolver, ExternalResolverCtx); - // Add the module to the JIT. ModuleHandleT H; - if (auto LHOrErr = Layer.addModule(std::move(M), std::move(Resolver))) - H = createHandle(Layer, *LHOrErr); + orc::VModuleKey K = ES.allocateVModule(); + Resolvers[K] = std::make_shared(*this, ExternalResolver, + ExternalResolverCtx); + if (auto LHOrErr = Layer.addModule(K, std::move(M))) + H = createHandle(Layer, *LHOrErr, K); else return mapError(LHOrErr.takeError()); @@ -288,7 +363,7 @@ public: } LLVMOrcErrorCode removeModule(ModuleHandleT H) { - if (auto Err = GenericHandles[H]->removeModule()) + if (auto Err = GenericHandles[H]->removeModule(ES)) return mapError(std::move(Err)); GenericHandles[H] = nullptr; FreeHandleIndexes.push_back(H); @@ -305,13 +380,13 @@ public: auto OwningObj = std::make_shared(std::move(Obj), std::move(ObjBuffer)); - // Create the resolver. - auto Resolver = createResolver(ExternalResolver, ExternalResolverCtx); + orc::VModuleKey K = ES.allocateVModule(); + Resolvers[K] = std::make_shared( + *this, ExternalResolver, ExternalResolverCtx); ModuleHandleT H; - if (auto HOrErr = ObjectLayer.addObject(std::move(OwningObj), - std::move(Resolver))) - H = createHandle(ObjectLayer, *HOrErr); + if (auto HOrErr = ObjectLayer.addObject(K, std::move(OwningObj))) + H = createHandle(ObjectLayer, *HOrErr, K); else return mapError(HOrErr.takeError()); @@ -358,18 +433,18 @@ public: private: template - unsigned createHandle(LayerT &Layer, HandleT Handle) { + unsigned createHandle(LayerT &Layer, HandleT Handle, orc::VModuleKey K) { unsigned NewHandle; if (!FreeHandleIndexes.empty()) { NewHandle = FreeHandleIndexes.back(); FreeHandleIndexes.pop_back(); GenericHandles[NewHandle] = - detail::createGenericHandle(Layer, std::move(Handle)); + detail::createGenericHandle(Layer, std::move(Handle), std::move(K)); return NewHandle; } else { NewHandle = GenericHandles.size(); GenericHandles.push_back( - detail::createGenericHandle(Layer, std::move(Handle))); + detail::createGenericHandle(Layer, std::move(Handle), std::move(K))); } return NewHandle; } @@ -386,6 +461,14 @@ private: return Result; } + void reportError(Error Err) { + // FIXME: Report errors on the execution session. + logAllUnhandledErrors(std::move(Err), errs(), "ORC error: "); + }; + + orc::SymbolStringPool SSP; + orc::ExecutionSession ES; + DataLayout DL; SectionMemoryManager CCMgrMemMgr; @@ -402,6 +485,8 @@ private: orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides; std::vector> IRStaticDestructorRunners; std::string ErrMsg; + + std::map> Resolvers; }; } // end namespace llvm diff --git a/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h b/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h index 166d1369c724..cc5a8a5c1cec 100644 --- a/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h +++ b/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h @@ -138,18 +138,67 @@ class OrcMCJITReplacement : public ExecutionEngine { std::shared_ptr ClientMM; }; - class LinkingResolver : public LegacyJITSymbolResolver { + class LinkingORCResolver : public orc::SymbolResolver { public: - LinkingResolver(OrcMCJITReplacement &M) : M(M) {} + LinkingORCResolver(OrcMCJITReplacement &M) : M(M) {} - JITSymbol findSymbol(const std::string &Name) override { - return M.ClientResolver->findSymbol(Name); + SymbolNameSet lookupFlags(SymbolFlagsMap &SymbolFlags, + const SymbolNameSet &Symbols) override { + SymbolNameSet UnresolvedSymbols; + + for (auto &S : Symbols) { + if (auto Sym = M.findMangledSymbol(*S)) { + SymbolFlags[S] = Sym.getFlags(); + } else if (auto Err = Sym.takeError()) { + M.reportError(std::move(Err)); + return SymbolNameSet(); + } else { + if (auto Sym2 = M.ClientResolver->findSymbolInLogicalDylib(*S)) { + SymbolFlags[S] = Sym2.getFlags(); + } else if (auto Err = Sym2.takeError()) { + M.reportError(std::move(Err)); + return SymbolNameSet(); + } else + UnresolvedSymbols.insert(S); + } + } + + return UnresolvedSymbols; } - JITSymbol findSymbolInLogicalDylib(const std::string &Name) override { - if (auto Sym = M.findMangledSymbol(Name)) - return Sym; - return M.ClientResolver->findSymbolInLogicalDylib(Name); + SymbolNameSet lookup(AsynchronousSymbolQuery &Query, + SymbolNameSet Symbols) override { + SymbolNameSet UnresolvedSymbols; + + for (auto &S : Symbols) { + if (auto Sym = M.findMangledSymbol(*S)) { + if (auto Addr = Sym.getAddress()) + Query.setDefinition(S, JITEvaluatedSymbol(*Addr, Sym.getFlags())); + else { + Query.setFailed(Addr.takeError()); + return SymbolNameSet(); + } + } else if (auto Err = Sym.takeError()) { + Query.setFailed(std::move(Err)); + return SymbolNameSet(); + } else { + if (auto Sym2 = M.ClientResolver->findSymbol(*S)) { + if (auto Addr = Sym2.getAddress()) + Query.setDefinition(S, + JITEvaluatedSymbol(*Addr, Sym2.getFlags())); + else { + Query.setFailed(Addr.takeError()); + return SymbolNameSet(); + } + } else if (auto Err = Sym2.takeError()) { + Query.setFailed(std::move(Err)); + return SymbolNameSet(); + } else + UnresolvedSymbols.insert(S); + } + } + + return UnresolvedSymbols; } private: @@ -166,18 +215,23 @@ private: std::move(TM)); } + void reportError(Error Err) { + logAllUnhandledErrors(std::move(Err), errs(), "MCJIT error: "); + } + public: OrcMCJITReplacement(std::shared_ptr MemMgr, std::shared_ptr ClientResolver, std::unique_ptr TM) - : ExecutionEngine(TM->createDataLayout()), TM(std::move(TM)), + : ExecutionEngine(TM->createDataLayout()), ES(SSP), TM(std::move(TM)), MemMgr( std::make_shared(*this, std::move(MemMgr))), - Resolver(std::make_shared(*this)), + Resolver(std::make_shared(*this)), ClientResolver(std::move(ClientResolver)), NotifyObjectLoaded(*this), NotifyFinalized(*this), - ObjectLayer([this]() { return this->MemMgr; }, NotifyObjectLoaded, - NotifyFinalized), + ObjectLayer(ES, [this](VModuleKey K) { return this->MemMgr; }, + [this](VModuleKey K) { return this->Resolver; }, + NotifyObjectLoaded, NotifyFinalized), CompileLayer(ObjectLayer, SimpleCompiler(*this->TM)), LazyEmitLayer(CompileLayer) {} @@ -201,20 +255,21 @@ public: delete Mod; }; LocalModules.push_back(std::shared_ptr(MPtr, std::move(Deleter))); - cantFail(LazyEmitLayer.addModule(LocalModules.back(), Resolver)); + cantFail( + LazyEmitLayer.addModule(ES.allocateVModule(), LocalModules.back())); } void addObjectFile(std::unique_ptr O) override { auto Obj = std::make_shared>(std::move(O), nullptr); - cantFail(ObjectLayer.addObject(std::move(Obj), Resolver)); + cantFail(ObjectLayer.addObject(ES.allocateVModule(), std::move(Obj))); } void addObjectFile(object::OwningBinary O) override { auto Obj = std::make_shared>(std::move(O)); - cantFail(ObjectLayer.addObject(std::move(Obj), Resolver)); + cantFail(ObjectLayer.addObject(ES.allocateVModule(), std::move(Obj))); } void addArchive(object::OwningBinary A) override { @@ -322,7 +377,7 @@ private: auto Obj = std::make_shared>( std::move(ChildObj), nullptr); - cantFail(ObjectLayer.addObject(std::move(Obj), Resolver)); + cantFail(ObjectLayer.addObject(ES.allocateVModule(), std::move(Obj))); if (auto Sym = ObjectLayer.findSymbol(Name, true)) return Sym; } @@ -374,9 +429,12 @@ private: using CompileLayerT = IRCompileLayer; using LazyEmitLayerT = LazyEmittingLayer; + SymbolStringPool SSP; + ExecutionSession ES; + std::unique_ptr TM; std::shared_ptr MemMgr; - std::shared_ptr Resolver; + std::shared_ptr Resolver; std::shared_ptr ClientResolver; Mangler Mang; diff --git a/llvm/tools/lli/OrcLazyJIT.h b/llvm/tools/lli/OrcLazyJIT.h index a5cc804bb045..66c5c5b63f2d 100644 --- a/llvm/tools/lli/OrcLazyJIT.h +++ b/llvm/tools/lli/OrcLazyJIT.h @@ -61,13 +61,38 @@ public: std::unique_ptr CCMgr, IndirectStubsManagerBuilder IndirectStubsMgrBuilder, bool InlineStubs) - : TM(std::move(TM)), DL(this->TM->createDataLayout()), + : ES(SSP), TM(std::move(TM)), DL(this->TM->createDataLayout()), CCMgr(std::move(CCMgr)), - ObjectLayer([]() { return std::make_shared(); }), + ObjectLayer(ES, + [](orc::VModuleKey) { + return std::make_shared(); + }, + [&](orc::VModuleKey K) { + auto ResolverI = Resolvers.find(K); + assert(ResolverI != Resolvers.end() && + "Missing resolver for module K"); + auto Resolver = std::move(ResolverI->second); + Resolvers.erase(ResolverI); + return Resolver; + }), CompileLayer(ObjectLayer, orc::SimpleCompiler(*this->TM)), IRDumpLayer(CompileLayer, createDebugDumper()), - CODLayer(IRDumpLayer, extractSingleFunction, *this->CCMgr, - std::move(IndirectStubsMgrBuilder), InlineStubs), + CODLayer( + ES, IRDumpLayer, + [&](orc::VModuleKey K) { + auto ResolverI = Resolvers.find(K); + assert(ResolverI != Resolvers.end() && + "Missing resolver for module K"); + auto Resolver = std::move(ResolverI->second); + Resolvers.erase(ResolverI); + return Resolver; + }, + [&](orc::VModuleKey K, std::shared_ptr R) { + assert(!Resolvers.count(K) && "Resolver already present"); + Resolvers[K] = std::move(R); + }, + extractSingleFunction, *this->CCMgr, + std::move(IndirectStubsMgrBuilder), InlineStubs), CXXRuntimeOverrides( [this](const std::string &S) { return mangle(S); }) {} @@ -114,24 +139,50 @@ public: // 2) Check for C++ runtime overrides. // 3) Search the host process (LLI)'s symbol table. if (!ModulesHandle) { - auto Resolver = - orc::createLambdaResolver( - [this](const std::string &Name) -> JITSymbol { - if (auto Sym = CODLayer.findSymbol(Name, true)) - return Sym; - return CXXRuntimeOverrides.searchOverrides(Name); + auto LegacyLookupInDylib = [this](const std::string &Name) -> JITSymbol { + if (auto Sym = CODLayer.findSymbol(Name, true)) + return Sym; + else if (auto Err = Sym.takeError()) + return std::move(Err); + return CXXRuntimeOverrides.searchOverrides(Name); + }; + + auto LegacyLookup = + [this, LegacyLookupInDylib](const std::string &Name) -> JITSymbol { + if (auto Sym = LegacyLookupInDylib(Name)) + return Sym; + else if (auto Err = Sym.takeError()) + return std::move(Err); + + if (auto Addr = RTDyldMemoryManager::getSymbolAddressInProcess(Name)) + return JITSymbol(Addr, JITSymbolFlags::Exported); + + return nullptr; + }; + + auto K = ES.allocateVModule(); + assert(!Resolvers.count(K) && "Resolver already present"); + Resolvers[K] = orc::createSymbolResolver( + [this, LegacyLookupInDylib](orc::SymbolFlagsMap &SymbolFlags, + const orc::SymbolNameSet &Symbols) { + auto NotFoundViaLegacyLookup = lookupFlagsWithLegacyFn( + SymbolFlags, Symbols, LegacyLookupInDylib); + if (!NotFoundViaLegacyLookup) { + logAllUnhandledErrors(NotFoundViaLegacyLookup.takeError(), errs(), + "OrcLazyJIT lookupFlags error: "); + SymbolFlags.clear(); + return orc::SymbolNameSet(); + } + return std::move(*NotFoundViaLegacyLookup); }, - [](const std::string &Name) { - if (auto Addr = - RTDyldMemoryManager::getSymbolAddressInProcess(Name)) - return JITSymbol(Addr, JITSymbolFlags::Exported); - return JITSymbol(nullptr); - } - ); + [LegacyLookup](orc::AsynchronousSymbolQuery &Query, + orc::SymbolNameSet Symbols) { + return lookupWithLegacyFn(Query, Symbols, LegacyLookup); + }); // Add the module to the JIT. if (auto ModulesHandleOrErr = - CODLayer.addModule(std::move(M), std::move(Resolver))) + CODLayer.addModule(std::move(K), std::move(M))) ModulesHandle = std::move(*ModulesHandleOrErr); else return ModulesHandleOrErr.takeError(); @@ -178,6 +229,11 @@ private: static TransformFtor createDebugDumper(); + orc::SymbolStringPool SSP; + orc::ExecutionSession ES; + + std::map> Resolvers; + std::unique_ptr TM; DataLayout DL; SectionMemoryManager CCMgrMemMgr; diff --git a/llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp index 61ce310e6311..4501b53c3c04 100644 --- a/llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp @@ -59,9 +59,22 @@ TEST(CompileOnDemandLayerTest, FindSymbol) { DummyCallbackManager CallbackMgr; + SymbolStringPool SSP; + ExecutionSession ES(SSP); + + auto GetResolver = + [](orc::VModuleKey) -> std::shared_ptr { + llvm_unreachable("Should never be called"); + }; + + auto SetResolver = [](orc::VModuleKey, std::shared_ptr) { + llvm_unreachable("Should never be called"); + }; + llvm::orc::CompileOnDemandLayer COD( - TestBaseLayer, [](Function &F) { return std::set{&F}; }, - CallbackMgr, [] { return llvm::make_unique(); }, true); + ES, TestBaseLayer, GetResolver, SetResolver, + [](Function &F) { return std::set{&F}; }, CallbackMgr, + [] { return llvm::make_unique(); }, true); auto Sym = COD.findSymbol("foo", true); diff --git a/llvm/unittests/ExecutionEngine/Orc/LazyEmittingLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/LazyEmittingLayerTest.cpp index 0dba66d47535..3801fa918db7 100644 --- a/llvm/unittests/ExecutionEngine/Orc/LazyEmittingLayerTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/LazyEmittingLayerTest.cpp @@ -15,11 +15,8 @@ namespace { struct MockBaseLayer { typedef int ModuleHandleT; - ModuleHandleT addModule( - std::shared_ptr, - std::unique_ptr MemMgr, - std::unique_ptr Resolver) { - EXPECT_FALSE(MemMgr); + ModuleHandleT addModule(llvm::orc::VModuleKey, + std::shared_ptr) { return 42; } }; @@ -27,7 +24,8 @@ struct MockBaseLayer { TEST(LazyEmittingLayerTest, Empty) { MockBaseLayer M; llvm::orc::LazyEmittingLayer L(M); - cantFail(L.addModule(std::unique_ptr(), nullptr)); + cantFail( + L.addModule(llvm::orc::VModuleKey(), std::unique_ptr())); } } diff --git a/llvm/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp index 2aa2b48d761e..9de1c22e45f6 100644 --- a/llvm/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp @@ -11,7 +11,6 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" -#include "llvm/ExecutionEngine/Orc/NullResolver.h" #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/Object/ObjectFile.h" @@ -49,20 +48,16 @@ public: MockBaseLayer() : MockSymbol(nullptr) { resetExpectations(); } template - llvm::Expected - addObject(ObjPtrT Obj, - std::shared_ptr Resolver) { - EXPECT_EQ(MockResolver, Resolver) << "Resolver should pass through"; + llvm::Expected addObject(VModuleKey K, ObjPtrT Obj) { + EXPECT_EQ(MockKey, K) << "Key should pass through"; EXPECT_EQ(MockObject + 1, *Obj) << "Transform should be applied"; LastCalled = "addObject"; MockObjHandle = 111; return MockObjHandle; } - template - void expectAddObject(ObjPtrT Obj, - std::shared_ptr Resolver) { - MockResolver = Resolver; + template void expectAddObject(VModuleKey K, ObjPtrT Obj) { + MockKey = K; MockObject = *Obj; } @@ -162,7 +157,7 @@ public: private: // Backing fields for remembering parameter/return values std::string LastCalled; - std::shared_ptr MockResolver; + VModuleKey MockKey; MockObjectFile MockObject; ObjHandleT MockObjHandle; std::string MockName; @@ -175,7 +170,7 @@ private: // Clear remembered parameters between calls void resetExpectations() { LastCalled = "nothing"; - MockResolver = nullptr; + MockKey = 0; MockObject = 0; MockObjHandle = 0; MockName = "bogus"; @@ -190,6 +185,9 @@ private: TEST(ObjectTransformLayerTest, Main) { MockBaseLayer M; + SymbolStringPool SSP; + ExecutionSession ES(SSP); + // Create one object transform layer using a transform (as a functor) // that allocates new objects, and deals in unique pointers. ObjectTransformLayer T1(M); @@ -205,16 +203,17 @@ TEST(ObjectTransformLayerTest, Main) { }); // Test addObject with T1 (allocating) + auto K1 = ES.allocateVModule(); auto Obj1 = std::make_shared(211); - auto SR = std::make_shared(); - M.expectAddObject(Obj1, SR); - auto H = cantFail(T1.addObject(std::move(Obj1), SR)); + M.expectAddObject(K1, Obj1); + auto H = cantFail(T1.addObject(K1, std::move(Obj1))); M.verifyAddObject(H); // Test addObjectSet with T2 (mutating) + auto K2 = ES.allocateVModule(); auto Obj2 = std::make_shared(222); - M.expectAddObject(Obj2, SR); - H = cantFail(T2.addObject(Obj2, SR)); + M.expectAddObject(K2, Obj2); + H = cantFail(T2.addObject(K2, Obj2)); M.verifyAddObject(H); EXPECT_EQ(223, *Obj2) << "Expected mutation"; @@ -291,9 +290,11 @@ TEST(ObjectTransformLayerTest, Main) { // Construct the jit layers. RTDyldObjectLinkingLayer BaseLayer( - []() { - return std::make_shared(); - }); + ES, + [](VModuleKey) { return std::make_shared(); }, + [](VModuleKey) -> std::shared_ptr { + llvm_unreachable("Should never be called"); + }); auto IdentityTransform = [](std::shared_ptr> @@ -311,8 +312,8 @@ TEST(ObjectTransformLayerTest, Main) { // Make sure that the calls from IRCompileLayer to ObjectTransformLayer // compile. - auto Resolver = std::make_shared(); - cantFail(CompileLayer.addModule(std::shared_ptr(), Resolver)); + cantFail(CompileLayer.addModule(ES.allocateVModule(), + std::shared_ptr())); // Make sure that the calls from ObjectTransformLayer to ObjectLinkingLayer // compile. diff --git a/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp index 8b25ede78bc8..3e7d3f6db39c 100644 --- a/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp @@ -12,6 +12,7 @@ #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/Orc/CompileUtils.h" #include "llvm/ExecutionEngine/Orc/LambdaResolver.h" +#include "llvm/ExecutionEngine/Orc/Legacy.h" #include "llvm/ExecutionEngine/Orc/NullResolver.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/IR/Constants.h" @@ -66,7 +67,12 @@ TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) { bool DebugSectionSeen = false; auto MM = std::make_shared(DebugSectionSeen); - RTDyldObjectLinkingLayer ObjLayer([&MM]() { return MM; }); + SymbolStringPool SSP; + ExecutionSession ES(SSP); + + RTDyldObjectLinkingLayer ObjLayer( + ES, [&MM](VModuleKey) { return MM; }, + [](orc::VModuleKey) { return std::make_shared(); }); LLVMContext Context; auto M = llvm::make_unique("", Context); @@ -92,18 +98,9 @@ TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) { std::make_shared>( SimpleCompiler(*TM)(*M)); - auto Resolver = - createLambdaResolver( - [](const std::string &Name) { - return JITSymbol(nullptr); - }, - [](const std::string &Name) { - return JITSymbol(nullptr); - }); - { // Test with ProcessAllSections = false (the default). - auto H = cantFail(ObjLayer.addObject(Obj, Resolver)); + auto H = cantFail(ObjLayer.addObject(ES.allocateVModule(), Obj)); cantFail(ObjLayer.emitAndFinalize(H)); EXPECT_EQ(DebugSectionSeen, false) << "Unexpected debug info section"; @@ -113,7 +110,7 @@ TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) { { // Test with ProcessAllSections = true. ObjLayer.setProcessAllSections(true); - auto H = cantFail(ObjLayer.addObject(Obj, Resolver)); + auto H = cantFail(ObjLayer.addObject(ES.allocateVModule(), Obj)); cantFail(ObjLayer.emitAndFinalize(H)); EXPECT_EQ(DebugSectionSeen, true) << "Expected debug info section not seen"; @@ -125,9 +122,22 @@ TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoDuplicateFinalization) { if (!TM) return; + SymbolStringPool SSP; + ExecutionSession ES(SSP); + auto MM = std::make_shared(); - RTDyldObjectLinkingLayer ObjLayer([&MM]() { return MM; }); + std::map> Resolvers; + + RTDyldObjectLinkingLayer ObjLayer(ES, [&MM](VModuleKey) { return MM; }, + [&](VModuleKey K) { + auto I = Resolvers.find(K); + assert(I != Resolvers.end() && + "Missing resolver"); + auto R = std::move(I->second); + Resolvers.erase(I); + return R; + }); SimpleCompiler Compile(*TM); // Create a pair of modules that will trigger recursive finalization: @@ -170,19 +180,25 @@ TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoDuplicateFinalization) { std::make_shared>( Compile(*MB2.getModule())); - auto Resolver = - createLambdaResolver( - [&](const std::string &Name) { - if (auto Sym = ObjLayer.findSymbol(Name, true)) - return Sym; - return JITSymbol(nullptr); + auto K1 = ES.allocateVModule(); + Resolvers[K1] = std::make_shared(); + cantFail(ObjLayer.addObject(K1, std::move(Obj1))); + + auto K2 = ES.allocateVModule(); + auto LegacyLookup = [&](const std::string &Name) { + return ObjLayer.findSymbol(Name, true); + }; + + Resolvers[K2] = createSymbolResolver( + [&](SymbolFlagsMap &SymbolFlags, const SymbolNameSet &Symbols) { + return cantFail( + lookupFlagsWithLegacyFn(SymbolFlags, Symbols, LegacyLookup)); }, - [](const std::string &Name) { - return JITSymbol(nullptr); + [&](AsynchronousSymbolQuery &Query, const SymbolNameSet &Symbols) { + return lookupWithLegacyFn(Query, Symbols, LegacyLookup); }); - cantFail(ObjLayer.addObject(std::move(Obj1), Resolver)); - auto H = cantFail(ObjLayer.addObject(std::move(Obj2), Resolver)); + auto H = cantFail(ObjLayer.addObject(K2, std::move(Obj2))); cantFail(ObjLayer.emitAndFinalize(H)); cantFail(ObjLayer.removeObject(H)); @@ -196,9 +212,14 @@ TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoPrematureAllocation) { if (!TM) return; + SymbolStringPool SSP; + ExecutionSession ES(SSP); + auto MM = std::make_shared(); - RTDyldObjectLinkingLayer ObjLayer([&MM]() { return MM; }); + RTDyldObjectLinkingLayer ObjLayer( + ES, [&MM](VModuleKey) { return MM; }, + [](VModuleKey) { return std::make_shared(); }); SimpleCompiler Compile(*TM); // Create a pair of unrelated modules: @@ -243,9 +264,8 @@ TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoPrematureAllocation) { std::make_shared>( Compile(*MB2.getModule())); - auto NR = std::make_shared(); - auto H = cantFail(ObjLayer.addObject(std::move(Obj1), NR)); - cantFail(ObjLayer.addObject(std::move(Obj2), NR)); + auto H = cantFail(ObjLayer.addObject(ES.allocateVModule(), std::move(Obj1))); + cantFail(ObjLayer.addObject(ES.allocateVModule(), std::move(Obj2))); cantFail(ObjLayer.emitAndFinalize(H)); cantFail(ObjLayer.removeObject(H)); @@ -256,8 +276,11 @@ TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoPrematureAllocation) { } TEST_F(RTDyldObjectLinkingLayerExecutionTest, TestNotifyLoadedSignature) { + SymbolStringPool SSP; + ExecutionSession ES(SSP); RTDyldObjectLinkingLayer ObjLayer( - []() { return nullptr; }, + ES, [](VModuleKey) { return nullptr; }, + [](VModuleKey) { return std::make_shared(); }, [](RTDyldObjectLinkingLayer::ObjHandleT, const RTDyldObjectLinkingLayer::ObjectPtr &obj, const RuntimeDyld::LoadedObjectInfo &info) {});