Big Kaleidoscope tutorial update.
This commit switches the underlying JIT for the Kaleidoscope tutorials from
MCJIT to a custom ORC-based JIT, KaleidoscopeJIT. This fixes a lot of the bugs
in Kaleidoscope that were introduced when we deleted the legacy JIT. The
documentation for Chapter 4, which introduces the JIT APIs, is updated to
reflect the change.
Also included are a number of C++11 modernizations and general cleanup. Where
appropriate, the docs have been updated to reflect these changes too.
llvm-svn: 246002
diff --git a/llvm/examples/Kaleidoscope/Chapter2/toy.cpp b/llvm/examples/Kaleidoscope/Chapter2/toy.cpp
index 9ecf75d..14cba32 100644
--- a/llvm/examples/Kaleidoscope/Chapter2/toy.cpp
+++ b/llvm/examples/Kaleidoscope/Chapter2/toy.cpp
@@ -348,8 +348,8 @@
static std::unique_ptr<FunctionAST> ParseTopLevelExpr() {
if (auto E = ParseExpression()) {
// Make an anonymous proto.
- auto Proto =
- llvm::make_unique<PrototypeAST>("", std::vector<std::string>());
+ auto Proto = llvm::make_unique<PrototypeAST>("__anon_expr",
+ std::vector<std::string>());
return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E));
}
return nullptr;
diff --git a/llvm/examples/Kaleidoscope/Chapter3/toy.cpp b/llvm/examples/Kaleidoscope/Chapter3/toy.cpp
index cb4f75f..328189c 100644
--- a/llvm/examples/Kaleidoscope/Chapter3/toy.cpp
+++ b/llvm/examples/Kaleidoscope/Chapter3/toy.cpp
@@ -1,9 +1,8 @@
#include "llvm/ADT/STLExtras.h"
-#include "llvm/IR/Verifier.h"
-#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/Verifier.h"
#include <cctype>
#include <cstdio>
#include <map>
@@ -91,7 +90,7 @@
class ExprAST {
public:
virtual ~ExprAST() {}
- virtual Value *Codegen() = 0;
+ virtual Value *codegen() = 0;
};
/// NumberExprAST - Expression class for numeric literals like "1.0".
@@ -100,7 +99,7 @@
public:
NumberExprAST(double Val) : Val(Val) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// VariableExprAST - Expression class for referencing a variable, like "a".
@@ -109,7 +108,7 @@
public:
VariableExprAST(const std::string &Name) : Name(Name) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// BinaryExprAST - Expression class for a binary operator.
@@ -121,7 +120,7 @@
BinaryExprAST(char Op, std::unique_ptr<ExprAST> LHS,
std::unique_ptr<ExprAST> RHS)
: Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// CallExprAST - Expression class for function calls.
@@ -133,7 +132,7 @@
CallExprAST(const std::string &Callee,
std::vector<std::unique_ptr<ExprAST>> Args)
: Callee(Callee), Args(std::move(Args)) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// PrototypeAST - This class represents the "prototype" for a function,
@@ -146,7 +145,8 @@
public:
PrototypeAST(const std::string &Name, std::vector<std::string> Args)
: Name(Name), Args(std::move(Args)) {}
- Function *Codegen();
+ Function *codegen();
+ const std::string &getName() const { return Name; }
};
/// FunctionAST - This class represents a function definition itself.
@@ -158,7 +158,7 @@
FunctionAST(std::unique_ptr<PrototypeAST> Proto,
std::unique_ptr<ExprAST> Body)
: Proto(std::move(Proto)), Body(std::move(Body)) {}
- Function *Codegen();
+ Function *codegen();
};
} // end anonymous namespace
@@ -197,10 +197,6 @@
Error(Str);
return nullptr;
}
-std::unique_ptr<FunctionAST> ErrorF(const char *Str) {
- Error(Str);
- return nullptr;
-}
static std::unique_ptr<ExprAST> ParseExpression();
@@ -365,8 +361,8 @@
static std::unique_ptr<FunctionAST> ParseTopLevelExpr() {
if (auto E = ParseExpression()) {
// Make an anonymous proto.
- auto Proto =
- llvm::make_unique<PrototypeAST>("", std::vector<std::string>());
+ auto Proto = llvm::make_unique<PrototypeAST>("__anon_expr",
+ std::vector<std::string>());
return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E));
}
return nullptr;
@@ -382,20 +378,20 @@
// Code Generation
//===----------------------------------------------------------------------===//
+static std::unique_ptr<Module> TheModule;
+static IRBuilder<> Builder(getGlobalContext());
+static std::map<std::string, Value *> NamedValues;
+
Value *ErrorV(const char *Str) {
Error(Str);
return nullptr;
}
-static Module *TheModule;
-static IRBuilder<> Builder(getGlobalContext());
-static std::map<std::string, Value *> NamedValues;
-
-Value *NumberExprAST::Codegen() {
+Value *NumberExprAST::codegen() {
return ConstantFP::get(getGlobalContext(), APFloat(Val));
}
-Value *VariableExprAST::Codegen() {
+Value *VariableExprAST::codegen() {
// Look this variable up in the function.
Value *V = NamedValues[Name];
if (!V)
@@ -403,9 +399,9 @@
return V;
}
-Value *BinaryExprAST::Codegen() {
- Value *L = LHS->Codegen();
- Value *R = RHS->Codegen();
+Value *BinaryExprAST::codegen() {
+ Value *L = LHS->codegen();
+ Value *R = RHS->codegen();
if (!L || !R)
return nullptr;
@@ -426,7 +422,7 @@
}
}
-Value *CallExprAST::Codegen() {
+Value *CallExprAST::codegen() {
// Look up the name in the global module table.
Function *CalleeF = TheModule->getFunction(Callee);
if (!CalleeF)
@@ -438,7 +434,7 @@
std::vector<Value *> ArgsV;
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
- ArgsV.push_back(Args[i]->Codegen());
+ ArgsV.push_back(Args[i]->codegen());
if (!ArgsV.back())
return nullptr;
}
@@ -446,7 +442,7 @@
return Builder.CreateCall(CalleeF, ArgsV, "calltmp");
}
-Function *PrototypeAST::Codegen() {
+Function *PrototypeAST::codegen() {
// Make the function type: double(double,double) etc.
std::vector<Type *> Doubles(Args.size(),
Type::getDoubleTy(getGlobalContext()));
@@ -454,45 +450,23 @@
FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false);
Function *F =
- Function::Create(FT, Function::ExternalLinkage, Name, TheModule);
-
- // If F conflicted, there was already something named 'Name'. If it has a
- // body, don't allow redefinition or reextern.
- if (F->getName() != Name) {
- // Delete the one we just made and get the existing one.
- F->eraseFromParent();
- F = TheModule->getFunction(Name);
-
- // If F already has a body, reject this.
- if (!F->empty()) {
- ErrorF("redefinition of function");
- return nullptr;
- }
-
- // If F took a different number of args, reject.
- if (F->arg_size() != Args.size()) {
- ErrorF("redefinition of function with different # args");
- return nullptr;
- }
- }
+ Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get());
// Set names for all arguments.
unsigned Idx = 0;
- for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size();
- ++AI, ++Idx) {
- AI->setName(Args[Idx]);
-
- // Add arguments to variable symbol table.
- NamedValues[Args[Idx]] = AI;
- }
+ for (auto &Arg : F->args())
+ Arg.setName(Args[Idx++]);
return F;
}
-Function *FunctionAST::Codegen() {
- NamedValues.clear();
+Function *FunctionAST::codegen() {
+ // First, check for an existing function from a previous 'extern' declaration.
+ Function *TheFunction = TheModule->getFunction(Proto->getName());
- Function *TheFunction = Proto->Codegen();
+ if (!TheFunction)
+ TheFunction = Proto->codegen();
+
if (!TheFunction)
return nullptr;
@@ -500,7 +474,12 @@
BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
Builder.SetInsertPoint(BB);
- if (Value *RetVal = Body->Codegen()) {
+ // Record the function arguments in the NamedValues map.
+ NamedValues.clear();
+ for (auto &Arg : TheFunction->args())
+ NamedValues[Arg.getName()] = &Arg;
+
+ if (Value *RetVal = Body->codegen()) {
// Finish off the function.
Builder.CreateRet(RetVal);
@@ -521,7 +500,7 @@
static void HandleDefinition() {
if (auto FnAST = ParseDefinition()) {
- if (auto *FnIR = FnAST->Codegen()) {
+ if (auto *FnIR = FnAST->codegen()) {
fprintf(stderr, "Read function definition:");
FnIR->dump();
}
@@ -533,7 +512,7 @@
static void HandleExtern() {
if (auto ProtoAST = ParseExtern()) {
- if (auto *FnIR = ProtoAST->Codegen()) {
+ if (auto *FnIR = ProtoAST->codegen()) {
fprintf(stderr, "Read extern: ");
FnIR->dump();
}
@@ -546,7 +525,7 @@
static void HandleTopLevelExpression() {
// Evaluate a top-level expression into an anonymous function.
if (auto FnAST = ParseTopLevelExpr()) {
- if (auto *FnIR = FnAST->Codegen()) {
+ if (auto *FnIR = FnAST->codegen()) {
fprintf(stderr, "Read top-level expression:");
FnIR->dump();
}
@@ -584,8 +563,6 @@
//===----------------------------------------------------------------------===//
int main() {
- LLVMContext &Context = getGlobalContext();
-
// Install standard binary operators.
// 1 is lowest precedence.
BinopPrecedence['<'] = 10;
@@ -598,9 +575,7 @@
getNextToken();
// Make the module, which holds all the code.
- std::unique_ptr<Module> Owner =
- llvm::make_unique<Module>("my cool jit", Context);
- TheModule = Owner.get();
+ TheModule = llvm::make_unique<Module>("my cool jit", getGlobalContext());
// Run the main "interpreter loop" now.
MainLoop();
diff --git a/llvm/examples/Kaleidoscope/Chapter4/toy.cpp b/llvm/examples/Kaleidoscope/Chapter4/toy.cpp
index 9b0d2ec..12777ae 100644
--- a/llvm/examples/Kaleidoscope/Chapter4/toy.cpp
+++ b/llvm/examples/Kaleidoscope/Chapter4/toy.cpp
@@ -1,11 +1,6 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Analysis/BasicAliasAnalysis.h"
#include "llvm/Analysis/Passes.h"
-#include "llvm/ExecutionEngine/ExecutionEngine.h"
-#include "llvm/ExecutionEngine/MCJIT.h"
-#include "llvm/ExecutionEngine/SectionMemoryManager.h"
-#include "llvm/IR/DataLayout.h"
-#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LegacyPassManager.h"
@@ -18,7 +13,10 @@
#include <map>
#include <string>
#include <vector>
+#include "../include/KaleidoscopeJIT.h"
+
using namespace llvm;
+using namespace llvm::orc;
//===----------------------------------------------------------------------===//
// Lexer
@@ -100,7 +98,7 @@
class ExprAST {
public:
virtual ~ExprAST() {}
- virtual Value *Codegen() = 0;
+ virtual Value *codegen() = 0;
};
/// NumberExprAST - Expression class for numeric literals like "1.0".
@@ -109,7 +107,7 @@
public:
NumberExprAST(double Val) : Val(Val) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// VariableExprAST - Expression class for referencing a variable, like "a".
@@ -118,7 +116,7 @@
public:
VariableExprAST(const std::string &Name) : Name(Name) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// BinaryExprAST - Expression class for a binary operator.
@@ -130,7 +128,7 @@
BinaryExprAST(char Op, std::unique_ptr<ExprAST> LHS,
std::unique_ptr<ExprAST> RHS)
: Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// CallExprAST - Expression class for function calls.
@@ -142,7 +140,7 @@
CallExprAST(const std::string &Callee,
std::vector<std::unique_ptr<ExprAST>> Args)
: Callee(Callee), Args(std::move(Args)) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// PrototypeAST - This class represents the "prototype" for a function,
@@ -155,7 +153,8 @@
public:
PrototypeAST(const std::string &Name, std::vector<std::string> Args)
: Name(Name), Args(std::move(Args)) {}
- Function *Codegen();
+ Function *codegen();
+ const std::string &getName() const { return Name; }
};
/// FunctionAST - This class represents a function definition itself.
@@ -167,7 +166,7 @@
FunctionAST(std::unique_ptr<PrototypeAST> Proto,
std::unique_ptr<ExprAST> Body)
: Proto(std::move(Proto)), Body(std::move(Body)) {}
- Function *Codegen();
+ Function *codegen();
};
} // end anonymous namespace
@@ -206,10 +205,6 @@
Error(Str);
return nullptr;
}
-std::unique_ptr<FunctionAST> ErrorF(const char *Str) {
- Error(Str);
- return nullptr;
-}
static std::unique_ptr<ExprAST> ParseExpression();
@@ -374,8 +369,8 @@
static std::unique_ptr<FunctionAST> ParseTopLevelExpr() {
if (auto E = ParseExpression()) {
// Make an anonymous proto.
- auto Proto =
- llvm::make_unique<PrototypeAST>("", std::vector<std::string>());
+ auto Proto = llvm::make_unique<PrototypeAST>("__anon_expr",
+ std::vector<std::string>());
return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E));
}
return nullptr;
@@ -388,258 +383,41 @@
}
//===----------------------------------------------------------------------===//
-// Quick and dirty hack
-//===----------------------------------------------------------------------===//
-
-// FIXME: Obviously we can do better than this
-std::string GenerateUniqueName(const char *root) {
- static int i = 0;
- char s[16];
- sprintf(s, "%s%d", root, i++);
- std::string S = s;
- return S;
-}
-
-std::string MakeLegalFunctionName(std::string Name) {
- std::string NewName;
- if (!Name.length())
- return GenerateUniqueName("anon_func_");
-
- // Start with what we have
- NewName = Name;
-
- // Look for a numberic first character
- if (NewName.find_first_of("0123456789") == 0) {
- NewName.insert(0, 1, 'n');
- }
-
- // Replace illegal characters with their ASCII equivalent
- std::string legal_elements =
- "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
- size_t pos;
- while ((pos = NewName.find_first_not_of(legal_elements)) !=
- std::string::npos) {
- char old_c = NewName.at(pos);
- char new_str[16];
- sprintf(new_str, "%d", (int)old_c);
- NewName = NewName.replace(pos, 1, new_str);
- }
-
- return NewName;
-}
-
-//===----------------------------------------------------------------------===//
-// MCJIT helper class
-//===----------------------------------------------------------------------===//
-
-class MCJITHelper {
-public:
- MCJITHelper(LLVMContext &C) : Context(C), OpenModule(NULL) {}
- ~MCJITHelper();
-
- Function *getFunction(const std::string FnName);
- Module *getModuleForNewFunction();
- void *getPointerToFunction(Function *F);
- void *getSymbolAddress(const std::string &Name);
- void dump();
-
-private:
- typedef std::vector<Module *> ModuleVector;
- typedef std::vector<ExecutionEngine *> EngineVector;
-
- LLVMContext &Context;
- Module *OpenModule;
- ModuleVector Modules;
- EngineVector Engines;
-};
-
-class HelpingMemoryManager : public SectionMemoryManager {
- HelpingMemoryManager(const HelpingMemoryManager &) = delete;
- void operator=(const HelpingMemoryManager &) = delete;
-
-public:
- HelpingMemoryManager(MCJITHelper *Helper) : MasterHelper(Helper) {}
- ~HelpingMemoryManager() override {}
-
- /// This method returns the address of the specified symbol.
- /// Our implementation will attempt to find symbols in other
- /// modules associated with the MCJITHelper to cross link symbols
- /// from one generated module to another.
- uint64_t getSymbolAddress(const std::string &Name) override;
-
-private:
- MCJITHelper *MasterHelper;
-};
-
-uint64_t HelpingMemoryManager::getSymbolAddress(const std::string &Name) {
- uint64_t FnAddr = SectionMemoryManager::getSymbolAddress(Name);
- if (FnAddr)
- return FnAddr;
-
- uint64_t HelperFun = (uint64_t)MasterHelper->getSymbolAddress(Name);
- if (!HelperFun)
- report_fatal_error("Program used extern function '" + Name +
- "' which could not be resolved!");
-
- return HelperFun;
-}
-
-MCJITHelper::~MCJITHelper() {
- if (OpenModule)
- delete OpenModule;
- EngineVector::iterator begin = Engines.begin();
- EngineVector::iterator end = Engines.end();
- EngineVector::iterator it;
- for (it = begin; it != end; ++it)
- delete *it;
-}
-
-Function *MCJITHelper::getFunction(const std::string FnName) {
- ModuleVector::iterator begin = Modules.begin();
- ModuleVector::iterator end = Modules.end();
- ModuleVector::iterator it;
- for (it = begin; it != end; ++it) {
- Function *F = (*it)->getFunction(FnName);
- if (F) {
- if (*it == OpenModule)
- return F;
-
- assert(OpenModule != NULL);
-
- // This function is in a module that has already been JITed.
- // We need to generate a new prototype for external linkage.
- Function *PF = OpenModule->getFunction(FnName);
- if (PF && !PF->empty()) {
- ErrorF("redefinition of function across modules");
- return nullptr;
- }
-
- // If we don't have a prototype yet, create one.
- if (!PF)
- PF = Function::Create(F->getFunctionType(), Function::ExternalLinkage,
- FnName, OpenModule);
- return PF;
- }
- }
- return NULL;
-}
-
-Module *MCJITHelper::getModuleForNewFunction() {
- // If we have a Module that hasn't been JITed, use that.
- if (OpenModule)
- return OpenModule;
-
- // Otherwise create a new Module.
- std::string ModName = GenerateUniqueName("mcjit_module_");
- Module *M = new Module(ModName, Context);
- Modules.push_back(M);
- OpenModule = M;
- return M;
-}
-
-void *MCJITHelper::getPointerToFunction(Function *F) {
- // See if an existing instance of MCJIT has this function.
- EngineVector::iterator begin = Engines.begin();
- EngineVector::iterator end = Engines.end();
- EngineVector::iterator it;
- for (it = begin; it != end; ++it) {
- void *P = (*it)->getPointerToFunction(F);
- if (P)
- return P;
- }
-
- // If we didn't find the function, see if we can generate it.
- if (OpenModule) {
- std::string ErrStr;
- ExecutionEngine *NewEngine =
- EngineBuilder(std::unique_ptr<Module>(OpenModule))
- .setErrorStr(&ErrStr)
- .setMCJITMemoryManager(std::unique_ptr<HelpingMemoryManager>(
- new HelpingMemoryManager(this)))
- .create();
- if (!NewEngine) {
- fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str());
- exit(1);
- }
-
- // Create a function pass manager for this engine
- auto *FPM = new legacy::FunctionPassManager(OpenModule);
-
- // Set up the optimizer pipeline. Start with registering info about how the
- // target lays out data structures.
- OpenModule->setDataLayout(NewEngine->getDataLayout());
- // Provide basic AliasAnalysis support for GVN.
- FPM->add(createBasicAliasAnalysisPass());
- // Promote allocas to registers.
- FPM->add(createPromoteMemoryToRegisterPass());
- // Do simple "peephole" optimizations and bit-twiddling optzns.
- FPM->add(createInstructionCombiningPass());
- // Reassociate expressions.
- FPM->add(createReassociatePass());
- // Eliminate Common SubExpressions.
- FPM->add(createGVNPass());
- // Simplify the control flow graph (deleting unreachable blocks, etc).
- FPM->add(createCFGSimplificationPass());
- FPM->doInitialization();
-
- // For each function in the module
- Module::iterator it;
- Module::iterator end = OpenModule->end();
- for (it = OpenModule->begin(); it != end; ++it) {
- // Run the FPM on this function
- FPM->run(*it);
- }
-
- // We don't need this anymore
- delete FPM;
-
- OpenModule = NULL;
- Engines.push_back(NewEngine);
- NewEngine->finalizeObject();
- return NewEngine->getPointerToFunction(F);
- }
- return NULL;
-}
-
-void *MCJITHelper::getSymbolAddress(const std::string &Name) {
- // Look for the symbol in each of our execution engines.
- EngineVector::iterator begin = Engines.begin();
- EngineVector::iterator end = Engines.end();
- EngineVector::iterator it;
- for (it = begin; it != end; ++it) {
- uint64_t FAddr = (*it)->getFunctionAddress(Name);
- if (FAddr) {
- return (void *)FAddr;
- }
- }
- return NULL;
-}
-
-void MCJITHelper::dump() {
- ModuleVector::iterator begin = Modules.begin();
- ModuleVector::iterator end = Modules.end();
- ModuleVector::iterator it;
- for (it = begin; it != end; ++it)
- (*it)->dump();
-}
-//===----------------------------------------------------------------------===//
// Code Generation
//===----------------------------------------------------------------------===//
-static MCJITHelper *JITHelper;
+static std::unique_ptr<Module> TheModule;
static IRBuilder<> Builder(getGlobalContext());
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;
Value *ErrorV(const char *Str) {
Error(Str);
return nullptr;
}
-Value *NumberExprAST::Codegen() {
+Function *getFunction(std::string Name) {
+ // First, see if the function has already been added to the current module.
+ if (auto *F = TheModule->getFunction(Name))
+ return F;
+
+ // If not, check whether we can codegen the declaration from some existing
+ // prototype.
+ auto FI = FunctionProtos.find(Name);
+ if (FI != FunctionProtos.end())
+ return FI->second->codegen();
+
+ // If no existing prototype exists, return null.
+ return nullptr;
+}
+
+Value *NumberExprAST::codegen() {
return ConstantFP::get(getGlobalContext(), APFloat(Val));
}
-Value *VariableExprAST::Codegen() {
+Value *VariableExprAST::codegen() {
// Look this variable up in the function.
Value *V = NamedValues[Name];
if (!V)
@@ -647,9 +425,9 @@
return V;
}
-Value *BinaryExprAST::Codegen() {
- Value *L = LHS->Codegen();
- Value *R = RHS->Codegen();
+Value *BinaryExprAST::codegen() {
+ Value *L = LHS->codegen();
+ Value *R = RHS->codegen();
if (!L || !R)
return nullptr;
@@ -670,9 +448,9 @@
}
}
-Value *CallExprAST::Codegen() {
+Value *CallExprAST::codegen() {
// Look up the name in the global module table.
- Function *CalleeF = JITHelper->getFunction(Callee);
+ Function *CalleeF = getFunction(Callee);
if (!CalleeF)
return ErrorV("Unknown function referenced");
@@ -682,7 +460,7 @@
std::vector<Value *> ArgsV;
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
- ArgsV.push_back(Args[i]->Codegen());
+ ArgsV.push_back(Args[i]->codegen());
if (!ArgsV.back())
return nullptr;
}
@@ -690,55 +468,30 @@
return Builder.CreateCall(CalleeF, ArgsV, "calltmp");
}
-Function *PrototypeAST::Codegen() {
+Function *PrototypeAST::codegen() {
// Make the function type: double(double,double) etc.
std::vector<Type *> Doubles(Args.size(),
Type::getDoubleTy(getGlobalContext()));
FunctionType *FT =
FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false);
- std::string FnName = MakeLegalFunctionName(Name);
-
- Module *M = JITHelper->getModuleForNewFunction();
-
- Function *F = Function::Create(FT, Function::ExternalLinkage, FnName, M);
-
- // If F conflicted, there was already something named 'Name'. If it has a
- // body, don't allow redefinition or reextern.
- if (F->getName() != FnName) {
- // Delete the one we just made and get the existing one.
- F->eraseFromParent();
- F = JITHelper->getFunction(Name);
- // If F already has a body, reject this.
- if (!F->empty()) {
- ErrorF("redefinition of function");
- return nullptr;
- }
-
- // If F took a different number of args, reject.
- if (F->arg_size() != Args.size()) {
- ErrorF("redefinition of function with different # args");
- return nullptr;
- }
- }
+ Function *F =
+ Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get());
// Set names for all arguments.
unsigned Idx = 0;
- for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size();
- ++AI, ++Idx) {
- AI->setName(Args[Idx]);
-
- // Add arguments to variable symbol table.
- NamedValues[Args[Idx]] = AI;
- }
+ for (auto &Arg : F->args())
+ Arg.setName(Args[Idx++]);
return F;
}
-Function *FunctionAST::Codegen() {
- NamedValues.clear();
-
- Function *TheFunction = Proto->Codegen();
+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;
@@ -746,13 +499,21 @@
BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
Builder.SetInsertPoint(BB);
- if (Value *RetVal = Body->Codegen()) {
+ // Record the function arguments in the NamedValues map.
+ NamedValues.clear();
+ for (auto &Arg : TheFunction->args())
+ NamedValues[Arg.getName()] = &Arg;
+
+ if (Value *RetVal = Body->codegen()) {
// Finish off the function.
Builder.CreateRet(RetVal);
// Validate the generated code, checking for consistency.
verifyFunction(*TheFunction);
+ // Run the optimizer on the function.
+ TheFPM->run(*TheFunction);
+
return TheFunction;
}
@@ -765,11 +526,35 @@
// Top-Level parsing and JIT Driver
//===----------------------------------------------------------------------===//
+static void InitializeModuleAndPassManager() {
+ // Open a new module.
+ TheModule = llvm::make_unique<Module>("my cool jit", getGlobalContext());
+ TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout());
+
+ // Create a new pass manager attached to it.
+ TheFPM = llvm::make_unique<legacy::FunctionPassManager>(TheModule.get());
+
+ // Provide basic AliasAnalysis support for GVN.
+ TheFPM->add(createBasicAliasAnalysisPass());
+ // Do simple "peephole" optimizations and bit-twiddling optzns.
+ TheFPM->add(createInstructionCombiningPass());
+ // Reassociate expressions.
+ TheFPM->add(createReassociatePass());
+ // Eliminate Common SubExpressions.
+ TheFPM->add(createGVNPass());
+ // Simplify the control flow graph (deleting unreachable blocks, etc).
+ TheFPM->add(createCFGSimplificationPass());
+
+ TheFPM->doInitialization();
+}
+
static void HandleDefinition() {
if (auto FnAST = ParseDefinition()) {
- if (auto *FnIR = FnAST->Codegen()) {
+ if (auto *FnIR = FnAST->codegen()) {
fprintf(stderr, "Read function definition:");
FnIR->dump();
+ TheJIT->addModule(std::move(TheModule));
+ InitializeModuleAndPassManager();
}
} else {
// Skip token for error recovery.
@@ -779,9 +564,10 @@
static void HandleExtern() {
if (auto ProtoAST = ParseExtern()) {
- if (auto *FnIR = ProtoAST->Codegen()) {
+ if (auto *FnIR = ProtoAST->codegen()) {
fprintf(stderr, "Read extern: ");
FnIR->dump();
+ FunctionProtos[ProtoAST->getName()] = std::move(ProtoAST);
}
} else {
// Skip token for error recovery.
@@ -792,14 +578,24 @@
static void HandleTopLevelExpression() {
// Evaluate a top-level expression into an anonymous function.
if (auto FnAST = ParseTopLevelExpr()) {
- if (auto *FnIR = FnAST->Codegen()) {
- // JIT the function, returning a function pointer.
- void *FPtr = JITHelper->getPointerToFunction(FnIR);
+ if (FnAST->codegen()) {
- // 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)FPtr;
+ // JIT the module containing the anonymous expression, keeping a handle so
+ // we can free it later.
+ auto H = TheJIT->addModule(std::move(TheModule));
+ InitializeModuleAndPassManager();
+
+ // Search the JIT for the __anon_expr symbol.
+ auto ExprSymbol = TheJIT->findSymbol("__anon_expr");
+ assert(ExprSymbol && "Function not found");
+
+ // Get the symbol's address and cast it to the right type (takes no
+ // arguments, returns a double) so we can call it as a native function.
+ 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);
}
} else {
// Skip token for error recovery.
@@ -854,8 +650,6 @@
InitializeNativeTarget();
InitializeNativeTargetAsmPrinter();
InitializeNativeTargetAsmParser();
- LLVMContext &Context = getGlobalContext();
- JITHelper = new MCJITHelper(Context);
// Install standard binary operators.
// 1 is lowest precedence.
@@ -868,11 +662,12 @@
fprintf(stderr, "ready> ");
getNextToken();
+ TheJIT = llvm::make_unique<KaleidoscopeJIT>();
+
+ InitializeModuleAndPassManager();
+
// Run the main "interpreter loop" now.
MainLoop();
- // Print out all of the generated code.
- JITHelper->dump();
-
return 0;
}
diff --git a/llvm/examples/Kaleidoscope/Chapter5/toy.cpp b/llvm/examples/Kaleidoscope/Chapter5/toy.cpp
index da7a81c..83af177 100644
--- a/llvm/examples/Kaleidoscope/Chapter5/toy.cpp
+++ b/llvm/examples/Kaleidoscope/Chapter5/toy.cpp
@@ -1,11 +1,6 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Analysis/BasicAliasAnalysis.h"
#include "llvm/Analysis/Passes.h"
-#include "llvm/ExecutionEngine/ExecutionEngine.h"
-#include "llvm/ExecutionEngine/MCJIT.h"
-#include "llvm/ExecutionEngine/SectionMemoryManager.h"
-#include "llvm/IR/DataLayout.h"
-#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LegacyPassManager.h"
@@ -18,7 +13,10 @@
#include <map>
#include <string>
#include <vector>
+#include "../include/KaleidoscopeJIT.h"
+
using namespace llvm;
+using namespace llvm::orc;
//===----------------------------------------------------------------------===//
// Lexer
@@ -117,7 +115,7 @@
class ExprAST {
public:
virtual ~ExprAST() {}
- virtual Value *Codegen() = 0;
+ virtual Value *codegen() = 0;
};
/// NumberExprAST - Expression class for numeric literals like "1.0".
@@ -126,7 +124,7 @@
public:
NumberExprAST(double Val) : Val(Val) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// VariableExprAST - Expression class for referencing a variable, like "a".
@@ -135,7 +133,7 @@
public:
VariableExprAST(const std::string &Name) : Name(Name) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// BinaryExprAST - Expression class for a binary operator.
@@ -147,7 +145,7 @@
BinaryExprAST(char Op, std::unique_ptr<ExprAST> LHS,
std::unique_ptr<ExprAST> RHS)
: Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// CallExprAST - Expression class for function calls.
@@ -159,7 +157,7 @@
CallExprAST(const std::string &Callee,
std::vector<std::unique_ptr<ExprAST>> Args)
: Callee(Callee), Args(std::move(Args)) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// IfExprAST - Expression class for if/then/else.
@@ -170,7 +168,7 @@
IfExprAST(std::unique_ptr<ExprAST> Cond, std::unique_ptr<ExprAST> Then,
std::unique_ptr<ExprAST> Else)
: Cond(std::move(Cond)), Then(std::move(Then)), Else(std::move(Else)) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// ForExprAST - Expression class for for/in.
@@ -184,7 +182,7 @@
std::unique_ptr<ExprAST> Body)
: VarName(VarName), Start(std::move(Start)), End(std::move(End)),
Step(std::move(Step)), Body(std::move(Body)) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// PrototypeAST - This class represents the "prototype" for a function,
@@ -197,7 +195,8 @@
public:
PrototypeAST(const std::string &Name, std::vector<std::string> Args)
: Name(Name), Args(std::move(Args)) {}
- Function *Codegen();
+ Function *codegen();
+ const std::string &getName() const { return Name; }
};
/// FunctionAST - This class represents a function definition itself.
@@ -209,7 +208,7 @@
FunctionAST(std::unique_ptr<PrototypeAST> Proto,
std::unique_ptr<ExprAST> Body)
: Proto(std::move(Proto)), Body(std::move(Body)) {}
- Function *Codegen();
+ Function *codegen();
};
} // end anonymous namespace
@@ -248,10 +247,6 @@
Error(Str);
return nullptr;
}
-std::unique_ptr<FunctionAST> ErrorF(const char *Str) {
- Error(Str);
- return nullptr;
-}
static std::unique_ptr<ExprAST> ParseExpression();
@@ -498,8 +493,8 @@
static std::unique_ptr<FunctionAST> ParseTopLevelExpr() {
if (auto E = ParseExpression()) {
// Make an anonymous proto.
- auto Proto =
- llvm::make_unique<PrototypeAST>("", std::vector<std::string>());
+ auto Proto = llvm::make_unique<PrototypeAST>("__anon_expr",
+ std::vector<std::string>());
return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E));
}
return nullptr;
@@ -515,21 +510,38 @@
// Code Generation
//===----------------------------------------------------------------------===//
-static Module *TheModule;
+static std::unique_ptr<Module> TheModule;
static IRBuilder<> Builder(getGlobalContext());
static std::map<std::string, Value *> NamedValues;
-static legacy::FunctionPassManager *TheFPM;
+static std::unique_ptr<legacy::FunctionPassManager> TheFPM;
+static std::unique_ptr<KaleidoscopeJIT> TheJIT;
+static std::map<std::string, std::unique_ptr<PrototypeAST>> FunctionProtos;
Value *ErrorV(const char *Str) {
Error(Str);
return nullptr;
}
-Value *NumberExprAST::Codegen() {
+Function *getFunction(std::string Name) {
+ // First, see if the function has already been added to the current module.
+ if (auto *F = TheModule->getFunction(Name))
+ return F;
+
+ // If not, check whether we can codegen the declaration from some existing
+ // prototype.
+ auto FI = FunctionProtos.find(Name);
+ if (FI != FunctionProtos.end())
+ return FI->second->codegen();
+
+ // If no existing prototype exists, return null.
+ return nullptr;
+}
+
+Value *NumberExprAST::codegen() {
return ConstantFP::get(getGlobalContext(), APFloat(Val));
}
-Value *VariableExprAST::Codegen() {
+Value *VariableExprAST::codegen() {
// Look this variable up in the function.
Value *V = NamedValues[Name];
if (!V)
@@ -537,9 +549,9 @@
return V;
}
-Value *BinaryExprAST::Codegen() {
- Value *L = LHS->Codegen();
- Value *R = RHS->Codegen();
+Value *BinaryExprAST::codegen() {
+ Value *L = LHS->codegen();
+ Value *R = RHS->codegen();
if (!L || !R)
return nullptr;
@@ -560,9 +572,9 @@
}
}
-Value *CallExprAST::Codegen() {
+Value *CallExprAST::codegen() {
// Look up the name in the global module table.
- Function *CalleeF = TheModule->getFunction(Callee);
+ Function *CalleeF = getFunction(Callee);
if (!CalleeF)
return ErrorV("Unknown function referenced");
@@ -572,7 +584,7 @@
std::vector<Value *> ArgsV;
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
- ArgsV.push_back(Args[i]->Codegen());
+ ArgsV.push_back(Args[i]->codegen());
if (!ArgsV.back())
return nullptr;
}
@@ -580,8 +592,8 @@
return Builder.CreateCall(CalleeF, ArgsV, "calltmp");
}
-Value *IfExprAST::Codegen() {
- Value *CondV = Cond->Codegen();
+Value *IfExprAST::codegen() {
+ Value *CondV = Cond->codegen();
if (!CondV)
return nullptr;
@@ -603,7 +615,7 @@
// Emit then value.
Builder.SetInsertPoint(ThenBB);
- Value *ThenV = Then->Codegen();
+ Value *ThenV = Then->codegen();
if (!ThenV)
return nullptr;
@@ -615,7 +627,7 @@
TheFunction->getBasicBlockList().push_back(ElseBB);
Builder.SetInsertPoint(ElseBB);
- Value *ElseV = Else->Codegen();
+ Value *ElseV = Else->codegen();
if (!ElseV)
return nullptr;
@@ -649,9 +661,9 @@
// endcond = endexpr
// br endcond, loop, endloop
// outloop:
-Value *ForExprAST::Codegen() {
+Value *ForExprAST::codegen() {
// Emit the start code first, without 'variable' in scope.
- Value *StartVal = Start->Codegen();
+ Value *StartVal = Start->codegen();
if (!StartVal)
return nullptr;
@@ -681,13 +693,13 @@
// Emit the body of the loop. This, like any other expr, can change the
// current BB. Note that we ignore the value computed by the body, but don't
// allow an error.
- if (!Body->Codegen())
+ if (!Body->codegen())
return nullptr;
// Emit the step value.
Value *StepVal = nullptr;
if (Step) {
- StepVal = Step->Codegen();
+ StepVal = Step->codegen();
if (!StepVal)
return nullptr;
} else {
@@ -698,7 +710,7 @@
Value *NextVar = Builder.CreateFAdd(Variable, StepVal, "nextvar");
// Compute the end condition.
- Value *EndCond = End->Codegen();
+ Value *EndCond = End->codegen();
if (!EndCond)
return nullptr;
@@ -730,7 +742,7 @@
return Constant::getNullValue(Type::getDoubleTy(getGlobalContext()));
}
-Function *PrototypeAST::Codegen() {
+Function *PrototypeAST::codegen() {
// Make the function type: double(double,double) etc.
std::vector<Type *> Doubles(Args.size(),
Type::getDoubleTy(getGlobalContext()));
@@ -738,45 +750,22 @@
FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false);
Function *F =
- Function::Create(FT, Function::ExternalLinkage, Name, TheModule);
-
- // If F conflicted, there was already something named 'Name'. If it has a
- // body, don't allow redefinition or reextern.
- if (F->getName() != Name) {
- // Delete the one we just made and get the existing one.
- F->eraseFromParent();
- F = TheModule->getFunction(Name);
-
- // If F already has a body, reject this.
- if (!F->empty()) {
- ErrorF("redefinition of function");
- return nullptr;
- }
-
- // If F took a different number of args, reject.
- if (F->arg_size() != Args.size()) {
- ErrorF("redefinition of function with different # args");
- return nullptr;
- }
- }
+ Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get());
// Set names for all arguments.
unsigned Idx = 0;
- for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size();
- ++AI, ++Idx) {
- AI->setName(Args[Idx]);
-
- // Add arguments to variable symbol table.
- NamedValues[Args[Idx]] = AI;
- }
+ for (auto &Arg : F->args())
+ Arg.setName(Args[Idx++]);
return F;
}
-Function *FunctionAST::Codegen() {
- NamedValues.clear();
-
- Function *TheFunction = Proto->Codegen();
+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;
@@ -784,14 +773,19 @@
BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
Builder.SetInsertPoint(BB);
- if (Value *RetVal = Body->Codegen()) {
+ // Record the function arguments in the NamedValues map.
+ NamedValues.clear();
+ for (auto &Arg : TheFunction->args())
+ NamedValues[Arg.getName()] = &Arg;
+
+ if (Value *RetVal = Body->codegen()) {
// Finish off the function.
Builder.CreateRet(RetVal);
// Validate the generated code, checking for consistency.
verifyFunction(*TheFunction);
- // Optimize the function.
+ // Run the optimizer on the function.
TheFPM->run(*TheFunction);
return TheFunction;
@@ -806,13 +800,35 @@
// Top-Level parsing and JIT Driver
//===----------------------------------------------------------------------===//
-static ExecutionEngine *TheExecutionEngine;
+static void InitializeModuleAndPassManager() {
+ // Open a new module.
+ TheModule = llvm::make_unique<Module>("my cool jit", getGlobalContext());
+ TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout());
+
+ // Create a new pass manager attached to it.
+ TheFPM = llvm::make_unique<legacy::FunctionPassManager>(TheModule.get());
+
+ // Provide basic AliasAnalysis support for GVN.
+ TheFPM->add(createBasicAliasAnalysisPass());
+ // Do simple "peephole" optimizations and bit-twiddling optzns.
+ TheFPM->add(createInstructionCombiningPass());
+ // Reassociate expressions.
+ TheFPM->add(createReassociatePass());
+ // Eliminate Common SubExpressions.
+ TheFPM->add(createGVNPass());
+ // Simplify the control flow graph (deleting unreachable blocks, etc).
+ TheFPM->add(createCFGSimplificationPass());
+
+ TheFPM->doInitialization();
+}
static void HandleDefinition() {
if (auto FnAST = ParseDefinition()) {
- if (auto *FnIR = FnAST->Codegen()) {
+ if (auto *FnIR = FnAST->codegen()) {
fprintf(stderr, "Read function definition:");
FnIR->dump();
+ TheJIT->addModule(std::move(TheModule));
+ InitializeModuleAndPassManager();
}
} else {
// Skip token for error recovery.
@@ -822,9 +838,10 @@
static void HandleExtern() {
if (auto ProtoAST = ParseExtern()) {
- if (auto *FnIR = ProtoAST->Codegen()) {
+ if (auto *FnIR = ProtoAST->codegen()) {
fprintf(stderr, "Read extern: ");
FnIR->dump();
+ FunctionProtos[ProtoAST->getName()] = std::move(ProtoAST);
}
} else {
// Skip token for error recovery.
@@ -835,15 +852,24 @@
static void HandleTopLevelExpression() {
// Evaluate a top-level expression into an anonymous function.
if (auto FnAST = ParseTopLevelExpr()) {
- if (auto *FnIR = FnAST->Codegen()) {
- TheExecutionEngine->finalizeObject();
- // JIT the function, returning a function pointer.
- void *FPtr = TheExecutionEngine->getPointerToFunction(FnIR);
+ if (FnAST->codegen()) {
- // 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)FPtr;
+ // JIT the module containing the anonymous expression, keeping a handle so
+ // we can free it later.
+ auto H = TheJIT->addModule(std::move(TheModule));
+ InitializeModuleAndPassManager();
+
+ // Search the JIT for the __anon_expr symbol.
+ auto ExprSymbol = TheJIT->findSymbol("__anon_expr");
+ assert(ExprSymbol && "Function not found");
+
+ // Get the symbol's address and cast it to the right type (takes no
+ // arguments, returns a double) so we can call it as a native function.
+ 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);
}
} else {
// Skip token for error recovery.
@@ -898,7 +924,6 @@
InitializeNativeTarget();
InitializeNativeTargetAsmPrinter();
InitializeNativeTargetAsmParser();
- LLVMContext &Context = getGlobalContext();
// Install standard binary operators.
// 1 is lowest precedence.
@@ -911,50 +936,12 @@
fprintf(stderr, "ready> ");
getNextToken();
- // Make the module, which holds all the code.
- std::unique_ptr<Module> Owner = make_unique<Module>("my cool jit", Context);
- TheModule = Owner.get();
+ TheJIT = llvm::make_unique<KaleidoscopeJIT>();
- // Create the JIT. This takes ownership of the module.
- std::string ErrStr;
- TheExecutionEngine =
- EngineBuilder(std::move(Owner))
- .setErrorStr(&ErrStr)
- .setMCJITMemoryManager(llvm::make_unique<SectionMemoryManager>())
- .create();
- if (!TheExecutionEngine) {
- fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str());
- exit(1);
- }
-
- legacy::FunctionPassManager OurFPM(TheModule);
-
- // Set up the optimizer pipeline. Start with registering info about how the
- // target lays out data structures.
- TheModule->setDataLayout(TheExecutionEngine->getDataLayout());
- // Provide basic AliasAnalysis support for GVN.
- OurFPM.add(createBasicAliasAnalysisPass());
- // Do simple "peephole" optimizations and bit-twiddling optzns.
- OurFPM.add(createInstructionCombiningPass());
- // Reassociate expressions.
- OurFPM.add(createReassociatePass());
- // Eliminate Common SubExpressions.
- OurFPM.add(createGVNPass());
- // Simplify the control flow graph (deleting unreachable blocks, etc).
- OurFPM.add(createCFGSimplificationPass());
-
- OurFPM.doInitialization();
-
- // Set the global so the code gen can use this.
- TheFPM = &OurFPM;
+ InitializeModuleAndPassManager();
// Run the main "interpreter loop" now.
MainLoop();
- TheFPM = 0;
-
- // Print out all of the generated code.
- TheModule->dump();
-
return 0;
}
diff --git a/llvm/examples/Kaleidoscope/Chapter6/toy.cpp b/llvm/examples/Kaleidoscope/Chapter6/toy.cpp
index b4e8397..e1bed45 100644
--- a/llvm/examples/Kaleidoscope/Chapter6/toy.cpp
+++ b/llvm/examples/Kaleidoscope/Chapter6/toy.cpp
@@ -1,11 +1,6 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Analysis/BasicAliasAnalysis.h"
#include "llvm/Analysis/Passes.h"
-#include "llvm/ExecutionEngine/ExecutionEngine.h"
-#include "llvm/ExecutionEngine/MCJIT.h"
-#include "llvm/ExecutionEngine/SectionMemoryManager.h"
-#include "llvm/IR/DataLayout.h"
-#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LegacyPassManager.h"
@@ -18,7 +13,10 @@
#include <map>
#include <string>
#include <vector>
+#include "../include/KaleidoscopeJIT.h"
+
using namespace llvm;
+using namespace llvm::orc;
//===----------------------------------------------------------------------===//
// Lexer
@@ -125,7 +123,7 @@
class ExprAST {
public:
virtual ~ExprAST() {}
- virtual Value *Codegen() = 0;
+ virtual Value *codegen() = 0;
};
/// NumberExprAST - Expression class for numeric literals like "1.0".
@@ -134,7 +132,7 @@
public:
NumberExprAST(double Val) : Val(Val) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// VariableExprAST - Expression class for referencing a variable, like "a".
@@ -143,7 +141,7 @@
public:
VariableExprAST(const std::string &Name) : Name(Name) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// UnaryExprAST - Expression class for a unary operator.
@@ -154,7 +152,7 @@
public:
UnaryExprAST(char Opcode, std::unique_ptr<ExprAST> Operand)
: Opcode(Opcode), Operand(std::move(Operand)) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// BinaryExprAST - Expression class for a binary operator.
@@ -166,7 +164,7 @@
BinaryExprAST(char Op, std::unique_ptr<ExprAST> LHS,
std::unique_ptr<ExprAST> RHS)
: Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// CallExprAST - Expression class for function calls.
@@ -178,7 +176,7 @@
CallExprAST(const std::string &Callee,
std::vector<std::unique_ptr<ExprAST>> Args)
: Callee(Callee), Args(std::move(Args)) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// IfExprAST - Expression class for if/then/else.
@@ -189,7 +187,7 @@
IfExprAST(std::unique_ptr<ExprAST> Cond, std::unique_ptr<ExprAST> Then,
std::unique_ptr<ExprAST> Else)
: Cond(std::move(Cond)), Then(std::move(Then)), Else(std::move(Else)) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// ForExprAST - Expression class for for/in.
@@ -203,7 +201,7 @@
std::unique_ptr<ExprAST> Body)
: VarName(VarName), Start(std::move(Start)), End(std::move(End)),
Step(std::move(Step)), Body(std::move(Body)) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// PrototypeAST - This class represents the "prototype" for a function,
@@ -220,6 +218,8 @@
bool IsOperator = false, unsigned Prec = 0)
: Name(Name), Args(std::move(Args)), IsOperator(IsOperator),
Precedence(Prec) {}
+ Function *codegen();
+ const std::string &getName() const { return Name; }
bool isUnaryOp() const { return IsOperator && Args.size() == 1; }
bool isBinaryOp() const { return IsOperator && Args.size() == 2; }
@@ -230,8 +230,6 @@
}
unsigned getBinaryPrecedence() const { return Precedence; }
-
- Function *Codegen();
};
/// FunctionAST - This class represents a function definition itself.
@@ -243,7 +241,7 @@
FunctionAST(std::unique_ptr<PrototypeAST> Proto,
std::unique_ptr<ExprAST> Body)
: Proto(std::move(Proto)), Body(std::move(Body)) {}
- Function *Codegen();
+ Function *codegen();
};
} // end anonymous namespace
@@ -282,10 +280,6 @@
Error(Str);
return nullptr;
}
-std::unique_ptr<FunctionAST> ErrorF(const char *Str) {
- Error(Str);
- return nullptr;
-}
static std::unique_ptr<ExprAST> ParseExpression();
@@ -590,8 +584,8 @@
static std::unique_ptr<FunctionAST> ParseTopLevelExpr() {
if (auto E = ParseExpression()) {
// Make an anonymous proto.
- auto Proto =
- llvm::make_unique<PrototypeAST>("", std::vector<std::string>());
+ auto Proto = llvm::make_unique<PrototypeAST>("__anon_expr",
+ std::vector<std::string>());
return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E));
}
return nullptr;
@@ -607,21 +601,38 @@
// Code Generation
//===----------------------------------------------------------------------===//
-static Module *TheModule;
+static std::unique_ptr<Module> TheModule;
static IRBuilder<> Builder(getGlobalContext());
static std::map<std::string, Value *> NamedValues;
-static legacy::FunctionPassManager *TheFPM;
+static std::unique_ptr<legacy::FunctionPassManager> TheFPM;
+static std::unique_ptr<KaleidoscopeJIT> TheJIT;
+static std::map<std::string, std::unique_ptr<PrototypeAST>> FunctionProtos;
Value *ErrorV(const char *Str) {
Error(Str);
return nullptr;
}
-Value *NumberExprAST::Codegen() {
+Function *getFunction(std::string Name) {
+ // First, see if the function has already been added to the current module.
+ if (auto *F = TheModule->getFunction(Name))
+ return F;
+
+ // If not, check whether we can codegen the declaration from some existing
+ // prototype.
+ auto FI = FunctionProtos.find(Name);
+ if (FI != FunctionProtos.end())
+ return FI->second->codegen();
+
+ // If no existing prototype exists, return null.
+ return nullptr;
+}
+
+Value *NumberExprAST::codegen() {
return ConstantFP::get(getGlobalContext(), APFloat(Val));
}
-Value *VariableExprAST::Codegen() {
+Value *VariableExprAST::codegen() {
// Look this variable up in the function.
Value *V = NamedValues[Name];
if (!V)
@@ -629,21 +640,21 @@
return V;
}
-Value *UnaryExprAST::Codegen() {
- Value *OperandV = Operand->Codegen();
+Value *UnaryExprAST::codegen() {
+ Value *OperandV = Operand->codegen();
if (!OperandV)
return nullptr;
- Function *F = TheModule->getFunction(std::string("unary") + Opcode);
+ Function *F = getFunction(std::string("unary") + Opcode);
if (!F)
return ErrorV("Unknown unary operator");
return Builder.CreateCall(F, OperandV, "unop");
}
-Value *BinaryExprAST::Codegen() {
- Value *L = LHS->Codegen();
- Value *R = RHS->Codegen();
+Value *BinaryExprAST::codegen() {
+ Value *L = LHS->codegen();
+ Value *R = RHS->codegen();
if (!L || !R)
return nullptr;
@@ -665,16 +676,16 @@
// If it wasn't a builtin binary operator, it must be a user defined one. Emit
// a call to it.
- Function *F = TheModule->getFunction(std::string("binary") + Op);
+ Function *F = getFunction(std::string("binary") + Op);
assert(F && "binary operator not found!");
Value *Ops[] = {L, R};
return Builder.CreateCall(F, Ops, "binop");
}
-Value *CallExprAST::Codegen() {
+Value *CallExprAST::codegen() {
// Look up the name in the global module table.
- Function *CalleeF = TheModule->getFunction(Callee);
+ Function *CalleeF = getFunction(Callee);
if (!CalleeF)
return ErrorV("Unknown function referenced");
@@ -684,7 +695,7 @@
std::vector<Value *> ArgsV;
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
- ArgsV.push_back(Args[i]->Codegen());
+ ArgsV.push_back(Args[i]->codegen());
if (!ArgsV.back())
return nullptr;
}
@@ -692,8 +703,8 @@
return Builder.CreateCall(CalleeF, ArgsV, "calltmp");
}
-Value *IfExprAST::Codegen() {
- Value *CondV = Cond->Codegen();
+Value *IfExprAST::codegen() {
+ Value *CondV = Cond->codegen();
if (!CondV)
return nullptr;
@@ -715,7 +726,7 @@
// Emit then value.
Builder.SetInsertPoint(ThenBB);
- Value *ThenV = Then->Codegen();
+ Value *ThenV = Then->codegen();
if (!ThenV)
return nullptr;
@@ -727,7 +738,7 @@
TheFunction->getBasicBlockList().push_back(ElseBB);
Builder.SetInsertPoint(ElseBB);
- Value *ElseV = Else->Codegen();
+ Value *ElseV = Else->codegen();
if (!ElseV)
return nullptr;
@@ -761,9 +772,9 @@
// endcond = endexpr
// br endcond, loop, endloop
// outloop:
-Value *ForExprAST::Codegen() {
+Value *ForExprAST::codegen() {
// Emit the start code first, without 'variable' in scope.
- Value *StartVal = Start->Codegen();
+ Value *StartVal = Start->codegen();
if (!StartVal)
return nullptr;
@@ -793,13 +804,13 @@
// Emit the body of the loop. This, like any other expr, can change the
// current BB. Note that we ignore the value computed by the body, but don't
// allow an error.
- if (!Body->Codegen())
+ if (!Body->codegen())
return nullptr;
// Emit the step value.
Value *StepVal = nullptr;
if (Step) {
- StepVal = Step->Codegen();
+ StepVal = Step->codegen();
if (!StepVal)
return nullptr;
} else {
@@ -810,7 +821,7 @@
Value *NextVar = Builder.CreateFAdd(Variable, StepVal, "nextvar");
// Compute the end condition.
- Value *EndCond = End->Codegen();
+ Value *EndCond = End->codegen();
if (!EndCond)
return nullptr;
@@ -842,7 +853,7 @@
return Constant::getNullValue(Type::getDoubleTy(getGlobalContext()));
}
-Function *PrototypeAST::Codegen() {
+Function *PrototypeAST::codegen() {
// Make the function type: double(double,double) etc.
std::vector<Type *> Doubles(Args.size(),
Type::getDoubleTy(getGlobalContext()));
@@ -850,64 +861,46 @@
FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false);
Function *F =
- Function::Create(FT, Function::ExternalLinkage, Name, TheModule);
-
- // If F conflicted, there was already something named 'Name'. If it has a
- // body, don't allow redefinition or reextern.
- if (F->getName() != Name) {
- // Delete the one we just made and get the existing one.
- F->eraseFromParent();
- F = TheModule->getFunction(Name);
-
- // If F already has a body, reject this.
- if (!F->empty()) {
- ErrorF("redefinition of function");
- return nullptr;
- }
-
- // If F took a different number of args, reject.
- if (F->arg_size() != Args.size()) {
- ErrorF("redefinition of function with different # args");
- return nullptr;
- }
- }
+ Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get());
// Set names for all arguments.
unsigned Idx = 0;
- for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size();
- ++AI, ++Idx) {
- AI->setName(Args[Idx]);
-
- // Add arguments to variable symbol table.
- NamedValues[Args[Idx]] = AI;
- }
+ for (auto &Arg : F->args())
+ Arg.setName(Args[Idx++]);
return F;
}
-Function *FunctionAST::Codegen() {
- NamedValues.clear();
-
- Function *TheFunction = Proto->Codegen();
+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;
// If this is an operator, install it.
- if (Proto->isBinaryOp())
- BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence();
+ if (P.isBinaryOp())
+ BinopPrecedence[P.getOperatorName()] = P.getBinaryPrecedence();
// Create a new basic block to start insertion into.
BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
Builder.SetInsertPoint(BB);
- if (Value *RetVal = Body->Codegen()) {
+ // Record the function arguments in the NamedValues map.
+ NamedValues.clear();
+ for (auto &Arg : TheFunction->args())
+ NamedValues[Arg.getName()] = &Arg;
+
+ if (Value *RetVal = Body->codegen()) {
// Finish off the function.
Builder.CreateRet(RetVal);
// Validate the generated code, checking for consistency.
verifyFunction(*TheFunction);
- // Optimize the function.
+ // Run the optimizer on the function.
TheFPM->run(*TheFunction);
return TheFunction;
@@ -916,7 +909,7 @@
// Error reading body, remove function.
TheFunction->eraseFromParent();
- if (Proto->isBinaryOp())
+ if (P.isBinaryOp())
BinopPrecedence.erase(Proto->getOperatorName());
return nullptr;
}
@@ -925,13 +918,35 @@
// Top-Level parsing and JIT Driver
//===----------------------------------------------------------------------===//
-static ExecutionEngine *TheExecutionEngine;
+static void InitializeModuleAndPassManager() {
+ // Open a new module.
+ TheModule = llvm::make_unique<Module>("my cool jit", getGlobalContext());
+ TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout());
+
+ // Create a new pass manager attached to it.
+ TheFPM = llvm::make_unique<legacy::FunctionPassManager>(TheModule.get());
+
+ // Provide basic AliasAnalysis support for GVN.
+ TheFPM->add(createBasicAliasAnalysisPass());
+ // Do simple "peephole" optimizations and bit-twiddling optzns.
+ TheFPM->add(createInstructionCombiningPass());
+ // Reassociate expressions.
+ TheFPM->add(createReassociatePass());
+ // Eliminate Common SubExpressions.
+ TheFPM->add(createGVNPass());
+ // Simplify the control flow graph (deleting unreachable blocks, etc).
+ TheFPM->add(createCFGSimplificationPass());
+
+ TheFPM->doInitialization();
+}
static void HandleDefinition() {
if (auto FnAST = ParseDefinition()) {
- if (auto *FnIR = FnAST->Codegen()) {
+ if (auto *FnIR = FnAST->codegen()) {
fprintf(stderr, "Read function definition:");
FnIR->dump();
+ TheJIT->addModule(std::move(TheModule));
+ InitializeModuleAndPassManager();
}
} else {
// Skip token for error recovery.
@@ -941,9 +956,10 @@
static void HandleExtern() {
if (auto ProtoAST = ParseExtern()) {
- if (auto *FnIR = ProtoAST->Codegen()) {
+ if (auto *FnIR = ProtoAST->codegen()) {
fprintf(stderr, "Read extern: ");
FnIR->dump();
+ FunctionProtos[ProtoAST->getName()] = std::move(ProtoAST);
}
} else {
// Skip token for error recovery.
@@ -954,15 +970,24 @@
static void HandleTopLevelExpression() {
// Evaluate a top-level expression into an anonymous function.
if (auto FnAST = ParseTopLevelExpr()) {
- if (auto *FnIR = FnAST->Codegen()) {
- TheExecutionEngine->finalizeObject();
- // JIT the function, returning a function pointer.
- void *FPtr = TheExecutionEngine->getPointerToFunction(FnIR);
+ if (FnAST->codegen()) {
- // 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)FPtr;
+ // JIT the module containing the anonymous expression, keeping a handle so
+ // we can free it later.
+ auto H = TheJIT->addModule(std::move(TheModule));
+ InitializeModuleAndPassManager();
+
+ // Search the JIT for the __anon_expr symbol.
+ auto ExprSymbol = TheJIT->findSymbol("__anon_expr");
+ assert(ExprSymbol && "Function not found");
+
+ // Get the symbol's address and cast it to the right type (takes no
+ // arguments, returns a double) so we can call it as a native function.
+ 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);
}
} else {
// Skip token for error recovery.
@@ -1017,7 +1042,6 @@
InitializeNativeTarget();
InitializeNativeTargetAsmPrinter();
InitializeNativeTargetAsmParser();
- LLVMContext &Context = getGlobalContext();
// Install standard binary operators.
// 1 is lowest precedence.
@@ -1030,50 +1054,12 @@
fprintf(stderr, "ready> ");
getNextToken();
- // Make the module, which holds all the code.
- std::unique_ptr<Module> Owner = make_unique<Module>("my cool jit", Context);
- TheModule = Owner.get();
+ TheJIT = llvm::make_unique<KaleidoscopeJIT>();
- // Create the JIT. This takes ownership of the module.
- std::string ErrStr;
- TheExecutionEngine =
- EngineBuilder(std::move(Owner))
- .setErrorStr(&ErrStr)
- .setMCJITMemoryManager(llvm::make_unique<SectionMemoryManager>())
- .create();
- if (!TheExecutionEngine) {
- fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str());
- exit(1);
- }
-
- legacy::FunctionPassManager OurFPM(TheModule);
-
- // Set up the optimizer pipeline. Start with registering info about how the
- // target lays out data structures.
- TheModule->setDataLayout(TheExecutionEngine->getDataLayout());
- // Provide basic AliasAnalysis support for GVN.
- OurFPM.add(createBasicAliasAnalysisPass());
- // Do simple "peephole" optimizations and bit-twiddling optzns.
- OurFPM.add(createInstructionCombiningPass());
- // Reassociate expressions.
- OurFPM.add(createReassociatePass());
- // Eliminate Common SubExpressions.
- OurFPM.add(createGVNPass());
- // Simplify the control flow graph (deleting unreachable blocks, etc).
- OurFPM.add(createCFGSimplificationPass());
-
- OurFPM.doInitialization();
-
- // Set the global so the code gen can use this.
- TheFPM = &OurFPM;
+ InitializeModuleAndPassManager();
// Run the main "interpreter loop" now.
MainLoop();
- TheFPM = 0;
-
- // Print out all of the generated code.
- TheModule->dump();
-
return 0;
}
diff --git a/llvm/examples/Kaleidoscope/Chapter7/toy.cpp b/llvm/examples/Kaleidoscope/Chapter7/toy.cpp
index a900c5f..4558522 100644
--- a/llvm/examples/Kaleidoscope/Chapter7/toy.cpp
+++ b/llvm/examples/Kaleidoscope/Chapter7/toy.cpp
@@ -1,11 +1,6 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Analysis/BasicAliasAnalysis.h"
#include "llvm/Analysis/Passes.h"
-#include "llvm/ExecutionEngine/ExecutionEngine.h"
-#include "llvm/ExecutionEngine/MCJIT.h"
-#include "llvm/ExecutionEngine/SectionMemoryManager.h"
-#include "llvm/IR/DataLayout.h"
-#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LegacyPassManager.h"
@@ -18,7 +13,10 @@
#include <map>
#include <string>
#include <vector>
+#include "../include/KaleidoscopeJIT.h"
+
using namespace llvm;
+using namespace llvm::orc;
//===----------------------------------------------------------------------===//
// Lexer
@@ -130,7 +128,7 @@
class ExprAST {
public:
virtual ~ExprAST() {}
- virtual Value *Codegen() = 0;
+ virtual Value *codegen() = 0;
};
/// NumberExprAST - Expression class for numeric literals like "1.0".
@@ -139,7 +137,7 @@
public:
NumberExprAST(double Val) : Val(Val) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// VariableExprAST - Expression class for referencing a variable, like "a".
@@ -149,7 +147,7 @@
public:
VariableExprAST(const std::string &Name) : Name(Name) {}
const std::string &getName() const { return Name; }
- Value *Codegen() override;
+ Value *codegen() override;
};
/// UnaryExprAST - Expression class for a unary operator.
@@ -160,7 +158,7 @@
public:
UnaryExprAST(char Opcode, std::unique_ptr<ExprAST> Operand)
: Opcode(Opcode), Operand(std::move(Operand)) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// BinaryExprAST - Expression class for a binary operator.
@@ -172,7 +170,7 @@
BinaryExprAST(char Op, std::unique_ptr<ExprAST> LHS,
std::unique_ptr<ExprAST> RHS)
: Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// CallExprAST - Expression class for function calls.
@@ -184,7 +182,7 @@
CallExprAST(const std::string &Callee,
std::vector<std::unique_ptr<ExprAST>> Args)
: Callee(Callee), Args(std::move(Args)) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// IfExprAST - Expression class for if/then/else.
@@ -195,7 +193,7 @@
IfExprAST(std::unique_ptr<ExprAST> Cond, std::unique_ptr<ExprAST> Then,
std::unique_ptr<ExprAST> Else)
: Cond(std::move(Cond)), Then(std::move(Then)), Else(std::move(Else)) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// ForExprAST - Expression class for for/in.
@@ -209,7 +207,7 @@
std::unique_ptr<ExprAST> Body)
: VarName(VarName), Start(std::move(Start)), End(std::move(End)),
Step(std::move(Step)), Body(std::move(Body)) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// VarExprAST - Expression class for var/in
@@ -222,7 +220,7 @@
std::vector<std::pair<std::string, std::unique_ptr<ExprAST>>> VarNames,
std::unique_ptr<ExprAST> Body)
: VarNames(std::move(VarNames)), Body(std::move(Body)) {}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// PrototypeAST - This class represents the "prototype" for a function,
@@ -239,6 +237,8 @@
bool IsOperator = false, unsigned Prec = 0)
: Name(Name), Args(std::move(Args)), IsOperator(IsOperator),
Precedence(Prec) {}
+ Function *codegen();
+ const std::string &getName() const { return Name; }
bool isUnaryOp() const { return IsOperator && Args.size() == 1; }
bool isBinaryOp() const { return IsOperator && Args.size() == 2; }
@@ -249,10 +249,6 @@
}
unsigned getBinaryPrecedence() const { return Precedence; }
-
- Function *Codegen();
-
- void CreateArgumentAllocas(Function *F);
};
/// FunctionAST - This class represents a function definition itself.
@@ -264,7 +260,7 @@
FunctionAST(std::unique_ptr<PrototypeAST> Proto,
std::unique_ptr<ExprAST> Body)
: Proto(std::move(Proto)), Body(std::move(Body)) {}
- Function *Codegen();
+ Function *codegen();
};
} // end anonymous namespace
@@ -303,10 +299,6 @@
Error(Str);
return nullptr;
}
-std::unique_ptr<FunctionAST> ErrorF(const char *Str) {
- Error(Str);
- return nullptr;
-}
static std::unique_ptr<ExprAST> ParseExpression();
@@ -662,8 +654,8 @@
static std::unique_ptr<FunctionAST> ParseTopLevelExpr() {
if (auto E = ParseExpression()) {
// Make an anonymous proto.
- auto Proto =
- llvm::make_unique<PrototypeAST>("", std::vector<std::string>());
+ auto Proto = llvm::make_unique<PrototypeAST>("__anon_expr",
+ std::vector<std::string>());
return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E));
}
return nullptr;
@@ -679,16 +671,33 @@
// Code Generation
//===----------------------------------------------------------------------===//
-static Module *TheModule;
+static std::unique_ptr<Module> TheModule;
static IRBuilder<> Builder(getGlobalContext());
static std::map<std::string, AllocaInst *> NamedValues;
-static legacy::FunctionPassManager *TheFPM;
+static std::unique_ptr<legacy::FunctionPassManager> TheFPM;
+static std::unique_ptr<KaleidoscopeJIT> TheJIT;
+static std::map<std::string, std::unique_ptr<PrototypeAST>> FunctionProtos;
Value *ErrorV(const char *Str) {
Error(Str);
return nullptr;
}
+Function *getFunction(std::string Name) {
+ // First, see if the function has already been added to the current module.
+ if (auto *F = TheModule->getFunction(Name))
+ return F;
+
+ // If not, check whether we can codegen the declaration from some existing
+ // prototype.
+ auto FI = FunctionProtos.find(Name);
+ if (FI != FunctionProtos.end())
+ return FI->second->codegen();
+
+ // If no existing prototype exists, return null.
+ return nullptr;
+}
+
/// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of
/// the function. This is used for mutable variables etc.
static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction,
@@ -699,11 +708,11 @@
VarName.c_str());
}
-Value *NumberExprAST::Codegen() {
+Value *NumberExprAST::codegen() {
return ConstantFP::get(getGlobalContext(), APFloat(Val));
}
-Value *VariableExprAST::Codegen() {
+Value *VariableExprAST::codegen() {
// Look this variable up in the function.
Value *V = NamedValues[Name];
if (!V)
@@ -713,19 +722,19 @@
return Builder.CreateLoad(V, Name.c_str());
}
-Value *UnaryExprAST::Codegen() {
- Value *OperandV = Operand->Codegen();
+Value *UnaryExprAST::codegen() {
+ Value *OperandV = Operand->codegen();
if (!OperandV)
return nullptr;
- Function *F = TheModule->getFunction(std::string("unary") + Opcode);
+ Function *F = getFunction(std::string("unary") + Opcode);
if (!F)
return ErrorV("Unknown unary operator");
return Builder.CreateCall(F, OperandV, "unop");
}
-Value *BinaryExprAST::Codegen() {
+Value *BinaryExprAST::codegen() {
// Special case '=' because we don't want to emit the LHS as an expression.
if (Op == '=') {
// Assignment requires the LHS to be an identifier.
@@ -736,7 +745,7 @@
if (!LHSE)
return ErrorV("destination of '=' must be a variable");
// Codegen the RHS.
- Value *Val = RHS->Codegen();
+ Value *Val = RHS->codegen();
if (!Val)
return nullptr;
@@ -749,8 +758,8 @@
return Val;
}
- Value *L = LHS->Codegen();
- Value *R = RHS->Codegen();
+ Value *L = LHS->codegen();
+ Value *R = RHS->codegen();
if (!L || !R)
return nullptr;
@@ -772,16 +781,16 @@
// If it wasn't a builtin binary operator, it must be a user defined one. Emit
// a call to it.
- Function *F = TheModule->getFunction(std::string("binary") + Op);
+ Function *F = getFunction(std::string("binary") + Op);
assert(F && "binary operator not found!");
Value *Ops[] = {L, R};
return Builder.CreateCall(F, Ops, "binop");
}
-Value *CallExprAST::Codegen() {
+Value *CallExprAST::codegen() {
// Look up the name in the global module table.
- Function *CalleeF = TheModule->getFunction(Callee);
+ Function *CalleeF = getFunction(Callee);
if (!CalleeF)
return ErrorV("Unknown function referenced");
@@ -791,7 +800,7 @@
std::vector<Value *> ArgsV;
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
- ArgsV.push_back(Args[i]->Codegen());
+ ArgsV.push_back(Args[i]->codegen());
if (!ArgsV.back())
return nullptr;
}
@@ -799,8 +808,8 @@
return Builder.CreateCall(CalleeF, ArgsV, "calltmp");
}
-Value *IfExprAST::Codegen() {
- Value *CondV = Cond->Codegen();
+Value *IfExprAST::codegen() {
+ Value *CondV = Cond->codegen();
if (!CondV)
return nullptr;
@@ -822,7 +831,7 @@
// Emit then value.
Builder.SetInsertPoint(ThenBB);
- Value *ThenV = Then->Codegen();
+ Value *ThenV = Then->codegen();
if (!ThenV)
return nullptr;
@@ -834,7 +843,7 @@
TheFunction->getBasicBlockList().push_back(ElseBB);
Builder.SetInsertPoint(ElseBB);
- Value *ElseV = Else->Codegen();
+ Value *ElseV = Else->codegen();
if (!ElseV)
return nullptr;
@@ -872,14 +881,14 @@
// store nextvar -> var
// br endcond, loop, endloop
// outloop:
-Value *ForExprAST::Codegen() {
+Value *ForExprAST::codegen() {
Function *TheFunction = Builder.GetInsertBlock()->getParent();
// Create an alloca for the variable in the entry block.
AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName);
// Emit the start code first, without 'variable' in scope.
- Value *StartVal = Start->Codegen();
+ Value *StartVal = Start->codegen();
if (!StartVal)
return nullptr;
@@ -905,13 +914,13 @@
// Emit the body of the loop. This, like any other expr, can change the
// current BB. Note that we ignore the value computed by the body, but don't
// allow an error.
- if (!Body->Codegen())
+ if (!Body->codegen())
return nullptr;
// Emit the step value.
Value *StepVal = nullptr;
if (Step) {
- StepVal = Step->Codegen();
+ StepVal = Step->codegen();
if (!StepVal)
return nullptr;
} else {
@@ -920,7 +929,7 @@
}
// Compute the end condition.
- Value *EndCond = End->Codegen();
+ Value *EndCond = End->codegen();
if (!EndCond)
return nullptr;
@@ -954,7 +963,7 @@
return Constant::getNullValue(Type::getDoubleTy(getGlobalContext()));
}
-Value *VarExprAST::Codegen() {
+Value *VarExprAST::codegen() {
std::vector<AllocaInst *> OldBindings;
Function *TheFunction = Builder.GetInsertBlock()->getParent();
@@ -971,7 +980,7 @@
// var a = a in ... # refers to outer 'a'.
Value *InitVal;
if (Init) {
- InitVal = Init->Codegen();
+ InitVal = Init->codegen();
if (!InitVal)
return nullptr;
} else { // If not specified, use 0.0.
@@ -990,7 +999,7 @@
}
// Codegen the body, now that all vars are in scope.
- Value *BodyVal = Body->Codegen();
+ Value *BodyVal = Body->codegen();
if (!BodyVal)
return nullptr;
@@ -1002,7 +1011,7 @@
return BodyVal;
}
-Function *PrototypeAST::Codegen() {
+Function *PrototypeAST::codegen() {
// Make the function type: double(double,double) etc.
std::vector<Type *> Doubles(Args.size(),
Type::getDoubleTy(getGlobalContext()));
@@ -1010,79 +1019,54 @@
FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false);
Function *F =
- Function::Create(FT, Function::ExternalLinkage, Name, TheModule);
-
- // If F conflicted, there was already something named 'Name'. If it has a
- // body, don't allow redefinition or reextern.
- if (F->getName() != Name) {
- // Delete the one we just made and get the existing one.
- F->eraseFromParent();
- F = TheModule->getFunction(Name);
-
- // If F already has a body, reject this.
- if (!F->empty()) {
- ErrorF("redefinition of function");
- return nullptr;
- }
-
- // If F took a different number of args, reject.
- if (F->arg_size() != Args.size()) {
- ErrorF("redefinition of function with different # args");
- return nullptr;
- }
- }
+ Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get());
// Set names for all arguments.
unsigned Idx = 0;
- for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size();
- ++AI, ++Idx)
- AI->setName(Args[Idx]);
+ for (auto &Arg : F->args())
+ Arg.setName(Args[Idx++]);
return F;
}
-/// CreateArgumentAllocas - Create an alloca for each argument and register the
-/// argument in the symbol table so that references to it will succeed.
-void PrototypeAST::CreateArgumentAllocas(Function *F) {
- Function::arg_iterator AI = F->arg_begin();
- for (unsigned Idx = 0, e = Args.size(); Idx != e; ++Idx, ++AI) {
- // Create an alloca for this variable.
- AllocaInst *Alloca = CreateEntryBlockAlloca(F, Args[Idx]);
-
- // Store the initial value into the alloca.
- Builder.CreateStore(AI, Alloca);
-
- // Add arguments to variable symbol table.
- NamedValues[Args[Idx]] = Alloca;
- }
-}
-
-Function *FunctionAST::Codegen() {
- NamedValues.clear();
-
- Function *TheFunction = Proto->Codegen();
+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;
// If this is an operator, install it.
- if (Proto->isBinaryOp())
- BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence();
+ if (P.isBinaryOp())
+ BinopPrecedence[P.getOperatorName()] = P.getBinaryPrecedence();
// Create a new basic block to start insertion into.
BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
Builder.SetInsertPoint(BB);
- // Add all arguments to the symbol table and create their allocas.
- Proto->CreateArgumentAllocas(TheFunction);
+ // Record the function arguments in the NamedValues map.
+ NamedValues.clear();
+ for (auto &Arg : TheFunction->args()) {
+ // Create an alloca for this variable.
+ AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, Arg.getName());
- if (Value *RetVal = Body->Codegen()) {
+ // Store the initial value into the alloca.
+ Builder.CreateStore(&Arg, Alloca);
+
+ // Add arguments to variable symbol table.
+ NamedValues[Arg.getName()] = Alloca;
+ }
+
+ if (Value *RetVal = Body->codegen()) {
// Finish off the function.
Builder.CreateRet(RetVal);
// Validate the generated code, checking for consistency.
verifyFunction(*TheFunction);
- // Optimize the function.
+ // Run the optimizer on the function.
TheFPM->run(*TheFunction);
return TheFunction;
@@ -1091,7 +1075,7 @@
// Error reading body, remove function.
TheFunction->eraseFromParent();
- if (Proto->isBinaryOp())
+ if (P.isBinaryOp())
BinopPrecedence.erase(Proto->getOperatorName());
return nullptr;
}
@@ -1100,13 +1084,35 @@
// Top-Level parsing and JIT Driver
//===----------------------------------------------------------------------===//
-static ExecutionEngine *TheExecutionEngine;
+static void InitializeModuleAndPassManager() {
+ // Open a new module.
+ TheModule = llvm::make_unique<Module>("my cool jit", getGlobalContext());
+ TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout());
+
+ // Create a new pass manager attached to it.
+ TheFPM = llvm::make_unique<legacy::FunctionPassManager>(TheModule.get());
+
+ // Provide basic AliasAnalysis support for GVN.
+ TheFPM->add(createBasicAliasAnalysisPass());
+ // Do simple "peephole" optimizations and bit-twiddling optzns.
+ TheFPM->add(createInstructionCombiningPass());
+ // Reassociate expressions.
+ TheFPM->add(createReassociatePass());
+ // Eliminate Common SubExpressions.
+ TheFPM->add(createGVNPass());
+ // Simplify the control flow graph (deleting unreachable blocks, etc).
+ TheFPM->add(createCFGSimplificationPass());
+
+ TheFPM->doInitialization();
+}
static void HandleDefinition() {
if (auto FnAST = ParseDefinition()) {
- if (auto *FnIR = FnAST->Codegen()) {
+ if (auto *FnIR = FnAST->codegen()) {
fprintf(stderr, "Read function definition:");
FnIR->dump();
+ TheJIT->addModule(std::move(TheModule));
+ InitializeModuleAndPassManager();
}
} else {
// Skip token for error recovery.
@@ -1116,9 +1122,10 @@
static void HandleExtern() {
if (auto ProtoAST = ParseExtern()) {
- if (auto *FnIR = ProtoAST->Codegen()) {
+ if (auto *FnIR = ProtoAST->codegen()) {
fprintf(stderr, "Read extern: ");
FnIR->dump();
+ FunctionProtos[ProtoAST->getName()] = std::move(ProtoAST);
}
} else {
// Skip token for error recovery.
@@ -1129,15 +1136,24 @@
static void HandleTopLevelExpression() {
// Evaluate a top-level expression into an anonymous function.
if (auto FnAST = ParseTopLevelExpr()) {
- if (auto *FnIR = FnAST->Codegen()) {
- TheExecutionEngine->finalizeObject();
- // JIT the function, returning a function pointer.
- void *FPtr = TheExecutionEngine->getPointerToFunction(FnIR);
+ if (FnAST->codegen()) {
- // 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)FPtr;
+ // JIT the module containing the anonymous expression, keeping a handle so
+ // we can free it later.
+ auto H = TheJIT->addModule(std::move(TheModule));
+ InitializeModuleAndPassManager();
+
+ // Search the JIT for the __anon_expr symbol.
+ auto ExprSymbol = TheJIT->findSymbol("__anon_expr");
+ assert(ExprSymbol && "Function not found");
+
+ // Get the symbol's address and cast it to the right type (takes no
+ // arguments, returns a double) so we can call it as a native function.
+ 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);
}
} else {
// Skip token for error recovery.
@@ -1192,7 +1208,6 @@
InitializeNativeTarget();
InitializeNativeTargetAsmPrinter();
InitializeNativeTargetAsmParser();
- LLVMContext &Context = getGlobalContext();
// Install standard binary operators.
// 1 is lowest precedence.
@@ -1206,52 +1221,12 @@
fprintf(stderr, "ready> ");
getNextToken();
- // Make the module, which holds all the code.
- std::unique_ptr<Module> Owner = make_unique<Module>("my cool jit", Context);
- TheModule = Owner.get();
+ TheJIT = llvm::make_unique<KaleidoscopeJIT>();
- // Create the JIT. This takes ownership of the module.
- std::string ErrStr;
- TheExecutionEngine =
- EngineBuilder(std::move(Owner))
- .setErrorStr(&ErrStr)
- .setMCJITMemoryManager(llvm::make_unique<SectionMemoryManager>())
- .create();
- if (!TheExecutionEngine) {
- fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str());
- exit(1);
- }
-
- legacy::FunctionPassManager OurFPM(TheModule);
-
- // Set up the optimizer pipeline. Start with registering info about how the
- // target lays out data structures.
- TheModule->setDataLayout(TheExecutionEngine->getDataLayout());
- // Provide basic AliasAnalysis support for GVN.
- OurFPM.add(createBasicAliasAnalysisPass());
- // Promote allocas to registers.
- OurFPM.add(createPromoteMemoryToRegisterPass());
- // Do simple "peephole" optimizations and bit-twiddling optzns.
- OurFPM.add(createInstructionCombiningPass());
- // Reassociate expressions.
- OurFPM.add(createReassociatePass());
- // Eliminate Common SubExpressions.
- OurFPM.add(createGVNPass());
- // Simplify the control flow graph (deleting unreachable blocks, etc).
- OurFPM.add(createCFGSimplificationPass());
-
- OurFPM.doInitialization();
-
- // Set the global so the code gen can use this.
- TheFPM = &OurFPM;
+ InitializeModuleAndPassManager();
// Run the main "interpreter loop" now.
MainLoop();
- TheFPM = 0;
-
- // Print out all of the generated code.
- TheModule->dump();
-
return 0;
}
diff --git a/llvm/examples/Kaleidoscope/Chapter8/toy.cpp b/llvm/examples/Kaleidoscope/Chapter8/toy.cpp
index b39a5a2..7338c6e 100644
--- a/llvm/examples/Kaleidoscope/Chapter8/toy.cpp
+++ b/llvm/examples/Kaleidoscope/Chapter8/toy.cpp
@@ -1,18 +1,12 @@
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/Triple.h"
+#include "llvm/Analysis/BasicAliasAnalysis.h"
#include "llvm/Analysis/Passes.h"
-#include "llvm/ExecutionEngine/ExecutionEngine.h"
-#include "llvm/ExecutionEngine/MCJIT.h"
-#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/IR/DIBuilder.h"
-#include "llvm/IR/DataLayout.h"
-#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
-#include "llvm/Support/Host.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Transforms/Scalar.h"
#include <cctype>
@@ -20,7 +14,10 @@
#include <map>
#include <string>
#include <vector>
+#include "../include/KaleidoscopeJIT.h"
+
using namespace llvm;
+using namespace llvm::orc;
//===----------------------------------------------------------------------===//
// Lexer
@@ -95,14 +92,11 @@
DICompileUnit *TheCU;
DIType *DblTy;
std::vector<DIScope *> LexicalBlocks;
- std::map<const PrototypeAST *, DIScope *> FnScopeMap;
void emitLocation(ExprAST *AST);
DIType *getDoubleTy();
} KSDbgInfo;
-static std::string IdentifierStr; // Filled in if tok_identifier
-static double NumVal; // Filled in if tok_number
struct SourceLocation {
int Line;
int Col;
@@ -121,6 +115,9 @@
return LastChar;
}
+static std::string IdentifierStr; // Filled in if tok_identifier
+static double NumVal; // Filled in if tok_number
+
/// gettok - Return the next token from standard input.
static int gettok() {
static int LastChar = ' ';
@@ -206,7 +203,7 @@
public:
ExprAST(SourceLocation Loc = CurLoc) : Loc(Loc) {}
virtual ~ExprAST() {}
- virtual Value *Codegen() = 0;
+ virtual Value *codegen() = 0;
int getLine() const { return Loc.Line; }
int getCol() const { return Loc.Col; }
virtual raw_ostream &dump(raw_ostream &out, int ind) {
@@ -223,7 +220,7 @@
raw_ostream &dump(raw_ostream &out, int ind) override {
return ExprAST::dump(out << Val, ind);
}
- Value *Codegen() override;
+ Value *codegen() override;
};
/// VariableExprAST - Expression class for referencing a variable, like "a".
@@ -234,10 +231,10 @@
VariableExprAST(SourceLocation Loc, const std::string &Name)
: ExprAST(Loc), Name(Name) {}
const std::string &getName() const { return Name; }
+ Value *codegen() override;
raw_ostream &dump(raw_ostream &out, int ind) override {
return ExprAST::dump(out << Name, ind);
}
- Value *Codegen() override;
};
/// UnaryExprAST - Expression class for a unary operator.
@@ -248,12 +245,12 @@
public:
UnaryExprAST(char Opcode, std::unique_ptr<ExprAST> Operand)
: Opcode(Opcode), Operand(std::move(Operand)) {}
+ Value *codegen() override;
raw_ostream &dump(raw_ostream &out, int ind) override {
ExprAST::dump(out << "unary" << Opcode, ind);
Operand->dump(out, ind + 1);
return out;
}
- Value *Codegen() override;
};
/// BinaryExprAST - Expression class for a binary operator.
@@ -265,13 +262,13 @@
BinaryExprAST(SourceLocation Loc, char Op, std::unique_ptr<ExprAST> LHS,
std::unique_ptr<ExprAST> RHS)
: ExprAST(Loc), Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {}
+ Value *codegen() override;
raw_ostream &dump(raw_ostream &out, int ind) override {
ExprAST::dump(out << "binary" << Op, ind);
LHS->dump(indent(out, ind) << "LHS:", ind + 1);
RHS->dump(indent(out, ind) << "RHS:", ind + 1);
return out;
}
- Value *Codegen() override;
};
/// CallExprAST - Expression class for function calls.
@@ -283,13 +280,13 @@
CallExprAST(SourceLocation Loc, const std::string &Callee,
std::vector<std::unique_ptr<ExprAST>> Args)
: ExprAST(Loc), Callee(Callee), Args(std::move(Args)) {}
+ Value *codegen() override;
raw_ostream &dump(raw_ostream &out, int ind) override {
ExprAST::dump(out << "call " << Callee, ind);
for (const auto &Arg : Args)
Arg->dump(indent(out, ind + 1), ind + 1);
return out;
}
- Value *Codegen() override;
};
/// IfExprAST - Expression class for if/then/else.
@@ -301,6 +298,7 @@
std::unique_ptr<ExprAST> Then, std::unique_ptr<ExprAST> Else)
: ExprAST(Loc), Cond(std::move(Cond)), Then(std::move(Then)),
Else(std::move(Else)) {}
+ Value *codegen() override;
raw_ostream &dump(raw_ostream &out, int ind) override {
ExprAST::dump(out << "if", ind);
Cond->dump(indent(out, ind) << "Cond:", ind + 1);
@@ -308,7 +306,6 @@
Else->dump(indent(out, ind) << "Else:", ind + 1);
return out;
}
- Value *Codegen() override;
};
/// ForExprAST - Expression class for for/in.
@@ -322,6 +319,7 @@
std::unique_ptr<ExprAST> Body)
: VarName(VarName), Start(std::move(Start)), End(std::move(End)),
Step(std::move(Step)), Body(std::move(Body)) {}
+ Value *codegen() override;
raw_ostream &dump(raw_ostream &out, int ind) override {
ExprAST::dump(out << "for", ind);
Start->dump(indent(out, ind) << "Cond:", ind + 1);
@@ -330,7 +328,6 @@
Body->dump(indent(out, ind) << "Body:", ind + 1);
return out;
}
- Value *Codegen() override;
};
/// VarExprAST - Expression class for var/in
@@ -343,6 +340,7 @@
std::vector<std::pair<std::string, std::unique_ptr<ExprAST>>> VarNames,
std::unique_ptr<ExprAST> Body)
: VarNames(std::move(VarNames)), Body(std::move(Body)) {}
+ Value *codegen() override;
raw_ostream &dump(raw_ostream &out, int ind) override {
ExprAST::dump(out << "var", ind);
for (const auto &NamedVar : VarNames)
@@ -350,7 +348,6 @@
Body->dump(indent(out, ind) << "Body:", ind + 1);
return out;
}
- Value *Codegen() override;
};
/// PrototypeAST - This class represents the "prototype" for a function,
@@ -369,6 +366,8 @@
unsigned Prec = 0)
: Name(Name), Args(std::move(Args)), IsOperator(IsOperator),
Precedence(Prec), Line(Loc.Line) {}
+ Function *codegen();
+ const std::string &getName() const { return Name; }
bool isUnaryOp() const { return IsOperator && Args.size() == 1; }
bool isBinaryOp() const { return IsOperator && Args.size() == 2; }
@@ -379,11 +378,7 @@
}
unsigned getBinaryPrecedence() const { return Precedence; }
-
- Function *Codegen();
-
- void CreateArgumentAllocas(Function *F);
- const std::vector<std::string> &getArgs() const { return Args; }
+ int getLine() const { return Line; }
};
/// FunctionAST - This class represents a function definition itself.
@@ -395,15 +390,13 @@
FunctionAST(std::unique_ptr<PrototypeAST> Proto,
std::unique_ptr<ExprAST> Body)
: Proto(std::move(Proto)), Body(std::move(Body)) {}
-
+ Function *codegen();
raw_ostream &dump(raw_ostream &out, int ind) {
indent(out, ind) << "FunctionAST\n";
++ind;
indent(out, ind) << "Body:";
return Body ? Body->dump(out, ind) : out << "null\n";
}
-
- Function *Codegen();
};
} // end anonymous namespace
@@ -442,10 +435,6 @@
Error(Str);
return nullptr;
}
-std::unique_ptr<FunctionAST> ErrorF(const char *Str) {
- Error(Str);
- return nullptr;
-}
static std::unique_ptr<ExprAST> ParseExpression();
@@ -809,7 +798,7 @@
SourceLocation FnLoc = CurLoc;
if (auto E = ParseExpression()) {
// Make an anonymous proto.
- auto Proto = llvm::make_unique<PrototypeAST>(FnLoc, "main",
+ auto Proto = llvm::make_unique<PrototypeAST>(FnLoc, "__anon_expr",
std::vector<std::string>());
return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E));
}
@@ -826,7 +815,7 @@
// Debug Info Support
//===----------------------------------------------------------------------===//
-static DIBuilder *DBuilder;
+static std::unique_ptr<DIBuilder> DBuilder;
DIType *DebugInfo::getDoubleTy() {
if (DblTy)
@@ -866,15 +855,31 @@
// Code Generation
//===----------------------------------------------------------------------===//
-static Module *TheModule;
+static std::unique_ptr<Module> TheModule;
static std::map<std::string, AllocaInst *> NamedValues;
-static legacy::FunctionPassManager *TheFPM;
+static std::unique_ptr<KaleidoscopeJIT> TheJIT;
+static std::map<std::string, std::unique_ptr<PrototypeAST>> FunctionProtos;
Value *ErrorV(const char *Str) {
Error(Str);
return nullptr;
}
+Function *getFunction(std::string Name) {
+ // First, see if the function has already been added to the current module.
+ if (auto *F = TheModule->getFunction(Name))
+ return F;
+
+ // If not, check whether we can codegen the declaration from some existing
+ // prototype.
+ auto FI = FunctionProtos.find(Name);
+ if (FI != FunctionProtos.end())
+ return FI->second->codegen();
+
+ // If no existing prototype exists, return null.
+ return nullptr;
+}
+
/// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of
/// the function. This is used for mutable variables etc.
static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction,
@@ -885,12 +890,12 @@
VarName.c_str());
}
-Value *NumberExprAST::Codegen() {
+Value *NumberExprAST::codegen() {
KSDbgInfo.emitLocation(this);
return ConstantFP::get(getGlobalContext(), APFloat(Val));
}
-Value *VariableExprAST::Codegen() {
+Value *VariableExprAST::codegen() {
// Look this variable up in the function.
Value *V = NamedValues[Name];
if (!V)
@@ -901,12 +906,12 @@
return Builder.CreateLoad(V, Name.c_str());
}
-Value *UnaryExprAST::Codegen() {
- Value *OperandV = Operand->Codegen();
+Value *UnaryExprAST::codegen() {
+ Value *OperandV = Operand->codegen();
if (!OperandV)
return nullptr;
- Function *F = TheModule->getFunction(std::string("unary") + Opcode);
+ Function *F = getFunction(std::string("unary") + Opcode);
if (!F)
return ErrorV("Unknown unary operator");
@@ -914,7 +919,7 @@
return Builder.CreateCall(F, OperandV, "unop");
}
-Value *BinaryExprAST::Codegen() {
+Value *BinaryExprAST::codegen() {
KSDbgInfo.emitLocation(this);
// Special case '=' because we don't want to emit the LHS as an expression.
@@ -927,7 +932,7 @@
if (!LHSE)
return ErrorV("destination of '=' must be a variable");
// Codegen the RHS.
- Value *Val = RHS->Codegen();
+ Value *Val = RHS->codegen();
if (!Val)
return nullptr;
@@ -940,8 +945,8 @@
return Val;
}
- Value *L = LHS->Codegen();
- Value *R = RHS->Codegen();
+ Value *L = LHS->codegen();
+ Value *R = RHS->codegen();
if (!L || !R)
return nullptr;
@@ -963,18 +968,18 @@
// If it wasn't a builtin binary operator, it must be a user defined one. Emit
// a call to it.
- Function *F = TheModule->getFunction(std::string("binary") + Op);
+ Function *F = getFunction(std::string("binary") + Op);
assert(F && "binary operator not found!");
Value *Ops[] = {L, R};
return Builder.CreateCall(F, Ops, "binop");
}
-Value *CallExprAST::Codegen() {
+Value *CallExprAST::codegen() {
KSDbgInfo.emitLocation(this);
// Look up the name in the global module table.
- Function *CalleeF = TheModule->getFunction(Callee);
+ Function *CalleeF = getFunction(Callee);
if (!CalleeF)
return ErrorV("Unknown function referenced");
@@ -984,7 +989,7 @@
std::vector<Value *> ArgsV;
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
- ArgsV.push_back(Args[i]->Codegen());
+ ArgsV.push_back(Args[i]->codegen());
if (!ArgsV.back())
return nullptr;
}
@@ -992,10 +997,10 @@
return Builder.CreateCall(CalleeF, ArgsV, "calltmp");
}
-Value *IfExprAST::Codegen() {
+Value *IfExprAST::codegen() {
KSDbgInfo.emitLocation(this);
- Value *CondV = Cond->Codegen();
+ Value *CondV = Cond->codegen();
if (!CondV)
return nullptr;
@@ -1017,7 +1022,7 @@
// Emit then value.
Builder.SetInsertPoint(ThenBB);
- Value *ThenV = Then->Codegen();
+ Value *ThenV = Then->codegen();
if (!ThenV)
return nullptr;
@@ -1029,7 +1034,7 @@
TheFunction->getBasicBlockList().push_back(ElseBB);
Builder.SetInsertPoint(ElseBB);
- Value *ElseV = Else->Codegen();
+ Value *ElseV = Else->codegen();
if (!ElseV)
return nullptr;
@@ -1067,7 +1072,7 @@
// store nextvar -> var
// br endcond, loop, endloop
// outloop:
-Value *ForExprAST::Codegen() {
+Value *ForExprAST::codegen() {
Function *TheFunction = Builder.GetInsertBlock()->getParent();
// Create an alloca for the variable in the entry block.
@@ -1076,7 +1081,7 @@
KSDbgInfo.emitLocation(this);
// Emit the start code first, without 'variable' in scope.
- Value *StartVal = Start->Codegen();
+ Value *StartVal = Start->codegen();
if (!StartVal)
return nullptr;
@@ -1102,13 +1107,13 @@
// Emit the body of the loop. This, like any other expr, can change the
// current BB. Note that we ignore the value computed by the body, but don't
// allow an error.
- if (!Body->Codegen())
+ if (!Body->codegen())
return nullptr;
// Emit the step value.
Value *StepVal = nullptr;
if (Step) {
- StepVal = Step->Codegen();
+ StepVal = Step->codegen();
if (!StepVal)
return nullptr;
} else {
@@ -1117,7 +1122,7 @@
}
// Compute the end condition.
- Value *EndCond = End->Codegen();
+ Value *EndCond = End->codegen();
if (!EndCond)
return nullptr;
@@ -1151,7 +1156,7 @@
return Constant::getNullValue(Type::getDoubleTy(getGlobalContext()));
}
-Value *VarExprAST::Codegen() {
+Value *VarExprAST::codegen() {
std::vector<AllocaInst *> OldBindings;
Function *TheFunction = Builder.GetInsertBlock()->getParent();
@@ -1168,7 +1173,7 @@
// var a = a in ... # refers to outer 'a'.
Value *InitVal;
if (Init) {
- InitVal = Init->Codegen();
+ InitVal = Init->codegen();
if (!InitVal)
return nullptr;
} else { // If not specified, use 0.0.
@@ -1189,7 +1194,7 @@
KSDbgInfo.emitLocation(this);
// Codegen the body, now that all vars are in scope.
- Value *BodyVal = Body->Codegen();
+ Value *BodyVal = Body->codegen();
if (!BodyVal)
return nullptr;
@@ -1201,7 +1206,7 @@
return BodyVal;
}
-Function *PrototypeAST::Codegen() {
+Function *PrototypeAST::codegen() {
// Make the function type: double(double,double) etc.
std::vector<Type *> Doubles(Args.size(),
Type::getDoubleTy(getGlobalContext()));
@@ -1209,105 +1214,79 @@
FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false);
Function *F =
- Function::Create(FT, Function::ExternalLinkage, Name, TheModule);
-
- // If F conflicted, there was already something named 'Name'. If it has a
- // body, don't allow redefinition or reextern.
- if (F->getName() != Name) {
- // Delete the one we just made and get the existing one.
- F->eraseFromParent();
- F = TheModule->getFunction(Name);
-
- // If F already has a body, reject this.
- if (!F->empty()) {
- ErrorF("redefinition of function");
- return nullptr;
- }
-
- // If F took a different number of args, reject.
- if (F->arg_size() != Args.size()) {
- ErrorF("redefinition of function with different # args");
- return nullptr;
- }
- }
+ Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get());
// Set names for all arguments.
unsigned Idx = 0;
- for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size();
- ++AI, ++Idx)
- AI->setName(Args[Idx]);
+ for (auto &Arg : F->args())
+ Arg.setName(Args[Idx++]);
+
+ return F;
+}
+
+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;
+
+ // If this is an operator, install it.
+ if (P.isBinaryOp())
+ BinopPrecedence[P.getOperatorName()] = P.getBinaryPrecedence();
+
+ // Create a new basic block to start insertion into.
+ BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
+ Builder.SetInsertPoint(BB);
// Create a subprogram DIE for this function.
DIFile *Unit = DBuilder->createFile(KSDbgInfo.TheCU->getFilename(),
KSDbgInfo.TheCU->getDirectory());
DIScope *FContext = Unit;
- unsigned LineNo = Line;
- unsigned ScopeLine = Line;
+ unsigned LineNo = P.getLine();
+ unsigned ScopeLine = LineNo;
DISubprogram *SP = DBuilder->createFunction(
- FContext, Name, StringRef(), Unit, LineNo,
- CreateFunctionType(Args.size(), Unit), false /* internal linkage */,
- true /* definition */, ScopeLine, DINode::FlagPrototyped, false, F);
-
- KSDbgInfo.FnScopeMap[this] = SP;
- return F;
-}
-
-/// CreateArgumentAllocas - Create an alloca for each argument and register the
-/// argument in the symbol table so that references to it will succeed.
-void PrototypeAST::CreateArgumentAllocas(Function *F) {
- Function::arg_iterator AI = F->arg_begin();
- for (unsigned Idx = 0, e = Args.size(); Idx != e; ++Idx, ++AI) {
- // Create an alloca for this variable.
- AllocaInst *Alloca = CreateEntryBlockAlloca(F, Args[Idx]);
-
- // Create a debug descriptor for the variable.
- DIScope *Scope = KSDbgInfo.LexicalBlocks.back();
- DIFile *Unit = DBuilder->createFile(KSDbgInfo.TheCU->getFilename(),
- KSDbgInfo.TheCU->getDirectory());
- DILocalVariable *D = DBuilder->createParameterVariable(
- Scope, Args[Idx], Idx + 1, Unit, Line, KSDbgInfo.getDoubleTy(), true);
-
- DBuilder->insertDeclare(Alloca, D, DBuilder->createExpression(),
- DebugLoc::get(Line, 0, Scope),
- Builder.GetInsertBlock());
-
- // Store the initial value into the alloca.
- Builder.CreateStore(AI, Alloca);
-
- // Add arguments to variable symbol table.
- NamedValues[Args[Idx]] = Alloca;
- }
-}
-
-Function *FunctionAST::Codegen() {
- NamedValues.clear();
-
- Function *TheFunction = Proto->Codegen();
- if (!TheFunction)
- return nullptr;
+ FContext, P.getName(), StringRef(), Unit, LineNo,
+ CreateFunctionType(TheFunction->arg_size(), Unit),
+ false /* internal linkage */, true /* definition */, ScopeLine,
+ DINode::FlagPrototyped, false, TheFunction);
// Push the current scope.
- KSDbgInfo.LexicalBlocks.push_back(KSDbgInfo.FnScopeMap[Proto.get()]);
+ KSDbgInfo.LexicalBlocks.push_back(SP);
// Unset the location for the prologue emission (leading instructions with no
// location in a function are considered part of the prologue and the debugger
// will run past them when breaking on a function)
KSDbgInfo.emitLocation(nullptr);
- // If this is an operator, install it.
- if (Proto->isBinaryOp())
- BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence();
+ // Record the function arguments in the NamedValues map.
+ NamedValues.clear();
+ unsigned ArgIdx = 0;
+ for (auto &Arg : TheFunction->args()) {
+ // Create an alloca for this variable.
+ AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, Arg.getName());
- // Create a new basic block to start insertion into.
- BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
- Builder.SetInsertPoint(BB);
+ // Create a debug descriptor for the variable.
+ DILocalVariable *D = DBuilder->createParameterVariable(
+ SP, Arg.getName(), ++ArgIdx, Unit, LineNo, KSDbgInfo.getDoubleTy(),
+ true);
- // Add all arguments to the symbol table and create their allocas.
- Proto->CreateArgumentAllocas(TheFunction);
+ DBuilder->insertDeclare(Alloca, D, DBuilder->createExpression(),
+ DebugLoc::get(LineNo, 0, SP),
+ Builder.GetInsertBlock());
+
+ // Store the initial value into the alloca.
+ Builder.CreateStore(&Arg, Alloca);
+
+ // Add arguments to variable symbol table.
+ NamedValues[Arg.getName()] = Alloca;
+ }
KSDbgInfo.emitLocation(Body.get());
- if (Value *RetVal = Body->Codegen()) {
+ if (Value *RetVal = Body->codegen()) {
// Finish off the function.
Builder.CreateRet(RetVal);
@@ -1317,16 +1296,13 @@
// Validate the generated code, checking for consistency.
verifyFunction(*TheFunction);
- // Optimize the function.
- TheFPM->run(*TheFunction);
-
return TheFunction;
}
// Error reading body, remove function.
TheFunction->eraseFromParent();
- if (Proto->isBinaryOp())
+ if (P.isBinaryOp())
BinopPrecedence.erase(Proto->getOperatorName());
// Pop off the lexical block for the function since we added it
@@ -1340,13 +1316,16 @@
// Top-Level parsing and JIT Driver
//===----------------------------------------------------------------------===//
-static ExecutionEngine *TheExecutionEngine;
+static void InitializeModule() {
+ // Open a new module.
+ TheModule = llvm::make_unique<Module>("my cool jit", getGlobalContext());
+ TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout());
+}
static void HandleDefinition() {
if (auto FnAST = ParseDefinition()) {
- if (!FnAST->Codegen()) {
+ if (!FnAST->codegen())
fprintf(stderr, "Error reading function definition:");
- }
} else {
// Skip token for error recovery.
getNextToken();
@@ -1355,9 +1334,10 @@
static void HandleExtern() {
if (auto ProtoAST = ParseExtern()) {
- if (!ProtoAST->Codegen()) {
+ if (!ProtoAST->codegen())
fprintf(stderr, "Error reading extern");
- }
+ else
+ FunctionProtos[ProtoAST->getName()] = std::move(ProtoAST);
} else {
// Skip token for error recovery.
getNextToken();
@@ -1367,7 +1347,7 @@
static void HandleTopLevelExpression() {
// Evaluate a top-level expression into an anonymous function.
if (auto FnAST = ParseTopLevelExpr()) {
- if (!FnAST->Codegen()) {
+ if (!FnAST->codegen()) {
fprintf(stderr, "Error generating code for top level expr");
}
} else {
@@ -1422,7 +1402,6 @@
InitializeNativeTarget();
InitializeNativeTargetAsmPrinter();
InitializeNativeTargetAsmParser();
- LLVMContext &Context = getGlobalContext();
// Install standard binary operators.
// 1 is lowest precedence.
@@ -1435,9 +1414,9 @@
// Prime the first token.
getNextToken();
- // Make the module, which holds all the code.
- std::unique_ptr<Module> Owner = make_unique<Module>("my cool jit", Context);
- TheModule = Owner.get();
+ TheJIT = llvm::make_unique<KaleidoscopeJIT>();
+
+ InitializeModule();
// Add the current debug info version into the module.
TheModule->addModuleFlag(Module::Warning, "Debug Info Version",
@@ -1448,7 +1427,7 @@
TheModule->addModuleFlag(llvm::Module::Warning, "Dwarf Version", 2);
// Construct the DIBuilder, we do this here because we need the module.
- DBuilder = new DIBuilder(*TheModule);
+ DBuilder = llvm::make_unique<DIBuilder>(*TheModule);
// Create the compile unit for the module.
// Currently down as "fib.ks" as a filename since we're redirecting stdin
@@ -1456,47 +1435,9 @@
KSDbgInfo.TheCU = DBuilder->createCompileUnit(
dwarf::DW_LANG_C, "fib.ks", ".", "Kaleidoscope Compiler", 0, "", 0);
- // Create the JIT. This takes ownership of the module.
- std::string ErrStr;
- TheExecutionEngine =
- EngineBuilder(std::move(Owner))
- .setErrorStr(&ErrStr)
- .setMCJITMemoryManager(llvm::make_unique<SectionMemoryManager>())
- .create();
- if (!TheExecutionEngine) {
- fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str());
- exit(1);
- }
-
- legacy::FunctionPassManager OurFPM(TheModule);
-
- // Set up the optimizer pipeline. Start with registering info about how the
- // target lays out data structures.
- TheModule->setDataLayout(TheExecutionEngine->getDataLayout());
-#if 0
- // Provide basic AliasAnalysis support for GVN.
- OurFPM.add(createBasicAliasAnalysisPass());
- // Promote allocas to registers.
- OurFPM.add(createPromoteMemoryToRegisterPass());
- // Do simple "peephole" optimizations and bit-twiddling optzns.
- OurFPM.add(createInstructionCombiningPass());
- // Reassociate expressions.
- OurFPM.add(createReassociatePass());
- // Eliminate Common SubExpressions.
- OurFPM.add(createGVNPass());
- // Simplify the control flow graph (deleting unreachable blocks, etc).
- OurFPM.add(createCFGSimplificationPass());
-#endif
- OurFPM.doInitialization();
-
- // Set the global so the code gen can use this.
- TheFPM = &OurFPM;
-
// Run the main "interpreter loop" now.
MainLoop();
- TheFPM = 0;
-
// Finalize the debug info.
DBuilder->finalize();
diff --git a/llvm/examples/Kaleidoscope/include/KaleidoscopeJIT.h b/llvm/examples/Kaleidoscope/include/KaleidoscopeJIT.h
new file mode 100644
index 0000000..0c825cc
--- /dev/null
+++ b/llvm/examples/Kaleidoscope/include/KaleidoscopeJIT.h
@@ -0,0 +1,114 @@
+//===----- KaleidoscopeJIT.h - A simple JIT for Kaleidoscope ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Contains a simple JIT definition for use in the kaleidoscope tutorials.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H
+#define LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H
+
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
+#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
+#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
+#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
+#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
+#include "llvm/IR/Mangler.h"
+#include "llvm/Support/DynamicLibrary.h"
+
+namespace llvm {
+namespace orc {
+
+class KaleidoscopeJIT {
+public:
+ typedef ObjectLinkingLayer<> ObjLayerT;
+ typedef IRCompileLayer<ObjLayerT> CompileLayerT;
+ typedef CompileLayerT::ModuleSetHandleT ModuleHandleT;
+
+ KaleidoscopeJIT()
+ : TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
+ CompileLayer(ObjectLayer, SimpleCompiler(*TM)) {
+ llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
+ }
+
+ TargetMachine &getTargetMachine() { return *TM; }
+
+ ModuleHandleT addModule(std::unique_ptr<Module> M) {
+ // We need a memory manager to allocate memory and resolve symbols for this
+ // new module. Create one that resolves symbols by looking back into the
+ // JIT.
+ auto Resolver = createLambdaResolver(
+ [&](const std::string &Name) {
+ if (auto Sym = findMangledSymbol(Name))
+ return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags());
+ return RuntimeDyld::SymbolInfo(nullptr);
+ },
+ [](const std::string &S) { return nullptr; });
+ auto H = CompileLayer.addModuleSet(singletonSet(std::move(M)),
+ make_unique<SectionMemoryManager>(),
+ std::move(Resolver));
+
+ ModuleHandles.push_back(H);
+ return H;
+ }
+
+ void removeModule(ModuleHandleT H) {
+ ModuleHandles.erase(
+ std::find(ModuleHandles.begin(), ModuleHandles.end(), H));
+ CompileLayer.removeModuleSet(H);
+ }
+
+ 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;
+ }
+
+ template <typename T> static std::vector<T> singletonSet(T t) {
+ std::vector<T> Vec;
+ Vec.push_back(std::move(t));
+ return Vec;
+ }
+
+ JITSymbol findMangledSymbol(const std::string &Name) {
+ // 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(ModuleHandles.rbegin(), ModuleHandles.rend()))
+ if (auto Sym = CompileLayer.findSymbolIn(H, Name, true))
+ 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);
+
+ return nullptr;
+ }
+
+ std::unique_ptr<TargetMachine> TM;
+ const DataLayout DL;
+ ObjLayerT ObjectLayer;
+ CompileLayerT CompileLayer;
+ std::vector<ModuleHandleT> ModuleHandles;
+};
+
+} // End namespace orc.
+} // End namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H