diff options
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; } |