Function *FunctionAST::Codegen() { NamedValues.clear(); Function *TheFunction = Proto->Codegen(); if (TheFunction == 0) return 0; // If this is an operator, install it. if (Proto->isBinaryOp()) BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); // Create a new basic block to start insertion into. BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); Builder.SetInsertPoint(BB); // Add all arguments to the symbol table and create their allocas. Proto->CreateArgumentAllocas(TheFunction); if (Value *RetVal = Body->Codegen()) { // Finish off the function. Builder.CreateRet(RetVal); // Validate the generated code, checking for consistency. verifyFunction(*TheFunction); return TheFunction; } // Error reading body, remove function. TheFunction->eraseFromParent(); if (Proto->isBinaryOp()) BinopPrecedence.erase(Proto->getOperatorName()); return 0; }
Value *VarExprAST::codegen() { std::vector<AllocaInst *> OldBindings; Function *TheFunction = Builder->GetInsertBlock()->getParent(); // 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.get(); // Emit the initializer before adding the variable to scope, this prevents // the initializer from referencing the variable itself, and permits stuff // like this: // var a = 1 in // var a = a in ... # refers to outer 'a'. Value *InitVal; if (Init) { InitVal = Init->codegen(); if (!InitVal) return nullptr; } else { // If not specified, use 0.0. InitVal = ConstantFP::get(*TheContext, APFloat(0.0)); } AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); Builder->CreateStore(InitVal, Alloca); // Remember the old variable binding so that we can restore the binding when // we unrecurse. OldBindings.push_back(NamedValues[VarName]); // Remember this binding. NamedValues[VarName] = Alloca; } // Codegen the body, now that all vars are in scope. Value *BodyVal = Body->codegen(); if (!BodyVal) return nullptr; // Pop all our variables from scope. for (unsigned i = 0, e = VarNames.size(); i != e; ++i) NamedValues[VarNames[i].first] = OldBindings[i]; // Return the body computation. return BodyVal; }
Value *BinaryExprAST::Codegen() { Value *L = LHS->Codegen(); Value *R = RHS->Codegen(); if (L == 0 || R == 0) return 0; switch (Op) { case '+': return Builder.CreateFAdd(L, R, "addtmp"); case '-': return Builder.CreateFSub(L, R, "subtmp"); case '*': return Builder.CreateFMul(L, R, "multmp"); case '<': L = Builder.CreateFCmpULT(L, R, "cmptmp"); // Convert bool 0/1 to double 0.0 or 1.0 return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), "booltmp"); default: return ErrorV("invalid binary operator"); } }
Value *LetExprAST::Codegen() { AllocaInst * OldBinding; Function *TheFunction = Builder.GetInsertBlock()->getParent(); // Register all variables and emit their initializer. const std::string &VarName = VarNameValue.first; ExprAST *Init = VarNameValue.second; // Emit the initializer before adding the variable to scope, this prevents // the initializer from referencing the variable itself, and permits stuff // like this: // var a = 1 in // var a = a in ... # refers to outer 'a'. Value *InitVal; if (Init) { InitVal = Init->Codegen(); if (InitVal == 0) return 0; } else { // If not specified, use 0.0. InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); } AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); Builder.CreateStore(InitVal, Alloca); // Remember the old variable binding so that we can restore the binding when // we unrecurse. OldBinding = NamedValues[VarName]; // Remember this binding. NamedValues[VarName] = Alloca; // Codegen the body, now that all vars are in scope. Value *BodyVal = Body->Codegen(); if (BodyVal == 0) return 0; // Pop all our variables from scope. NamedValues[VarNameValue.first] = OldBinding; // Return the body computation. return BodyVal; }
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<VariableExprAST*>(LHS); if (!LHSE) return ErrorV("destination of '=' must be a variable"); // Codegen the RHS. Value *Val = RHS->Codegen(); if (Val == 0) return 0; // Look up the name. Value *Variable = NamedValues[LHSE->getName()]; if (Variable == 0) 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; switch (Op) { case '+': return Builder.CreateAdd(L, R, "addtmp"); case '-': return Builder.CreateSub(L, R, "subtmp"); case '*': return Builder.CreateMul(L, R, "multmp"); case '<': L = Builder.CreateFCmpULT(L, R, "cmptmp"); // Convert bool 0/1 to double 0.0 or 1.0 return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), "booltmp"); default: break; } // 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); assert(F && "binary operator not found!"); Value *Ops[] = { L, R }; return Builder.CreateCall(F, Ops, Ops+2, "binop"); }
Value *UnaryExprAST::Codegen() { Value *OperandV = Operand->Codegen(); if (OperandV == 0) return 0; Function *F = TheModule->getFunction(std::string("unary")+Opcode); if (F == 0) return ErrorV("Unknown unary operator"); return Builder.CreateCall(F, OperandV, "unop"); }
Value *UnaryExprAST::Codegen() { Value *OperandV = Operand->Codegen(); if (OperandV == 0) return 0; #ifdef USE_MCJIT Function *F = TheHelper->getFunction(MakeLegalFunctionName(std::string("unary")+Opcode)); #else Function *F = TheModule->getFunction(std::string("unary")+Opcode); #endif if (F == 0) return ErrorV("Unknown unary operator"); return Builder.CreateCall(F, OperandV, "unop"); }
StatementAST* Parser::statement() { switch(this->_tok.type()){ case TokenType::IF: return this->ifstatement(); case TokenType::FOR: return this->forstatement(); case TokenType::WHILE: return this->whilestatement(); case TokenType::REPEAT: return this->repeatstatement(); //AFFECTATION OR EXPRESSION STATEMENTS default: ExprAST* expr = this->expression(); if(!expr) return nullptr; if(this->_tok == TokenType::AFFECT){ //verifie que expr est une variable. if (!expr->isVar()) { Logger::error << this->getErrorHeader() << *expr << this->getErrorHeader() << " is not a variable." << std::endl; exit(EXIT_FAILURE); } // On consumme l'affectation this->eatToken(); ExprAST* affectedExpr = this->expression(); if(!affectedExpr) return nullptr; return new AffectationAST((VariableAST*) expr, affectedExpr); } //sinon l'expression doit se terminer a la fin de la ligne ou du fichier if(this->_tok!=TokenType::ENDF && !this->eatToken(TokenType::ENDL)) return nullptr; return new StatementExprAST(expr); } }
Value *ForExprAST::Codegen() { // Output this as: // ... // start = startexpr // goto loop // loop: // variable = phi [start, loopheader], [nextvariable, loopend] // ... // bodyexpr // ... // loopend: // step = stepexpr // nextvariable = variable + step // endcond = endexpr // br endcond, loop, endloop // outloop: // Emit the start code first, without 'variable' in scope. Value *StartVal = Start->Codegen(); if (StartVal == 0) return 0; // Make the new basic block for the loop header, inserting after current // block. Function *TheFunction = Builder.GetInsertBlock()->getParent(); BasicBlock *PreheaderBB = Builder.GetInsertBlock(); BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); // Insert an explicit fall through from the current block to the LoopBB. Builder.CreateBr(LoopBB); // Start insertion in LoopBB. Builder.SetInsertPoint(LoopBB); // Start the PHI node with an entry for Start. PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), VarName.c_str()); Variable->addIncoming(StartVal, PreheaderBB); // Within the loop, the variable is defined equal to the PHI node. If it // shadows an existing variable, we have to restore it, so save it now. Value *OldVal = NamedValues[VarName]; NamedValues[VarName] = Variable; // 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; // Emit the step value. Value *StepVal; if (Step) { StepVal = Step->Codegen(); if (StepVal == 0) return 0; } else { // If not specified, use 1.0. StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); } Value *NextVar = Builder.CreateAdd(Variable, StepVal, "nextvar"); // Compute the end condition. Value *EndCond = End->Codegen(); if (EndCond == 0) return EndCond; // Convert condition to a bool by comparing equal to 0.0. EndCond = Builder.CreateFCmpONE(EndCond, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "loopcond"); // Create the "after loop" block and insert it. BasicBlock *LoopEndBB = Builder.GetInsertBlock(); BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); // Insert the conditional branch into the end of LoopEndBB. Builder.CreateCondBr(EndCond, LoopBB, AfterBB); // Any new code will be inserted in AfterBB. Builder.SetInsertPoint(AfterBB); // Add a new entry to the PHI node for the backedge. Variable->addIncoming(NextVar, LoopEndBB); // Restore the unshadowed variable. if (OldVal) NamedValues[VarName] = OldVal; else NamedValues.erase(VarName); // for expr always returns 0.0. return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); }
ExprAST* transform_to_lambda_calculus(ExprAST* expr) { switch(expr->getAST_Type()) { //Non-Lambda case ExprAST::Function: { FunctionAST* func = (FunctionAST*)expr; std::cout << "Before Lambda-Calculus Conversion: " << std::endl; func->print(); LambdaAST* lambda; std::vector<PrototypeAST*> protos; if(func->proto->args.size()>0) { for(int i=0;i<func->proto->args.size();++i) { std::vector<std::string> args; args.push_back(func->proto->args.at(i)); PrototypeAST* proto = new PrototypeAST("",args); proto = new PrototypeAST("",args); protos.push_back(proto); } for(int i=protos.size()-1;i>=0;i-=1) { if(i<protos.size()-1) { lambda = new LambdaAST(protos.at(i),lambda); } else { ExprAST* lambda_body = transform_to_lambda_calculus(func->body); lambda = new LambdaAST(protos.at(i),lambda_body); } } } else { std::vector<std::string> args; PrototypeAST* proto = new PrototypeAST("",args); ExprAST* lambda_body = transform_to_lambda_calculus(func->body); lambda = new LambdaAST(proto,lambda_body); } LetAST* let = new LetAST(func->proto->name,lambda); std::cout << "After Lambda-Calculus Conversion: " << std::endl; let->print(); return let; } break; case ExprAST::FunctionCall: { CallExprAST* func_call = (CallExprAST*)expr; std::cout << "Before Lambda-Calculus Conversion: " << std::endl; func_call->print(); std::cout << std::endl; ExprAST* apply = new VariableExprAST(func_call->callee); for(int i=0;i<func_call->args.size();++i) { ExprAST* transformed_arg = transform_to_lambda_calculus(func_call->args.at(i)); apply = new ApplyAST(apply,transformed_arg); } std::cout << "After Lambda-Calculus Conversion: " << std::endl; apply->print(); std::cout << std::endl; return apply; } break; case ExprAST::BinaryOp: { BinaryExprAST* bin_op = (BinaryExprAST*)expr; ExprAST* lhs = transform_to_lambda_calculus(bin_op->lhs); ExprAST* rhs = transform_to_lambda_calculus(bin_op->rhs); return new BinaryExprAST(bin_op->op,lhs,rhs); } case ExprAST::Number: case ExprAST::Char: case ExprAST::True: case ExprAST::False: case ExprAST::Variable: //Lambda case ExprAST::Lambda: case ExprAST::Let: case ExprAST::LetRec: case ExprAST::Apply: return expr; case ExprAST::Prototype: out() << "Error Parsing AST, received PrototypeExprAST in lambda calculus conversion." << std::endl; correct_parsing = false; return expr; } }
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: 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; // Store the value into the alloca. Builder.CreateStore(StartVal, Alloca); // Make the new basic block for the loop header, inserting after current // block. BasicBlock *LoopBB = BasicBlock::Create(TheContext, "loop", TheFunction); // Insert an explicit fall through from the current block to the LoopBB. Builder.CreateBr(LoopBB); // Start insertion in LoopBB. Builder.SetInsertPoint(LoopBB); // Within the loop, the variable is defined equal to the PHI node. If it // shadows an existing variable, we have to restore it, so save it now. AllocaInst *OldVal = NamedValues[VarName]; NamedValues[VarName] = Alloca; // 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; // Emit the step value. Value *StepVal; if (Step) { StepVal = Step->Codegen(); if (StepVal == 0) return 0; } else { // If not specified, use 1.0. StepVal = ConstantFP::get(TheContext, APFloat(1.0)); } // Compute the end condition. Value *EndCond = End->Codegen(); if (EndCond == 0) return EndCond; // Reload, increment, and restore the alloca. This handles the case where // the body of the loop mutates the variable. Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str()); Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar"); Builder.CreateStore(NextVar, Alloca); // Convert condition to a bool by comparing equal to 0.0. EndCond = Builder.CreateFCmpONE( EndCond, ConstantFP::get(TheContext, APFloat(0.0)), "loopcond"); // Create the "after loop" block and insert it. BasicBlock *AfterBB = BasicBlock::Create(TheContext, "afterloop", TheFunction); // Insert the conditional branch into the end of LoopEndBB. Builder.CreateCondBr(EndCond, LoopBB, AfterBB); // Any new code will be inserted in AfterBB. Builder.SetInsertPoint(AfterBB); // Restore the unshadowed variable. if (OldVal) NamedValues[VarName] = OldVal; else NamedValues.erase(VarName); // for expr always returns 0.0. return Constant::getNullValue(Type::getDoubleTy(TheContext)); }
int FAO::Compute() { ExprAST * tree = ParseExpression(); return tree->GetValue(); }