1
0
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:
Lang Hames 2020-09-22 22:37:25 -07:00
parent efc9f3486a
commit 18259b0a87
27 changed files with 1039 additions and 2762 deletions

View File

@ -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:**

View File

@ -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++

View File

@ -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()

View File

@ -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()));
}
};

View File

@ -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.

View File

@ -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:

View File

@ -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.

View File

@ -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);
}
};

View File

@ -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.

View File

@ -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);
}
};

View File

@ -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.

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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() {

View File

@ -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();

View File

@ -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

View File

@ -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>

View File

@ -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