[llvm] ad92f16 - [ORC][examples] Update Kaleidoscope and BuildingAJIT tutorial series to OrcV2.
Lang Hames via llvm-commits
llvm-commits at lists.llvm.org
Sun Oct 18 21:23:00 PDT 2020
Author: Lang Hames
Date: 2020-10-18T21:03:04-07:00
New Revision: ad92f16ccc5f87625bfea2823cd79700bea52c54
URL: https://github.com/llvm/llvm-project/commit/ad92f16ccc5f87625bfea2823cd79700bea52c54
DIFF: https://github.com/llvm/llvm-project/commit/ad92f16ccc5f87625bfea2823cd79700bea52c54.diff
LOG: [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.
Added:
Modified:
llvm/docs/tutorial/BuildingAJIT4.rst
llvm/examples/Kaleidoscope/BuildingAJIT/CMakeLists.txt
llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h
llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/toy.cpp
llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h
llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/toy.cpp
llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h
llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/toy.cpp
llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h
llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/toy.cpp
llvm/examples/Kaleidoscope/Chapter3/toy.cpp
llvm/examples/Kaleidoscope/Chapter4/toy.cpp
llvm/examples/Kaleidoscope/Chapter5/toy.cpp
llvm/examples/Kaleidoscope/Chapter6/toy.cpp
llvm/examples/Kaleidoscope/Chapter7/toy.cpp
llvm/examples/Kaleidoscope/Chapter8/toy.cpp
llvm/examples/Kaleidoscope/Chapter9/toy.cpp
llvm/examples/Kaleidoscope/include/KaleidoscopeJIT.h
llvm/include/llvm/ExecutionEngine/Orc/TPCIndirectionUtils.h
llvm/lib/ExecutionEngine/Orc/TPCIndirectionUtils.cpp
Removed:
llvm/docs/tutorial/BuildingAJIT5.rst
llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/CMakeLists.txt
llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h
llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/RemoteJITUtils.h
llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/Server/CMakeLists.txt
llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/Server/server.cpp
llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/toy.cpp
################################################################################
diff --git a/llvm/docs/tutorial/BuildingAJIT4.rst b/llvm/docs/tutorial/BuildingAJIT4.rst
index 3d3f81e43858..6eb3d52ccb8a 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 <BuildingAJIT3.html>`_ 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 <BuildingAJIT3.html>`_ 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 0fda8610efbf..000000000000
--- 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
diff erent process. This can be a separate process on the same
-machine, a process on a
diff erent machine, or even a process on a
diff erent
-platform/architecture. The code builds on top of the lazy-AST-compiling JIT
-stack from `Chapter 4 <BuildingAJIT3.html>`_.
-
-**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 947b5a3a3271..dc516ab459ca 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 adb6be436660..9b35456a7041 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<TargetProcessControl> TPC;
+ std::unique_ptr<ExecutionSession> 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<TargetProcessControl> TPC,
+ std::unique_ptr<ExecutionSession> 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<SectionMemoryManager>(); }),
- CompileLayer(ES, ObjectLayer,
+ CompileLayer(*this->ES, ObjectLayer,
std::make_unique<ConcurrentIRCompiler>(std::move(JTMB))),
- DL(std::move(DL)), Mangle(ES, this->DL),
- Ctx(std::make_unique<LLVMContext>()),
- MainJD(ES.createBareJITDylib("<main>")) {
+ MainJD(this->ES->createBareJITDylib("<main>")) {
MainJD.addGenerator(
cantFail(DynamicLibrarySearchGenerator::GetForCurrentProcess(
DL.getGlobalPrefix())));
}
+ ~KaleidoscopeJIT() {
+ if (auto Err = ES->endSession())
+ ES->reportError(std::move(Err));
+ }
+
static Expected<std::unique_ptr<KaleidoscopeJIT>> Create() {
- auto JTMB = JITTargetMachineBuilder::detectHost();
+ auto TPC = SelfTargetProcessControl::Create();
+ if (!TPC)
+ return TPC.takeError();
+
+ auto ES = std::make_unique<ExecutionSession>();
- 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<KaleidoscopeJIT>(std::move(*JTMB), std::move(*DL));
+ return std::make_unique<KaleidoscopeJIT>(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<Module> 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<JITEvaluatedSymbol> 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 ad942d1e45e7..2a405aebf3f1 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<FunctionAST> ParseDefinition() {
}
/// toplevelexpr ::= expression
-static std::unique_ptr<FunctionAST> ParseTopLevelExpr(unsigned ExprCount) {
+static std::unique_ptr<FunctionAST> ParseTopLevelExpr() {
if (auto E = ParseExpression()) {
// Make an anonymous proto.
- auto Proto = std::make_unique<PrototypeAST>
- (("__anon_expr" + Twine(ExprCount)).str(), std::vector<std::string>());
+ auto Proto = std::make_unique<PrototypeAST>("__anon_expr",
+ std::vector<std::string>());
return std::make_unique<FunctionAST>(std::move(Proto), std::move(E));
}
return nullptr;
@@ -697,7 +697,7 @@ static std::unique_ptr<PrototypeAST> ParseExtern() {
//===----------------------------------------------------------------------===//
static std::unique_ptr<KaleidoscopeJIT> TheJIT;
-static LLVMContext *TheContext;
+static std::unique_ptr<LLVMContext> TheContext;
static std::unique_ptr<IRBuilder<>> Builder;
static std::unique_ptr<Module> TheModule;
static std::map<std::string, AllocaInst *> 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<LLVMContext>();
TheModule = std::make_unique<Module>("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 28649ffe4910..cc3700b71faa 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<TargetProcessControl> TPC;
+ std::unique_ptr<ExecutionSession> 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<TargetProcessControl> TPC,
+ std::unique_ptr<ExecutionSession> 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<SectionMemoryManager>(); }),
- CompileLayer(ES, ObjectLayer,
+ CompileLayer(*this->ES, ObjectLayer,
std::make_unique<ConcurrentIRCompiler>(std::move(JTMB))),
- OptimizeLayer(ES, CompileLayer, optimizeModule), DL(std::move(DL)),
- Mangle(ES, this->DL), Ctx(std::make_unique<LLVMContext>()),
- MainJD(ES.createBareJITDylib("<main>")) {
+ OptimizeLayer(*this->ES, CompileLayer, optimizeModule),
+ MainJD(this->ES->createBareJITDylib("<main>")) {
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<std::unique_ptr<KaleidoscopeJIT>> Create() {
- auto JTMB = JITTargetMachineBuilder::detectHost();
+ auto TPC = SelfTargetProcessControl::Create();
+ if (!TPC)
+ return TPC.takeError();
- if (!JTMB)
- return JTMB.takeError();
+ auto ES = std::make_unique<ExecutionSession>();
- auto DL = JTMB->getDefaultDataLayoutForTarget();
+ JITTargetMachineBuilder JTMB((*TPC)->getTargetTriple());
+
+ auto DL = JTMB.getDefaultDataLayoutForTarget();
if (!DL)
return DL.takeError();
- return std::make_unique<KaleidoscopeJIT>(std::move(*JTMB), std::move(*DL));
+ return std::make_unique<KaleidoscopeJIT>(std::move(*TPC), std::move(ES),
+ std::move(JTMB), std::move(*DL));
}
- Error addModule(std::unique_ptr<Module> 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<JITEvaluatedSymbol> 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 136ae9636c56..2a405aebf3f1 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<FunctionAST> ParseDefinition() {
}
/// toplevelexpr ::= expression
-static std::unique_ptr<FunctionAST> ParseTopLevelExpr(unsigned ExprCount) {
+static std::unique_ptr<FunctionAST> ParseTopLevelExpr() {
if (auto E = ParseExpression()) {
// Make an anonymous proto.
- auto Proto = std::make_unique<PrototypeAST>(
- ("__anon_expr" + Twine(ExprCount)).str(), std::vector<std::string>());
+ auto Proto = std::make_unique<PrototypeAST>("__anon_expr",
+ std::vector<std::string>());
return std::make_unique<FunctionAST>(std::move(Proto), std::move(E));
}
return nullptr;
@@ -697,7 +697,7 @@ static std::unique_ptr<PrototypeAST> ParseExtern() {
//===----------------------------------------------------------------------===//
static std::unique_ptr<KaleidoscopeJIT> TheJIT;
-static LLVMContext *TheContext;
+static std::unique_ptr<LLVMContext> TheContext;
static std::unique_ptr<IRBuilder<>> Builder;
static std::unique_ptr<Module> TheModule;
static std::map<std::string, AllocaInst *> 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<LLVMContext>();
TheModule = std::make_unique<Module>("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 34c4b9683572..810a4cd48e30 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 <algorithm>
-#include <map>
#include <memory>
-#include <set>
-#include <string>
-#include <vector>
namespace llvm {
namespace orc {
class KaleidoscopeJIT {
private:
- ExecutionSession ES;
- std::map<VModuleKey, std::shared_ptr<SymbolResolver>> Resolvers;
- std::unique_ptr<TargetMachine> TM;
- const DataLayout DL;
- LegacyRTDyldObjectLinkingLayer ObjectLayer;
- LegacyIRCompileLayer<decltype(ObjectLayer), SimpleCompiler> CompileLayer;
+ std::unique_ptr<TargetProcessControl> TPC;
+ std::unique_ptr<ExecutionSession> ES;
+ std::unique_ptr<TPCIndirectionUtils> TPCIU;
- using OptimizeFunction =
- std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>;
+ DataLayout DL;
+ MangleAndInterner Mangle;
- LegacyIRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer;
+ RTDyldObjectLinkingLayer ObjectLayer;
+ IRCompileLayer CompileLayer;
+ IRTransformLayer OptimizeLayer;
+ CompileOnDemandLayer CODLayer;
- std::unique_ptr<JITCompileCallbackManager> CompileCallbackManager;
- LegacyCompileOnDemandLayer<decltype(OptimizeLayer)> 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<SectionMemoryManager>(),
- Resolvers[K]};
- }),
- CompileLayer(AcknowledgeORCv1Deprecation, ObjectLayer,
- SimpleCompiler(*TM)),
- OptimizeLayer(AcknowledgeORCv1Deprecation, CompileLayer,
- [this](std::unique_ptr<Module> 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<SymbolResolver> R) {
- Resolvers[K] = std::move(R);
- },
- [](Function &F) { return std::set<Function *>({&F}); },
- *CompileCallbackManager,
- orc::createLocalIndirectStubsManagerBuilder(
- TM->getTargetTriple())) {
- llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
+ KaleidoscopeJIT(std::unique_ptr<TargetProcessControl> TPC,
+ std::unique_ptr<ExecutionSession> ES,
+ std::unique_ptr<TPCIndirectionUtils> 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<SectionMemoryManager>(); }),
+ CompileLayer(*this->ES, ObjectLayer,
+ std::make_unique<ConcurrentIRCompiler>(std::move(JTMB))),
+ OptimizeLayer(*this->ES, CompileLayer, optimizeModule),
+ CODLayer(*this->ES, OptimizeLayer,
+ this->TPCIU->getLazyCallThroughManager(),
+ [this] { return this->TPCIU->createIndirectStubsManager(); }),
+ MainJD(this->ES->createBareJITDylib("<main>")) {
+ 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<Module> 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<std::unique_ptr<KaleidoscopeJIT>> Create() {
+ auto TPC = SelfTargetProcessControl::Create();
+ if (!TPC)
+ return TPC.takeError();
+
+ auto ES = std::make_unique<ExecutionSession>();
+
+ 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<KaleidoscopeJIT>(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<JITEvaluatedSymbol> lookup(StringRef Name) {
+ return ES->lookup({&MainJD}, Mangle(Name.str()));
}
private:
- std::unique_ptr<Module> optimizeModule(std::unique_ptr<Module> M) {
- // Create a function pass manager.
- auto FPM = std::make_unique<legacy::FunctionPassManager>(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<ThreadSafeModule>
+ optimizeModule(ThreadSafeModule TSM, const MaterializationResponsibility &R) {
+ TSM.withModuleDo([](Module &M) {
+ // Create a function pass manager.
+ auto FPM = std::make_unique<legacy::FunctionPassManager>(&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 d082e510e291..2a405aebf3f1 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<FunctionAST> ParseTopLevelExpr() {
if (auto E = ParseExpression()) {
// Make an anonymous proto.
auto Proto = std::make_unique<PrototypeAST>("__anon_expr",
- std::vector<std::string>());
+ std::vector<std::string>());
return std::make_unique<FunctionAST>(std::move(Proto), std::move(E));
}
return nullptr;
@@ -696,12 +696,13 @@ static std::unique_ptr<PrototypeAST> ParseExtern() {
// Code Generation
//===----------------------------------------------------------------------===//
-static LLVMContext TheContext;
-static IRBuilder<> Builder(TheContext);
+static std::unique_ptr<KaleidoscopeJIT> TheJIT;
+static std::unique_ptr<LLVMContext> TheContext;
+static std::unique_ptr<IRBuilder<>> Builder;
static std::unique_ptr<Module> TheModule;
static std::map<std::string, AllocaInst *> NamedValues;
-static std::unique_ptr<KaleidoscopeJIT> TheJIT;
static std::map<std::string, std::unique_ptr<PrototypeAST>> 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<AllocaInst *> 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<Type *> Doubles(Args.size(), Type::getDoubleTy(TheContext));
+ std::vector<Type *> 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<Module>("my cool jit", TheContext);
- TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout());
+ // Open a new context and module.
+ TheContext = std::make_unique<LLVMContext>();
+ TheModule = std::make_unique<Module>("my cool jit", *TheContext);
+ TheModule->setDataLayout(TheJIT->getDataLayout());
+
+ // Create a new builder for the module.
+ Builder = std::make_unique<IRBuilder<>>(*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<KaleidoscopeJIT>();
-
+ 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 c87565737f2d..ba63e7cf9ca5 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 <algorithm>
-#include <cassert>
-#include <cstdlib>
-#include <map>
#include <memory>
-#include <string>
-#include <vector>
class PrototypeAST;
class ExprAST;
@@ -64,164 +56,191 @@ class FunctionAST {
/// 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<llvm::Module>
-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<SymbolResolver> Resolver;
- std::unique_ptr<TargetMachine> TM;
- const DataLayout DL;
- LegacyRTDyldObjectLinkingLayer ObjectLayer;
- LegacyIRCompileLayer<decltype(ObjectLayer), SimpleCompiler> CompileLayer;
+class KaleidoscopeASTLayer;
+class KaleidoscopeJIT;
+
+class KaleidoscopeASTMaterializationUnit : public MaterializationUnit {
+public:
+ KaleidoscopeASTMaterializationUnit(KaleidoscopeASTLayer &L,
+ std::unique_ptr<FunctionAST> F);
+
+ StringRef getName() const override {
+ return "KaleidoscopeASTMaterializationUnit";
+ }
- using OptimizeFunction =
- std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>;
+ void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
- LegacyIRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer;
+private:
+ void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {
+ llvm_unreachable("Kaleidoscope functions are not overridable");
+ }
- std::unique_ptr<JITCompileCallbackManager> CompileCallbackMgr;
- std::unique_ptr<IndirectStubsManager> IndirectStubsMgr;
+ KaleidoscopeASTLayer &L;
+ std::unique_ptr<FunctionAST> 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<SectionMemoryManager>(), Resolver};
- }),
- CompileLayer(AcknowledgeORCv1Deprecation, ObjectLayer,
- SimpleCompiler(*TM)),
- OptimizeLayer(AcknowledgeORCv1Deprecation, CompileLayer,
- [this](std::unique_ptr<Module> 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<FunctionAST> F) {
+ return RT->getJITDylib().define(
+ std::make_unique<KaleidoscopeASTMaterializationUnit>(*this,
+ std::move(F)),
+ RT);
}
- TargetMachine &getTargetMachine() { return *TM; }
+ void emit(std::unique_ptr<MaterializationResponsibility> MR,
+ std::unique_ptr<FunctionAST> F) {
+ BaseLayer.emit(std::move(MR), irgenAndTakeOwnership(*F, ""));
+ }
- VModuleKey addModule(std::unique_ptr<Module> 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<FunctionAST> 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<FunctionAST>(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<FunctionAST> F)
+ : MaterializationUnit(L.getInterface(*F), nullptr), L(L), F(std::move(F)) {}
+
+void KaleidoscopeASTMaterializationUnit::materialize(
+ std::unique_ptr<MaterializationResponsibility> R) {
+ L.emit(std::move(R), std::move(F));
+}
+
+class KaleidoscopeJIT {
+private:
+ std::unique_ptr<TargetProcessControl> TPC;
+ std::unique_ptr<ExecutionSession> ES;
+ std::unique_ptr<TPCIndirectionUtils> 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<TargetProcessControl> TPC,
+ std::unique_ptr<ExecutionSession> ES,
+ std::unique_ptr<TPCIndirectionUtils> 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<SectionMemoryManager>(); }),
+ CompileLayer(*this->ES, ObjectLayer,
+ std::make_unique<ConcurrentIRCompiler>(std::move(JTMB))),
+ OptimizeLayer(*this->ES, CompileLayer, optimizeModule),
+ ASTLayer(OptimizeLayer, this->DL),
+ MainJD(this->ES->createBareJITDylib("<main>")) {
+ 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<std::unique_ptr<KaleidoscopeJIT>> Create() {
+ auto TPC = SelfTargetProcessControl::Create();
+ if (!TPC)
+ return TPC.takeError();
+
+ auto ES = std::make_unique<ExecutionSession>();
+
+ 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<KaleidoscopeJIT>(std::move(*TPC), std::move(ES),
+ std::move(*TPCIU), std::move(JTMB),
+ std::move(*DL));
}
- std::unique_ptr<Module> optimizeModule(std::unique_ptr<Module> M) {
- // Create a function pass manager.
- auto FPM = std::make_unique<legacy::FunctionPassManager>(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<FunctionAST> F, ResourceTrackerSP RT = nullptr) {
+ if (!RT)
+ RT = MainJD.getDefaultResourceTracker();
+ return ASTLayer.add(RT, std::move(F));
+ }
+
+ Expected<JITEvaluatedSymbol> lookup(StringRef Name) {
+ return ES->lookup({&MainJD}, Mangle(Name.str()));
+ }
+
+private:
+ static Expected<ThreadSafeModule>
+ optimizeModule(ThreadSafeModule TSM, const MaterializationResponsibility &R) {
+ TSM.withModuleDo([](Module &M) {
+ // Create a function pass manager.
+ auto FPM = std::make_unique<legacy::FunctionPassManager>(&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 e39e8a94d037..dc6d9da87c7e 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<FunctionAST> ParseTopLevelExpr() {
if (auto E = ParseExpression()) {
// Make an anonymous proto.
auto Proto = std::make_unique<PrototypeAST>("__anon_expr",
- std::vector<std::string>());
+ std::vector<std::string>());
return std::make_unique<FunctionAST>(std::move(Proto), std::move(E));
}
return nullptr;
@@ -681,11 +679,11 @@ static std::unique_ptr<PrototypeAST> ParseExtern() {
// Code Generation
//===----------------------------------------------------------------------===//
-static LLVMContext TheContext;
-static IRBuilder<> Builder(TheContext);
+static std::unique_ptr<KaleidoscopeJIT> TheJIT;
+static std::unique_ptr<LLVMContext> TheContext;
+static std::unique_ptr<IRBuilder<>> Builder;
static std::unique_ptr<Module> TheModule;
static std::map<std::string, AllocaInst *> NamedValues;
-static std::unique_ptr<KaleidoscopeJIT> TheJIT;
static std::map<std::string, std::unique_ptr<PrototypeAST>> 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<AllocaInst *> 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<Type *> Doubles(Args.size(), Type::getDoubleTy(TheContext));
+ std::vector<Type *> 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<Module>("my cool jit", TheContext);
- TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout());
+ // Open a new context and module.
+ TheContext = std::make_unique<LLVMContext>();
+ TheModule = std::make_unique<Module>("my cool jit", *TheContext);
+ TheModule->setDataLayout(TheJIT->getDataLayout());
+
+ // Create a new builder for the module.
+ Builder = std::make_unique<IRBuilder<>>(*TheContext);
}
-std::unique_ptr<llvm::Module>
-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<PrototypeAST>(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<PrototypeAST>(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<KaleidoscopeJIT>();
-
+ 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 48d729966364..000000000000
--- 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 d22f893ac611..000000000000
--- 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 <algorithm>
-#include <cassert>
-#include <cstdlib>
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-class PrototypeAST;
-class ExprAST;
-
-/// FunctionAST - This class represents a function definition itself.
-class FunctionAST {
- std::unique_ptr<PrototypeAST> Proto;
- std::unique_ptr<ExprAST> Body;
-
-public:
- FunctionAST(std::unique_ptr<PrototypeAST> Proto,
- std::unique_ptr<ExprAST> 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<llvm::Module>
-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<SymbolResolver> Resolver;
- std::unique_ptr<TargetMachine> TM;
- const DataLayout DL;
- LegacyRTDyldObjectLinkingLayer ObjectLayer;
- LegacyIRCompileLayer<decltype(ObjectLayer), SimpleCompiler> CompileLayer;
-
- using OptimizeFunction =
- std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>;
-
- LegacyIRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer;
-
- JITCompileCallbackManager *CompileCallbackMgr;
- std::unique_ptr<IndirectStubsManager> 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<std::string, 0>())),
- 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<Module> 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<Module> 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<FunctionAST> 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<FunctionAST>(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<Module> optimizeModule(std::unique_ptr<Module> M) {
- // Create a function pass manager.
- auto FPM = std::make_unique<legacy::FunctionPassManager>(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 c7d15bb8dd97..000000000000
--- 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 <cassert>
-#include <cerrno>
-#include <system_error>
-
-#if !defined(_MSC_VER) && !defined(__MINGW32__)
-#include <unistd.h>
-#else
-#include <io.h>
-#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<ssize_t>(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<ssize_t>(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 c7252ae14c6a..000000000000
--- 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 e50a7ecf96bc..000000000000
--- 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 <cstdint>
-#include <cstdio>
-#include <cstring>
-#include <string>
-#include <netinet/in.h>
-#include <sys/socket.h>
-
-using namespace llvm;
-using namespace llvm::orc;
-
-// Command line argument for TCP port.
-cl::opt<uint32_t> Port("port",
- cl::desc("TCP port to listen on"),
- cl::init(20000));
-
-ExitOnError ExitOnErr;
-
-using MainFun = int (*)(int, const char*[]);
-
-template <typename NativePtrT>
-NativePtrT MakeNative(uint64_t P) {
- return reinterpret_cast<NativePtrT>(static_cast<uintptr_t>(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<sockaddr*>(&servAddr),
- sizeof(servAddr)) < 0) {
- errs() << "Error on binding.\n";
- return 1;
- }
- listen(sockfd, 1);
- int newsockfd = accept(sockfd, reinterpret_cast<sockaddr*>(&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<FDRPCChannel, OrcX86_64_SysV>;
-
- 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 b9819327f843..000000000000
--- 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 <algorithm>
-#include <cassert>
-#include <cctype>
-#include <cstdint>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <map>
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-
-using namespace llvm;
-using namespace llvm::orc;
-
-// Command line argument for TCP hostname.
-cl::opt<std::string> HostName("hostname",
- cl::desc("TCP hostname to connect to"),
- cl::init("localhost"));
-
-// Command line argument for TCP port.
-cl::opt<uint32_t> 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<ExprAST> Operand;
-
-public:
- UnaryExprAST(char Opcode, std::unique_ptr<ExprAST> 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<ExprAST> LHS, RHS;
-
-public:
- BinaryExprAST(char Op, std::unique_ptr<ExprAST> LHS,
- std::unique_ptr<ExprAST> 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<std::unique_ptr<ExprAST>> Args;
-
-public:
- CallExprAST(const std::string &Callee,
- std::vector<std::unique_ptr<ExprAST>> Args)
- : Callee(Callee), Args(std::move(Args)) {}
-
- Value *codegen() override;
-};
-
-/// IfExprAST - Expression class for if/then/else.
-class IfExprAST : public ExprAST {
- std::unique_ptr<ExprAST> Cond, Then, Else;
-
-public:
- IfExprAST(std::unique_ptr<ExprAST> Cond, std::unique_ptr<ExprAST> Then,
- std::unique_ptr<ExprAST> 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<ExprAST> Start, End, Step, Body;
-
-public:
- ForExprAST(const std::string &VarName, std::unique_ptr<ExprAST> Start,
- std::unique_ptr<ExprAST> End, std::unique_ptr<ExprAST> Step,
- std::unique_ptr<ExprAST> 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<std::pair<std::string, std::unique_ptr<ExprAST>>> VarNames;
- std::unique_ptr<ExprAST> Body;
-
-public:
- VarExprAST(
- std::vector<std::pair<std::string, std::unique_ptr<ExprAST>>> VarNames,
- std::unique_ptr<ExprAST> 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<std::string> Args;
- bool IsOperator;
- unsigned Precedence; // Precedence if a binary op.
-
-public:
- PrototypeAST(const std::string &Name, std::vector<std::string> 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<char, int> 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<ExprAST> LogError(const char *Str) {
- fprintf(stderr, "Error: %s\n", Str);
- return nullptr;
-}
-
-std::unique_ptr<PrototypeAST> LogErrorP(const char *Str) {
- LogError(Str);
- return nullptr;
-}
-
-static std::unique_ptr<ExprAST> ParseExpression();
-
-/// numberexpr ::= number
-static std::unique_ptr<ExprAST> ParseNumberExpr() {
- auto Result = std::make_unique<NumberExprAST>(NumVal);
- getNextToken(); // consume the number
- return std::move(Result);
-}
-
-/// parenexpr ::= '(' expression ')'
-static std::unique_ptr<ExprAST> 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<ExprAST> ParseIdentifierExpr() {
- std::string IdName = IdentifierStr;
-
- getNextToken(); // eat identifier.
-
- if (CurTok != '(') // Simple variable ref.
- return std::make_unique<VariableExprAST>(IdName);
-
- // Call.
- getNextToken(); // eat (
- std::vector<std::unique_ptr<ExprAST>> 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<CallExprAST>(IdName, std::move(Args));
-}
-
-/// ifexpr ::= 'if' expression 'then' expression 'else' expression
-static std::unique_ptr<ExprAST> 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<IfExprAST>(std::move(Cond), std::move(Then),
- std::move(Else));
-}
-
-/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression
-static std::unique_ptr<ExprAST> 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<ExprAST> 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<ForExprAST>(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<ExprAST> ParseVarExpr() {
- getNextToken(); // eat the var.
-
- std::vector<std::pair<std::string, std::unique_ptr<ExprAST>>> 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<ExprAST> 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<VarExprAST>(std::move(VarNames), std::move(Body));
-}
-
-/// primary
-/// ::= identifierexpr
-/// ::= numberexpr
-/// ::= parenexpr
-/// ::= ifexpr
-/// ::= forexpr
-/// ::= varexpr
-static std::unique_ptr<ExprAST> 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<ExprAST> 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<UnaryExprAST>(Opc, std::move(Operand));
- return nullptr;
-}
-
-/// binoprhs
-/// ::= ('+' unary)*
-static std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec,
- std::unique_ptr<ExprAST> 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<BinaryExprAST>(BinOp, std::move(LHS), std::move(RHS));
- }
-}
-
-/// expression
-/// ::= unary binoprhs
-///
-static std::unique_ptr<ExprAST> 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<PrototypeAST> 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<std::string> 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<PrototypeAST>(FnName, ArgNames, Kind != 0,
- BinaryPrecedence);
-}
-
-/// definition ::= 'def' prototype expression
-static std::unique_ptr<FunctionAST> ParseDefinition() {
- getNextToken(); // eat def.
- auto Proto = ParsePrototype();
- if (!Proto)
- return nullptr;
-
- if (auto E = ParseExpression())
- return std::make_unique<FunctionAST>(std::move(Proto), std::move(E));
- return nullptr;
-}
-
-/// toplevelexpr ::= expression
-static std::unique_ptr<FunctionAST> ParseTopLevelExpr() {
- if (auto E = ParseExpression()) {
-
- auto PEArgs = std::vector<std::unique_ptr<ExprAST>>();
- PEArgs.push_back(std::move(E));
- auto PrintExpr =
- std::make_unique<CallExprAST>("printExprResult", std::move(PEArgs));
-
- // Make an anonymous proto.
- auto Proto = std::make_unique<PrototypeAST>("__anon_expr",
- std::vector<std::string>());
- return std::make_unique<FunctionAST>(std::move(Proto),
- std::move(PrintExpr));
- }
- return nullptr;
-}
-
-/// external ::= 'extern' prototype
-static std::unique_ptr<PrototypeAST> ParseExtern() {
- getNextToken(); // eat extern.
- return ParsePrototype();
-}
-
-//===----------------------------------------------------------------------===//
-// Code Generation
-//===----------------------------------------------------------------------===//
-
-static LLVMContext TheContext;
-static IRBuilder<> Builder(TheContext);
-static std::unique_ptr<Module> TheModule;
-static std::map<std::string, AllocaInst *> NamedValues;
-static std::unique_ptr<KaleidoscopeJIT> TheJIT;
-static std::map<std::string, std::unique_ptr<PrototypeAST>> 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<VariableExprAST *>(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<Value *> 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<AllocaInst *> 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<Type *> 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<Module>("my cool jit", TheContext);
- TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout());
-}
-
-std::unique_ptr<llvm::Module>
-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<PrototypeAST>(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<PrototypeAST>(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<FDRPCChannel> 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<sockaddr*>(&servAddr),
- sizeof(servAddr)) < 0) {
- errs() << "Failure to connect.\n";
- exit(1);
- }
-
- return std::make_unique<FDRPCChannel>(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<KaleidoscopeJIT>(ES, *Remote);
-
- // Automatically inject a definition for 'printExprResult'.
- FunctionProtos["printExprResult"] =
- std::make_unique<PrototypeAST>("printExprResult",
- std::vector<std::string>({"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 557780df7b37..61adfbc6af3b 100644
--- a/llvm/examples/Kaleidoscope/Chapter3/toy.cpp
+++ b/llvm/examples/Kaleidoscope/Chapter3/toy.cpp
@@ -399,9 +399,9 @@ static std::unique_ptr<PrototypeAST> ParseExtern() {
// Code Generation
//===----------------------------------------------------------------------===//
-static LLVMContext TheContext;
-static IRBuilder<> Builder(TheContext);
+static std::unique_ptr<LLVMContext> TheContext;
static std::unique_ptr<Module> TheModule;
+static std::unique_ptr<IRBuilder<>> Builder;
static std::map<std::string, Value *> 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<Type *> Doubles(Args.size(), Type::getDoubleTy(TheContext));
+ std::vector<Type *> 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<LLVMContext>();
+ TheModule = std::make_unique<Module>("my cool jit", *TheContext);
+
+ // Create a new builder for the module.
+ Builder = std::make_unique<IRBuilder<>>(*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<Module>("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 f9321f8ea98a..20aec1a35201 100644
--- a/llvm/examples/Kaleidoscope/Chapter4/toy.cpp
+++ b/llvm/examples/Kaleidoscope/Chapter4/toy.cpp
@@ -409,13 +409,14 @@ static std::unique_ptr<PrototypeAST> ParseExtern() {
// Code Generation
//===----------------------------------------------------------------------===//
-static LLVMContext TheContext;
-static IRBuilder<> Builder(TheContext);
+static std::unique_ptr<LLVMContext> TheContext;
static std::unique_ptr<Module> TheModule;
+static std::unique_ptr<IRBuilder<>> Builder;
static std::map<std::string, Value *> NamedValues;
static std::unique_ptr<legacy::FunctionPassManager> TheFPM;
static std::unique_ptr<KaleidoscopeJIT> TheJIT;
static std::map<std::string, std::unique_ptr<PrototypeAST>> 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<Type *> Doubles(Args.size(), Type::getDoubleTy(TheContext));
+ std::vector<Type *> 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<Module>("my cool jit", TheContext);
- TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout());
+ // Open a new context and module.
+ TheContext = std::make_unique<LLVMContext>();
+ TheModule = std::make_unique<Module>("my cool jit", *TheContext);
+ TheModule->setDataLayout(TheJIT->getDataLayout());
+
+ // Create a new builder for the module.
+ Builder = std::make_unique<IRBuilder<>>(*TheContext);
// Create a new pass manager attached to it.
TheFPM = std::make_unique<legacy::FunctionPassManager>(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<KaleidoscopeJIT>();
+ TheJIT = ExitOnErr(KaleidoscopeJIT::Create());
InitializeModuleAndPassManager();
diff --git a/llvm/examples/Kaleidoscope/Chapter5/toy.cpp b/llvm/examples/Kaleidoscope/Chapter5/toy.cpp
index 22bec97b312a..0790407b73b6 100644
--- a/llvm/examples/Kaleidoscope/Chapter5/toy.cpp
+++ b/llvm/examples/Kaleidoscope/Chapter5/toy.cpp
@@ -536,13 +536,14 @@ static std::unique_ptr<PrototypeAST> ParseExtern() {
// Code Generation
//===----------------------------------------------------------------------===//
-static LLVMContext TheContext;
-static IRBuilder<> Builder(TheContext);
+static std::unique_ptr<LLVMContext> TheContext;
static std::unique_ptr<Module> TheModule;
+static std::unique_ptr<IRBuilder<>> Builder;
static std::map<std::string, Value *> NamedValues;
static std::unique_ptr<legacy::FunctionPassManager> TheFPM;
static std::unique_ptr<KaleidoscopeJIT> TheJIT;
static std::map<std::string, std::unique_ptr<PrototypeAST>> 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<Type *> Doubles(Args.size(), Type::getDoubleTy(TheContext));
+ std::vector<Type *> 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<Module>("my cool jit", TheContext);
- TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout());
+ TheContext = std::make_unique<LLVMContext>();
+ TheModule = std::make_unique<Module>("my cool jit", *TheContext);
+ TheModule->setDataLayout(TheJIT->getDataLayout());
+
+ // Create a new builder for the module.
+ Builder = std::make_unique<IRBuilder<>>(*TheContext);
// Create a new pass manager attached to it.
TheFPM = std::make_unique<legacy::FunctionPassManager>(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<KaleidoscopeJIT>();
+ TheJIT = ExitOnErr(KaleidoscopeJIT::Create());
InitializeModuleAndPassManager();
diff --git a/llvm/examples/Kaleidoscope/Chapter6/toy.cpp b/llvm/examples/Kaleidoscope/Chapter6/toy.cpp
index 2a7dedc510ac..2538221538ac 100644
--- a/llvm/examples/Kaleidoscope/Chapter6/toy.cpp
+++ b/llvm/examples/Kaleidoscope/Chapter6/toy.cpp
@@ -628,13 +628,14 @@ static std::unique_ptr<PrototypeAST> ParseExtern() {
// Code Generation
//===----------------------------------------------------------------------===//
-static LLVMContext TheContext;
-static IRBuilder<> Builder(TheContext);
+static std::unique_ptr<LLVMContext> TheContext;
static std::unique_ptr<Module> TheModule;
+static std::unique_ptr<IRBuilder<>> Builder;
static std::map<std::string, Value *> NamedValues;
static std::unique_ptr<legacy::FunctionPassManager> TheFPM;
static std::unique_ptr<KaleidoscopeJIT> TheJIT;
static std::map<std::string, std::unique_ptr<PrototypeAST>> 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<Type *> Doubles(Args.size(), Type::getDoubleTy(TheContext));
+ std::vector<Type *> 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<Module>("my cool jit", TheContext);
- TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout());
+ TheContext = std::make_unique<LLVMContext>();
+ TheModule = std::make_unique<Module>("my cool jit", *TheContext);
+ TheModule->setDataLayout(TheJIT->getDataLayout());
+
+ // Create a new builder for the module.
+ Builder = std::make_unique<IRBuilder<>>(*TheContext);
// Create a new pass manager attached to it.
TheFPM = std::make_unique<legacy::FunctionPassManager>(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<KaleidoscopeJIT>();
+ TheJIT = ExitOnErr(KaleidoscopeJIT::Create());
InitializeModuleAndPassManager();
diff --git a/llvm/examples/Kaleidoscope/Chapter7/toy.cpp b/llvm/examples/Kaleidoscope/Chapter7/toy.cpp
index 317b602765e0..f2d4cbb80486 100644
--- a/llvm/examples/Kaleidoscope/Chapter7/toy.cpp
+++ b/llvm/examples/Kaleidoscope/Chapter7/toy.cpp
@@ -701,13 +701,14 @@ static std::unique_ptr<PrototypeAST> ParseExtern() {
// Code Generation
//===----------------------------------------------------------------------===//
-static LLVMContext TheContext;
-static IRBuilder<> Builder(TheContext);
+static std::unique_ptr<LLVMContext> TheContext;
static std::unique_ptr<Module> TheModule;
+static std::unique_ptr<IRBuilder<>> Builder;
static std::map<std::string, AllocaInst *> NamedValues;
static std::unique_ptr<legacy::FunctionPassManager> TheFPM;
static std::unique_ptr<KaleidoscopeJIT> TheJIT;
static std::map<std::string, std::unique_ptr<PrototypeAST>> 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<AllocaInst *> 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<Type *> Doubles(Args.size(), Type::getDoubleTy(TheContext));
+ std::vector<Type *> 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<Module>("my cool jit", TheContext);
- TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout());
+ TheContext = std::make_unique<LLVMContext>();
+ TheModule = std::make_unique<Module>("my cool jit", *TheContext);
+ TheModule->setDataLayout(TheJIT->getDataLayout());
+
+ // Create a new builder for the module.
+ Builder = std::make_unique<IRBuilder<>>(*TheContext);
// Create a new pass manager attached to it.
TheFPM = std::make_unique<legacy::FunctionPassManager>(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<KaleidoscopeJIT>();
+ TheJIT = ExitOnErr(KaleidoscopeJIT::Create());
InitializeModuleAndPassManager();
diff --git a/llvm/examples/Kaleidoscope/Chapter8/toy.cpp b/llvm/examples/Kaleidoscope/Chapter8/toy.cpp
index 92903741f210..a1fe89a9f844 100644
--- a/llvm/examples/Kaleidoscope/Chapter8/toy.cpp
+++ b/llvm/examples/Kaleidoscope/Chapter8/toy.cpp
@@ -702,11 +702,12 @@ static std::unique_ptr<PrototypeAST> ParseExtern() {
// Code Generation
//===----------------------------------------------------------------------===//
-static LLVMContext TheContext;
-static IRBuilder<> Builder(TheContext);
+static std::unique_ptr<LLVMContext> TheContext;
static std::unique_ptr<Module> TheModule;
+static std::unique_ptr<IRBuilder<>> Builder;
static std::map<std::string, AllocaInst *> NamedValues;
static std::map<std::string, std::unique_ptr<PrototypeAST>> 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<AllocaInst *> 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<Type *> Doubles(Args.size(), Type::getDoubleTy(TheContext));
+ std::vector<Type *> 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<Module>("my cool jit", TheContext);
+ TheContext = std::make_unique<LLVMContext>();
+ TheModule = std::make_unique<Module>("my cool jit", *TheContext);
+
+ // Create a new builder for the module.
+ Builder = std::make_unique<IRBuilder<>>(*TheContext);
}
static void HandleDefinition() {
diff --git a/llvm/examples/Kaleidoscope/Chapter9/toy.cpp b/llvm/examples/Kaleidoscope/Chapter9/toy.cpp
index 7b33dae6e13a..29a4ee14fc01 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;
@@ -814,6 +813,19 @@ static std::unique_ptr<PrototypeAST> ParseExtern() {
return ParsePrototype();
}
+//===----------------------------------------------------------------------===//
+// Code Generation Globals
+//===----------------------------------------------------------------------===//
+
+static std::unique_ptr<LLVMContext> TheContext;
+static std::unique_ptr<Module> TheModule;
+static std::unique_ptr<IRBuilder<>> Builder;
+static ExitOnError ExitOnErr;
+
+static std::map<std::string, AllocaInst *> NamedValues;
+static std::unique_ptr<KaleidoscopeJIT> TheJIT;
+static std::map<std::string, std::unique_ptr<PrototypeAST>> 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<Module> TheModule;
-static std::map<std::string, AllocaInst *> NamedValues;
-static std::unique_ptr<KaleidoscopeJIT> TheJIT;
-static std::map<std::string, std::unique_ptr<PrototypeAST>> 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<AllocaInst *> 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<Type *> Doubles(Args.size(), Type::getDoubleTy(TheContext));
+ std::vector<Type *> 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<Module>("my cool jit", TheContext);
- TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout());
+ TheContext = std::make_unique<LLVMContext>();
+ TheModule = std::make_unique<Module>("my cool jit", *TheContext);
+ TheModule->setDataLayout(TheJIT->getDataLayout());
+
+ Builder = std::make_unique<IRBuilder<>>(*TheContext);
}
static void HandleDefinition() {
@@ -1416,7 +1426,7 @@ int main() {
// Prime the first token.
getNextToken();
- TheJIT = std::make_unique<KaleidoscopeJIT>();
+ TheJIT = ExitOnErr(KaleidoscopeJIT::Create());
InitializeModule();
diff --git a/llvm/examples/Kaleidoscope/include/KaleidoscopeJIT.h b/llvm/examples/Kaleidoscope/include/KaleidoscopeJIT.h
index 86fdc1ed4fe9..9b35456a7041 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 <algorithm>
-#include <map>
+#include "llvm/IR/LLVMContext.h"
#include <memory>
-#include <string>
-#include <vector>
namespace llvm {
namespace orc {
class KaleidoscopeJIT {
-public:
- using ObjLayerT = LegacyRTDyldObjectLinkingLayer;
- using CompileLayerT = LegacyIRCompileLayer<ObjLayerT, SimpleCompiler>;
-
- 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<SectionMemoryManager>(), Resolver};
- }),
- CompileLayer(AcknowledgeORCv1Deprecation, ObjectLayer,
- SimpleCompiler(*TM)) {
- llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
- }
+private:
+ std::unique_ptr<TargetProcessControl> TPC;
+ std::unique_ptr<ExecutionSession> ES;
- TargetMachine &getTargetMachine() { return *TM; }
+ DataLayout DL;
+ MangleAndInterner Mangle;
- VModuleKey addModule(std::unique_ptr<Module> 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<TargetProcessControl> TPC,
+ std::unique_ptr<ExecutionSession> 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<SectionMemoryManager>(); }),
+ CompileLayer(*this->ES, ObjectLayer,
+ std::make_unique<ConcurrentIRCompiler>(std::move(JTMB))),
+ MainJD(this->ES->createBareJITDylib("<main>")) {
+ 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<std::unique_ptr<KaleidoscopeJIT>> Create() {
+ auto TPC = SelfTargetProcessControl::Create();
+ if (!TPC)
+ return TPC.takeError();
+
+ auto ES = std::make_unique<ExecutionSession>();
+
+ JITTargetMachineBuilder JTMB((*TPC)->getTargetTriple());
+
+ auto DL = JTMB.getDefaultDataLayoutForTarget();
+ if (!DL)
+ return DL.takeError();
+
+ return std::make_unique<KaleidoscopeJIT>(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<SymbolResolver> Resolver;
- std::unique_ptr<TargetMachine> TM;
- const DataLayout DL;
- ObjLayerT ObjectLayer;
- CompileLayerT CompileLayer;
- std::vector<VModuleKey> ModuleKeys;
+ Expected<JITEvaluatedSymbol> 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 90097f1131f3..e7abd7fb90df 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/TPCIndirectionUtils.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/TPCIndirectionUtils.h
@@ -157,6 +157,19 @@ class TPCIndirectionUtils {
std::vector<std::unique_ptr<Allocation>> 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 <typename ORCABI>
diff --git a/llvm/lib/ExecutionEngine/Orc/TPCIndirectionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/TPCIndirectionUtils.cpp
index 85dc4bec9a12..de13f064189a 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 <future>
+
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<LazyCallThroughManager *>(LCTMAddr);
+ std::promise<JITTargetAddress> 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
More information about the llvm-commits
mailing list