#include "syntree.hpp" #include "funct.hpp" // Prilikom interpretacije poziva funkcije, koristi se registar svih // definisanih funkcija kome se pristupa preko statickog metoda Call, // klase Funct int FunctCallNode::Operate(const vector& v) { return Funct::Call(_name, v); } /* trenutni modul */ Module* theModule; /* kontekst */ LLVMContext theContext; /* mapa koja preslikava lokalne promenljive u njihove alokatore */ map namedValues; /* builder za pravljenje instrukcija */ IRBuilder<> builder(theContext); /* optimizacija funkcija */ legacy::FunctionPassManager* theFPM; Value* ConstantNode::Codegen() const { return ConstantInt::get(theContext, APInt(32, _value)); } Value* VariableNode::Codegen() const { AllocaInst *alloca = namedValues[_name]; if (alloca == nullptr) throw "Promenljiva " + _name + " ne postoji"; return builder.CreateLoad(alloca, _name); } Value* PlusNode::Codegen() const { Value *l = _operands[0]->Codegen(); Value *d = _operands[1]->Codegen(); if (l == nullptr || d == nullptr) return nullptr; return builder.CreateAdd(l, d, "tmpadd"); } Value* TimesNode::Codegen() const { Value *l = _operands[0]->Codegen(); Value *d = _operands[1]->Codegen(); if (l == nullptr || d == nullptr) return nullptr; return builder.CreateMul(l, d, "tmpmul"); } Value* DivideNode::Codegen() const { Value *l = _operands[0]->Codegen(); Value *d = _operands[1]->Codegen(); if (l == nullptr || d == nullptr) return nullptr; return builder.CreateUDiv(l, d, "tmpdiv"); } Value* MinusNode::Codegen() const { Value *l = _operands[0]->Codegen(); Value *d = _operands[1]->Codegen(); if (l == nullptr || d == nullptr) return nullptr; return builder.CreateSub(l, d, "tmpsub"); } Value* EqNode::Codegen() const { Value *l = _operands[0]->Codegen(); Value *d = _operands[1]->Codegen(); if (l == nullptr || d == nullptr) return nullptr; return builder.CreateICmpEQ(l, d, "tmpcmp"); } Value* QuestionNode::Codegen() const { Value* condV = _operands[0]->Codegen(); if (condV == nullptr) return nullptr; 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* thenV = _operands[1]->Codegen(); if (thenV == nullptr) return nullptr; builder.CreateBr(mergeBB); thenBB = builder.GetInsertBlock(); theFunction->getBasicBlockList().push_back(elseBB); builder.SetInsertPoint(elseBB); Value* elseV = _operands[2]->Codegen(); if (elseV == nullptr) return nullptr; builder.CreateBr(mergeBB); elseBB = builder.GetInsertBlock(); theFunction->getBasicBlockList().push_back(mergeBB); builder.SetInsertPoint(mergeBB); PHINode* phi = builder.CreatePHI(Type::getInt32Ty(theContext), 2, "iftmp"); phi->addIncoming(thenV, thenBB); phi->addIncoming(elseV, elseBB); return phi; } Value* AssignmentNode::Codegen() const { Function* f = builder.GetInsertBlock()->getParent(); Value *val = _expression->Codegen(); if (val == nullptr) return nullptr; AllocaInst* alloca = namedValues[_var_name]; if (alloca == nullptr) { alloca = createEntryBlockAlloca(f, _var_name); namedValues[_var_name] = alloca; } return builder.CreateStore(val, alloca); } Value* FunctCallNode::Codegen() const { Function *f = theModule->getFunction(_name); if (f == nullptr) throw "Funckija " + _name + " nije definisana"; vector argV; for (unsigned i = 0; i < _operands.size(); i++) { Value *val = _operands[i]->Codegen(); if (val == nullptr) return nullptr; argV.push_back(val); } Funct* fun = Funct::GetFunct(_name); if (fun->HasReturn()) return builder.CreateCall(f, argV, "calltmp"); else return builder.CreateCall(f, argV); } Value* PrintNode::Codegen() const { Function *f = theModule->getFunction("printi"); if (f == nullptr) { vector Ints(1, Type::getInt32Ty(theContext)); FunctionType *FT = FunctionType::get(Type::getVoidTy(theContext), Ints, false); f = Function::Create(FT, Function::ExternalLinkage, "printi", theModule); } Value *val = _expression->Codegen(); if (val == nullptr) return nullptr; vector argV; argV.push_back(val); return builder.CreateCall(f, argV); } Value* SequenceNode::Codegen() const { Value *l = _operands[0]->Codegen(); Value *d = _operands[1]->Codegen(); if (l == nullptr || d == nullptr) return nullptr; return d; } void initializeModuleAndPassManager() { theModule = new Module("Moj modul", theContext); theFPM = new legacy::FunctionPassManager(theModule); theFPM->add(createInstructionCombiningPass()); theFPM->add(createReassociatePass()); theFPM->add(createNewGVNPass()); theFPM->add(createCFGSimplificationPass()); theFPM->add(createPromoteMemoryToRegisterPass()); theFPM->doInitialization(); } AllocaInst* createEntryBlockAlloca(Function* theFunction, const string& name) { IRBuilder<> TmpB(&theFunction->getEntryBlock(), theFunction->getEntryBlock().begin()); return TmpB.CreateAlloca(Type::getInt32Ty(theContext), 0, name); }