diff options
author | Lang Hames <lhames@gmail.com> | 2015-08-26 03:07:41 +0000 |
---|---|---|
committer | Lang Hames <lhames@gmail.com> | 2015-08-26 03:07:41 +0000 |
commit | 2d789c3699e75b31798fc696c38fcfb3f8d47477 (patch) | |
tree | 36abf050f79f78d374e44ddbe2e8e328f3cc97fc /llvm/examples/Kaleidoscope/Chapter5/toy.cpp | |
parent | 9dc042a0b62c817412a2f0fbddcab7b2f953aec8 (diff) | |
download | bcm5719-llvm-2d789c3699e75b31798fc696c38fcfb3f8d47477.tar.gz bcm5719-llvm-2d789c3699e75b31798fc696c38fcfb3f8d47477.zip |
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
Diffstat (limited to 'llvm/examples/Kaleidoscope/Chapter5/toy.cpp')
-rw-r--r-- | llvm/examples/Kaleidoscope/Chapter5/toy.cpp | 239 |
1 files changed, 113 insertions, 126 deletions
diff --git a/llvm/examples/Kaleidoscope/Chapter5/toy.cpp b/llvm/examples/Kaleidoscope/Chapter5/toy.cpp index da7a81c6776..83af1776b20 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 @@ namespace { 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 @@ class NumberExprAST : public ExprAST { 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 @@ class VariableExprAST : public ExprAST { 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 @@ public: BinaryExprAST(char Op, std::unique_ptr<ExprAST> LHS, std::unique_ptr<ExprAST> RHS) : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} - Value *Codegen() override; + Value *codegen() override; }; /// CallExprAST - Expression class for function calls. @@ -159,7 +157,7 @@ public: 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 @@ public: IfExprAST(std::unique_ptr<ExprAST> Cond, std::unique_ptr<ExprAST> Then, std::unique_ptr<ExprAST> Else) : Cond(std::move(Cond)), Then(std::move(Then)), Else(std::move(Else)) {} - Value *Codegen() override; + Value *codegen() override; }; /// ForExprAST - Expression class for for/in. @@ -184,7 +182,7 @@ public: 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 @@ class PrototypeAST { 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 @@ public: 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 @@ std::unique_ptr<PrototypeAST> ErrorP(const char *Str) { 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> ParseDefinition() { 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 @@ static std::unique_ptr<PrototypeAST> ParseExtern() { // 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 @@ Value *VariableExprAST::Codegen() { 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 *BinaryExprAST::Codegen() { } } -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 @@ Value *CallExprAST::Codegen() { 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 @@ Value *CallExprAST::Codegen() { 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 @@ Value *IfExprAST::Codegen() { // Emit then value. Builder.SetInsertPoint(ThenBB); - Value *ThenV = Then->Codegen(); + Value *ThenV = Then->codegen(); if (!ThenV) return nullptr; @@ -615,7 +627,7 @@ Value *IfExprAST::Codegen() { TheFunction->getBasicBlockList().push_back(ElseBB); Builder.SetInsertPoint(ElseBB); - Value *ElseV = Else->Codegen(); + Value *ElseV = Else->codegen(); if (!ElseV) return nullptr; @@ -649,9 +661,9 @@ Value *IfExprAST::Codegen() { // 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 @@ Value *ForExprAST::Codegen() { // 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 *ForExprAST::Codegen() { 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 @@ Value *ForExprAST::Codegen() { 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 @@ Function *PrototypeAST::Codegen() { 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 @@ Function *FunctionAST::Codegen() { 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 @@ Function *FunctionAST::Codegen() { // 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 HandleDefinition() { 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 HandleExtern() { 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); - - // 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; + if (FnAST->codegen()) { + + // JIT the module containing the anonymous expression, keeping a handle so + // we can free it later. + auto H = TheJIT->addModule(std::move(TheModule)); + 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 @@ int main() { InitializeNativeTarget(); InitializeNativeTargetAsmPrinter(); InitializeNativeTargetAsmParser(); - LLVMContext &Context = getGlobalContext(); // Install standard binary operators. // 1 is lowest precedence. @@ -911,50 +936,12 @@ int main() { 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(); - - // 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); - } + TheJIT = llvm::make_unique<KaleidoscopeJIT>(); - 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; } |