WIP
[kaleidoscope.git] / Kaleidoscope / codegen.cpp
index c185a3e0c699f4445a0435c494953c13c8a19343..e9e1d2422e795c95b57d22bcaf9c0bd2fcead1c5 100644 (file)
@@ -11,7 +11,6 @@
 #include <llvm/Transforms/Scalar/SimplifyCFG.h>
 #include <llvm/Transforms/InstCombine/InstCombine.h>
 #include <llvm/Transforms/IPO/PassManagerBuilder.h>
-#include <llvm/Analysis/OptimizationDiagnosticInfo.h>
 #include <llvm/Analysis/MemorySSA.h>
 #include <llvm/Analysis/PostDominators.h>
 #include "ast.hpp"
@@ -43,10 +42,6 @@ void InitializeModuleAndPassManager(void) {
        TheFPM->addPass(GVNSinkPass());
 }
 
-void PrintModule() {
-       TheModule->print(errs(), nullptr);
-}
-
 std::map<std::string, std::unique_ptr<PrototypeAST>> 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));
+}