#include "ast.hpp" #include LLVMContext TheContext; map NamedValues; IRBuilder<> Builder(TheContext); Module* TheModule; FunctionPassManager *TheFPM; ExprAST::~ExprAST() { } InnerExprAST::InnerExprAST(ExprAST* a) { _nodes.resize(0); _nodes.push_back(a); } InnerExprAST::InnerExprAST(ExprAST* a, ExprAST* b) { _nodes.resize(0); _nodes.push_back(a); _nodes.push_back(b); } InnerExprAST::InnerExprAST(ExprAST* a, ExprAST* b, ExprAST* c) { _nodes.resize(0); _nodes.push_back(a); _nodes.push_back(b); _nodes.push_back(c); } InnerExprAST::InnerExprAST(vector a) { _nodes = a; } InnerExprAST::~InnerExprAST() { for (unsigned i = 0; i < _nodes.size(); i++) delete _nodes[i]; } FunctionAST::~FunctionAST() { delete Body; } Value* NumberExprAST::codegen() const { return ConstantFP::get(TheContext, APFloat(Val)); } Value* VariableExprAST::codegen() const { Value* tmp = NamedValues[Name]; if (tmp == NULL) { cerr << "Promenljiva " << Name << " nije prethodno definisana" << endl; return NULL; } return tmp; } Value* AddExprAST::codegen() const { Value* l = _nodes[0]->codegen(); Value* d = _nodes[1]->codegen(); if (l == NULL || d == NULL) { return NULL; } return Builder.CreateFAdd(l, d, "addtmp"); } Value* SubExprAST::codegen() const { Value* l = _nodes[0]->codegen(); Value* d = _nodes[1]->codegen(); if (l == NULL || d == NULL) { return NULL; } return Builder.CreateFSub(l, d, "subtmp"); } Value* MulExprAST::codegen() const { Value* l = _nodes[0]->codegen(); Value* d = _nodes[1]->codegen(); if (l == NULL || d == NULL) { return NULL; } return Builder.CreateFMul(l, d, "multmp"); } Value* DivExprAST::codegen() const { Value* l = _nodes[0]->codegen(); Value* d = _nodes[1]->codegen(); if (l == NULL || d == NULL) { return NULL; } return Builder.CreateFDiv(l, d, "divtmp"); } Value* LtExprAST::codegen() const { Value* l = _nodes[0]->codegen(); Value* d = _nodes[1]->codegen(); if (l == NULL || d == NULL) { return NULL; } l = Builder.CreateFCmpULT(l, d, "lttmp"); return Builder.CreateUIToFP(l, Type::getDoubleTy(TheContext), "booltmp"); } Value* GtExprAST::codegen() const { Value* l = _nodes[0]->codegen(); Value* d = _nodes[1]->codegen(); if (l == NULL || d == NULL) { return NULL; } l = Builder.CreateFCmpUGT(l, d, "gttmp"); return Builder.CreateUIToFP(l, Type::getDoubleTy(TheContext), "booltmp"); } Value* CallExprAST::codegen() const { // Look up the name in the global module table. Function *CalleeF = TheModule->getFunction(Callee); if (!CalleeF) { cerr << "Poziv fje " << Callee << " koja nije definisana" << endl; return NULL; } // If argument mismatch error. if (CalleeF->arg_size() != _nodes.size()) { cerr << "Pogresan broj argumenata fje " << Callee << endl; return NULL; } vector ArgsV; for (unsigned i = 0, e = _nodes.size(); i != e; ++i) { ArgsV.push_back(_nodes[i]->codegen()); if (!ArgsV.back()) return NULL; } return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); } Value* IfExprAST::codegen() const { Value *CondV = _nodes[0]->codegen(); if (CondV == NULL) return NULL; CondV = Builder.CreateFCmpONE(CondV, ConstantFP::get(TheContext, APFloat(0.0)), "ifcond"); Function *TheFunction = Builder.GetInsertBlock()->getParent(); BasicBlock *ThenBB = BasicBlock::Create(TheContext, "then", TheFunction); BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else"); BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont"); Builder.CreateCondBr(CondV, ThenBB, ElseBB); Builder.SetInsertPoint(ThenBB); Value *Then = _nodes[1]->codegen(); if (Then == NULL) return NULL; Builder.CreateBr(MergeBB); ThenBB = Builder.GetInsertBlock(); TheFunction->getBasicBlockList().push_back(ElseBB); Builder.SetInsertPoint(ElseBB); Value *Else = _nodes[2]->codegen(); if (Else == NULL) return NULL; Builder.CreateBr(MergeBB); ElseBB = Builder.GetInsertBlock(); TheFunction->getBasicBlockList().push_back(MergeBB); Builder.SetInsertPoint(MergeBB); PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(TheContext), 2, "iftmp"); PN->addIncoming(Then, ThenBB); PN->addIncoming(Else, ElseBB); return PN; } Function* PrototypeAST::codegen() const { vector Doubles(Args.size(), Type::getDoubleTy(TheContext)); FunctionType *FT = FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); unsigned Idx = 0; for (auto &Arg : F->args()) Arg.setName(Args[Idx++]); return F; } Function* FunctionAST::codegen() const { // First, check for an existing function from a previous 'extern' declaration. Function *TheFunction = TheModule->getFunction(Proto.getName()); if (!TheFunction) TheFunction = Proto.codegen(); if (!TheFunction) return NULL; if (!TheFunction->empty()) { cerr << "Nije dozvoljena redefinicija fje " << Proto.getName() << endl; return NULL; } // Create a new basic block to start insertion into. BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); Builder.SetInsertPoint(BB); // Record the function arguments in the NamedValues map. NamedValues.clear(); for (auto &Arg : TheFunction->args()) NamedValues[Arg.getName()] = &Arg; if (Value *RetVal = Body->codegen()) { // Finish off the function. Builder.CreateRet(RetVal); // Validate the generated code, checking for consistency. verifyFunction(*TheFunction); TheFPM->run(*TheFunction); return TheFunction; } // Error reading body, remove function. TheFunction->eraseFromParent(); return NULL; } void InitializeModuleAndPassManager() { TheModule = new Module("my_module", TheContext); TheFPM = new FunctionPassManager(TheModule); // Eliminate Common SubExpressions. TheFPM->add(createGVNPass()); TheFPM->doInitialization(); }