From ad92f16ccc5f87625bfea2823cd79700bea52c54 Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Tue, 22 Sep 2020 22:37:25 -0700 Subject: [PATCH] [ORC][examples] Update Kaleidoscope and BuildingAJIT tutorial series to OrcV2. This patch updates the Kaleidoscope and BuildingAJIT tutorial series (chapter 1-4) to OrcV2. Chapter 5 of the BuildingAJIT series is removed -- it will be re-instated once we have in-tree support for out-of-process JITing. This patch only updates the tutorial code, not the text. Patches welcome for that, otherwise I will try to update it in a few weeks. --- llvm/docs/tutorial/BuildingAJIT4.rst | 12 +- llvm/docs/tutorial/BuildingAJIT5.rst | 57 - .../Kaleidoscope/BuildingAJIT/CMakeLists.txt | 6 +- .../BuildingAJIT/Chapter1/KaleidoscopeJIT.h | 53 +- .../Kaleidoscope/BuildingAJIT/Chapter1/toy.cpp | 42 +- .../BuildingAJIT/Chapter2/KaleidoscopeJIT.h | 61 +- .../Kaleidoscope/BuildingAJIT/Chapter2/toy.cpp | 42 +- .../BuildingAJIT/Chapter3/KaleidoscopeJIT.h | 204 +-- .../Kaleidoscope/BuildingAJIT/Chapter3/toy.cpp | 145 +-- .../BuildingAJIT/Chapter4/KaleidoscopeJIT.h | 317 ++--- .../Kaleidoscope/BuildingAJIT/Chapter4/toy.cpp | 160 +-- .../BuildingAJIT/Chapter5/CMakeLists.txt | 22 - .../BuildingAJIT/Chapter5/KaleidoscopeJIT.h | 248 ---- .../BuildingAJIT/Chapter5/RemoteJITUtils.h | 75 -- .../BuildingAJIT/Chapter5/Server/CMakeLists.txt | 20 - .../BuildingAJIT/Chapter5/Server/server.cpp | 111 -- .../Kaleidoscope/BuildingAJIT/Chapter5/toy.cpp | 1309 -------------------- llvm/examples/Kaleidoscope/Chapter3/toy.cpp | 45 +- llvm/examples/Kaleidoscope/Chapter4/toy.cpp | 60 +- llvm/examples/Kaleidoscope/Chapter5/toy.cpp | 118 +- llvm/examples/Kaleidoscope/Chapter6/toy.cpp | 122 +- llvm/examples/Kaleidoscope/Chapter7/toy.cpp | 136 +- llvm/examples/Kaleidoscope/Chapter8/toy.cpp | 113 +- llvm/examples/Kaleidoscope/Chapter9/toy.cpp | 138 ++- .../Kaleidoscope/include/KaleidoscopeJIT.h | 155 +-- .../llvm/ExecutionEngine/Orc/TPCIndirectionUtils.h | 13 + .../ExecutionEngine/Orc/TPCIndirectionUtils.cpp | 21 + 27 files changed, 1041 insertions(+), 2764 deletions(-) delete mode 100644 llvm/docs/tutorial/BuildingAJIT5.rst delete mode 100644 llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/CMakeLists.txt delete mode 100644 llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h delete mode 100644 llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/RemoteJITUtils.h delete mode 100644 llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/Server/CMakeLists.txt delete mode 100644 llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/Server/server.cpp delete mode 100644 llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/toy.cpp diff --git a/llvm/docs/tutorial/BuildingAJIT4.rst b/llvm/docs/tutorial/BuildingAJIT4.rst index 3d3f81e..6eb3d52 100644 --- a/llvm/docs/tutorial/BuildingAJIT4.rst +++ b/llvm/docs/tutorial/BuildingAJIT4.rst @@ -1,6 +1,6 @@ -=========================================================================== -Building a JIT: Extreme Laziness - Using Compile Callbacks to JIT from ASTs -=========================================================================== +======================================================================= +Building a JIT: Extreme Laziness - Using LazyReexports to JIT from ASTs +======================================================================= .. contents:: :local: @@ -13,9 +13,9 @@ Chapter 4 Introduction ====================== Welcome to Chapter 4 of the "Building an ORC-based JIT in LLVM" tutorial. This -chapter introduces the Compile Callbacks and Indirect Stubs APIs and shows how -they can be used to replace the CompileOnDemand layer from -`Chapter 3 `_ with a custom lazy-JITing scheme that JITs +chapter introduces custom MaterializationUnits and Layers, and the lazy +reexports API. Together these will be used to replace the CompileOnDemandLayer +from `Chapter 3 `_ with a custom lazy-JITing scheme that JITs directly from Kaleidoscope ASTs. **To be done:** diff --git a/llvm/docs/tutorial/BuildingAJIT5.rst b/llvm/docs/tutorial/BuildingAJIT5.rst deleted file mode 100644 index 0fda861..0000000 --- a/llvm/docs/tutorial/BuildingAJIT5.rst +++ /dev/null @@ -1,57 +0,0 @@ -============================================================================= -Building a JIT: Remote-JITing -- Process Isolation and Laziness at a Distance -============================================================================= - -.. contents:: - :local: - -**This tutorial is under active development. It is incomplete and details may -change frequently.** Nonetheless we invite you to try it out as it stands, and -we welcome any feedback. - -Chapter 5 Introduction -====================== - -Welcome to Chapter 5 of the "Building an ORC-based JIT in LLVM" tutorial. This -chapter introduces the ORC RemoteJIT Client/Server APIs and shows how to use -them to build a JIT stack that will execute its code via a communications -channel with a different process. This can be a separate process on the same -machine, a process on a different machine, or even a process on a different -platform/architecture. The code builds on top of the lazy-AST-compiling JIT -stack from `Chapter 4 `_. - -**To be done -- this is going to be a long one:** - -**(1) Introduce channels, RPC, RemoteJIT Client and Server APIs** - -**(2) Describe the client code in greater detail. Discuss modifications of the -KaleidoscopeJIT class, and the REPL itself.** - -**(3) Describe the server code.** - -**(4) Describe how to run the demo.** - -Full Code Listing -================= - -Here is the complete code listing for our running example that JITs lazily from -Kaleidoscope ASTS. To build this example, use: - -.. code-block:: bash - - # Compile - clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core orcjit native` -O3 -o toy - clang++ -g Server/server.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core orcjit native` -O3 -o toy-server - # Run - ./toy-server & - ./toy - -Here is the code for the modified KaleidoscopeJIT: - -.. literalinclude:: ../../examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h - :language: c++ - -And the code for the JIT server: - -.. literalinclude:: ../../examples/Kaleidoscope/BuildingAJIT/Chapter5/Server/server.cpp - :language: c++ diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/CMakeLists.txt b/llvm/examples/Kaleidoscope/BuildingAJIT/CMakeLists.txt index 947b5a3..dc516ab 100644 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/CMakeLists.txt +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/CMakeLists.txt @@ -3,6 +3,6 @@ add_subdirectory(Chapter2) add_subdirectory(Chapter3) add_subdirectory(Chapter4) -if (NOT WIN32) - add_subdirectory(Chapter5) -endif() +# if (NOT WIN32) +# add_subdirectory(Chapter5) +# endif() diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h index adb6be4..9b35456a 100644 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h @@ -21,6 +21,7 @@ #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" +#include "llvm/ExecutionEngine/Orc/TargetProcessControl.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/LLVMContext.h" @@ -31,53 +32,67 @@ namespace orc { class KaleidoscopeJIT { private: - ExecutionSession ES; - RTDyldObjectLinkingLayer ObjectLayer; - IRCompileLayer CompileLayer; + std::unique_ptr TPC; + std::unique_ptr ES; DataLayout DL; MangleAndInterner Mangle; - ThreadSafeContext Ctx; + + RTDyldObjectLinkingLayer ObjectLayer; + IRCompileLayer CompileLayer; JITDylib &MainJD; public: - KaleidoscopeJIT(JITTargetMachineBuilder JTMB, DataLayout DL) - : ObjectLayer(ES, + KaleidoscopeJIT(std::unique_ptr TPC, + std::unique_ptr ES, + JITTargetMachineBuilder JTMB, DataLayout DL) + : TPC(std::move(TPC)), ES(std::move(ES)), DL(std::move(DL)), + Mangle(*this->ES, this->DL), + ObjectLayer(*this->ES, []() { return std::make_unique(); }), - CompileLayer(ES, ObjectLayer, + CompileLayer(*this->ES, ObjectLayer, std::make_unique(std::move(JTMB))), - DL(std::move(DL)), Mangle(ES, this->DL), - Ctx(std::make_unique()), - MainJD(ES.createBareJITDylib("
")) { + MainJD(this->ES->createBareJITDylib("
")) { MainJD.addGenerator( cantFail(DynamicLibrarySearchGenerator::GetForCurrentProcess( DL.getGlobalPrefix()))); } + ~KaleidoscopeJIT() { + if (auto Err = ES->endSession()) + ES->reportError(std::move(Err)); + } + static Expected> Create() { - auto JTMB = JITTargetMachineBuilder::detectHost(); + auto TPC = SelfTargetProcessControl::Create(); + if (!TPC) + return TPC.takeError(); + + auto ES = std::make_unique(); - if (!JTMB) - return JTMB.takeError(); + JITTargetMachineBuilder JTMB((*TPC)->getTargetTriple()); - auto DL = JTMB->getDefaultDataLayoutForTarget(); + auto DL = JTMB.getDefaultDataLayoutForTarget(); if (!DL) return DL.takeError(); - return std::make_unique(std::move(*JTMB), std::move(*DL)); + return std::make_unique(std::move(*TPC), std::move(ES), + std::move(JTMB), std::move(*DL)); } const DataLayout &getDataLayout() const { return DL; } - LLVMContext &getContext() { return *Ctx.getContext(); } + JITDylib &getMainJITDylib() { return MainJD; } - Error addModule(std::unique_ptr M) { - return CompileLayer.add(MainJD, ThreadSafeModule(std::move(M), Ctx)); + Error addModule(ThreadSafeModule TSM, ResourceTrackerSP RT = nullptr) { + if (!RT) + RT = MainJD.getDefaultResourceTracker(); + return CompileLayer.add(RT, std::move(TSM)); } Expected lookup(StringRef Name) { - return ES.lookup({&MainJD}, Mangle(Name.str())); + return ES->lookup({&MainJD}, Mangle(Name.str())); } }; diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/toy.cpp b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/toy.cpp index ad942d1..2a405ae 100644 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/toy.cpp +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/toy.cpp @@ -676,11 +676,11 @@ static std::unique_ptr ParseDefinition() { } /// toplevelexpr ::= expression -static std::unique_ptr ParseTopLevelExpr(unsigned ExprCount) { +static std::unique_ptr ParseTopLevelExpr() { if (auto E = ParseExpression()) { // Make an anonymous proto. - auto Proto = std::make_unique - (("__anon_expr" + Twine(ExprCount)).str(), std::vector()); + auto Proto = std::make_unique("__anon_expr", + std::vector()); return std::make_unique(std::move(Proto), std::move(E)); } return nullptr; @@ -697,7 +697,7 @@ static std::unique_ptr ParseExtern() { //===----------------------------------------------------------------------===// static std::unique_ptr TheJIT; -static LLVMContext *TheContext; +static std::unique_ptr TheContext; static std::unique_ptr> Builder; static std::unique_ptr TheModule; static std::map NamedValues; @@ -1102,7 +1102,8 @@ Function *FunctionAST::codegen() { //===----------------------------------------------------------------------===// static void InitializeModule() { - // Open a new module. + // Open a new context and module. + TheContext = std::make_unique(); TheModule = std::make_unique("my cool jit", *TheContext); TheModule->setDataLayout(TheJIT->getDataLayout()); @@ -1116,7 +1117,8 @@ static void HandleDefinition() { fprintf(stderr, "Read function definition:"); FnIR->print(errs()); fprintf(stderr, "\n"); - ExitOnErr(TheJIT->addModule(std::move(TheModule))); + auto TSM = ThreadSafeModule(std::move(TheModule), std::move(TheContext)); + ExitOnErr(TheJIT->addModule(std::move(TSM))); InitializeModule(); } } else { @@ -1140,27 +1142,27 @@ static void HandleExtern() { } static void HandleTopLevelExpression() { - static unsigned ExprCount = 0; - - // Update ExprCount. This number will be added to anonymous expressions to - // prevent them from clashing. - ++ExprCount; - // Evaluate a top-level expression into an anonymous function. - if (auto FnAST = ParseTopLevelExpr(ExprCount)) { + if (auto FnAST = ParseTopLevelExpr()) { if (FnAST->codegen()) { - // JIT the module containing the anonymous expression, keeping a handle so - // we can free it later. - ExitOnErr(TheJIT->addModule(std::move(TheModule))); + // Create a ResourceTracker to track JIT'd memory allocated to our + // anonymous expression -- that way we can free it after executing. + auto RT = TheJIT->getMainJITDylib().createResourceTracker(); + + auto TSM = ThreadSafeModule(std::move(TheModule), std::move(TheContext)); + ExitOnErr(TheJIT->addModule(std::move(TSM), RT)); InitializeModule(); // Get the anonymous expression's JITSymbol. - auto Sym = - ExitOnErr(TheJIT->lookup(("__anon_expr" + Twine(ExprCount)).str())); + auto Sym = ExitOnErr(TheJIT->lookup("__anon_expr")); + // Get the symbol's address and cast it to the right type (takes no + // arguments, returns a double) so we can call it as a native function. auto *FP = (double (*)())(intptr_t)Sym.getAddress(); - assert(FP && "Failed to codegen function"); fprintf(stderr, "Evaluated to %f\n", FP()); + + // Delete the anonymous expression module from the JIT. + ExitOnErr(RT->remove()); } } else { // Skip token for error recovery. @@ -1229,8 +1231,6 @@ int main() { getNextToken(); TheJIT = ExitOnErr(KaleidoscopeJIT::Create()); - TheContext = &TheJIT->getContext(); - InitializeModule(); // Run the main "interpreter loop" now. diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h index 28649ff..cc3700b 100644 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h @@ -22,6 +22,7 @@ #include "llvm/ExecutionEngine/Orc/IRTransformLayer.h" #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" +#include "llvm/ExecutionEngine/Orc/TargetProcessControl.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/LLVMContext.h" @@ -36,54 +37,70 @@ namespace orc { class KaleidoscopeJIT { private: - ExecutionSession ES; - RTDyldObjectLinkingLayer ObjectLayer; - IRCompileLayer CompileLayer; - IRTransformLayer OptimizeLayer; + std::unique_ptr TPC; + std::unique_ptr ES; DataLayout DL; MangleAndInterner Mangle; - ThreadSafeContext Ctx; + + RTDyldObjectLinkingLayer ObjectLayer; + IRCompileLayer CompileLayer; + IRTransformLayer OptimizeLayer; JITDylib &MainJD; public: - KaleidoscopeJIT(JITTargetMachineBuilder JTMB, DataLayout DL) - : ObjectLayer(ES, + KaleidoscopeJIT(std::unique_ptr TPC, + std::unique_ptr ES, + JITTargetMachineBuilder JTMB, DataLayout DL) + : TPC(std::move(TPC)), ES(std::move(ES)), DL(std::move(DL)), + Mangle(*this->ES, this->DL), + ObjectLayer(*this->ES, []() { return std::make_unique(); }), - CompileLayer(ES, ObjectLayer, + CompileLayer(*this->ES, ObjectLayer, std::make_unique(std::move(JTMB))), - OptimizeLayer(ES, CompileLayer, optimizeModule), DL(std::move(DL)), - Mangle(ES, this->DL), Ctx(std::make_unique()), - MainJD(ES.createBareJITDylib("
")) { + OptimizeLayer(*this->ES, CompileLayer, optimizeModule), + MainJD(this->ES->createBareJITDylib("
")) { MainJD.addGenerator( cantFail(DynamicLibrarySearchGenerator::GetForCurrentProcess( DL.getGlobalPrefix()))); } - const DataLayout &getDataLayout() const { return DL; } - - LLVMContext &getContext() { return *Ctx.getContext(); } + ~KaleidoscopeJIT() { + if (auto Err = ES->endSession()) + ES->reportError(std::move(Err)); + } static Expected> Create() { - auto JTMB = JITTargetMachineBuilder::detectHost(); + auto TPC = SelfTargetProcessControl::Create(); + if (!TPC) + return TPC.takeError(); - if (!JTMB) - return JTMB.takeError(); + auto ES = std::make_unique(); - auto DL = JTMB->getDefaultDataLayoutForTarget(); + JITTargetMachineBuilder JTMB((*TPC)->getTargetTriple()); + + auto DL = JTMB.getDefaultDataLayoutForTarget(); if (!DL) return DL.takeError(); - return std::make_unique(std::move(*JTMB), std::move(*DL)); + return std::make_unique(std::move(*TPC), std::move(ES), + std::move(JTMB), std::move(*DL)); } - Error addModule(std::unique_ptr M) { - return OptimizeLayer.add(MainJD, ThreadSafeModule(std::move(M), Ctx)); + const DataLayout &getDataLayout() const { return DL; } + + JITDylib &getMainJITDylib() { return MainJD; } + + Error addModule(ThreadSafeModule TSM, ResourceTrackerSP RT = nullptr) { + if (!RT) + RT = MainJD.getDefaultResourceTracker(); + + return OptimizeLayer.add(RT, std::move(TSM)); } Expected lookup(StringRef Name) { - return ES.lookup({&MainJD}, Mangle(Name.str())); + return ES->lookup({&MainJD}, Mangle(Name.str())); } private: diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/toy.cpp b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/toy.cpp index 136ae96..2a405ae 100644 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/toy.cpp +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/toy.cpp @@ -676,11 +676,11 @@ static std::unique_ptr ParseDefinition() { } /// toplevelexpr ::= expression -static std::unique_ptr ParseTopLevelExpr(unsigned ExprCount) { +static std::unique_ptr ParseTopLevelExpr() { if (auto E = ParseExpression()) { // Make an anonymous proto. - auto Proto = std::make_unique( - ("__anon_expr" + Twine(ExprCount)).str(), std::vector()); + auto Proto = std::make_unique("__anon_expr", + std::vector()); return std::make_unique(std::move(Proto), std::move(E)); } return nullptr; @@ -697,7 +697,7 @@ static std::unique_ptr ParseExtern() { //===----------------------------------------------------------------------===// static std::unique_ptr TheJIT; -static LLVMContext *TheContext; +static std::unique_ptr TheContext; static std::unique_ptr> Builder; static std::unique_ptr TheModule; static std::map NamedValues; @@ -1102,7 +1102,8 @@ Function *FunctionAST::codegen() { //===----------------------------------------------------------------------===// static void InitializeModule() { - // Open a new module. + // Open a new context and module. + TheContext = std::make_unique(); TheModule = std::make_unique("my cool jit", *TheContext); TheModule->setDataLayout(TheJIT->getDataLayout()); @@ -1116,7 +1117,8 @@ static void HandleDefinition() { fprintf(stderr, "Read function definition:"); FnIR->print(errs()); fprintf(stderr, "\n"); - ExitOnErr(TheJIT->addModule(std::move(TheModule))); + auto TSM = ThreadSafeModule(std::move(TheModule), std::move(TheContext)); + ExitOnErr(TheJIT->addModule(std::move(TSM))); InitializeModule(); } } else { @@ -1140,27 +1142,27 @@ static void HandleExtern() { } static void HandleTopLevelExpression() { - static unsigned ExprCount = 0; - - // Update ExprCount. This number will be added to anonymous expressions to - // prevent them from clashing. - ++ExprCount; - // Evaluate a top-level expression into an anonymous function. - if (auto FnAST = ParseTopLevelExpr(ExprCount)) { + if (auto FnAST = ParseTopLevelExpr()) { if (FnAST->codegen()) { - // JIT the module containing the anonymous expression, keeping a handle so - // we can free it later. - ExitOnErr(TheJIT->addModule(std::move(TheModule))); + // Create a ResourceTracker to track JIT'd memory allocated to our + // anonymous expression -- that way we can free it after executing. + auto RT = TheJIT->getMainJITDylib().createResourceTracker(); + + auto TSM = ThreadSafeModule(std::move(TheModule), std::move(TheContext)); + ExitOnErr(TheJIT->addModule(std::move(TSM), RT)); InitializeModule(); // Get the anonymous expression's JITSymbol. - auto Sym = - ExitOnErr(TheJIT->lookup(("__anon_expr" + Twine(ExprCount)).str())); + auto Sym = ExitOnErr(TheJIT->lookup("__anon_expr")); + // Get the symbol's address and cast it to the right type (takes no + // arguments, returns a double) so we can call it as a native function. auto *FP = (double (*)())(intptr_t)Sym.getAddress(); - assert(FP && "Failed to codegen function"); fprintf(stderr, "Evaluated to %f\n", FP()); + + // Delete the anonymous expression module from the JIT. + ExitOnErr(RT->remove()); } } else { // Skip token for error recovery. @@ -1229,8 +1231,6 @@ int main() { getNextToken(); TheJIT = ExitOnErr(KaleidoscopeJIT::Create()); - TheContext = &TheJIT->getContext(); - InitializeModule(); // Run the main "interpreter loop" now. diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h index 34c4b96..810a4cd 100644 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h @@ -13,139 +13,143 @@ #ifndef LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H #define LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H -#include "llvm/ADT/STLExtras.h" -#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h" #include "llvm/ExecutionEngine/Orc/CompileUtils.h" +#include "llvm/ExecutionEngine/Orc/Core.h" +#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" #include "llvm/ExecutionEngine/Orc/IRTransformLayer.h" -#include "llvm/ExecutionEngine/Orc/LambdaResolver.h" +#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" -#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" -#include "llvm/ExecutionEngine/RuntimeDyld.h" +#include "llvm/ExecutionEngine/Orc/TPCIndirectionUtils.h" +#include "llvm/ExecutionEngine/Orc/TargetProcessControl.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/IR/LegacyPassManager.h" -#include "llvm/IR/Mangler.h" -#include "llvm/Support/DynamicLibrary.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/InstCombine/InstCombine.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Scalar/GVN.h" -#include -#include #include -#include -#include -#include namespace llvm { namespace orc { class KaleidoscopeJIT { private: - ExecutionSession ES; - std::map> Resolvers; - std::unique_ptr TM; - const DataLayout DL; - LegacyRTDyldObjectLinkingLayer ObjectLayer; - LegacyIRCompileLayer CompileLayer; + std::unique_ptr TPC; + std::unique_ptr ES; + std::unique_ptr TPCIU; - using OptimizeFunction = - std::function(std::unique_ptr)>; + DataLayout DL; + MangleAndInterner Mangle; - LegacyIRTransformLayer OptimizeLayer; + RTDyldObjectLinkingLayer ObjectLayer; + IRCompileLayer CompileLayer; + IRTransformLayer OptimizeLayer; + CompileOnDemandLayer CODLayer; - std::unique_ptr CompileCallbackManager; - LegacyCompileOnDemandLayer CODLayer; + JITDylib &MainJD; + + static void handleLazyCallThroughError() { + errs() << "LazyCallThrough error: Could not find function body"; + exit(1); + } public: - KaleidoscopeJIT() - : TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()), - ObjectLayer(AcknowledgeORCv1Deprecation, ES, - [this](VModuleKey K) { - return LegacyRTDyldObjectLinkingLayer::Resources{ - std::make_shared(), - Resolvers[K]}; - }), - CompileLayer(AcknowledgeORCv1Deprecation, ObjectLayer, - SimpleCompiler(*TM)), - OptimizeLayer(AcknowledgeORCv1Deprecation, CompileLayer, - [this](std::unique_ptr M) { - return optimizeModule(std::move(M)); - }), - CompileCallbackManager(cantFail(orc::createLocalCompileCallbackManager( - TM->getTargetTriple(), ES, 0))), - CODLayer( - AcknowledgeORCv1Deprecation, 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())) { - llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr); + KaleidoscopeJIT(std::unique_ptr TPC, + std::unique_ptr ES, + std::unique_ptr TPCIU, + JITTargetMachineBuilder JTMB, DataLayout DL) + : TPC(std::move(TPC)), ES(std::move(ES)), TPCIU(std::move(TPCIU)), + DL(std::move(DL)), Mangle(*this->ES, this->DL), + ObjectLayer(*this->ES, + []() { return std::make_unique(); }), + CompileLayer(*this->ES, ObjectLayer, + std::make_unique(std::move(JTMB))), + OptimizeLayer(*this->ES, CompileLayer, optimizeModule), + CODLayer(*this->ES, OptimizeLayer, + this->TPCIU->getLazyCallThroughManager(), + [this] { return this->TPCIU->createIndirectStubsManager(); }), + MainJD(this->ES->createBareJITDylib("
")) { + MainJD.addGenerator( + cantFail(DynamicLibrarySearchGenerator::GetForCurrentProcess( + DL.getGlobalPrefix()))); + } + + ~KaleidoscopeJIT() { + if (auto Err = ES->endSession()) + ES->reportError(std::move(Err)); + if (auto Err = TPCIU->cleanup()) + ES->reportError(std::move(Err)); } - TargetMachine &getTargetMachine() { return *TM; } - - VModuleKey addModule(std::unique_ptr M) { - // Create a new VModuleKey. - VModuleKey K = ES.allocateVModule(); - - // Build a resolver and associate it with the new key. - Resolvers[K] = createLegacyLookupResolver( - ES, - [this](StringRef Name) -> JITSymbol { - if (auto Sym = CompileLayer.findSymbol(std::string(Name), false)) - return Sym; - else if (auto Err = Sym.takeError()) - return std::move(Err); - if (auto SymAddr = RTDyldMemoryManager::getSymbolAddressInProcess( - std::string(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. - cantFail(CODLayer.addModule(K, std::move(M))); - return K; + static Expected> Create() { + auto TPC = SelfTargetProcessControl::Create(); + if (!TPC) + return TPC.takeError(); + + auto ES = std::make_unique(); + + auto TPCIU = TPCIndirectionUtils::Create(**TPC); + if (!TPCIU) + return TPCIU.takeError(); + + (*TPCIU)->createLazyCallThroughManager( + *ES, pointerToJITTargetAddress(&handleLazyCallThroughError)); + + if (auto Err = setUpInProcessLCTMReentryViaTPCIU(**TPCIU)) + return std::move(Err); + + JITTargetMachineBuilder JTMB((*TPC)->getTargetTriple()); + + auto DL = JTMB.getDefaultDataLayoutForTarget(); + if (!DL) + return DL.takeError(); + + return std::make_unique(std::move(*TPC), std::move(ES), + std::move(*TPCIU), std::move(JTMB), + std::move(*DL)); } - JITSymbol findSymbol(const std::string Name) { - std::string MangledName; - raw_string_ostream MangledNameStream(MangledName); - Mangler::getNameWithPrefix(MangledNameStream, Name, DL); - return CODLayer.findSymbol(MangledNameStream.str(), true); + const DataLayout &getDataLayout() const { return DL; } + + JITDylib &getMainJITDylib() { return MainJD; } + + Error addModule(ThreadSafeModule TSM, ResourceTrackerSP RT = nullptr) { + if (!RT) + RT = MainJD.getDefaultResourceTracker(); + + return OptimizeLayer.add(RT, std::move(TSM)); } - void removeModule(VModuleKey K) { - cantFail(CODLayer.removeModule(K)); + Expected lookup(StringRef Name) { + return ES->lookup({&MainJD}, Mangle(Name.str())); } private: - std::unique_ptr optimizeModule(std::unique_ptr M) { - // Create a function pass manager. - auto FPM = std::make_unique(M.get()); - - // Add some optimizations. - FPM->add(createInstructionCombiningPass()); - FPM->add(createReassociatePass()); - FPM->add(createGVNPass()); - FPM->add(createCFGSimplificationPass()); - FPM->doInitialization(); - - // Run the optimizations over all functions in the module being added to - // the JIT. - for (auto &F : *M) - FPM->run(F); - - return M; + static Expected + optimizeModule(ThreadSafeModule TSM, const MaterializationResponsibility &R) { + TSM.withModuleDo([](Module &M) { + // Create a function pass manager. + auto FPM = std::make_unique(&M); + + // Add some optimizations. + FPM->add(createInstructionCombiningPass()); + FPM->add(createReassociatePass()); + FPM->add(createGVNPass()); + FPM->add(createCFGSimplificationPass()); + FPM->doInitialization(); + + // Run the optimizations over all functions in the module being added to + // the JIT. + for (auto &F : M) + FPM->run(F); + }); + + return std::move(TSM); } }; diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/toy.cpp b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/toy.cpp index d082e51..2a405ae 100644 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/toy.cpp +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/toy.cpp @@ -680,7 +680,7 @@ static std::unique_ptr ParseTopLevelExpr() { if (auto E = ParseExpression()) { // Make an anonymous proto. auto Proto = std::make_unique("__anon_expr", - std::vector()); + std::vector()); return std::make_unique(std::move(Proto), std::move(E)); } return nullptr; @@ -696,12 +696,13 @@ static std::unique_ptr ParseExtern() { // Code Generation //===----------------------------------------------------------------------===// -static LLVMContext TheContext; -static IRBuilder<> Builder(TheContext); +static std::unique_ptr TheJIT; +static std::unique_ptr TheContext; +static std::unique_ptr> Builder; static std::unique_ptr TheModule; static std::map NamedValues; -static std::unique_ptr TheJIT; static std::map> FunctionProtos; +static ExitOnError ExitOnErr; Value *LogErrorV(const char *Str) { LogError(Str); @@ -729,11 +730,11 @@ static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, StringRef VarName) { IRBuilder<> TmpB(&TheFunction->getEntryBlock(), TheFunction->getEntryBlock().begin()); - return TmpB.CreateAlloca(Type::getDoubleTy(TheContext), nullptr, VarName); + return TmpB.CreateAlloca(Type::getDoubleTy(*TheContext), nullptr, VarName); } Value *NumberExprAST::codegen() { - return ConstantFP::get(TheContext, APFloat(Val)); + return ConstantFP::get(*TheContext, APFloat(Val)); } Value *VariableExprAST::codegen() { @@ -743,7 +744,7 @@ Value *VariableExprAST::codegen() { return LogErrorV("Unknown variable name"); // Load the value. - return Builder.CreateLoad(V, Name.c_str()); + return Builder->CreateLoad(V, Name.c_str()); } Value *UnaryExprAST::codegen() { @@ -755,7 +756,7 @@ Value *UnaryExprAST::codegen() { if (!F) return LogErrorV("Unknown unary operator"); - return Builder.CreateCall(F, OperandV, "unop"); + return Builder->CreateCall(F, OperandV, "unop"); } Value *BinaryExprAST::codegen() { @@ -778,7 +779,7 @@ Value *BinaryExprAST::codegen() { if (!Variable) return LogErrorV("Unknown variable name"); - Builder.CreateStore(Val, Variable); + Builder->CreateStore(Val, Variable); return Val; } @@ -789,15 +790,15 @@ Value *BinaryExprAST::codegen() { switch (Op) { case '+': - return Builder.CreateFAdd(L, R, "addtmp"); + return Builder->CreateFAdd(L, R, "addtmp"); case '-': - return Builder.CreateFSub(L, R, "subtmp"); + return Builder->CreateFSub(L, R, "subtmp"); case '*': - return Builder.CreateFMul(L, R, "multmp"); + return Builder->CreateFMul(L, R, "multmp"); case '<': - L = Builder.CreateFCmpULT(L, R, "cmptmp"); + L = Builder->CreateFCmpULT(L, R, "cmptmp"); // Convert bool 0/1 to double 0.0 or 1.0 - return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); + return Builder->CreateUIToFP(L, Type::getDoubleTy(*TheContext), "booltmp"); default: break; } @@ -808,7 +809,7 @@ Value *BinaryExprAST::codegen() { assert(F && "binary operator not found!"); Value *Ops[] = {L, R}; - return Builder.CreateCall(F, Ops, "binop"); + return Builder->CreateCall(F, Ops, "binop"); } Value *CallExprAST::codegen() { @@ -828,7 +829,7 @@ Value *CallExprAST::codegen() { return nullptr; } - return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); + return Builder->CreateCall(CalleeF, ArgsV, "calltmp"); } Value *IfExprAST::codegen() { @@ -837,46 +838,46 @@ Value *IfExprAST::codegen() { return nullptr; // Convert condition to a bool by comparing equal to 0.0. - CondV = Builder.CreateFCmpONE( - CondV, ConstantFP::get(TheContext, APFloat(0.0)), "ifcond"); + CondV = Builder->CreateFCmpONE( + CondV, ConstantFP::get(*TheContext, APFloat(0.0)), "ifcond"); - Function *TheFunction = Builder.GetInsertBlock()->getParent(); + Function *TheFunction = Builder->GetInsertBlock()->getParent(); // Create blocks for the then and else cases. Insert the 'then' block at the // end of the function. - BasicBlock *ThenBB = BasicBlock::Create(TheContext, "then", TheFunction); - BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else"); - BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont"); + BasicBlock *ThenBB = BasicBlock::Create(*TheContext, "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(*TheContext, "else"); + BasicBlock *MergeBB = BasicBlock::Create(*TheContext, "ifcont"); - Builder.CreateCondBr(CondV, ThenBB, ElseBB); + Builder->CreateCondBr(CondV, ThenBB, ElseBB); // Emit then value. - Builder.SetInsertPoint(ThenBB); + Builder->SetInsertPoint(ThenBB); Value *ThenV = Then->codegen(); if (!ThenV) return nullptr; - Builder.CreateBr(MergeBB); + Builder->CreateBr(MergeBB); // Codegen of 'Then' can change the current block, update ThenBB for the PHI. - ThenBB = Builder.GetInsertBlock(); + ThenBB = Builder->GetInsertBlock(); // Emit else block. TheFunction->getBasicBlockList().push_back(ElseBB); - Builder.SetInsertPoint(ElseBB); + Builder->SetInsertPoint(ElseBB); Value *ElseV = Else->codegen(); if (!ElseV) return nullptr; - Builder.CreateBr(MergeBB); + Builder->CreateBr(MergeBB); // Codegen of 'Else' can change the current block, update ElseBB for the PHI. - ElseBB = Builder.GetInsertBlock(); + ElseBB = Builder->GetInsertBlock(); // Emit merge block. TheFunction->getBasicBlockList().push_back(MergeBB); - Builder.SetInsertPoint(MergeBB); - PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(TheContext), 2, "iftmp"); + Builder->SetInsertPoint(MergeBB); + PHINode *PN = Builder->CreatePHI(Type::getDoubleTy(*TheContext), 2, "iftmp"); PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); @@ -903,7 +904,7 @@ Value *IfExprAST::codegen() { // br endcond, loop, endloop // outloop: Value *ForExprAST::codegen() { - Function *TheFunction = Builder.GetInsertBlock()->getParent(); + Function *TheFunction = Builder->GetInsertBlock()->getParent(); // Create an alloca for the variable in the entry block. AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); @@ -914,17 +915,17 @@ Value *ForExprAST::codegen() { return nullptr; // Store the value into the alloca. - Builder.CreateStore(StartVal, Alloca); + Builder->CreateStore(StartVal, Alloca); // Make the new basic block for the loop header, inserting after current // block. - BasicBlock *LoopBB = BasicBlock::Create(TheContext, "loop", TheFunction); + BasicBlock *LoopBB = BasicBlock::Create(*TheContext, "loop", TheFunction); // Insert an explicit fall through from the current block to the LoopBB. - Builder.CreateBr(LoopBB); + Builder->CreateBr(LoopBB); // Start insertion in LoopBB. - Builder.SetInsertPoint(LoopBB); + Builder->SetInsertPoint(LoopBB); // Within the loop, the variable is defined equal to the PHI node. If it // shadows an existing variable, we have to restore it, so save it now. @@ -945,7 +946,7 @@ Value *ForExprAST::codegen() { return nullptr; } else { // If not specified, use 1.0. - StepVal = ConstantFP::get(TheContext, APFloat(1.0)); + StepVal = ConstantFP::get(*TheContext, APFloat(1.0)); } // Compute the end condition. @@ -955,23 +956,23 @@ Value *ForExprAST::codegen() { // Reload, increment, and restore the alloca. This handles the case where // the body of the loop mutates the variable. - Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str()); - Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar"); - Builder.CreateStore(NextVar, Alloca); + Value *CurVar = Builder->CreateLoad(Alloca, VarName.c_str()); + Value *NextVar = Builder->CreateFAdd(CurVar, StepVal, "nextvar"); + Builder->CreateStore(NextVar, Alloca); // Convert condition to a bool by comparing equal to 0.0. - EndCond = Builder.CreateFCmpONE( - EndCond, ConstantFP::get(TheContext, APFloat(0.0)), "loopcond"); + EndCond = Builder->CreateFCmpONE( + EndCond, ConstantFP::get(*TheContext, APFloat(0.0)), "loopcond"); // Create the "after loop" block and insert it. BasicBlock *AfterBB = - BasicBlock::Create(TheContext, "afterloop", TheFunction); + BasicBlock::Create(*TheContext, "afterloop", TheFunction); // Insert the conditional branch into the end of LoopEndBB. - Builder.CreateCondBr(EndCond, LoopBB, AfterBB); + Builder->CreateCondBr(EndCond, LoopBB, AfterBB); // Any new code will be inserted in AfterBB. - Builder.SetInsertPoint(AfterBB); + Builder->SetInsertPoint(AfterBB); // Restore the unshadowed variable. if (OldVal) @@ -980,13 +981,13 @@ Value *ForExprAST::codegen() { NamedValues.erase(VarName); // for expr always returns 0.0. - return Constant::getNullValue(Type::getDoubleTy(TheContext)); + return Constant::getNullValue(Type::getDoubleTy(*TheContext)); } Value *VarExprAST::codegen() { std::vector OldBindings; - Function *TheFunction = Builder.GetInsertBlock()->getParent(); + Function *TheFunction = Builder->GetInsertBlock()->getParent(); // Register all variables and emit their initializer. for (unsigned i = 0, e = VarNames.size(); i != e; ++i) { @@ -1004,11 +1005,11 @@ Value *VarExprAST::codegen() { if (!InitVal) return nullptr; } else { // If not specified, use 0.0. - InitVal = ConstantFP::get(TheContext, APFloat(0.0)); + InitVal = ConstantFP::get(*TheContext, APFloat(0.0)); } AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); - Builder.CreateStore(InitVal, Alloca); + Builder->CreateStore(InitVal, Alloca); // Remember the old variable binding so that we can restore the binding when // we unrecurse. @@ -1033,9 +1034,9 @@ Value *VarExprAST::codegen() { Function *PrototypeAST::codegen() { // Make the function type: double(double,double) etc. - std::vector Doubles(Args.size(), Type::getDoubleTy(TheContext)); + std::vector Doubles(Args.size(), Type::getDoubleTy(*TheContext)); FunctionType *FT = - FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); + FunctionType::get(Type::getDoubleTy(*TheContext), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get()); @@ -1062,8 +1063,8 @@ Function *FunctionAST::codegen() { BinopPrecedence[P.getOperatorName()] = P.getBinaryPrecedence(); // Create a new basic block to start insertion into. - BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); - Builder.SetInsertPoint(BB); + BasicBlock *BB = BasicBlock::Create(*TheContext, "entry", TheFunction); + Builder->SetInsertPoint(BB); // Record the function arguments in the NamedValues map. NamedValues.clear(); @@ -1072,7 +1073,7 @@ Function *FunctionAST::codegen() { AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, Arg.getName()); // Store the initial value into the alloca. - Builder.CreateStore(&Arg, Alloca); + Builder->CreateStore(&Arg, Alloca); // Add arguments to variable symbol table. NamedValues[std::string(Arg.getName())] = Alloca; @@ -1080,7 +1081,7 @@ Function *FunctionAST::codegen() { if (Value *RetVal = Body->codegen()) { // Finish off the function. - Builder.CreateRet(RetVal); + Builder->CreateRet(RetVal); // Validate the generated code, checking for consistency. verifyFunction(*TheFunction); @@ -1101,9 +1102,13 @@ Function *FunctionAST::codegen() { //===----------------------------------------------------------------------===// static void InitializeModule() { - // Open a new module. - TheModule = std::make_unique("my cool jit", TheContext); - TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout()); + // Open a new context and module. + TheContext = std::make_unique(); + TheModule = std::make_unique("my cool jit", *TheContext); + TheModule->setDataLayout(TheJIT->getDataLayout()); + + // Create a new builder for the module. + Builder = std::make_unique>(*TheContext); } static void HandleDefinition() { @@ -1112,7 +1117,8 @@ static void HandleDefinition() { fprintf(stderr, "Read function definition:"); FnIR->print(errs()); fprintf(stderr, "\n"); - TheJIT->addModule(std::move(TheModule)); + auto TSM = ThreadSafeModule(std::move(TheModule), std::move(TheContext)); + ExitOnErr(TheJIT->addModule(std::move(TSM))); InitializeModule(); } } else { @@ -1139,22 +1145,24 @@ static void HandleTopLevelExpression() { // Evaluate a top-level expression into an anonymous function. if (auto FnAST = ParseTopLevelExpr()) { if (FnAST->codegen()) { - // JIT the module containing the anonymous expression, keeping a handle so - // we can free it later. - auto H = TheJIT->addModule(std::move(TheModule)); + // Create a ResourceTracker to track JIT'd memory allocated to our + // anonymous expression -- that way we can free it after executing. + auto RT = TheJIT->getMainJITDylib().createResourceTracker(); + + auto TSM = ThreadSafeModule(std::move(TheModule), std::move(TheContext)); + ExitOnErr(TheJIT->addModule(std::move(TSM), RT)); InitializeModule(); - // Search the JIT for the __anon_expr symbol. - auto ExprSymbol = TheJIT->findSymbol("__anon_expr"); - assert(ExprSymbol && "Function not found"); + // Get the anonymous expression's JITSymbol. + auto Sym = ExitOnErr(TheJIT->lookup("__anon_expr")); // Get the symbol's address and cast it to the right type (takes no // arguments, returns a double) so we can call it as a native function. - double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress()); + auto *FP = (double (*)())(intptr_t)Sym.getAddress(); fprintf(stderr, "Evaluated to %f\n", FP()); // Delete the anonymous expression module from the JIT. - TheJIT->removeModule(H); + ExitOnErr(RT->remove()); } } else { // Skip token for error recovery. @@ -1222,8 +1230,7 @@ int main() { fprintf(stderr, "ready> "); getNextToken(); - TheJIT = std::make_unique(); - + TheJIT = ExitOnErr(KaleidoscopeJIT::Create()); InitializeModule(); // Run the main "interpreter loop" now. diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h index c875657..ba63e7c 100644 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h @@ -13,34 +13,26 @@ #ifndef LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H #define LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H -#include "llvm/ADT/STLExtras.h" -#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h" #include "llvm/ExecutionEngine/Orc/CompileUtils.h" +#include "llvm/ExecutionEngine/Orc/Core.h" +#include "llvm/ExecutionEngine/Orc/ExecutionUtils.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/JITTargetMachineBuilder.h" #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" -#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" +#include "llvm/ExecutionEngine/Orc/TPCIndirectionUtils.h" +#include "llvm/ExecutionEngine/Orc/TargetProcessControl.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/IR/LegacyPassManager.h" -#include "llvm/IR/Mangler.h" -#include "llvm/Support/DynamicLibrary.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/InstCombine/InstCombine.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Scalar/GVN.h" -#include -#include -#include -#include #include -#include -#include class PrototypeAST; class ExprAST; @@ -64,164 +56,191 @@ public: /// suffix (needed to prevent a name-clash with the function's stub), /// and then take ownership of the module that the function was compiled /// into. -std::unique_ptr -irgenAndTakeOwnership(FunctionAST &FnAST, const std::string &Suffix); +llvm::orc::ThreadSafeModule irgenAndTakeOwnership(FunctionAST &FnAST, + const std::string &Suffix); namespace llvm { namespace orc { -class KaleidoscopeJIT { -private: - ExecutionSession ES; - std::shared_ptr Resolver; - std::unique_ptr TM; - const DataLayout DL; - LegacyRTDyldObjectLinkingLayer ObjectLayer; - LegacyIRCompileLayer CompileLayer; +class KaleidoscopeASTLayer; +class KaleidoscopeJIT; + +class KaleidoscopeASTMaterializationUnit : public MaterializationUnit { +public: + KaleidoscopeASTMaterializationUnit(KaleidoscopeASTLayer &L, + std::unique_ptr F); + + StringRef getName() const override { + return "KaleidoscopeASTMaterializationUnit"; + } - using OptimizeFunction = - std::function(std::unique_ptr)>; + void materialize(std::unique_ptr R) override; - LegacyIRTransformLayer OptimizeLayer; +private: + void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override { + llvm_unreachable("Kaleidoscope functions are not overridable"); + } - std::unique_ptr CompileCallbackMgr; - std::unique_ptr IndirectStubsMgr; + KaleidoscopeASTLayer &L; + std::unique_ptr F; +}; +class KaleidoscopeASTLayer { public: - KaleidoscopeJIT() - : Resolver(createLegacyLookupResolver( - ES, - [this](StringRef Name) -> JITSymbol { - if (auto Sym = IndirectStubsMgr->findStub(Name, false)) - return Sym; - if (auto Sym = OptimizeLayer.findSymbol(std::string(Name), false)) - return Sym; - else if (auto Err = Sym.takeError()) - return std::move(Err); - if (auto SymAddr = RTDyldMemoryManager::getSymbolAddressInProcess( - std::string(Name))) - return JITSymbol(SymAddr, JITSymbolFlags::Exported); - return nullptr; - }, - [](Error Err) { cantFail(std::move(Err), "lookupFlags failed"); })), - TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()), - ObjectLayer(AcknowledgeORCv1Deprecation, ES, - [this](VModuleKey K) { - return LegacyRTDyldObjectLinkingLayer::Resources{ - std::make_shared(), Resolver}; - }), - CompileLayer(AcknowledgeORCv1Deprecation, ObjectLayer, - SimpleCompiler(*TM)), - OptimizeLayer(AcknowledgeORCv1Deprecation, CompileLayer, - [this](std::unique_ptr M) { - return optimizeModule(std::move(M)); - }), - CompileCallbackMgr(cantFail(orc::createLocalCompileCallbackManager( - TM->getTargetTriple(), ES, 0))) { - auto IndirectStubsMgrBuilder = - orc::createLocalIndirectStubsManagerBuilder(TM->getTargetTriple()); - IndirectStubsMgr = IndirectStubsMgrBuilder(); - llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr); + KaleidoscopeASTLayer(IRLayer &BaseLayer, const DataLayout &DL) + : BaseLayer(BaseLayer), DL(DL) {} + + Error add(ResourceTrackerSP RT, std::unique_ptr F) { + return RT->getJITDylib().define( + std::make_unique(*this, + std::move(F)), + RT); } - TargetMachine &getTargetMachine() { return *TM; } + void emit(std::unique_ptr MR, + std::unique_ptr F) { + BaseLayer.emit(std::move(MR), irgenAndTakeOwnership(*F, "")); + } - VModuleKey addModule(std::unique_ptr M) { - // Add the module to the JIT with a new VModuleKey. - auto K = ES.allocateVModule(); - cantFail(OptimizeLayer.addModule(K, std::move(M))); - return K; + SymbolFlagsMap getInterface(FunctionAST &F) { + MangleAndInterner Mangle(BaseLayer.getExecutionSession(), DL); + SymbolFlagsMap Symbols; + Symbols[Mangle(F.getName())] = + JITSymbolFlags(JITSymbolFlags::Exported | JITSymbolFlags::Callable); + return Symbols; } - Error addFunctionAST(std::unique_ptr FnAST) { - // Move ownership of FnAST to a shared pointer - C++11 lambdas don't support - // capture-by-move, which is be required for unique_ptr. - auto SharedFnAST = std::shared_ptr(std::move(FnAST)); - - // Set the action to compile our AST. This lambda will be run if/when - // execution hits the compile callback (via the stub). - // - // The steps to compile are: - // (1) IRGen the function. - // (2) Add the IR module to the JIT to make it executable like any other - // module. - // (3) Use findSymbol to get the address of the compiled function. - // (4) Update the stub pointer to point at the implementation so that - /// subsequent calls go directly to it and bypass the compiler. - // (5) Return the address of the implementation: this lambda will actually - // be run inside an attempted call to the function, and we need to - // continue on to the implementation to complete the attempted call. - // The JIT runtime (the resolver block) will use the return address of - // this function as the address to continue at once it has reset the - // CPU state to what it was immediately before the call. - auto CompileAction = [this, SharedFnAST]() { - auto M = irgenAndTakeOwnership(*SharedFnAST, "$impl"); - addModule(std::move(M)); - auto Sym = findSymbol(SharedFnAST->getName() + "$impl"); - assert(Sym && "Couldn't find compiled function?"); - JITTargetAddress SymAddr = cantFail(Sym.getAddress()); - if (auto Err = IndirectStubsMgr->updatePointer( - mangle(SharedFnAST->getName()), SymAddr)) { - logAllUnhandledErrors(std::move(Err), errs(), - "Error updating function pointer: "); - exit(1); - } - - return SymAddr; - }; - - // Create a CompileCallback using the CompileAction - this is the re-entry - // point into the compiler for functions that haven't been compiled yet. - auto CCAddr = cantFail( - CompileCallbackMgr->getCompileCallback(std::move(CompileAction))); - - // Create an indirect stub. This serves as the functions "canonical - // definition" - an unchanging (constant address) entry point to the - // function implementation. - // Initially we point the stub's function-pointer at the compile callback - // that we just created. When the compile action for the callback is run we - // will update the stub's function pointer to point at the function - // implementation that we just implemented. - if (auto Err = IndirectStubsMgr->createStub( - mangle(SharedFnAST->getName()), CCAddr, JITSymbolFlags::Exported)) - return Err; - - return Error::success(); +private: + IRLayer &BaseLayer; + const DataLayout &DL; +}; + +KaleidoscopeASTMaterializationUnit::KaleidoscopeASTMaterializationUnit( + KaleidoscopeASTLayer &L, std::unique_ptr F) + : MaterializationUnit(L.getInterface(*F), nullptr), L(L), F(std::move(F)) {} + +void KaleidoscopeASTMaterializationUnit::materialize( + std::unique_ptr R) { + L.emit(std::move(R), std::move(F)); +} + +class KaleidoscopeJIT { +private: + std::unique_ptr TPC; + std::unique_ptr ES; + std::unique_ptr TPCIU; + + DataLayout DL; + MangleAndInterner Mangle; + + RTDyldObjectLinkingLayer ObjectLayer; + IRCompileLayer CompileLayer; + IRTransformLayer OptimizeLayer; + KaleidoscopeASTLayer ASTLayer; + + JITDylib &MainJD; + + static void handleLazyCallThroughError() { + errs() << "LazyCallThrough error: Could not find function body"; + exit(1); } - JITSymbol findSymbol(const std::string Name) { - return OptimizeLayer.findSymbol(mangle(Name), true); +public: + KaleidoscopeJIT(std::unique_ptr TPC, + std::unique_ptr ES, + std::unique_ptr TPCIU, + JITTargetMachineBuilder JTMB, DataLayout DL) + : TPC(std::move(TPC)), ES(std::move(ES)), TPCIU(std::move(TPCIU)), + DL(std::move(DL)), Mangle(*this->ES, this->DL), + ObjectLayer(*this->ES, + []() { return std::make_unique(); }), + CompileLayer(*this->ES, ObjectLayer, + std::make_unique(std::move(JTMB))), + OptimizeLayer(*this->ES, CompileLayer, optimizeModule), + ASTLayer(OptimizeLayer, this->DL), + MainJD(this->ES->createBareJITDylib("
")) { + MainJD.addGenerator( + cantFail(DynamicLibrarySearchGenerator::GetForCurrentProcess( + DL.getGlobalPrefix()))); } - void removeModule(VModuleKey K) { - cantFail(OptimizeLayer.removeModule(K)); + ~KaleidoscopeJIT() { + if (auto Err = ES->endSession()) + ES->reportError(std::move(Err)); + if (auto Err = TPCIU->cleanup()) + ES->reportError(std::move(Err)); } -private: - std::string mangle(const std::string &Name) { - std::string MangledName; - raw_string_ostream MangledNameStream(MangledName); - Mangler::getNameWithPrefix(MangledNameStream, Name, DL); - return MangledNameStream.str(); + static Expected> Create() { + auto TPC = SelfTargetProcessControl::Create(); + if (!TPC) + return TPC.takeError(); + + auto ES = std::make_unique(); + + auto TPCIU = TPCIndirectionUtils::Create(**TPC); + if (!TPCIU) + return TPCIU.takeError(); + + (*TPCIU)->createLazyCallThroughManager( + *ES, pointerToJITTargetAddress(&handleLazyCallThroughError)); + + if (auto Err = setUpInProcessLCTMReentryViaTPCIU(**TPCIU)) + return std::move(Err); + + JITTargetMachineBuilder JTMB((*TPC)->getTargetTriple()); + + auto DL = JTMB.getDefaultDataLayoutForTarget(); + if (!DL) + return DL.takeError(); + + return std::make_unique(std::move(*TPC), std::move(ES), + std::move(*TPCIU), std::move(JTMB), + std::move(*DL)); } - std::unique_ptr optimizeModule(std::unique_ptr M) { - // Create a function pass manager. - auto FPM = std::make_unique(M.get()); + const DataLayout &getDataLayout() const { return DL; } - // Add some optimizations. - FPM->add(createInstructionCombiningPass()); - FPM->add(createReassociatePass()); - FPM->add(createGVNPass()); - FPM->add(createCFGSimplificationPass()); - FPM->doInitialization(); + JITDylib &getMainJITDylib() { return MainJD; } - // Run the optimizations over all functions in the module being added to - // the JIT. - for (auto &F : *M) - FPM->run(F); + Error addModule(ThreadSafeModule TSM, ResourceTrackerSP RT = nullptr) { + if (!RT) + RT = MainJD.getDefaultResourceTracker(); - return M; + return OptimizeLayer.add(RT, std::move(TSM)); + } + + Error addAST(std::unique_ptr F, ResourceTrackerSP RT = nullptr) { + if (!RT) + RT = MainJD.getDefaultResourceTracker(); + return ASTLayer.add(RT, std::move(F)); + } + + Expected lookup(StringRef Name) { + return ES->lookup({&MainJD}, Mangle(Name.str())); + } + +private: + static Expected + optimizeModule(ThreadSafeModule TSM, const MaterializationResponsibility &R) { + TSM.withModuleDo([](Module &M) { + // Create a function pass manager. + auto FPM = std::make_unique(&M); + + // Add some optimizations. + FPM->add(createInstructionCombiningPass()); + FPM->add(createReassociatePass()); + FPM->add(createGVNPass()); + FPM->add(createCFGSimplificationPass()); + FPM->doInitialization(); + + // Run the optimizations over all functions in the module being added to + // the JIT. + for (auto &F : M) + FPM->run(F); + }); + + return std::move(TSM); } }; diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/toy.cpp b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/toy.cpp index e39e8a9..dc6d9da 100644 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/toy.cpp +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/toy.cpp @@ -10,8 +10,6 @@ #include "llvm/IR/Module.h" #include "llvm/IR/Type.h" #include "llvm/IR/Verifier.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Target/TargetMachine.h" #include "KaleidoscopeJIT.h" @@ -665,7 +663,7 @@ static std::unique_ptr ParseTopLevelExpr() { if (auto E = ParseExpression()) { // Make an anonymous proto. auto Proto = std::make_unique("__anon_expr", - std::vector()); + std::vector()); return std::make_unique(std::move(Proto), std::move(E)); } return nullptr; @@ -681,11 +679,11 @@ static std::unique_ptr ParseExtern() { // Code Generation //===----------------------------------------------------------------------===// -static LLVMContext TheContext; -static IRBuilder<> Builder(TheContext); +static std::unique_ptr TheJIT; +static std::unique_ptr TheContext; +static std::unique_ptr> Builder; static std::unique_ptr TheModule; static std::map NamedValues; -static std::unique_ptr TheJIT; static std::map> FunctionProtos; static ExitOnError ExitOnErr; @@ -715,11 +713,11 @@ static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, StringRef VarName) { IRBuilder<> TmpB(&TheFunction->getEntryBlock(), TheFunction->getEntryBlock().begin()); - return TmpB.CreateAlloca(Type::getDoubleTy(TheContext), nullptr, VarName); + return TmpB.CreateAlloca(Type::getDoubleTy(*TheContext), nullptr, VarName); } Value *NumberExprAST::codegen() { - return ConstantFP::get(TheContext, APFloat(Val)); + return ConstantFP::get(*TheContext, APFloat(Val)); } Value *VariableExprAST::codegen() { @@ -729,7 +727,7 @@ Value *VariableExprAST::codegen() { return LogErrorV("Unknown variable name"); // Load the value. - return Builder.CreateLoad(V, Name.c_str()); + return Builder->CreateLoad(V, Name.c_str()); } Value *UnaryExprAST::codegen() { @@ -741,7 +739,7 @@ Value *UnaryExprAST::codegen() { if (!F) return LogErrorV("Unknown unary operator"); - return Builder.CreateCall(F, OperandV, "unop"); + return Builder->CreateCall(F, OperandV, "unop"); } Value *BinaryExprAST::codegen() { @@ -764,7 +762,7 @@ Value *BinaryExprAST::codegen() { if (!Variable) return LogErrorV("Unknown variable name"); - Builder.CreateStore(Val, Variable); + Builder->CreateStore(Val, Variable); return Val; } @@ -775,15 +773,15 @@ Value *BinaryExprAST::codegen() { switch (Op) { case '+': - return Builder.CreateFAdd(L, R, "addtmp"); + return Builder->CreateFAdd(L, R, "addtmp"); case '-': - return Builder.CreateFSub(L, R, "subtmp"); + return Builder->CreateFSub(L, R, "subtmp"); case '*': - return Builder.CreateFMul(L, R, "multmp"); + return Builder->CreateFMul(L, R, "multmp"); case '<': - L = Builder.CreateFCmpULT(L, R, "cmptmp"); + L = Builder->CreateFCmpULT(L, R, "cmptmp"); // Convert bool 0/1 to double 0.0 or 1.0 - return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); + return Builder->CreateUIToFP(L, Type::getDoubleTy(*TheContext), "booltmp"); default: break; } @@ -794,7 +792,7 @@ Value *BinaryExprAST::codegen() { assert(F && "binary operator not found!"); Value *Ops[] = {L, R}; - return Builder.CreateCall(F, Ops, "binop"); + return Builder->CreateCall(F, Ops, "binop"); } Value *CallExprAST::codegen() { @@ -814,7 +812,7 @@ Value *CallExprAST::codegen() { return nullptr; } - return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); + return Builder->CreateCall(CalleeF, ArgsV, "calltmp"); } Value *IfExprAST::codegen() { @@ -823,46 +821,46 @@ Value *IfExprAST::codegen() { return nullptr; // Convert condition to a bool by comparing equal to 0.0. - CondV = Builder.CreateFCmpONE( - CondV, ConstantFP::get(TheContext, APFloat(0.0)), "ifcond"); + CondV = Builder->CreateFCmpONE( + CondV, ConstantFP::get(*TheContext, APFloat(0.0)), "ifcond"); - Function *TheFunction = Builder.GetInsertBlock()->getParent(); + Function *TheFunction = Builder->GetInsertBlock()->getParent(); // Create blocks for the then and else cases. Insert the 'then' block at the // end of the function. - BasicBlock *ThenBB = BasicBlock::Create(TheContext, "then", TheFunction); - BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else"); - BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont"); + BasicBlock *ThenBB = BasicBlock::Create(*TheContext, "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(*TheContext, "else"); + BasicBlock *MergeBB = BasicBlock::Create(*TheContext, "ifcont"); - Builder.CreateCondBr(CondV, ThenBB, ElseBB); + Builder->CreateCondBr(CondV, ThenBB, ElseBB); // Emit then value. - Builder.SetInsertPoint(ThenBB); + Builder->SetInsertPoint(ThenBB); Value *ThenV = Then->codegen(); if (!ThenV) return nullptr; - Builder.CreateBr(MergeBB); + Builder->CreateBr(MergeBB); // Codegen of 'Then' can change the current block, update ThenBB for the PHI. - ThenBB = Builder.GetInsertBlock(); + ThenBB = Builder->GetInsertBlock(); // Emit else block. TheFunction->getBasicBlockList().push_back(ElseBB); - Builder.SetInsertPoint(ElseBB); + Builder->SetInsertPoint(ElseBB); Value *ElseV = Else->codegen(); if (!ElseV) return nullptr; - Builder.CreateBr(MergeBB); + Builder->CreateBr(MergeBB); // Codegen of 'Else' can change the current block, update ElseBB for the PHI. - ElseBB = Builder.GetInsertBlock(); + ElseBB = Builder->GetInsertBlock(); // Emit merge block. TheFunction->getBasicBlockList().push_back(MergeBB); - Builder.SetInsertPoint(MergeBB); - PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(TheContext), 2, "iftmp"); + Builder->SetInsertPoint(MergeBB); + PHINode *PN = Builder->CreatePHI(Type::getDoubleTy(*TheContext), 2, "iftmp"); PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); @@ -889,7 +887,7 @@ Value *IfExprAST::codegen() { // br endcond, loop, endloop // outloop: Value *ForExprAST::codegen() { - Function *TheFunction = Builder.GetInsertBlock()->getParent(); + Function *TheFunction = Builder->GetInsertBlock()->getParent(); // Create an alloca for the variable in the entry block. AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); @@ -900,17 +898,17 @@ Value *ForExprAST::codegen() { return nullptr; // Store the value into the alloca. - Builder.CreateStore(StartVal, Alloca); + Builder->CreateStore(StartVal, Alloca); // Make the new basic block for the loop header, inserting after current // block. - BasicBlock *LoopBB = BasicBlock::Create(TheContext, "loop", TheFunction); + BasicBlock *LoopBB = BasicBlock::Create(*TheContext, "loop", TheFunction); // Insert an explicit fall through from the current block to the LoopBB. - Builder.CreateBr(LoopBB); + Builder->CreateBr(LoopBB); // Start insertion in LoopBB. - Builder.SetInsertPoint(LoopBB); + Builder->SetInsertPoint(LoopBB); // Within the loop, the variable is defined equal to the PHI node. If it // shadows an existing variable, we have to restore it, so save it now. @@ -931,7 +929,7 @@ Value *ForExprAST::codegen() { return nullptr; } else { // If not specified, use 1.0. - StepVal = ConstantFP::get(TheContext, APFloat(1.0)); + StepVal = ConstantFP::get(*TheContext, APFloat(1.0)); } // Compute the end condition. @@ -941,23 +939,23 @@ Value *ForExprAST::codegen() { // Reload, increment, and restore the alloca. This handles the case where // the body of the loop mutates the variable. - Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str()); - Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar"); - Builder.CreateStore(NextVar, Alloca); + Value *CurVar = Builder->CreateLoad(Alloca, VarName.c_str()); + Value *NextVar = Builder->CreateFAdd(CurVar, StepVal, "nextvar"); + Builder->CreateStore(NextVar, Alloca); // Convert condition to a bool by comparing equal to 0.0. - EndCond = Builder.CreateFCmpONE( - EndCond, ConstantFP::get(TheContext, APFloat(0.0)), "loopcond"); + EndCond = Builder->CreateFCmpONE( + EndCond, ConstantFP::get(*TheContext, APFloat(0.0)), "loopcond"); // Create the "after loop" block and insert it. BasicBlock *AfterBB = - BasicBlock::Create(TheContext, "afterloop", TheFunction); + BasicBlock::Create(*TheContext, "afterloop", TheFunction); // Insert the conditional branch into the end of LoopEndBB. - Builder.CreateCondBr(EndCond, LoopBB, AfterBB); + Builder->CreateCondBr(EndCond, LoopBB, AfterBB); // Any new code will be inserted in AfterBB. - Builder.SetInsertPoint(AfterBB); + Builder->SetInsertPoint(AfterBB); // Restore the unshadowed variable. if (OldVal) @@ -966,13 +964,13 @@ Value *ForExprAST::codegen() { NamedValues.erase(VarName); // for expr always returns 0.0. - return Constant::getNullValue(Type::getDoubleTy(TheContext)); + return Constant::getNullValue(Type::getDoubleTy(*TheContext)); } Value *VarExprAST::codegen() { std::vector OldBindings; - Function *TheFunction = Builder.GetInsertBlock()->getParent(); + Function *TheFunction = Builder->GetInsertBlock()->getParent(); // Register all variables and emit their initializer. for (unsigned i = 0, e = VarNames.size(); i != e; ++i) { @@ -990,11 +988,11 @@ Value *VarExprAST::codegen() { if (!InitVal) return nullptr; } else { // If not specified, use 0.0. - InitVal = ConstantFP::get(TheContext, APFloat(0.0)); + InitVal = ConstantFP::get(*TheContext, APFloat(0.0)); } AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); - Builder.CreateStore(InitVal, Alloca); + Builder->CreateStore(InitVal, Alloca); // Remember the old variable binding so that we can restore the binding when // we unrecurse. @@ -1019,9 +1017,9 @@ Value *VarExprAST::codegen() { Function *PrototypeAST::codegen() { // Make the function type: double(double,double) etc. - std::vector Doubles(Args.size(), Type::getDoubleTy(TheContext)); + std::vector Doubles(Args.size(), Type::getDoubleTy(*TheContext)); FunctionType *FT = - FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); + FunctionType::get(Type::getDoubleTy(*TheContext), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get()); @@ -1046,6 +1044,7 @@ Function *FunctionAST::codegen() { // Transfer ownership of the prototype to the FunctionProtos map, but keep a // reference to it for use below. auto &P = *Proto; + FunctionProtos[Proto->getName()] = std::move(Proto); Function *TheFunction = getFunction(P.getName()); if (!TheFunction) return nullptr; @@ -1055,8 +1054,8 @@ Function *FunctionAST::codegen() { BinopPrecedence[P.getOperatorName()] = P.getBinaryPrecedence(); // Create a new basic block to start insertion into. - BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); - Builder.SetInsertPoint(BB); + BasicBlock *BB = BasicBlock::Create(*TheContext, "entry", TheFunction); + Builder->SetInsertPoint(BB); // Record the function arguments in the NamedValues map. NamedValues.clear(); @@ -1065,7 +1064,7 @@ Function *FunctionAST::codegen() { AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, Arg.getName()); // Store the initial value into the alloca. - Builder.CreateStore(&Arg, Alloca); + Builder->CreateStore(&Arg, Alloca); // Add arguments to variable symbol table. NamedValues[std::string(Arg.getName())] = Alloca; @@ -1073,7 +1072,7 @@ Function *FunctionAST::codegen() { if (Value *RetVal = Body->codegen()) { // Finish off the function. - Builder.CreateRet(RetVal); + Builder->CreateRet(RetVal); // Validate the generated code, checking for consistency. verifyFunction(*TheFunction); @@ -1085,7 +1084,7 @@ Function *FunctionAST::codegen() { TheFunction->eraseFromParent(); if (P.isBinaryOp()) - BinopPrecedence.erase(Proto->getOperatorName()); + BinopPrecedence.erase(P.getOperatorName()); return nullptr; } @@ -1094,19 +1093,23 @@ Function *FunctionAST::codegen() { //===----------------------------------------------------------------------===// static void InitializeModule() { - // Open a new module. - TheModule = std::make_unique("my cool jit", TheContext); - TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout()); + // Open a new context and module. + TheContext = std::make_unique(); + TheModule = std::make_unique("my cool jit", *TheContext); + TheModule->setDataLayout(TheJIT->getDataLayout()); + + // Create a new builder for the module. + Builder = std::make_unique>(*TheContext); } -std::unique_ptr -irgenAndTakeOwnership(FunctionAST &FnAST, const std::string &Suffix) { +ThreadSafeModule irgenAndTakeOwnership(FunctionAST &FnAST, + const std::string &Suffix) { if (auto *F = FnAST.codegen()) { F->setName(F->getName() + Suffix); - auto M = std::move(TheModule); + auto TSM = ThreadSafeModule(std::move(TheModule), std::move(TheContext)); // Start a new module. InitializeModule(); - return M; + return TSM; } else report_fatal_error("Couldn't compile lazily JIT'd function"); } @@ -1115,7 +1118,7 @@ static void HandleDefinition() { if (auto FnAST = ParseDefinition()) { FunctionProtos[FnAST->getProto().getName()] = std::make_unique(FnAST->getProto()); - ExitOnErr(TheJIT->addFunctionAST(std::move(FnAST))); + ExitOnErr(TheJIT->addAST(std::move(FnAST))); } else { // Skip token for error recovery. getNextToken(); @@ -1139,25 +1142,25 @@ static void HandleExtern() { static void HandleTopLevelExpression() { // Evaluate a top-level expression into an anonymous function. if (auto FnAST = ParseTopLevelExpr()) { - FunctionProtos[FnAST->getName()] = - std::make_unique(FnAST->getProto()); if (FnAST->codegen()) { - // JIT the module containing the anonymous expression, keeping a handle so - // we can free it later. - auto H = TheJIT->addModule(std::move(TheModule)); + // Create a ResourceTracker to track JIT'd memory allocated to our + // anonymous expression -- that way we can free it after executing. + auto RT = TheJIT->getMainJITDylib().createResourceTracker(); + + auto TSM = ThreadSafeModule(std::move(TheModule), std::move(TheContext)); + ExitOnErr(TheJIT->addModule(std::move(TSM), RT)); InitializeModule(); - // Search the JIT for the __anon_expr symbol. - auto ExprSymbol = TheJIT->findSymbol("__anon_expr"); - assert(ExprSymbol && "Function not found"); + // Get the anonymous expression's JITSymbol. + auto Sym = ExitOnErr(TheJIT->lookup("__anon_expr")); // Get the symbol's address and cast it to the right type (takes no // arguments, returns a double) so we can call it as a native function. - double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress()); + auto *FP = (double (*)())(intptr_t)Sym.getAddress(); fprintf(stderr, "Evaluated to %f\n", FP()); // Delete the anonymous expression module from the JIT. - TheJIT->removeModule(H); + ExitOnErr(RT->remove()); } } else { // Skip token for error recovery. @@ -1213,8 +1216,6 @@ int main() { InitializeNativeTargetAsmPrinter(); InitializeNativeTargetAsmParser(); - ExitOnErr.setBanner("Kaleidoscope: "); - // Install standard binary operators. // 1 is lowest precedence. BinopPrecedence['='] = 2; @@ -1227,8 +1228,7 @@ int main() { fprintf(stderr, "ready> "); getNextToken(); - TheJIT = std::make_unique(); - + TheJIT = ExitOnErr(KaleidoscopeJIT::Create()); InitializeModule(); // Run the main "interpreter loop" now. diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/CMakeLists.txt b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/CMakeLists.txt deleted file mode 100644 index 48d7299..0000000 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -add_subdirectory(Server) - -set(LLVM_LINK_COMPONENTS - Analysis - Core - ExecutionEngine - InstCombine - Object - OrcError - OrcJIT - RuntimeDyld - ScalarOpts - Support - TransformUtils - native - ) - -add_kaleidoscope_chapter(BuildingAJIT-Ch5 - toy.cpp - ) - -export_executable_symbols(BuildingAJIT-Ch5) diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h deleted file mode 100644 index d22f893..0000000 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h +++ /dev/null @@ -1,248 +0,0 @@ -//===- KaleidoscopeJIT.h - A simple JIT for Kaleidoscope --------*- 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 -// -//===----------------------------------------------------------------------===// -// -// Contains a simple JIT definition for use in the kaleidoscope tutorials. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H -#define LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H - -#include "RemoteJITUtils.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/IRCompileLayer.h" -#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h" -#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" -#include "llvm/ExecutionEngine/Orc/LambdaResolver.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" -#include "llvm/Support/DynamicLibrary.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Transforms/InstCombine/InstCombine.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/Scalar/GVN.h" -#include -#include -#include -#include -#include -#include -#include - -class PrototypeAST; -class ExprAST; - -/// FunctionAST - This class represents a function definition itself. -class FunctionAST { - std::unique_ptr Proto; - std::unique_ptr Body; - -public: - FunctionAST(std::unique_ptr Proto, - std::unique_ptr Body) - : Proto(std::move(Proto)), Body(std::move(Body)) {} - - const PrototypeAST& getProto() const; - const std::string& getName() const; - llvm::Function *codegen(); -}; - -/// This will compile FnAST to IR, rename the function to add the given -/// suffix (needed to prevent a name-clash with the function's stub), -/// and then take ownership of the module that the function was compiled -/// into. -std::unique_ptr -irgenAndTakeOwnership(FunctionAST &FnAST, const std::string &Suffix); - -namespace llvm { -namespace orc { - -// Typedef the remote-client API. -using MyRemote = remote::OrcRemoteTargetClient; - -class KaleidoscopeJIT { -private: - ExecutionSession &ES; - std::shared_ptr Resolver; - std::unique_ptr TM; - const DataLayout DL; - LegacyRTDyldObjectLinkingLayer ObjectLayer; - LegacyIRCompileLayer CompileLayer; - - using OptimizeFunction = - std::function(std::unique_ptr)>; - - LegacyIRTransformLayer OptimizeLayer; - - JITCompileCallbackManager *CompileCallbackMgr; - std::unique_ptr IndirectStubsMgr; - MyRemote &Remote; - -public: - KaleidoscopeJIT(ExecutionSession &ES, MyRemote &Remote) - : ES(ES), - Resolver(createLegacyLookupResolver( - ES, - [this](StringRef Name) -> JITSymbol { - if (auto Sym = IndirectStubsMgr->findStub(Name, false)) - return Sym; - if (auto Sym = OptimizeLayer.findSymbol(std::string(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(AcknowledgeORCv1Deprecation, ES, - [this](VModuleKey K) { - return LegacyRTDyldObjectLinkingLayer::Resources{ - cantFail(this->Remote.createRemoteMemoryManager()), - Resolver}; - }), - CompileLayer(AcknowledgeORCv1Deprecation, ObjectLayer, - SimpleCompiler(*TM)), - OptimizeLayer(AcknowledgeORCv1Deprecation, CompileLayer, - [this](std::unique_ptr M) { - return optimizeModule(std::move(M)); - }), - Remote(Remote) { - auto CCMgrOrErr = Remote.enableCompileCallbacks(0); - if (!CCMgrOrErr) { - logAllUnhandledErrors(CCMgrOrErr.takeError(), errs(), - "Error enabling remote compile callbacks:"); - exit(1); - } - CompileCallbackMgr = &*CCMgrOrErr; - IndirectStubsMgr = cantFail(Remote.createIndirectStubsManager()); - llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr); - } - - TargetMachine &getTargetMachine() { return *TM; } - - VModuleKey addModule(std::unique_ptr M) { - // Add the module with a new VModuleKey. - auto K = ES.allocateVModule(); - cantFail(OptimizeLayer.addModule(K, std::move(M))); - return K; - } - - Error addFunctionAST(std::unique_ptr FnAST) { - // Move ownership of FnAST to a shared pointer - C++11 lambdas don't support - // capture-by-move, which is be required for unique_ptr. - auto SharedFnAST = std::shared_ptr(std::move(FnAST)); - - // Set the action to compile our AST. This lambda will be run if/when - // execution hits the compile callback (via the stub). - // - // The steps to compile are: - // (1) IRGen the function. - // (2) Add the IR module to the JIT to make it executable like any other - // module. - // (3) Use findSymbol to get the address of the compiled function. - // (4) Update the stub pointer to point at the implementation so that - /// subsequent calls go directly to it and bypass the compiler. - // (5) Return the address of the implementation: this lambda will actually - // be run inside an attempted call to the function, and we need to - // continue on to the implementation to complete the attempted call. - // The JIT runtime (the resolver block) will use the return address of - // this function as the address to continue at once it has reset the - // CPU state to what it was immediately before the call. - auto CompileAction = [this, SharedFnAST]() { - auto M = irgenAndTakeOwnership(*SharedFnAST, "$impl"); - addModule(std::move(M)); - auto Sym = findSymbol(SharedFnAST->getName() + "$impl"); - assert(Sym && "Couldn't find compiled function?"); - JITTargetAddress SymAddr = cantFail(Sym.getAddress()); - if (auto Err = IndirectStubsMgr->updatePointer( - mangle(SharedFnAST->getName()), SymAddr)) { - logAllUnhandledErrors(std::move(Err), errs(), - "Error updating function pointer: "); - exit(1); - } - - return SymAddr; - }; - - // Create a CompileCallback suing the CompileAction - this is the re-entry - // point into the compiler for functions that haven't been compiled yet. - auto CCAddr = cantFail( - CompileCallbackMgr->getCompileCallback(std::move(CompileAction))); - - // Create an indirect stub. This serves as the functions "canonical - // definition" - an unchanging (constant address) entry point to the - // function implementation. - // Initially we point the stub's function-pointer at the compile callback - // that we just created. In the compile action for the callback we will - // update the stub's function pointer to point at the function - // implementation that we just implemented. - if (auto Err = IndirectStubsMgr->createStub( - mangle(SharedFnAST->getName()), CCAddr, JITSymbolFlags::Exported)) - return Err; - - return Error::success(); - } - - Error executeRemoteExpr(JITTargetAddress ExprAddr) { - return Remote.callVoidVoid(ExprAddr); - } - - JITSymbol findSymbol(const std::string Name) { - return OptimizeLayer.findSymbol(mangle(Name), true); - } - - void removeModule(VModuleKey K) { - cantFail(OptimizeLayer.removeModule(K)); - } - -private: - std::string mangle(const std::string &Name) { - std::string MangledName; - raw_string_ostream MangledNameStream(MangledName); - Mangler::getNameWithPrefix(MangledNameStream, Name, DL); - return MangledNameStream.str(); - } - - std::unique_ptr optimizeModule(std::unique_ptr M) { - // Create a function pass manager. - auto FPM = std::make_unique(M.get()); - - // Add some optimizations. - FPM->add(createInstructionCombiningPass()); - FPM->add(createReassociatePass()); - FPM->add(createGVNPass()); - FPM->add(createCFGSimplificationPass()); - FPM->doInitialization(); - - // Run the optimizations over all functions in the module being added to - // the JIT. - for (auto &F : *M) - FPM->run(F); - - return M; - } -}; - -} // end namespace orc -} // end namespace llvm - -#endif // LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/RemoteJITUtils.h b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/RemoteJITUtils.h deleted file mode 100644 index c7d15bb..0000000 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/RemoteJITUtils.h +++ /dev/null @@ -1,75 +0,0 @@ -//===-- RemoteJITUtils.h - Utilities for remote-JITing with LLI -*- 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 -// -//===----------------------------------------------------------------------===// -// -// Utilities for remote-JITing with LLI. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLI_REMOTEJITUTILS_H -#define LLVM_TOOLS_LLI_REMOTEJITUTILS_H - -#include "llvm/ExecutionEngine/Orc/RPC/RawByteChannel.h" -#include "llvm/Support/Error.h" -#include -#include -#include - -#if !defined(_MSC_VER) && !defined(__MINGW32__) -#include -#else -#include -#endif - -/// RPC channel that reads from and writes from file descriptors. -class FDRPCChannel final : public llvm::orc::rpc::RawByteChannel { -public: - FDRPCChannel(int InFD, int OutFD) : InFD(InFD), OutFD(OutFD) {} - - llvm::Error readBytes(char *Dst, unsigned Size) override { - assert(Dst && "Attempt to read into null."); - ssize_t Completed = 0; - while (Completed < static_cast(Size)) { - ssize_t Read = ::read(InFD, Dst + Completed, Size - Completed); - if (Read <= 0) { - auto ErrNo = errno; - if (ErrNo == EAGAIN || ErrNo == EINTR) - continue; - else - return llvm::errorCodeToError( - std::error_code(errno, std::generic_category())); - } - Completed += Read; - } - return llvm::Error::success(); - } - - llvm::Error appendBytes(const char *Src, unsigned Size) override { - assert(Src && "Attempt to append from null."); - ssize_t Completed = 0; - while (Completed < static_cast(Size)) { - ssize_t Written = ::write(OutFD, Src + Completed, Size - Completed); - if (Written < 0) { - auto ErrNo = errno; - if (ErrNo == EAGAIN || ErrNo == EINTR) - continue; - else - return llvm::errorCodeToError( - std::error_code(errno, std::generic_category())); - } - Completed += Written; - } - return llvm::Error::success(); - } - - llvm::Error send() override { return llvm::Error::success(); } - -private: - int InFD, OutFD; -}; - -#endif // LLVM_TOOLS_LLI_REMOTEJITUTILS_H diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/Server/CMakeLists.txt b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/Server/CMakeLists.txt deleted file mode 100644 index c7252ae..0000000 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/Server/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -set(LLVM_LINK_COMPONENTS - Analysis - Core - ExecutionEngine - InstCombine - Object - OrcError - OrcJIT - RuntimeDyld - ScalarOpts - Support - TransformUtils - native - ) - -add_kaleidoscope_chapter(BuildingAJIT-Ch5-Server - server.cpp - ) - -export_executable_symbols(BuildingAJIT-Ch5-Server) diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/Server/server.cpp b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/Server/server.cpp deleted file mode 100644 index e50a7ec..0000000 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/Server/server.cpp +++ /dev/null @@ -1,111 +0,0 @@ -#include "../RemoteJITUtils.h" -#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" -#include "llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h" -#include "llvm/ExecutionEngine/Orc/OrcABISupport.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/DynamicLibrary.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/TargetSelect.h" -#include -#include -#include -#include -#include -#include - -using namespace llvm; -using namespace llvm::orc; - -// Command line argument for TCP port. -cl::opt Port("port", - cl::desc("TCP port to listen on"), - cl::init(20000)); - -ExitOnError ExitOnErr; - -using MainFun = int (*)(int, const char*[]); - -template -NativePtrT MakeNative(uint64_t P) { - return reinterpret_cast(static_cast(P)); -} - -extern "C" -void printExprResult(double Val) { - printf("Expression evaluated to: %f\n", Val); -} - -// --- LAZY COMPILE TEST --- -int main(int argc, char* argv[]) { - if (argc == 0) - ExitOnErr.setBanner("jit_server: "); - else - ExitOnErr.setBanner(std::string(argv[0]) + ": "); - - // --- Initialize LLVM --- - cl::ParseCommandLineOptions(argc, argv, "LLVM lazy JIT example.\n"); - - InitializeNativeTarget(); - InitializeNativeTargetAsmPrinter(); - InitializeNativeTargetAsmParser(); - - if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr)) { - errs() << "Error loading program symbols.\n"; - return 1; - } - - // --- Initialize remote connection --- - - int sockfd = socket(PF_INET, SOCK_STREAM, 0); - sockaddr_in servAddr, clientAddr; - socklen_t clientAddrLen = sizeof(clientAddr); - memset(&servAddr, 0, sizeof(servAddr)); - servAddr.sin_family = PF_INET; - servAddr.sin_family = INADDR_ANY; - servAddr.sin_port = htons(Port); - - { - // avoid "Address already in use" error. - int yes = 1; - if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) { - errs() << "Error calling setsockopt.\n"; - return 1; - } - } - - if (bind(sockfd, reinterpret_cast(&servAddr), - sizeof(servAddr)) < 0) { - errs() << "Error on binding.\n"; - return 1; - } - listen(sockfd, 1); - int newsockfd = accept(sockfd, reinterpret_cast(&clientAddr), - &clientAddrLen); - - auto SymbolLookup = - [](const std::string &Name) { - return RTDyldMemoryManager::getSymbolAddressInProcess(Name); - }; - - auto RegisterEHFrames = - [](uint8_t *Addr, uint32_t Size) { - RTDyldMemoryManager::registerEHFramesInProcess(Addr, Size); - }; - - auto DeregisterEHFrames = - [](uint8_t *Addr, uint32_t Size) { - RTDyldMemoryManager::deregisterEHFramesInProcess(Addr, Size); - }; - - FDRPCChannel TCPChannel(newsockfd, newsockfd); - - using MyServerT = remote::OrcRemoteTargetServer; - - MyServerT Server(TCPChannel, SymbolLookup, RegisterEHFrames, DeregisterEHFrames); - - while (!Server.receivedTerminate()) - ExitOnErr(Server.handleOne()); - - return 0; -} diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/toy.cpp b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/toy.cpp deleted file mode 100644 index b981932..0000000 --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/toy.cpp +++ /dev/null @@ -1,1309 +0,0 @@ -#include "llvm/ADT/APFloat.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/Type.h" -#include "llvm/IR/Verifier.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/TargetSelect.h" -#include "llvm/Target/TargetMachine.h" -#include "KaleidoscopeJIT.h" -#include "RemoteJITUtils.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace llvm; -using namespace llvm::orc; - -// Command line argument for TCP hostname. -cl::opt HostName("hostname", - cl::desc("TCP hostname to connect to"), - cl::init("localhost")); - -// Command line argument for TCP port. -cl::opt Port("port", - cl::desc("TCP port to connect to"), - cl::init(20000)); - -//===----------------------------------------------------------------------===// -// Lexer -//===----------------------------------------------------------------------===// - -// The lexer returns tokens [0-255] if it is an unknown character, otherwise one -// of these for known things. -enum Token { - tok_eof = -1, - - // commands - tok_def = -2, - tok_extern = -3, - - // primary - tok_identifier = -4, - tok_number = -5, - - // control - tok_if = -6, - tok_then = -7, - tok_else = -8, - tok_for = -9, - tok_in = -10, - - // operators - tok_binary = -11, - tok_unary = -12, - - // var definition - tok_var = -13 -}; - -static std::string IdentifierStr; // Filled in if tok_identifier -static double NumVal; // Filled in if tok_number - -/// gettok - Return the next token from standard input. -static int gettok() { - static int LastChar = ' '; - - // Skip any whitespace. - while (isspace(LastChar)) - LastChar = getchar(); - - if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* - IdentifierStr = LastChar; - while (isalnum((LastChar = getchar()))) - IdentifierStr += LastChar; - - if (IdentifierStr == "def") - return tok_def; - if (IdentifierStr == "extern") - return tok_extern; - if (IdentifierStr == "if") - return tok_if; - if (IdentifierStr == "then") - return tok_then; - if (IdentifierStr == "else") - return tok_else; - if (IdentifierStr == "for") - return tok_for; - if (IdentifierStr == "in") - return tok_in; - if (IdentifierStr == "binary") - return tok_binary; - if (IdentifierStr == "unary") - return tok_unary; - if (IdentifierStr == "var") - return tok_var; - return tok_identifier; - } - - if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ - std::string NumStr; - do { - NumStr += LastChar; - LastChar = getchar(); - } while (isdigit(LastChar) || LastChar == '.'); - - NumVal = strtod(NumStr.c_str(), nullptr); - return tok_number; - } - - if (LastChar == '#') { - // Comment until end of line. - do - LastChar = getchar(); - while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); - - if (LastChar != EOF) - return gettok(); - } - - // Check for end of file. Don't eat the EOF. - if (LastChar == EOF) - return tok_eof; - - // Otherwise, just return the character as its ascii value. - int ThisChar = LastChar; - LastChar = getchar(); - return ThisChar; -} - -//===----------------------------------------------------------------------===// -// Abstract Syntax Tree (aka Parse Tree) -//===----------------------------------------------------------------------===// - -/// ExprAST - Base class for all expression nodes. -class ExprAST { -public: - virtual ~ExprAST() = default; - - virtual Value *codegen() = 0; -}; - -/// NumberExprAST - Expression class for numeric literals like "1.0". -class NumberExprAST : public ExprAST { - double Val; - -public: - NumberExprAST(double Val) : Val(Val) {} - - Value *codegen() override; -}; - -/// VariableExprAST - Expression class for referencing a variable, like "a". -class VariableExprAST : public ExprAST { - std::string Name; - -public: - VariableExprAST(const std::string &Name) : Name(Name) {} - - Value *codegen() override; - const std::string &getName() const { return Name; } -}; - -/// UnaryExprAST - Expression class for a unary operator. -class UnaryExprAST : public ExprAST { - char Opcode; - std::unique_ptr Operand; - -public: - UnaryExprAST(char Opcode, std::unique_ptr Operand) - : Opcode(Opcode), Operand(std::move(Operand)) {} - - Value *codegen() override; -}; - -/// BinaryExprAST - Expression class for a binary operator. -class BinaryExprAST : public ExprAST { - char Op; - std::unique_ptr LHS, RHS; - -public: - BinaryExprAST(char Op, std::unique_ptr LHS, - std::unique_ptr RHS) - : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} - - Value *codegen() override; -}; - -/// CallExprAST - Expression class for function calls. -class CallExprAST : public ExprAST { - std::string Callee; - std::vector> Args; - -public: - CallExprAST(const std::string &Callee, - std::vector> Args) - : Callee(Callee), Args(std::move(Args)) {} - - Value *codegen() override; -}; - -/// IfExprAST - Expression class for if/then/else. -class IfExprAST : public ExprAST { - std::unique_ptr Cond, Then, Else; - -public: - IfExprAST(std::unique_ptr Cond, std::unique_ptr Then, - std::unique_ptr Else) - : Cond(std::move(Cond)), Then(std::move(Then)), Else(std::move(Else)) {} - - Value *codegen() override; -}; - -/// ForExprAST - Expression class for for/in. -class ForExprAST : public ExprAST { - std::string VarName; - std::unique_ptr Start, End, Step, Body; - -public: - ForExprAST(const std::string &VarName, std::unique_ptr Start, - std::unique_ptr End, std::unique_ptr Step, - std::unique_ptr Body) - : VarName(VarName), Start(std::move(Start)), End(std::move(End)), - Step(std::move(Step)), Body(std::move(Body)) {} - - Value *codegen() override; -}; - -/// VarExprAST - Expression class for var/in -class VarExprAST : public ExprAST { - std::vector>> VarNames; - std::unique_ptr Body; - -public: - VarExprAST( - std::vector>> VarNames, - std::unique_ptr Body) - : VarNames(std::move(VarNames)), Body(std::move(Body)) {} - - Value *codegen() override; -}; - -/// PrototypeAST - This class represents the "prototype" for a function, -/// which captures its name, and its argument names (thus implicitly the number -/// of arguments the function takes), as well as if it is an operator. -class PrototypeAST { - std::string Name; - std::vector Args; - bool IsOperator; - unsigned Precedence; // Precedence if a binary op. - -public: - PrototypeAST(const std::string &Name, std::vector Args, - bool IsOperator = false, unsigned Prec = 0) - : Name(Name), Args(std::move(Args)), IsOperator(IsOperator), - Precedence(Prec) {} - - Function *codegen(); - const std::string &getName() const { return Name; } - - bool isUnaryOp() const { return IsOperator && Args.size() == 1; } - bool isBinaryOp() const { return IsOperator && Args.size() == 2; } - - char getOperatorName() const { - assert(isUnaryOp() || isBinaryOp()); - return Name[Name.size() - 1]; - } - - unsigned getBinaryPrecedence() const { return Precedence; } -}; - -//===----------------------------------------------------------------------===// -// Parser -//===----------------------------------------------------------------------===// - -/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current -/// token the parser is looking at. getNextToken reads another token from the -/// lexer and updates CurTok with its results. -static int CurTok; -static int getNextToken() { return CurTok = gettok(); } - -/// BinopPrecedence - This holds the precedence for each binary operator that is -/// defined. -static std::map BinopPrecedence; - -/// GetTokPrecedence - Get the precedence of the pending binary operator token. -static int GetTokPrecedence() { - if (!isascii(CurTok)) - return -1; - - // Make sure it's a declared binop. - int TokPrec = BinopPrecedence[CurTok]; - if (TokPrec <= 0) - return -1; - return TokPrec; -} - -/// LogError* - These are little helper functions for error handling. -std::unique_ptr LogError(const char *Str) { - fprintf(stderr, "Error: %s\n", Str); - return nullptr; -} - -std::unique_ptr LogErrorP(const char *Str) { - LogError(Str); - return nullptr; -} - -static std::unique_ptr ParseExpression(); - -/// numberexpr ::= number -static std::unique_ptr ParseNumberExpr() { - auto Result = std::make_unique(NumVal); - getNextToken(); // consume the number - return std::move(Result); -} - -/// parenexpr ::= '(' expression ')' -static std::unique_ptr ParseParenExpr() { - getNextToken(); // eat (. - auto V = ParseExpression(); - if (!V) - return nullptr; - - if (CurTok != ')') - return LogError("expected ')'"); - getNextToken(); // eat ). - return V; -} - -/// identifierexpr -/// ::= identifier -/// ::= identifier '(' expression* ')' -static std::unique_ptr ParseIdentifierExpr() { - std::string IdName = IdentifierStr; - - getNextToken(); // eat identifier. - - if (CurTok != '(') // Simple variable ref. - return std::make_unique(IdName); - - // Call. - getNextToken(); // eat ( - std::vector> Args; - if (CurTok != ')') { - while (true) { - if (auto Arg = ParseExpression()) - Args.push_back(std::move(Arg)); - else - return nullptr; - - if (CurTok == ')') - break; - - if (CurTok != ',') - return LogError("Expected ')' or ',' in argument list"); - getNextToken(); - } - } - - // Eat the ')'. - getNextToken(); - - return std::make_unique(IdName, std::move(Args)); -} - -/// ifexpr ::= 'if' expression 'then' expression 'else' expression -static std::unique_ptr ParseIfExpr() { - getNextToken(); // eat the if. - - // condition. - auto Cond = ParseExpression(); - if (!Cond) - return nullptr; - - if (CurTok != tok_then) - return LogError("expected then"); - getNextToken(); // eat the then - - auto Then = ParseExpression(); - if (!Then) - return nullptr; - - if (CurTok != tok_else) - return LogError("expected else"); - - getNextToken(); - - auto Else = ParseExpression(); - if (!Else) - return nullptr; - - return std::make_unique(std::move(Cond), std::move(Then), - std::move(Else)); -} - -/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression -static std::unique_ptr ParseForExpr() { - getNextToken(); // eat the for. - - if (CurTok != tok_identifier) - return LogError("expected identifier after for"); - - std::string IdName = IdentifierStr; - getNextToken(); // eat identifier. - - if (CurTok != '=') - return LogError("expected '=' after for"); - getNextToken(); // eat '='. - - auto Start = ParseExpression(); - if (!Start) - return nullptr; - if (CurTok != ',') - return LogError("expected ',' after for start value"); - getNextToken(); - - auto End = ParseExpression(); - if (!End) - return nullptr; - - // The step value is optional. - std::unique_ptr Step; - if (CurTok == ',') { - getNextToken(); - Step = ParseExpression(); - if (!Step) - return nullptr; - } - - if (CurTok != tok_in) - return LogError("expected 'in' after for"); - getNextToken(); // eat 'in'. - - auto Body = ParseExpression(); - if (!Body) - return nullptr; - - return std::make_unique(IdName, std::move(Start), std::move(End), - std::move(Step), std::move(Body)); -} - -/// varexpr ::= 'var' identifier ('=' expression)? -// (',' identifier ('=' expression)?)* 'in' expression -static std::unique_ptr ParseVarExpr() { - getNextToken(); // eat the var. - - std::vector>> VarNames; - - // At least one variable name is required. - if (CurTok != tok_identifier) - return LogError("expected identifier after var"); - - while (true) { - std::string Name = IdentifierStr; - getNextToken(); // eat identifier. - - // Read the optional initializer. - std::unique_ptr Init = nullptr; - if (CurTok == '=') { - getNextToken(); // eat the '='. - - Init = ParseExpression(); - if (!Init) - return nullptr; - } - - VarNames.push_back(std::make_pair(Name, std::move(Init))); - - // End of var list, exit loop. - if (CurTok != ',') - break; - getNextToken(); // eat the ','. - - if (CurTok != tok_identifier) - return LogError("expected identifier list after var"); - } - - // At this point, we have to have 'in'. - if (CurTok != tok_in) - return LogError("expected 'in' keyword after 'var'"); - getNextToken(); // eat 'in'. - - auto Body = ParseExpression(); - if (!Body) - return nullptr; - - return std::make_unique(std::move(VarNames), std::move(Body)); -} - -/// primary -/// ::= identifierexpr -/// ::= numberexpr -/// ::= parenexpr -/// ::= ifexpr -/// ::= forexpr -/// ::= varexpr -static std::unique_ptr ParsePrimary() { - switch (CurTok) { - default: - return LogError("unknown token when expecting an expression"); - case tok_identifier: - return ParseIdentifierExpr(); - case tok_number: - return ParseNumberExpr(); - case '(': - return ParseParenExpr(); - case tok_if: - return ParseIfExpr(); - case tok_for: - return ParseForExpr(); - case tok_var: - return ParseVarExpr(); - } -} - -/// unary -/// ::= primary -/// ::= '!' unary -static std::unique_ptr ParseUnary() { - // If the current token is not an operator, it must be a primary expr. - if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') - return ParsePrimary(); - - // If this is a unary operator, read it. - int Opc = CurTok; - getNextToken(); - if (auto Operand = ParseUnary()) - return std::make_unique(Opc, std::move(Operand)); - return nullptr; -} - -/// binoprhs -/// ::= ('+' unary)* -static std::unique_ptr ParseBinOpRHS(int ExprPrec, - std::unique_ptr LHS) { - // If this is a binop, find its precedence. - while (true) { - int TokPrec = GetTokPrecedence(); - - // If this is a binop that binds at least as tightly as the current binop, - // consume it, otherwise we are done. - if (TokPrec < ExprPrec) - return LHS; - - // Okay, we know this is a binop. - int BinOp = CurTok; - getNextToken(); // eat binop - - // Parse the unary expression after the binary operator. - auto RHS = ParseUnary(); - if (!RHS) - return nullptr; - - // If BinOp binds less tightly with RHS than the operator after RHS, let - // the pending operator take RHS as its LHS. - int NextPrec = GetTokPrecedence(); - if (TokPrec < NextPrec) { - RHS = ParseBinOpRHS(TokPrec + 1, std::move(RHS)); - if (!RHS) - return nullptr; - } - - // Merge LHS/RHS. - LHS = - std::make_unique(BinOp, std::move(LHS), std::move(RHS)); - } -} - -/// expression -/// ::= unary binoprhs -/// -static std::unique_ptr ParseExpression() { - auto LHS = ParseUnary(); - if (!LHS) - return nullptr; - - return ParseBinOpRHS(0, std::move(LHS)); -} - -/// prototype -/// ::= id '(' id* ')' -/// ::= binary LETTER number? (id, id) -/// ::= unary LETTER (id) -static std::unique_ptr ParsePrototype() { - std::string FnName; - - unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. - unsigned BinaryPrecedence = 30; - - switch (CurTok) { - default: - return LogErrorP("Expected function name in prototype"); - case tok_identifier: - FnName = IdentifierStr; - Kind = 0; - getNextToken(); - break; - case tok_unary: - getNextToken(); - if (!isascii(CurTok)) - return LogErrorP("Expected unary operator"); - FnName = "unary"; - FnName += (char)CurTok; - Kind = 1; - getNextToken(); - break; - case tok_binary: - getNextToken(); - if (!isascii(CurTok)) - return LogErrorP("Expected binary operator"); - FnName = "binary"; - FnName += (char)CurTok; - Kind = 2; - getNextToken(); - - // Read the precedence if present. - if (CurTok == tok_number) { - if (NumVal < 1 || NumVal > 100) - return LogErrorP("Invalid precedecnce: must be 1..100"); - BinaryPrecedence = (unsigned)NumVal; - getNextToken(); - } - break; - } - - if (CurTok != '(') - return LogErrorP("Expected '(' in prototype"); - - std::vector ArgNames; - while (getNextToken() == tok_identifier) - ArgNames.push_back(IdentifierStr); - if (CurTok != ')') - return LogErrorP("Expected ')' in prototype"); - - // success. - getNextToken(); // eat ')'. - - // Verify right number of names for operator. - if (Kind && ArgNames.size() != Kind) - return LogErrorP("Invalid number of operands for operator"); - - return std::make_unique(FnName, ArgNames, Kind != 0, - BinaryPrecedence); -} - -/// definition ::= 'def' prototype expression -static std::unique_ptr ParseDefinition() { - getNextToken(); // eat def. - auto Proto = ParsePrototype(); - if (!Proto) - return nullptr; - - if (auto E = ParseExpression()) - return std::make_unique(std::move(Proto), std::move(E)); - return nullptr; -} - -/// toplevelexpr ::= expression -static std::unique_ptr ParseTopLevelExpr() { - if (auto E = ParseExpression()) { - - auto PEArgs = std::vector>(); - PEArgs.push_back(std::move(E)); - auto PrintExpr = - std::make_unique("printExprResult", std::move(PEArgs)); - - // Make an anonymous proto. - auto Proto = std::make_unique("__anon_expr", - std::vector()); - return std::make_unique(std::move(Proto), - std::move(PrintExpr)); - } - return nullptr; -} - -/// external ::= 'extern' prototype -static std::unique_ptr ParseExtern() { - getNextToken(); // eat extern. - return ParsePrototype(); -} - -//===----------------------------------------------------------------------===// -// Code Generation -//===----------------------------------------------------------------------===// - -static LLVMContext TheContext; -static IRBuilder<> Builder(TheContext); -static std::unique_ptr TheModule; -static std::map NamedValues; -static std::unique_ptr TheJIT; -static std::map> FunctionProtos; -static ExitOnError ExitOnErr; - -Value *LogErrorV(const char *Str) { - LogError(Str); - return nullptr; -} - -Function *getFunction(std::string Name) { - // First, see if the function has already been added to the current module. - if (auto *F = TheModule->getFunction(Name)) - return F; - - // If not, check whether we can codegen the declaration from some existing - // prototype. - auto FI = FunctionProtos.find(Name); - if (FI != FunctionProtos.end()) - return FI->second->codegen(); - - // If no existing prototype exists, return null. - return nullptr; -} - -/// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of -/// the function. This is used for mutable variables etc. -static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, - StringRef VarName) { - IRBuilder<> TmpB(&TheFunction->getEntryBlock(), - TheFunction->getEntryBlock().begin()); - return TmpB.CreateAlloca(Type::getDoubleTy(TheContext), nullptr, VarName); -} - -Value *NumberExprAST::codegen() { - return ConstantFP::get(TheContext, APFloat(Val)); -} - -Value *VariableExprAST::codegen() { - // Look this variable up in the function. - Value *V = NamedValues[Name]; - if (!V) - return LogErrorV("Unknown variable name"); - - // Load the value. - return Builder.CreateLoad(V, Name.c_str()); -} - -Value *UnaryExprAST::codegen() { - Value *OperandV = Operand->codegen(); - if (!OperandV) - return nullptr; - - Function *F = getFunction(std::string("unary") + Opcode); - if (!F) - return LogErrorV("Unknown unary operator"); - - return Builder.CreateCall(F, OperandV, "unop"); -} - -Value *BinaryExprAST::codegen() { - // Special case '=' because we don't want to emit the LHS as an expression. - if (Op == '=') { - // Assignment requires the LHS to be an identifier. - // This assume we're building without RTTI because LLVM builds that way by - // default. If you build LLVM with RTTI this can be changed to a - // dynamic_cast for automatic error checking. - VariableExprAST *LHSE = static_cast(LHS.get()); - if (!LHSE) - return LogErrorV("destination of '=' must be a variable"); - // Codegen the RHS. - Value *Val = RHS->codegen(); - if (!Val) - return nullptr; - - // Look up the name. - Value *Variable = NamedValues[LHSE->getName()]; - if (!Variable) - return LogErrorV("Unknown variable name"); - - Builder.CreateStore(Val, Variable); - return Val; - } - - Value *L = LHS->codegen(); - Value *R = RHS->codegen(); - if (!L || !R) - return nullptr; - - switch (Op) { - case '+': - return Builder.CreateFAdd(L, R, "addtmp"); - case '-': - return Builder.CreateFSub(L, R, "subtmp"); - case '*': - return Builder.CreateFMul(L, R, "multmp"); - case '<': - L = Builder.CreateFCmpULT(L, R, "cmptmp"); - // Convert bool 0/1 to double 0.0 or 1.0 - return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); - default: - break; - } - - // If it wasn't a builtin binary operator, it must be a user defined one. Emit - // a call to it. - Function *F = getFunction(std::string("binary") + Op); - assert(F && "binary operator not found!"); - - Value *Ops[] = {L, R}; - return Builder.CreateCall(F, Ops, "binop"); -} - -Value *CallExprAST::codegen() { - // Look up the name in the global module table. - Function *CalleeF = getFunction(Callee); - if (!CalleeF) - return LogErrorV("Unknown function referenced"); - - // If argument mismatch error. - if (CalleeF->arg_size() != Args.size()) - return LogErrorV("Incorrect # arguments passed"); - - std::vector ArgsV; - for (unsigned i = 0, e = Args.size(); i != e; ++i) { - ArgsV.push_back(Args[i]->codegen()); - if (!ArgsV.back()) - return nullptr; - } - - return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); -} - -Value *IfExprAST::codegen() { - Value *CondV = Cond->codegen(); - if (!CondV) - return nullptr; - - // Convert condition to a bool by comparing equal to 0.0. - CondV = Builder.CreateFCmpONE( - CondV, ConstantFP::get(TheContext, APFloat(0.0)), "ifcond"); - - Function *TheFunction = Builder.GetInsertBlock()->getParent(); - - // Create blocks for the then and else cases. Insert the 'then' block at the - // end of the function. - BasicBlock *ThenBB = BasicBlock::Create(TheContext, "then", TheFunction); - BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else"); - BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont"); - - Builder.CreateCondBr(CondV, ThenBB, ElseBB); - - // Emit then value. - Builder.SetInsertPoint(ThenBB); - - Value *ThenV = Then->codegen(); - if (!ThenV) - return nullptr; - - Builder.CreateBr(MergeBB); - // Codegen of 'Then' can change the current block, update ThenBB for the PHI. - ThenBB = Builder.GetInsertBlock(); - - // Emit else block. - TheFunction->getBasicBlockList().push_back(ElseBB); - Builder.SetInsertPoint(ElseBB); - - Value *ElseV = Else->codegen(); - if (!ElseV) - return nullptr; - - Builder.CreateBr(MergeBB); - // Codegen of 'Else' can change the current block, update ElseBB for the PHI. - ElseBB = Builder.GetInsertBlock(); - - // Emit merge block. - TheFunction->getBasicBlockList().push_back(MergeBB); - Builder.SetInsertPoint(MergeBB); - PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(TheContext), 2, "iftmp"); - - PN->addIncoming(ThenV, ThenBB); - PN->addIncoming(ElseV, ElseBB); - return PN; -} - -// Output for-loop as: -// var = alloca double -// ... -// start = startexpr -// store start -> var -// goto loop -// loop: -// ... -// bodyexpr -// ... -// loopend: -// step = stepexpr -// endcond = endexpr -// -// curvar = load var -// nextvar = curvar + step -// store nextvar -> var -// br endcond, loop, endloop -// outloop: -Value *ForExprAST::codegen() { - Function *TheFunction = Builder.GetInsertBlock()->getParent(); - - // Create an alloca for the variable in the entry block. - AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); - - // Emit the start code first, without 'variable' in scope. - Value *StartVal = Start->codegen(); - if (!StartVal) - return nullptr; - - // Store the value into the alloca. - Builder.CreateStore(StartVal, Alloca); - - // Make the new basic block for the loop header, inserting after current - // block. - BasicBlock *LoopBB = BasicBlock::Create(TheContext, "loop", TheFunction); - - // Insert an explicit fall through from the current block to the LoopBB. - Builder.CreateBr(LoopBB); - - // Start insertion in LoopBB. - Builder.SetInsertPoint(LoopBB); - - // Within the loop, the variable is defined equal to the PHI node. If it - // shadows an existing variable, we have to restore it, so save it now. - AllocaInst *OldVal = NamedValues[VarName]; - NamedValues[VarName] = Alloca; - - // Emit the body of the loop. This, like any other expr, can change the - // current BB. Note that we ignore the value computed by the body, but don't - // allow an error. - if (!Body->codegen()) - return nullptr; - - // Emit the step value. - Value *StepVal = nullptr; - if (Step) { - StepVal = Step->codegen(); - if (!StepVal) - return nullptr; - } else { - // If not specified, use 1.0. - StepVal = ConstantFP::get(TheContext, APFloat(1.0)); - } - - // Compute the end condition. - Value *EndCond = End->codegen(); - if (!EndCond) - return nullptr; - - // Reload, increment, and restore the alloca. This handles the case where - // the body of the loop mutates the variable. - Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str()); - Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar"); - Builder.CreateStore(NextVar, Alloca); - - // Convert condition to a bool by comparing equal to 0.0. - EndCond = Builder.CreateFCmpONE( - EndCond, ConstantFP::get(TheContext, APFloat(0.0)), "loopcond"); - - // Create the "after loop" block and insert it. - BasicBlock *AfterBB = - BasicBlock::Create(TheContext, "afterloop", TheFunction); - - // Insert the conditional branch into the end of LoopEndBB. - Builder.CreateCondBr(EndCond, LoopBB, AfterBB); - - // Any new code will be inserted in AfterBB. - Builder.SetInsertPoint(AfterBB); - - // Restore the unshadowed variable. - if (OldVal) - NamedValues[VarName] = OldVal; - else - NamedValues.erase(VarName); - - // for expr always returns 0.0. - return Constant::getNullValue(Type::getDoubleTy(TheContext)); -} - -Value *VarExprAST::codegen() { - std::vector OldBindings; - - Function *TheFunction = Builder.GetInsertBlock()->getParent(); - - // Register all variables and emit their initializer. - for (unsigned i = 0, e = VarNames.size(); i != e; ++i) { - const std::string &VarName = VarNames[i].first; - ExprAST *Init = VarNames[i].second.get(); - - // Emit the initializer before adding the variable to scope, this prevents - // the initializer from referencing the variable itself, and permits stuff - // like this: - // var a = 1 in - // var a = a in ... # refers to outer 'a'. - Value *InitVal; - if (Init) { - InitVal = Init->codegen(); - if (!InitVal) - return nullptr; - } else { // If not specified, use 0.0. - InitVal = ConstantFP::get(TheContext, APFloat(0.0)); - } - - AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); - Builder.CreateStore(InitVal, Alloca); - - // Remember the old variable binding so that we can restore the binding when - // we unrecurse. - OldBindings.push_back(NamedValues[VarName]); - - // Remember this binding. - NamedValues[VarName] = Alloca; - } - - // Codegen the body, now that all vars are in scope. - Value *BodyVal = Body->codegen(); - if (!BodyVal) - return nullptr; - - // Pop all our variables from scope. - for (unsigned i = 0, e = VarNames.size(); i != e; ++i) - NamedValues[VarNames[i].first] = OldBindings[i]; - - // Return the body computation. - return BodyVal; -} - -Function *PrototypeAST::codegen() { - // Make the function type: double(double,double) etc. - std::vector Doubles(Args.size(), Type::getDoubleTy(TheContext)); - FunctionType *FT = - FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); - - Function *F = - Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get()); - - // Set names for all arguments. - unsigned Idx = 0; - for (auto &Arg : F->args()) - Arg.setName(Args[Idx++]); - - return F; -} - -const PrototypeAST& FunctionAST::getProto() const { - return *Proto; -} - -const std::string& FunctionAST::getName() const { - return Proto->getName(); -} - -Function *FunctionAST::codegen() { - // Transfer ownership of the prototype to the FunctionProtos map, but keep a - // reference to it for use below. - auto &P = *Proto; - Function *TheFunction = getFunction(P.getName()); - if (!TheFunction) - return nullptr; - - // If this is an operator, install it. - if (P.isBinaryOp()) - BinopPrecedence[P.getOperatorName()] = P.getBinaryPrecedence(); - - // Create a new basic block to start insertion into. - BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); - Builder.SetInsertPoint(BB); - - // Record the function arguments in the NamedValues map. - NamedValues.clear(); - for (auto &Arg : TheFunction->args()) { - // Create an alloca for this variable. - AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, Arg.getName()); - - // Store the initial value into the alloca. - Builder.CreateStore(&Arg, Alloca); - - // Add arguments to variable symbol table. - NamedValues[std::string(Arg.getName())] = Alloca; - } - - if (Value *RetVal = Body->codegen()) { - // Finish off the function. - Builder.CreateRet(RetVal); - - // Validate the generated code, checking for consistency. - verifyFunction(*TheFunction); - - return TheFunction; - } - - // Error reading body, remove function. - TheFunction->eraseFromParent(); - - if (P.isBinaryOp()) - BinopPrecedence.erase(Proto->getOperatorName()); - return nullptr; -} - -//===----------------------------------------------------------------------===// -// Top-Level parsing and JIT Driver -//===----------------------------------------------------------------------===// - -static void InitializeModule() { - // Open a new module. - TheModule = std::make_unique("my cool jit", TheContext); - TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout()); -} - -std::unique_ptr -irgenAndTakeOwnership(FunctionAST &FnAST, const std::string &Suffix) { - if (auto *F = FnAST.codegen()) { - F->setName(F->getName() + Suffix); - auto M = std::move(TheModule); - // Start a new module. - InitializeModule(); - return M; - } else - report_fatal_error("Couldn't compile lazily JIT'd function"); -} - -static void HandleDefinition() { - if (auto FnAST = ParseDefinition()) { - FunctionProtos[FnAST->getProto().getName()] = - std::make_unique(FnAST->getProto()); - ExitOnErr(TheJIT->addFunctionAST(std::move(FnAST))); - } else { - // Skip token for error recovery. - getNextToken(); - } -} - -static void HandleExtern() { - if (auto ProtoAST = ParseExtern()) { - if (auto *FnIR = ProtoAST->codegen()) { - fprintf(stderr, "Read extern: "); - FnIR->print(errs()); - fprintf(stderr, "\n"); - FunctionProtos[ProtoAST->getName()] = std::move(ProtoAST); - } - } else { - // Skip token for error recovery. - getNextToken(); - } -} - -static void HandleTopLevelExpression() { - // Evaluate a top-level expression into an anonymous function. - if (auto FnAST = ParseTopLevelExpr()) { - FunctionProtos[FnAST->getName()] = - std::make_unique(FnAST->getProto()); - if (FnAST->codegen()) { - // JIT the module containing the anonymous expression, keeping a handle so - // we can free it later. - auto H = TheJIT->addModule(std::move(TheModule)); - InitializeModule(); - - // Search the JIT for the __anon_expr symbol. - auto ExprSymbol = TheJIT->findSymbol("__anon_expr"); - assert(ExprSymbol && "Function not found"); - - // Get the symbol's address and cast it to the right type (takes no - // arguments, returns a double) so we can call it as a native function. - ExitOnErr(TheJIT->executeRemoteExpr(cantFail(ExprSymbol.getAddress()))); - - // Delete the anonymous expression module from the JIT. - TheJIT->removeModule(H); - } - } else { - // Skip token for error recovery. - getNextToken(); - } -} - -/// top ::= definition | external | expression | ';' -static void MainLoop() { - while (true) { - fprintf(stderr, "ready> "); - switch (CurTok) { - case tok_eof: - return; - case ';': // ignore top-level semicolons. - getNextToken(); - break; - case tok_def: - HandleDefinition(); - break; - case tok_extern: - HandleExtern(); - break; - default: - HandleTopLevelExpression(); - break; - } - } -} - -//===----------------------------------------------------------------------===// -// "Library" functions that can be "extern'd" from user code. -//===----------------------------------------------------------------------===// - -/// putchard - putchar that takes a double and returns 0. -extern "C" double putchard(double X) { - fputc((char)X, stderr); - return 0; -} - -/// printd - printf that takes a double prints it as "%f\n", returning 0. -extern "C" double printd(double X) { - fprintf(stderr, "%f\n", X); - return 0; -} - -//===----------------------------------------------------------------------===// -// TCP / Connection setup code. -//===----------------------------------------------------------------------===// - -std::unique_ptr connect() { - int sockfd = socket(PF_INET, SOCK_STREAM, 0); - hostent *server = gethostbyname(HostName.c_str()); - - if (!server) { - errs() << "Could not find host " << HostName << "\n"; - exit(1); - } - - sockaddr_in servAddr; - memset(&servAddr, 0, sizeof(servAddr)); - servAddr.sin_family = PF_INET; - char *src; - memcpy(&src, &server->h_addr, sizeof(char *)); - memcpy(&servAddr.sin_addr.s_addr, src, server->h_length); - servAddr.sin_port = htons(Port); - if (connect(sockfd, reinterpret_cast(&servAddr), - sizeof(servAddr)) < 0) { - errs() << "Failure to connect.\n"; - exit(1); - } - - return std::make_unique(sockfd, sockfd); -} - -//===----------------------------------------------------------------------===// -// Main driver code. -//===----------------------------------------------------------------------===// - -int main(int argc, char *argv[]) { - // Parse the command line options. - cl::ParseCommandLineOptions(argc, argv, "Building A JIT - Client.\n"); - - InitializeNativeTarget(); - InitializeNativeTargetAsmPrinter(); - InitializeNativeTargetAsmParser(); - - ExitOnErr.setBanner("Kaleidoscope: "); - - // Install standard binary operators. - // 1 is lowest precedence. - BinopPrecedence['='] = 2; - BinopPrecedence['<'] = 10; - BinopPrecedence['+'] = 20; - BinopPrecedence['-'] = 20; - BinopPrecedence['*'] = 40; // highest. - - ExecutionSession ES; - auto TCPChannel = connect(); - auto Remote = ExitOnErr(MyRemote::Create(*TCPChannel, ES)); - TheJIT = std::make_unique(ES, *Remote); - - // Automatically inject a definition for 'printExprResult'. - FunctionProtos["printExprResult"] = - std::make_unique("printExprResult", - std::vector({"Val"})); - - // Prime the first token. - fprintf(stderr, "ready> "); - getNextToken(); - - InitializeModule(); - - // Run the main "interpreter loop" now. - MainLoop(); - - // Delete the JIT before the Remote and Channel go out of scope, otherwise - // we'll crash in the JIT destructor when it tries to release remote - // resources over a channel that no longer exists. - TheJIT = nullptr; - - // Send a terminate message to the remote to tell it to exit cleanly. - ExitOnErr(Remote->terminateSession()); - - return 0; -} diff --git a/llvm/examples/Kaleidoscope/Chapter3/toy.cpp b/llvm/examples/Kaleidoscope/Chapter3/toy.cpp index 557780d..61adfbc 100644 --- a/llvm/examples/Kaleidoscope/Chapter3/toy.cpp +++ b/llvm/examples/Kaleidoscope/Chapter3/toy.cpp @@ -399,9 +399,9 @@ static std::unique_ptr ParseExtern() { // Code Generation //===----------------------------------------------------------------------===// -static LLVMContext TheContext; -static IRBuilder<> Builder(TheContext); +static std::unique_ptr TheContext; static std::unique_ptr TheModule; +static std::unique_ptr> Builder; static std::map NamedValues; Value *LogErrorV(const char *Str) { @@ -410,7 +410,7 @@ Value *LogErrorV(const char *Str) { } Value *NumberExprAST::codegen() { - return ConstantFP::get(TheContext, APFloat(Val)); + return ConstantFP::get(*TheContext, APFloat(Val)); } Value *VariableExprAST::codegen() { @@ -429,15 +429,15 @@ Value *BinaryExprAST::codegen() { switch (Op) { case '+': - return Builder.CreateFAdd(L, R, "addtmp"); + return Builder->CreateFAdd(L, R, "addtmp"); case '-': - return Builder.CreateFSub(L, R, "subtmp"); + return Builder->CreateFSub(L, R, "subtmp"); case '*': - return Builder.CreateFMul(L, R, "multmp"); + return Builder->CreateFMul(L, R, "multmp"); case '<': - L = Builder.CreateFCmpULT(L, R, "cmptmp"); + L = Builder->CreateFCmpULT(L, R, "cmptmp"); // Convert bool 0/1 to double 0.0 or 1.0 - return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); + return Builder->CreateUIToFP(L, Type::getDoubleTy(*TheContext), "booltmp"); default: return LogErrorV("invalid binary operator"); } @@ -460,14 +460,14 @@ Value *CallExprAST::codegen() { return nullptr; } - return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); + return Builder->CreateCall(CalleeF, ArgsV, "calltmp"); } Function *PrototypeAST::codegen() { // Make the function type: double(double,double) etc. - std::vector Doubles(Args.size(), Type::getDoubleTy(TheContext)); + std::vector Doubles(Args.size(), Type::getDoubleTy(*TheContext)); FunctionType *FT = - FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); + FunctionType::get(Type::getDoubleTy(*TheContext), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get()); @@ -491,8 +491,8 @@ Function *FunctionAST::codegen() { return nullptr; // Create a new basic block to start insertion into. - BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); - Builder.SetInsertPoint(BB); + BasicBlock *BB = BasicBlock::Create(*TheContext, "entry", TheFunction); + Builder->SetInsertPoint(BB); // Record the function arguments in the NamedValues map. NamedValues.clear(); @@ -501,7 +501,7 @@ Function *FunctionAST::codegen() { if (Value *RetVal = Body->codegen()) { // Finish off the function. - Builder.CreateRet(RetVal); + Builder->CreateRet(RetVal); // Validate the generated code, checking for consistency. verifyFunction(*TheFunction); @@ -518,12 +518,24 @@ Function *FunctionAST::codegen() { // Top-Level parsing and JIT Driver //===----------------------------------------------------------------------===// +static void InitializeModule() { + // Open a new context and module. + TheContext = std::make_unique(); + TheModule = std::make_unique("my cool jit", *TheContext); + + // Create a new builder for the module. + Builder = std::make_unique>(*TheContext); +} + static void HandleDefinition() { if (auto FnAST = ParseDefinition()) { if (auto *FnIR = FnAST->codegen()) { fprintf(stderr, "Read function definition:"); FnIR->print(errs()); fprintf(stderr, "\n"); + + // Reset the module. + InitializeModule(); } } else { // Skip token for error recovery. @@ -551,6 +563,9 @@ static void HandleTopLevelExpression() { fprintf(stderr, "Read top-level expression:"); FnIR->print(errs()); fprintf(stderr, "\n"); + + // Reset the module. + InitializeModule(); } } else { // Skip token for error recovery. @@ -598,7 +613,7 @@ int main() { getNextToken(); // Make the module, which holds all the code. - TheModule = std::make_unique("my cool jit", TheContext); + InitializeModule(); // Run the main "interpreter loop" now. MainLoop(); diff --git a/llvm/examples/Kaleidoscope/Chapter4/toy.cpp b/llvm/examples/Kaleidoscope/Chapter4/toy.cpp index f9321f8..20aec1a 100644 --- a/llvm/examples/Kaleidoscope/Chapter4/toy.cpp +++ b/llvm/examples/Kaleidoscope/Chapter4/toy.cpp @@ -409,13 +409,14 @@ static std::unique_ptr ParseExtern() { // Code Generation //===----------------------------------------------------------------------===// -static LLVMContext TheContext; -static IRBuilder<> Builder(TheContext); +static std::unique_ptr TheContext; static std::unique_ptr TheModule; +static std::unique_ptr> Builder; static std::map NamedValues; static std::unique_ptr TheFPM; static std::unique_ptr TheJIT; static std::map> FunctionProtos; +static ExitOnError ExitOnErr; Value *LogErrorV(const char *Str) { LogError(Str); @@ -438,7 +439,7 @@ Function *getFunction(std::string Name) { } Value *NumberExprAST::codegen() { - return ConstantFP::get(TheContext, APFloat(Val)); + return ConstantFP::get(*TheContext, APFloat(Val)); } Value *VariableExprAST::codegen() { @@ -457,15 +458,15 @@ Value *BinaryExprAST::codegen() { switch (Op) { case '+': - return Builder.CreateFAdd(L, R, "addtmp"); + return Builder->CreateFAdd(L, R, "addtmp"); case '-': - return Builder.CreateFSub(L, R, "subtmp"); + return Builder->CreateFSub(L, R, "subtmp"); case '*': - return Builder.CreateFMul(L, R, "multmp"); + return Builder->CreateFMul(L, R, "multmp"); case '<': - L = Builder.CreateFCmpULT(L, R, "cmptmp"); + L = Builder->CreateFCmpULT(L, R, "cmptmp"); // Convert bool 0/1 to double 0.0 or 1.0 - return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); + return Builder->CreateUIToFP(L, Type::getDoubleTy(*TheContext), "booltmp"); default: return LogErrorV("invalid binary operator"); } @@ -488,14 +489,14 @@ Value *CallExprAST::codegen() { return nullptr; } - return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); + return Builder->CreateCall(CalleeF, ArgsV, "calltmp"); } Function *PrototypeAST::codegen() { // Make the function type: double(double,double) etc. - std::vector Doubles(Args.size(), Type::getDoubleTy(TheContext)); + std::vector Doubles(Args.size(), Type::getDoubleTy(*TheContext)); FunctionType *FT = - FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); + FunctionType::get(Type::getDoubleTy(*TheContext), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get()); @@ -518,8 +519,8 @@ Function *FunctionAST::codegen() { return nullptr; // Create a new basic block to start insertion into. - BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); - Builder.SetInsertPoint(BB); + BasicBlock *BB = BasicBlock::Create(*TheContext, "entry", TheFunction); + Builder->SetInsertPoint(BB); // Record the function arguments in the NamedValues map. NamedValues.clear(); @@ -528,7 +529,7 @@ Function *FunctionAST::codegen() { if (Value *RetVal = Body->codegen()) { // Finish off the function. - Builder.CreateRet(RetVal); + Builder->CreateRet(RetVal); // Validate the generated code, checking for consistency. verifyFunction(*TheFunction); @@ -549,9 +550,13 @@ Function *FunctionAST::codegen() { //===----------------------------------------------------------------------===// static void InitializeModuleAndPassManager() { - // Open a new module. - TheModule = std::make_unique("my cool jit", TheContext); - TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout()); + // Open a new context and module. + TheContext = std::make_unique(); + TheModule = std::make_unique("my cool jit", *TheContext); + TheModule->setDataLayout(TheJIT->getDataLayout()); + + // Create a new builder for the module. + Builder = std::make_unique>(*TheContext); // Create a new pass manager attached to it. TheFPM = std::make_unique(TheModule.get()); @@ -574,7 +579,8 @@ static void HandleDefinition() { fprintf(stderr, "Read function definition:"); FnIR->print(errs()); fprintf(stderr, "\n"); - TheJIT->addModule(std::move(TheModule)); + ExitOnErr(TheJIT->addModule( + ThreadSafeModule(std::move(TheModule), std::move(TheContext)))); InitializeModuleAndPassManager(); } } else { @@ -601,22 +607,24 @@ static void HandleTopLevelExpression() { // Evaluate a top-level expression into an anonymous function. if (auto FnAST = ParseTopLevelExpr()) { if (FnAST->codegen()) { - // JIT the module containing the anonymous expression, keeping a handle so - // we can free it later. - auto H = TheJIT->addModule(std::move(TheModule)); + // Create a ResourceTracker to track JIT'd memory allocated to our + // anonymous expression -- that way we can free it after executing. + auto RT = TheJIT->getMainJITDylib().createResourceTracker(); + + auto TSM = ThreadSafeModule(std::move(TheModule), std::move(TheContext)); + ExitOnErr(TheJIT->addModule(std::move(TSM), RT)); InitializeModuleAndPassManager(); // Search the JIT for the __anon_expr symbol. - auto ExprSymbol = TheJIT->findSymbol("__anon_expr"); - assert(ExprSymbol && "Function not found"); + auto ExprSymbol = ExitOnErr(TheJIT->lookup("__anon_expr")); // Get the symbol's address and cast it to the right type (takes no // arguments, returns a double) so we can call it as a native function. - double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress()); + double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress(); fprintf(stderr, "Evaluated to %f\n", FP()); // Delete the anonymous expression module from the JIT. - TheJIT->removeModule(H); + ExitOnErr(RT->remove()); } } else { // Skip token for error recovery. @@ -689,7 +697,7 @@ int main() { fprintf(stderr, "ready> "); getNextToken(); - TheJIT = std::make_unique(); + TheJIT = ExitOnErr(KaleidoscopeJIT::Create()); InitializeModuleAndPassManager(); diff --git a/llvm/examples/Kaleidoscope/Chapter5/toy.cpp b/llvm/examples/Kaleidoscope/Chapter5/toy.cpp index 22bec97..0790407 100644 --- a/llvm/examples/Kaleidoscope/Chapter5/toy.cpp +++ b/llvm/examples/Kaleidoscope/Chapter5/toy.cpp @@ -536,13 +536,14 @@ static std::unique_ptr ParseExtern() { // Code Generation //===----------------------------------------------------------------------===// -static LLVMContext TheContext; -static IRBuilder<> Builder(TheContext); +static std::unique_ptr TheContext; static std::unique_ptr TheModule; +static std::unique_ptr> Builder; static std::map NamedValues; static std::unique_ptr TheFPM; static std::unique_ptr TheJIT; static std::map> FunctionProtos; +static ExitOnError ExitOnErr; Value *LogErrorV(const char *Str) { LogError(Str); @@ -565,7 +566,7 @@ Function *getFunction(std::string Name) { } Value *NumberExprAST::codegen() { - return ConstantFP::get(TheContext, APFloat(Val)); + return ConstantFP::get(*TheContext, APFloat(Val)); } Value *VariableExprAST::codegen() { @@ -584,15 +585,15 @@ Value *BinaryExprAST::codegen() { switch (Op) { case '+': - return Builder.CreateFAdd(L, R, "addtmp"); + return Builder->CreateFAdd(L, R, "addtmp"); case '-': - return Builder.CreateFSub(L, R, "subtmp"); + return Builder->CreateFSub(L, R, "subtmp"); case '*': - return Builder.CreateFMul(L, R, "multmp"); + return Builder->CreateFMul(L, R, "multmp"); case '<': - L = Builder.CreateFCmpULT(L, R, "cmptmp"); + L = Builder->CreateFCmpULT(L, R, "cmptmp"); // Convert bool 0/1 to double 0.0 or 1.0 - return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); + return Builder->CreateUIToFP(L, Type::getDoubleTy(*TheContext), "booltmp"); default: return LogErrorV("invalid binary operator"); } @@ -615,7 +616,7 @@ Value *CallExprAST::codegen() { return nullptr; } - return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); + return Builder->CreateCall(CalleeF, ArgsV, "calltmp"); } Value *IfExprAST::codegen() { @@ -624,46 +625,46 @@ Value *IfExprAST::codegen() { return nullptr; // Convert condition to a bool by comparing non-equal to 0.0. - CondV = Builder.CreateFCmpONE( - CondV, ConstantFP::get(TheContext, APFloat(0.0)), "ifcond"); + CondV = Builder->CreateFCmpONE( + CondV, ConstantFP::get(*TheContext, APFloat(0.0)), "ifcond"); - Function *TheFunction = Builder.GetInsertBlock()->getParent(); + Function *TheFunction = Builder->GetInsertBlock()->getParent(); // Create blocks for the then and else cases. Insert the 'then' block at the // end of the function. - BasicBlock *ThenBB = BasicBlock::Create(TheContext, "then", TheFunction); - BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else"); - BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont"); + BasicBlock *ThenBB = BasicBlock::Create(*TheContext, "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(*TheContext, "else"); + BasicBlock *MergeBB = BasicBlock::Create(*TheContext, "ifcont"); - Builder.CreateCondBr(CondV, ThenBB, ElseBB); + Builder->CreateCondBr(CondV, ThenBB, ElseBB); // Emit then value. - Builder.SetInsertPoint(ThenBB); + Builder->SetInsertPoint(ThenBB); Value *ThenV = Then->codegen(); if (!ThenV) return nullptr; - Builder.CreateBr(MergeBB); + Builder->CreateBr(MergeBB); // Codegen of 'Then' can change the current block, update ThenBB for the PHI. - ThenBB = Builder.GetInsertBlock(); + ThenBB = Builder->GetInsertBlock(); // Emit else block. TheFunction->getBasicBlockList().push_back(ElseBB); - Builder.SetInsertPoint(ElseBB); + Builder->SetInsertPoint(ElseBB); Value *ElseV = Else->codegen(); if (!ElseV) return nullptr; - Builder.CreateBr(MergeBB); + Builder->CreateBr(MergeBB); // Codegen of 'Else' can change the current block, update ElseBB for the PHI. - ElseBB = Builder.GetInsertBlock(); + ElseBB = Builder->GetInsertBlock(); // Emit merge block. TheFunction->getBasicBlockList().push_back(MergeBB); - Builder.SetInsertPoint(MergeBB); - PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(TheContext), 2, "iftmp"); + Builder->SetInsertPoint(MergeBB); + PHINode *PN = Builder->CreatePHI(Type::getDoubleTy(*TheContext), 2, "iftmp"); PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); @@ -693,19 +694,19 @@ Value *ForExprAST::codegen() { // Make the new basic block for the loop header, inserting after current // block. - Function *TheFunction = Builder.GetInsertBlock()->getParent(); - BasicBlock *PreheaderBB = Builder.GetInsertBlock(); - BasicBlock *LoopBB = BasicBlock::Create(TheContext, "loop", TheFunction); + Function *TheFunction = Builder->GetInsertBlock()->getParent(); + BasicBlock *PreheaderBB = Builder->GetInsertBlock(); + BasicBlock *LoopBB = BasicBlock::Create(*TheContext, "loop", TheFunction); // Insert an explicit fall through from the current block to the LoopBB. - Builder.CreateBr(LoopBB); + Builder->CreateBr(LoopBB); // Start insertion in LoopBB. - Builder.SetInsertPoint(LoopBB); + Builder->SetInsertPoint(LoopBB); // Start the PHI node with an entry for Start. PHINode *Variable = - Builder.CreatePHI(Type::getDoubleTy(TheContext), 2, VarName); + Builder->CreatePHI(Type::getDoubleTy(*TheContext), 2, VarName); Variable->addIncoming(StartVal, PreheaderBB); // Within the loop, the variable is defined equal to the PHI node. If it @@ -727,10 +728,10 @@ Value *ForExprAST::codegen() { return nullptr; } else { // If not specified, use 1.0. - StepVal = ConstantFP::get(TheContext, APFloat(1.0)); + StepVal = ConstantFP::get(*TheContext, APFloat(1.0)); } - Value *NextVar = Builder.CreateFAdd(Variable, StepVal, "nextvar"); + Value *NextVar = Builder->CreateFAdd(Variable, StepVal, "nextvar"); // Compute the end condition. Value *EndCond = End->codegen(); @@ -738,19 +739,19 @@ Value *ForExprAST::codegen() { return nullptr; // Convert condition to a bool by comparing non-equal to 0.0. - EndCond = Builder.CreateFCmpONE( - EndCond, ConstantFP::get(TheContext, APFloat(0.0)), "loopcond"); + EndCond = Builder->CreateFCmpONE( + EndCond, ConstantFP::get(*TheContext, APFloat(0.0)), "loopcond"); // Create the "after loop" block and insert it. - BasicBlock *LoopEndBB = Builder.GetInsertBlock(); + BasicBlock *LoopEndBB = Builder->GetInsertBlock(); BasicBlock *AfterBB = - BasicBlock::Create(TheContext, "afterloop", TheFunction); + BasicBlock::Create(*TheContext, "afterloop", TheFunction); // Insert the conditional branch into the end of LoopEndBB. - Builder.CreateCondBr(EndCond, LoopBB, AfterBB); + Builder->CreateCondBr(EndCond, LoopBB, AfterBB); // Any new code will be inserted in AfterBB. - Builder.SetInsertPoint(AfterBB); + Builder->SetInsertPoint(AfterBB); // Add a new entry to the PHI node for the backedge. Variable->addIncoming(NextVar, LoopEndBB); @@ -762,14 +763,14 @@ Value *ForExprAST::codegen() { NamedValues.erase(VarName); // for expr always returns 0.0. - return Constant::getNullValue(Type::getDoubleTy(TheContext)); + return Constant::getNullValue(Type::getDoubleTy(*TheContext)); } Function *PrototypeAST::codegen() { // Make the function type: double(double,double) etc. - std::vector Doubles(Args.size(), Type::getDoubleTy(TheContext)); + std::vector Doubles(Args.size(), Type::getDoubleTy(*TheContext)); FunctionType *FT = - FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); + FunctionType::get(Type::getDoubleTy(*TheContext), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get()); @@ -792,8 +793,8 @@ Function *FunctionAST::codegen() { return nullptr; // Create a new basic block to start insertion into. - BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); - Builder.SetInsertPoint(BB); + BasicBlock *BB = BasicBlock::Create(*TheContext, "entry", TheFunction); + Builder->SetInsertPoint(BB); // Record the function arguments in the NamedValues map. NamedValues.clear(); @@ -802,7 +803,7 @@ Function *FunctionAST::codegen() { if (Value *RetVal = Body->codegen()) { // Finish off the function. - Builder.CreateRet(RetVal); + Builder->CreateRet(RetVal); // Validate the generated code, checking for consistency. verifyFunction(*TheFunction); @@ -824,8 +825,12 @@ Function *FunctionAST::codegen() { static void InitializeModuleAndPassManager() { // Open a new module. - TheModule = std::make_unique("my cool jit", TheContext); - TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout()); + TheContext = std::make_unique(); + TheModule = std::make_unique("my cool jit", *TheContext); + TheModule->setDataLayout(TheJIT->getDataLayout()); + + // Create a new builder for the module. + Builder = std::make_unique>(*TheContext); // Create a new pass manager attached to it. TheFPM = std::make_unique(TheModule.get()); @@ -848,7 +853,8 @@ static void HandleDefinition() { fprintf(stderr, "Read function definition:"); FnIR->print(errs()); fprintf(stderr, "\n"); - TheJIT->addModule(std::move(TheModule)); + ExitOnErr(TheJIT->addModule( + ThreadSafeModule(std::move(TheModule), std::move(TheContext)))); InitializeModuleAndPassManager(); } } else { @@ -875,22 +881,24 @@ static void HandleTopLevelExpression() { // Evaluate a top-level expression into an anonymous function. if (auto FnAST = ParseTopLevelExpr()) { if (FnAST->codegen()) { - // JIT the module containing the anonymous expression, keeping a handle so - // we can free it later. - auto H = TheJIT->addModule(std::move(TheModule)); + // Create a ResourceTracker to track JIT'd memory allocated to our + // anonymous expression -- that way we can free it after executing. + auto RT = TheJIT->getMainJITDylib().createResourceTracker(); + + auto TSM = ThreadSafeModule(std::move(TheModule), std::move(TheContext)); + ExitOnErr(TheJIT->addModule(std::move(TSM), RT)); InitializeModuleAndPassManager(); // Search the JIT for the __anon_expr symbol. - auto ExprSymbol = TheJIT->findSymbol("__anon_expr"); - assert(ExprSymbol && "Function not found"); + auto ExprSymbol = ExitOnErr(TheJIT->lookup("__anon_expr")); // Get the symbol's address and cast it to the right type (takes no // arguments, returns a double) so we can call it as a native function. - double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress()); + double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress(); fprintf(stderr, "Evaluated to %f\n", FP()); // Delete the anonymous expression module from the JIT. - TheJIT->removeModule(H); + ExitOnErr(RT->remove()); } } else { // Skip token for error recovery. @@ -963,7 +971,7 @@ int main() { fprintf(stderr, "ready> "); getNextToken(); - TheJIT = std::make_unique(); + TheJIT = ExitOnErr(KaleidoscopeJIT::Create()); InitializeModuleAndPassManager(); diff --git a/llvm/examples/Kaleidoscope/Chapter6/toy.cpp b/llvm/examples/Kaleidoscope/Chapter6/toy.cpp index 2a7dedc..2538221 100644 --- a/llvm/examples/Kaleidoscope/Chapter6/toy.cpp +++ b/llvm/examples/Kaleidoscope/Chapter6/toy.cpp @@ -628,13 +628,14 @@ static std::unique_ptr ParseExtern() { // Code Generation //===----------------------------------------------------------------------===// -static LLVMContext TheContext; -static IRBuilder<> Builder(TheContext); +static std::unique_ptr TheContext; static std::unique_ptr TheModule; +static std::unique_ptr> Builder; static std::map NamedValues; static std::unique_ptr TheFPM; static std::unique_ptr TheJIT; static std::map> FunctionProtos; +static ExitOnError ExitOnErr; Value *LogErrorV(const char *Str) { LogError(Str); @@ -657,7 +658,7 @@ Function *getFunction(std::string Name) { } Value *NumberExprAST::codegen() { - return ConstantFP::get(TheContext, APFloat(Val)); + return ConstantFP::get(*TheContext, APFloat(Val)); } Value *VariableExprAST::codegen() { @@ -677,7 +678,7 @@ Value *UnaryExprAST::codegen() { if (!F) return LogErrorV("Unknown unary operator"); - return Builder.CreateCall(F, OperandV, "unop"); + return Builder->CreateCall(F, OperandV, "unop"); } Value *BinaryExprAST::codegen() { @@ -688,15 +689,15 @@ Value *BinaryExprAST::codegen() { switch (Op) { case '+': - return Builder.CreateFAdd(L, R, "addtmp"); + return Builder->CreateFAdd(L, R, "addtmp"); case '-': - return Builder.CreateFSub(L, R, "subtmp"); + return Builder->CreateFSub(L, R, "subtmp"); case '*': - return Builder.CreateFMul(L, R, "multmp"); + return Builder->CreateFMul(L, R, "multmp"); case '<': - L = Builder.CreateFCmpULT(L, R, "cmptmp"); + L = Builder->CreateFCmpULT(L, R, "cmptmp"); // Convert bool 0/1 to double 0.0 or 1.0 - return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); + return Builder->CreateUIToFP(L, Type::getDoubleTy(*TheContext), "booltmp"); default: break; } @@ -707,7 +708,7 @@ Value *BinaryExprAST::codegen() { assert(F && "binary operator not found!"); Value *Ops[] = {L, R}; - return Builder.CreateCall(F, Ops, "binop"); + return Builder->CreateCall(F, Ops, "binop"); } Value *CallExprAST::codegen() { @@ -727,7 +728,7 @@ Value *CallExprAST::codegen() { return nullptr; } - return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); + return Builder->CreateCall(CalleeF, ArgsV, "calltmp"); } Value *IfExprAST::codegen() { @@ -736,46 +737,46 @@ Value *IfExprAST::codegen() { return nullptr; // Convert condition to a bool by comparing non-equal to 0.0. - CondV = Builder.CreateFCmpONE( - CondV, ConstantFP::get(TheContext, APFloat(0.0)), "ifcond"); + CondV = Builder->CreateFCmpONE( + CondV, ConstantFP::get(*TheContext, APFloat(0.0)), "ifcond"); - Function *TheFunction = Builder.GetInsertBlock()->getParent(); + Function *TheFunction = Builder->GetInsertBlock()->getParent(); // Create blocks for the then and else cases. Insert the 'then' block at the // end of the function. - BasicBlock *ThenBB = BasicBlock::Create(TheContext, "then", TheFunction); - BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else"); - BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont"); + BasicBlock *ThenBB = BasicBlock::Create(*TheContext, "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(*TheContext, "else"); + BasicBlock *MergeBB = BasicBlock::Create(*TheContext, "ifcont"); - Builder.CreateCondBr(CondV, ThenBB, ElseBB); + Builder->CreateCondBr(CondV, ThenBB, ElseBB); // Emit then value. - Builder.SetInsertPoint(ThenBB); + Builder->SetInsertPoint(ThenBB); Value *ThenV = Then->codegen(); if (!ThenV) return nullptr; - Builder.CreateBr(MergeBB); + Builder->CreateBr(MergeBB); // Codegen of 'Then' can change the current block, update ThenBB for the PHI. - ThenBB = Builder.GetInsertBlock(); + ThenBB = Builder->GetInsertBlock(); // Emit else block. TheFunction->getBasicBlockList().push_back(ElseBB); - Builder.SetInsertPoint(ElseBB); + Builder->SetInsertPoint(ElseBB); Value *ElseV = Else->codegen(); if (!ElseV) return nullptr; - Builder.CreateBr(MergeBB); + Builder->CreateBr(MergeBB); // Codegen of 'Else' can change the current block, update ElseBB for the PHI. - ElseBB = Builder.GetInsertBlock(); + ElseBB = Builder->GetInsertBlock(); // Emit merge block. TheFunction->getBasicBlockList().push_back(MergeBB); - Builder.SetInsertPoint(MergeBB); - PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(TheContext), 2, "iftmp"); + Builder->SetInsertPoint(MergeBB); + PHINode *PN = Builder->CreatePHI(Type::getDoubleTy(*TheContext), 2, "iftmp"); PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); @@ -805,19 +806,19 @@ Value *ForExprAST::codegen() { // Make the new basic block for the loop header, inserting after current // block. - Function *TheFunction = Builder.GetInsertBlock()->getParent(); - BasicBlock *PreheaderBB = Builder.GetInsertBlock(); - BasicBlock *LoopBB = BasicBlock::Create(TheContext, "loop", TheFunction); + Function *TheFunction = Builder->GetInsertBlock()->getParent(); + BasicBlock *PreheaderBB = Builder->GetInsertBlock(); + BasicBlock *LoopBB = BasicBlock::Create(*TheContext, "loop", TheFunction); // Insert an explicit fall through from the current block to the LoopBB. - Builder.CreateBr(LoopBB); + Builder->CreateBr(LoopBB); // Start insertion in LoopBB. - Builder.SetInsertPoint(LoopBB); + Builder->SetInsertPoint(LoopBB); // Start the PHI node with an entry for Start. PHINode *Variable = - Builder.CreatePHI(Type::getDoubleTy(TheContext), 2, VarName); + Builder->CreatePHI(Type::getDoubleTy(*TheContext), 2, VarName); Variable->addIncoming(StartVal, PreheaderBB); // Within the loop, the variable is defined equal to the PHI node. If it @@ -839,10 +840,10 @@ Value *ForExprAST::codegen() { return nullptr; } else { // If not specified, use 1.0. - StepVal = ConstantFP::get(TheContext, APFloat(1.0)); + StepVal = ConstantFP::get(*TheContext, APFloat(1.0)); } - Value *NextVar = Builder.CreateFAdd(Variable, StepVal, "nextvar"); + Value *NextVar = Builder->CreateFAdd(Variable, StepVal, "nextvar"); // Compute the end condition. Value *EndCond = End->codegen(); @@ -850,19 +851,19 @@ Value *ForExprAST::codegen() { return nullptr; // Convert condition to a bool by comparing non-equal to 0.0. - EndCond = Builder.CreateFCmpONE( - EndCond, ConstantFP::get(TheContext, APFloat(0.0)), "loopcond"); + EndCond = Builder->CreateFCmpONE( + EndCond, ConstantFP::get(*TheContext, APFloat(0.0)), "loopcond"); // Create the "after loop" block and insert it. - BasicBlock *LoopEndBB = Builder.GetInsertBlock(); + BasicBlock *LoopEndBB = Builder->GetInsertBlock(); BasicBlock *AfterBB = - BasicBlock::Create(TheContext, "afterloop", TheFunction); + BasicBlock::Create(*TheContext, "afterloop", TheFunction); // Insert the conditional branch into the end of LoopEndBB. - Builder.CreateCondBr(EndCond, LoopBB, AfterBB); + Builder->CreateCondBr(EndCond, LoopBB, AfterBB); // Any new code will be inserted in AfterBB. - Builder.SetInsertPoint(AfterBB); + Builder->SetInsertPoint(AfterBB); // Add a new entry to the PHI node for the backedge. Variable->addIncoming(NextVar, LoopEndBB); @@ -874,14 +875,14 @@ Value *ForExprAST::codegen() { NamedValues.erase(VarName); // for expr always returns 0.0. - return Constant::getNullValue(Type::getDoubleTy(TheContext)); + return Constant::getNullValue(Type::getDoubleTy(*TheContext)); } Function *PrototypeAST::codegen() { // Make the function type: double(double,double) etc. - std::vector Doubles(Args.size(), Type::getDoubleTy(TheContext)); + std::vector Doubles(Args.size(), Type::getDoubleTy(*TheContext)); FunctionType *FT = - FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); + FunctionType::get(Type::getDoubleTy(*TheContext), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get()); @@ -908,8 +909,8 @@ Function *FunctionAST::codegen() { BinopPrecedence[P.getOperatorName()] = P.getBinaryPrecedence(); // Create a new basic block to start insertion into. - BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); - Builder.SetInsertPoint(BB); + BasicBlock *BB = BasicBlock::Create(*TheContext, "entry", TheFunction); + Builder->SetInsertPoint(BB); // Record the function arguments in the NamedValues map. NamedValues.clear(); @@ -918,7 +919,7 @@ Function *FunctionAST::codegen() { if (Value *RetVal = Body->codegen()) { // Finish off the function. - Builder.CreateRet(RetVal); + Builder->CreateRet(RetVal); // Validate the generated code, checking for consistency. verifyFunction(*TheFunction); @@ -943,8 +944,12 @@ Function *FunctionAST::codegen() { static void InitializeModuleAndPassManager() { // Open a new module. - TheModule = std::make_unique("my cool jit", TheContext); - TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout()); + TheContext = std::make_unique(); + TheModule = std::make_unique("my cool jit", *TheContext); + TheModule->setDataLayout(TheJIT->getDataLayout()); + + // Create a new builder for the module. + Builder = std::make_unique>(*TheContext); // Create a new pass manager attached to it. TheFPM = std::make_unique(TheModule.get()); @@ -967,7 +972,8 @@ static void HandleDefinition() { fprintf(stderr, "Read function definition:"); FnIR->print(errs()); fprintf(stderr, "\n"); - TheJIT->addModule(std::move(TheModule)); + ExitOnErr(TheJIT->addModule( + ThreadSafeModule(std::move(TheModule), std::move(TheContext)))); InitializeModuleAndPassManager(); } } else { @@ -994,22 +1000,24 @@ static void HandleTopLevelExpression() { // Evaluate a top-level expression into an anonymous function. if (auto FnAST = ParseTopLevelExpr()) { if (FnAST->codegen()) { - // JIT the module containing the anonymous expression, keeping a handle so - // we can free it later. - auto H = TheJIT->addModule(std::move(TheModule)); + // Create a ResourceTracker to track JIT'd memory allocated to our + // anonymous expression -- that way we can free it after executing. + auto RT = TheJIT->getMainJITDylib().createResourceTracker(); + + auto TSM = ThreadSafeModule(std::move(TheModule), std::move(TheContext)); + ExitOnErr(TheJIT->addModule(std::move(TSM), RT)); InitializeModuleAndPassManager(); // Search the JIT for the __anon_expr symbol. - auto ExprSymbol = TheJIT->findSymbol("__anon_expr"); - assert(ExprSymbol && "Function not found"); + auto ExprSymbol = ExitOnErr(TheJIT->lookup("__anon_expr")); // Get the symbol's address and cast it to the right type (takes no // arguments, returns a double) so we can call it as a native function. - double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress()); + double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress(); fprintf(stderr, "Evaluated to %f\n", FP()); // Delete the anonymous expression module from the JIT. - TheJIT->removeModule(H); + ExitOnErr(RT->remove()); } } else { // Skip token for error recovery. @@ -1082,7 +1090,7 @@ int main() { fprintf(stderr, "ready> "); getNextToken(); - TheJIT = std::make_unique(); + TheJIT = ExitOnErr(KaleidoscopeJIT::Create()); InitializeModuleAndPassManager(); diff --git a/llvm/examples/Kaleidoscope/Chapter7/toy.cpp b/llvm/examples/Kaleidoscope/Chapter7/toy.cpp index 317b602..f2d4cbb 100644 --- a/llvm/examples/Kaleidoscope/Chapter7/toy.cpp +++ b/llvm/examples/Kaleidoscope/Chapter7/toy.cpp @@ -701,13 +701,14 @@ static std::unique_ptr ParseExtern() { // Code Generation //===----------------------------------------------------------------------===// -static LLVMContext TheContext; -static IRBuilder<> Builder(TheContext); +static std::unique_ptr TheContext; static std::unique_ptr TheModule; +static std::unique_ptr> Builder; static std::map NamedValues; static std::unique_ptr TheFPM; static std::unique_ptr TheJIT; static std::map> FunctionProtos; +static ExitOnError ExitOnErr; Value *LogErrorV(const char *Str) { LogError(Str); @@ -735,11 +736,11 @@ static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, StringRef VarName) { IRBuilder<> TmpB(&TheFunction->getEntryBlock(), TheFunction->getEntryBlock().begin()); - return TmpB.CreateAlloca(Type::getDoubleTy(TheContext), nullptr, VarName); + return TmpB.CreateAlloca(Type::getDoubleTy(*TheContext), nullptr, VarName); } Value *NumberExprAST::codegen() { - return ConstantFP::get(TheContext, APFloat(Val)); + return ConstantFP::get(*TheContext, APFloat(Val)); } Value *VariableExprAST::codegen() { @@ -749,7 +750,7 @@ Value *VariableExprAST::codegen() { return LogErrorV("Unknown variable name"); // Load the value. - return Builder.CreateLoad(V, Name.c_str()); + return Builder->CreateLoad(V, Name.c_str()); } Value *UnaryExprAST::codegen() { @@ -761,7 +762,7 @@ Value *UnaryExprAST::codegen() { if (!F) return LogErrorV("Unknown unary operator"); - return Builder.CreateCall(F, OperandV, "unop"); + return Builder->CreateCall(F, OperandV, "unop"); } Value *BinaryExprAST::codegen() { @@ -784,7 +785,7 @@ Value *BinaryExprAST::codegen() { if (!Variable) return LogErrorV("Unknown variable name"); - Builder.CreateStore(Val, Variable); + Builder->CreateStore(Val, Variable); return Val; } @@ -795,15 +796,15 @@ Value *BinaryExprAST::codegen() { switch (Op) { case '+': - return Builder.CreateFAdd(L, R, "addtmp"); + return Builder->CreateFAdd(L, R, "addtmp"); case '-': - return Builder.CreateFSub(L, R, "subtmp"); + return Builder->CreateFSub(L, R, "subtmp"); case '*': - return Builder.CreateFMul(L, R, "multmp"); + return Builder->CreateFMul(L, R, "multmp"); case '<': - L = Builder.CreateFCmpULT(L, R, "cmptmp"); + L = Builder->CreateFCmpULT(L, R, "cmptmp"); // Convert bool 0/1 to double 0.0 or 1.0 - return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); + return Builder->CreateUIToFP(L, Type::getDoubleTy(*TheContext), "booltmp"); default: break; } @@ -814,7 +815,7 @@ Value *BinaryExprAST::codegen() { assert(F && "binary operator not found!"); Value *Ops[] = {L, R}; - return Builder.CreateCall(F, Ops, "binop"); + return Builder->CreateCall(F, Ops, "binop"); } Value *CallExprAST::codegen() { @@ -834,7 +835,7 @@ Value *CallExprAST::codegen() { return nullptr; } - return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); + return Builder->CreateCall(CalleeF, ArgsV, "calltmp"); } Value *IfExprAST::codegen() { @@ -843,46 +844,46 @@ Value *IfExprAST::codegen() { return nullptr; // Convert condition to a bool by comparing non-equal to 0.0. - CondV = Builder.CreateFCmpONE( - CondV, ConstantFP::get(TheContext, APFloat(0.0)), "ifcond"); + CondV = Builder->CreateFCmpONE( + CondV, ConstantFP::get(*TheContext, APFloat(0.0)), "ifcond"); - Function *TheFunction = Builder.GetInsertBlock()->getParent(); + Function *TheFunction = Builder->GetInsertBlock()->getParent(); // Create blocks for the then and else cases. Insert the 'then' block at the // end of the function. - BasicBlock *ThenBB = BasicBlock::Create(TheContext, "then", TheFunction); - BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else"); - BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont"); + BasicBlock *ThenBB = BasicBlock::Create(*TheContext, "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(*TheContext, "else"); + BasicBlock *MergeBB = BasicBlock::Create(*TheContext, "ifcont"); - Builder.CreateCondBr(CondV, ThenBB, ElseBB); + Builder->CreateCondBr(CondV, ThenBB, ElseBB); // Emit then value. - Builder.SetInsertPoint(ThenBB); + Builder->SetInsertPoint(ThenBB); Value *ThenV = Then->codegen(); if (!ThenV) return nullptr; - Builder.CreateBr(MergeBB); + Builder->CreateBr(MergeBB); // Codegen of 'Then' can change the current block, update ThenBB for the PHI. - ThenBB = Builder.GetInsertBlock(); + ThenBB = Builder->GetInsertBlock(); // Emit else block. TheFunction->getBasicBlockList().push_back(ElseBB); - Builder.SetInsertPoint(ElseBB); + Builder->SetInsertPoint(ElseBB); Value *ElseV = Else->codegen(); if (!ElseV) return nullptr; - Builder.CreateBr(MergeBB); + Builder->CreateBr(MergeBB); // Codegen of 'Else' can change the current block, update ElseBB for the PHI. - ElseBB = Builder.GetInsertBlock(); + ElseBB = Builder->GetInsertBlock(); // Emit merge block. TheFunction->getBasicBlockList().push_back(MergeBB); - Builder.SetInsertPoint(MergeBB); - PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(TheContext), 2, "iftmp"); + Builder->SetInsertPoint(MergeBB); + PHINode *PN = Builder->CreatePHI(Type::getDoubleTy(*TheContext), 2, "iftmp"); PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); @@ -909,7 +910,7 @@ Value *IfExprAST::codegen() { // br endcond, loop, endloop // outloop: Value *ForExprAST::codegen() { - Function *TheFunction = Builder.GetInsertBlock()->getParent(); + Function *TheFunction = Builder->GetInsertBlock()->getParent(); // Create an alloca for the variable in the entry block. AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); @@ -920,17 +921,17 @@ Value *ForExprAST::codegen() { return nullptr; // Store the value into the alloca. - Builder.CreateStore(StartVal, Alloca); + Builder->CreateStore(StartVal, Alloca); // Make the new basic block for the loop header, inserting after current // block. - BasicBlock *LoopBB = BasicBlock::Create(TheContext, "loop", TheFunction); + BasicBlock *LoopBB = BasicBlock::Create(*TheContext, "loop", TheFunction); // Insert an explicit fall through from the current block to the LoopBB. - Builder.CreateBr(LoopBB); + Builder->CreateBr(LoopBB); // Start insertion in LoopBB. - Builder.SetInsertPoint(LoopBB); + Builder->SetInsertPoint(LoopBB); // Within the loop, the variable is defined equal to the PHI node. If it // shadows an existing variable, we have to restore it, so save it now. @@ -951,7 +952,7 @@ Value *ForExprAST::codegen() { return nullptr; } else { // If not specified, use 1.0. - StepVal = ConstantFP::get(TheContext, APFloat(1.0)); + StepVal = ConstantFP::get(*TheContext, APFloat(1.0)); } // Compute the end condition. @@ -961,23 +962,23 @@ Value *ForExprAST::codegen() { // Reload, increment, and restore the alloca. This handles the case where // the body of the loop mutates the variable. - Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str()); - Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar"); - Builder.CreateStore(NextVar, Alloca); + Value *CurVar = Builder->CreateLoad(Alloca, VarName.c_str()); + Value *NextVar = Builder->CreateFAdd(CurVar, StepVal, "nextvar"); + Builder->CreateStore(NextVar, Alloca); // Convert condition to a bool by comparing non-equal to 0.0. - EndCond = Builder.CreateFCmpONE( - EndCond, ConstantFP::get(TheContext, APFloat(0.0)), "loopcond"); + EndCond = Builder->CreateFCmpONE( + EndCond, ConstantFP::get(*TheContext, APFloat(0.0)), "loopcond"); // Create the "after loop" block and insert it. BasicBlock *AfterBB = - BasicBlock::Create(TheContext, "afterloop", TheFunction); + BasicBlock::Create(*TheContext, "afterloop", TheFunction); // Insert the conditional branch into the end of LoopEndBB. - Builder.CreateCondBr(EndCond, LoopBB, AfterBB); + Builder->CreateCondBr(EndCond, LoopBB, AfterBB); // Any new code will be inserted in AfterBB. - Builder.SetInsertPoint(AfterBB); + Builder->SetInsertPoint(AfterBB); // Restore the unshadowed variable. if (OldVal) @@ -986,13 +987,13 @@ Value *ForExprAST::codegen() { NamedValues.erase(VarName); // for expr always returns 0.0. - return Constant::getNullValue(Type::getDoubleTy(TheContext)); + return Constant::getNullValue(Type::getDoubleTy(*TheContext)); } Value *VarExprAST::codegen() { std::vector OldBindings; - Function *TheFunction = Builder.GetInsertBlock()->getParent(); + Function *TheFunction = Builder->GetInsertBlock()->getParent(); // Register all variables and emit their initializer. for (unsigned i = 0, e = VarNames.size(); i != e; ++i) { @@ -1010,11 +1011,11 @@ Value *VarExprAST::codegen() { if (!InitVal) return nullptr; } else { // If not specified, use 0.0. - InitVal = ConstantFP::get(TheContext, APFloat(0.0)); + InitVal = ConstantFP::get(*TheContext, APFloat(0.0)); } AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); - Builder.CreateStore(InitVal, Alloca); + Builder->CreateStore(InitVal, Alloca); // Remember the old variable binding so that we can restore the binding when // we unrecurse. @@ -1039,9 +1040,9 @@ Value *VarExprAST::codegen() { Function *PrototypeAST::codegen() { // Make the function type: double(double,double) etc. - std::vector Doubles(Args.size(), Type::getDoubleTy(TheContext)); + std::vector Doubles(Args.size(), Type::getDoubleTy(*TheContext)); FunctionType *FT = - FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); + FunctionType::get(Type::getDoubleTy(*TheContext), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get()); @@ -1068,8 +1069,8 @@ Function *FunctionAST::codegen() { BinopPrecedence[P.getOperatorName()] = P.getBinaryPrecedence(); // Create a new basic block to start insertion into. - BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); - Builder.SetInsertPoint(BB); + BasicBlock *BB = BasicBlock::Create(*TheContext, "entry", TheFunction); + Builder->SetInsertPoint(BB); // Record the function arguments in the NamedValues map. NamedValues.clear(); @@ -1078,7 +1079,7 @@ Function *FunctionAST::codegen() { AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, Arg.getName()); // Store the initial value into the alloca. - Builder.CreateStore(&Arg, Alloca); + Builder->CreateStore(&Arg, Alloca); // Add arguments to variable symbol table. NamedValues[std::string(Arg.getName())] = Alloca; @@ -1086,7 +1087,7 @@ Function *FunctionAST::codegen() { if (Value *RetVal = Body->codegen()) { // Finish off the function. - Builder.CreateRet(RetVal); + Builder->CreateRet(RetVal); // Validate the generated code, checking for consistency. verifyFunction(*TheFunction); @@ -1111,8 +1112,12 @@ Function *FunctionAST::codegen() { static void InitializeModuleAndPassManager() { // Open a new module. - TheModule = std::make_unique("my cool jit", TheContext); - TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout()); + TheContext = std::make_unique(); + TheModule = std::make_unique("my cool jit", *TheContext); + TheModule->setDataLayout(TheJIT->getDataLayout()); + + // Create a new builder for the module. + Builder = std::make_unique>(*TheContext); // Create a new pass manager attached to it. TheFPM = std::make_unique(TheModule.get()); @@ -1137,7 +1142,8 @@ static void HandleDefinition() { fprintf(stderr, "Read function definition:"); FnIR->print(errs()); fprintf(stderr, "\n"); - TheJIT->addModule(std::move(TheModule)); + ExitOnErr(TheJIT->addModule( + ThreadSafeModule(std::move(TheModule), std::move(TheContext)))); InitializeModuleAndPassManager(); } } else { @@ -1164,22 +1170,24 @@ static void HandleTopLevelExpression() { // Evaluate a top-level expression into an anonymous function. if (auto FnAST = ParseTopLevelExpr()) { if (FnAST->codegen()) { - // JIT the module containing the anonymous expression, keeping a handle so - // we can free it later. - auto H = TheJIT->addModule(std::move(TheModule)); + // Create a ResourceTracker to track JIT'd memory allocated to our + // anonymous expression -- that way we can free it after executing. + auto RT = TheJIT->getMainJITDylib().createResourceTracker(); + + auto TSM = ThreadSafeModule(std::move(TheModule), std::move(TheContext)); + ExitOnErr(TheJIT->addModule(std::move(TSM), RT)); InitializeModuleAndPassManager(); // Search the JIT for the __anon_expr symbol. - auto ExprSymbol = TheJIT->findSymbol("__anon_expr"); - assert(ExprSymbol && "Function not found"); + auto ExprSymbol = ExitOnErr(TheJIT->lookup("__anon_expr")); // Get the symbol's address and cast it to the right type (takes no // arguments, returns a double) so we can call it as a native function. - double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress()); + double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress(); fprintf(stderr, "Evaluated to %f\n", FP()); // Delete the anonymous expression module from the JIT. - TheJIT->removeModule(H); + ExitOnErr(RT->remove()); } } else { // Skip token for error recovery. @@ -1253,7 +1261,7 @@ int main() { fprintf(stderr, "ready> "); getNextToken(); - TheJIT = std::make_unique(); + TheJIT = ExitOnErr(KaleidoscopeJIT::Create()); InitializeModuleAndPassManager(); diff --git a/llvm/examples/Kaleidoscope/Chapter8/toy.cpp b/llvm/examples/Kaleidoscope/Chapter8/toy.cpp index 9290374..a1fe89a 100644 --- a/llvm/examples/Kaleidoscope/Chapter8/toy.cpp +++ b/llvm/examples/Kaleidoscope/Chapter8/toy.cpp @@ -702,11 +702,12 @@ static std::unique_ptr ParseExtern() { // Code Generation //===----------------------------------------------------------------------===// -static LLVMContext TheContext; -static IRBuilder<> Builder(TheContext); +static std::unique_ptr TheContext; static std::unique_ptr TheModule; +static std::unique_ptr> Builder; static std::map NamedValues; static std::map> FunctionProtos; +static ExitOnError ExitOnErr; Value *LogErrorV(const char *Str) { LogError(Str); @@ -734,11 +735,11 @@ static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, StringRef VarName) { IRBuilder<> TmpB(&TheFunction->getEntryBlock(), TheFunction->getEntryBlock().begin()); - return TmpB.CreateAlloca(Type::getDoubleTy(TheContext), nullptr, VarName); + return TmpB.CreateAlloca(Type::getDoubleTy(*TheContext), nullptr, VarName); } Value *NumberExprAST::codegen() { - return ConstantFP::get(TheContext, APFloat(Val)); + return ConstantFP::get(*TheContext, APFloat(Val)); } Value *VariableExprAST::codegen() { @@ -748,7 +749,7 @@ Value *VariableExprAST::codegen() { return LogErrorV("Unknown variable name"); // Load the value. - return Builder.CreateLoad(V, Name.c_str()); + return Builder->CreateLoad(V, Name.c_str()); } Value *UnaryExprAST::codegen() { @@ -760,7 +761,7 @@ Value *UnaryExprAST::codegen() { if (!F) return LogErrorV("Unknown unary operator"); - return Builder.CreateCall(F, OperandV, "unop"); + return Builder->CreateCall(F, OperandV, "unop"); } Value *BinaryExprAST::codegen() { @@ -783,7 +784,7 @@ Value *BinaryExprAST::codegen() { if (!Variable) return LogErrorV("Unknown variable name"); - Builder.CreateStore(Val, Variable); + Builder->CreateStore(Val, Variable); return Val; } @@ -794,15 +795,15 @@ Value *BinaryExprAST::codegen() { switch (Op) { case '+': - return Builder.CreateFAdd(L, R, "addtmp"); + return Builder->CreateFAdd(L, R, "addtmp"); case '-': - return Builder.CreateFSub(L, R, "subtmp"); + return Builder->CreateFSub(L, R, "subtmp"); case '*': - return Builder.CreateFMul(L, R, "multmp"); + return Builder->CreateFMul(L, R, "multmp"); case '<': - L = Builder.CreateFCmpULT(L, R, "cmptmp"); + L = Builder->CreateFCmpULT(L, R, "cmptmp"); // Convert bool 0/1 to double 0.0 or 1.0 - return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); + return Builder->CreateUIToFP(L, Type::getDoubleTy(*TheContext), "booltmp"); default: break; } @@ -813,7 +814,7 @@ Value *BinaryExprAST::codegen() { assert(F && "binary operator not found!"); Value *Ops[] = {L, R}; - return Builder.CreateCall(F, Ops, "binop"); + return Builder->CreateCall(F, Ops, "binop"); } Value *CallExprAST::codegen() { @@ -833,7 +834,7 @@ Value *CallExprAST::codegen() { return nullptr; } - return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); + return Builder->CreateCall(CalleeF, ArgsV, "calltmp"); } Value *IfExprAST::codegen() { @@ -842,46 +843,46 @@ Value *IfExprAST::codegen() { return nullptr; // Convert condition to a bool by comparing non-equal to 0.0. - CondV = Builder.CreateFCmpONE( - CondV, ConstantFP::get(TheContext, APFloat(0.0)), "ifcond"); + CondV = Builder->CreateFCmpONE( + CondV, ConstantFP::get(*TheContext, APFloat(0.0)), "ifcond"); - Function *TheFunction = Builder.GetInsertBlock()->getParent(); + Function *TheFunction = Builder->GetInsertBlock()->getParent(); // Create blocks for the then and else cases. Insert the 'then' block at the // end of the function. - BasicBlock *ThenBB = BasicBlock::Create(TheContext, "then", TheFunction); - BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else"); - BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont"); + BasicBlock *ThenBB = BasicBlock::Create(*TheContext, "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(*TheContext, "else"); + BasicBlock *MergeBB = BasicBlock::Create(*TheContext, "ifcont"); - Builder.CreateCondBr(CondV, ThenBB, ElseBB); + Builder->CreateCondBr(CondV, ThenBB, ElseBB); // Emit then value. - Builder.SetInsertPoint(ThenBB); + Builder->SetInsertPoint(ThenBB); Value *ThenV = Then->codegen(); if (!ThenV) return nullptr; - Builder.CreateBr(MergeBB); + Builder->CreateBr(MergeBB); // Codegen of 'Then' can change the current block, update ThenBB for the PHI. - ThenBB = Builder.GetInsertBlock(); + ThenBB = Builder->GetInsertBlock(); // Emit else block. TheFunction->getBasicBlockList().push_back(ElseBB); - Builder.SetInsertPoint(ElseBB); + Builder->SetInsertPoint(ElseBB); Value *ElseV = Else->codegen(); if (!ElseV) return nullptr; - Builder.CreateBr(MergeBB); + Builder->CreateBr(MergeBB); // Codegen of 'Else' can change the current block, update ElseBB for the PHI. - ElseBB = Builder.GetInsertBlock(); + ElseBB = Builder->GetInsertBlock(); // Emit merge block. TheFunction->getBasicBlockList().push_back(MergeBB); - Builder.SetInsertPoint(MergeBB); - PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(TheContext), 2, "iftmp"); + Builder->SetInsertPoint(MergeBB); + PHINode *PN = Builder->CreatePHI(Type::getDoubleTy(*TheContext), 2, "iftmp"); PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); @@ -908,7 +909,7 @@ Value *IfExprAST::codegen() { // br endcond, loop, endloop // outloop: Value *ForExprAST::codegen() { - Function *TheFunction = Builder.GetInsertBlock()->getParent(); + Function *TheFunction = Builder->GetInsertBlock()->getParent(); // Create an alloca for the variable in the entry block. AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); @@ -919,17 +920,17 @@ Value *ForExprAST::codegen() { return nullptr; // Store the value into the alloca. - Builder.CreateStore(StartVal, Alloca); + Builder->CreateStore(StartVal, Alloca); // Make the new basic block for the loop header, inserting after current // block. - BasicBlock *LoopBB = BasicBlock::Create(TheContext, "loop", TheFunction); + BasicBlock *LoopBB = BasicBlock::Create(*TheContext, "loop", TheFunction); // Insert an explicit fall through from the current block to the LoopBB. - Builder.CreateBr(LoopBB); + Builder->CreateBr(LoopBB); // Start insertion in LoopBB. - Builder.SetInsertPoint(LoopBB); + Builder->SetInsertPoint(LoopBB); // Within the loop, the variable is defined equal to the PHI node. If it // shadows an existing variable, we have to restore it, so save it now. @@ -950,7 +951,7 @@ Value *ForExprAST::codegen() { return nullptr; } else { // If not specified, use 1.0. - StepVal = ConstantFP::get(TheContext, APFloat(1.0)); + StepVal = ConstantFP::get(*TheContext, APFloat(1.0)); } // Compute the end condition. @@ -960,23 +961,23 @@ Value *ForExprAST::codegen() { // Reload, increment, and restore the alloca. This handles the case where // the body of the loop mutates the variable. - Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str()); - Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar"); - Builder.CreateStore(NextVar, Alloca); + Value *CurVar = Builder->CreateLoad(Alloca, VarName.c_str()); + Value *NextVar = Builder->CreateFAdd(CurVar, StepVal, "nextvar"); + Builder->CreateStore(NextVar, Alloca); // Convert condition to a bool by comparing non-equal to 0.0. - EndCond = Builder.CreateFCmpONE( - EndCond, ConstantFP::get(TheContext, APFloat(0.0)), "loopcond"); + EndCond = Builder->CreateFCmpONE( + EndCond, ConstantFP::get(*TheContext, APFloat(0.0)), "loopcond"); // Create the "after loop" block and insert it. BasicBlock *AfterBB = - BasicBlock::Create(TheContext, "afterloop", TheFunction); + BasicBlock::Create(*TheContext, "afterloop", TheFunction); // Insert the conditional branch into the end of LoopEndBB. - Builder.CreateCondBr(EndCond, LoopBB, AfterBB); + Builder->CreateCondBr(EndCond, LoopBB, AfterBB); // Any new code will be inserted in AfterBB. - Builder.SetInsertPoint(AfterBB); + Builder->SetInsertPoint(AfterBB); // Restore the unshadowed variable. if (OldVal) @@ -985,13 +986,13 @@ Value *ForExprAST::codegen() { NamedValues.erase(VarName); // for expr always returns 0.0. - return Constant::getNullValue(Type::getDoubleTy(TheContext)); + return Constant::getNullValue(Type::getDoubleTy(*TheContext)); } Value *VarExprAST::codegen() { std::vector OldBindings; - Function *TheFunction = Builder.GetInsertBlock()->getParent(); + Function *TheFunction = Builder->GetInsertBlock()->getParent(); // Register all variables and emit their initializer. for (unsigned i = 0, e = VarNames.size(); i != e; ++i) { @@ -1009,11 +1010,11 @@ Value *VarExprAST::codegen() { if (!InitVal) return nullptr; } else { // If not specified, use 0.0. - InitVal = ConstantFP::get(TheContext, APFloat(0.0)); + InitVal = ConstantFP::get(*TheContext, APFloat(0.0)); } AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); - Builder.CreateStore(InitVal, Alloca); + Builder->CreateStore(InitVal, Alloca); // Remember the old variable binding so that we can restore the binding when // we unrecurse. @@ -1038,9 +1039,9 @@ Value *VarExprAST::codegen() { Function *PrototypeAST::codegen() { // Make the function type: double(double,double) etc. - std::vector Doubles(Args.size(), Type::getDoubleTy(TheContext)); + std::vector Doubles(Args.size(), Type::getDoubleTy(*TheContext)); FunctionType *FT = - FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); + FunctionType::get(Type::getDoubleTy(*TheContext), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get()); @@ -1067,8 +1068,8 @@ Function *FunctionAST::codegen() { BinopPrecedence[P.getOperatorName()] = P.getBinaryPrecedence(); // Create a new basic block to start insertion into. - BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); - Builder.SetInsertPoint(BB); + BasicBlock *BB = BasicBlock::Create(*TheContext, "entry", TheFunction); + Builder->SetInsertPoint(BB); // Record the function arguments in the NamedValues map. NamedValues.clear(); @@ -1077,7 +1078,7 @@ Function *FunctionAST::codegen() { AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, Arg.getName()); // Store the initial value into the alloca. - Builder.CreateStore(&Arg, Alloca); + Builder->CreateStore(&Arg, Alloca); // Add arguments to variable symbol table. NamedValues[std::string(Arg.getName())] = Alloca; @@ -1085,7 +1086,7 @@ Function *FunctionAST::codegen() { if (Value *RetVal = Body->codegen()) { // Finish off the function. - Builder.CreateRet(RetVal); + Builder->CreateRet(RetVal); // Validate the generated code, checking for consistency. verifyFunction(*TheFunction); @@ -1107,7 +1108,11 @@ Function *FunctionAST::codegen() { static void InitializeModuleAndPassManager() { // Open a new module. - TheModule = std::make_unique("my cool jit", TheContext); + TheContext = std::make_unique(); + TheModule = std::make_unique("my cool jit", *TheContext); + + // Create a new builder for the module. + Builder = std::make_unique>(*TheContext); } static void HandleDefinition() { diff --git a/llvm/examples/Kaleidoscope/Chapter9/toy.cpp b/llvm/examples/Kaleidoscope/Chapter9/toy.cpp index 7b33dae..29a4ee1 100644 --- a/llvm/examples/Kaleidoscope/Chapter9/toy.cpp +++ b/llvm/examples/Kaleidoscope/Chapter9/toy.cpp @@ -88,8 +88,7 @@ namespace { class PrototypeAST; class ExprAST; } -static LLVMContext TheContext; -static IRBuilder<> Builder(TheContext); + struct DebugInfo { DICompileUnit *TheCU; DIType *DblTy; @@ -815,6 +814,19 @@ static std::unique_ptr ParseExtern() { } //===----------------------------------------------------------------------===// +// Code Generation Globals +//===----------------------------------------------------------------------===// + +static std::unique_ptr TheContext; +static std::unique_ptr TheModule; +static std::unique_ptr> Builder; +static ExitOnError ExitOnErr; + +static std::map NamedValues; +static std::unique_ptr TheJIT; +static std::map> FunctionProtos; + +//===----------------------------------------------------------------------===// // Debug Info Support //===----------------------------------------------------------------------===// @@ -830,13 +842,13 @@ DIType *DebugInfo::getDoubleTy() { void DebugInfo::emitLocation(ExprAST *AST) { if (!AST) - return Builder.SetCurrentDebugLocation(DebugLoc()); + return Builder->SetCurrentDebugLocation(DebugLoc()); DIScope *Scope; if (LexicalBlocks.empty()) Scope = TheCU; else Scope = LexicalBlocks.back(); - Builder.SetCurrentDebugLocation( + Builder->SetCurrentDebugLocation( DebugLoc::get(AST->getLine(), AST->getCol(), Scope)); } @@ -857,11 +869,6 @@ static DISubroutineType *CreateFunctionType(unsigned NumArgs, DIFile *Unit) { // Code Generation //===----------------------------------------------------------------------===// -static std::unique_ptr TheModule; -static std::map NamedValues; -static std::unique_ptr TheJIT; -static std::map> FunctionProtos; - Value *LogErrorV(const char *Str) { LogError(Str); return nullptr; @@ -888,12 +895,12 @@ static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, StringRef VarName) { IRBuilder<> TmpB(&TheFunction->getEntryBlock(), TheFunction->getEntryBlock().begin()); - return TmpB.CreateAlloca(Type::getDoubleTy(TheContext), nullptr, VarName); + return TmpB.CreateAlloca(Type::getDoubleTy(*TheContext), nullptr, VarName); } Value *NumberExprAST::codegen() { KSDbgInfo.emitLocation(this); - return ConstantFP::get(TheContext, APFloat(Val)); + return ConstantFP::get(*TheContext, APFloat(Val)); } Value *VariableExprAST::codegen() { @@ -904,7 +911,7 @@ Value *VariableExprAST::codegen() { KSDbgInfo.emitLocation(this); // Load the value. - return Builder.CreateLoad(V, Name.c_str()); + return Builder->CreateLoad(V, Name.c_str()); } Value *UnaryExprAST::codegen() { @@ -917,7 +924,7 @@ Value *UnaryExprAST::codegen() { return LogErrorV("Unknown unary operator"); KSDbgInfo.emitLocation(this); - return Builder.CreateCall(F, OperandV, "unop"); + return Builder->CreateCall(F, OperandV, "unop"); } Value *BinaryExprAST::codegen() { @@ -942,7 +949,7 @@ Value *BinaryExprAST::codegen() { if (!Variable) return LogErrorV("Unknown variable name"); - Builder.CreateStore(Val, Variable); + Builder->CreateStore(Val, Variable); return Val; } @@ -953,15 +960,15 @@ Value *BinaryExprAST::codegen() { switch (Op) { case '+': - return Builder.CreateFAdd(L, R, "addtmp"); + return Builder->CreateFAdd(L, R, "addtmp"); case '-': - return Builder.CreateFSub(L, R, "subtmp"); + return Builder->CreateFSub(L, R, "subtmp"); case '*': - return Builder.CreateFMul(L, R, "multmp"); + return Builder->CreateFMul(L, R, "multmp"); case '<': - L = Builder.CreateFCmpULT(L, R, "cmptmp"); + L = Builder->CreateFCmpULT(L, R, "cmptmp"); // Convert bool 0/1 to double 0.0 or 1.0 - return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); + return Builder->CreateUIToFP(L, Type::getDoubleTy(*TheContext), "booltmp"); default: break; } @@ -972,7 +979,7 @@ Value *BinaryExprAST::codegen() { assert(F && "binary operator not found!"); Value *Ops[] = {L, R}; - return Builder.CreateCall(F, Ops, "binop"); + return Builder->CreateCall(F, Ops, "binop"); } Value *CallExprAST::codegen() { @@ -994,7 +1001,7 @@ Value *CallExprAST::codegen() { return nullptr; } - return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); + return Builder->CreateCall(CalleeF, ArgsV, "calltmp"); } Value *IfExprAST::codegen() { @@ -1005,46 +1012,46 @@ Value *IfExprAST::codegen() { return nullptr; // Convert condition to a bool by comparing non-equal to 0.0. - CondV = Builder.CreateFCmpONE( - CondV, ConstantFP::get(TheContext, APFloat(0.0)), "ifcond"); + CondV = Builder->CreateFCmpONE( + CondV, ConstantFP::get(*TheContext, APFloat(0.0)), "ifcond"); - Function *TheFunction = Builder.GetInsertBlock()->getParent(); + Function *TheFunction = Builder->GetInsertBlock()->getParent(); // Create blocks for the then and else cases. Insert the 'then' block at the // end of the function. - BasicBlock *ThenBB = BasicBlock::Create(TheContext, "then", TheFunction); - BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else"); - BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont"); + BasicBlock *ThenBB = BasicBlock::Create(*TheContext, "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(*TheContext, "else"); + BasicBlock *MergeBB = BasicBlock::Create(*TheContext, "ifcont"); - Builder.CreateCondBr(CondV, ThenBB, ElseBB); + Builder->CreateCondBr(CondV, ThenBB, ElseBB); // Emit then value. - Builder.SetInsertPoint(ThenBB); + Builder->SetInsertPoint(ThenBB); Value *ThenV = Then->codegen(); if (!ThenV) return nullptr; - Builder.CreateBr(MergeBB); + Builder->CreateBr(MergeBB); // Codegen of 'Then' can change the current block, update ThenBB for the PHI. - ThenBB = Builder.GetInsertBlock(); + ThenBB = Builder->GetInsertBlock(); // Emit else block. TheFunction->getBasicBlockList().push_back(ElseBB); - Builder.SetInsertPoint(ElseBB); + Builder->SetInsertPoint(ElseBB); Value *ElseV = Else->codegen(); if (!ElseV) return nullptr; - Builder.CreateBr(MergeBB); + Builder->CreateBr(MergeBB); // Codegen of 'Else' can change the current block, update ElseBB for the PHI. - ElseBB = Builder.GetInsertBlock(); + ElseBB = Builder->GetInsertBlock(); // Emit merge block. TheFunction->getBasicBlockList().push_back(MergeBB); - Builder.SetInsertPoint(MergeBB); - PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(TheContext), 2, "iftmp"); + Builder->SetInsertPoint(MergeBB); + PHINode *PN = Builder->CreatePHI(Type::getDoubleTy(*TheContext), 2, "iftmp"); PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); @@ -1071,7 +1078,7 @@ Value *IfExprAST::codegen() { // br endcond, loop, endloop // outloop: Value *ForExprAST::codegen() { - Function *TheFunction = Builder.GetInsertBlock()->getParent(); + Function *TheFunction = Builder->GetInsertBlock()->getParent(); // Create an alloca for the variable in the entry block. AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); @@ -1084,17 +1091,17 @@ Value *ForExprAST::codegen() { return nullptr; // Store the value into the alloca. - Builder.CreateStore(StartVal, Alloca); + Builder->CreateStore(StartVal, Alloca); // Make the new basic block for the loop header, inserting after current // block. - BasicBlock *LoopBB = BasicBlock::Create(TheContext, "loop", TheFunction); + BasicBlock *LoopBB = BasicBlock::Create(*TheContext, "loop", TheFunction); // Insert an explicit fall through from the current block to the LoopBB. - Builder.CreateBr(LoopBB); + Builder->CreateBr(LoopBB); // Start insertion in LoopBB. - Builder.SetInsertPoint(LoopBB); + Builder->SetInsertPoint(LoopBB); // Within the loop, the variable is defined equal to the PHI node. If it // shadows an existing variable, we have to restore it, so save it now. @@ -1115,7 +1122,7 @@ Value *ForExprAST::codegen() { return nullptr; } else { // If not specified, use 1.0. - StepVal = ConstantFP::get(TheContext, APFloat(1.0)); + StepVal = ConstantFP::get(*TheContext, APFloat(1.0)); } // Compute the end condition. @@ -1125,23 +1132,23 @@ Value *ForExprAST::codegen() { // Reload, increment, and restore the alloca. This handles the case where // the body of the loop mutates the variable. - Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str()); - Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar"); - Builder.CreateStore(NextVar, Alloca); + Value *CurVar = Builder->CreateLoad(Alloca, VarName.c_str()); + Value *NextVar = Builder->CreateFAdd(CurVar, StepVal, "nextvar"); + Builder->CreateStore(NextVar, Alloca); // Convert condition to a bool by comparing non-equal to 0.0. - EndCond = Builder.CreateFCmpONE( - EndCond, ConstantFP::get(TheContext, APFloat(0.0)), "loopcond"); + EndCond = Builder->CreateFCmpONE( + EndCond, ConstantFP::get(*TheContext, APFloat(0.0)), "loopcond"); // Create the "after loop" block and insert it. BasicBlock *AfterBB = - BasicBlock::Create(TheContext, "afterloop", TheFunction); + BasicBlock::Create(*TheContext, "afterloop", TheFunction); // Insert the conditional branch into the end of LoopEndBB. - Builder.CreateCondBr(EndCond, LoopBB, AfterBB); + Builder->CreateCondBr(EndCond, LoopBB, AfterBB); // Any new code will be inserted in AfterBB. - Builder.SetInsertPoint(AfterBB); + Builder->SetInsertPoint(AfterBB); // Restore the unshadowed variable. if (OldVal) @@ -1150,13 +1157,13 @@ Value *ForExprAST::codegen() { NamedValues.erase(VarName); // for expr always returns 0.0. - return Constant::getNullValue(Type::getDoubleTy(TheContext)); + return Constant::getNullValue(Type::getDoubleTy(*TheContext)); } Value *VarExprAST::codegen() { std::vector OldBindings; - Function *TheFunction = Builder.GetInsertBlock()->getParent(); + Function *TheFunction = Builder->GetInsertBlock()->getParent(); // Register all variables and emit their initializer. for (unsigned i = 0, e = VarNames.size(); i != e; ++i) { @@ -1174,11 +1181,11 @@ Value *VarExprAST::codegen() { if (!InitVal) return nullptr; } else { // If not specified, use 0.0. - InitVal = ConstantFP::get(TheContext, APFloat(0.0)); + InitVal = ConstantFP::get(*TheContext, APFloat(0.0)); } AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); - Builder.CreateStore(InitVal, Alloca); + Builder->CreateStore(InitVal, Alloca); // Remember the old variable binding so that we can restore the binding when // we unrecurse. @@ -1205,9 +1212,9 @@ Value *VarExprAST::codegen() { Function *PrototypeAST::codegen() { // Make the function type: double(double,double) etc. - std::vector Doubles(Args.size(), Type::getDoubleTy(TheContext)); + std::vector Doubles(Args.size(), Type::getDoubleTy(*TheContext)); FunctionType *FT = - FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); + FunctionType::get(Type::getDoubleTy(*TheContext), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get()); @@ -1234,8 +1241,8 @@ Function *FunctionAST::codegen() { BinopPrecedence[P.getOperatorName()] = P.getBinaryPrecedence(); // Create a new basic block to start insertion into. - BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); - Builder.SetInsertPoint(BB); + BasicBlock *BB = BasicBlock::Create(*TheContext, "entry", TheFunction); + Builder->SetInsertPoint(BB); // Create a subprogram DIE for this function. DIFile *Unit = DBuilder->createFile(KSDbgInfo.TheCU->getFilename(), @@ -1271,10 +1278,10 @@ Function *FunctionAST::codegen() { DBuilder->insertDeclare(Alloca, D, DBuilder->createExpression(), DebugLoc::get(LineNo, 0, SP), - Builder.GetInsertBlock()); + Builder->GetInsertBlock()); // Store the initial value into the alloca. - Builder.CreateStore(&Arg, Alloca); + Builder->CreateStore(&Arg, Alloca); // Add arguments to variable symbol table. NamedValues[std::string(Arg.getName())] = Alloca; @@ -1284,7 +1291,7 @@ Function *FunctionAST::codegen() { if (Value *RetVal = Body->codegen()) { // Finish off the function. - Builder.CreateRet(RetVal); + Builder->CreateRet(RetVal); // Pop off the lexical block for the function. KSDbgInfo.LexicalBlocks.pop_back(); @@ -1314,8 +1321,11 @@ Function *FunctionAST::codegen() { static void InitializeModule() { // Open a new module. - TheModule = std::make_unique("my cool jit", TheContext); - TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout()); + TheContext = std::make_unique(); + TheModule = std::make_unique("my cool jit", *TheContext); + TheModule->setDataLayout(TheJIT->getDataLayout()); + + Builder = std::make_unique>(*TheContext); } static void HandleDefinition() { @@ -1416,7 +1426,7 @@ int main() { // Prime the first token. getNextToken(); - TheJIT = std::make_unique(); + TheJIT = ExitOnErr(KaleidoscopeJIT::Create()); InitializeModule(); diff --git a/llvm/examples/Kaleidoscope/include/KaleidoscopeJIT.h b/llvm/examples/Kaleidoscope/include/KaleidoscopeJIT.h index 86fdc1e..9b35456a 100644 --- a/llvm/examples/Kaleidoscope/include/KaleidoscopeJIT.h +++ b/llvm/examples/Kaleidoscope/include/KaleidoscopeJIT.h @@ -13,126 +13,87 @@ #ifndef LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H #define LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/CompileUtils.h" +#include "llvm/ExecutionEngine/Orc/Core.h" +#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" -#include "llvm/ExecutionEngine/Orc/LambdaResolver.h" +#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" -#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" +#include "llvm/ExecutionEngine/Orc/TargetProcessControl.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 "llvm/IR/LLVMContext.h" #include -#include -#include namespace llvm { namespace orc { class KaleidoscopeJIT { -public: - using ObjLayerT = LegacyRTDyldObjectLinkingLayer; - using CompileLayerT = LegacyIRCompileLayer; - - KaleidoscopeJIT() - : Resolver(createLegacyLookupResolver( - ES, - [this](StringRef Name) { - return findMangledSymbol(std::string(Name)); - }, - [](Error Err) { cantFail(std::move(Err), "lookupFlags failed"); })), - TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()), - ObjectLayer(AcknowledgeORCv1Deprecation, ES, - [this](VModuleKey) { - return ObjLayerT::Resources{ - std::make_shared(), Resolver}; - }), - CompileLayer(AcknowledgeORCv1Deprecation, ObjectLayer, - SimpleCompiler(*TM)) { - llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr); - } +private: + std::unique_ptr TPC; + std::unique_ptr ES; - TargetMachine &getTargetMachine() { return *TM; } + DataLayout DL; + MangleAndInterner Mangle; - VModuleKey addModule(std::unique_ptr M) { - auto K = ES.allocateVModule(); - cantFail(CompileLayer.addModule(K, std::move(M))); - ModuleKeys.push_back(K); - return K; - } + RTDyldObjectLinkingLayer ObjectLayer; + IRCompileLayer CompileLayer; - void removeModule(VModuleKey K) { - ModuleKeys.erase(find(ModuleKeys, K)); - cantFail(CompileLayer.removeModule(K)); + JITDylib &MainJD; + +public: + KaleidoscopeJIT(std::unique_ptr TPC, + std::unique_ptr ES, + JITTargetMachineBuilder JTMB, DataLayout DL) + : TPC(std::move(TPC)), ES(std::move(ES)), DL(std::move(DL)), + Mangle(*this->ES, this->DL), + ObjectLayer(*this->ES, + []() { return std::make_unique(); }), + CompileLayer(*this->ES, ObjectLayer, + std::make_unique(std::move(JTMB))), + MainJD(this->ES->createBareJITDylib("
")) { + MainJD.addGenerator( + cantFail(DynamicLibrarySearchGenerator::GetForCurrentProcess( + DL.getGlobalPrefix()))); } - JITSymbol findSymbol(const std::string Name) { - return findMangledSymbol(mangle(Name)); + ~KaleidoscopeJIT() { + if (auto Err = ES->endSession()) + ES->reportError(std::move(Err)); } -private: - std::string mangle(const std::string &Name) { - std::string MangledName; - { - raw_string_ostream MangledNameStream(MangledName); - Mangler::getNameWithPrefix(MangledNameStream, Name, DL); - } - return MangledName; + static Expected> Create() { + auto TPC = SelfTargetProcessControl::Create(); + if (!TPC) + return TPC.takeError(); + + auto ES = std::make_unique(); + + JITTargetMachineBuilder JTMB((*TPC)->getTargetTriple()); + + auto DL = JTMB.getDefaultDataLayoutForTarget(); + if (!DL) + return DL.takeError(); + + return std::make_unique(std::move(*TPC), std::move(ES), + std::move(JTMB), std::move(*DL)); } - JITSymbol findMangledSymbol(const std::string &Name) { -#ifdef _WIN32 - // The symbol lookup of ObjectLinkingLayer uses the SymbolRef::SF_Exported - // flag to decide whether a symbol will be visible or not, when we call - // IRCompileLayer::findSymbolIn with ExportedSymbolsOnly set to true. - // - // But for Windows COFF objects, this flag is currently never set. - // For a potential solution see: https://reviews.llvm.org/rL258665 - // For now, we allow non-exported symbols on Windows as a workaround. - const bool ExportedSymbolsOnly = false; -#else - const bool ExportedSymbolsOnly = true; -#endif - - // Search modules in reverse order: from last added to first added. - // This is the opposite of the usual search order for dlsym, but makes more - // sense in a REPL where we want to bind to the newest available definition. - for (auto H : make_range(ModuleKeys.rbegin(), ModuleKeys.rend())) - if (auto Sym = CompileLayer.findSymbolIn(H, Name, ExportedSymbolsOnly)) - return Sym; - - // If we can't find the symbol in the JIT, try looking in the host process. - if (auto SymAddr = RTDyldMemoryManager::getSymbolAddressInProcess(Name)) - return JITSymbol(SymAddr, JITSymbolFlags::Exported); - -#ifdef _WIN32 - // For Windows retry without "_" at beginning, as RTDyldMemoryManager uses - // GetProcAddress and standard libraries like msvcrt.dll use names - // with and without "_" (for example "_itoa" but "sin"). - if (Name.length() > 2 && Name[0] == '_') - if (auto SymAddr = - RTDyldMemoryManager::getSymbolAddressInProcess(Name.substr(1))) - return JITSymbol(SymAddr, JITSymbolFlags::Exported); -#endif - - return nullptr; + const DataLayout &getDataLayout() const { return DL; } + + JITDylib &getMainJITDylib() { return MainJD; } + + Error addModule(ThreadSafeModule TSM, ResourceTrackerSP RT = nullptr) { + if (!RT) + RT = MainJD.getDefaultResourceTracker(); + return CompileLayer.add(RT, std::move(TSM)); } - ExecutionSession ES; - std::shared_ptr Resolver; - std::unique_ptr TM; - const DataLayout DL; - ObjLayerT ObjectLayer; - CompileLayerT CompileLayer; - std::vector ModuleKeys; + Expected lookup(StringRef Name) { + return ES->lookup({&MainJD}, Mangle(Name.str())); + } }; } // end namespace orc diff --git a/llvm/include/llvm/ExecutionEngine/Orc/TPCIndirectionUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/TPCIndirectionUtils.h index 90097f1..e7abd7f 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/TPCIndirectionUtils.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/TPCIndirectionUtils.h @@ -157,6 +157,19 @@ private: std::vector> IndirectStubAllocs; }; +/// This will call writeResolver on the given TPCIndirectionUtils instance +/// to set up re-entry via a function that will directly return the trampoline +/// landing address. +/// +/// The TPCIndirectionUtils' LazyCallThroughManager must have been previously +/// created via TPCIndirectionUtils::createLazyCallThroughManager. +/// +/// The TPCIndirectionUtils' writeResolver method must not have been previously +/// called. +/// +/// This function is experimental and likely subject to revision. +Error setUpInProcessLCTMReentryViaTPCIU(TPCIndirectionUtils &TPCIU); + namespace detail { template diff --git a/llvm/lib/ExecutionEngine/Orc/TPCIndirectionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/TPCIndirectionUtils.cpp index 85dc4be..de13f06 100644 --- a/llvm/lib/ExecutionEngine/Orc/TPCIndirectionUtils.cpp +++ b/llvm/lib/ExecutionEngine/Orc/TPCIndirectionUtils.cpp @@ -11,6 +11,8 @@ #include "llvm/ExecutionEngine/Orc/TargetProcessControl.h" #include "llvm/Support/MathExtras.h" +#include + using namespace llvm; using namespace llvm::orc; @@ -398,5 +400,24 @@ TPCIndirectionUtils::getIndirectStubs(unsigned NumStubs) { return std::move(Result); } +static JITTargetAddress reentry(JITTargetAddress LCTMAddr, + JITTargetAddress TrampolineAddr) { + auto &LCTM = *jitTargetAddressToPointer(LCTMAddr); + std::promise LandingAddrP; + auto LandingAddrF = LandingAddrP.get_future(); + LCTM.resolveTrampolineLandingAddress( + TrampolineAddr, + [&](JITTargetAddress Addr) { LandingAddrP.set_value(Addr); }); + return LandingAddrF.get(); +} + +Error setUpInProcessLCTMReentryViaTPCIU(TPCIndirectionUtils &TPCIU) { + auto &LCTM = TPCIU.getLazyCallThroughManager(); + return TPCIU + .writeResolverBlock(pointerToJITTargetAddress(&reentry), + pointerToJITTargetAddress(&LCTM)) + .takeError(); +} + } // end namespace orc } // end namespace llvm -- 2.7.4