mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 20:23:11 +01:00
[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.
This commit is contained in:
parent
efc9f3486a
commit
18259b0a87
@ -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:**
|
||||
|
@ -1,57 +0,0 @@
|
||||
=============================================================================
|
||||
Building a JIT: Remote-JITing -- Process Isolation and Laziness at a Distance
|
||||
=============================================================================
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
**This tutorial is under active development. It is incomplete and details may
|
||||
change frequently.** Nonetheless we invite you to try it out as it stands, and
|
||||
we welcome any feedback.
|
||||
|
||||
Chapter 5 Introduction
|
||||
======================
|
||||
|
||||
Welcome to Chapter 5 of the "Building an ORC-based JIT in LLVM" tutorial. This
|
||||
chapter introduces the ORC RemoteJIT Client/Server APIs and shows how to use
|
||||
them to build a JIT stack that will execute its code via a communications
|
||||
channel with a different process. This can be a separate process on the same
|
||||
machine, a process on a different machine, or even a process on a different
|
||||
platform/architecture. The code builds on top of the lazy-AST-compiling JIT
|
||||
stack from `Chapter 4 <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++
|
@ -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()
|
||||
|
@ -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();
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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()));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
std::unique_ptr<TargetProcessControl> TPC;
|
||||
std::unique_ptr<ExecutionSession> ES;
|
||||
|
||||
DataLayout DL;
|
||||
MangleAndInterner Mangle;
|
||||
|
||||
RTDyldObjectLinkingLayer ObjectLayer;
|
||||
IRCompileLayer CompileLayer;
|
||||
IRTransformLayer OptimizeLayer;
|
||||
|
||||
DataLayout DL;
|
||||
MangleAndInterner Mangle;
|
||||
ThreadSafeContext Ctx;
|
||||
|
||||
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:
|
||||
|
@ -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.
|
||||
|
@ -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())));
|
||||
}
|
||||
|
||||
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;
|
||||
~KaleidoscopeJIT() {
|
||||
if (auto Err = ES->endSession())
|
||||
ES->reportError(std::move(Err));
|
||||
if (auto Err = TPCIU->cleanup())
|
||||
ES->reportError(std::move(Err));
|
||||
}
|
||||
|
||||
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);
|
||||
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));
|
||||
}
|
||||
|
||||
void removeModule(VModuleKey K) {
|
||||
cantFail(CODLayer.removeModule(K));
|
||||
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()));
|
||||
}
|
||||
|
||||
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());
|
||||
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();
|
||||
// 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);
|
||||
// Run the optimizations over all functions in the module being added to
|
||||
// the JIT.
|
||||
for (auto &F : M)
|
||||
FPM->run(F);
|
||||
});
|
||||
|
||||
return M;
|
||||
return std::move(TSM);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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 @@ public:
|
||||
/// suffix (needed to prevent a name-clash with the function's stub),
|
||||
/// and then take ownership of the module that the function was compiled
|
||||
/// into.
|
||||
std::unique_ptr<llvm::Module>
|
||||
irgenAndTakeOwnership(FunctionAST &FnAST, const std::string &Suffix);
|
||||
llvm::orc::ThreadSafeModule irgenAndTakeOwnership(FunctionAST &FnAST,
|
||||
const std::string &Suffix);
|
||||
|
||||
namespace llvm {
|
||||
namespace orc {
|
||||
|
||||
class KaleidoscopeASTLayer;
|
||||
class KaleidoscopeJIT;
|
||||
|
||||
class KaleidoscopeASTMaterializationUnit : public MaterializationUnit {
|
||||
public:
|
||||
KaleidoscopeASTMaterializationUnit(KaleidoscopeASTLayer &L,
|
||||
std::unique_ptr<FunctionAST> F);
|
||||
|
||||
StringRef getName() const override {
|
||||
return "KaleidoscopeASTMaterializationUnit";
|
||||
}
|
||||
|
||||
void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
|
||||
|
||||
private:
|
||||
void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {
|
||||
llvm_unreachable("Kaleidoscope functions are not overridable");
|
||||
}
|
||||
|
||||
KaleidoscopeASTLayer &L;
|
||||
std::unique_ptr<FunctionAST> F;
|
||||
};
|
||||
|
||||
class KaleidoscopeASTLayer {
|
||||
public:
|
||||
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);
|
||||
}
|
||||
|
||||
void emit(std::unique_ptr<MaterializationResponsibility> MR,
|
||||
std::unique_ptr<FunctionAST> F) {
|
||||
BaseLayer.emit(std::move(MR), irgenAndTakeOwnership(*F, ""));
|
||||
}
|
||||
|
||||
SymbolFlagsMap getInterface(FunctionAST &F) {
|
||||
MangleAndInterner Mangle(BaseLayer.getExecutionSession(), DL);
|
||||
SymbolFlagsMap Symbols;
|
||||
Symbols[Mangle(F.getName())] =
|
||||
JITSymbolFlags(JITSymbolFlags::Exported | JITSymbolFlags::Callable);
|
||||
return Symbols;
|
||||
}
|
||||
|
||||
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:
|
||||
ExecutionSession ES;
|
||||
std::shared_ptr<SymbolResolver> Resolver;
|
||||
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;
|
||||
KaleidoscopeASTLayer ASTLayer;
|
||||
|
||||
std::unique_ptr<JITCompileCallbackManager> CompileCallbackMgr;
|
||||
std::unique_ptr<IndirectStubsManager> IndirectStubsMgr;
|
||||
JITDylib &MainJD;
|
||||
|
||||
static void handleLazyCallThroughError() {
|
||||
errs() << "LazyCallThrough error: Could not find function body";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
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);
|
||||
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())));
|
||||
}
|
||||
|
||||
TargetMachine &getTargetMachine() { return *TM; }
|
||||
|
||||
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;
|
||||
~KaleidoscopeJIT() {
|
||||
if (auto Err = ES->endSession())
|
||||
ES->reportError(std::move(Err));
|
||||
if (auto Err = TPCIU->cleanup())
|
||||
ES->reportError(std::move(Err));
|
||||
}
|
||||
|
||||
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));
|
||||
static Expected<std::unique_ptr<KaleidoscopeJIT>> Create() {
|
||||
auto TPC = SelfTargetProcessControl::Create();
|
||||
if (!TPC)
|
||||
return TPC.takeError();
|
||||
|
||||
// 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);
|
||||
}
|
||||
auto ES = std::make_unique<ExecutionSession>();
|
||||
|
||||
return SymAddr;
|
||||
};
|
||||
auto TPCIU = TPCIndirectionUtils::Create(**TPC);
|
||||
if (!TPCIU)
|
||||
return TPCIU.takeError();
|
||||
|
||||
// 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)));
|
||||
(*TPCIU)->createLazyCallThroughManager(
|
||||
*ES, pointerToJITTargetAddress(&handleLazyCallThroughError));
|
||||
|
||||
// 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;
|
||||
if (auto Err = setUpInProcessLCTMReentryViaTPCIU(**TPCIU))
|
||||
return std::move(Err);
|
||||
|
||||
return Error::success();
|
||||
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) {
|
||||
return OptimizeLayer.findSymbol(mangle(Name), 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(OptimizeLayer.removeModule(K));
|
||||
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:
|
||||
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<ThreadSafeModule>
|
||||
optimizeModule(ThreadSafeModule TSM, const MaterializationResponsibility &R) {
|
||||
TSM.withModuleDo([](Module &M) {
|
||||
// Create a function pass manager.
|
||||
auto FPM = std::make_unique<legacy::FunctionPassManager>(&M);
|
||||
|
||||
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();
|
||||
|
||||
// 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);
|
||||
});
|
||||
|
||||
// Run the optimizations over all functions in the module being added to
|
||||
// the JIT.
|
||||
for (auto &F : *M)
|
||||
FPM->run(F);
|
||||
|
||||
return M;
|
||||
return std::move(TSM);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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)
|
@ -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
|
@ -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
|
@ -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)
|
@ -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;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -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();
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
TargetMachine &getTargetMachine() { return *TM; }
|
||||
|
||||
VModuleKey addModule(std::unique_ptr<Module> M) {
|
||||
auto K = ES.allocateVModule();
|
||||
cantFail(CompileLayer.addModule(K, std::move(M)));
|
||||
ModuleKeys.push_back(K);
|
||||
return K;
|
||||
}
|
||||
|
||||
void removeModule(VModuleKey K) {
|
||||
ModuleKeys.erase(find(ModuleKeys, K));
|
||||
cantFail(CompileLayer.removeModule(K));
|
||||
}
|
||||
|
||||
JITSymbol findSymbol(const std::string Name) {
|
||||
return findMangledSymbol(mangle(Name));
|
||||
}
|
||||
|
||||
private:
|
||||
std::string mangle(const std::string &Name) {
|
||||
std::string MangledName;
|
||||
{
|
||||
raw_string_ostream MangledNameStream(MangledName);
|
||||
Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
|
||||
}
|
||||
return MangledName;
|
||||
std::unique_ptr<TargetProcessControl> TPC;
|
||||
std::unique_ptr<ExecutionSession> ES;
|
||||
|
||||
DataLayout DL;
|
||||
MangleAndInterner Mangle;
|
||||
|
||||
RTDyldObjectLinkingLayer ObjectLayer;
|
||||
IRCompileLayer CompileLayer;
|
||||
|
||||
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 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;
|
||||
~KaleidoscopeJIT() {
|
||||
if (auto Err = ES->endSession())
|
||||
ES->reportError(std::move(Err));
|
||||
}
|
||||
|
||||
ExecutionSession ES;
|
||||
std::shared_ptr<SymbolResolver> Resolver;
|
||||
std::unique_ptr<TargetMachine> TM;
|
||||
const DataLayout DL;
|
||||
ObjLayerT ObjectLayer;
|
||||
CompileLayerT CompileLayer;
|
||||
std::vector<VModuleKey> ModuleKeys;
|
||||
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));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
Expected<JITEvaluatedSymbol> lookup(StringRef Name) {
|
||||
return ES->lookup({&MainJD}, Mangle(Name.str()));
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace orc
|
||||
|
@ -157,6 +157,19 @@ private:
|
||||
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>
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user