#include "Backend.h" using namespace sysy; namespace sysy { using RegId = RegManager::RegId; string CodeGen::code_gen() { string code; code += module_gen(module); return code; } string CodeGen::module_gen(Module *module) { string code; string dataCode; string textCode; // clear last module's label record clearModuleRecord(module); // generate asmcode for all global values dataCode += globaldata_gen(); code += space + ".arch armv7ve " + eol; code += space + ".text " + eol; auto functions = module->getFunctions(); for (auto iter = functions->begin(); iter != functions->end(); ++iter) { string name = iter->first; Function *func = iter->second; auto bblist = func->getBasicBlocks(); if (bblist.empty()) continue; // generate asmcode for each function textCode += function_gen(func) + eol; } code += (dataCode + textCode + eol); return code; } string CodeGen::functionHead_gen(Function *func) { string code; code += space + ".globl " + func->getName() + eol; code += space + ".p2align " + std::to_string(int_p2align) + eol; code += space + ".type " + func->getName() + ", %function" + eol; code += func->getName() + ":" + eol; return code; } /** * stack structure: * * last function stack * -------------------------- <-- fp point * callee-saved regs (include fp, sp, lr) * -------------------------- * local variables and subfunc's return value (ir inst) * -------------------------- * arg0,arg1,arg2,arg3 (as tempory variable) * -------------------------- * caller-saved regs * -------------------------- * arg_x ~ arg_4 * -------------------------- <-- sp point * next function stack * */ /** * prologue : * preserve callee-saved registers (lr, fp and other callee-saved regs) * set new fp * alloc stack space for local var/ args / return value. * store args to stack * */ string CodeGen::prologueCode_gen(Function *func) { string code; /** *code in here */ return code; } /* epilogue : * free stack space * restore sp * restore used callee-saved register(lr, fp and other callee-saved * regs) bx lr */ string CodeGen::epilogueCode_gen(Function *func) { string code; /** *code in here */ return code; } string CodeGen::function_gen(Function *func) { curFunc = func; clearFunctionRecord(func); string bbCode; auto bbs = func->getBasicBlocks(); for (auto iter = bbs.begin(); iter != bbs.end(); ++iter) { auto bb = iter->get(); bbCode += basicBlock_gen(bb); } string code; string funcHead = functionHead_gen(func); string prologueCode = prologueCode_gen(func); string epilogueCode = epilogueCode_gen(func); string literalPoolsCode = literalPoolsCode_gen(func); // code = funcHead + prologueCode + bbCode + epilogueCode + literalPoolsCode; return code; } string CodeGen::basicBlock_gen(BasicBlock *bb) { curBB = bb; string bbLabel = getBBLabel(bb); string code; code += bbLabel + ":" + eol; for (auto &instr : bb->getInstructions()) { auto instrType = instr->getKind(); code += instruction_gen(instr.get()); } return code; } /** * RegId : binaryInst_gen returns RegId as its destination operand * code : asmcode generated by binaryInst_gen */ pair CodeGen::binaryInst_gen(BinaryInst *bInst, RegId dstRegId) { string code; /** *code in here */ return {dstRegId, code}; } pair CodeGen::unaryInst_gen(UnaryInst *uInst, RegId dstRegId) { string code; /** *code in here */ return {dstRegId, code}; } pair CodeGen::allocaInst_gen(AllocaInst *aInst, RegManager::RegId dstRegId) { string code; /** *code in here */ return {dstRegId, code}; } string CodeGen::storeInst_gen(StoreInst *stInst) { string code; /** *code in here */ return code; } pair CodeGen::loadInst_gen(LoadInst *ldInst, RegId dstRegId) { string code; /** *code in here */ return {dstRegId, code}; } string CodeGen::returnInst_gen(ReturnInst *retInst) { string code; /** *code in here */ return code; } string CodeGen::uncondBrInst_gen(UncondBrInst *ubInst) { string code; /** *code in here */ return code; } string CodeGen::condBrInst_gen(CondBrInst *cbInst) { string code; /** *code in here */ return code; } pair CodeGen::callInst_gen(CallInst *callInst, RegId dstRegId) { string code; /** *code in here */ return {dstRegId, code}; } string CodeGen::instruction_gen(Instruction *instr) { string code; string unkName = instr->getName(); RegManager::RegId dstRegId = RegManager::RNONE; auto instrType = instr->getKind(); pair tmp; switch (instrType) { // binary inst case Instruction::kAdd: case Instruction::kMul: case Instruction::kSub: { BinaryInst *bInst = dynamic_cast(instr); // registers are used only for instruction operation, consider use which // register (any one that is free for use) tmp = binaryInst_gen(bInst, RegManager::RANY); code += tmp.second; dstRegId = tmp.first; break; } case Instruction::kLoad: { LoadInst *ldInst = dynamic_cast(instr); tmp = loadInst_gen(ldInst, RegManager::RANY); code += M_emitComment("load inst"); code += tmp.second; dstRegId = tmp.first; break; } case Instruction::kStore: { StoreInst *stInst = dynamic_cast(instr); code += M_emitComment("store inst"); code += storeInst_gen(stInst); return code; break; } case Instruction::kAlloca: { AllocaInst *aInst = dynamic_cast(instr); tmp = allocaInst_gen(aInst, RegManager::RANY); code += M_emitComment("alloca inst"); code += tmp.second; dstRegId = tmp.first; break; } case Instruction::kReturn: { ReturnInst *retInst = dynamic_cast(instr); code += M_emitComment("return inst"); code += returnInst_gen(retInst); return code; break; } case Instruction::kCall: { CallInst *cInst = dynamic_cast(instr); auto tmp = callInst_gen(cInst, RegManager::RANY); code += tmp.second; dstRegId = tmp.first; if (dstRegId == RegManager::R0) return code; break; } case Instruction::kBr: { UncondBrInst *ubInst = dynamic_cast(instr); code += uncondBrInst_gen(ubInst); return code; break; } case Instruction::kCondBr: { CondBrInst *cbInst = dynamic_cast(instr); code += condBrInst_gen(cbInst); return code; break; } default: { code += "ERROR CODE : instruction " + unkName + " is not implementation" + eol; break; } } if (!instr->getType()->isVoid()) { code += storeRegToStack_gen(dstRegId, instr); // regm.freeReg(dstRegId);//TODO : code in here. } return code; } // string CodeGen::globaldata_gen() { string asmCode; /** *code in here */ return asmCode; } string CodeGen::literalPoolsCode_gen(Function *func) { string code; /** *code in here */ return code; } } // namespace sysy