/// Read-Eval-Print-Loop static void repl(CEnv& cenv, ExecutionEngine* engine) { while (1) { std::cout << "> "; std::cout.flush(); SExp exp = readExpression(std::cin); try { AST* ast = parseExpression(exp); if (ast->evaluatable()) { ASTPrototype* proto = new ASTPrototype(false, "", vector<string>()); ASTFunction* func = new ASTFunction(proto, ast); Function* code = func->Funcgen(cenv); void* fp = engine->getPointerToFunction(code); double (*f)() = (double (*)())fp; std::cout << f() << endl; } else { Value* code = ast->Codegen(cenv); std::cout << "Generated code:" << endl; code->dump(); } } catch (SyntaxError e) { std::cerr << "Syntax error: " << e.what() << endl; } } }
Value* ASTIf::Codegen(CEnv& cenv) { Value* condV = _cond->Codegen(cenv); // Convert condition to a bool by comparing equal to 0.0. condV = cenv.builder.CreateFCmpONE( condV, ConstantFP::get(APFloat(0.0)), "ifcond"); Function* parent = cenv.builder.GetInsertBlock()->getParent(); // Create blocks for the then and else cases. // Insert the 'then' block at the end of the function. BasicBlock* thenBB = BasicBlock::Create("then", parent); BasicBlock* elseBB = BasicBlock::Create("else"); BasicBlock* mergeBB = BasicBlock::Create("ifcont"); cenv.builder.CreateCondBr(condV, thenBB, elseBB); // Emit then value. cenv.builder.SetInsertPoint(thenBB); Value* thenV = _then->Codegen(cenv); cenv.builder.CreateBr(mergeBB); // Codegen of 'Then' can change the current block, update thenBB thenBB = cenv.builder.GetInsertBlock(); // Emit else block. parent->getBasicBlockList().push_back(elseBB); cenv.builder.SetInsertPoint(elseBB); Value* elseV = _else->Codegen(cenv); cenv.builder.CreateBr(mergeBB); // Codegen of 'Else' can change the current block, update elseBB elseBB = cenv.builder.GetInsertBlock(); // Emit merge block. parent->getBasicBlockList().push_back(mergeBB); cenv.builder.SetInsertPoint(mergeBB); PHINode* pn = cenv.builder.CreatePHI(Type::DoubleTy, "iftmp"); pn->addIncoming(thenV, thenBB); pn->addIncoming(elseV, elseBB); return pn; }
Function* ASTFunction::Funcgen(CEnv& cenv) { cenv.env.clear(); Function* f = _proto->Funcgen(cenv); // Create a new basic block to start insertion into. BasicBlock* bb = BasicBlock::Create("entry", f); cenv.builder.SetInsertPoint(bb); try { Value* retVal = _body->Codegen(cenv); cenv.builder.CreateRet(retVal); // Finish function verifyFunction(*f); // Validate generated code cenv.fpm.run(*f); // Optimize function return f; } catch (SyntaxError e) { f->eraseFromParent(); // Error reading body, remove function throw e; } return 0; // Never reached }