#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* tmp = namedValues[_name]; if (tmp == nullptr) throw "Promenljiva " + _name + " ne postoji"; return builder.CreateLoad(tmp, _name); } Value* PlusNode::Codegen() const { Value *l = _operands[0]->Codegen(); Value *r = _operands[1]->Codegen(); if (!l || !r) return nullptr; return builder.CreateAdd(l, r, "addtmp"); } Value* TimesNode::Codegen() const { Value *l = _operands[0]->Codegen(); Value *r = _operands[1]->Codegen(); if (!l || !r) return nullptr; return builder.CreateMul(l, r, "multmp"); } Value* DivideNode::Codegen() const { Value *l = _operands[0]->Codegen(); Value *r = _operands[1]->Codegen(); if (!l || !r) return nullptr; return builder.CreateUDiv(l, r, "divtmp"); } Value* MinusNode::Codegen() const { Value *l = _operands[0]->Codegen(); Value *r = _operands[1]->Codegen(); if (!l || !r) return nullptr; return builder.CreateSub(l, r, "subtmp"); } Value* EqNode::Codegen() const { Value *l = _operands[0]->Codegen(); Value *r = _operands[1]->Codegen(); if (!l || !r) return nullptr; return builder.CreateICmpEQ(l, r, "subtmp"); } 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 { Value *Val = _expression->Codegen(); if (Val == nullptr) return nullptr; AllocaInst* alloca = namedValues[_var_name]; if (alloca == nullptr) { Function* TheFunction = builder.GetInsertBlock()->getParent(); alloca = createEntryBlockAlloca(TheFunction, _var_name); namedValues[_var_name] = alloca; } builder.CreateStore(Val, alloca); return Val; } Value* FunctCallNode::Codegen() const { Function* CalleeF = theModule->getFunction(_name); if (CalleeF == nullptr) throw "Function " + _name + " ne postoji"; unsigned arg_size = CalleeF->arg_size(); if (arg_size != _operands.size()) throw "Funkcija " + _name + " treba da bude pozvana sa " + to_string(arg_size) + " argumenata"; vector args; for (unsigned i = 0; i < arg_size; i++) { Value *tmp = _operands[i]->Codegen(); if (tmp == nullptr) return nullptr; args.push_back(tmp); } return builder.CreateCall(CalleeF, args, "calltmp"); } Value* PrintNode::Codegen() const { Function* TheFunction = theModule->getFunction("printi"); if (TheFunction == nullptr) { vector ints(1, Type::getInt32Ty(theContext)); FunctionType* FT = FunctionType::get(Type::getVoidTy(theContext), ints, false); TheFunction = Function::Create(FT, Function::ExternalLinkage, "printi", theModule); } Value *Val = _expression->Codegen(); if (Val == nullptr) return nullptr; return builder.CreateCall(TheFunction, Val); } Value* SequenceNode::Codegen() const { Value *l = _operands[0]->Codegen(); Value *r = _operands[1]->Codegen(); if (!l || !r) return nullptr; return r; } void initializeModuleAndPassManager() { theModule = new Module("My module", 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); } Function* getFunction(string s) { //TODO return nullptr; }