X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=examples%2FKaleidoscope%2FChapter7%2Ftoy.cpp;h=5c0094013d975b11696409b89dc795bba2bd7b89;hb=d16725c31fbb40fcbf0cdf68b2b417ba445c5140;hp=e63738f71fef47fab2c3acb67c72e0c97ca80ce4;hpb=6efccd025c94f94bd7a32f0e721305a73fb76c84;p=oota-llvm.git diff --git a/examples/Kaleidoscope/Chapter7/toy.cpp b/examples/Kaleidoscope/Chapter7/toy.cpp index e63738f71fe..5c0094013d9 100644 --- a/examples/Kaleidoscope/Chapter7/toy.cpp +++ b/examples/Kaleidoscope/Chapter7/toy.cpp @@ -1,14 +1,10 @@ +#include "llvm/ADT/STLExtras.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" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" -#include "llvm/PassManager.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Transforms/Scalar.h" #include @@ -16,7 +12,10 @@ #include #include #include +#include "../include/KaleidoscopeJIT.h" + using namespace llvm; +using namespace llvm::orc; //===----------------------------------------------------------------------===// // Lexer @@ -96,7 +95,7 @@ static int gettok() { LastChar = getchar(); } while (isdigit(LastChar) || LastChar == '.'); - NumVal = strtod(NumStr.c_str(), 0); + NumVal = strtod(NumStr.c_str(), nullptr); return tok_number; } @@ -128,7 +127,7 @@ namespace { class ExprAST { public: virtual ~ExprAST() {} - virtual Value *Codegen() = 0; + virtual Value *codegen() = 0; }; /// NumberExprAST - Expression class for numeric literals like "1.0". @@ -136,8 +135,8 @@ class NumberExprAST : public ExprAST { double Val; public: - NumberExprAST(double val) : Val(val) {} - virtual Value *Codegen(); + NumberExprAST(double Val) : Val(Val) {} + Value *codegen() override; }; /// VariableExprAST - Expression class for referencing a variable, like "a". @@ -145,93 +144,103 @@ class VariableExprAST : public ExprAST { std::string Name; public: - VariableExprAST(const std::string &name) : Name(name) {} + VariableExprAST(const std::string &Name) : Name(Name) {} const std::string &getName() const { return Name; } - virtual Value *Codegen(); + Value *codegen() override; }; /// UnaryExprAST - Expression class for a unary operator. class UnaryExprAST : public ExprAST { char Opcode; - ExprAST *Operand; + std::unique_ptr Operand; public: - UnaryExprAST(char opcode, ExprAST *operand) - : Opcode(opcode), Operand(operand) {} - virtual Value *Codegen(); + UnaryExprAST(char Opcode, std::unique_ptr Operand) + : Opcode(Opcode), Operand(std::move(Operand)) {} + Value *codegen() override; }; /// BinaryExprAST - Expression class for a binary operator. class BinaryExprAST : public ExprAST { char Op; - ExprAST *LHS, *RHS; + std::unique_ptr LHS, RHS; public: - BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) - : Op(op), LHS(lhs), RHS(rhs) {} - virtual Value *Codegen(); + BinaryExprAST(char Op, std::unique_ptr LHS, + std::unique_ptr RHS) + : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} + Value *codegen() override; }; /// CallExprAST - Expression class for function calls. class CallExprAST : public ExprAST { std::string Callee; - std::vector Args; + std::vector> Args; public: - CallExprAST(const std::string &callee, std::vector &args) - : Callee(callee), Args(args) {} - virtual Value *Codegen(); + CallExprAST(const std::string &Callee, + std::vector> Args) + : Callee(Callee), Args(std::move(Args)) {} + Value *codegen() override; }; /// IfExprAST - Expression class for if/then/else. class IfExprAST : public ExprAST { - ExprAST *Cond, *Then, *Else; + std::unique_ptr Cond, Then, Else; public: - IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else) - : Cond(cond), Then(then), Else(_else) {} - virtual Value *Codegen(); + IfExprAST(std::unique_ptr Cond, std::unique_ptr Then, + std::unique_ptr Else) + : Cond(std::move(Cond)), Then(std::move(Then)), Else(std::move(Else)) {} + Value *codegen() override; }; /// ForExprAST - Expression class for for/in. class ForExprAST : public ExprAST { std::string VarName; - ExprAST *Start, *End, *Step, *Body; + std::unique_ptr Start, End, Step, Body; public: - ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end, - ExprAST *step, ExprAST *body) - : VarName(varname), Start(start), End(end), Step(step), Body(body) {} - virtual Value *Codegen(); + ForExprAST(const std::string &VarName, std::unique_ptr Start, + std::unique_ptr End, std::unique_ptr Step, + std::unique_ptr Body) + : VarName(VarName), Start(std::move(Start)), End(std::move(End)), + Step(std::move(Step)), Body(std::move(Body)) {} + Value *codegen() override; }; /// VarExprAST - Expression class for var/in class VarExprAST : public ExprAST { - std::vector > VarNames; - ExprAST *Body; + std::vector>> VarNames; + std::unique_ptr Body; public: - VarExprAST(const std::vector > &varnames, - ExprAST *body) - : VarNames(varnames), Body(body) {} - - virtual Value *Codegen(); + VarExprAST( + std::vector>> VarNames, + std::unique_ptr Body) + : VarNames(std::move(VarNames)), Body(std::move(Body)) {} + Value *codegen() override; }; /// PrototypeAST - This class represents the "prototype" for a function, -/// which captures its argument names as well as if it is an operator. +/// which captures its name, and its argument names (thus implicitly the number +/// of arguments the function takes), as well as if it is an operator. class PrototypeAST { std::string Name; std::vector Args; - bool isOperator; + bool IsOperator; unsigned Precedence; // Precedence if a binary op. + public: - PrototypeAST(const std::string &name, const std::vector &args, - bool isoperator = false, unsigned prec = 0) - : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {} + PrototypeAST(const std::string &Name, std::vector Args, + 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; } + bool isUnaryOp() const { return IsOperator && Args.size() == 1; } + bool isBinaryOp() const { return IsOperator && Args.size() == 2; } char getOperatorName() const { assert(isUnaryOp() || isBinaryOp()); @@ -239,21 +248,18 @@ public: } unsigned getBinaryPrecedence() const { return Precedence; } - - Function *Codegen(); - - void CreateArgumentAllocas(Function *F); }; /// FunctionAST - This class represents a function definition itself. class FunctionAST { - PrototypeAST *Proto; - ExprAST *Body; + std::unique_ptr Proto; + std::unique_ptr Body; public: - FunctionAST(PrototypeAST *proto, ExprAST *body) : Proto(proto), Body(body) {} - - Function *Codegen(); + FunctionAST(std::unique_ptr Proto, + std::unique_ptr Body) + : Proto(std::move(Proto)), Body(std::move(Body)) {} + Function *codegen(); }; } // end anonymous namespace @@ -284,41 +290,58 @@ static int GetTokPrecedence() { } /// Error* - These are little helper functions for error handling. -ExprAST *Error(const char *Str) { +std::unique_ptr Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str); - return 0; + return nullptr; } -PrototypeAST *ErrorP(const char *Str) { + +std::unique_ptr ErrorP(const char *Str) { Error(Str); - return 0; + return nullptr; } -FunctionAST *ErrorF(const char *Str) { - Error(Str); - return 0; + +static std::unique_ptr ParseExpression(); + +/// numberexpr ::= number +static std::unique_ptr ParseNumberExpr() { + auto Result = llvm::make_unique(NumVal); + getNextToken(); // consume the number + return std::move(Result); } -static ExprAST *ParseExpression(); +/// parenexpr ::= '(' expression ')' +static std::unique_ptr ParseParenExpr() { + getNextToken(); // eat (. + auto V = ParseExpression(); + if (!V) + return nullptr; + + if (CurTok != ')') + return Error("expected ')'"); + getNextToken(); // eat ). + return V; +} /// identifierexpr /// ::= identifier /// ::= identifier '(' expression* ')' -static ExprAST *ParseIdentifierExpr() { +static std::unique_ptr ParseIdentifierExpr() { std::string IdName = IdentifierStr; getNextToken(); // eat identifier. if (CurTok != '(') // Simple variable ref. - return new VariableExprAST(IdName); + return llvm::make_unique(IdName); // Call. getNextToken(); // eat ( - std::vector Args; + std::vector> Args; if (CurTok != ')') { while (1) { - ExprAST *Arg = ParseExpression(); - if (!Arg) - return 0; - Args.push_back(Arg); + if (auto Arg = ParseExpression()) + Args.push_back(std::move(Arg)); + else + return nullptr; if (CurTok == ')') break; @@ -332,60 +355,41 @@ static ExprAST *ParseIdentifierExpr() { // Eat the ')'. getNextToken(); - return new CallExprAST(IdName, Args); -} - -/// numberexpr ::= number -static ExprAST *ParseNumberExpr() { - ExprAST *Result = new NumberExprAST(NumVal); - getNextToken(); // consume the number - return Result; -} - -/// parenexpr ::= '(' expression ')' -static ExprAST *ParseParenExpr() { - getNextToken(); // eat (. - ExprAST *V = ParseExpression(); - if (!V) - return 0; - - if (CurTok != ')') - return Error("expected ')'"); - getNextToken(); // eat ). - return V; + return llvm::make_unique(IdName, std::move(Args)); } /// ifexpr ::= 'if' expression 'then' expression 'else' expression -static ExprAST *ParseIfExpr() { +static std::unique_ptr ParseIfExpr() { getNextToken(); // eat the if. // condition. - ExprAST *Cond = ParseExpression(); + auto Cond = ParseExpression(); if (!Cond) - return 0; + return nullptr; if (CurTok != tok_then) return Error("expected then"); getNextToken(); // eat the then - ExprAST *Then = ParseExpression(); - if (Then == 0) - return 0; + auto Then = ParseExpression(); + if (!Then) + return nullptr; if (CurTok != tok_else) return Error("expected else"); getNextToken(); - ExprAST *Else = ParseExpression(); + auto Else = ParseExpression(); if (!Else) - return 0; + return nullptr; - return new IfExprAST(Cond, Then, Else); + return llvm::make_unique(std::move(Cond), std::move(Then), + std::move(Else)); } /// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression -static ExprAST *ParseForExpr() { +static std::unique_ptr ParseForExpr() { getNextToken(); // eat the for. if (CurTok != tok_identifier) @@ -398,43 +402,44 @@ static ExprAST *ParseForExpr() { return Error("expected '=' after for"); getNextToken(); // eat '='. - ExprAST *Start = ParseExpression(); - if (Start == 0) - return 0; + auto Start = ParseExpression(); + if (!Start) + return nullptr; if (CurTok != ',') return Error("expected ',' after for start value"); getNextToken(); - ExprAST *End = ParseExpression(); - if (End == 0) - return 0; + auto End = ParseExpression(); + if (!End) + return nullptr; // The step value is optional. - ExprAST *Step = 0; + std::unique_ptr Step; if (CurTok == ',') { getNextToken(); Step = ParseExpression(); - if (Step == 0) - return 0; + if (!Step) + return nullptr; } if (CurTok != tok_in) return Error("expected 'in' after for"); getNextToken(); // eat 'in'. - ExprAST *Body = ParseExpression(); - if (Body == 0) - return 0; + auto Body = ParseExpression(); + if (!Body) + return nullptr; - return new ForExprAST(IdName, Start, End, Step, Body); + return llvm::make_unique(IdName, std::move(Start), std::move(End), + std::move(Step), std::move(Body)); } /// varexpr ::= 'var' identifier ('=' expression)? // (',' identifier ('=' expression)?)* 'in' expression -static ExprAST *ParseVarExpr() { +static std::unique_ptr ParseVarExpr() { getNextToken(); // eat the var. - std::vector > VarNames; + std::vector>> VarNames; // At least one variable name is required. if (CurTok != tok_identifier) @@ -445,16 +450,16 @@ static ExprAST *ParseVarExpr() { getNextToken(); // eat identifier. // Read the optional initializer. - ExprAST *Init = 0; + std::unique_ptr Init = nullptr; if (CurTok == '=') { getNextToken(); // eat the '='. Init = ParseExpression(); - if (Init == 0) - return 0; + if (!Init) + return nullptr; } - VarNames.push_back(std::make_pair(Name, Init)); + VarNames.push_back(std::make_pair(Name, std::move(Init))); // End of var list, exit loop. if (CurTok != ',') @@ -470,11 +475,11 @@ static ExprAST *ParseVarExpr() { return Error("expected 'in' keyword after 'var'"); getNextToken(); // eat 'in'. - ExprAST *Body = ParseExpression(); - if (Body == 0) - return 0; + auto Body = ParseExpression(); + if (!Body) + return nullptr; - return new VarExprAST(VarNames, Body); + return llvm::make_unique(std::move(VarNames), std::move(Body)); } /// primary @@ -484,7 +489,7 @@ static ExprAST *ParseVarExpr() { /// ::= ifexpr /// ::= forexpr /// ::= varexpr -static ExprAST *ParsePrimary() { +static std::unique_ptr ParsePrimary() { switch (CurTok) { default: return Error("unknown token when expecting an expression"); @@ -506,7 +511,7 @@ static ExprAST *ParsePrimary() { /// unary /// ::= primary /// ::= '!' unary -static ExprAST *ParseUnary() { +static std::unique_ptr ParseUnary() { // If the current token is not an operator, it must be a primary expr. if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') return ParsePrimary(); @@ -514,14 +519,15 @@ static ExprAST *ParseUnary() { // If this is a unary operator, read it. int Opc = CurTok; getNextToken(); - if (ExprAST *Operand = ParseUnary()) - return new UnaryExprAST(Opc, Operand); - return 0; + if (auto Operand = ParseUnary()) + return llvm::make_unique(Opc, std::move(Operand)); + return nullptr; } /// binoprhs /// ::= ('+' unary)* -static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { +static std::unique_ptr ParseBinOpRHS(int ExprPrec, + std::unique_ptr LHS) { // If this is a binop, find its precedence. while (1) { int TokPrec = GetTokPrecedence(); @@ -536,40 +542,41 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { getNextToken(); // eat binop // Parse the unary expression after the binary operator. - ExprAST *RHS = ParseUnary(); + auto RHS = ParseUnary(); if (!RHS) - return 0; + return nullptr; // If BinOp binds less tightly with RHS than the operator after RHS, let // the pending operator take RHS as its LHS. int NextPrec = GetTokPrecedence(); if (TokPrec < NextPrec) { - RHS = ParseBinOpRHS(TokPrec + 1, RHS); - if (RHS == 0) - return 0; + RHS = ParseBinOpRHS(TokPrec + 1, std::move(RHS)); + if (!RHS) + return nullptr; } // Merge LHS/RHS. - LHS = new BinaryExprAST(BinOp, LHS, RHS); + LHS = + llvm::make_unique(BinOp, std::move(LHS), std::move(RHS)); } } /// expression /// ::= unary binoprhs /// -static ExprAST *ParseExpression() { - ExprAST *LHS = ParseUnary(); +static std::unique_ptr ParseExpression() { + auto LHS = ParseUnary(); if (!LHS) - return 0; + return nullptr; - return ParseBinOpRHS(0, LHS); + return ParseBinOpRHS(0, std::move(LHS)); } /// prototype /// ::= id '(' id* ')' /// ::= binary LETTER number? (id, id) /// ::= unary LETTER (id) -static PrototypeAST *ParsePrototype() { +static std::unique_ptr ParsePrototype() { std::string FnName; unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. @@ -627,33 +634,35 @@ static PrototypeAST *ParsePrototype() { if (Kind && ArgNames.size() != Kind) return ErrorP("Invalid number of operands for operator"); - return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence); + return llvm::make_unique(FnName, ArgNames, Kind != 0, + BinaryPrecedence); } /// definition ::= 'def' prototype expression -static FunctionAST *ParseDefinition() { +static std::unique_ptr ParseDefinition() { getNextToken(); // eat def. - PrototypeAST *Proto = ParsePrototype(); - if (Proto == 0) - return 0; + auto Proto = ParsePrototype(); + if (!Proto) + return nullptr; - if (ExprAST *E = ParseExpression()) - return new FunctionAST(Proto, E); - return 0; + if (auto E = ParseExpression()) + return llvm::make_unique(std::move(Proto), std::move(E)); + return nullptr; } /// toplevelexpr ::= expression -static FunctionAST *ParseTopLevelExpr() { - if (ExprAST *E = ParseExpression()) { +static std::unique_ptr ParseTopLevelExpr() { + if (auto E = ParseExpression()) { // Make an anonymous proto. - PrototypeAST *Proto = new PrototypeAST("", std::vector()); - return new FunctionAST(Proto, E); + auto Proto = llvm::make_unique("__anon_expr", + std::vector()); + return llvm::make_unique(std::move(Proto), std::move(E)); } - return 0; + return nullptr; } /// external ::= 'extern' prototype -static PrototypeAST *ParseExtern() { +static std::unique_ptr ParseExtern() { getNextToken(); // eat extern. return ParsePrototype(); } @@ -662,14 +671,31 @@ static PrototypeAST *ParseExtern() { // Code Generation //===----------------------------------------------------------------------===// -static Module *TheModule; +static std::unique_ptr TheModule; static IRBuilder<> Builder(getGlobalContext()); static std::map NamedValues; -static FunctionPassManager *TheFPM; +static std::unique_ptr TheFPM; +static std::unique_ptr TheJIT; +static std::map> FunctionProtos; Value *ErrorV(const char *Str) { Error(Str); - return 0; + 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 @@ -678,61 +704,64 @@ static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, const std::string &VarName) { IRBuilder<> TmpB(&TheFunction->getEntryBlock(), TheFunction->getEntryBlock().begin()); - return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0, + return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), nullptr, 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 == 0) + if (!V) return ErrorV("Unknown variable name"); // Load the value. return Builder.CreateLoad(V, Name.c_str()); } -Value *UnaryExprAST::Codegen() { - Value *OperandV = Operand->Codegen(); - if (OperandV == 0) - return 0; +Value *UnaryExprAST::codegen() { + Value *OperandV = Operand->codegen(); + if (!OperandV) + return nullptr; - Function *F = TheModule->getFunction(std::string("unary") + Opcode); - if (F == 0) + 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. - VariableExprAST *LHSE = dynamic_cast(LHS); + // This assume we're building without RTTI because LLVM builds that way by + // default. If you build LLVM with RTTI this can be changed to a + // dynamic_cast for automatic error checking. + VariableExprAST *LHSE = static_cast(LHS.get()); if (!LHSE) return ErrorV("destination of '=' must be a variable"); // Codegen the RHS. - Value *Val = RHS->Codegen(); - if (Val == 0) - return 0; + Value *Val = RHS->codegen(); + if (!Val) + return nullptr; // Look up the name. Value *Variable = NamedValues[LHSE->getName()]; - if (Variable == 0) + if (!Variable) return ErrorV("Unknown variable name"); Builder.CreateStore(Val, Variable); return Val; } - Value *L = LHS->Codegen(); - Value *R = RHS->Codegen(); - if (L == 0 || R == 0) - return 0; + Value *L = LHS->codegen(); + Value *R = RHS->codegen(); + if (!L || !R) + return nullptr; switch (Op) { case '+': @@ -752,17 +781,17 @@ Value *BinaryExprAST::Codegen() { // 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 }; + 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); - if (CalleeF == 0) + Function *CalleeF = getFunction(Callee); + if (!CalleeF) return ErrorV("Unknown function referenced"); // If argument mismatch error. @@ -771,18 +800,18 @@ Value *CallExprAST::Codegen() { std::vector ArgsV; for (unsigned i = 0, e = Args.size(); i != e; ++i) { - ArgsV.push_back(Args[i]->Codegen()); - if (ArgsV.back() == 0) - return 0; + ArgsV.push_back(Args[i]->codegen()); + if (!ArgsV.back()) + return nullptr; } return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); } -Value *IfExprAST::Codegen() { - Value *CondV = Cond->Codegen(); - if (CondV == 0) - return 0; +Value *IfExprAST::codegen() { + Value *CondV = Cond->codegen(); + if (!CondV) + return nullptr; // Convert condition to a bool by comparing equal to 0.0. CondV = Builder.CreateFCmpONE( @@ -802,9 +831,9 @@ Value *IfExprAST::Codegen() { // Emit then value. Builder.SetInsertPoint(ThenBB); - Value *ThenV = Then->Codegen(); - if (ThenV == 0) - return 0; + Value *ThenV = Then->codegen(); + if (!ThenV) + return nullptr; Builder.CreateBr(MergeBB); // Codegen of 'Then' can change the current block, update ThenBB for the PHI. @@ -814,9 +843,9 @@ Value *IfExprAST::Codegen() { TheFunction->getBasicBlockList().push_back(ElseBB); Builder.SetInsertPoint(ElseBB); - Value *ElseV = Else->Codegen(); - if (ElseV == 0) - return 0; + Value *ElseV = Else->codegen(); + if (!ElseV) + return nullptr; Builder.CreateBr(MergeBB); // Codegen of 'Else' can change the current block, update ElseBB for the PHI. @@ -833,36 +862,35 @@ Value *IfExprAST::Codegen() { return PN; } -Value *ForExprAST::Codegen() { - // Output this as: - // var = alloca double - // ... - // start = startexpr - // store start -> var - // goto loop - // loop: - // ... - // bodyexpr - // ... - // loopend: - // step = stepexpr - // endcond = endexpr - // - // curvar = load var - // nextvar = curvar + step - // store nextvar -> var - // br endcond, loop, endloop - // outloop: - +// Output for-loop as: +// var = alloca double +// ... +// start = startexpr +// store start -> var +// goto loop +// loop: +// ... +// bodyexpr +// ... +// loopend: +// step = stepexpr +// endcond = endexpr +// +// curvar = load var +// nextvar = curvar + step +// store nextvar -> var +// br endcond, loop, endloop +// outloop: +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(); - if (StartVal == 0) - return 0; + Value *StartVal = Start->codegen(); + if (!StartVal) + return nullptr; // Store the value into the alloca. Builder.CreateStore(StartVal, Alloca); @@ -886,24 +914,24 @@ 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() == 0) - return 0; + if (!Body->codegen()) + return nullptr; // Emit the step value. - Value *StepVal; + Value *StepVal = nullptr; if (Step) { - StepVal = Step->Codegen(); - if (StepVal == 0) - return 0; + StepVal = Step->codegen(); + if (!StepVal) + return nullptr; } else { // If not specified, use 1.0. StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); } // Compute the end condition. - Value *EndCond = End->Codegen(); - if (EndCond == 0) - return EndCond; + Value *EndCond = End->codegen(); + if (!EndCond) + return nullptr; // Reload, increment, and restore the alloca. This handles the case where // the body of the loop mutates the variable. @@ -935,7 +963,7 @@ Value *ForExprAST::Codegen() { return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); } -Value *VarExprAST::Codegen() { +Value *VarExprAST::codegen() { std::vector OldBindings; Function *TheFunction = Builder.GetInsertBlock()->getParent(); @@ -943,7 +971,7 @@ Value *VarExprAST::Codegen() { // Register all variables and emit their initializer. for (unsigned i = 0, e = VarNames.size(); i != e; ++i) { const std::string &VarName = VarNames[i].first; - ExprAST *Init = VarNames[i].second; + ExprAST *Init = VarNames[i].second.get(); // Emit the initializer before adding the variable to scope, this prevents // the initializer from referencing the variable itself, and permits stuff @@ -952,9 +980,9 @@ Value *VarExprAST::Codegen() { // var a = a in ... # refers to outer 'a'. Value *InitVal; if (Init) { - InitVal = Init->Codegen(); - if (InitVal == 0) - return 0; + InitVal = Init->codegen(); + if (!InitVal) + return nullptr; } else { // If not specified, use 0.0. InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); } @@ -971,9 +999,9 @@ Value *VarExprAST::Codegen() { } // Codegen the body, now that all vars are in scope. - Value *BodyVal = Body->Codegen(); - if (BodyVal == 0) - return 0; + Value *BodyVal = Body->codegen(); + if (!BodyVal) + return nullptr; // Pop all our variables from scope. for (unsigned i = 0, e = VarNames.size(); i != e; ++i) @@ -983,7 +1011,7 @@ Value *VarExprAST::Codegen() { return BodyVal; } -Function *PrototypeAST::Codegen() { +Function *PrototypeAST::codegen() { // Make the function type: double(double,double) etc. std::vector Doubles(Args.size(), Type::getDoubleTy(getGlobalContext())); @@ -991,79 +1019,54 @@ 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 0; - } - - // If F took a different number of args, reject. - if (F->arg_size() != Args.size()) { - ErrorF("redefinition of function with different # args"); - return 0; - } - } + 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(); - if (TheFunction == 0) - return 0; +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()); + + // 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()) { + 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; @@ -1072,22 +1075,42 @@ Function *FunctionAST::Codegen() { // Error reading body, remove function. TheFunction->eraseFromParent(); - if (Proto->isBinaryOp()) + if (P.isBinaryOp()) BinopPrecedence.erase(Proto->getOperatorName()); - return 0; + return nullptr; } //===----------------------------------------------------------------------===// // Top-Level parsing and JIT Driver //===----------------------------------------------------------------------===// -static ExecutionEngine *TheExecutionEngine; +static void InitializeModuleAndPassManager() { + // Open a new module. + TheModule = llvm::make_unique("my cool jit", getGlobalContext()); + TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout()); + + // Create a new pass manager attached to it. + TheFPM = llvm::make_unique(TheModule.get()); + + // 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 (FunctionAST *F = ParseDefinition()) { - if (Function *LF = F->Codegen()) { + if (auto FnAST = ParseDefinition()) { + if (auto *FnIR = FnAST->codegen()) { fprintf(stderr, "Read function definition:"); - LF->dump(); + FnIR->dump(); + TheJIT->addModule(std::move(TheModule)); + InitializeModuleAndPassManager(); } } else { // Skip token for error recovery. @@ -1096,10 +1119,11 @@ static void HandleDefinition() { } static void HandleExtern() { - if (PrototypeAST *P = ParseExtern()) { - if (Function *F = P->Codegen()) { + if (auto ProtoAST = ParseExtern()) { + if (auto *FnIR = ProtoAST->codegen()) { fprintf(stderr, "Read extern: "); - F->dump(); + FnIR->dump(); + FunctionProtos[ProtoAST->getName()] = std::move(ProtoAST); } } else { // Skip token for error recovery. @@ -1109,16 +1133,25 @@ static void HandleExtern() { static void HandleTopLevelExpression() { // Evaluate a top-level expression into an anonymous function. - if (FunctionAST *F = ParseTopLevelExpr()) { - if (Function *LF = F->Codegen()) { - TheExecutionEngine->finalizeObject(); - // JIT the function, returning a function pointer. - void *FPtr = TheExecutionEngine->getPointerToFunction(LF); - - // 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 (auto FnAST = ParseTopLevelExpr()) { + if (FnAST->codegen()) { + + // JIT the module containing the anonymous expression, keeping a handle so + // we can free it later. + auto H = TheJIT->addModule(std::move(TheModule)); + 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. @@ -1133,9 +1166,9 @@ static void MainLoop() { switch (CurTok) { case tok_eof: return; - case ';': + case ';': // ignore top-level semicolons. getNextToken(); - break; // ignore top-level semicolons. + break; case tok_def: HandleDefinition(); break; @@ -1155,13 +1188,13 @@ static void MainLoop() { /// putchard - putchar that takes a double and returns 0. extern "C" double putchard(double X) { - putchar((char)X); + fputc((char)X, stderr); return 0; } /// printd - printf that takes a double prints it as "%f\n", returning 0. extern "C" double printd(double X) { - printf("%f\n", X); + fprintf(stderr, "%f\n", X); return 0; } @@ -1173,7 +1206,6 @@ int main() { InitializeNativeTarget(); InitializeNativeTargetAsmPrinter(); InitializeNativeTargetAsmParser(); - LLVMContext &Context = getGlobalContext(); // Install standard binary operators. // 1 is lowest precedence. @@ -1187,53 +1219,12 @@ int main() { fprintf(stderr, "ready> "); getNextToken(); - // Make the module, which holds all the code. - std::unique_ptr Owner = make_unique("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()) - .create(); - if (!TheExecutionEngine) { - fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); - exit(1); - } + TheJIT = llvm::make_unique(); - FunctionPassManager OurFPM(TheModule); - - // Set up the optimizer pipeline. Start with registering info about how the - // target lays out data structures. - TheModule->setDataLayout(TheExecutionEngine->getDataLayout()); - OurFPM.add(new DataLayoutPass()); - // 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; }