X-Git-Url: http://git.lukelau.me/?p=kaleidoscope.git;a=blobdiff_plain;f=Kaleidoscope%2Fcodegen.cpp;h=e9e1d2422e795c95b57d22bcaf9c0bd2fcead1c5;hp=c185a3e0c699f4445a0435c494953c13c8a19343;hb=ca0890e5fc8e5abbb1edd253e66c6c273e7756c0;hpb=5f81038886345b9c1e130bc7cfdd463e76b37b84 diff --git a/Kaleidoscope/codegen.cpp b/Kaleidoscope/codegen.cpp index c185a3e..e9e1d24 100644 --- a/Kaleidoscope/codegen.cpp +++ b/Kaleidoscope/codegen.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include "ast.hpp" @@ -43,10 +42,6 @@ void InitializeModuleAndPassManager(void) { TheFPM->addPass(GVNSinkPass()); } -void PrintModule() { - TheModule->print(errs(), nullptr); -} - std::map> functionProtos; Function *getFunction(std::string name) { @@ -60,8 +55,8 @@ Function *getFunction(std::string name) { return nullptr; } -Value *LogErrorV(const char *Str) { - LogError(Str); +Value *LogErrorV(std::string str) { + LogError(str); return nullptr; } @@ -93,9 +88,23 @@ Value *BinaryExprAST::codegen() { L = Builder.CreateFCmpULT(L, R, "cmptmp"); // convert bool 0/1 to double 0.0/1.0 return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); + case '>': + L = Builder.CreateFCmpUGT(L, R, "cmptmp"); + return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); + case '|': + L = Builder.CreateFCmpUGE(L, ConstantFP::get(TheContext, APFloat(1.0)), "leftbooltmp"); + R = Builder.CreateFCmpUGE(R, ConstantFP::get(TheContext, APFloat(1.0)), "leftbooltmp"); + L = Builder.CreateOr(L, R, "orbooltmp"); + return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "ortmp"); default: - return LogErrorV("Invalid binary operator"); + break; } + + Function *F = getFunction(std::string("binary") + Op); + assert(F && "binary oprator not found!"); + + Value *Ops[2] = {L, R}; + return Builder.CreateCall(F, Ops, "binop"); } Value *CallExprAST::codegen() { @@ -137,6 +146,9 @@ Function *FunctionAST::codegen() { if (!func) return nullptr; + if (P.isBinaryOp()) + BinopPrecedence[P.getOperatorName()] = P.getBinaryPrecedence(); + BasicBlock *bb = BasicBlock::Create(TheContext, "entry", func); Builder.SetInsertPoint(bb); @@ -146,7 +158,13 @@ Function *FunctionAST::codegen() { if (Value *retVal = Body->codegen()) { Builder.CreateRet(retVal); - verifyFunction(*func); + + if (verifyFunction(*func, &errs())) { + func->print(errs()); + func->eraseFromParent(); + return nullptr; + } + TheFPM->run(*func, *TheFAM); return func; } @@ -154,3 +172,102 @@ Function *FunctionAST::codegen() { func->eraseFromParent(); return nullptr; } + +Value *IfExprAST::codegen() { + Value *condV = Cond->codegen(); + if (!condV) return nullptr; + + //convert to bool + condV = Builder.CreateFCmpONE(condV, ConstantFP::get(TheContext, APFloat(0.0)), "ifcond"); + + Function *func = Builder.GetInsertBlock()->getParent(); + + BasicBlock *thenBB = BasicBlock::Create(TheContext, "then", func); + BasicBlock *elseBB = BasicBlock::Create(TheContext, "else", func); + BasicBlock *mergeBB = BasicBlock::Create(TheContext, "merge", func); + + Builder.CreateCondBr(condV, thenBB, elseBB); + + Builder.SetInsertPoint(thenBB); + + Value *thenV = Then->codegen(); + if (!thenV) return nullptr; + + Builder.CreateBr(mergeBB); + + //codegen of then can change the current block, so get then again + thenBB = Builder.GetInsertBlock(); + + Builder.SetInsertPoint(elseBB); + + Value *elseV = Else->codegen(); + if (!elseV) return nullptr; + + Builder.CreateBr(mergeBB); + + //codegen of else can change the current block, so get else again + elseBB = Builder.GetInsertBlock(); + + Builder.SetInsertPoint(mergeBB); + PHINode *phiNode = Builder.CreatePHI(Type::getDoubleTy(TheContext), 2, "iftmp"); + phiNode->addIncoming(thenV, thenBB); + phiNode->addIncoming(elseV, elseBB); + + return phiNode; +} + +Value *ForExprAST::codegen() { + auto *startValue = Start->codegen(); + if (!startValue) return nullptr; + + auto *func = Builder.GetInsertBlock()->getParent(); + auto *preheaderBB = Builder.GetInsertBlock(); + auto *loopBB = BasicBlock::Create(TheContext, "loop", func); + + Builder.CreateBr(loopBB); + + Builder.SetInsertPoint(loopBB); + + auto *index = Builder.CreatePHI(Type::getDoubleTy(TheContext), 2, VarName.c_str()); + index->addIncoming(startValue, preheaderBB); + + // if the index variable shadows an existing value, save it to restore later + auto *oldVal = NamedValues[VarName]; + NamedValues[VarName] = index; + + // emit the loop body + if (!Body->codegen()) return nullptr; + + Value *stepVal = nullptr; + if (Step) { + stepVal = Step->codegen(); + if (!stepVal) return nullptr; + } else { + stepVal = ConstantFP::get(TheContext, APFloat(1.0)); + } + + // increment the index + auto *nextVar = Builder.CreateFAdd(index, stepVal, "nextvar"); + + auto *endCond = End->codegen(); + if (!endCond) return nullptr; + + endCond = Builder.CreateFCmpONE(endCond, ConstantFP::get(TheContext, APFloat(0.0)), "loopcond"); + + auto *loopEndBB = Builder.GetInsertBlock(); + auto *afterBB = BasicBlock::Create(TheContext, "afterloop", func); + + Builder.CreateCondBr(endCond, loopBB, afterBB); + + Builder.SetInsertPoint(afterBB); + + index->addIncoming(nextVar, loopEndBB); + + // restore shadowed index variable + if (oldVal) + NamedValues[VarName] = oldVal; + else + NamedValues.erase(VarName); + + return Constant::getNullValue(Type::getDoubleTy(TheContext)); +}